refactor(editor): remove selection global types (#9532)

Closes: [BS-2217](https://linear.app/affine-design/issue/BS-2217/remove-global-types-in-selection)
This commit is contained in:
Saul-Mirone
2025-01-06 03:45:10 +00:00
parent 8669936f2f
commit fc863e484c
105 changed files with 501 additions and 358 deletions

View File

@@ -13,6 +13,11 @@ 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 { Slice } from '@blocksuite/store';
import { flip, offset } from '@floating-ui/dom';
import { html, nothing } from 'lit';
@@ -44,7 +49,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
this,
({ abortController }) => {
const selection = this.host.selection;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (
!!textSelection &&
(!!textSelection.to || !!textSelection.from.length)
@@ -52,7 +57,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
return null;
}
const blockSelections = selection.filter('block');
const blockSelections = selection.filter(BlockSelection);
if (
blockSelections.length > 1 ||
(blockSelections.length === 1 &&
@@ -126,7 +131,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -167,7 +172,8 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
this.disposables.add(
this.std.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;

View File

@@ -4,6 +4,7 @@ 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';
@@ -73,7 +74,7 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<
}
override renderBlock() {
const selected = !!this.selected?.is('block');
const selected = !!this.selected?.is(BlockSelection);
return html`
<div
draggable="${this.blockDraggable ? 'true' : 'false'}"

View File

@@ -2,7 +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 { ShadowlessElement } from '@blocksuite/block-std';
import {
BlockSelection,
ShadowlessElement,
SurfaceSelection,
} from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import { OpenInNewIcon } from '@blocksuite/icons/lit';
import { html } from 'lit';
@@ -31,7 +35,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
private _selectBlock() {
const selectionManager = this.bookmark.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.bookmark.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -55,8 +59,8 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
this.disposables.add(
this.bookmark.selection.slots.changed.on(() => {
this._isSelected =
!!this.bookmark.selected?.is('block') ||
!!this.bookmark.selected?.is('surface');
!!this.bookmark.selected?.is(BlockSelection) ||
!!this.bookmark.selected?.is(SurfaceSelection);
})
);
}

View File

@@ -11,7 +11,11 @@ import {
} from '@blocksuite/affine-shared/services';
import { getViewportElement } from '@blocksuite/affine-shared/utils';
import type { BlockComponent } from '@blocksuite/block-std';
import { getInlineRangeProvider } from '@blocksuite/block-std';
import {
BlockSelection,
getInlineRangeProvider,
TextSelection,
} from '@blocksuite/block-std';
import { IS_MAC } from '@blocksuite/global/env';
import { noop } from '@blocksuite/global/utils';
import {
@@ -178,7 +182,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
this.bindHotKey({
Backspace: ctx => {
const state = ctx.get('keyboardState');
const textSelection = selectionManager.find('text');
const textSelection = selectionManager.find(TextSelection);
if (!textSelection) {
state.raw.preventDefault();
return;
@@ -189,7 +193,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
if (from.index === 0 && from.length === 0) {
state.raw.preventDefault();
selectionManager.setGroup('note', [
selectionManager.create('block', { blockId: this.blockId }),
selectionManager.create(BlockSelection, { blockId: this.blockId }),
]);
return true;
}

View File

@@ -8,6 +8,7 @@ import {
} from '@blocksuite/affine-components/icons';
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
import { isInsidePageEditor } from '@blocksuite/affine-shared/utils';
import { BlockSelection } from '@blocksuite/block-std';
import { noop, sleep } from '@blocksuite/global/utils';
import { html } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js';
@@ -134,7 +135,7 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
host.updateComplete
.then(() => {
host.selection.setGroup('note', [
host.selection.create('block', {
host.selection.create(BlockSelection, {
blockId: codeId,
}),
]);

View File

@@ -9,7 +9,11 @@ import {
} from '@blocksuite/affine-components/toolbar';
import type { CodeBlockModel } from '@blocksuite/affine-model';
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
import { WidgetComponent } from '@blocksuite/block-std';
import {
BlockSelection,
TextSelection,
WidgetComponent,
} from '@blocksuite/block-std';
import { limitShift, shift } from '@floating-ui/dom';
import { html } from 'lit';
@@ -34,7 +38,7 @@ export class AffineCodeToolbarWidget extends WidgetComponent<
const codeBlock = this.block;
const selection = this.host.selection;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (
!!textSelection &&
(!!textSelection.to || !!textSelection.from.length)
@@ -42,7 +46,7 @@ export class AffineCodeToolbarWidget extends WidgetComponent<
return null;
}
const blockSelections = selection.filter('block');
const blockSelections = selection.filter(BlockSelection);
if (
blockSelections.length > 1 ||
(blockSelections.length === 1 &&

View File

@@ -1,6 +1,7 @@
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
import type { DividerBlockModel } from '@blocksuite/affine-model';
import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '@blocksuite/affine-shared/consts';
import { BlockSelection } from '@blocksuite/block-std';
import { html } from 'lit';
import { dividerBlockStyles } from './styles.js';
@@ -15,7 +16,7 @@ export class DividerBlockComponent extends CaptionedBlockComponent<DividerBlockM
this.handleEvent('click', () => {
this.host.selection.setGroup('note', [
this.host.selection.create('block', {
this.host.selection.create(BlockSelection, {
blockId: this.blockId,
}),
]);

View File

@@ -3,7 +3,11 @@ import type { EdgelessTextBlockModel } from '@blocksuite/affine-model';
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import type { BlockComponent } from '@blocksuite/block-std';
import { GfxBlockComponent } from '@blocksuite/block-std';
import {
BlockSelection,
GfxBlockComponent,
TextSelection,
} from '@blocksuite/block-std';
import { Bound } from '@blocksuite/global/utils';
import { css, html } from 'lit';
import { query, state } from 'lit/decorators.js';
@@ -88,7 +92,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
.then(() => {
const command = this.std.command;
const blockSelections = this.model.children.map(child =>
this.std.selection.create('block', {
this.std.selection.create(BlockSelection, {
blockId: child.id,
})
);
@@ -178,7 +182,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
if (newParagraphId) {
std.selection.setGroup('note', [
std.selection.create('text', {
std.selection.create(TextSelection, {
from: {
blockId: newParagraphId,
index: 0,
@@ -310,7 +314,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
const last = paragraphOrLists.at(-1);
if (last) {
this.host.selection.setGroup('note', [
this.host.selection.create('text', {
this.host.selection.create(TextSelection, {
from: {
blockId: last.blockId,
index: last.model.text?.length ?? 0,

View File

@@ -9,7 +9,7 @@ import {
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import type { BlockService } from '@blocksuite/block-std';
import { BlockSelection, 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';
@@ -56,7 +56,7 @@ export class EmbedBlockComponent<
}
}
const selected = !!this.selected?.is('block');
const selected = !!this.selected?.is(BlockSelection);
return html`
<div
draggable="${this.blockDraggable ? 'true' : 'false'}"

View File

@@ -7,7 +7,12 @@ import {
EMBED_CARD_HEIGHT,
EMBED_CARD_WIDTH,
} from '@blocksuite/affine-shared/consts';
import type { BlockStdScope } from '@blocksuite/block-std';
import {
BlockSelection,
type BlockStdScope,
SurfaceSelection,
TextSelection,
} from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { Bound, Vec } from '@blocksuite/global/utils';
@@ -26,9 +31,9 @@ export function insertEmbedCard(
const selectionManager = host.selection;
let blockId: string | undefined;
const textSelection = selectionManager.find('text');
const blockSelection = selectionManager.find('block');
const surfaceSelection = selectionManager.find('surface');
const textSelection = selectionManager.find(TextSelection);
const blockSelection = selectionManager.find(BlockSelection);
const surfaceSelection = selectionManager.find(SurfaceSelection);
if (textSelection) {
blockId = textSelection.blockId;
} else if (blockSelection) {

View File

@@ -3,6 +3,7 @@ import type {
EmbedFigmaModel,
EmbedFigmaStyles,
} from '@blocksuite/affine-model';
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
import { html } from 'lit';
import { state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
@@ -41,7 +42,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -77,7 +78,8 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<
this.disposables.add(
this.std.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;

View File

@@ -4,6 +4,7 @@ import type {
EmbedGithubStyles,
} from '@blocksuite/affine-model';
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
import { html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
@@ -61,7 +62,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -111,7 +112,8 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
this.disposables.add(
this.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
})
);
}

View File

@@ -1,4 +1,5 @@
import type { EmbedHtmlModel, EmbedHtmlStyles } from '@blocksuite/affine-model';
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
import { html } from 'lit';
import { query, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
@@ -35,7 +36,7 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -54,7 +55,8 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
this.disposables.add(
this.std.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;

View File

@@ -21,6 +21,7 @@ import {
matchFlavours,
referenceToNode,
} from '@blocksuite/affine-shared/utils';
import { BlockSelection } from '@blocksuite/block-std';
import { Bound, throttle } from '@blocksuite/global/utils';
import { Text } from '@blocksuite/store';
import { computed } from '@preact/signals-core';
@@ -107,7 +108,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
private readonly _selectBlock = () => {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);

View File

@@ -1,6 +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 { html } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
@@ -46,7 +47,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -93,7 +94,8 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
this.disposables.add(
this.std.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;

View File

@@ -1,5 +1,9 @@
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { isGfxBlockComponent, ShadowlessElement } from '@blocksuite/block-std';
import {
BlockSelection,
isGfxBlockComponent,
ShadowlessElement,
} from '@blocksuite/block-std';
import { throttle, WithDisposable } from '@blocksuite/global/utils';
import { html, nothing } from 'lit';
import { property, queryAsync } from 'lit/decorators.js';
@@ -64,7 +68,7 @@ export class EmbedSyncedDocCard extends WithDisposable(ShadowlessElement) {
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.block.blockId,
});
selectionManager.setGroup('note', [blockSelection]);

View File

@@ -8,7 +8,7 @@ import {
ThemeExtensionIdentifier,
ThemeProvider,
} from '@blocksuite/affine-shared/services';
import { BlockStdScope } from '@blocksuite/block-std';
import { BlockSelection, BlockStdScope } from '@blocksuite/block-std';
import { assertExists, Bound } from '@blocksuite/global/utils';
import { html } from 'lit';
import { choose } from 'lit/directives/choose.js';
@@ -52,7 +52,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
}
const theme = this.isPageMode ? appTheme : edgelessTheme;
const isSelected = !!this.selected?.is('block');
const isSelected = !!this.selected?.is(BlockSelection);
const scale = this.model.scale ?? 1;
this.dataset.nestedEditor = '';

View File

@@ -19,6 +19,7 @@ import {
SpecProvider,
} from '@blocksuite/affine-shared/utils';
import {
BlockSelection,
BlockServiceWatcher,
BlockStdScope,
type EditorHost,
@@ -164,7 +165,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
edgelessTheme = themeExtension.getEdgelessTheme(this.syncedDoc.id).value;
}
const theme = isPageMode ? appTheme : edgelessTheme;
const isSelected = !!this.selected?.is('block');
const isSelected = !!this.selected?.is(BlockSelection);
this.dataset.nestedEditor = '';
@@ -428,7 +429,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);

View File

@@ -4,6 +4,7 @@ import type {
EmbedYoutubeStyles,
} from '@blocksuite/affine-model';
import { ThemeProvider } from '@blocksuite/affine-shared/services';
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
import { html, nothing } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
@@ -49,7 +50,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
private _selectBlock() {
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);
@@ -96,7 +97,8 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
this.disposables.add(
this.std.selection.slots.changed.on(() => {
this._isSelected =
!!this.selected?.is('block') || !!this.selected?.is('surface');
!!this.selected?.is(BlockSelection) ||
!!this.selected?.is(SurfaceSelection);
this._showOverlay =
this._isResizing || this._isDragging || !this._isSelected;

View File

@@ -1,5 +1,10 @@
import { ImageSelection } from '@blocksuite/affine-shared/selection';
import type { BaseSelection, UIEventStateContext } from '@blocksuite/block-std';
import { ShadowlessElement } from '@blocksuite/block-std';
import {
BlockSelection,
ShadowlessElement,
TextSelection,
} from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import { css, html, type PropertyValues } from 'lit';
import { property, query, state } from 'lit/decorators.js';
@@ -66,9 +71,9 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
selection.update(selList =>
selList
.filter<BaseSelection>(sel => !sel.is('image'))
.filter<BaseSelection>(sel => !sel.is(ImageSelection))
.concat(
selection.create('text', {
selection.create(TextSelection, {
from: {
blockId,
index: 0,
@@ -86,9 +91,11 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
selection.update(selList => {
return selList.map(sel => {
const current =
sel.is('image') && sel.blockId === this.block.blockId;
sel.is(ImageSelection) && sel.blockId === this.block.blockId;
if (current) {
return selection.create('block', { blockId: this.block.blockId });
return selection.create(BlockSelection, {
blockId: this.block.blockId,
});
}
return sel;
});
@@ -119,7 +126,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
const std = this._host.std;
// If the selection is not image selection, we should not handle it.
if (!std.selection.find('image')) {
if (!std.selection.find(ImageSelection)) {
return false;
}
@@ -145,7 +152,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
// If the selection is not image selection, we should not handle it.
if (!std.selection.find('image')) {
if (!std.selection.find(ImageSelection)) {
return false;
}
@@ -178,7 +185,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
this._disposables.add(
selection.slots.changed.on(selList => {
this._isSelected = selList.some(
sel => sel.blockId === this.block.blockId && sel.is('image')
sel => sel.blockId === this.block.blockId && sel.is(ImageSelection)
);
})
);
@@ -200,7 +207,9 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
selection.update(selList => {
return selList
.filter(sel => !['block', 'image', 'text'].includes(sel.type))
.concat(selection.create('image', { blockId: this.block.blockId }));
.concat(
selection.create(ImageSelection, { blockId: this.block.blockId })
);
});
return true;
}
@@ -213,7 +222,8 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
selection.update(selList =>
selList.filter(
sel => !(sel.is('image') && sel.blockId === this.block.blockId)
sel =>
!(sel.is(ImageSelection) && sel.blockId === this.block.blockId)
)
);
},

View File

@@ -1,6 +1,7 @@
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
import { Peekable } from '@blocksuite/affine-components/peek';
import type { ImageBlockModel } from '@blocksuite/affine-model';
import { BlockSelection } from '@blocksuite/block-std';
import { IS_MOBILE } from '@blocksuite/global/env';
import { html } from 'lit';
import { property, query, state } from 'lit/decorators.js';
@@ -51,7 +52,7 @@ export class ImageBlockComponent extends CaptionedBlockComponent<
event.stopPropagation();
const selectionManager = this.host.selection;
const blockSelection = selectionManager.create('block', {
const blockSelection = selectionManager.create(BlockSelection, {
blockId: this.blockId,
});
selectionManager.setGroup('note', [blockSelection]);

View File

@@ -1,6 +1,7 @@
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
import { createLitPortal } from '@blocksuite/affine-components/portal';
import type { LatexBlockModel } from '@blocksuite/affine-model';
import { BlockSelection } from '@blocksuite/block-std';
import type { Placement } from '@floating-ui/dom';
import { effect } from '@preact/signals-core';
import katex from 'katex';
@@ -19,7 +20,7 @@ export class LatexBlockComponent extends CaptionedBlockComponent<LatexBlockModel
}
get isBlockSelected() {
const blockSelection = this.selection.filter('block');
const blockSelection = this.selection.filter(BlockSelection);
return blockSelection.some(
selection => selection.blockId === this.model.id
);

View File

@@ -1,6 +1,6 @@
import type { IndentContext } from '@blocksuite/affine-shared/types';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
import { correctNumberedListsOrderToPrev } from './utils.js';
@@ -13,7 +13,7 @@ export const canDedentListCommand: Command<
const { std } = ctx;
const { selection, doc } = std;
if (!blockId) {
const text = selection.find('text');
const text = selection.find(TextSelection);
/**
* Do nothing if the selection:
* - is not a text selection
@@ -148,7 +148,7 @@ export const dedentListCommand: Command<'indentContext'> = (ctx, next) => {
doc.moveBlocks([model], grandParent, parent, false);
correctNumberedListsOrderToPrev(doc, model);
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -3,7 +3,7 @@ import {
getNearestHeadingBefore,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
import { correctNumberedListsOrderToPrev } from './utils.js';
@@ -16,7 +16,7 @@ export const canIndentListCommand: Command<
const { std } = ctx;
const { selection, doc } = std;
if (!blockId) {
const text = selection.find('text');
const text = selection.find(TextSelection);
/**
* Do nothing if the selection:
* - is not a text selection
@@ -133,7 +133,7 @@ export const indentListCommand: Command<'indentContext', never> = (
});
}
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -15,7 +15,11 @@ import {
import { DocModeProvider } from '@blocksuite/affine-shared/services';
import { getViewportElement } from '@blocksuite/affine-shared/utils';
import type { BaseSelection, BlockComponent } from '@blocksuite/block-std';
import { getInlineRangeProvider } from '@blocksuite/block-std';
import {
BlockSelection,
getInlineRangeProvider,
TextSelection,
} from '@blocksuite/block-std';
import type { InlineRangeProvider } from '@blocksuite/inline';
import { effect } from '@preact/signals-core';
import { html, nothing, type TemplateResult } from 'lit';
@@ -95,8 +99,10 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
const selection = this.host.selection;
selection.update(selList => {
return selList
.filter<BaseSelection>(sel => !sel.is('text') && !sel.is('block'))
.concat(selection.create('block', { blockId: this.blockId }));
.filter<BaseSelection>(
sel => !sel.is(TextSelection) && !sel.is(BlockSelection)
)
.concat(selection.create(BlockSelection, { blockId: this.blockId }));
});
}

View File

@@ -3,7 +3,7 @@ import {
textKeymap,
} from '@blocksuite/affine-components/rich-text';
import { ListBlockSchema } from '@blocksuite/affine-model';
import { KeymapExtension } from '@blocksuite/block-std';
import { KeymapExtension, TextSelection } from '@blocksuite/block-std';
import { IS_MAC } from '@blocksuite/global/env';
import { forwardDelete } from './utils/forward-delete.js';
@@ -12,7 +12,7 @@ export const ListKeymapExtension = KeymapExtension(
std => {
return {
Enter: ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return false;
ctx.get('keyboardState').raw.preventDefault();
@@ -23,7 +23,7 @@ export const ListKeymapExtension = KeymapExtension(
return true;
},
'Mod-Enter': ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return false;
ctx.get('keyboardState').raw.preventDefault();
@@ -40,7 +40,7 @@ export const ListKeymapExtension = KeymapExtension(
if (selectedModels?.length !== 1) {
return false;
}
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return false;
ctx.get('keyboardState').raw.preventDefault();
@@ -61,7 +61,7 @@ export const ListKeymapExtension = KeymapExtension(
if (selectedModels?.length !== 1) {
return;
}
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return false;
ctx.get('keyboardState').raw.preventDefault();
@@ -76,7 +76,7 @@ export const ListKeymapExtension = KeymapExtension(
return true;
},
Backspace: ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return false;
const isCollapsed = text.isCollapsed();
const isStart = isCollapsed && text.from.index === 0;

View File

@@ -2,7 +2,7 @@ import {
getNextContentBlock,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockStdScope } from '@blocksuite/block-std';
import { type BlockStdScope, TextSelection } from '@blocksuite/block-std';
import type { Text } from '@blocksuite/store';
// When deleting at line end of a list block,
@@ -20,7 +20,7 @@ import type { Text } from '@blocksuite/store';
- Line9
*/
export function forwardDelete(std: BlockStdScope): true | undefined {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const isCollapsed = text.isCollapsed();
const doc = std.doc;

View File

@@ -8,7 +8,11 @@ import {
mergeToCodeModel,
transformModel,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import {
BlockSelection,
type Command,
TextSelection,
} from '@blocksuite/block-std';
import type { BlockModel } from '@blocksuite/store';
type UpdateBlockConfig = {
@@ -108,11 +112,11 @@ export const updateBlockType: Command<
onModelTextUpdated(host, model)
);
const selectionManager = host.selection;
const textSelection = selectionManager.find('text');
const textSelection = selectionManager.find(TextSelection);
if (!textSelection) {
return false;
}
const newTextSelection = selectionManager.create('text', {
const newTextSelection = selectionManager.create(TextSelection, {
from: {
blockId: firstNewModel.id,
index: textSelection.from.index,
@@ -143,13 +147,13 @@ export const updateBlockType: Command<
const selectionManager = host.selection;
const blockSelections = selectionManager.filter('block');
const blockSelections = selectionManager.filter(BlockSelection);
if (blockSelections.length === 0) {
return false;
}
requestAnimationFrame(() => {
const selections = updatedBlocks.map(model => {
return selectionManager.create('block', {
return selectionManager.create(BlockSelection, {
blockId: model.id,
});
});

View File

@@ -1,5 +1,5 @@
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const dedentBlocksToRoot: Command<
never,
@@ -13,7 +13,7 @@ export const dedentBlocksToRoot: Command<
const { std, stopCapture = true } = ctx;
const { doc } = std;
if (!blockIds || !blockIds.length) {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (text) {
// If the text selection is not at the beginning of the block, use default behavior
if (text.from.index !== 0) return;

View File

@@ -2,7 +2,7 @@ import {
calculateCollapsedSiblings,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const dedentBlocks: Command<
never,
@@ -75,7 +75,7 @@ export const dedentBlocks: Command<
std.command.exec('dedentBlock', { blockId: id, stopCapture: false });
});
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -1,4 +1,4 @@
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const focusBlockEnd: Command<'focusBlock'> = (ctx, next) => {
const { focusBlock, std } = ctx;
@@ -7,7 +7,7 @@ export const focusBlockEnd: Command<'focusBlock'> = (ctx, next) => {
const { selection } = std;
selection.setGroup('note', [
selection.create('text', {
selection.create(TextSelection, {
from: {
blockId: focusBlock.blockId,
index: focusBlock.model.text.length,

View File

@@ -1,4 +1,4 @@
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const focusBlockStart: Command<'focusBlock'> = (ctx, next) => {
const { focusBlock, std } = ctx;
@@ -7,7 +7,7 @@ export const focusBlockStart: Command<'focusBlock'> = (ctx, next) => {
const { selection } = std;
selection.setGroup('note', [
selection.create('text', {
selection.create(TextSelection, {
from: { blockId: focusBlock.blockId, index: 0, length: 0 },
to: null,
}),

View File

@@ -3,7 +3,7 @@ import {
getNearestHeadingBefore,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const indentBlocks: Command<
never,
@@ -117,7 +117,7 @@ export const indentBlocks: Command<
}
}
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -1,4 +1,4 @@
import type { Command } from '@blocksuite/block-std';
import { BlockSelection, type Command } from '@blocksuite/block-std';
export const selectBlock: Command<'focusBlock'> = (ctx, next) => {
const { focusBlock, std } = ctx;
@@ -9,7 +9,7 @@ export const selectBlock: Command<'focusBlock'> = (ctx, next) => {
const { selection } = std;
selection.setGroup('note', [
selection.create('block', { blockId: focusBlock.blockId }),
selection.create(BlockSelection, { blockId: focusBlock.blockId }),
]);
return next();

View File

@@ -1,4 +1,4 @@
import type { Command } from '@blocksuite/block-std';
import { BlockSelection, type Command } from '@blocksuite/block-std';
export const selectBlocksBetween: Command<
'focusBlock' | 'anchorBlock',
@@ -14,7 +14,7 @@ export const selectBlocksBetween: Command<
// In same block
if (anchorBlock.blockId === focusBlock.blockId) {
const blockId = focusBlock.blockId;
selection.setGroup('note', [selection.create('block', { blockId })]);
selection.setGroup('note', [selection.create(BlockSelection, { blockId })]);
return next();
}
@@ -23,11 +23,11 @@ export const selectBlocksBetween: Command<
if (selections.every(sel => sel.blockId !== focusBlock.blockId)) {
if (tail) {
selections.push(
selection.create('block', { blockId: focusBlock.blockId })
selection.create(BlockSelection, { blockId: focusBlock.blockId })
);
} else {
selections.unshift(
selection.create('block', { blockId: focusBlock.blockId })
selection.create(BlockSelection, { blockId: focusBlock.blockId })
);
}
}

View File

@@ -1,17 +1,21 @@
import type { BlockSelection, BlockStdScope } from '@blocksuite/block-std';
import {
BlockSelection,
type BlockStdScope,
TextSelection,
} from '@blocksuite/block-std';
const getSelection = (std: BlockStdScope) => std.selection;
function getBlockSelectionBySide(std: BlockStdScope, tail: boolean) {
const selection = getSelection(std);
const selections = selection.filter('block');
const selections = selection.filter(BlockSelection);
const sel = selections.at(tail ? -1 : 0) as BlockSelection | undefined;
return sel ?? null;
}
function getTextSelection(std: BlockStdScope) {
const selection = getSelection(std);
return selection.find('text');
return selection.find(TextSelection);
}
const pathToBlock = (std: BlockStdScope, blockId: string) =>

View File

@@ -15,7 +15,11 @@ import {
stopPropagation,
} from '@blocksuite/affine-shared/utils';
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
import { ShadowlessElement, toGfxBlockComponent } from '@blocksuite/block-std';
import {
ShadowlessElement,
TextSelection,
toGfxBlockComponent,
} from '@blocksuite/block-std';
import {
almostEqual,
Bound,
@@ -305,7 +309,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
this.updateComplete
.then(() => {
this.std.selection.setGroup('note', [
this.std.selection.create('text', {
this.std.selection.create(TextSelection, {
from: {
blockId: pId,
index: 0,

View File

@@ -4,9 +4,10 @@ import { matchFlavours } from '@blocksuite/affine-shared/utils';
import {
type BaseSelection,
type BlockComponent,
type BlockSelection,
BlockSelection,
BlockService,
type BlockStdScope,
TextSelection,
type UIEventHandler,
type UIEventStateContext,
} from '@blocksuite/block-std';
@@ -95,7 +96,7 @@ export class NoteBlockService extends BlockService {
const [codeModel] = newModels;
onModelElementUpdated(ctx.std, codeModel, codeElement => {
this._std.selection.setGroup('note', [
this._std.selection.create('text', {
this._std.selection.create(TextSelection, {
from: {
blockId: codeElement.blockId,
index: 0,
@@ -439,7 +440,7 @@ export class NoteBlockService extends BlockService {
const blockId = doc.addBlock('affine:paragraph', {}, parent, index + 1);
const sel = selection.create('text', {
const sel = selection.create(TextSelection, {
from: {
blockId,
index: 0,
@@ -469,7 +470,7 @@ export class NoteBlockService extends BlockService {
}
ctx.std.selection.update(selList => {
return selList.filter(sel => !sel.is('block'));
return selList.filter(sel => !sel.is(BlockSelection));
});
return next();
@@ -481,7 +482,7 @@ export class NoteBlockService extends BlockService {
private readonly _onSelectAll: UIEventHandler = ctx => {
const selection = this._std.selection;
const block = selection.find('block');
const block = selection.find(BlockSelection);
if (!block) {
return;
}
@@ -492,13 +493,13 @@ export class NoteBlockService extends BlockService {
ctx.get('defaultState').event.preventDefault();
const children = note.children;
const blocks: BlockSelection[] = children.map(child => {
return selection.create('block', {
return selection.create(BlockSelection, {
blockId: child.id,
});
});
selection.update(selList => {
return selList
.filter<BaseSelection>(sel => !sel.is('block'))
.filter<BaseSelection>(sel => !sel.is(BlockSelection))
.concat(blocks);
});
};

View File

@@ -1,5 +1,5 @@
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
/**
* Add a paragraph next to the current block.
@@ -17,7 +17,7 @@ export const addParagraphCommand: Command<
let blockId = ctx.blockId;
if (!blockId) {
const text = selection.find('text');
const text = selection.find(TextSelection);
blockId = text?.blockId;
}
if (!blockId) return;

View File

@@ -3,7 +3,7 @@ import {
calculateCollapsedSiblings,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const canDedentParagraphCommand: Command<
never,
@@ -13,7 +13,7 @@ export const canDedentParagraphCommand: Command<
let { blockId, inlineIndex } = ctx;
const { std } = ctx;
const { selection, doc } = std;
const text = selection.find('text');
const text = selection.find(TextSelection);
if (!blockId) {
/**
@@ -97,7 +97,7 @@ export const dedentParagraphCommand: Command<'indentContext'> = (ctx, next) => {
doc.moveBlocks([model], grandParent, parent, false);
}
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -5,7 +5,7 @@ import {
getNearestHeadingBefore,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const canIndentParagraphCommand: Command<
never,
@@ -18,7 +18,7 @@ export const canIndentParagraphCommand: Command<
const { schema } = doc;
if (!blockId) {
const text = selection.find('text');
const text = selection.find(TextSelection);
/**
* Do nothing if the selection:
* - is not a text selection
@@ -140,7 +140,7 @@ export const indentParagraphCommand: Command<'indentContext'> = (ctx, next) => {
} as Partial<ListBlockModel>);
}
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (textSelection) {
host.updateComplete
.then(() => {

View File

@@ -3,7 +3,7 @@ import {
getInlineEditorByModel,
} from '@blocksuite/affine-components/rich-text';
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const splitParagraphCommand: Command<
never,
@@ -16,7 +16,7 @@ export const splitParagraphCommand: Command<
const { doc, host, selection } = std;
let blockId = ctx.blockId;
if (!blockId) {
const text = selection.find('text');
const text = selection.find(TextSelection);
blockId = text?.blockId;
}
if (!blockId) return;

View File

@@ -16,7 +16,7 @@ import {
getViewportElement,
} from '@blocksuite/affine-shared/utils';
import type { BlockComponent } from '@blocksuite/block-std';
import { getInlineRangeProvider } 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 { html, nothing, type TemplateResult } from 'lit';
@@ -119,7 +119,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
this._displayPlaceholder.value = false;
return;
}
const textSelection = this.host.selection.find('text');
const textSelection = this.host.selection.find(TextSelection);
const isCollapsed = textSelection?.isCollapsed() ?? false;
if (!this.selected || !isCollapsed) {
this._displayPlaceholder.value = false;
@@ -159,7 +159,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
// reset text selection when selected block is collapsed
if (this.model.type.startsWith('h') && collapsed) {
const collapsedSiblings = this.collapsedSiblings;
const textSelection = this.host.selection.find('text');
const textSelection = this.host.selection.find(TextSelection);
if (
textSelection &&

View File

@@ -9,7 +9,7 @@ import {
calculateCollapsedSiblings,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import { KeymapExtension } from '@blocksuite/block-std';
import { KeymapExtension, TextSelection } from '@blocksuite/block-std';
import { IS_MAC } from '@blocksuite/global/env';
import { forwardDelete } from './utils/forward-delete.js';
@@ -19,7 +19,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
std => {
return {
Backspace: ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const isCollapsed = text.isCollapsed();
const isStart = isCollapsed && text.from.index === 0;
@@ -52,7 +52,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
},
'Mod-Enter': ctx => {
const { doc } = std;
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const model = doc.getBlock(text.from.blockId)?.model;
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;
@@ -79,7 +79,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
},
Enter: ctx => {
const { doc } = std;
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const model = doc.getBlock(text.from.blockId)?.model;
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;

View File

@@ -3,11 +3,15 @@ import {
getNextContentBlock,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockStdScope } from '@blocksuite/block-std';
import {
BlockSelection,
type BlockStdScope,
TextSelection,
} from '@blocksuite/block-std';
export function forwardDelete(std: BlockStdScope) {
const { doc, host } = std;
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const isCollapsed = text.isCollapsed();
const model = doc.getBlock(text.from.blockId)?.model;
@@ -30,7 +34,7 @@ export function forwardDelete(std: BlockStdScope) {
if (matchFlavours(nextSibling, ignoreForwardDeleteFlavourList)) {
std.selection.setGroup('note', [
std.selection.create('block', { blockId: nextSibling.id }),
std.selection.create(BlockSelection, { blockId: nextSibling.id }),
]);
return true;
}
@@ -61,7 +65,7 @@ export function forwardDelete(std: BlockStdScope) {
if (nextBlock) {
std.selection.setGroup('note', [
std.selection.create('block', { blockId: nextBlock.id }),
std.selection.create(BlockSelection, { blockId: nextBlock.id }),
]);
}
return true;

View File

@@ -11,7 +11,7 @@ import {
getPrevContentBlock,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { EditorHost } from '@blocksuite/block-std';
import { BlockSelection, type EditorHost } from '@blocksuite/block-std';
import type { BlockModel, Text } from '@blocksuite/store';
/**
@@ -72,7 +72,7 @@ export function mergeWithPrev(editorHost: EditorHost, model: BlockModel) {
...EMBED_BLOCK_FLAVOUR_LIST,
])
) {
const selection = editorHost.selection.create('block', {
const selection = editorHost.selection.create(BlockSelection, {
blockId: prevBlock.id,
});
editorHost.selection.setGroup('note', [selection]);

View File

@@ -28,10 +28,12 @@ import {
import {
type BaseSelection,
BlockComponent,
BlockSelection,
BlockServiceWatcher,
BlockStdScope,
type EditorHost,
LifeCycleWatcher,
TextSelection,
} from '@blocksuite/block-std';
import {
GfxBlockElementModel,
@@ -267,7 +269,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
private _focusBlock() {
this.selection.update(() => {
return [this.selection.create('block', { blockId: this.blockId })];
return [this.selection.create(BlockSelection, { blockId: this.blockId })];
});
}
@@ -287,9 +289,9 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
requestConnectedFrame(() => {
selection.update(selList => {
return selList
.filter<BaseSelection>(sel => !sel.is('block'))
.filter<BaseSelection>(sel => !sel.is(BlockSelection))
.concat(
selection.create('text', {
selection.create(TextSelection, {
from: {
blockId: model.id,
index: 0,
@@ -415,7 +417,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
this._disposables.add(
selection.slots.changed.on(selList => {
this._focused = selList.some(
sel => sel.blockId === this.blockId && sel.is('block')
sel => sel.blockId === this.blockId && sel.is(BlockSelection)
);
})
);

View File

@@ -1,4 +1,7 @@
import type { BlockComponent } from '@blocksuite/block-std';
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';
@@ -55,7 +58,9 @@ export class BlockSelection extends SignalWatcher(LitElement) {
protected override updated(_changedProperties: PropertyValues): void {
super.updated(_changedProperties);
if (this.block) {
this.style.display = this.block.selected?.is('block') ? 'block' : 'none';
this.style.display = this.block.selected?.is(StdBlockSelection)
? 'block'
: 'none';
}
}

View File

@@ -3,7 +3,11 @@ import {
getCurrentNativeRange,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockStdScope, EditorHost } from '@blocksuite/block-std';
import {
type BlockStdScope,
type EditorHost,
TextSelection,
} from '@blocksuite/block-std';
import type { InlineEditor, InlineRange } from '@blocksuite/inline';
import { BlockModel } from '@blocksuite/store';
@@ -81,7 +85,7 @@ export function selectTextModel(
) {
const { selection } = std;
selection.setGroup('note', [
selection.create('text', {
selection.create(TextSelection, {
from: { blockId: id, index, length },
to: null,
}),

View File

@@ -1,5 +1,5 @@
import { matchFlavours } from '@blocksuite/affine-shared/utils';
import type { Command, TextSelection } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
import type { Text } from '@blocksuite/store';
export const deleteTextCommand: Command<
@@ -36,7 +36,7 @@ export const deleteTextCommand: Command<
if (!to) {
fromText.delete(from.index, from.length);
ctx.std.selection.setGroup('note', [
ctx.std.selection.create('text', {
ctx.std.selection.create(TextSelection, {
from: {
blockId: from.blockId,
index: from.index,
@@ -69,7 +69,7 @@ export const deleteTextCommand: Command<
});
ctx.std.selection.setGroup('note', [
ctx.std.selection.create('text', {
ctx.std.selection.create(TextSelection, {
from: {
blockId: from.blockId,
index: from.index,

View File

@@ -2,7 +2,12 @@ import type { ReferenceInfo } from '@blocksuite/affine-model';
import { ParseDocUrlProvider } from '@blocksuite/affine-shared/services';
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
import type { BlockComponent } from '@blocksuite/block-std';
import { BLOCK_ID_ATTR, ShadowlessElement } from '@blocksuite/block-std';
import {
BLOCK_ID_ATTR,
BlockSelection,
ShadowlessElement,
TextSelection,
} from '@blocksuite/block-std';
import {
type DeltaInsert,
INLINE_ROOT_ATTR,
@@ -69,12 +74,12 @@ export class AffineLink extends ShadowlessElement {
}
const selection = this.std?.selection;
const textSelection = selection?.find('text');
const textSelection = selection?.find(TextSelection);
if (!!textSelection && !textSelection.isCollapsed()) {
return null;
}
const blockSelections = selection?.filter('block');
const blockSelections = selection?.filter(BlockSelection);
if (blockSelections?.length) {
return null;
}

View File

@@ -15,6 +15,7 @@ import {
BLOCK_ID_ATTR,
type BlockComponent,
type BlockStdScope,
TextSelection,
} from '@blocksuite/block-std';
import { WithDisposable } from '@blocksuite/global/utils';
import type { InlineRange } from '@blocksuite/inline/types';
@@ -438,7 +439,7 @@ export class LinkPopup extends WithDisposable(LitElement) {
reference: null,
});
this.inlineEditor.setInlineRange(this.targetInlineRange);
const textSelection = this.host?.selection.find('text');
const textSelection = this.host?.selection.find(TextSelection);
if (!textSelection) return;
this.std?.range.syncTextSelectionToRange(textSelection);
@@ -452,7 +453,7 @@ export class LinkPopup extends WithDisposable(LitElement) {
index: this.targetInlineRange.index,
length: text.length,
});
const textSelection = this.host?.selection.find('text');
const textSelection = this.host?.selection.find(TextSelection);
if (!textSelection) return;
this.std?.range.syncTextSelectionToRange(textSelection);

View File

@@ -12,7 +12,9 @@ import {
import {
BLOCK_ID_ATTR,
type BlockComponent,
BlockSelection,
ShadowlessElement,
TextSelection,
} from '@blocksuite/block-std';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import { WithDisposable } from '@blocksuite/global/utils';
@@ -108,12 +110,12 @@ export class AffineReference extends WithDisposable(ShadowlessElement) {
if (!selection) {
return null;
}
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (!!textSelection && !textSelection.isCollapsed()) {
return null;
}
const blockSelections = selection.filter('block');
const blockSelections = selection.filter(BlockSelection);
if (blockSelections.length) {
return null;
}

View File

@@ -1,4 +1,9 @@
import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std';
import {
BlockSelection,
type BlockStdScope,
TextSelection,
type UIEventHandler,
} from '@blocksuite/block-std';
import {
focusTextModel,
@@ -11,21 +16,21 @@ export const textCommonKeymap = (
): Record<string, UIEventHandler> => {
return {
ArrowUp: () => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const inline = getInlineEditorByModel(std.host, text.from.blockId);
if (!inline) return;
return !inline.isFirstLine(inline.getInlineRange());
},
ArrowDown: () => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const inline = getInlineEditorByModel(std.host, text.from.blockId);
if (!inline) return;
return !inline.isLastLine(inline.getInlineRange());
},
Escape: ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
selectBlock(std, text.from.blockId);
@@ -33,7 +38,7 @@ export const textCommonKeymap = (
return true;
},
'Mod-a': ctx => {
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) return;
const model = std.doc.getBlock(text.from.blockId)?.model;
@@ -53,7 +58,7 @@ export const textCommonKeymap = (
return true;
},
Enter: ctx => {
const blocks = std.selection.filter('block');
const blocks = std.selection.filter(BlockSelection);
const blockId = blocks.at(-1)?.blockId;
if (!blockId) return;
@@ -68,5 +73,7 @@ export const textCommonKeymap = (
};
function selectBlock(std: BlockStdScope, blockId: string) {
std.selection.setGroup('note', [std.selection.create('block', { blockId })]);
std.selection.setGroup('note', [
std.selection.create(BlockSelection, { blockId }),
]);
}

View File

@@ -3,7 +3,11 @@ import {
createDefaultDoc,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std';
import {
type BlockStdScope,
TextSelection,
type UIEventHandler,
} from '@blocksuite/block-std';
import type { InlineEditor } from '@blocksuite/inline';
import { getInlineEditorByModel } from '../dom.js';
@@ -20,7 +24,7 @@ export const bracketKeymap = (
const { doc, selection } = std;
if (doc.readonly) return;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (!textSelection) return;
const model = doc.getBlock(textSelection.from.blockId)?.model;
if (!model) return;
@@ -46,7 +50,7 @@ export const bracketKeymap = (
const { doc, selection } = std;
if (doc.readonly) return;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (!textSelection) return;
const model = doc.getBlock(textSelection.from.blockId)?.model;
if (!model) return;
@@ -97,7 +101,7 @@ export const bracketKeymap = (
const { doc, selection } = std;
if (doc.readonly) return;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (!textSelection || textSelection.isCollapsed()) return;
if (!textSelection.isInSameBlock()) return;
const model = doc.getBlock(textSelection.from.blockId)?.model;

View File

@@ -1,4 +1,8 @@
import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std';
import {
type BlockStdScope,
TextSelection,
type UIEventHandler,
} from '@blocksuite/block-std';
import { textFormatConfigs } from '../format/index.js';
@@ -13,7 +17,7 @@ export const textFormatKeymap = (std: BlockStdScope) =>
const { doc, selection } = std;
if (doc.readonly) return;
const textSelection = selection.find('text');
const textSelection = selection.find(TextSelection);
if (!textSelection) return;
config.action(std.host);

View File

@@ -2,7 +2,7 @@ import {
isMarkdownPrefix,
matchFlavours,
} from '@blocksuite/affine-shared/utils';
import type { BlockStdScope } from '@blocksuite/block-std';
import { type BlockStdScope, TextSelection } from '@blocksuite/block-std';
import { getInlineEditorByModel } from '../dom.js';
import { toDivider } from './divider.js';
@@ -17,7 +17,7 @@ export function markdownInput(
): string | undefined {
if (!id) {
const selection = std.selection;
const text = selection.find('text');
const text = selection.find(TextSelection);
id = text?.from.blockId;
}
if (!id) return;

View File

@@ -1,7 +1,8 @@
import type {
BlockStdScope,
EditorHost,
TextRangePoint,
import {
type BlockStdScope,
type EditorHost,
type TextRangePoint,
TextSelection,
} from '@blocksuite/block-std';
import type {
BlockSnapshot,
@@ -38,7 +39,7 @@ const sliceText = (slots: JobSlots, std: EditorHost['std']) => {
const snapshot = payload.snapshot;
const model = payload.model;
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (text && text.from.blockId === model.id) {
handlePoint(text.from, snapshot, model);
return;

View File

@@ -7,9 +7,10 @@ import {
import {
BLOCK_ID_ATTR,
type BlockComponent,
BlockSelection,
type EditorHost,
type TextRangePoint,
type TextSelection,
TextSelection,
} from '@blocksuite/block-std';
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
import { assertExists } from '@blocksuite/global/utils';
@@ -25,6 +26,7 @@ import {
import * as Y from 'yjs';
import { REFERENCE_NODE } from '../../consts';
import { ImageSelection } from '../../selection';
import {
ParseDocUrlProvider,
type ParseDocUrlService,
@@ -290,19 +292,19 @@ class PasteTr {
}
if (!cursorModel.text) {
if (matchFlavours(cursorModel, ['affine:image'])) {
const selection = this.std.selection.create('image', {
const selection = this.std.selection.create(ImageSelection, {
blockId: target.blockId,
});
this.std.selection.setGroup('note', [selection]);
return;
}
const selection = this.std.selection.create('block', {
const selection = this.std.selection.create(BlockSelection, {
blockId: target.blockId,
});
this.std.selection.setGroup('note', [selection]);
return;
}
const selection = this.std.selection.create('text', {
const selection = this.std.selection.create(TextSelection, {
from: {
blockId: target.blockId,
index: cursorModel.text ? this.lastIndex : 0,
@@ -511,7 +513,7 @@ export const pasteMiddleware = (std: EditorHost['std']): JobMiddleware => {
const { snapshot } = payload;
flatNote(snapshot);
const text = std.selection.find('text');
const text = std.selection.find(TextSelection);
if (!text) {
return;
}

View File

@@ -16,7 +16,7 @@ export const getSelectedBlocksCommand: Command<
blockSelections?: BlockSelection[];
imageSelections?: ImageSelection[];
filter?: (el: BlockComponent) => boolean;
types?: Extract<BlockSuite.SelectionType, 'block' | 'text' | 'image'>[];
types?: Array<'image' | 'text' | 'block'>;
roles?: RoleType[];
mode?: 'all' | 'flat' | 'highest';
}

View File

@@ -1,4 +1,4 @@
import type { Command } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const clearAndSelectFirstModelCommand: Command<'selectedModels'> = (
ctx,
@@ -17,7 +17,7 @@ export const clearAndSelectFirstModelCommand: Command<'selectedModels'> = (
const firstModel = models[0];
if (firstModel.text) {
firstModel.text.clear();
const selection = ctx.std.selection.create('text', {
const selection = ctx.std.selection.create(TextSelection, {
from: {
blockId: firstModel.id,
index: 0,

View File

@@ -32,7 +32,7 @@ export const getSelectedModelsCommand: Command<
never,
'selectedModels',
{
types?: Extract<BlockSuite.SelectionType, 'block' | 'text' | 'image'>[];
types?: Array<'image' | 'text' | 'block'>;
mode?: 'all' | 'flat' | 'highest';
}
> = (ctx, next) => {

View File

@@ -1,10 +1,10 @@
import type { BlockSelection, Command } from '@blocksuite/block-std';
import { BlockSelection, type Command } from '@blocksuite/block-std';
export const getBlockSelectionsCommand: Command<
never,
'currentBlockSelections'
> = (ctx, next) => {
const currentBlockSelections = ctx.std.selection.filter('block');
const currentBlockSelections = ctx.std.selection.filter(BlockSelection);
if (currentBlockSelections.length === 0) return;
next({ currentBlockSelections });

View File

@@ -1,12 +1,12 @@
import type { Command } from '@blocksuite/block-std';
import type { ImageSelection } from '../../selection/index.js';
import { ImageSelection } from '../../selection/index.js';
export const getImageSelectionsCommand: Command<
never,
'currentImageSelections'
> = (ctx, next) => {
const currentImageSelections = ctx.std.selection.filter('image');
const currentImageSelections = ctx.std.selection.filter(ImageSelection);
if (currentImageSelections.length === 0) return;
next({ currentImageSelections });

View File

@@ -1,10 +1,10 @@
import type { Command, TextSelection } from '@blocksuite/block-std';
import { type Command, TextSelection } from '@blocksuite/block-std';
export const getTextSelectionCommand: Command<never, 'currentTextSelection'> = (
ctx,
next
) => {
const currentTextSelection = ctx.std.selection.find('text');
const currentTextSelection = ctx.std.selection.find(TextSelection);
if (!currentTextSelection) return;
next({ currentTextSelection });

View File

@@ -1,5 +1,10 @@
import { findNoteBlockModel } from '@blocksuite/affine-shared/utils';
import type { BlockComponent } from '@blocksuite/block-std';
import {
type BlockComponent,
BlockSelection,
SurfaceSelection,
TextSelection,
} from '@blocksuite/block-std';
import type { AffineDragHandleWidget } from '../drag-handle.js';
@@ -15,7 +20,7 @@ export class SelectionHelper {
setSelectedBlocks = (blocks: BlockComponent[], noteId?: string) => {
const { selection } = this;
const selections = blocks.map(block =>
selection.create('block', {
selection.create(BlockSelection, {
blockId: block.blockId,
})
);
@@ -28,7 +33,7 @@ export class SelectionHelper {
: findNoteBlockModel(blocks[0].model)?.id;
if (!surfaceElementId) return;
const surfaceSelection = selection.create(
'surface',
SurfaceSelection,
blocks[0]!.blockId,
[surfaceElementId],
true
@@ -49,9 +54,9 @@ export class SelectionHelper {
get selectedBlocks() {
const selection = this.selection;
return selection.find('text')
? selection.filter('text')
: selection.filter('block');
return selection.find(TextSelection)
? selection.filter(TextSelection)
: selection.filter(BlockSelection);
}
get selection() {

View File

@@ -23,6 +23,7 @@ import {
} from '@blocksuite/affine-shared/utils';
import {
type BlockComponent,
BlockSelection,
type DndEventState,
isGfxBlockComponent,
type UIEventHandler,
@@ -158,7 +159,7 @@ export class DragEventWatcher {
const selectBlockAndStartDragging = () => {
this._std.selection.setGroup('note', [
this._std.selection.create('block', {
this._std.selection.create(BlockSelection, {
blockId: hoverBlock.blockId,
}),
]);

View File

@@ -101,7 +101,7 @@ export class AffineDocRemoteSelectionWidget extends WidgetComponent {
if (textSelection) {
const range = this.std.range.textSelectionToRange(
this._selectionManager.create('text', {
this._selectionManager.create(TextSelection, {
from: {
blockId: textSelection.to
? textSelection.to.blockId

View File

@@ -1,6 +1,5 @@
import '@blocksuite/affine-shared/selection';
import type { DocMode } from '@blocksuite/affine-model';
import { HighlightSelection } from '@blocksuite/affine-shared/selection';
import { WidgetComponent } from '@blocksuite/block-std';
import {
GfxControllerIdentifier,
@@ -65,7 +64,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent {
anchorBounds$ = signal<Bound | null>(null);
highlighted$ = computed(() =>
this.service.selectionManager.find('highlight')
this.service.selectionManager.find(HighlightSelection)
);
#getBoundsInEdgeless() {