mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-21 03:56:23 +08:00
refactor(editor): gfx text package (#10738)
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*",
|
||||
"@blocksuite/affine-fragment-frame-panel": "workspace:*",
|
||||
"@blocksuite/affine-fragment-outline": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
@@ -104,6 +105,7 @@
|
||||
"./fragments/doc-title": "./src/fragments/doc-title.ts",
|
||||
"./fragments/frame-panel": "./src/fragments/frame-panel.ts",
|
||||
"./fragments/outline": "./src/fragments/outline.ts",
|
||||
"./gfx/text": "./src/gfx/text.ts",
|
||||
"./components/block-selection": "./src/components/block-selection.ts",
|
||||
"./components/block-zero-width": "./src/components/block-zero-width.ts",
|
||||
"./components/caption": "./src/components/caption.ts",
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-gfx-text';
|
||||
@@ -30,6 +30,7 @@
|
||||
"@blocksuite/affine-block-table": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
+2
-4
@@ -4,6 +4,7 @@ import {
|
||||
EdgelessCRUDIdentifier,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { FontFamilyIcon } from '@blocksuite/affine-components/icons';
|
||||
import { mountTextElementEditor } from '@blocksuite/affine-gfx-text';
|
||||
import type {
|
||||
Connection,
|
||||
ConnectorElementModel,
|
||||
@@ -56,10 +57,7 @@ import {
|
||||
SHAPE_OVERLAY_HEIGHT,
|
||||
SHAPE_OVERLAY_WIDTH,
|
||||
} from '../../utils/consts.js';
|
||||
import {
|
||||
mountShapeTextEditor,
|
||||
mountTextElementEditor,
|
||||
} from '../../utils/text.js';
|
||||
import { mountShapeTextEditor } from '../../utils/text.js';
|
||||
import { ShapeComponentConfig } from '../toolbar/shape/shape-menu-config.js';
|
||||
import {
|
||||
type AUTO_COMPLETE_TARGET_TYPE,
|
||||
|
||||
+1
-1
@@ -2,6 +2,7 @@ import { addAttachments } from '@blocksuite/affine-block-attachment';
|
||||
import { insertEdgelessTextCommand } from '@blocksuite/affine-block-edgeless-text';
|
||||
import { addImages } from '@blocksuite/affine-block-image';
|
||||
import { CanvasElementType } from '@blocksuite/affine-block-surface';
|
||||
import { mountTextElementEditor } from '@blocksuite/affine-gfx-text';
|
||||
import {
|
||||
MAX_IMAGE_WIDTH,
|
||||
type MindmapStyle,
|
||||
@@ -18,7 +19,6 @@ import * as Y from 'yjs';
|
||||
|
||||
import type { EdgelessRootBlockComponent } from '../../../edgeless-root-block.js';
|
||||
import type { EdgelessRootService } from '../../../edgeless-root-service.js';
|
||||
import { mountTextElementEditor } from '../../../utils/text.js';
|
||||
|
||||
export type ConfigProperty = 'x' | 'y' | 'r' | 's' | 'z' | 'o';
|
||||
export type ConfigState = 'default' | 'active' | 'hover' | 'next';
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
PresentTool,
|
||||
} from '@blocksuite/affine-block-frame';
|
||||
import { ConnectionOverlay } from '@blocksuite/affine-block-surface';
|
||||
import { TextTool } from '@blocksuite/affine-gfx-text';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { EdgelessRootBlockSpec } from './edgeless-root-spec.js';
|
||||
@@ -19,7 +20,6 @@ import { NoteTool } from './gfx-tool/note-tool.js';
|
||||
import { PanTool } from './gfx-tool/pan-tool.js';
|
||||
import { ShapeTool } from './gfx-tool/shape-tool.js';
|
||||
import { TemplateTool } from './gfx-tool/template-tool.js';
|
||||
import { TextTool } from './gfx-tool/text-tool.js';
|
||||
import { EditPropsMiddlewareBuilder } from './middlewares/base.js';
|
||||
import { SnapManager } from './utils/snap-manager.js';
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
isNoteBlock,
|
||||
OverlayIdentifier,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { addText, mountTextElementEditor } from '@blocksuite/affine-gfx-text';
|
||||
import type {
|
||||
EdgelessTextBlockModel,
|
||||
FrameBlockModel,
|
||||
@@ -55,12 +56,10 @@ import { calPanDelta } from '../utils/panning-utils.js';
|
||||
import { isCanvasElement, isEdgelessTextBlock } from '../utils/query.js';
|
||||
import type { SnapManager } from '../utils/snap-manager.js';
|
||||
import {
|
||||
addText,
|
||||
mountConnectorLabelEditor,
|
||||
mountFrameTitleEditor,
|
||||
mountGroupTitleEditor,
|
||||
mountShapeTextEditor,
|
||||
mountTextElementEditor,
|
||||
} from '../utils/text.js';
|
||||
import { CanvasElementEventExt } from './default-tool-ext/event-ext.js';
|
||||
import type { DefaultToolExt } from './default-tool-ext/ext.js';
|
||||
|
||||
@@ -9,4 +9,3 @@ export { NoteTool, type NoteToolOption } from './note-tool.js';
|
||||
export { PanTool, type PanToolOption } from './pan-tool.js';
|
||||
export { ShapeTool, type ShapeToolOption } from './shape-tool.js';
|
||||
export { TemplateTool } from './template-tool.js';
|
||||
export { TextTool } from './text-tool.js';
|
||||
|
||||
@@ -1,16 +1,10 @@
|
||||
import {
|
||||
CanvasElementType,
|
||||
EdgelessCRUDIdentifier,
|
||||
type IModelCoord,
|
||||
TextUtils,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
||||
import type {
|
||||
ConnectorElementModel,
|
||||
FrameBlockModel,
|
||||
GroupElementModel,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { ShapeElementModel, TextElementModel } from '@blocksuite/affine-model';
|
||||
import type { PointerEventState } from '@blocksuite/block-std';
|
||||
import { ShapeElementModel } from '@blocksuite/affine-model';
|
||||
import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions';
|
||||
import type { IVec } from '@blocksuite/global/gfx';
|
||||
import { Bound } from '@blocksuite/global/gfx';
|
||||
@@ -20,47 +14,8 @@ import { EdgelessConnectorLabelEditor } from '../components/text/edgeless-connec
|
||||
import { EdgelessFrameTitleEditor } from '../components/text/edgeless-frame-title-editor.js';
|
||||
import { EdgelessGroupTitleEditor } from '../components/text/edgeless-group-title-editor.js';
|
||||
import { EdgelessShapeTextEditor } from '../components/text/edgeless-shape-text-editor.js';
|
||||
import { EdgelessTextEditor } from '../components/text/edgeless-text-editor.js';
|
||||
import type { EdgelessRootBlockComponent } from '../edgeless-root-block.js';
|
||||
|
||||
export function mountTextElementEditor(
|
||||
textElement: TextElementModel,
|
||||
edgeless: EdgelessRootBlockComponent,
|
||||
focusCoord?: IModelCoord
|
||||
) {
|
||||
if (!edgeless.mountElm) {
|
||||
throw new BlockSuiteError(
|
||||
ErrorCode.ValueNotExists,
|
||||
"edgeless block's mount point does not exist"
|
||||
);
|
||||
}
|
||||
|
||||
let cursorIndex = textElement.text.length;
|
||||
if (focusCoord) {
|
||||
cursorIndex = Math.min(
|
||||
TextUtils.getCursorByCoord(textElement, focusCoord),
|
||||
cursorIndex
|
||||
);
|
||||
}
|
||||
|
||||
const textEditor = new EdgelessTextEditor();
|
||||
textEditor.edgeless = edgeless;
|
||||
textEditor.element = textElement;
|
||||
|
||||
edgeless.append(textEditor);
|
||||
textEditor.updateComplete
|
||||
.then(() => {
|
||||
textEditor.inlineEditor?.focusIndex(cursorIndex);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
edgeless.gfx.tool.setTool('default');
|
||||
edgeless.gfx.selection.set({
|
||||
elements: [textElement.id],
|
||||
editing: true,
|
||||
});
|
||||
}
|
||||
|
||||
export function mountShapeTextEditor(
|
||||
shapeElement: ShapeElementModel,
|
||||
edgeless: EdgelessRootBlockComponent
|
||||
@@ -145,39 +100,6 @@ export function mountGroupTitleEditor(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Canvas Text has been deprecated
|
||||
*/
|
||||
export function addText(
|
||||
edgeless: EdgelessRootBlockComponent,
|
||||
event: PointerEventState
|
||||
) {
|
||||
const [x, y] = edgeless.service.viewport.toModelCoord(event.x, event.y);
|
||||
const selected = edgeless.service.gfx.getElementByPoint(x, y);
|
||||
|
||||
if (!selected) {
|
||||
const [modelX, modelY] = edgeless.service.viewport.toModelCoord(
|
||||
event.x,
|
||||
event.y
|
||||
);
|
||||
const id = edgeless.std
|
||||
.get(EdgelessCRUDIdentifier)
|
||||
.addElement(CanvasElementType.TEXT, {
|
||||
xywh: new Bound(modelX, modelY, 32, 32).serialize(),
|
||||
text: new Y.Text(),
|
||||
});
|
||||
if (!id) return;
|
||||
edgeless.doc.captureSync();
|
||||
const textElement = edgeless.service.crud.getElementById(id);
|
||||
if (!textElement) return;
|
||||
if (textElement instanceof TextElementModel) {
|
||||
mountTextElementEditor(textElement, edgeless);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function mountConnectorLabelEditor(
|
||||
connector: ConnectorElementModel,
|
||||
edgeless: EdgelessRootBlockComponent,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { effects as gfxCanvasTextEffects } from '@blocksuite/affine-gfx-text/effects';
|
||||
|
||||
import { EdgelessAutoCompletePanel } from './edgeless/components/auto-complete/auto-complete-panel.js';
|
||||
import { EdgelessAutoComplete } from './edgeless/components/auto-complete/edgeless-auto-complete.js';
|
||||
import { EdgelessToolIconButton } from './edgeless/components/buttons/tool-icon-button.js';
|
||||
@@ -36,7 +38,6 @@ import { EdgelessConnectorLabelEditor } from './edgeless/components/text/edgeles
|
||||
import { EdgelessFrameTitleEditor } from './edgeless/components/text/edgeless-frame-title-editor.js';
|
||||
import { EdgelessGroupTitleEditor } from './edgeless/components/text/edgeless-group-title-editor.js';
|
||||
import { EdgelessShapeTextEditor } from './edgeless/components/text/edgeless-shape-text-editor.js';
|
||||
import { EdgelessTextEditor } from './edgeless/components/text/edgeless-text-editor.js';
|
||||
import { EdgelessBrushMenu } from './edgeless/components/toolbar/brush/brush-menu.js';
|
||||
import { EdgelessBrushToolButton } from './edgeless/components/toolbar/brush/brush-tool-button.js';
|
||||
import { EdgelessSlideMenu } from './edgeless/components/toolbar/common/slide-menu.js';
|
||||
@@ -122,6 +123,7 @@ export function effects() {
|
||||
|
||||
// Register components by category
|
||||
registerRootComponents();
|
||||
registerGfxEffects();
|
||||
registerWidgets();
|
||||
registerEdgelessToolbarComponents();
|
||||
registerEdgelessPanelComponents();
|
||||
@@ -139,6 +141,10 @@ function registerRootComponents() {
|
||||
);
|
||||
}
|
||||
|
||||
function registerGfxEffects() {
|
||||
gfxCanvasTextEffects();
|
||||
}
|
||||
|
||||
function registerWidgets() {
|
||||
customElements.define(AFFINE_INNER_MODAL_WIDGET, AffineInnerModalWidget);
|
||||
customElements.define(AFFINE_MODAL_WIDGET, AffineModalWidget);
|
||||
@@ -258,7 +264,6 @@ function registerEdgelessEditorComponents() {
|
||||
'edgeless-frame-title-editor',
|
||||
EdgelessFrameTitleEditor
|
||||
);
|
||||
customElements.define('edgeless-text-editor', EdgelessTextEditor);
|
||||
}
|
||||
|
||||
function registerMiscComponents() {
|
||||
@@ -348,7 +353,6 @@ declare global {
|
||||
'edgeless-frame-title-editor': EdgelessFrameTitleEditor;
|
||||
'edgeless-group-title-editor': EdgelessGroupTitleEditor;
|
||||
'edgeless-shape-text-editor': EdgelessShapeTextEditor;
|
||||
'edgeless-text-editor': EdgelessTextEditor;
|
||||
'edgeless-toolbar-widget': EdgelessToolbarWidget;
|
||||
'presentation-toolbar': PresentationToolbar;
|
||||
'edgeless-brush-menu': EdgelessBrushMenu;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
{ "path": "../block-table" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../fragments/fragment-doc-title" },
|
||||
{ "path": "../../gfx/text" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "@blocksuite/affine-gfx-text",
|
||||
"description": "Gfx text for BlockSuite.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test:unit": "nx vite:test --run --passWithNoTests",
|
||||
"test:unit:coverage": "nx vite:test --run --coverage",
|
||||
"test:e2e": "playwright test"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"keywords": [],
|
||||
"author": "toeverything",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-block-edgeless-text": "workspace:*",
|
||||
"@blocksuite/affine-block-surface": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/block-std": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.1",
|
||||
"@blocksuite/inline": "workspace:*",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"lit": "^3.2.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"minimatch": "^10.0.1",
|
||||
"yjs": "^13.6.21",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./effects": "./src/effects.ts"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist",
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
}
|
||||
+25
-20
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
EdgelessCRUDIdentifier,
|
||||
getSurfaceBlock,
|
||||
TextUtils,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import type { TextElementModel } from '@blocksuite/affine-model';
|
||||
@@ -7,21 +8,26 @@ import type { RichText } from '@blocksuite/affine-rich-text';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { getSelectedRect } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
type BlockStdScope,
|
||||
RANGE_SYNC_EXCLUDE_ATTR,
|
||||
ShadowlessElement,
|
||||
stdContext,
|
||||
} from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { Bound, toRadian, Vec } from '@blocksuite/global/gfx';
|
||||
import { WithDisposable } from '@blocksuite/global/lit';
|
||||
import { consume } from '@lit/context';
|
||||
import { css, html, nothing } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import type { EdgelessRootBlockComponent } from '../../edgeless-root-block.js';
|
||||
import { deleteElements } from '../../utils/crud.js';
|
||||
|
||||
export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
get crud() {
|
||||
return this.edgeless.std.get(EdgelessCRUDIdentifier);
|
||||
return this.std.get(EdgelessCRUDIdentifier);
|
||||
}
|
||||
|
||||
get gfx() {
|
||||
return this.std.get(GfxControllerIdentifier);
|
||||
}
|
||||
|
||||
static BORDER_WIDTH = 1;
|
||||
@@ -71,10 +77,9 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
private _keeping = false;
|
||||
|
||||
private readonly _updateRect = () => {
|
||||
const edgeless = this.edgeless;
|
||||
const element = this.element;
|
||||
|
||||
if (!edgeless || !element || !this.inlineEditorContainer) return;
|
||||
if (!element || !this.inlineEditorContainer) return;
|
||||
|
||||
const newWidth = this.inlineEditorContainer.scrollWidth;
|
||||
const newHeight = this.inlineEditorContainer.scrollHeight;
|
||||
@@ -153,10 +158,6 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
|
||||
override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
if (!this.edgeless) {
|
||||
console.error('edgeless is not set.');
|
||||
return;
|
||||
}
|
||||
if (!this.element) {
|
||||
console.error('text element is not set.');
|
||||
return;
|
||||
@@ -166,9 +167,13 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
}
|
||||
|
||||
override firstUpdated(): void {
|
||||
const edgeless = this.edgeless;
|
||||
const element = this.element;
|
||||
const { dispatcher } = this.edgeless;
|
||||
const dispatcher = this.std.event;
|
||||
const surface = getSurfaceBlock(this.std.store);
|
||||
if (!surface) {
|
||||
console.error('surface block is not found.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateComplete
|
||||
.then(() => {
|
||||
@@ -179,13 +184,13 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
});
|
||||
|
||||
this.disposables.add(
|
||||
edgeless.service.surface.elementUpdated.on(({ id }) => {
|
||||
surface.elementUpdated.on(({ id }) => {
|
||||
if (id === element.id) this.requestUpdate();
|
||||
})
|
||||
);
|
||||
|
||||
this.disposables.add(
|
||||
edgeless.service.viewport.viewportUpdated.on(() => {
|
||||
this.gfx.viewport.viewportUpdated.on(() => {
|
||||
this.requestUpdate();
|
||||
})
|
||||
);
|
||||
@@ -197,10 +202,10 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
element.display = true;
|
||||
|
||||
if (element.text.length === 0) {
|
||||
deleteElements(edgeless, [element]);
|
||||
this.crud.deleteElements([element]);
|
||||
}
|
||||
|
||||
edgeless.service.selection.set({
|
||||
this.gfx.selection.set({
|
||||
elements: [],
|
||||
editing: false,
|
||||
});
|
||||
@@ -346,7 +351,7 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
);
|
||||
const rect = getSelectedRect([this.element]);
|
||||
|
||||
const { translateX, translateY, zoom } = this.edgeless.service.viewport;
|
||||
const { translateX, translateY, zoom } = this.gfx.viewport;
|
||||
const [visualX, visualY] = this.getVisualPosition(this.element);
|
||||
const containerOffset = this.getContainerOffset();
|
||||
const transformOperation = [
|
||||
@@ -358,7 +363,7 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
];
|
||||
|
||||
const isEmpty = !text.length && !this._isComposition;
|
||||
const color = this.edgeless.std
|
||||
const color = this.std
|
||||
.get(ThemeProvider)
|
||||
.generateColorProperty(this.element.color, '#000000');
|
||||
|
||||
@@ -404,8 +409,8 @@ export class EdgelessTextEditor extends WithDisposable(ShadowlessElement) {
|
||||
this._keeping = keeping;
|
||||
}
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor edgeless!: EdgelessRootBlockComponent;
|
||||
@consume({ context: stdContext })
|
||||
accessor std!: BlockStdScope;
|
||||
|
||||
@property({ attribute: false })
|
||||
accessor element!: TextElementModel;
|
||||
@@ -0,0 +1,11 @@
|
||||
import { EdgelessTextEditor } from './edgeless-text-editor';
|
||||
|
||||
export function effects() {
|
||||
customElements.define('edgeless-text-editor', EdgelessTextEditor);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'edgeless-text-editor': EdgelessTextEditor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './edgeless-text-editor';
|
||||
export * from './mount-text-editor';
|
||||
export * from './tool';
|
||||
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
CanvasElementType,
|
||||
EdgelessCRUDIdentifier,
|
||||
type IModelCoord,
|
||||
TextUtils,
|
||||
} from '@blocksuite/affine-block-surface';
|
||||
import { TextElementModel } from '@blocksuite/affine-model';
|
||||
import type { BlockComponent, PointerEventState } from '@blocksuite/block-std';
|
||||
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
|
||||
import { Bound } from '@blocksuite/global/gfx';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import { EdgelessTextEditor } from './edgeless-text-editor';
|
||||
|
||||
export function mountTextElementEditor(
|
||||
textElement: TextElementModel,
|
||||
edgeless: BlockComponent,
|
||||
focusCoord?: IModelCoord
|
||||
) {
|
||||
let cursorIndex = textElement.text.length;
|
||||
if (focusCoord) {
|
||||
cursorIndex = Math.min(
|
||||
TextUtils.getCursorByCoord(textElement, focusCoord),
|
||||
cursorIndex
|
||||
);
|
||||
}
|
||||
|
||||
const textEditor = new EdgelessTextEditor();
|
||||
textEditor.element = textElement;
|
||||
|
||||
edgeless.append(textEditor);
|
||||
textEditor.updateComplete
|
||||
.then(() => {
|
||||
textEditor.inlineEditor?.focusIndex(cursorIndex);
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
const gfx = edgeless.std.get(GfxControllerIdentifier);
|
||||
|
||||
// @ts-expect-error TODO: refactor gfx tool
|
||||
gfx.tool.setTool('default');
|
||||
gfx.selection.set({
|
||||
elements: [textElement.id],
|
||||
editing: true,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*
|
||||
* Canvas Text has been deprecated
|
||||
*/
|
||||
export function addText(edgeless: BlockComponent, event: PointerEventState) {
|
||||
const gfx = edgeless.std.get(GfxControllerIdentifier);
|
||||
const crud = edgeless.std.get(EdgelessCRUDIdentifier);
|
||||
const [x, y] = gfx.viewport.toModelCoord(event.x, event.y);
|
||||
const selected = gfx.getElementByPoint(x, y);
|
||||
|
||||
if (!selected) {
|
||||
const [modelX, modelY] = gfx.viewport.toModelCoord(event.x, event.y);
|
||||
|
||||
const id = edgeless.std
|
||||
.get(EdgelessCRUDIdentifier)
|
||||
.addElement(CanvasElementType.TEXT, {
|
||||
xywh: new Bound(modelX, modelY, 32, 32).serialize(),
|
||||
text: new Y.Text(),
|
||||
});
|
||||
if (!id) return;
|
||||
|
||||
edgeless.doc.captureSync();
|
||||
const textElement = crud.getElementById(id);
|
||||
if (!textElement) return;
|
||||
if (textElement instanceof TextElementModel) {
|
||||
mountTextElementEditor(textElement, edgeless);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-7
@@ -9,10 +9,9 @@ import { BaseTool, type GfxController } from '@blocksuite/block-std/gfx';
|
||||
import { Bound } from '@blocksuite/global/gfx';
|
||||
import * as Y from 'yjs';
|
||||
|
||||
import type { EdgelessRootBlockComponent } from '../edgeless-root-block.js';
|
||||
import { mountTextElementEditor } from '../utils/text.js';
|
||||
import { mountTextElementEditor } from './mount-text-editor';
|
||||
|
||||
export function addText(gfx: GfxController, event: PointerEventState) {
|
||||
function addText(gfx: GfxController, event: PointerEventState) {
|
||||
const [x, y] = gfx.viewport.toModelCoord(event.x, event.y);
|
||||
const selected = gfx.getElementByPoint(x, y);
|
||||
|
||||
@@ -31,10 +30,11 @@ export function addText(gfx: GfxController, event: PointerEventState) {
|
||||
gfx.doc.captureSync();
|
||||
const textElement = gfx.getElementById(id) as TextElementModel;
|
||||
const edgelessView = gfx.std.view.getBlock(gfx.std.store.root!.id);
|
||||
mountTextElementEditor(
|
||||
textElement,
|
||||
edgelessView as EdgelessRootBlockComponent
|
||||
);
|
||||
if (!edgelessView) {
|
||||
console.error('edgeless view is not found.');
|
||||
return;
|
||||
}
|
||||
mountTextElementEditor(textElement, edgelessView);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ export class TextTool extends BaseTool {
|
||||
if (textFlag) {
|
||||
const [x, y] = this.gfx.viewport.toModelCoord(e.x, e.y);
|
||||
this.gfx.std.command.exec(insertEdgelessTextCommand, { x, y });
|
||||
// @ts-expect-error TODO: refactor gfx tool
|
||||
this.gfx.tool.setTool('default');
|
||||
} else {
|
||||
addText(this.gfx, e);
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../blocks/block-edgeless-text" },
|
||||
{ "path": "../../blocks/block-surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../../framework/block-std" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/inline" },
|
||||
{ "path": "../../../framework/store" }
|
||||
]
|
||||
}
|
||||
@@ -297,6 +297,7 @@ export const PackageList = [
|
||||
'blocksuite/affine/blocks/block-table',
|
||||
'blocksuite/affine/components',
|
||||
'blocksuite/affine/fragments/fragment-doc-title',
|
||||
'blocksuite/affine/gfx/text',
|
||||
'blocksuite/affine/model',
|
||||
'blocksuite/affine/rich-text',
|
||||
'blocksuite/affine/shared',
|
||||
@@ -429,6 +430,22 @@ export const PackageList = [
|
||||
'blocksuite/framework/store',
|
||||
],
|
||||
},
|
||||
{
|
||||
location: 'blocksuite/affine/gfx/text',
|
||||
name: '@blocksuite/affine-gfx-text',
|
||||
workspaceDependencies: [
|
||||
'blocksuite/affine/blocks/block-edgeless-text',
|
||||
'blocksuite/affine/blocks/block-surface',
|
||||
'blocksuite/affine/components',
|
||||
'blocksuite/affine/model',
|
||||
'blocksuite/affine/rich-text',
|
||||
'blocksuite/affine/shared',
|
||||
'blocksuite/framework/block-std',
|
||||
'blocksuite/framework/global',
|
||||
'blocksuite/framework/inline',
|
||||
'blocksuite/framework/store',
|
||||
],
|
||||
},
|
||||
{
|
||||
location: 'blocksuite/affine/model',
|
||||
name: '@blocksuite/affine-model',
|
||||
@@ -923,6 +940,7 @@ export type PackageName =
|
||||
| '@blocksuite/affine-fragment-doc-title'
|
||||
| '@blocksuite/affine-fragment-frame-panel'
|
||||
| '@blocksuite/affine-fragment-outline'
|
||||
| '@blocksuite/affine-gfx-text'
|
||||
| '@blocksuite/affine-model'
|
||||
| '@blocksuite/affine-rich-text'
|
||||
| '@blocksuite/affine-shared'
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
{ "path": "./blocksuite/affine/fragments/fragment-doc-title" },
|
||||
{ "path": "./blocksuite/affine/fragments/fragment-frame-panel" },
|
||||
{ "path": "./blocksuite/affine/fragments/fragment-outline" },
|
||||
{ "path": "./blocksuite/affine/gfx/text" },
|
||||
{ "path": "./blocksuite/affine/model" },
|
||||
{ "path": "./blocksuite/affine/rich-text" },
|
||||
{ "path": "./blocksuite/affine/shared" },
|
||||
|
||||
@@ -2617,6 +2617,7 @@ __metadata:
|
||||
"@blocksuite/affine-block-table": "workspace:*"
|
||||
"@blocksuite/affine-components": "workspace:*"
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*"
|
||||
"@blocksuite/affine-gfx-text": "workspace:*"
|
||||
"@blocksuite/affine-model": "workspace:*"
|
||||
"@blocksuite/affine-rich-text": "workspace:*"
|
||||
"@blocksuite/affine-shared": "workspace:*"
|
||||
@@ -2841,6 +2842,33 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@blocksuite/affine-gfx-text@workspace:*, @blocksuite/affine-gfx-text@workspace:blocksuite/affine/gfx/text":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@blocksuite/affine-gfx-text@workspace:blocksuite/affine/gfx/text"
|
||||
dependencies:
|
||||
"@blocksuite/affine-block-edgeless-text": "workspace:*"
|
||||
"@blocksuite/affine-block-surface": "workspace:*"
|
||||
"@blocksuite/affine-components": "workspace:*"
|
||||
"@blocksuite/affine-model": "workspace:*"
|
||||
"@blocksuite/affine-rich-text": "workspace:*"
|
||||
"@blocksuite/affine-shared": "workspace:*"
|
||||
"@blocksuite/block-std": "workspace:*"
|
||||
"@blocksuite/global": "workspace:*"
|
||||
"@blocksuite/icons": "npm:^2.2.1"
|
||||
"@blocksuite/inline": "workspace:*"
|
||||
"@blocksuite/store": "workspace:*"
|
||||
"@lit/context": "npm:^1.1.2"
|
||||
"@preact/signals-core": "npm:^1.8.0"
|
||||
"@toeverything/theme": "npm:^1.1.12"
|
||||
"@types/lodash-es": "npm:^4.17.12"
|
||||
lit: "npm:^3.2.0"
|
||||
lodash-es: "npm:^4.17.21"
|
||||
minimatch: "npm:^10.0.1"
|
||||
yjs: "npm:^13.6.21"
|
||||
zod: "npm:^3.23.8"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@blocksuite/affine-model@workspace:*, @blocksuite/affine-model@workspace:blocksuite/affine/model":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@blocksuite/affine-model@workspace:blocksuite/affine/model"
|
||||
@@ -3108,6 +3136,7 @@ __metadata:
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*"
|
||||
"@blocksuite/affine-fragment-frame-panel": "workspace:*"
|
||||
"@blocksuite/affine-fragment-outline": "workspace:*"
|
||||
"@blocksuite/affine-gfx-text": "workspace:*"
|
||||
"@blocksuite/affine-model": "workspace:*"
|
||||
"@blocksuite/affine-rich-text": "workspace:*"
|
||||
"@blocksuite/affine-shared": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user