refactor(editor): edgeless element toolbar with new pattern (#10511)

This commit is contained in:
fundon
2025-03-18 15:36:25 +00:00
parent 3939cc1c52
commit cb37d25d7b
31 changed files with 838 additions and 367 deletions
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinAttachmentToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Attachment',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinBookmarkToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Bookmark',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinBrushToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Brush',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,51 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
import {
AddTextIcon,
ConnectorCIcon,
FlipDirectionIcon,
StartPointIcon,
} from '@blocksuite/icons/lit';
export const builtinConnectorToolbarConfig = {
actions: [
{
id: 'a.stroke-color',
tooltip: 'Stroke style',
run() {},
},
{
id: 'b.style',
tooltip: 'Style',
run() {},
},
{
id: 'c.start-point-style',
icon: StartPointIcon(),
tooltip: 'Start point style',
run() {},
},
{
id: 'd.flip-direction',
icon: FlipDirectionIcon(),
tooltip: 'Flip direction',
run() {},
},
{
id: 'e.end-point-style',
icon: StartPointIcon(),
tooltip: 'End point style',
run() {},
},
{
id: 'f.connector-shape',
icon: ConnectorCIcon(),
tooltip: 'Connector shape',
run() {},
},
{
id: 'g.add-text',
icon: AddTextIcon(),
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinEmbedToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Embed',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinFrameToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Frame',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinGroupToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Group',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinImageToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Image',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,84 @@
import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
import { BlockFlavourIdentifier } from '@blocksuite/block-std';
import type { ExtensionType } from '@blocksuite/store';
import { builtinAttachmentToolbarConfig } from './attachment';
import { builtinBookmarkToolbarConfig } from './bookmark';
import { builtinBrushToolbarConfig } from './brush';
import { builtinConnectorToolbarConfig } from './connector';
import { builtinEmbedToolbarConfig } from './embed';
import { builtinFrameToolbarConfig } from './frame';
import { builtinGroupToolbarConfig } from './group';
import { builtinImageToolbarConfig } from './image';
import { builtinMindmapToolbarConfig } from './mindmap';
import { builtinMiscToolbarConfig } from './misc';
import { builtinNoteToolbarConfig } from './note';
import { builtinShapeToolbarConfig } from './shape';
import { builtinTextToolbarConfig } from './text';
export const EdgelessElementToolbarExtension: ExtensionType[] = [
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:attachment'),
config: builtinAttachmentToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:bookmark'),
config: builtinBookmarkToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:image'),
config: builtinImageToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:brush'),
config: builtinBrushToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:connector'),
config: builtinConnectorToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:embed'),
config: builtinEmbedToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:frame'),
config: builtinFrameToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:group'),
config: builtinGroupToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:mindmap'),
config: builtinMindmapToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:note'),
config: builtinNoteToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:shape'),
config: builtinShapeToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:text'),
config: builtinTextToolbarConfig,
}),
ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:*'),
config: builtinMiscToolbarConfig,
}),
];
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinMindmapToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Mindmap',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,41 @@
import {
ActionPlacement,
type ToolbarModuleConfig,
} from '@blocksuite/affine-shared/services';
import {
ConnectorCIcon,
LockIcon,
ReleaseFromGroupIcon,
} from '@blocksuite/icons/lit';
export const builtinMiscToolbarConfig = {
actions: [
{
placement: ActionPlacement.Start,
id: 'a.release-from-group',
tooltip: 'Release from group',
icon: ReleaseFromGroupIcon(),
run() {},
},
{
placement: ActionPlacement.Start,
id: 'a.misc',
label: 'Misc',
run() {},
},
{
placement: ActionPlacement.End,
id: 'a.draw-connector',
icon: ConnectorCIcon(),
tooltip: 'Draw connector',
run() {},
},
{
placement: ActionPlacement.End,
id: 'b.lock',
icon: LockIcon(),
tooltip: 'Lock',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinNoteToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Note',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,39 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
import {
AddTextIcon,
ShapeIcon,
StyleGeneralIcon,
} from '@blocksuite/icons/lit';
export const builtinShapeToolbarConfig = {
actions: [
{
id: 'a.switch-type',
icon: ShapeIcon(),
tooltip: 'Switch type',
run() {},
},
{
id: 'b.style',
icon: StyleGeneralIcon(),
tooltip: 'Style',
run() {},
},
{
id: 'c.fill-color',
label: 'Fill color',
run() {},
},
{
id: 'd.border-style',
label: 'Border style',
run() {},
},
{
id: 'e.text',
icon: AddTextIcon(),
tooltip: 'Show add button or text menu',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -0,0 +1,11 @@
import type { ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
export const builtinTextToolbarConfig = {
actions: [
{
id: 'a.test',
label: 'Text',
run() {},
},
],
} as const satisfies ToolbarModuleConfig;
@@ -3,6 +3,7 @@ import { ConnectionOverlay } from '@blocksuite/affine-block-surface';
import { TextTool } from '@blocksuite/affine-gfx-text';
import type { ExtensionType } from '@blocksuite/store';
import { EdgelessElementToolbarExtension } from './configs/toolbar';
import { EdgelessRootBlockSpec } from './edgeless-root-spec.js';
import { BrushTool } from './gfx-tool/brush-tool.js';
import { ConnectorTool } from './gfx-tool/connector-tool.js';
@@ -40,7 +41,8 @@ export const EdgelessBuiltInManager: ExtensionType[] = [
MindMapIndicatorOverlay,
SnapManager,
EditPropsMiddlewareBuilder,
];
EdgelessElementToolbarExtension,
].flat();
export const EdgelessBuiltInSpecs: ExtensionType[] = [
EdgelessRootBlockSpec,
@@ -27,13 +27,6 @@ export function mountShapeTextEditor(
);
}
if (!shapeElement.text) {
const text = new Y.Text();
edgeless.std
.get(EdgelessCRUDIdentifier)
.updateElement(shapeElement.id, { text });
}
const updatedElement = edgeless.service.crud.getElementById(shapeElement.id);
if (!(updatedElement instanceof ShapeElementModel)) {
@@ -41,17 +34,25 @@ export function mountShapeTextEditor(
return;
}
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [shapeElement.id],
editing: true,
});
if (!shapeElement.text) {
const text = new Y.Text();
edgeless.std
.get(EdgelessCRUDIdentifier)
.updateElement(shapeElement.id, { text });
}
const shapeEditor = new EdgelessShapeTextEditor();
shapeEditor.element = updatedElement;
shapeEditor.edgeless = edgeless;
shapeEditor.mountEditor = mountShapeTextEditor;
edgeless.mountElm.append(shapeEditor);
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [shapeElement.id],
editing: true,
});
}
export function mountFrameTitleEditor(
@@ -65,16 +66,17 @@ export function mountFrameTitleEditor(
);
}
const frameEditor = new EdgelessFrameTitleEditor();
frameEditor.frameModel = frame;
frameEditor.edgeless = edgeless;
edgeless.mountElm.append(frameEditor);
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [frame.id],
editing: true,
});
const frameEditor = new EdgelessFrameTitleEditor();
frameEditor.frameModel = frame;
frameEditor.edgeless = edgeless;
edgeless.mountElm.append(frameEditor);
}
export function mountGroupTitleEditor(
@@ -88,16 +90,17 @@ export function mountGroupTitleEditor(
);
}
const groupEditor = new EdgelessGroupTitleEditor();
groupEditor.group = group;
groupEditor.edgeless = edgeless;
edgeless.mountElm.append(groupEditor);
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [group.id],
editing: true,
});
const groupEditor = new EdgelessGroupTitleEditor();
groupEditor.group = group;
groupEditor.edgeless = edgeless;
edgeless.mountElm.append(groupEditor);
}
export function mountConnectorLabelEditor(
@@ -112,6 +115,12 @@ export function mountConnectorLabelEditor(
);
}
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [connector.id],
editing: true,
});
if (!connector.text) {
const text = new Y.Text();
const labelOffset = connector.labelOffset;
@@ -143,9 +152,4 @@ export function mountConnectorLabelEditor(
editor.inlineEditor?.focusEnd();
})
.catch(console.error);
edgeless.gfx.tool.setTool('default');
edgeless.gfx.selection.set({
elements: [connector.id],
editing: true,
});
}