mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-28 15:55:19 +08:00
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:
@@ -13,6 +13,11 @@ import {
|
|||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { humanFileSize } from '@blocksuite/affine-shared/utils';
|
import { humanFileSize } from '@blocksuite/affine-shared/utils';
|
||||||
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
SurfaceSelection,
|
||||||
|
TextSelection,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { Slice } from '@blocksuite/store';
|
import { Slice } from '@blocksuite/store';
|
||||||
import { flip, offset } from '@floating-ui/dom';
|
import { flip, offset } from '@floating-ui/dom';
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
@@ -44,7 +49,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
|
|||||||
this,
|
this,
|
||||||
({ abortController }) => {
|
({ abortController }) => {
|
||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (
|
if (
|
||||||
!!textSelection &&
|
!!textSelection &&
|
||||||
(!!textSelection.to || !!textSelection.from.length)
|
(!!textSelection.to || !!textSelection.from.length)
|
||||||
@@ -52,7 +57,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection.filter('block');
|
const blockSelections = selection.filter(BlockSelection);
|
||||||
if (
|
if (
|
||||||
blockSelections.length > 1 ||
|
blockSelections.length > 1 ||
|
||||||
(blockSelections.length === 1 &&
|
(blockSelections.length === 1 &&
|
||||||
@@ -126,7 +131,7 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -167,7 +172,8 @@ export class AttachmentBlockComponent extends CaptionedBlockComponent<
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.std.selection.slots.changed.on(() => {
|
this.std.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
|
|
||||||
this._showOverlay =
|
this._showOverlay =
|
||||||
this._isResizing || this._isDragging || !this._isSelected;
|
this._isResizing || this._isDragging || !this._isSelected;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
} from '@blocksuite/affine-components/caption';
|
} from '@blocksuite/affine-components/caption';
|
||||||
import type { BookmarkBlockModel } from '@blocksuite/affine-model';
|
import type { BookmarkBlockModel } from '@blocksuite/affine-model';
|
||||||
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { property, query } from 'lit/decorators.js';
|
import { property, query } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -73,7 +74,7 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<
|
|||||||
}
|
}
|
||||||
|
|
||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
const selected = !!this.selected?.is('block');
|
const selected = !!this.selected?.is(BlockSelection);
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
draggable="${this.blockDraggable ? 'true' : 'false'}"
|
draggable="${this.blockDraggable ? 'true' : 'false'}"
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ import { getEmbedCardIcons } from '@blocksuite/affine-block-embed';
|
|||||||
import { WebIcon16 } from '@blocksuite/affine-components/icons';
|
import { WebIcon16 } from '@blocksuite/affine-components/icons';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { getHostName } from '@blocksuite/affine-shared/utils';
|
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 { WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { OpenInNewIcon } from '@blocksuite/icons/lit';
|
import { OpenInNewIcon } from '@blocksuite/icons/lit';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
@@ -31,7 +35,7 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.bookmark.host.selection;
|
const selectionManager = this.bookmark.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.bookmark.blockId,
|
blockId: this.bookmark.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -55,8 +59,8 @@ export class BookmarkCard extends WithDisposable(ShadowlessElement) {
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.bookmark.selection.slots.changed.on(() => {
|
this.bookmark.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.bookmark.selected?.is('block') ||
|
!!this.bookmark.selected?.is(BlockSelection) ||
|
||||||
!!this.bookmark.selected?.is('surface');
|
!!this.bookmark.selected?.is(SurfaceSelection);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import {
|
|||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { getViewportElement } from '@blocksuite/affine-shared/utils';
|
import { getViewportElement } from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent } from '@blocksuite/block-std';
|
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 { IS_MAC } from '@blocksuite/global/env';
|
||||||
import { noop } from '@blocksuite/global/utils';
|
import { noop } from '@blocksuite/global/utils';
|
||||||
import {
|
import {
|
||||||
@@ -178,7 +182,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
|
|||||||
this.bindHotKey({
|
this.bindHotKey({
|
||||||
Backspace: ctx => {
|
Backspace: ctx => {
|
||||||
const state = ctx.get('keyboardState');
|
const state = ctx.get('keyboardState');
|
||||||
const textSelection = selectionManager.find('text');
|
const textSelection = selectionManager.find(TextSelection);
|
||||||
if (!textSelection) {
|
if (!textSelection) {
|
||||||
state.raw.preventDefault();
|
state.raw.preventDefault();
|
||||||
return;
|
return;
|
||||||
@@ -189,7 +193,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent<
|
|||||||
if (from.index === 0 && from.length === 0) {
|
if (from.index === 0 && from.length === 0) {
|
||||||
state.raw.preventDefault();
|
state.raw.preventDefault();
|
||||||
selectionManager.setGroup('note', [
|
selectionManager.setGroup('note', [
|
||||||
selectionManager.create('block', { blockId: this.blockId }),
|
selectionManager.create(BlockSelection, { blockId: this.blockId }),
|
||||||
]);
|
]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from '@blocksuite/affine-components/icons';
|
} from '@blocksuite/affine-components/icons';
|
||||||
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
import type { MenuItemGroup } from '@blocksuite/affine-components/toolbar';
|
||||||
import { isInsidePageEditor } from '@blocksuite/affine-shared/utils';
|
import { isInsidePageEditor } from '@blocksuite/affine-shared/utils';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { noop, sleep } from '@blocksuite/global/utils';
|
import { noop, sleep } from '@blocksuite/global/utils';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||||
@@ -134,7 +135,7 @@ export const clipboardGroup: MenuItemGroup<CodeBlockToolbarContext> = {
|
|||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
host.selection.setGroup('note', [
|
host.selection.setGroup('note', [
|
||||||
host.selection.create('block', {
|
host.selection.create(BlockSelection, {
|
||||||
blockId: codeId,
|
blockId: codeId,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import {
|
|||||||
} from '@blocksuite/affine-components/toolbar';
|
} from '@blocksuite/affine-components/toolbar';
|
||||||
import type { CodeBlockModel } from '@blocksuite/affine-model';
|
import type { CodeBlockModel } from '@blocksuite/affine-model';
|
||||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
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 { limitShift, shift } from '@floating-ui/dom';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
|
|
||||||
@@ -34,7 +38,7 @@ export class AffineCodeToolbarWidget extends WidgetComponent<
|
|||||||
const codeBlock = this.block;
|
const codeBlock = this.block;
|
||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (
|
if (
|
||||||
!!textSelection &&
|
!!textSelection &&
|
||||||
(!!textSelection.to || !!textSelection.from.length)
|
(!!textSelection.to || !!textSelection.from.length)
|
||||||
@@ -42,7 +46,7 @@ export class AffineCodeToolbarWidget extends WidgetComponent<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection.filter('block');
|
const blockSelections = selection.filter(BlockSelection);
|
||||||
if (
|
if (
|
||||||
blockSelections.length > 1 ||
|
blockSelections.length > 1 ||
|
||||||
(blockSelections.length === 1 &&
|
(blockSelections.length === 1 &&
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||||
import type { DividerBlockModel } from '@blocksuite/affine-model';
|
import type { DividerBlockModel } from '@blocksuite/affine-model';
|
||||||
import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '@blocksuite/affine-shared/consts';
|
import { BLOCK_CHILDREN_CONTAINER_PADDING_LEFT } from '@blocksuite/affine-shared/consts';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
|
|
||||||
import { dividerBlockStyles } from './styles.js';
|
import { dividerBlockStyles } from './styles.js';
|
||||||
@@ -15,7 +16,7 @@ export class DividerBlockComponent extends CaptionedBlockComponent<DividerBlockM
|
|||||||
|
|
||||||
this.handleEvent('click', () => {
|
this.handleEvent('click', () => {
|
||||||
this.host.selection.setGroup('note', [
|
this.host.selection.setGroup('note', [
|
||||||
this.host.selection.create('block', {
|
this.host.selection.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import type { EdgelessTextBlockModel } from '@blocksuite/affine-model';
|
|||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent } from '@blocksuite/block-std';
|
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 { Bound } from '@blocksuite/global/utils';
|
||||||
import { css, html } from 'lit';
|
import { css, html } from 'lit';
|
||||||
import { query, state } from 'lit/decorators.js';
|
import { query, state } from 'lit/decorators.js';
|
||||||
@@ -88,7 +92,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
const command = this.std.command;
|
const command = this.std.command;
|
||||||
const blockSelections = this.model.children.map(child =>
|
const blockSelections = this.model.children.map(child =>
|
||||||
this.std.selection.create('block', {
|
this.std.selection.create(BlockSelection, {
|
||||||
blockId: child.id,
|
blockId: child.id,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -178,7 +182,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
|
|||||||
|
|
||||||
if (newParagraphId) {
|
if (newParagraphId) {
|
||||||
std.selection.setGroup('note', [
|
std.selection.setGroup('note', [
|
||||||
std.selection.create('text', {
|
std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: newParagraphId,
|
blockId: newParagraphId,
|
||||||
index: 0,
|
index: 0,
|
||||||
@@ -310,7 +314,7 @@ export class EdgelessTextBlockComponent extends GfxBlockComponent<EdgelessTextBl
|
|||||||
const last = paragraphOrLists.at(-1);
|
const last = paragraphOrLists.at(-1);
|
||||||
if (last) {
|
if (last) {
|
||||||
this.host.selection.setGroup('note', [
|
this.host.selection.setGroup('note', [
|
||||||
this.host.selection.create('text', {
|
this.host.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: last.blockId,
|
blockId: last.blockId,
|
||||||
index: last.model.text?.length ?? 0,
|
index: last.model.text?.length ?? 0,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
EMBED_CARD_WIDTH,
|
EMBED_CARD_WIDTH,
|
||||||
} from '@blocksuite/affine-shared/consts';
|
} from '@blocksuite/affine-shared/consts';
|
||||||
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
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 { GfxCompatibleProps } from '@blocksuite/block-std/gfx';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
import type { TemplateResult } from 'lit';
|
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`
|
return html`
|
||||||
<div
|
<div
|
||||||
draggable="${this.blockDraggable ? 'true' : 'false'}"
|
draggable="${this.blockDraggable ? 'true' : 'false'}"
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ import {
|
|||||||
EMBED_CARD_HEIGHT,
|
EMBED_CARD_HEIGHT,
|
||||||
EMBED_CARD_WIDTH,
|
EMBED_CARD_WIDTH,
|
||||||
} from '@blocksuite/affine-shared/consts';
|
} 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 { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||||
import { Bound, Vec } from '@blocksuite/global/utils';
|
import { Bound, Vec } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
@@ -26,9 +31,9 @@ export function insertEmbedCard(
|
|||||||
const selectionManager = host.selection;
|
const selectionManager = host.selection;
|
||||||
|
|
||||||
let blockId: string | undefined;
|
let blockId: string | undefined;
|
||||||
const textSelection = selectionManager.find('text');
|
const textSelection = selectionManager.find(TextSelection);
|
||||||
const blockSelection = selectionManager.find('block');
|
const blockSelection = selectionManager.find(BlockSelection);
|
||||||
const surfaceSelection = selectionManager.find('surface');
|
const surfaceSelection = selectionManager.find(SurfaceSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
blockId = textSelection.blockId;
|
blockId = textSelection.blockId;
|
||||||
} else if (blockSelection) {
|
} else if (blockSelection) {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
EmbedFigmaModel,
|
EmbedFigmaModel,
|
||||||
EmbedFigmaStyles,
|
EmbedFigmaStyles,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
|
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { state } from 'lit/decorators.js';
|
import { state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -41,7 +42,7 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -77,7 +78,8 @@ export class EmbedFigmaBlockComponent extends EmbedBlockComponent<
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.std.selection.slots.changed.on(() => {
|
this.std.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
|
|
||||||
this._showOverlay =
|
this._showOverlay =
|
||||||
this._isResizing || this._isDragging || !this._isSelected;
|
this._isResizing || this._isDragging || !this._isSelected;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
EmbedGithubStyles,
|
EmbedGithubStyles,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
|
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
import { property, state } from 'lit/decorators.js';
|
import { property, state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -61,7 +62,7 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -111,7 +112,8 @@ export class EmbedGithubBlockComponent extends EmbedBlockComponent<
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.selection.slots.changed.on(() => {
|
this.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { EmbedHtmlModel, EmbedHtmlStyles } from '@blocksuite/affine-model';
|
import type { EmbedHtmlModel, EmbedHtmlStyles } from '@blocksuite/affine-model';
|
||||||
|
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { query, state } from 'lit/decorators.js';
|
import { query, state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -35,7 +36,7 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -54,7 +55,8 @@ export class EmbedHtmlBlockComponent extends EmbedBlockComponent<EmbedHtmlModel>
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.std.selection.slots.changed.on(() => {
|
this.std.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
|
|
||||||
this._showOverlay =
|
this._showOverlay =
|
||||||
this._isResizing || this._isDragging || !this._isSelected;
|
this._isResizing || this._isDragging || !this._isSelected;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import {
|
|||||||
matchFlavours,
|
matchFlavours,
|
||||||
referenceToNode,
|
referenceToNode,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { Bound, throttle } from '@blocksuite/global/utils';
|
import { Bound, throttle } from '@blocksuite/global/utils';
|
||||||
import { Text } from '@blocksuite/store';
|
import { Text } from '@blocksuite/store';
|
||||||
import { computed } from '@preact/signals-core';
|
import { computed } from '@preact/signals-core';
|
||||||
@@ -107,7 +108,7 @@ export class EmbedLinkedDocBlockComponent extends EmbedBlockComponent<EmbedLinke
|
|||||||
|
|
||||||
private readonly _selectBlock = () => {
|
private readonly _selectBlock = () => {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { OpenIcon } from '@blocksuite/affine-components/icons';
|
import { OpenIcon } from '@blocksuite/affine-components/icons';
|
||||||
import type { EmbedLoomModel, EmbedLoomStyles } from '@blocksuite/affine-model';
|
import type { EmbedLoomModel, EmbedLoomStyles } from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
|
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { property, state } from 'lit/decorators.js';
|
import { property, state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -46,7 +47,7 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -93,7 +94,8 @@ export class EmbedLoomBlockComponent extends EmbedBlockComponent<
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.std.selection.slots.changed.on(() => {
|
this.std.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
|
|
||||||
this._showOverlay =
|
this._showOverlay =
|
||||||
this._isResizing || this._isDragging || !this._isSelected;
|
this._isResizing || this._isDragging || !this._isSelected;
|
||||||
|
|||||||
+6
-2
@@ -1,5 +1,9 @@
|
|||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
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 { throttle, WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
import { property, queryAsync } from 'lit/decorators.js';
|
import { property, queryAsync } from 'lit/decorators.js';
|
||||||
@@ -64,7 +68,7 @@ export class EmbedSyncedDocCard extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.block.blockId,
|
blockId: this.block.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
|
|||||||
+2
-2
@@ -8,7 +8,7 @@ import {
|
|||||||
ThemeExtensionIdentifier,
|
ThemeExtensionIdentifier,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} 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 { assertExists, Bound } from '@blocksuite/global/utils';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { choose } from 'lit/directives/choose.js';
|
import { choose } from 'lit/directives/choose.js';
|
||||||
@@ -52,7 +52,7 @@ export class EmbedEdgelessSyncedDocBlockComponent extends toEdgelessEmbedBlock(
|
|||||||
}
|
}
|
||||||
const theme = this.isPageMode ? appTheme : edgelessTheme;
|
const theme = this.isPageMode ? appTheme : edgelessTheme;
|
||||||
|
|
||||||
const isSelected = !!this.selected?.is('block');
|
const isSelected = !!this.selected?.is(BlockSelection);
|
||||||
const scale = this.model.scale ?? 1;
|
const scale = this.model.scale ?? 1;
|
||||||
|
|
||||||
this.dataset.nestedEditor = '';
|
this.dataset.nestedEditor = '';
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
SpecProvider,
|
SpecProvider,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
|
BlockSelection,
|
||||||
BlockServiceWatcher,
|
BlockServiceWatcher,
|
||||||
BlockStdScope,
|
BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
@@ -164,7 +165,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
edgelessTheme = themeExtension.getEdgelessTheme(this.syncedDoc.id).value;
|
edgelessTheme = themeExtension.getEdgelessTheme(this.syncedDoc.id).value;
|
||||||
}
|
}
|
||||||
const theme = isPageMode ? appTheme : edgelessTheme;
|
const theme = isPageMode ? appTheme : edgelessTheme;
|
||||||
const isSelected = !!this.selected?.is('block');
|
const isSelected = !!this.selected?.is(BlockSelection);
|
||||||
|
|
||||||
this.dataset.nestedEditor = '';
|
this.dataset.nestedEditor = '';
|
||||||
|
|
||||||
@@ -428,7 +429,7 @@ export class EmbedSyncedDocBlockComponent extends EmbedBlockComponent<EmbedSynce
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
EmbedYoutubeStyles,
|
EmbedYoutubeStyles,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||||
|
import { BlockSelection, SurfaceSelection } from '@blocksuite/block-std';
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
import { property, state } from 'lit/decorators.js';
|
import { property, state } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
@@ -49,7 +50,7 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
|||||||
|
|
||||||
private _selectBlock() {
|
private _selectBlock() {
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
@@ -96,7 +97,8 @@ export class EmbedYoutubeBlockComponent extends EmbedBlockComponent<
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this.std.selection.slots.changed.on(() => {
|
this.std.selection.slots.changed.on(() => {
|
||||||
this._isSelected =
|
this._isSelected =
|
||||||
!!this.selected?.is('block') || !!this.selected?.is('surface');
|
!!this.selected?.is(BlockSelection) ||
|
||||||
|
!!this.selected?.is(SurfaceSelection);
|
||||||
|
|
||||||
this._showOverlay =
|
this._showOverlay =
|
||||||
this._isResizing || this._isDragging || !this._isSelected;
|
this._isResizing || this._isDragging || !this._isSelected;
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
import { ImageSelection } from '@blocksuite/affine-shared/selection';
|
||||||
import type { BaseSelection, UIEventStateContext } from '@blocksuite/block-std';
|
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 { WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { css, html, type PropertyValues } from 'lit';
|
import { css, html, type PropertyValues } from 'lit';
|
||||||
import { property, query, state } from 'lit/decorators.js';
|
import { property, query, state } from 'lit/decorators.js';
|
||||||
@@ -66,9 +71,9 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
selection.update(selList =>
|
selection.update(selList =>
|
||||||
selList
|
selList
|
||||||
.filter<BaseSelection>(sel => !sel.is('image'))
|
.filter<BaseSelection>(sel => !sel.is(ImageSelection))
|
||||||
.concat(
|
.concat(
|
||||||
selection.create('text', {
|
selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId,
|
blockId,
|
||||||
index: 0,
|
index: 0,
|
||||||
@@ -86,9 +91,11 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
|
|||||||
selection.update(selList => {
|
selection.update(selList => {
|
||||||
return selList.map(sel => {
|
return selList.map(sel => {
|
||||||
const current =
|
const current =
|
||||||
sel.is('image') && sel.blockId === this.block.blockId;
|
sel.is(ImageSelection) && sel.blockId === this.block.blockId;
|
||||||
if (current) {
|
if (current) {
|
||||||
return selection.create('block', { blockId: this.block.blockId });
|
return selection.create(BlockSelection, {
|
||||||
|
blockId: this.block.blockId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return sel;
|
return sel;
|
||||||
});
|
});
|
||||||
@@ -119,7 +126,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
|
|||||||
const std = this._host.std;
|
const std = this._host.std;
|
||||||
|
|
||||||
// If the selection is not image selection, we should not handle it.
|
// If the selection is not image selection, we should not handle it.
|
||||||
if (!std.selection.find('image')) {
|
if (!std.selection.find(ImageSelection)) {
|
||||||
return false;
|
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 the selection is not image selection, we should not handle it.
|
||||||
|
|
||||||
if (!std.selection.find('image')) {
|
if (!std.selection.find(ImageSelection)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,7 +185,7 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
|
|||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
selection.slots.changed.on(selList => {
|
selection.slots.changed.on(selList => {
|
||||||
this._isSelected = selList.some(
|
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 => {
|
selection.update(selList => {
|
||||||
return selList
|
return selList
|
||||||
.filter(sel => !['block', 'image', 'text'].includes(sel.type))
|
.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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -213,7 +222,8 @@ export class ImageBlockPageComponent extends WithDisposable(ShadowlessElement) {
|
|||||||
|
|
||||||
selection.update(selList =>
|
selection.update(selList =>
|
||||||
selList.filter(
|
selList.filter(
|
||||||
sel => !(sel.is('image') && sel.blockId === this.block.blockId)
|
sel =>
|
||||||
|
!(sel.is(ImageSelection) && sel.blockId === this.block.blockId)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||||
import { Peekable } from '@blocksuite/affine-components/peek';
|
import { Peekable } from '@blocksuite/affine-components/peek';
|
||||||
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { IS_MOBILE } from '@blocksuite/global/env';
|
import { IS_MOBILE } from '@blocksuite/global/env';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { property, query, state } from 'lit/decorators.js';
|
import { property, query, state } from 'lit/decorators.js';
|
||||||
@@ -51,7 +52,7 @@ export class ImageBlockComponent extends CaptionedBlockComponent<
|
|||||||
|
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const selectionManager = this.host.selection;
|
const selectionManager = this.host.selection;
|
||||||
const blockSelection = selectionManager.create('block', {
|
const blockSelection = selectionManager.create(BlockSelection, {
|
||||||
blockId: this.blockId,
|
blockId: this.blockId,
|
||||||
});
|
});
|
||||||
selectionManager.setGroup('note', [blockSelection]);
|
selectionManager.setGroup('note', [blockSelection]);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||||
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
||||||
import type { LatexBlockModel } from '@blocksuite/affine-model';
|
import type { LatexBlockModel } from '@blocksuite/affine-model';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import type { Placement } from '@floating-ui/dom';
|
import type { Placement } from '@floating-ui/dom';
|
||||||
import { effect } from '@preact/signals-core';
|
import { effect } from '@preact/signals-core';
|
||||||
import katex from 'katex';
|
import katex from 'katex';
|
||||||
@@ -19,7 +20,7 @@ export class LatexBlockComponent extends CaptionedBlockComponent<LatexBlockModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isBlockSelected() {
|
get isBlockSelected() {
|
||||||
const blockSelection = this.selection.filter('block');
|
const blockSelection = this.selection.filter(BlockSelection);
|
||||||
return blockSelection.some(
|
return blockSelection.some(
|
||||||
selection => selection.blockId === this.model.id
|
selection => selection.blockId === this.model.id
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import type { IndentContext } from '@blocksuite/affine-shared/types';
|
import type { IndentContext } from '@blocksuite/affine-shared/types';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
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';
|
import { correctNumberedListsOrderToPrev } from './utils.js';
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ export const canDedentListCommand: Command<
|
|||||||
const { std } = ctx;
|
const { std } = ctx;
|
||||||
const { selection, doc } = std;
|
const { selection, doc } = std;
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
/**
|
/**
|
||||||
* Do nothing if the selection:
|
* Do nothing if the selection:
|
||||||
* - is not a text selection
|
* - is not a text selection
|
||||||
@@ -148,7 +148,7 @@ export const dedentListCommand: Command<'indentContext'> = (ctx, next) => {
|
|||||||
doc.moveBlocks([model], grandParent, parent, false);
|
doc.moveBlocks([model], grandParent, parent, false);
|
||||||
correctNumberedListsOrderToPrev(doc, model);
|
correctNumberedListsOrderToPrev(doc, model);
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
getNearestHeadingBefore,
|
getNearestHeadingBefore,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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';
|
import { correctNumberedListsOrderToPrev } from './utils.js';
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export const canIndentListCommand: Command<
|
|||||||
const { std } = ctx;
|
const { std } = ctx;
|
||||||
const { selection, doc } = std;
|
const { selection, doc } = std;
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
/**
|
/**
|
||||||
* Do nothing if the selection:
|
* Do nothing if the selection:
|
||||||
* - is not a text 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) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ import {
|
|||||||
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
import { DocModeProvider } from '@blocksuite/affine-shared/services';
|
||||||
import { getViewportElement } from '@blocksuite/affine-shared/utils';
|
import { getViewportElement } from '@blocksuite/affine-shared/utils';
|
||||||
import type { BaseSelection, BlockComponent } from '@blocksuite/block-std';
|
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 type { InlineRangeProvider } from '@blocksuite/inline';
|
||||||
import { effect } from '@preact/signals-core';
|
import { effect } from '@preact/signals-core';
|
||||||
import { html, nothing, type TemplateResult } from 'lit';
|
import { html, nothing, type TemplateResult } from 'lit';
|
||||||
@@ -95,8 +99,10 @@ export class ListBlockComponent extends CaptionedBlockComponent<ListBlockModel>
|
|||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
selection.update(selList => {
|
selection.update(selList => {
|
||||||
return selList
|
return selList
|
||||||
.filter<BaseSelection>(sel => !sel.is('text') && !sel.is('block'))
|
.filter<BaseSelection>(
|
||||||
.concat(selection.create('block', { blockId: this.blockId }));
|
sel => !sel.is(TextSelection) && !sel.is(BlockSelection)
|
||||||
|
)
|
||||||
|
.concat(selection.create(BlockSelection, { blockId: this.blockId }));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
textKeymap,
|
textKeymap,
|
||||||
} from '@blocksuite/affine-components/rich-text';
|
} from '@blocksuite/affine-components/rich-text';
|
||||||
import { ListBlockSchema } from '@blocksuite/affine-model';
|
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 { IS_MAC } from '@blocksuite/global/env';
|
||||||
|
|
||||||
import { forwardDelete } from './utils/forward-delete.js';
|
import { forwardDelete } from './utils/forward-delete.js';
|
||||||
@@ -12,7 +12,7 @@ export const ListKeymapExtension = KeymapExtension(
|
|||||||
std => {
|
std => {
|
||||||
return {
|
return {
|
||||||
Enter: ctx => {
|
Enter: ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return false;
|
if (!text) return false;
|
||||||
|
|
||||||
ctx.get('keyboardState').raw.preventDefault();
|
ctx.get('keyboardState').raw.preventDefault();
|
||||||
@@ -23,7 +23,7 @@ export const ListKeymapExtension = KeymapExtension(
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
'Mod-Enter': ctx => {
|
'Mod-Enter': ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return false;
|
if (!text) return false;
|
||||||
|
|
||||||
ctx.get('keyboardState').raw.preventDefault();
|
ctx.get('keyboardState').raw.preventDefault();
|
||||||
@@ -40,7 +40,7 @@ export const ListKeymapExtension = KeymapExtension(
|
|||||||
if (selectedModels?.length !== 1) {
|
if (selectedModels?.length !== 1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return false;
|
if (!text) return false;
|
||||||
|
|
||||||
ctx.get('keyboardState').raw.preventDefault();
|
ctx.get('keyboardState').raw.preventDefault();
|
||||||
@@ -61,7 +61,7 @@ export const ListKeymapExtension = KeymapExtension(
|
|||||||
if (selectedModels?.length !== 1) {
|
if (selectedModels?.length !== 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return false;
|
if (!text) return false;
|
||||||
|
|
||||||
ctx.get('keyboardState').raw.preventDefault();
|
ctx.get('keyboardState').raw.preventDefault();
|
||||||
@@ -76,7 +76,7 @@ export const ListKeymapExtension = KeymapExtension(
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
Backspace: ctx => {
|
Backspace: ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return false;
|
if (!text) return false;
|
||||||
const isCollapsed = text.isCollapsed();
|
const isCollapsed = text.isCollapsed();
|
||||||
const isStart = isCollapsed && text.from.index === 0;
|
const isStart = isCollapsed && text.from.index === 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
getNextContentBlock,
|
getNextContentBlock,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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';
|
import type { Text } from '@blocksuite/store';
|
||||||
|
|
||||||
// When deleting at line end of a list block,
|
// When deleting at line end of a list block,
|
||||||
@@ -20,7 +20,7 @@ import type { Text } from '@blocksuite/store';
|
|||||||
- Line9
|
- Line9
|
||||||
*/
|
*/
|
||||||
export function forwardDelete(std: BlockStdScope): true | undefined {
|
export function forwardDelete(std: BlockStdScope): true | undefined {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const isCollapsed = text.isCollapsed();
|
const isCollapsed = text.isCollapsed();
|
||||||
const doc = std.doc;
|
const doc = std.doc;
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import {
|
|||||||
mergeToCodeModel,
|
mergeToCodeModel,
|
||||||
transformModel,
|
transformModel,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
type UpdateBlockConfig = {
|
type UpdateBlockConfig = {
|
||||||
@@ -108,11 +112,11 @@ export const updateBlockType: Command<
|
|||||||
onModelTextUpdated(host, model)
|
onModelTextUpdated(host, model)
|
||||||
);
|
);
|
||||||
const selectionManager = host.selection;
|
const selectionManager = host.selection;
|
||||||
const textSelection = selectionManager.find('text');
|
const textSelection = selectionManager.find(TextSelection);
|
||||||
if (!textSelection) {
|
if (!textSelection) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const newTextSelection = selectionManager.create('text', {
|
const newTextSelection = selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: firstNewModel.id,
|
blockId: firstNewModel.id,
|
||||||
index: textSelection.from.index,
|
index: textSelection.from.index,
|
||||||
@@ -143,13 +147,13 @@ export const updateBlockType: Command<
|
|||||||
|
|
||||||
const selectionManager = host.selection;
|
const selectionManager = host.selection;
|
||||||
|
|
||||||
const blockSelections = selectionManager.filter('block');
|
const blockSelections = selectionManager.filter(BlockSelection);
|
||||||
if (blockSelections.length === 0) {
|
if (blockSelections.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const selections = updatedBlocks.map(model => {
|
const selections = updatedBlocks.map(model => {
|
||||||
return selectionManager.create('block', {
|
return selectionManager.create(BlockSelection, {
|
||||||
blockId: model.id,
|
blockId: model.id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
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<
|
export const dedentBlocksToRoot: Command<
|
||||||
never,
|
never,
|
||||||
@@ -13,7 +13,7 @@ export const dedentBlocksToRoot: Command<
|
|||||||
const { std, stopCapture = true } = ctx;
|
const { std, stopCapture = true } = ctx;
|
||||||
const { doc } = std;
|
const { doc } = std;
|
||||||
if (!blockIds || !blockIds.length) {
|
if (!blockIds || !blockIds.length) {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (text) {
|
if (text) {
|
||||||
// If the text selection is not at the beginning of the block, use default behavior
|
// If the text selection is not at the beginning of the block, use default behavior
|
||||||
if (text.from.index !== 0) return;
|
if (text.from.index !== 0) return;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
calculateCollapsedSiblings,
|
calculateCollapsedSiblings,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { Command } from '@blocksuite/block-std';
|
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const dedentBlocks: Command<
|
export const dedentBlocks: Command<
|
||||||
never,
|
never,
|
||||||
@@ -75,7 +75,7 @@ export const dedentBlocks: Command<
|
|||||||
std.command.exec('dedentBlock', { blockId: id, stopCapture: false });
|
std.command.exec('dedentBlock', { blockId: id, stopCapture: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -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) => {
|
export const focusBlockEnd: Command<'focusBlock'> = (ctx, next) => {
|
||||||
const { focusBlock, std } = ctx;
|
const { focusBlock, std } = ctx;
|
||||||
@@ -7,7 +7,7 @@ export const focusBlockEnd: Command<'focusBlock'> = (ctx, next) => {
|
|||||||
const { selection } = std;
|
const { selection } = std;
|
||||||
|
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('text', {
|
selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: focusBlock.blockId,
|
blockId: focusBlock.blockId,
|
||||||
index: focusBlock.model.text.length,
|
index: focusBlock.model.text.length,
|
||||||
|
|||||||
@@ -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) => {
|
export const focusBlockStart: Command<'focusBlock'> = (ctx, next) => {
|
||||||
const { focusBlock, std } = ctx;
|
const { focusBlock, std } = ctx;
|
||||||
@@ -7,7 +7,7 @@ export const focusBlockStart: Command<'focusBlock'> = (ctx, next) => {
|
|||||||
const { selection } = std;
|
const { selection } = std;
|
||||||
|
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('text', {
|
selection.create(TextSelection, {
|
||||||
from: { blockId: focusBlock.blockId, index: 0, length: 0 },
|
from: { blockId: focusBlock.blockId, index: 0, length: 0 },
|
||||||
to: null,
|
to: null,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
getNearestHeadingBefore,
|
getNearestHeadingBefore,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { Command } from '@blocksuite/block-std';
|
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const indentBlocks: Command<
|
export const indentBlocks: Command<
|
||||||
never,
|
never,
|
||||||
@@ -117,7 +117,7 @@ export const indentBlocks: Command<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -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) => {
|
export const selectBlock: Command<'focusBlock'> = (ctx, next) => {
|
||||||
const { focusBlock, std } = ctx;
|
const { focusBlock, std } = ctx;
|
||||||
@@ -9,7 +9,7 @@ export const selectBlock: Command<'focusBlock'> = (ctx, next) => {
|
|||||||
const { selection } = std;
|
const { selection } = std;
|
||||||
|
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('block', { blockId: focusBlock.blockId }),
|
selection.create(BlockSelection, { blockId: focusBlock.blockId }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Command } from '@blocksuite/block-std';
|
import { BlockSelection, type Command } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const selectBlocksBetween: Command<
|
export const selectBlocksBetween: Command<
|
||||||
'focusBlock' | 'anchorBlock',
|
'focusBlock' | 'anchorBlock',
|
||||||
@@ -14,7 +14,7 @@ export const selectBlocksBetween: Command<
|
|||||||
// In same block
|
// In same block
|
||||||
if (anchorBlock.blockId === focusBlock.blockId) {
|
if (anchorBlock.blockId === focusBlock.blockId) {
|
||||||
const blockId = focusBlock.blockId;
|
const blockId = focusBlock.blockId;
|
||||||
selection.setGroup('note', [selection.create('block', { blockId })]);
|
selection.setGroup('note', [selection.create(BlockSelection, { blockId })]);
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ export const selectBlocksBetween: Command<
|
|||||||
if (selections.every(sel => sel.blockId !== focusBlock.blockId)) {
|
if (selections.every(sel => sel.blockId !== focusBlock.blockId)) {
|
||||||
if (tail) {
|
if (tail) {
|
||||||
selections.push(
|
selections.push(
|
||||||
selection.create('block', { blockId: focusBlock.blockId })
|
selection.create(BlockSelection, { blockId: focusBlock.blockId })
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
selections.unshift(
|
selections.unshift(
|
||||||
selection.create('block', { blockId: focusBlock.blockId })
|
selection.create(BlockSelection, { blockId: focusBlock.blockId })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
const getSelection = (std: BlockStdScope) => std.selection;
|
||||||
|
|
||||||
function getBlockSelectionBySide(std: BlockStdScope, tail: boolean) {
|
function getBlockSelectionBySide(std: BlockStdScope, tail: boolean) {
|
||||||
const selection = getSelection(std);
|
const selection = getSelection(std);
|
||||||
const selections = selection.filter('block');
|
const selections = selection.filter(BlockSelection);
|
||||||
const sel = selections.at(tail ? -1 : 0) as BlockSelection | undefined;
|
const sel = selections.at(tail ? -1 : 0) as BlockSelection | undefined;
|
||||||
return sel ?? null;
|
return sel ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTextSelection(std: BlockStdScope) {
|
function getTextSelection(std: BlockStdScope) {
|
||||||
const selection = getSelection(std);
|
const selection = getSelection(std);
|
||||||
return selection.find('text');
|
return selection.find(TextSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pathToBlock = (std: BlockStdScope, blockId: string) =>
|
const pathToBlock = (std: BlockStdScope, blockId: string) =>
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ import {
|
|||||||
stopPropagation,
|
stopPropagation,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
||||||
import { ShadowlessElement, toGfxBlockComponent } from '@blocksuite/block-std';
|
import {
|
||||||
|
ShadowlessElement,
|
||||||
|
TextSelection,
|
||||||
|
toGfxBlockComponent,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
almostEqual,
|
almostEqual,
|
||||||
Bound,
|
Bound,
|
||||||
@@ -305,7 +309,7 @@ export class EdgelessNoteBlockComponent extends toGfxBlockComponent(
|
|||||||
this.updateComplete
|
this.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.std.selection.setGroup('note', [
|
this.std.selection.setGroup('note', [
|
||||||
this.std.selection.create('text', {
|
this.std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: pId,
|
blockId: pId,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
|||||||
import {
|
import {
|
||||||
type BaseSelection,
|
type BaseSelection,
|
||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
type BlockSelection,
|
BlockSelection,
|
||||||
BlockService,
|
BlockService,
|
||||||
type BlockStdScope,
|
type BlockStdScope,
|
||||||
|
TextSelection,
|
||||||
type UIEventHandler,
|
type UIEventHandler,
|
||||||
type UIEventStateContext,
|
type UIEventStateContext,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
@@ -95,7 +96,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
const [codeModel] = newModels;
|
const [codeModel] = newModels;
|
||||||
onModelElementUpdated(ctx.std, codeModel, codeElement => {
|
onModelElementUpdated(ctx.std, codeModel, codeElement => {
|
||||||
this._std.selection.setGroup('note', [
|
this._std.selection.setGroup('note', [
|
||||||
this._std.selection.create('text', {
|
this._std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: codeElement.blockId,
|
blockId: codeElement.blockId,
|
||||||
index: 0,
|
index: 0,
|
||||||
@@ -439,7 +440,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
|
|
||||||
const blockId = doc.addBlock('affine:paragraph', {}, parent, index + 1);
|
const blockId = doc.addBlock('affine:paragraph', {}, parent, index + 1);
|
||||||
|
|
||||||
const sel = selection.create('text', {
|
const sel = selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId,
|
blockId,
|
||||||
index: 0,
|
index: 0,
|
||||||
@@ -469,7 +470,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.std.selection.update(selList => {
|
ctx.std.selection.update(selList => {
|
||||||
return selList.filter(sel => !sel.is('block'));
|
return selList.filter(sel => !sel.is(BlockSelection));
|
||||||
});
|
});
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
@@ -481,7 +482,7 @@ export class NoteBlockService extends BlockService {
|
|||||||
|
|
||||||
private readonly _onSelectAll: UIEventHandler = ctx => {
|
private readonly _onSelectAll: UIEventHandler = ctx => {
|
||||||
const selection = this._std.selection;
|
const selection = this._std.selection;
|
||||||
const block = selection.find('block');
|
const block = selection.find(BlockSelection);
|
||||||
if (!block) {
|
if (!block) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -492,13 +493,13 @@ export class NoteBlockService extends BlockService {
|
|||||||
ctx.get('defaultState').event.preventDefault();
|
ctx.get('defaultState').event.preventDefault();
|
||||||
const children = note.children;
|
const children = note.children;
|
||||||
const blocks: BlockSelection[] = children.map(child => {
|
const blocks: BlockSelection[] = children.map(child => {
|
||||||
return selection.create('block', {
|
return selection.create(BlockSelection, {
|
||||||
blockId: child.id,
|
blockId: child.id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
selection.update(selList => {
|
selection.update(selList => {
|
||||||
return selList
|
return selList
|
||||||
.filter<BaseSelection>(sel => !sel.is('block'))
|
.filter<BaseSelection>(sel => !sel.is(BlockSelection))
|
||||||
.concat(blocks);
|
.concat(blocks);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { focusTextModel } from '@blocksuite/affine-components/rich-text';
|
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.
|
* Add a paragraph next to the current block.
|
||||||
@@ -17,7 +17,7 @@ export const addParagraphCommand: Command<
|
|||||||
|
|
||||||
let blockId = ctx.blockId;
|
let blockId = ctx.blockId;
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
blockId = text?.blockId;
|
blockId = text?.blockId;
|
||||||
}
|
}
|
||||||
if (!blockId) return;
|
if (!blockId) return;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
calculateCollapsedSiblings,
|
calculateCollapsedSiblings,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { Command } from '@blocksuite/block-std';
|
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const canDedentParagraphCommand: Command<
|
export const canDedentParagraphCommand: Command<
|
||||||
never,
|
never,
|
||||||
@@ -13,7 +13,7 @@ export const canDedentParagraphCommand: Command<
|
|||||||
let { blockId, inlineIndex } = ctx;
|
let { blockId, inlineIndex } = ctx;
|
||||||
const { std } = ctx;
|
const { std } = ctx;
|
||||||
const { selection, doc } = std;
|
const { selection, doc } = std;
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
|
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
/**
|
/**
|
||||||
@@ -97,7 +97,7 @@ export const dedentParagraphCommand: Command<'indentContext'> = (ctx, next) => {
|
|||||||
doc.moveBlocks([model], grandParent, parent, false);
|
doc.moveBlocks([model], grandParent, parent, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
getNearestHeadingBefore,
|
getNearestHeadingBefore,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { Command } from '@blocksuite/block-std';
|
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const canIndentParagraphCommand: Command<
|
export const canIndentParagraphCommand: Command<
|
||||||
never,
|
never,
|
||||||
@@ -18,7 +18,7 @@ export const canIndentParagraphCommand: Command<
|
|||||||
const { schema } = doc;
|
const { schema } = doc;
|
||||||
|
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
/**
|
/**
|
||||||
* Do nothing if the selection:
|
* Do nothing if the selection:
|
||||||
* - is not a text selection
|
* - is not a text selection
|
||||||
@@ -140,7 +140,7 @@ export const indentParagraphCommand: Command<'indentContext'> = (ctx, next) => {
|
|||||||
} as Partial<ListBlockModel>);
|
} as Partial<ListBlockModel>);
|
||||||
}
|
}
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
host.updateComplete
|
host.updateComplete
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
getInlineEditorByModel,
|
getInlineEditorByModel,
|
||||||
} from '@blocksuite/affine-components/rich-text';
|
} from '@blocksuite/affine-components/rich-text';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
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<
|
export const splitParagraphCommand: Command<
|
||||||
never,
|
never,
|
||||||
@@ -16,7 +16,7 @@ export const splitParagraphCommand: Command<
|
|||||||
const { doc, host, selection } = std;
|
const { doc, host, selection } = std;
|
||||||
let blockId = ctx.blockId;
|
let blockId = ctx.blockId;
|
||||||
if (!blockId) {
|
if (!blockId) {
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
blockId = text?.blockId;
|
blockId = text?.blockId;
|
||||||
}
|
}
|
||||||
if (!blockId) return;
|
if (!blockId) return;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
getViewportElement,
|
getViewportElement,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent } from '@blocksuite/block-std';
|
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 type { InlineRangeProvider } from '@blocksuite/inline';
|
||||||
import { effect, signal } from '@preact/signals-core';
|
import { effect, signal } from '@preact/signals-core';
|
||||||
import { html, nothing, type TemplateResult } from 'lit';
|
import { html, nothing, type TemplateResult } from 'lit';
|
||||||
@@ -119,7 +119,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
this._displayPlaceholder.value = false;
|
this._displayPlaceholder.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
const isCollapsed = textSelection?.isCollapsed() ?? false;
|
const isCollapsed = textSelection?.isCollapsed() ?? false;
|
||||||
if (!this.selected || !isCollapsed) {
|
if (!this.selected || !isCollapsed) {
|
||||||
this._displayPlaceholder.value = false;
|
this._displayPlaceholder.value = false;
|
||||||
@@ -159,7 +159,7 @@ export class ParagraphBlockComponent extends CaptionedBlockComponent<
|
|||||||
// reset text selection when selected block is collapsed
|
// reset text selection when selected block is collapsed
|
||||||
if (this.model.type.startsWith('h') && collapsed) {
|
if (this.model.type.startsWith('h') && collapsed) {
|
||||||
const collapsedSiblings = this.collapsedSiblings;
|
const collapsedSiblings = this.collapsedSiblings;
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
textSelection &&
|
textSelection &&
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
calculateCollapsedSiblings,
|
calculateCollapsedSiblings,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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 { IS_MAC } from '@blocksuite/global/env';
|
||||||
|
|
||||||
import { forwardDelete } from './utils/forward-delete.js';
|
import { forwardDelete } from './utils/forward-delete.js';
|
||||||
@@ -19,7 +19,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
|
|||||||
std => {
|
std => {
|
||||||
return {
|
return {
|
||||||
Backspace: ctx => {
|
Backspace: ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const isCollapsed = text.isCollapsed();
|
const isCollapsed = text.isCollapsed();
|
||||||
const isStart = isCollapsed && text.from.index === 0;
|
const isStart = isCollapsed && text.from.index === 0;
|
||||||
@@ -52,7 +52,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
|
|||||||
},
|
},
|
||||||
'Mod-Enter': ctx => {
|
'Mod-Enter': ctx => {
|
||||||
const { doc } = std;
|
const { doc } = std;
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const model = doc.getBlock(text.from.blockId)?.model;
|
const model = doc.getBlock(text.from.blockId)?.model;
|
||||||
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;
|
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;
|
||||||
@@ -79,7 +79,7 @@ export const ParagraphKeymapExtension = KeymapExtension(
|
|||||||
},
|
},
|
||||||
Enter: ctx => {
|
Enter: ctx => {
|
||||||
const { doc } = std;
|
const { doc } = std;
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const model = doc.getBlock(text.from.blockId)?.model;
|
const model = doc.getBlock(text.from.blockId)?.model;
|
||||||
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;
|
if (!model || !matchFlavours(model, ['affine:paragraph'])) return;
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ import {
|
|||||||
getNextContentBlock,
|
getNextContentBlock,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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) {
|
export function forwardDelete(std: BlockStdScope) {
|
||||||
const { doc, host } = std;
|
const { doc, host } = std;
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const isCollapsed = text.isCollapsed();
|
const isCollapsed = text.isCollapsed();
|
||||||
const model = doc.getBlock(text.from.blockId)?.model;
|
const model = doc.getBlock(text.from.blockId)?.model;
|
||||||
@@ -30,7 +34,7 @@ export function forwardDelete(std: BlockStdScope) {
|
|||||||
|
|
||||||
if (matchFlavours(nextSibling, ignoreForwardDeleteFlavourList)) {
|
if (matchFlavours(nextSibling, ignoreForwardDeleteFlavourList)) {
|
||||||
std.selection.setGroup('note', [
|
std.selection.setGroup('note', [
|
||||||
std.selection.create('block', { blockId: nextSibling.id }),
|
std.selection.create(BlockSelection, { blockId: nextSibling.id }),
|
||||||
]);
|
]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -61,7 +65,7 @@ export function forwardDelete(std: BlockStdScope) {
|
|||||||
|
|
||||||
if (nextBlock) {
|
if (nextBlock) {
|
||||||
std.selection.setGroup('note', [
|
std.selection.setGroup('note', [
|
||||||
std.selection.create('block', { blockId: nextBlock.id }),
|
std.selection.create(BlockSelection, { blockId: nextBlock.id }),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
getPrevContentBlock,
|
getPrevContentBlock,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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';
|
import type { BlockModel, Text } from '@blocksuite/store';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -72,7 +72,7 @@ export function mergeWithPrev(editorHost: EditorHost, model: BlockModel) {
|
|||||||
...EMBED_BLOCK_FLAVOUR_LIST,
|
...EMBED_BLOCK_FLAVOUR_LIST,
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
const selection = editorHost.selection.create('block', {
|
const selection = editorHost.selection.create(BlockSelection, {
|
||||||
blockId: prevBlock.id,
|
blockId: prevBlock.id,
|
||||||
});
|
});
|
||||||
editorHost.selection.setGroup('note', [selection]);
|
editorHost.selection.setGroup('note', [selection]);
|
||||||
|
|||||||
@@ -28,10 +28,12 @@ import {
|
|||||||
import {
|
import {
|
||||||
type BaseSelection,
|
type BaseSelection,
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
BlockServiceWatcher,
|
BlockServiceWatcher,
|
||||||
BlockStdScope,
|
BlockStdScope,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
LifeCycleWatcher,
|
LifeCycleWatcher,
|
||||||
|
TextSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
GfxBlockElementModel,
|
GfxBlockElementModel,
|
||||||
@@ -267,7 +269,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
|
|
||||||
private _focusBlock() {
|
private _focusBlock() {
|
||||||
this.selection.update(() => {
|
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(() => {
|
requestConnectedFrame(() => {
|
||||||
selection.update(selList => {
|
selection.update(selList => {
|
||||||
return selList
|
return selList
|
||||||
.filter<BaseSelection>(sel => !sel.is('block'))
|
.filter<BaseSelection>(sel => !sel.is(BlockSelection))
|
||||||
.concat(
|
.concat(
|
||||||
selection.create('text', {
|
selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: model.id,
|
blockId: model.id,
|
||||||
index: 0,
|
index: 0,
|
||||||
@@ -415,7 +417,7 @@ export class SurfaceRefBlockComponent extends BlockComponent<SurfaceRefBlockMode
|
|||||||
this._disposables.add(
|
this._disposables.add(
|
||||||
selection.slots.changed.on(selList => {
|
selection.slots.changed.on(selList => {
|
||||||
this._focused = selList.some(
|
this._focused = selList.some(
|
||||||
sel => sel.blockId === this.blockId && sel.is('block')
|
sel => sel.blockId === this.blockId && sel.is(BlockSelection)
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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 { SignalWatcher } from '@blocksuite/global/utils';
|
||||||
import { css, LitElement, type PropertyValues } from 'lit';
|
import { css, LitElement, type PropertyValues } from 'lit';
|
||||||
import { property } from 'lit/decorators.js';
|
import { property } from 'lit/decorators.js';
|
||||||
@@ -55,7 +58,9 @@ export class BlockSelection extends SignalWatcher(LitElement) {
|
|||||||
protected override updated(_changedProperties: PropertyValues): void {
|
protected override updated(_changedProperties: PropertyValues): void {
|
||||||
super.updated(_changedProperties);
|
super.updated(_changedProperties);
|
||||||
if (this.block) {
|
if (this.block) {
|
||||||
this.style.display = this.block.selected?.is('block') ? 'block' : 'none';
|
this.style.display = this.block.selected?.is(StdBlockSelection)
|
||||||
|
? 'block'
|
||||||
|
: 'none';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import {
|
|||||||
getCurrentNativeRange,
|
getCurrentNativeRange,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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 type { InlineEditor, InlineRange } from '@blocksuite/inline';
|
||||||
import { BlockModel } from '@blocksuite/store';
|
import { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
@@ -81,7 +85,7 @@ export function selectTextModel(
|
|||||||
) {
|
) {
|
||||||
const { selection } = std;
|
const { selection } = std;
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('text', {
|
selection.create(TextSelection, {
|
||||||
from: { blockId: id, index, length },
|
from: { blockId: id, index, length },
|
||||||
to: null,
|
to: null,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
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';
|
import type { Text } from '@blocksuite/store';
|
||||||
|
|
||||||
export const deleteTextCommand: Command<
|
export const deleteTextCommand: Command<
|
||||||
@@ -36,7 +36,7 @@ export const deleteTextCommand: Command<
|
|||||||
if (!to) {
|
if (!to) {
|
||||||
fromText.delete(from.index, from.length);
|
fromText.delete(from.index, from.length);
|
||||||
ctx.std.selection.setGroup('note', [
|
ctx.std.selection.setGroup('note', [
|
||||||
ctx.std.selection.create('text', {
|
ctx.std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: from.blockId,
|
blockId: from.blockId,
|
||||||
index: from.index,
|
index: from.index,
|
||||||
@@ -69,7 +69,7 @@ export const deleteTextCommand: Command<
|
|||||||
});
|
});
|
||||||
|
|
||||||
ctx.std.selection.setGroup('note', [
|
ctx.std.selection.setGroup('note', [
|
||||||
ctx.std.selection.create('text', {
|
ctx.std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: from.blockId,
|
blockId: from.blockId,
|
||||||
index: from.index,
|
index: from.index,
|
||||||
|
|||||||
+8
-3
@@ -2,7 +2,12 @@ import type { ReferenceInfo } from '@blocksuite/affine-model';
|
|||||||
import { ParseDocUrlProvider } from '@blocksuite/affine-shared/services';
|
import { ParseDocUrlProvider } from '@blocksuite/affine-shared/services';
|
||||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||||
import type { BlockComponent } from '@blocksuite/block-std';
|
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 {
|
import {
|
||||||
type DeltaInsert,
|
type DeltaInsert,
|
||||||
INLINE_ROOT_ATTR,
|
INLINE_ROOT_ATTR,
|
||||||
@@ -69,12 +74,12 @@ export class AffineLink extends ShadowlessElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const selection = this.std?.selection;
|
const selection = this.std?.selection;
|
||||||
const textSelection = selection?.find('text');
|
const textSelection = selection?.find(TextSelection);
|
||||||
if (!!textSelection && !textSelection.isCollapsed()) {
|
if (!!textSelection && !textSelection.isCollapsed()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection?.filter('block');
|
const blockSelections = selection?.filter(BlockSelection);
|
||||||
if (blockSelections?.length) {
|
if (blockSelections?.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -15,6 +15,7 @@ import {
|
|||||||
BLOCK_ID_ATTR,
|
BLOCK_ID_ATTR,
|
||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
type BlockStdScope,
|
type BlockStdScope,
|
||||||
|
TextSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { WithDisposable } from '@blocksuite/global/utils';
|
import { WithDisposable } from '@blocksuite/global/utils';
|
||||||
import type { InlineRange } from '@blocksuite/inline/types';
|
import type { InlineRange } from '@blocksuite/inline/types';
|
||||||
@@ -438,7 +439,7 @@ export class LinkPopup extends WithDisposable(LitElement) {
|
|||||||
reference: null,
|
reference: null,
|
||||||
});
|
});
|
||||||
this.inlineEditor.setInlineRange(this.targetInlineRange);
|
this.inlineEditor.setInlineRange(this.targetInlineRange);
|
||||||
const textSelection = this.host?.selection.find('text');
|
const textSelection = this.host?.selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
this.std?.range.syncTextSelectionToRange(textSelection);
|
this.std?.range.syncTextSelectionToRange(textSelection);
|
||||||
@@ -452,7 +453,7 @@ export class LinkPopup extends WithDisposable(LitElement) {
|
|||||||
index: this.targetInlineRange.index,
|
index: this.targetInlineRange.index,
|
||||||
length: text.length,
|
length: text.length,
|
||||||
});
|
});
|
||||||
const textSelection = this.host?.selection.find('text');
|
const textSelection = this.host?.selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
this.std?.range.syncTextSelectionToRange(textSelection);
|
this.std?.range.syncTextSelectionToRange(textSelection);
|
||||||
|
|||||||
+4
-2
@@ -12,7 +12,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
BLOCK_ID_ATTR,
|
BLOCK_ID_ATTR,
|
||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
ShadowlessElement,
|
ShadowlessElement,
|
||||||
|
TextSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import { WithDisposable } from '@blocksuite/global/utils';
|
import { WithDisposable } from '@blocksuite/global/utils';
|
||||||
@@ -108,12 +110,12 @@ export class AffineReference extends WithDisposable(ShadowlessElement) {
|
|||||||
if (!selection) {
|
if (!selection) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (!!textSelection && !textSelection.isCollapsed()) {
|
if (!!textSelection && !textSelection.isCollapsed()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection.filter('block');
|
const blockSelections = selection.filter(BlockSelection);
|
||||||
if (blockSelections.length) {
|
if (blockSelections.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
import type { BlockStdScope, UIEventHandler } from '@blocksuite/block-std';
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
type BlockStdScope,
|
||||||
|
TextSelection,
|
||||||
|
type UIEventHandler,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
focusTextModel,
|
focusTextModel,
|
||||||
@@ -11,21 +16,21 @@ export const textCommonKeymap = (
|
|||||||
): Record<string, UIEventHandler> => {
|
): Record<string, UIEventHandler> => {
|
||||||
return {
|
return {
|
||||||
ArrowUp: () => {
|
ArrowUp: () => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const inline = getInlineEditorByModel(std.host, text.from.blockId);
|
const inline = getInlineEditorByModel(std.host, text.from.blockId);
|
||||||
if (!inline) return;
|
if (!inline) return;
|
||||||
return !inline.isFirstLine(inline.getInlineRange());
|
return !inline.isFirstLine(inline.getInlineRange());
|
||||||
},
|
},
|
||||||
ArrowDown: () => {
|
ArrowDown: () => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
const inline = getInlineEditorByModel(std.host, text.from.blockId);
|
const inline = getInlineEditorByModel(std.host, text.from.blockId);
|
||||||
if (!inline) return;
|
if (!inline) return;
|
||||||
return !inline.isLastLine(inline.getInlineRange());
|
return !inline.isLastLine(inline.getInlineRange());
|
||||||
},
|
},
|
||||||
Escape: ctx => {
|
Escape: ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
selectBlock(std, text.from.blockId);
|
selectBlock(std, text.from.blockId);
|
||||||
@@ -33,7 +38,7 @@ export const textCommonKeymap = (
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
'Mod-a': ctx => {
|
'Mod-a': ctx => {
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
||||||
const model = std.doc.getBlock(text.from.blockId)?.model;
|
const model = std.doc.getBlock(text.from.blockId)?.model;
|
||||||
@@ -53,7 +58,7 @@ export const textCommonKeymap = (
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
Enter: ctx => {
|
Enter: ctx => {
|
||||||
const blocks = std.selection.filter('block');
|
const blocks = std.selection.filter(BlockSelection);
|
||||||
const blockId = blocks.at(-1)?.blockId;
|
const blockId = blocks.at(-1)?.blockId;
|
||||||
|
|
||||||
if (!blockId) return;
|
if (!blockId) return;
|
||||||
@@ -68,5 +73,7 @@ export const textCommonKeymap = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
function selectBlock(std: BlockStdScope, blockId: string) {
|
function selectBlock(std: BlockStdScope, blockId: string) {
|
||||||
std.selection.setGroup('note', [std.selection.create('block', { blockId })]);
|
std.selection.setGroup('note', [
|
||||||
|
std.selection.create(BlockSelection, { blockId }),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ import {
|
|||||||
createDefaultDoc,
|
createDefaultDoc,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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 type { InlineEditor } from '@blocksuite/inline';
|
||||||
|
|
||||||
import { getInlineEditorByModel } from '../dom.js';
|
import { getInlineEditorByModel } from '../dom.js';
|
||||||
@@ -20,7 +24,7 @@ export const bracketKeymap = (
|
|||||||
const { doc, selection } = std;
|
const { doc, selection } = std;
|
||||||
if (doc.readonly) return;
|
if (doc.readonly) return;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
||||||
if (!model) return;
|
if (!model) return;
|
||||||
@@ -46,7 +50,7 @@ export const bracketKeymap = (
|
|||||||
const { doc, selection } = std;
|
const { doc, selection } = std;
|
||||||
if (doc.readonly) return;
|
if (doc.readonly) return;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
||||||
if (!model) return;
|
if (!model) return;
|
||||||
@@ -97,7 +101,7 @@ export const bracketKeymap = (
|
|||||||
const { doc, selection } = std;
|
const { doc, selection } = std;
|
||||||
if (doc.readonly) return;
|
if (doc.readonly) return;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (!textSelection || textSelection.isCollapsed()) return;
|
if (!textSelection || textSelection.isCollapsed()) return;
|
||||||
if (!textSelection.isInSameBlock()) return;
|
if (!textSelection.isInSameBlock()) return;
|
||||||
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
const model = doc.getBlock(textSelection.from.blockId)?.model;
|
||||||
|
|||||||
@@ -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';
|
import { textFormatConfigs } from '../format/index.js';
|
||||||
|
|
||||||
@@ -13,7 +17,7 @@ export const textFormatKeymap = (std: BlockStdScope) =>
|
|||||||
const { doc, selection } = std;
|
const { doc, selection } = std;
|
||||||
if (doc.readonly) return;
|
if (doc.readonly) return;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
config.action(std.host);
|
config.action(std.host);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import {
|
|||||||
isMarkdownPrefix,
|
isMarkdownPrefix,
|
||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} 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 { getInlineEditorByModel } from '../dom.js';
|
||||||
import { toDivider } from './divider.js';
|
import { toDivider } from './divider.js';
|
||||||
@@ -17,7 +17,7 @@ export function markdownInput(
|
|||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (!id) {
|
if (!id) {
|
||||||
const selection = std.selection;
|
const selection = std.selection;
|
||||||
const text = selection.find('text');
|
const text = selection.find(TextSelection);
|
||||||
id = text?.from.blockId;
|
id = text?.from.blockId;
|
||||||
}
|
}
|
||||||
if (!id) return;
|
if (!id) return;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type {
|
import {
|
||||||
BlockStdScope,
|
type BlockStdScope,
|
||||||
EditorHost,
|
type EditorHost,
|
||||||
TextRangePoint,
|
type TextRangePoint,
|
||||||
|
TextSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import type {
|
import type {
|
||||||
BlockSnapshot,
|
BlockSnapshot,
|
||||||
@@ -38,7 +39,7 @@ const sliceText = (slots: JobSlots, std: EditorHost['std']) => {
|
|||||||
const snapshot = payload.snapshot;
|
const snapshot = payload.snapshot;
|
||||||
|
|
||||||
const model = payload.model;
|
const model = payload.model;
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (text && text.from.blockId === model.id) {
|
if (text && text.from.blockId === model.id) {
|
||||||
handlePoint(text.from, snapshot, model);
|
handlePoint(text.from, snapshot, model);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import {
|
|||||||
import {
|
import {
|
||||||
BLOCK_ID_ATTR,
|
BLOCK_ID_ATTR,
|
||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
type EditorHost,
|
type EditorHost,
|
||||||
type TextRangePoint,
|
type TextRangePoint,
|
||||||
type TextSelection,
|
TextSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
@@ -25,6 +26,7 @@ import {
|
|||||||
import * as Y from 'yjs';
|
import * as Y from 'yjs';
|
||||||
|
|
||||||
import { REFERENCE_NODE } from '../../consts';
|
import { REFERENCE_NODE } from '../../consts';
|
||||||
|
import { ImageSelection } from '../../selection';
|
||||||
import {
|
import {
|
||||||
ParseDocUrlProvider,
|
ParseDocUrlProvider,
|
||||||
type ParseDocUrlService,
|
type ParseDocUrlService,
|
||||||
@@ -290,19 +292,19 @@ class PasteTr {
|
|||||||
}
|
}
|
||||||
if (!cursorModel.text) {
|
if (!cursorModel.text) {
|
||||||
if (matchFlavours(cursorModel, ['affine:image'])) {
|
if (matchFlavours(cursorModel, ['affine:image'])) {
|
||||||
const selection = this.std.selection.create('image', {
|
const selection = this.std.selection.create(ImageSelection, {
|
||||||
blockId: target.blockId,
|
blockId: target.blockId,
|
||||||
});
|
});
|
||||||
this.std.selection.setGroup('note', [selection]);
|
this.std.selection.setGroup('note', [selection]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const selection = this.std.selection.create('block', {
|
const selection = this.std.selection.create(BlockSelection, {
|
||||||
blockId: target.blockId,
|
blockId: target.blockId,
|
||||||
});
|
});
|
||||||
this.std.selection.setGroup('note', [selection]);
|
this.std.selection.setGroup('note', [selection]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const selection = this.std.selection.create('text', {
|
const selection = this.std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: target.blockId,
|
blockId: target.blockId,
|
||||||
index: cursorModel.text ? this.lastIndex : 0,
|
index: cursorModel.text ? this.lastIndex : 0,
|
||||||
@@ -511,7 +513,7 @@ export const pasteMiddleware = (std: EditorHost['std']): JobMiddleware => {
|
|||||||
const { snapshot } = payload;
|
const { snapshot } = payload;
|
||||||
flatNote(snapshot);
|
flatNote(snapshot);
|
||||||
|
|
||||||
const text = std.selection.find('text');
|
const text = std.selection.find(TextSelection);
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export const getSelectedBlocksCommand: Command<
|
|||||||
blockSelections?: BlockSelection[];
|
blockSelections?: BlockSelection[];
|
||||||
imageSelections?: ImageSelection[];
|
imageSelections?: ImageSelection[];
|
||||||
filter?: (el: BlockComponent) => boolean;
|
filter?: (el: BlockComponent) => boolean;
|
||||||
types?: Extract<BlockSuite.SelectionType, 'block' | 'text' | 'image'>[];
|
types?: Array<'image' | 'text' | 'block'>;
|
||||||
roles?: RoleType[];
|
roles?: RoleType[];
|
||||||
mode?: 'all' | 'flat' | 'highest';
|
mode?: 'all' | 'flat' | 'highest';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { Command } from '@blocksuite/block-std';
|
import { type Command, TextSelection } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const clearAndSelectFirstModelCommand: Command<'selectedModels'> = (
|
export const clearAndSelectFirstModelCommand: Command<'selectedModels'> = (
|
||||||
ctx,
|
ctx,
|
||||||
@@ -17,7 +17,7 @@ export const clearAndSelectFirstModelCommand: Command<'selectedModels'> = (
|
|||||||
const firstModel = models[0];
|
const firstModel = models[0];
|
||||||
if (firstModel.text) {
|
if (firstModel.text) {
|
||||||
firstModel.text.clear();
|
firstModel.text.clear();
|
||||||
const selection = ctx.std.selection.create('text', {
|
const selection = ctx.std.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: firstModel.id,
|
blockId: firstModel.id,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ export const getSelectedModelsCommand: Command<
|
|||||||
never,
|
never,
|
||||||
'selectedModels',
|
'selectedModels',
|
||||||
{
|
{
|
||||||
types?: Extract<BlockSuite.SelectionType, 'block' | 'text' | 'image'>[];
|
types?: Array<'image' | 'text' | 'block'>;
|
||||||
mode?: 'all' | 'flat' | 'highest';
|
mode?: 'all' | 'flat' | 'highest';
|
||||||
}
|
}
|
||||||
> = (ctx, next) => {
|
> = (ctx, next) => {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import type { BlockSelection, Command } from '@blocksuite/block-std';
|
import { BlockSelection, type Command } from '@blocksuite/block-std';
|
||||||
|
|
||||||
export const getBlockSelectionsCommand: Command<
|
export const getBlockSelectionsCommand: Command<
|
||||||
never,
|
never,
|
||||||
'currentBlockSelections'
|
'currentBlockSelections'
|
||||||
> = (ctx, next) => {
|
> = (ctx, next) => {
|
||||||
const currentBlockSelections = ctx.std.selection.filter('block');
|
const currentBlockSelections = ctx.std.selection.filter(BlockSelection);
|
||||||
if (currentBlockSelections.length === 0) return;
|
if (currentBlockSelections.length === 0) return;
|
||||||
|
|
||||||
next({ currentBlockSelections });
|
next({ currentBlockSelections });
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import type { Command } from '@blocksuite/block-std';
|
import type { Command } from '@blocksuite/block-std';
|
||||||
|
|
||||||
import type { ImageSelection } from '../../selection/index.js';
|
import { ImageSelection } from '../../selection/index.js';
|
||||||
|
|
||||||
export const getImageSelectionsCommand: Command<
|
export const getImageSelectionsCommand: Command<
|
||||||
never,
|
never,
|
||||||
'currentImageSelections'
|
'currentImageSelections'
|
||||||
> = (ctx, next) => {
|
> = (ctx, next) => {
|
||||||
const currentImageSelections = ctx.std.selection.filter('image');
|
const currentImageSelections = ctx.std.selection.filter(ImageSelection);
|
||||||
if (currentImageSelections.length === 0) return;
|
if (currentImageSelections.length === 0) return;
|
||||||
|
|
||||||
next({ currentImageSelections });
|
next({ currentImageSelections });
|
||||||
|
|||||||
@@ -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'> = (
|
export const getTextSelectionCommand: Command<never, 'currentTextSelection'> = (
|
||||||
ctx,
|
ctx,
|
||||||
next
|
next
|
||||||
) => {
|
) => {
|
||||||
const currentTextSelection = ctx.std.selection.find('text');
|
const currentTextSelection = ctx.std.selection.find(TextSelection);
|
||||||
if (!currentTextSelection) return;
|
if (!currentTextSelection) return;
|
||||||
|
|
||||||
next({ currentTextSelection });
|
next({ currentTextSelection });
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
import { findNoteBlockModel } from '@blocksuite/affine-shared/utils';
|
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';
|
import type { AffineDragHandleWidget } from '../drag-handle.js';
|
||||||
|
|
||||||
@@ -15,7 +20,7 @@ export class SelectionHelper {
|
|||||||
setSelectedBlocks = (blocks: BlockComponent[], noteId?: string) => {
|
setSelectedBlocks = (blocks: BlockComponent[], noteId?: string) => {
|
||||||
const { selection } = this;
|
const { selection } = this;
|
||||||
const selections = blocks.map(block =>
|
const selections = blocks.map(block =>
|
||||||
selection.create('block', {
|
selection.create(BlockSelection, {
|
||||||
blockId: block.blockId,
|
blockId: block.blockId,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -28,7 +33,7 @@ export class SelectionHelper {
|
|||||||
: findNoteBlockModel(blocks[0].model)?.id;
|
: findNoteBlockModel(blocks[0].model)?.id;
|
||||||
if (!surfaceElementId) return;
|
if (!surfaceElementId) return;
|
||||||
const surfaceSelection = selection.create(
|
const surfaceSelection = selection.create(
|
||||||
'surface',
|
SurfaceSelection,
|
||||||
blocks[0]!.blockId,
|
blocks[0]!.blockId,
|
||||||
[surfaceElementId],
|
[surfaceElementId],
|
||||||
true
|
true
|
||||||
@@ -49,9 +54,9 @@ export class SelectionHelper {
|
|||||||
get selectedBlocks() {
|
get selectedBlocks() {
|
||||||
const selection = this.selection;
|
const selection = this.selection;
|
||||||
|
|
||||||
return selection.find('text')
|
return selection.find(TextSelection)
|
||||||
? selection.filter('text')
|
? selection.filter(TextSelection)
|
||||||
: selection.filter('block');
|
: selection.filter(BlockSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
get selection() {
|
get selection() {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import {
|
import {
|
||||||
type BlockComponent,
|
type BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
type DndEventState,
|
type DndEventState,
|
||||||
isGfxBlockComponent,
|
isGfxBlockComponent,
|
||||||
type UIEventHandler,
|
type UIEventHandler,
|
||||||
@@ -158,7 +159,7 @@ export class DragEventWatcher {
|
|||||||
|
|
||||||
const selectBlockAndStartDragging = () => {
|
const selectBlockAndStartDragging = () => {
|
||||||
this._std.selection.setGroup('note', [
|
this._std.selection.setGroup('note', [
|
||||||
this._std.selection.create('block', {
|
this._std.selection.create(BlockSelection, {
|
||||||
blockId: hoverBlock.blockId,
|
blockId: hoverBlock.blockId,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export class AffineDocRemoteSelectionWidget extends WidgetComponent {
|
|||||||
|
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
const range = this.std.range.textSelectionToRange(
|
const range = this.std.range.textSelectionToRange(
|
||||||
this._selectionManager.create('text', {
|
this._selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: textSelection.to
|
blockId: textSelection.to
|
||||||
? textSelection.to.blockId
|
? textSelection.to.blockId
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import '@blocksuite/affine-shared/selection';
|
|
||||||
|
|
||||||
import type { DocMode } from '@blocksuite/affine-model';
|
import type { DocMode } from '@blocksuite/affine-model';
|
||||||
|
import { HighlightSelection } from '@blocksuite/affine-shared/selection';
|
||||||
import { WidgetComponent } from '@blocksuite/block-std';
|
import { WidgetComponent } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
GfxControllerIdentifier,
|
GfxControllerIdentifier,
|
||||||
@@ -65,7 +64,7 @@ export class AffineScrollAnchoringWidget extends WidgetComponent {
|
|||||||
anchorBounds$ = signal<Bound | null>(null);
|
anchorBounds$ = signal<Bound | null>(null);
|
||||||
|
|
||||||
highlighted$ = computed(() =>
|
highlighted$ = computed(() =>
|
||||||
this.service.selectionManager.find('highlight')
|
this.service.selectionManager.find(HighlightSelection)
|
||||||
);
|
);
|
||||||
|
|
||||||
#getBoundsInEdgeless() {
|
#getBoundsInEdgeless() {
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ export {
|
|||||||
PlainTextAdapterFactoryExtension,
|
PlainTextAdapterFactoryExtension,
|
||||||
PlainTextAdapterFactoryIdentifier,
|
PlainTextAdapterFactoryIdentifier,
|
||||||
} from '@blocksuite/affine-shared/adapters';
|
} from '@blocksuite/affine-shared/adapters';
|
||||||
|
export { HighlightSelection } from '@blocksuite/affine-shared/selection';
|
||||||
export * from '@blocksuite/affine-shared/services';
|
export * from '@blocksuite/affine-shared/services';
|
||||||
export { scrollbarStyle } from '@blocksuite/affine-shared/styles';
|
export { scrollbarStyle } from '@blocksuite/affine-shared/styles';
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { LassoMode } from '@blocksuite/affine-shared/types';
|
import { LassoMode } from '@blocksuite/affine-shared/types';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
|
import { SurfaceSelection, TextSelection } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
GfxBlockElementModel,
|
GfxBlockElementModel,
|
||||||
type GfxToolsMap,
|
type GfxToolsMap,
|
||||||
@@ -167,8 +168,8 @@ export class EdgelessPageKeyboardManager extends PageKeyboardManager {
|
|||||||
const std = this.rootComponent.std;
|
const std = this.rootComponent.std;
|
||||||
if (
|
if (
|
||||||
std.selection.getGroup('note').length > 0 ||
|
std.selection.getGroup('note').length > 0 ||
|
||||||
std.selection.find('text') ||
|
std.selection.find(TextSelection) ||
|
||||||
Boolean(std.selection.find('surface')?.editing)
|
Boolean(std.selection.find(SurfaceSelection)?.editing)
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ import {
|
|||||||
requestConnectedFrame,
|
requestConnectedFrame,
|
||||||
requestThrottledConnectedFrame,
|
requestThrottledConnectedFrame,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type {
|
import {
|
||||||
GfxBlockComponent,
|
BlockComponent,
|
||||||
|
type GfxBlockComponent,
|
||||||
SurfaceSelection,
|
SurfaceSelection,
|
||||||
UIEventHandler,
|
type UIEventHandler,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { BlockComponent } from '@blocksuite/block-std';
|
|
||||||
import {
|
import {
|
||||||
GfxControllerIdentifier,
|
GfxControllerIdentifier,
|
||||||
type GfxViewportElement,
|
type GfxViewportElement,
|
||||||
@@ -454,7 +454,7 @@ export class EdgelessRootBlockComponent extends BlockComponent<
|
|||||||
|
|
||||||
this.handleEvent('selectionChange', () => {
|
this.handleEvent('selectionChange', () => {
|
||||||
const surface = this.host.selection.value.find(
|
const surface = this.host.selection.value.find(
|
||||||
(sel): sel is SurfaceSelection => sel.is('surface')
|
(sel): sel is SurfaceSelection => sel.is(SurfaceSelection)
|
||||||
);
|
);
|
||||||
if (!surface) return;
|
if (!surface) return;
|
||||||
|
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ import {
|
|||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { requestThrottledConnectedFrame } from '@blocksuite/affine-shared/utils';
|
import { requestThrottledConnectedFrame } from '@blocksuite/affine-shared/utils';
|
||||||
import type {
|
import {
|
||||||
GfxBlockComponent,
|
BlockComponent,
|
||||||
|
type GfxBlockComponent,
|
||||||
SurfaceSelection,
|
SurfaceSelection,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { BlockComponent } from '@blocksuite/block-std';
|
|
||||||
import type { GfxViewportElement } from '@blocksuite/block-std/gfx';
|
import type { GfxViewportElement } from '@blocksuite/block-std/gfx';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import { css, html } from 'lit';
|
import { css, html } from 'lit';
|
||||||
@@ -181,7 +181,7 @@ export class EdgelessRootPreviewBlockComponent
|
|||||||
|
|
||||||
this.handleEvent('selectionChange', () => {
|
this.handleEvent('selectionChange', () => {
|
||||||
const surface = this.host.selection.value.find(
|
const surface = this.host.selection.value.find(
|
||||||
(sel): sel is SurfaceSelection => sel.is('surface')
|
(sel): sel is SurfaceSelection => sel.is(SurfaceSelection)
|
||||||
);
|
);
|
||||||
if (!surface) return;
|
if (!surface) return;
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,18 @@ import {
|
|||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
import { ParagraphBlockComponent } from '@blocksuite/affine-block-paragraph';
|
import { ParagraphBlockComponent } from '@blocksuite/affine-block-paragraph';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
import type { BlockComponent, UIEventHandler } from '@blocksuite/block-std';
|
import {
|
||||||
|
type BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
|
type UIEventHandler,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { IS_MAC, IS_WINDOWS } from '@blocksuite/global/env';
|
import { IS_MAC, IS_WINDOWS } from '@blocksuite/global/env';
|
||||||
|
|
||||||
export class PageKeyboardManager {
|
export class PageKeyboardManager {
|
||||||
private readonly _handleDelete: UIEventHandler = ctx => {
|
private readonly _handleDelete: UIEventHandler = ctx => {
|
||||||
const event = ctx.get('keyboardState').raw;
|
const event = ctx.get('keyboardState').raw;
|
||||||
const blockSelections = this._currentSelection.filter(sel =>
|
const blockSelections = this._currentSelection.filter(sel =>
|
||||||
sel.is('block')
|
sel.is(BlockSelection)
|
||||||
);
|
);
|
||||||
if (blockSelections.length === 0) {
|
if (blockSelections.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import {
|
|||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { PointerEventState } from '@blocksuite/block-std';
|
import type { PointerEventState } from '@blocksuite/block-std';
|
||||||
import { BlockComponent } from '@blocksuite/block-std';
|
import {
|
||||||
|
BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
|
TextSelection,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import type { BlockModel, Text } from '@blocksuite/store';
|
import type { BlockModel, Text } from '@blocksuite/store';
|
||||||
import { css, html } from 'lit';
|
import { css, html } from 'lit';
|
||||||
import { query } from 'lit/decorators.js';
|
import { query } from 'lit/decorators.js';
|
||||||
@@ -236,7 +240,7 @@ export class PageRootBlockComponent extends BlockComponent<
|
|||||||
})
|
})
|
||||||
.flatMap(model => {
|
.flatMap(model => {
|
||||||
return model.children.map(child => {
|
return model.children.map(child => {
|
||||||
return this.std.selection.create('block', {
|
return this.std.selection.create(BlockSelection, {
|
||||||
blockId: child.id,
|
blockId: child.id,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -247,7 +251,7 @@ export class PageRootBlockComponent extends BlockComponent<
|
|||||||
ArrowUp: () => {
|
ArrowUp: () => {
|
||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
const sel = selection.value.find(
|
const sel = selection.value.find(
|
||||||
sel => sel.is('text') || sel.is('block')
|
sel => sel.is(TextSelection) || sel.is(BlockSelection)
|
||||||
);
|
);
|
||||||
if (!sel) return;
|
if (!sel) return;
|
||||||
let model: BlockModel | null = null;
|
let model: BlockModel | null = null;
|
||||||
@@ -262,8 +266,8 @@ export class PageRootBlockComponent extends BlockComponent<
|
|||||||
if (!model) return;
|
if (!model) return;
|
||||||
const prevNote = this.doc.getPrev(model);
|
const prevNote = this.doc.getPrev(model);
|
||||||
if (!prevNote || prevNote.flavour !== 'affine:note') {
|
if (!prevNote || prevNote.flavour !== 'affine:note') {
|
||||||
const isFirstText = sel.is('text') && sel.start.index === 0;
|
const isFirstText = sel.is(TextSelection) && sel.start.index === 0;
|
||||||
const isBlock = sel.is('block');
|
const isBlock = sel.is(BlockSelection);
|
||||||
if (isBlock || isFirstText) {
|
if (isBlock || isFirstText) {
|
||||||
focusTitle(this.host);
|
focusTitle(this.host);
|
||||||
}
|
}
|
||||||
@@ -361,7 +365,7 @@ export class PageRootBlockComponent extends BlockComponent<
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
if (!newTextSelectionId) return;
|
if (!newTextSelectionId) return;
|
||||||
this.host.selection.setGroup('note', [
|
this.host.selection.setGroup('note', [
|
||||||
this.host.selection.create('text', {
|
this.host.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: newTextSelectionId,
|
blockId: newTextSelectionId,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
|||||||
@@ -52,7 +52,12 @@ import {
|
|||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { getHostName, referenceToNode } from '@blocksuite/affine-shared/utils';
|
import { getHostName, referenceToNode } from '@blocksuite/affine-shared/utils';
|
||||||
import { type BlockStdScope, WidgetComponent } from '@blocksuite/block-std';
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
type BlockStdScope,
|
||||||
|
TextSelection,
|
||||||
|
WidgetComponent,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { type BlockModel, Text } from '@blocksuite/store';
|
import { type BlockModel, Text } from '@blocksuite/store';
|
||||||
import { autoUpdate, computePosition, flip, offset } from '@floating-ui/dom';
|
import { autoUpdate, computePosition, flip, offset } from '@floating-ui/dom';
|
||||||
import { html, nothing, type TemplateResult } from 'lit';
|
import { html, nothing, type TemplateResult } from 'lit';
|
||||||
@@ -709,13 +714,13 @@ export class EmbedCardToolbar extends WidgetComponent<
|
|||||||
|
|
||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this._selection.slots.changed.on(() => {
|
this._selection.slots.changed.on(() => {
|
||||||
const hasTextSelection = this._selection.find('text');
|
const hasTextSelection = this._selection.find(TextSelection);
|
||||||
if (hasTextSelection) {
|
if (hasTextSelection) {
|
||||||
this._hide();
|
this._hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = this._selection.filter('block');
|
const blockSelections = this._selection.filter(BlockSelection);
|
||||||
if (!blockSelections || blockSelections.length !== 1) {
|
if (!blockSelections || blockSelections.length !== 1) {
|
||||||
this._hide();
|
this._hide();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ import {
|
|||||||
} from '@blocksuite/affine-components/toolbar';
|
} from '@blocksuite/affine-components/toolbar';
|
||||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||||
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
import { matchFlavours } from '@blocksuite/affine-shared/utils';
|
||||||
import type {
|
import {
|
||||||
BaseSelection,
|
type BaseSelection,
|
||||||
BlockComponent,
|
type BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
CursorSelection,
|
CursorSelection,
|
||||||
|
TextSelection,
|
||||||
|
WidgetComponent,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
import { WidgetComponent } from '@blocksuite/block-std';
|
import { DatabaseSelection } from '@blocksuite/data-view';
|
||||||
import {
|
import {
|
||||||
assertExists,
|
assertExists,
|
||||||
DisposableGroup,
|
DisposableGroup,
|
||||||
@@ -129,11 +132,12 @@ export class AffineFormatBarWidget extends WidgetComponent {
|
|||||||
this.disposables.add(
|
this.disposables.add(
|
||||||
this._selectionManager.slots.changed.on(() => {
|
this._selectionManager.slots.changed.on(() => {
|
||||||
const update = async () => {
|
const update = async () => {
|
||||||
const textSelection = rootComponent.selection.find('text');
|
const textSelection = rootComponent.selection.find(TextSelection);
|
||||||
const blockSelections = rootComponent.selection.filter('block');
|
const blockSelections =
|
||||||
|
rootComponent.selection.filter(BlockSelection);
|
||||||
|
|
||||||
// Should not re-render format bar when only cursor selection changed in edgeless
|
// Should not re-render format bar when only cursor selection changed in edgeless
|
||||||
const cursorSelection = rootComponent.selection.find('cursor');
|
const cursorSelection = rootComponent.selection.find(CursorSelection);
|
||||||
if (cursorSelection) {
|
if (cursorSelection) {
|
||||||
if (!this._lastCursor) {
|
if (!this._lastCursor) {
|
||||||
this._lastCursor = cursorSelection;
|
this._lastCursor = cursorSelection;
|
||||||
@@ -202,7 +206,7 @@ export class AffineFormatBarWidget extends WidgetComponent {
|
|||||||
this.disposables.addFromEvent(document, 'selectionchange', () => {
|
this.disposables.addFromEvent(document, 'selectionchange', () => {
|
||||||
if (!this.host.event.active) return;
|
if (!this.host.event.active) return;
|
||||||
|
|
||||||
const databaseSelection = this.host.selection.find('database');
|
const databaseSelection = this.host.selection.find(DatabaseSelection);
|
||||||
if (!databaseSelection) {
|
if (!databaseSelection) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import {
|
|||||||
} from '@blocksuite/affine-components/toolbar';
|
} from '@blocksuite/affine-components/toolbar';
|
||||||
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
import type { ImageBlockModel } from '@blocksuite/affine-model';
|
||||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
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 { limitShift, shift } from '@floating-ui/dom';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
|
|
||||||
@@ -35,7 +39,7 @@ export class AffineImageToolbarWidget extends WidgetComponent<
|
|||||||
const imageBlock = this.block;
|
const imageBlock = this.block;
|
||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (
|
if (
|
||||||
!!textSelection &&
|
!!textSelection &&
|
||||||
(!!textSelection.to || !!textSelection.from.length)
|
(!!textSelection.to || !!textSelection.from.length)
|
||||||
@@ -43,7 +47,7 @@ export class AffineImageToolbarWidget extends WidgetComponent<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection.filter('block');
|
const blockSelections = selection.filter(BlockSelection);
|
||||||
if (
|
if (
|
||||||
blockSelections.length > 1 ||
|
blockSelections.length > 1 ||
|
||||||
(blockSelections.length === 1 &&
|
(blockSelections.length === 1 &&
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
getBlockProps,
|
getBlockProps,
|
||||||
isInsidePageEditor,
|
isInsidePageEditor,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
|
|
||||||
export function duplicate(
|
export function duplicate(
|
||||||
@@ -38,7 +39,7 @@ export function duplicate(
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
const { selection } = editorHost;
|
const { selection } = editorHost;
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('block', {
|
selection.create(BlockSelection, {
|
||||||
blockId: duplicateId,
|
blockId: duplicateId,
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
BLOCK_ID_ATTR,
|
BLOCK_ID_ATTR,
|
||||||
BlockComponent,
|
BlockComponent,
|
||||||
|
BlockSelection,
|
||||||
type PointerEventState,
|
type PointerEventState,
|
||||||
WidgetComponent,
|
WidgetComponent,
|
||||||
} from '@blocksuite/block-std';
|
} from '@blocksuite/block-std';
|
||||||
@@ -188,7 +189,7 @@ export class AffinePageDraggingAreaWidget extends WidgetComponent<
|
|||||||
this._allBlocksWithRect,
|
this._allBlocksWithRect,
|
||||||
userRect
|
userRect
|
||||||
).map(blockPath => {
|
).map(blockPath => {
|
||||||
return this.host.selection.create('block', {
|
return this.host.selection.create(BlockSelection, {
|
||||||
blockId: blockPath,
|
blockId: blockPath,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
matchFlavours,
|
matchFlavours,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
import type { UIEventStateContext } from '@blocksuite/block-std';
|
import type { UIEventStateContext } from '@blocksuite/block-std';
|
||||||
import { WidgetComponent } from '@blocksuite/block-std';
|
import { TextSelection, WidgetComponent } from '@blocksuite/block-std';
|
||||||
import {
|
import {
|
||||||
assertExists,
|
assertExists,
|
||||||
assertType,
|
assertType,
|
||||||
@@ -122,7 +122,7 @@ export class AffineSlashMenuWidget extends WidgetComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
const model = this.host.doc.getBlock(textSelection.blockId)?.model;
|
const model = this.host.doc.getBlock(textSelection.blockId)?.model;
|
||||||
@@ -149,7 +149,7 @@ export class AffineSlashMenuWidget extends WidgetComponent {
|
|||||||
assertType<RootBlockComponent>(rootComponent);
|
assertType<RootBlockComponent>(rootComponent);
|
||||||
|
|
||||||
inlineRangeApplyCallback(() => {
|
inlineRangeApplyCallback(() => {
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
const model = this.host.doc.getBlock(textSelection.blockId)?.model;
|
const model = this.host.doc.getBlock(textSelection.blockId)?.model;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
TextFormatConfig,
|
TextFormatConfig,
|
||||||
} from '@blocksuite/affine-components/rich-text';
|
} from '@blocksuite/affine-components/rich-text';
|
||||||
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
||||||
|
import { BlockSelection } from '@blocksuite/block-std';
|
||||||
import { assertType } from '@blocksuite/global/utils';
|
import { assertType } from '@blocksuite/global/utils';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
@@ -128,7 +129,7 @@ export function createTextFormatItem(
|
|||||||
.chain()
|
.chain()
|
||||||
.formatBlock({
|
.formatBlock({
|
||||||
blockSelections: [
|
blockSelections: [
|
||||||
std.selection.create('block', {
|
std.selection.create(BlockSelection, {
|
||||||
blockId: model.id,
|
blockId: model.id,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -19,7 +19,11 @@ import {
|
|||||||
} from '@blocksuite/affine-components/toolbar';
|
} from '@blocksuite/affine-components/toolbar';
|
||||||
import type { SurfaceRefBlockModel } from '@blocksuite/affine-model';
|
import type { SurfaceRefBlockModel } from '@blocksuite/affine-model';
|
||||||
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
import { PAGE_HEADER_HEIGHT } from '@blocksuite/affine-shared/consts';
|
||||||
import { WidgetComponent } from '@blocksuite/block-std';
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
TextSelection,
|
||||||
|
WidgetComponent,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { offset, shift } from '@floating-ui/dom';
|
import { offset, shift } from '@floating-ui/dom';
|
||||||
import { html, nothing } from 'lit';
|
import { html, nothing } from 'lit';
|
||||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||||
@@ -48,7 +52,7 @@ export class AffineSurfaceRefToolbar extends WidgetComponent<
|
|||||||
const surfaceRefBlock = this.block;
|
const surfaceRefBlock = this.block;
|
||||||
const selection = this.host.selection;
|
const selection = this.host.selection;
|
||||||
|
|
||||||
const textSelection = selection.find('text');
|
const textSelection = selection.find(TextSelection);
|
||||||
if (
|
if (
|
||||||
!!textSelection &&
|
!!textSelection &&
|
||||||
(!!textSelection.to || !!textSelection.from.length)
|
(!!textSelection.to || !!textSelection.from.length)
|
||||||
@@ -56,7 +60,7 @@ export class AffineSurfaceRefToolbar extends WidgetComponent<
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockSelections = selection.filter('block');
|
const blockSelections = selection.filter(BlockSelection);
|
||||||
if (
|
if (
|
||||||
blockSelections.length > 1 ||
|
blockSelections.length > 1 ||
|
||||||
(blockSelections.length === 1 &&
|
(blockSelections.length === 1 &&
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ import {
|
|||||||
Slot,
|
Slot,
|
||||||
} from '@blocksuite/global/utils';
|
} from '@blocksuite/global/utils';
|
||||||
|
|
||||||
import type { CursorSelection, SurfaceSelection } from '../selection/index.js';
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
CursorSelection,
|
||||||
|
SurfaceSelection,
|
||||||
|
TextSelection,
|
||||||
|
} from '../selection/index.js';
|
||||||
import type { GfxController } from './controller.js';
|
import type { GfxController } from './controller.js';
|
||||||
import { GfxExtension, GfxExtensionIdentifier } from './extension.js';
|
import { GfxExtension, GfxExtensionIdentifier } from './extension.js';
|
||||||
import type { GfxModel } from './model/model.js';
|
import type { GfxModel } from './model/model.js';
|
||||||
@@ -215,9 +220,9 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
this.disposable.add(
|
this.disposable.add(
|
||||||
this.stdSelection.slots.changed.on(selections => {
|
this.stdSelection.slots.changed.on(selections => {
|
||||||
const { cursor = [], surface = [] } = groupBy(selections, sel => {
|
const { cursor = [], surface = [] } = groupBy(selections, sel => {
|
||||||
if (sel.is('surface')) {
|
if (sel.is(SurfaceSelection)) {
|
||||||
return 'surface';
|
return 'surface';
|
||||||
} else if (sel.is('cursor')) {
|
} else if (sel.is(CursorSelection)) {
|
||||||
return 'cursor';
|
return 'cursor';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,15 +266,15 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
let hasBlockSelection = false;
|
let hasBlockSelection = false;
|
||||||
|
|
||||||
selections.forEach(selection => {
|
selections.forEach(selection => {
|
||||||
if (selection.is('text')) {
|
if (selection.is(TextSelection)) {
|
||||||
hasTextSelection = true;
|
hasTextSelection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.is('block')) {
|
if (selection.is(BlockSelection)) {
|
||||||
hasBlockSelection = true;
|
hasBlockSelection = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.is('surface')) {
|
if (selection.is(SurfaceSelection)) {
|
||||||
const surfaceSelections = surfaceMap.get(id) ?? [];
|
const surfaceSelections = surfaceMap.get(id) ?? [];
|
||||||
surfaceSelections.push(selection);
|
surfaceSelections.push(selection);
|
||||||
surfaceMap.set(id, surfaceSelections);
|
surfaceMap.set(id, surfaceSelections);
|
||||||
@@ -277,7 +282,7 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
selection.elements.forEach(id => selectedSet.add(id));
|
selection.elements.forEach(id => selectedSet.add(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection.is('cursor')) {
|
if (selection.is(CursorSelection)) {
|
||||||
cursorMap.set(id, selection);
|
cursorMap.set(id, selection);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -318,7 +323,7 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
if (elements.length > 0 && this.surfaceModel) {
|
if (elements.length > 0 && this.surfaceModel) {
|
||||||
instances.push(
|
instances.push(
|
||||||
this.stdSelection.create(
|
this.stdSelection.create(
|
||||||
'surface',
|
SurfaceSelection,
|
||||||
this.surfaceModel.id,
|
this.surfaceModel.id,
|
||||||
elements,
|
elements,
|
||||||
selection.editing ?? false,
|
selection.editing ?? false,
|
||||||
@@ -331,7 +336,7 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
instances = instances.concat(
|
instances = instances.concat(
|
||||||
blocks.map(blockId =>
|
blocks.map(blockId =>
|
||||||
this.stdSelection.create(
|
this.stdSelection.create(
|
||||||
'surface',
|
SurfaceSelection,
|
||||||
blockId,
|
blockId,
|
||||||
[blockId],
|
[blockId],
|
||||||
selection.editing ?? false,
|
selection.editing ?? false,
|
||||||
@@ -368,7 +373,11 @@ export class GfxSelectionManager extends GfxExtension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCursor(cursor: CursorSelection | IPoint) {
|
setCursor(cursor: CursorSelection | IPoint) {
|
||||||
const instance = this.stdSelection.create('cursor', cursor.x, cursor.y);
|
const instance = this.stdSelection.create(
|
||||||
|
CursorSelection,
|
||||||
|
cursor.x,
|
||||||
|
cursor.y
|
||||||
|
);
|
||||||
|
|
||||||
this.stdSelection.setGroup('gfx', [...this.surfaceSelections, instance]);
|
this.stdSelection.setGroup('gfx', [...this.surfaceSelections, instance]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { InlineRange, InlineRangeProvider } from '@blocksuite/inline';
|
import type { InlineRange, InlineRangeProvider } from '@blocksuite/inline';
|
||||||
import { signal } from '@preact/signals-core';
|
import { signal } from '@preact/signals-core';
|
||||||
|
|
||||||
import type { TextSelection } from '../selection/index.js';
|
import { TextSelection } from '../selection/index.js';
|
||||||
import type { BlockComponent } from '../view/element/block-component.js';
|
import type { BlockComponent } from '../view/element/block-component.js';
|
||||||
|
|
||||||
export const getInlineRangeProvider: (
|
export const getInlineRangeProvider: (
|
||||||
@@ -40,7 +40,7 @@ export const getInlineRangeProvider: (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const elementRange = rangeManager.textSelectionToRange(
|
const elementRange = rangeManager.textSelectionToRange(
|
||||||
selectionManager.create('text', {
|
selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
index: 0,
|
index: 0,
|
||||||
blockId: element.blockId,
|
blockId: element.blockId,
|
||||||
@@ -72,7 +72,7 @@ export const getInlineRangeProvider: (
|
|||||||
if (!inlineRange) {
|
if (!inlineRange) {
|
||||||
selectionManager.clear(['text']);
|
selectionManager.clear(['text']);
|
||||||
} else {
|
} else {
|
||||||
const textSelection = selectionManager.create('text', {
|
const textSelection = selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: element.blockId,
|
blockId: element.blockId,
|
||||||
index: inlineRange.index,
|
index: inlineRange.index,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { throttle } from '@blocksuite/global/utils';
|
import { throttle } from '@blocksuite/global/utils';
|
||||||
import type { BlockModel } from '@blocksuite/store';
|
import type { BlockModel } from '@blocksuite/store';
|
||||||
|
|
||||||
import type { BaseSelection, TextSelection } from '../selection/index.js';
|
import { type BaseSelection, TextSelection } from '../selection/index.js';
|
||||||
import type { BlockComponent } from '../view/element/block-component.js';
|
import type { BlockComponent } from '../view/element/block-component.js';
|
||||||
import { BLOCK_ID_ATTR } from '../view/index.js';
|
import { BLOCK_ID_ATTR } from '../view/index.js';
|
||||||
import { RANGE_SYNC_EXCLUDE_ATTR } from './consts.js';
|
import { RANGE_SYNC_EXCLUDE_ATTR } from './consts.js';
|
||||||
@@ -30,7 +30,7 @@ export class RangeBinding {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly _onBeforeInput = (event: InputEvent) => {
|
private readonly _onBeforeInput = (event: InputEvent) => {
|
||||||
const selection = this.selectionManager.find('text');
|
const selection = this.selectionManager.find(TextSelection);
|
||||||
if (!selection) return;
|
if (!selection) return;
|
||||||
|
|
||||||
if (event.isComposing) return;
|
if (event.isComposing) return;
|
||||||
@@ -74,7 +74,7 @@ export class RangeBinding {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const newSelection = this.selectionManager.create('text', {
|
const newSelection = this.selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: from.blockId,
|
blockId: from.blockId,
|
||||||
index: from.index + (event.data?.length ?? 0),
|
index: from.index + (event.data?.length ?? 0),
|
||||||
@@ -95,7 +95,7 @@ export class RangeBinding {
|
|||||||
};
|
};
|
||||||
|
|
||||||
private readonly _onCompositionStart = () => {
|
private readonly _onCompositionStart = () => {
|
||||||
const selection = this.selectionManager.find('text');
|
const selection = this.selectionManager.find(TextSelection);
|
||||||
if (!selection) return;
|
if (!selection) return;
|
||||||
|
|
||||||
const { from, to } = selection;
|
const { from, to } = selection;
|
||||||
@@ -153,7 +153,7 @@ export class RangeBinding {
|
|||||||
|
|
||||||
await this.host.updateComplete;
|
await this.host.updateComplete;
|
||||||
|
|
||||||
const selection = this.selectionManager.create('text', {
|
const selection = this.selectionManager.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: from.blockId,
|
blockId: from.blockId,
|
||||||
index: from.index + (event.data?.length ?? 0),
|
index: from.index + (event.data?.length ?? 0),
|
||||||
@@ -249,7 +249,7 @@ export class RangeBinding {
|
|||||||
private readonly _onStdSelectionChanged = (selections: BaseSelection[]) => {
|
private readonly _onStdSelectionChanged = (selections: BaseSelection[]) => {
|
||||||
const text =
|
const text =
|
||||||
selections.find((selection): selection is TextSelection =>
|
selections.find((selection): selection is TextSelection =>
|
||||||
selection.is('text')
|
selection.is(TextSelection)
|
||||||
) ?? null;
|
) ?? null;
|
||||||
|
|
||||||
if (text === this._prevTextSelection) {
|
if (text === this._prevTextSelection) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { INLINE_ROOT_ATTR, type InlineRootElement } from '@blocksuite/inline';
|
import { INLINE_ROOT_ATTR, type InlineRootElement } from '@blocksuite/inline';
|
||||||
|
|
||||||
import { LifeCycleWatcher } from '../extension/index.js';
|
import { LifeCycleWatcher } from '../extension/index.js';
|
||||||
import type { TextSelection } from '../selection/index.js';
|
import { TextSelection } from '../selection/index.js';
|
||||||
import type { BlockComponent } from '../view/element/block-component.js';
|
import type { BlockComponent } from '../view/element/block-component.js';
|
||||||
import { BLOCK_ID_ATTR } from '../view/index.js';
|
import { BLOCK_ID_ATTR } from '../view/index.js';
|
||||||
import { RANGE_QUERY_EXCLUDE_ATTR, RANGE_SYNC_EXCLUDE_ATTR } from './consts.js';
|
import { RANGE_QUERY_EXCLUDE_ATTR, RANGE_SYNC_EXCLUDE_ATTR } from './consts.js';
|
||||||
@@ -163,7 +163,7 @@ export class RangeManager extends LifeCycleWatcher {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.std.host.selection.create('text', {
|
return this.std.host.selection.create(TextSelection, {
|
||||||
from: {
|
from: {
|
||||||
blockId: startBlock.blockId,
|
blockId: startBlock.blockId,
|
||||||
index: startInlineRange.index,
|
index: startInlineRange.index,
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||||
|
|
||||||
type SelectionConstructor<T = unknown> = {
|
import type { SelectionConstructor } from './manager';
|
||||||
type: string;
|
|
||||||
group: string;
|
|
||||||
new (...args: unknown[]): T;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BaseSelectionOptions = {
|
export type BaseSelectionOptions = {
|
||||||
blockId: string;
|
blockId: string;
|
||||||
@@ -21,9 +17,8 @@ export abstract class BaseSelection {
|
|||||||
return (this.constructor as SelectionConstructor).group;
|
return (this.constructor as SelectionConstructor).group;
|
||||||
}
|
}
|
||||||
|
|
||||||
get type(): BlockSuite.SelectionType {
|
get type(): string {
|
||||||
return (this.constructor as SelectionConstructor)
|
return (this.constructor as SelectionConstructor).type as string;
|
||||||
.type as BlockSuite.SelectionType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor({ blockId }: BaseSelectionOptions) {
|
constructor({ blockId }: BaseSelectionOptions) {
|
||||||
@@ -39,10 +34,10 @@ export abstract class BaseSelection {
|
|||||||
|
|
||||||
abstract equals(other: BaseSelection): boolean;
|
abstract equals(other: BaseSelection): boolean;
|
||||||
|
|
||||||
is<T extends BlockSuite.SelectionType>(
|
is<T extends SelectionConstructor>(
|
||||||
type: T
|
type: T
|
||||||
): this is BlockSuite.SelectionInstance[T] {
|
): this is T extends SelectionConstructor<infer U> ? U : never {
|
||||||
return this.type === type;
|
return this.type === type.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract toJSON(): Record<string, unknown>;
|
abstract toJSON(): Record<string, unknown>;
|
||||||
|
|||||||
@@ -1,27 +1,3 @@
|
|||||||
import type {
|
|
||||||
BlockSelection,
|
|
||||||
CursorSelection,
|
|
||||||
SurfaceSelection,
|
|
||||||
TextSelection,
|
|
||||||
} from './variants/index.js';
|
|
||||||
|
|
||||||
export * from './base.js';
|
export * from './base.js';
|
||||||
export * from './manager.js';
|
export * from './manager.js';
|
||||||
export * from './variants/index.js';
|
export * from './variants/index.js';
|
||||||
|
|
||||||
declare global {
|
|
||||||
namespace BlockSuite {
|
|
||||||
interface Selection {
|
|
||||||
block: typeof BlockSelection;
|
|
||||||
cursor: typeof CursorSelection;
|
|
||||||
surface: typeof SurfaceSelection;
|
|
||||||
text: typeof TextSelection;
|
|
||||||
}
|
|
||||||
|
|
||||||
type SelectionType = keyof Selection;
|
|
||||||
|
|
||||||
type SelectionInstance = {
|
|
||||||
[P in SelectionType]: InstanceType<Selection[P]>;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ import { SelectionIdentifier } from '../identifier.js';
|
|||||||
import type { BlockStdScope } from '../scope/index.js';
|
import type { BlockStdScope } from '../scope/index.js';
|
||||||
import type { BaseSelection } from './base.js';
|
import type { BaseSelection } from './base.js';
|
||||||
|
|
||||||
export interface SelectionConstructor {
|
export interface SelectionConstructor<T extends BaseSelection = BaseSelection> {
|
||||||
type: string;
|
type: string;
|
||||||
|
group: string;
|
||||||
|
|
||||||
new (...args: any[]): BaseSelection;
|
new (...args: any[]): T;
|
||||||
fromJSON(json: Record<string, unknown>): BaseSelection;
|
fromJSON(json: Record<string, unknown>): T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SelectionManager extends LifeCycleWatcher {
|
export class SelectionManager extends LifeCycleWatcher {
|
||||||
@@ -143,18 +144,11 @@ export class SelectionManager extends LifeCycleWatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
create<T extends BlockSuite.SelectionType>(
|
create<T extends SelectionConstructor>(
|
||||||
type: T,
|
Type: T,
|
||||||
...args: ConstructorParameters<BlockSuite.Selection[T]>
|
...args: ConstructorParameters<T>
|
||||||
): BlockSuite.SelectionInstance[T] {
|
): InstanceType<T> {
|
||||||
const ctor = this._selectionConstructors[type];
|
return new Type(...args) as InstanceType<T>;
|
||||||
if (!ctor) {
|
|
||||||
throw new BlockSuiteError(
|
|
||||||
ErrorCode.SelectionError,
|
|
||||||
`Unknown selection type: ${type}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return new ctor(...args) as BlockSuite.SelectionInstance[T];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
@@ -162,27 +156,23 @@ export class SelectionManager extends LifeCycleWatcher {
|
|||||||
this.disposables.dispose();
|
this.disposables.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
filter<T extends BlockSuite.SelectionType>(type: T) {
|
filter<T extends SelectionConstructor>(type: T) {
|
||||||
return this.filter$(type).value;
|
return this.filter$(type).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
filter$<T extends BlockSuite.SelectionType>(type: T) {
|
filter$<T extends SelectionConstructor>(type: T) {
|
||||||
return computed(() =>
|
return computed(() =>
|
||||||
this.value.filter((sel): sel is BlockSuite.SelectionInstance[T] =>
|
this.value.filter((sel): sel is InstanceType<T> => sel.is(type))
|
||||||
sel.is(type)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
find<T extends BlockSuite.SelectionType>(type: T) {
|
find<T extends SelectionConstructor>(type: T) {
|
||||||
return this.find$(type).value;
|
return this.find$(type).value;
|
||||||
}
|
}
|
||||||
|
|
||||||
find$<T extends BlockSuite.SelectionType>(type: T) {
|
find$<T extends SelectionConstructor>(type: T) {
|
||||||
return computed(() =>
|
return computed(() =>
|
||||||
this.value.find((sel): sel is BlockSuite.SelectionInstance[T] =>
|
this.value.find((sel): sel is InstanceType<T> => sel.is(type))
|
||||||
sel.is(type)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import type { TextSelection } from '@blocksuite/block-std';
|
import { ShadowlessElement, TextSelection } from '@blocksuite/block-std';
|
||||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
|
||||||
import type { RichText } from '@blocksuite/blocks';
|
import type { RichText } from '@blocksuite/blocks';
|
||||||
import { WithDisposable } from '@blocksuite/global/utils';
|
import { WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { css, html, nothing } from 'lit';
|
import { css, html, nothing } from 'lit';
|
||||||
@@ -69,7 +68,7 @@ export class CommentInput extends WithDisposable(ShadowlessElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
if (!textSelection) {
|
if (!textSelection) {
|
||||||
this.remove();
|
this.remove();
|
||||||
return nothing;
|
return nothing;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
import { ShadowlessElement, TextSelection } from '@blocksuite/block-std';
|
||||||
import { WithDisposable } from '@blocksuite/global/utils';
|
import { WithDisposable } from '@blocksuite/global/utils';
|
||||||
import { css, html } from 'lit';
|
import { css, html } from 'lit';
|
||||||
import { property, query } from 'lit/decorators.js';
|
import { property, query } from 'lit/decorators.js';
|
||||||
@@ -60,7 +60,7 @@ export class CommentPanel extends WithDisposable(ShadowlessElement) {
|
|||||||
commentManager: CommentManager | null = null;
|
commentManager: CommentManager | null = null;
|
||||||
|
|
||||||
private _addComment() {
|
private _addComment() {
|
||||||
const textSelection = this.editor.host?.selection.find('text');
|
const textSelection = this.editor.host?.selection.find(TextSelection);
|
||||||
if (!textSelection) return;
|
if (!textSelection) return;
|
||||||
|
|
||||||
const commentInput = new CommentInput();
|
const commentInput = new CommentInput();
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import {
|
|||||||
DEFAULT_NOTE_WIDTH,
|
DEFAULT_NOTE_WIDTH,
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import type { BlockComponent, EditorHost } from '@blocksuite/block-std';
|
import type {
|
||||||
|
BlockComponent,
|
||||||
|
EditorHost,
|
||||||
|
TextSelection,
|
||||||
|
} from '@blocksuite/block-std';
|
||||||
import { BLOCK_ID_ATTR } from '@blocksuite/block-std';
|
import { BLOCK_ID_ATTR } from '@blocksuite/block-std';
|
||||||
import { assertExists } from '@blocksuite/global/utils';
|
import { assertExists } from '@blocksuite/global/utils';
|
||||||
import type { InlineRootElement } from '@inline/inline-editor.js';
|
import type { InlineRootElement } from '@inline/inline-editor.js';
|
||||||
@@ -1180,7 +1184,7 @@ export async function assertBlockSelections(page: Page, paths: string[]) {
|
|||||||
if (!host) {
|
if (!host) {
|
||||||
throw new Error('editor-host host not found');
|
throw new Error('editor-host host not found');
|
||||||
}
|
}
|
||||||
return host.selection.filter('block');
|
return host.selection.value.filter(b => b.type === 'block');
|
||||||
});
|
});
|
||||||
const actualPaths = selections.map(selection => selection.blockId);
|
const actualPaths = selections.map(selection => selection.blockId);
|
||||||
expect(actualPaths).toEqual(paths);
|
expect(actualPaths).toEqual(paths);
|
||||||
@@ -1199,13 +1203,13 @@ export async function assertTextSelection(
|
|||||||
length: number;
|
length: number;
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
const selection = await page.evaluate(() => {
|
const selection = (await page.evaluate(() => {
|
||||||
const host = document.querySelector<EditorHost>('editor-host');
|
const host = document.querySelector<EditorHost>('editor-host');
|
||||||
if (!host) {
|
if (!host) {
|
||||||
throw new Error('editor-host host not found');
|
throw new Error('editor-host host not found');
|
||||||
}
|
}
|
||||||
return host.selection.find('text');
|
return host.selection.value.find(b => b.type === 'text');
|
||||||
});
|
})) as TextSelection | undefined;
|
||||||
|
|
||||||
if (!from && !to) {
|
if (!from && !to) {
|
||||||
expect(selection).toBeUndefined();
|
expect(selection).toBeUndefined();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WorkspaceImpl } from '@affine/core/modules/workspace/impls/workspace';
|
import { WorkspaceImpl } from '@affine/core/modules/workspace/impls/workspace';
|
||||||
import type {
|
import {
|
||||||
EditorHost,
|
type EditorHost,
|
||||||
TextRangePoint,
|
type TextRangePoint,
|
||||||
TextSelection,
|
TextSelection,
|
||||||
} from '@blocksuite/affine/block-std';
|
} from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
@@ -68,7 +68,7 @@ function processSnapshot(
|
|||||||
*/
|
*/
|
||||||
function processTextInSnapshot(snapshot: SliceSnapshot, host: EditorHost) {
|
function processTextInSnapshot(snapshot: SliceSnapshot, host: EditorHost) {
|
||||||
const { content } = snapshot;
|
const { content } = snapshot;
|
||||||
const text = host.selection.find('text');
|
const text = host.selection.find(TextSelection);
|
||||||
if (!content.length || !text) return;
|
if (!content.length || !text) return;
|
||||||
|
|
||||||
content.forEach(snapshot => processSnapshot(snapshot, text, host));
|
content.forEach(snapshot => processSnapshot(snapshot, text, host));
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ChatHistoryOrder } from '@affine/graphql';
|
import { ChatHistoryOrder } from '@affine/graphql';
|
||||||
import type {
|
import {
|
||||||
BlockSelection,
|
BlockSelection,
|
||||||
EditorHost,
|
type EditorHost,
|
||||||
TextSelection,
|
TextSelection,
|
||||||
} from '@blocksuite/affine/block-std';
|
} from '@blocksuite/affine/block-std';
|
||||||
import type {
|
import type {
|
||||||
@@ -198,8 +198,8 @@ const REPLACE_SELECTION = {
|
|||||||
icon: ReplaceIcon,
|
icon: ReplaceIcon,
|
||||||
title: 'Replace selection',
|
title: 'Replace selection',
|
||||||
showWhen: (host: EditorHost) => {
|
showWhen: (host: EditorHost) => {
|
||||||
const textSelection = host.selection.find('text');
|
const textSelection = host.selection.find(TextSelection);
|
||||||
const blockSelections = host.selection.filter('block');
|
const blockSelections = host.selection.filter(BlockSelection);
|
||||||
if (
|
if (
|
||||||
(!textSelection || textSelection.from.length === 0) &&
|
(!textSelection || textSelection.from.length === 0) &&
|
||||||
blockSelections?.length === 0
|
blockSelections?.length === 0
|
||||||
|
|||||||
+7
-3
@@ -1,4 +1,8 @@
|
|||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import {
|
||||||
|
BlockSelection,
|
||||||
|
type EditorHost,
|
||||||
|
TextSelection,
|
||||||
|
} from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
type AffineAIPanelWidgetConfig,
|
type AffineAIPanelWidgetConfig,
|
||||||
type AIItemGroupConfig,
|
type AIItemGroupConfig,
|
||||||
@@ -92,8 +96,8 @@ export class AskAIToolbarButton extends WithDisposable(LitElement) {
|
|||||||
this._panelRoot.style.visibility = text ? 'hidden' : 'visible';
|
this._panelRoot.style.visibility = text ? 'hidden' : 'visible';
|
||||||
};
|
};
|
||||||
|
|
||||||
const textSelection = this.host.selection.find('text');
|
const textSelection = this.host.selection.find(TextSelection);
|
||||||
const blockSelections = this.host.selection.filter('block');
|
const blockSelections = this.host.selection.filter(BlockSelection);
|
||||||
let lastBlockId: string | undefined;
|
let lastBlockId: string | undefined;
|
||||||
if (textSelection) {
|
if (textSelection) {
|
||||||
lastBlockId = textSelection.to?.blockId ?? textSelection.blockId;
|
lastBlockId = textSelection.to?.blockId ?? textSelection.blockId;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import { type EditorHost, TextSelection } from '@blocksuite/affine/block-std';
|
||||||
import type {
|
import type {
|
||||||
AffineAIPanelWidget,
|
AffineAIPanelWidget,
|
||||||
AffineAIPanelWidgetConfig,
|
AffineAIPanelWidgetConfig,
|
||||||
@@ -209,7 +209,7 @@ export function actionToHandler<T extends keyof BlockSuitePresets.AIActions>(
|
|||||||
|
|
||||||
export function handleInlineAskAIAction(host: EditorHost) {
|
export function handleInlineAskAIAction(host: EditorHost) {
|
||||||
const panel = getAIPanelWidget(host);
|
const panel = getAIPanelWidget(host);
|
||||||
const selection = host.selection.find('text');
|
const selection = host.selection.find(TextSelection);
|
||||||
const lastBlockPath = selection
|
const lastBlockPath = selection
|
||||||
? (selection.to?.blockId ?? selection.blockId)
|
? (selection.to?.blockId ?? selection.blockId)
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { EditorHost } from '@blocksuite/affine/block-std';
|
import { type EditorHost, TextSelection } from '@blocksuite/affine/block-std';
|
||||||
import {
|
import {
|
||||||
GfxBlockElementModel,
|
GfxBlockElementModel,
|
||||||
type GfxModel,
|
type GfxModel,
|
||||||
@@ -214,7 +214,7 @@ async function insertMarkdownAbove(host: EditorHost) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSelection(host: EditorHost) {
|
function getSelection(host: EditorHost) {
|
||||||
const textSelection = host.selection.find('text');
|
const textSelection = host.selection.find(TextSelection);
|
||||||
const mode = textSelection ? 'flat' : 'highest';
|
const mode = textSelection ? 'flat' : 'highest';
|
||||||
const { selectedBlocks } = getSelections(host, mode);
|
const { selectedBlocks } = getSelections(host, mode);
|
||||||
if (!selectedBlocks) return;
|
if (!selectedBlocks) return;
|
||||||
|
|||||||
+5
-1
@@ -9,6 +9,8 @@ const buttonOptions: AskAIButtonOptions = {
|
|||||||
panelWidth: 240,
|
panelWidth: 240,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
import { BlockSelection } from '@blocksuite/affine/block-std';
|
||||||
|
|
||||||
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
|
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
|
||||||
import { buildAICodeItemGroups } from '../../_common/config';
|
import { buildAICodeItemGroups } from '../../_common/config';
|
||||||
|
|
||||||
@@ -22,7 +24,9 @@ export function setupCodeToolbarAIEntry(codeToolbar: AffineCodeToolbarWidget) {
|
|||||||
action: () => {
|
action: () => {
|
||||||
const { selection } = host;
|
const { selection } = host;
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('block', { blockId: blockComponent.blockId }),
|
selection.create(BlockSelection, {
|
||||||
|
blockId: blockComponent.blockId,
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
render: item =>
|
render: item =>
|
||||||
|
|||||||
+7
-2
@@ -1,6 +1,9 @@
|
|||||||
import '../../_common/components/ask-ai-button';
|
import '../../_common/components/ask-ai-button';
|
||||||
|
|
||||||
import type { AffineImageToolbarWidget } from '@blocksuite/affine/blocks';
|
import {
|
||||||
|
type AffineImageToolbarWidget,
|
||||||
|
ImageSelection,
|
||||||
|
} from '@blocksuite/affine/blocks';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
|
|
||||||
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
|
import type { AskAIButtonOptions } from '../../_common/components/ask-ai-button';
|
||||||
@@ -26,7 +29,9 @@ export function setupImageToolbarAIEntry(
|
|||||||
action: () => {
|
action: () => {
|
||||||
const { selection } = host;
|
const { selection } = host;
|
||||||
selection.setGroup('note', [
|
selection.setGroup('note', [
|
||||||
selection.create('image', { blockId: blockComponent.blockId }),
|
selection.create(ImageSelection, {
|
||||||
|
blockId: blockComponent.blockId,
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
render: item =>
|
render: item =>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user