From a5f36eb1d8bfba5ff56c5e264426f9374885dcaf Mon Sep 17 00:00:00 2001 From: L-Sun Date: Mon, 10 Feb 2025 18:17:28 +0000 Subject: [PATCH] refactor(editor): configurable page block title (#10063) ### What changes - make page block title rendering configurable so that a journal title can be rendered by AFFiNE side. - move page block render logic to a seperate component --- .../components/edgeless-note-background.ts | 21 ++------- .../edgeless-page-block-title.css.ts | 9 ++++ .../components/edgeless-page-block-title.ts | 44 +++++++++++++++++++ blocksuite/affine/block-note/src/config.ts | 11 +++-- blocksuite/affine/block-note/src/effects.ts | 2 + .../block-note/src/note-edgeless-block.css.ts | 10 +---- .../block-note/src/note-edgeless-block.ts | 37 +++------------- blocksuite/affine/block-note/src/utils.ts | 18 ++++++++ .../block-suite-editor/lit-adaper.tsx | 2 +- .../specs/custom/spec-patchers.tsx | 14 +++++- 10 files changed, 105 insertions(+), 63 deletions(-) create mode 100644 blocksuite/affine/block-note/src/components/edgeless-page-block-title.css.ts create mode 100644 blocksuite/affine/block-note/src/components/edgeless-page-block-title.ts create mode 100644 blocksuite/affine/block-note/src/utils.ts diff --git a/blocksuite/affine/block-note/src/components/edgeless-note-background.ts b/blocksuite/affine/block-note/src/components/edgeless-note-background.ts index e535799131..07c0b1e2a8 100644 --- a/blocksuite/affine/block-note/src/components/edgeless-note-background.ts +++ b/blocksuite/affine/block-note/src/components/edgeless-note-background.ts @@ -1,13 +1,9 @@ import { DefaultTheme, NoteBlockModel, - NoteDisplayMode, StrokeStyle, } from '@blocksuite/affine-model'; -import { - FeatureFlagService, - ThemeProvider, -} from '@blocksuite/affine-shared/services'; +import { ThemeProvider } from '@blocksuite/affine-shared/services'; import { getClosestBlockComponentByPoint, handleNativeRangeAtPoint, @@ -37,6 +33,7 @@ import { html, nothing } from 'lit'; import { property } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; +import { isPageBlock } from '../utils'; import * as styles from './edgeless-note-background.css'; @requiredProperties({ @@ -74,18 +71,6 @@ export class EdgelessNoteBackground extends SignalWatcher( return this.std.host.doc; } - private get _isPageBlock() { - return ( - this.std.get(FeatureFlagService).getFlag('enable_page_block') && - // is the first page visible note - this.note.parent?.children.find( - child => - matchFlavours(child, ['affine:note']) && - child.displayMode !== NoteDisplayMode.EdgelessOnly - ) === this.note - ); - } - private _tryAddParagraph(x: number, y: number) { const nearest = getClosestBlockComponentByPoint( new Point(x, y) @@ -174,7 +159,7 @@ export class EdgelessNoteBackground extends SignalWatcher( @pointerdown=${stopPropagation} @click=${this._handleClickAtBackground} > - ${this._isPageBlock ? this._renderHeader() : nothing} + ${isPageBlock(this.std, this.note) ? this._renderHeader() : nothing} `; } diff --git a/blocksuite/affine/block-note/src/components/edgeless-page-block-title.css.ts b/blocksuite/affine/block-note/src/components/edgeless-page-block-title.css.ts new file mode 100644 index 0000000000..0ab4fcc891 --- /dev/null +++ b/blocksuite/affine/block-note/src/components/edgeless-page-block-title.css.ts @@ -0,0 +1,9 @@ +import { globalStyle, style } from '@vanilla-extract/css'; + +export const pageBlockTitle = style({ + position: 'relative', +}); + +globalStyle(`${pageBlockTitle} .doc-title-container`, { + padding: '26px 0px', +}); diff --git a/blocksuite/affine/block-note/src/components/edgeless-page-block-title.ts b/blocksuite/affine/block-note/src/components/edgeless-page-block-title.ts new file mode 100644 index 0000000000..693454afb0 --- /dev/null +++ b/blocksuite/affine/block-note/src/components/edgeless-page-block-title.ts @@ -0,0 +1,44 @@ +import { NoteBlockModel } from '@blocksuite/affine-model'; +import { + type BlockStdScope, + PropTypes, + requiredProperties, + ShadowlessElement, + stdContext, +} from '@blocksuite/block-std'; +import { SignalWatcher, WithDisposable } from '@blocksuite/global/utils'; +import { consume } from '@lit/context'; +import { html } from 'lit'; +import { property } from 'lit/decorators.js'; + +import { isPageBlock } from '../utils'; +import * as styles from './edgeless-page-block-title.css'; + +@requiredProperties({ + note: PropTypes.instanceOf(NoteBlockModel), +}) +export class EdgelessPageBlockTitle extends SignalWatcher( + WithDisposable(ShadowlessElement) +) { + override render() { + if (!isPageBlock(this.std, this.note)) return; + + const title = this.std.getConfig('affine:note')?.pageBlockTitle({ + note: this.note, + std: this.std, + }); + + return html`
${title}
`; + } + + @consume({ context: stdContext }) + accessor std!: BlockStdScope; + + @property({ attribute: false }) + accessor note!: NoteBlockModel; +} +declare global { + interface HTMLElementTagNameMap { + 'edgeless-page-block-title': EdgelessPageBlockTitle; + } +} diff --git a/blocksuite/affine/block-note/src/config.ts b/blocksuite/affine/block-note/src/config.ts index 3048b00a8a..751ec1b49a 100644 --- a/blocksuite/affine/block-note/src/config.ts +++ b/blocksuite/affine/block-note/src/config.ts @@ -2,11 +2,14 @@ import type { NoteBlockModel } from '@blocksuite/affine-model'; import { type BlockStdScope, ConfigExtension } from '@blocksuite/block-std'; import type { TemplateResult } from 'lit'; +type NoteBlockContext = { + note: NoteBlockModel; + std: BlockStdScope; +}; + export type NoteConfig = { - edgelessNoteHeader: (context: { - note: NoteBlockModel; - std: BlockStdScope; - }) => TemplateResult; + edgelessNoteHeader: (context: NoteBlockContext) => TemplateResult; + pageBlockTitle: (context: NoteBlockContext) => TemplateResult; }; export function NoteConfigExtension(config: NoteConfig) { diff --git a/blocksuite/affine/block-note/src/effects.ts b/blocksuite/affine/block-note/src/effects.ts index 46162bcc95..6372bf6537 100644 --- a/blocksuite/affine/block-note/src/effects.ts +++ b/blocksuite/affine/block-note/src/effects.ts @@ -1,5 +1,6 @@ import { EdgelessNoteBackground } from './components/edgeless-note-background'; import { EdgelessNoteMask } from './components/edgeless-note-mask'; +import { EdgelessPageBlockTitle } from './components/edgeless-page-block-title'; import type { NoteConfig } from './config'; import { NoteBlockComponent } from './note-block'; import { @@ -13,6 +14,7 @@ export function effects() { customElements.define(AFFINE_EDGELESS_NOTE, EdgelessNoteBlockComponent); customElements.define('edgeless-note-mask', EdgelessNoteMask); customElements.define('edgeless-note-background', EdgelessNoteBackground); + customElements.define('edgeless-page-block-title', EdgelessPageBlockTitle); } declare global { diff --git a/blocksuite/affine/block-note/src/note-edgeless-block.css.ts b/blocksuite/affine/block-note/src/note-edgeless-block.css.ts index ea5ad8bd9c..d2654a26f5 100644 --- a/blocksuite/affine/block-note/src/note-edgeless-block.css.ts +++ b/blocksuite/affine/block-note/src/note-edgeless-block.css.ts @@ -1,6 +1,6 @@ import { EDGELESS_BLOCK_CHILD_PADDING } from '@blocksuite/affine-shared/consts'; import { cssVar } from '@toeverything/theme'; -import { globalStyle, style } from '@vanilla-extract/css'; +import { style } from '@vanilla-extract/css'; export const ACTIVE_NOTE_EXTRA_PADDING = 20; @@ -58,14 +58,6 @@ export const noteBackground = style({ }, }); -globalStyle(`${edgelessNoteContainer} > doc-title`, { - position: 'relative', -}); - -globalStyle(`${edgelessNoteContainer} > doc-title .doc-title-container`, { - padding: '26px 0px', -}); - export const pageContent = style({ width: '100%', height: '100%', diff --git a/blocksuite/affine/block-note/src/note-edgeless-block.ts b/blocksuite/affine/block-note/src/note-edgeless-block.ts index 8a26689e25..6d14d45e94 100644 --- a/blocksuite/affine/block-note/src/note-edgeless-block.ts +++ b/blocksuite/affine/block-note/src/note-edgeless-block.ts @@ -3,11 +3,7 @@ import type { DocTitle } from '@blocksuite/affine-components/doc-title'; import { MoreIndicatorIcon } from '@blocksuite/affine-components/icons'; import { NoteDisplayMode } from '@blocksuite/affine-model'; import { EDGELESS_BLOCK_CHILD_PADDING } from '@blocksuite/affine-shared/consts'; -import { FeatureFlagService } from '@blocksuite/affine-shared/services'; -import { - matchFlavours, - stopPropagation, -} from '@blocksuite/affine-shared/utils'; +import { stopPropagation } from '@blocksuite/affine-shared/utils'; import { toGfxBlockComponent } from '@blocksuite/block-std'; import { Bound } from '@blocksuite/global/utils'; import { html, nothing } from 'lit'; @@ -19,19 +15,13 @@ import { styleMap } from 'lit/directives/style-map.js'; import { NoteBlockComponent } from './note-block'; import { ACTIVE_NOTE_EXTRA_PADDING } from './note-edgeless-block.css'; import * as styles from './note-edgeless-block.css'; +import { isPageBlock } from './utils'; export const AFFINE_EDGELESS_NOTE = 'affine-edgeless-note'; export class EdgelessNoteBlockComponent extends toGfxBlockComponent( NoteBlockComponent ) { - private get _isPageBlock() { - return ( - this.std.get(FeatureFlagService).getFlag('enable_page_block') && - this._isFirstVisibleNote() - ); - } - private get _isShowCollapsedContent() { return ( this.model.edgeless.collapse && @@ -88,7 +78,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( } private _handleKeyDown(e: KeyboardEvent) { - if (e.key === 'ArrowUp' && this._isPageBlock) { + if (e.key === 'ArrowUp') { this._docTitle?.inlineEditor?.focusEnd(); } } @@ -103,16 +93,6 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( } } - private _isFirstVisibleNote() { - return ( - this.model.parent?.children.find( - child => - matchFlavours(child, ['affine:note']) && - child.displayMode !== NoteDisplayMode.EdgelessOnly - ) === this.model - ); - } - private _leaved() { if (this._isHover) { this._isHover = false; @@ -259,12 +239,9 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent( .note=${this.model} > - ${this._isPageBlock && !collapse - ? html`` - : nothing} +
- ${isCollapsable && !this._isPageBlock + ${isCollapsable && !isPageBlock(this.std, this.model) ? html`