From ffd54c662076a871053070c5d788bfa14ed3f7e4 Mon Sep 17 00:00:00 2001 From: fundon Date: Mon, 27 Jan 2025 02:56:10 +0000 Subject: [PATCH] refactor(editor): use selected signal in block component (#9849) --- .../block-attachment/src/attachment-block.ts | 19 +++++------------ .../block-bookmark/src/bookmark-block.ts | 8 ++++--- .../src/components/bookmark-card.ts | 21 +++---------------- .../src/common/embed-block-element.ts | 12 ++++++----- .../src/common/to-edgeless-embed-block.ts | 4 +--- .../embed-figma-block/embed-figma-block.ts | 20 ++++++------------ .../embed-github-block/embed-github-block.ts | 17 +++------------ .../src/embed-html-block/embed-html-block.ts | 20 ++++++------------ .../src/embed-loom-block/embed-loom-block.ts | 20 ++++++------------ .../embed-edgeless-synced-doc-block.ts | 5 ++--- .../embed-synced-doc-block.ts | 5 ++--- .../embed-youtube-block.ts | 20 ++++++------------ .../block-paragraph/src/paragraph-block.ts | 12 +++++++++-- .../block-table/src/selection-controller.ts | 10 ++++----- .../components/src/block-selection/index.ts | 20 ++++-------------- .../src/caption/captioned-block-component.ts | 4 +++- .../src/view/element/block-component.ts | 21 +++++++------------ .../src/view/element/gfx-block-component.ts | 10 +++++++++ 18 files changed, 90 insertions(+), 158 deletions(-) diff --git a/blocksuite/affine/block-attachment/src/attachment-block.ts b/blocksuite/affine/block-attachment/src/attachment-block.ts index 16c8eb97735e3..90a143c82f13d 100644 --- a/blocksuite/affine/block-attachment/src/attachment-block.ts +++ b/blocksuite/affine/block-attachment/src/attachment-block.ts @@ -13,11 +13,7 @@ import { } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; import { humanFileSize } from '@blocksuite/affine-shared/utils'; -import { - BlockSelection, - SurfaceSelection, - TextSelection, -} from '@blocksuite/block-std'; +import { BlockSelection, TextSelection } from '@blocksuite/block-std'; import { Slice } from '@blocksuite/store'; import { flip, offset } from '@floating-ui/dom'; import { html, nothing } from 'lit'; @@ -170,26 +166,21 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent< // this is required to prevent iframe from capturing pointer events this.disposables.add( - this.std.selection.slots.changed.on(() => { - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - - this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this.selected$.subscribe(selected => { + this._showOverlay = this._isResizing || this._isDragging || !selected; }) ); // this is required to prevent iframe from capturing pointer events this.handleEvent('dragStart', () => { this._isDragging = true; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); this.handleEvent('dragEnd', () => { this._isDragging = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); } diff --git a/blocksuite/affine/block-bookmark/src/bookmark-block.ts b/blocksuite/affine/block-bookmark/src/bookmark-block.ts index 7a6404c65b15f..329d73c1b3b40 100644 --- a/blocksuite/affine/block-bookmark/src/bookmark-block.ts +++ b/blocksuite/affine/block-bookmark/src/bookmark-block.ts @@ -4,7 +4,6 @@ import { } from '@blocksuite/affine-components/caption'; import type { BookmarkBlockModel } from '@blocksuite/affine-model'; import { DocModeProvider } from '@blocksuite/affine-shared/services'; -import { BlockSelection } from '@blocksuite/block-std'; import { html } from 'lit'; import { property, query } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -70,13 +69,16 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent diff --git a/blocksuite/affine/block-bookmark/src/components/bookmark-card.ts b/blocksuite/affine/block-bookmark/src/components/bookmark-card.ts index 64ba7dbc8866a..7746a61eb71ac 100644 --- a/blocksuite/affine/block-bookmark/src/components/bookmark-card.ts +++ b/blocksuite/affine/block-bookmark/src/components/bookmark-card.ts @@ -2,15 +2,11 @@ import { getEmbedCardIcons } from '@blocksuite/affine-block-embed'; import { WebIcon16 } from '@blocksuite/affine-components/icons'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; import { getHostName } from '@blocksuite/affine-shared/utils'; -import { - BlockSelection, - ShadowlessElement, - SurfaceSelection, -} from '@blocksuite/block-std'; +import { BlockSelection, ShadowlessElement } from '@blocksuite/block-std'; import { WithDisposable } from '@blocksuite/global/utils'; import { OpenInNewIcon } from '@blocksuite/icons/lit'; import { html } from 'lit'; -import { property, state } from 'lit/decorators.js'; +import { property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import type { BookmarkBlockComponent } from '../bookmark-block.js'; @@ -55,14 +51,6 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) { .get(ThemeProvider) .theme$.subscribe(() => this.requestUpdate()) ); - - this.disposables.add( - this.bookmark.selection.slots.changed.on(() => { - this._isSelected = - !!this.bookmark.selected?.is(BlockSelection) || - !!this.bookmark.selected?.is(SurfaceSelection); - }) - ); } override render() { @@ -72,7 +60,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) { loading: this.loading, error: this.error, [style]: true, - selected: this._isSelected, + selected: this.bookmark.selected$.value, }); const domainName = url.match( @@ -148,9 +136,6 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) { `; } - @state() - private accessor _isSelected = false; - @property({ attribute: false }) accessor bookmark!: BookmarkBlockComponent; diff --git a/blocksuite/affine/block-embed/src/common/embed-block-element.ts b/blocksuite/affine/block-embed/src/common/embed-block-element.ts index 880ce5d4d3eca..fcba24bbe590a 100644 --- a/blocksuite/affine/block-embed/src/common/embed-block-element.ts +++ b/blocksuite/affine/block-embed/src/common/embed-block-element.ts @@ -9,7 +9,7 @@ import { EMBED_CARD_WIDTH, } from '@blocksuite/affine-shared/consts'; import { DocModeProvider } from '@blocksuite/affine-shared/services'; -import { BlockSelection, type BlockService } from '@blocksuite/block-std'; +import type { BlockService } from '@blocksuite/block-std'; import type { GfxCompatibleProps } from '@blocksuite/block-std/gfx'; import type { BlockModel } from '@blocksuite/store'; import type { TemplateResult } from 'lit'; @@ -43,6 +43,10 @@ export class EmbedBlockComponent< protected embedContainerStyle: StyleInfo = {}; renderEmbed = (content: () => TemplateResult) => { + const selected = this.selected$.value; + const isInEdgeless = + this.std.get(DocModeProvider).getEditorMode() === 'edgeless'; + if ( this._cardStyle === 'horizontal' || this._cardStyle === 'horizontalThin' || @@ -50,19 +54,17 @@ export class EmbedBlockComponent< ) { this.style.display = 'block'; - const mode = this.std.get(DocModeProvider).getEditorMode(); - if (mode === 'edgeless') { + if (isInEdgeless) { this.style.minWidth = `${EMBED_CARD_MIN_WIDTH}px`; } } - const selected = !!this.selected?.is(BlockSelection); return html`
{ this._isResizing = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }) ); } diff --git a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts index 1dad950eda03a..b162ff6b49dba 100644 --- a/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts +++ b/blocksuite/affine/block-embed/src/embed-figma-block/embed-figma-block.ts @@ -3,7 +3,7 @@ import type { EmbedFigmaModel, EmbedFigmaStyles, } from '@blocksuite/affine-model'; -import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std'; +import { BlockSelection } from '@blocksuite/block-std'; import { html } from 'lit'; import { state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -76,26 +76,21 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent< // this is required to prevent iframe from capturing pointer events this.disposables.add( - this.std.selection.slots.changed.on(() => { - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - - this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this.selected$.subscribe(selected => { + this._showOverlay = this._isResizing || this._isDragging || !selected; }) ); // this is required to prevent iframe from capturing pointer events this.handleEvent('dragStart', () => { this._isDragging = true; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); this.handleEvent('dragEnd', () => { this._isDragging = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); } @@ -109,7 +104,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<
{ - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - }) - ); } override renderBlock() { @@ -170,7 +162,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent< 'affine-embed-github-block': true, loading, [style]: true, - selected: this._isSelected, + selected: this.selected$.value, })} style=${styleMap({ transform: `scale(${this._scale})`, @@ -269,9 +261,6 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent< ); } - @state() - private accessor _isSelected = false; - @property({ attribute: false }) accessor loading = false; } diff --git a/blocksuite/affine/block-embed/src/embed-html-block/embed-html-block.ts b/blocksuite/affine/block-embed/src/embed-html-block/embed-html-block.ts index 9122ede6601c4..c6c97acbd30a8 100644 --- a/blocksuite/affine/block-embed/src/embed-html-block/embed-html-block.ts +++ b/blocksuite/affine/block-embed/src/embed-html-block/embed-html-block.ts @@ -1,5 +1,5 @@ import type { EmbedHtmlModel, EmbedHtmlStyles } from '@blocksuite/affine-model'; -import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std'; +import { BlockSelection } from '@blocksuite/block-std'; import { html } from 'lit'; import { query, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -53,26 +53,21 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent // this is required to prevent iframe from capturing pointer events this.disposables.add( - this.std.selection.slots.changed.on(() => { - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - - this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this.selected$.subscribe(selected => { + this._showOverlay = this._isResizing || this._isDragging || !selected; }) ); // this is required to prevent iframe from capturing pointer events this.handleEvent('dragStart', () => { this._isDragging = true; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); this.handleEvent('dragEnd', () => { this._isDragging = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); } @@ -96,7 +91,7 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent
}); } - @state() - protected accessor _isSelected = false; - @state() protected accessor _showOverlay = true; diff --git a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-block.ts b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-block.ts index 7ee1e2fa6d8c7..fc8e4ebf67cff 100644 --- a/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-block.ts +++ b/blocksuite/affine/block-embed/src/embed-loom-block/embed-loom-block.ts @@ -1,7 +1,7 @@ import { OpenIcon } from '@blocksuite/affine-components/icons'; import type { EmbedLoomModel, EmbedLoomStyles } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; -import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std'; +import { BlockSelection } from '@blocksuite/block-std'; import { html } from 'lit'; import { property, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -92,26 +92,21 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent< // this is required to prevent iframe from capturing pointer events this.disposables.add( - this.std.selection.slots.changed.on(() => { - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - - this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this.selected$.subscribe(selected => { + this._showOverlay = this._isResizing || this._isDragging || !selected; }) ); // this is required to prevent iframe from capturing pointer events this.handleEvent('dragStart', () => { this._isDragging = true; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); this.handleEvent('dragEnd', () => { this._isDragging = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); } @@ -137,7 +132,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent< class=${classMap({ 'affine-embed-loom-block': true, loading, - selected: this._isSelected, + selected: this.selected$.value, })} style=${styleMap({ transform: `scale(${this._scale})`, @@ -193,9 +188,6 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent< ); } - @state() - protected accessor _isSelected = false; - @state() protected accessor _showOverlay = true; diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts index 54cd506cb239d..6a14ee07c7117 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-edgeless-synced-doc-block.ts @@ -8,7 +8,7 @@ import { ThemeExtensionIdentifier, ThemeProvider, } from '@blocksuite/affine-shared/services'; -import { BlockSelection, BlockStdScope } from '@blocksuite/block-std'; +import { BlockStdScope } from '@blocksuite/block-std'; import { Bound } from '@blocksuite/global/utils'; import { html, nothing } from 'lit'; import { choose } from 'lit/directives/choose.js'; @@ -55,7 +55,6 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock( } const theme = this.isPageMode ? appTheme : edgelessTheme; - const isSelected = !!this.selected?.is(BlockSelection); const scale = this.model.scale ?? 1; this.dataset.nestedEditor = ''; @@ -94,8 +93,8 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock( 'affine-embed-synced-doc-container': true, [editorMode]: true, [theme]: true, - selected: isSelected, surface: true, + selected: this.selected$.value, })} @click=${this._handleClick} style=${containerStyleMap} diff --git a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts index e2b9537ed51d1..f4faabc9467ed 100644 --- a/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts +++ b/blocksuite/affine/block-embed/src/embed-synced-doc-block/embed-synced-doc-block.ts @@ -180,7 +180,6 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent
diff --git a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-block.ts b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-block.ts index b2bb14b28f84e..de42a7d99935f 100644 --- a/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-block.ts +++ b/blocksuite/affine/block-embed/src/embed-youtube-block/embed-youtube-block.ts @@ -4,7 +4,7 @@ import type { EmbedYoutubeStyles, } from '@blocksuite/affine-model'; import { ThemeProvider } from '@blocksuite/affine-shared/services'; -import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std'; +import { BlockSelection } from '@blocksuite/block-std'; import { html, nothing } from 'lit'; import { property, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -95,26 +95,21 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent< // this is required to prevent iframe from capturing pointer events this.disposables.add( - this.std.selection.slots.changed.on(() => { - this._isSelected = - !!this.selected?.is(BlockSelection) || - !!this.selected?.is(SurfaceSelection); - - this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this.selected$.subscribe(selected => { + this._showOverlay = this._isResizing || this._isDragging || !selected; }) ); // this is required to prevent iframe from capturing pointer events this.handleEvent('dragStart', () => { this._isDragging = true; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); this.handleEvent('dragEnd', () => { this._isDragging = false; this._showOverlay = - this._isResizing || this._isDragging || !this._isSelected; + this._isResizing || this._isDragging || !this.selected$.peek(); }); matchMedia('print').addEventListener('change', () => { @@ -160,7 +155,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent< class=${classMap({ 'affine-embed-youtube-block': true, loading, - selected: this._isSelected, + selected: this.selected$.value, })} style=${styleMap({ transform: `scale(${this._scale})`, @@ -238,9 +233,6 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent< ); } - @state() - protected accessor _isSelected = false; - @state() private accessor _showImage = false; diff --git a/blocksuite/affine/block-paragraph/src/paragraph-block.ts b/blocksuite/affine/block-paragraph/src/paragraph-block.ts index 8f32267ea4c7f..fb8d1c20bc2ee 100644 --- a/blocksuite/affine/block-paragraph/src/paragraph-block.ts +++ b/blocksuite/affine/block-paragraph/src/paragraph-block.ts @@ -18,7 +18,7 @@ import { import type { BlockComponent } from '@blocksuite/block-std'; import { getInlineRangeProvider, TextSelection } from '@blocksuite/block-std'; import type { InlineRangeProvider } from '@blocksuite/inline'; -import { effect, signal } from '@preact/signals-core'; +import { computed, effect, signal } from '@preact/signals-core'; import { html, nothing, type TemplateResult } from 'lit'; import { query, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -34,6 +34,14 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent< > { static override styles = paragraphBlockStyles; + focused$ = computed(() => { + const selection = this.std.selection.value.find( + selection => selection.blockId === this.model?.id + ); + if (!selection) return false; + return selection.is(TextSelection); + }); + private readonly _composing = signal(false); private readonly _displayPlaceholder = signal(false); @@ -121,7 +129,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent< } const textSelection = this.host.selection.find(TextSelection); const isCollapsed = textSelection?.isCollapsed() ?? false; - if (!this.selected || !isCollapsed) { + if (!this.focused$.value || !isCollapsed) { this._displayPlaceholder.value = false; return; } diff --git a/blocksuite/affine/block-table/src/selection-controller.ts b/blocksuite/affine/block-table/src/selection-controller.ts index 7918e42ff90b3..c09c26ddae025 100644 --- a/blocksuite/affine/block-table/src/selection-controller.ts +++ b/blocksuite/affine/block-table/src/selection-controller.ts @@ -266,11 +266,9 @@ export class SelectionController implements ReactiveController { } selected$ = computed(() => this.getSelected()); getSelected(): TableSelectionData | undefined { - const selected = this.host.selected; - - if (selected instanceof TableSelection) { - return selected.data; - } - return undefined; + const selection = this.host.selection.value.find( + selection => selection.blockId === this.host.model.id + ); + return selection?.is(TableSelection) ? selection.data : undefined; } } diff --git a/blocksuite/affine/components/src/block-selection/index.ts b/blocksuite/affine/components/src/block-selection/index.ts index d919aec936b14..e15c8347c7ecc 100644 --- a/blocksuite/affine/components/src/block-selection/index.ts +++ b/blocksuite/affine/components/src/block-selection/index.ts @@ -1,7 +1,3 @@ -import { - type BlockComponent, - BlockSelection as StdBlockSelection, -} from '@blocksuite/block-std'; import { SignalWatcher } from '@blocksuite/global/utils'; import { css, LitElement, type PropertyValues } from 'lit'; import { property } from 'lit/decorators.js'; @@ -50,22 +46,14 @@ export class BlockSelection extends SignalWatcher(LitElement) { this.style.borderWidth = `${this.borderWidth}px`; } - override disconnectedCallback() { - super.disconnectedCallback(); - this.block = null as unknown as BlockComponent; // force gc - } - - protected override updated(_changedProperties: PropertyValues): void { - super.updated(_changedProperties); - if (this.block) { - this.style.display = this.block.selected?.is(StdBlockSelection) - ? 'block' - : 'none'; + protected override updated(changed: PropertyValues) { + if (changed.has('selected')) { + this.style.display = this.selected ? 'block' : 'none'; } } @property({ attribute: false }) - accessor block!: BlockComponent; + accessor selected = false; @property({ attribute: false }) accessor borderRadius: number = 5; diff --git a/blocksuite/affine/components/src/caption/captioned-block-component.ts b/blocksuite/affine/components/src/caption/captioned-block-component.ts index 72f1f9efa179a..b0bbf46ba2a10 100644 --- a/blocksuite/affine/components/src/caption/captioned-block-component.ts +++ b/blocksuite/affine/components/src/caption/captioned-block-component.ts @@ -58,7 +58,9 @@ export class CaptionedBlockComponent< >` : nothing} ${this.selectedStyle === SelectedStyle.Background - ? html`` + ? html`` : null} ${this.useZeroWidth && !this.doc.readonly ? html`` diff --git a/blocksuite/framework/block-std/src/view/element/block-component.ts b/blocksuite/framework/block-std/src/view/element/block-component.ts index 1cc4a57f74665..0f14ad240f40a 100644 --- a/blocksuite/framework/block-std/src/view/element/block-component.ts +++ b/blocksuite/framework/block-std/src/view/element/block-component.ts @@ -12,6 +12,7 @@ import { html } from 'lit/static-html.js'; import type { EventName, UIEventHandler } from '../../event/index.js'; import type { BlockService } from '../../extension/index.js'; import type { BlockStdScope } from '../../scope/index.js'; +import { BlockSelection } from '../../selection/index.js'; import { PropTypes, requiredProperties } from '../decorators/index.js'; import { blockComponentSymbol, @@ -35,16 +36,12 @@ export class BlockComponent< @consume({ context: stdContext }) accessor std!: BlockStdScope; - private readonly _selected = computed(() => { - const selection = this.std.selection.value.find(selection => { - return selection.blockId === this.model?.id; - }); - - if (!selection) { - return null; - } - - return selection; + selected$ = computed(() => { + const selection = this.std.selection.value.find( + selection => selection.blockId === this.model?.id + ); + if (!selection) return false; + return selection.is(BlockSelection); }); [blockComponentSymbol] = true; @@ -141,10 +138,6 @@ export class BlockComponent< return rootComponent ?? null; } - get selected() { - return this._selected.value; - } - get selection() { return this.host.selection; } diff --git a/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts b/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts index 609fc0d9cda62..9c63990065589 100644 --- a/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts +++ b/blocksuite/framework/block-std/src/view/element/gfx-block-component.ts @@ -1,10 +1,12 @@ import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { Bound } from '@blocksuite/global/utils'; +import { computed } from '@preact/signals-core'; import { nothing } from 'lit'; import type { BlockService } from '../../extension/index.js'; import { GfxControllerIdentifier } from '../../gfx/identifiers.js'; import type { GfxBlockElementModel } from '../../gfx/index.js'; +import { SurfaceSelection } from '../../selection/index.js'; import { BlockComponent } from './block-component.js'; export function isGfxBlockComponent( @@ -137,6 +139,14 @@ export function toGfxBlockComponent< return class extends CustomBlock { [GfxElementSymbol] = true; + override selected$ = computed(() => { + const selection = this.std.selection.value.find( + selection => selection.blockId === this.model?.id + ); + if (!selection) return false; + return selection.is(SurfaceSelection); + }); + get gfx() { return this.std.get(GfxControllerIdentifier); }