diff --git a/blocksuite/affine/blocks/block-frame/package.json b/blocksuite/affine/blocks/block-frame/package.json index c99eb8560c..98db6cb9e5 100644 --- a/blocksuite/affine/blocks/block-frame/package.json +++ b/blocksuite/affine/blocks/block-frame/package.json @@ -14,8 +14,10 @@ "@blocksuite/affine-components": "workspace:*", "@blocksuite/affine-model": "workspace:*", "@blocksuite/affine-shared": "workspace:*", + "@blocksuite/affine-widget-frame-title": "workspace:*", "@blocksuite/block-std": "workspace:*", "@blocksuite/global": "workspace:*", + "@blocksuite/icons": "^2.2.6", "@blocksuite/inline": "workspace:*", "@blocksuite/store": "workspace:*", "@floating-ui/dom": "^1.6.13", diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/element-transform/frame-highlight-manager.ts b/blocksuite/affine/blocks/block-frame/src/frame-highlight-manager.ts similarity index 98% rename from blocksuite/affine/blocks/block-root/src/edgeless/element-transform/frame-highlight-manager.ts rename to blocksuite/affine/blocks/block-frame/src/frame-highlight-manager.ts index 28f8322aff..a15f359e00 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/element-transform/frame-highlight-manager.ts +++ b/blocksuite/affine/blocks/block-frame/src/frame-highlight-manager.ts @@ -1,8 +1,3 @@ -import { - type EdgelessFrameManager, - type FrameOverlay, - isFrameBlock, -} from '@blocksuite/affine-block-frame'; import { OverlayIdentifier } from '@blocksuite/affine-block-surface'; import { type FrameBlockModel, @@ -18,6 +13,12 @@ import { TransformExtension, } from '@blocksuite/block-std/gfx'; +import { + type EdgelessFrameManager, + type FrameOverlay, + isFrameBlock, +} from './frame-manager'; + export class FrameHighlightManager extends TransformExtension { static override key = 'frame-highlight-manager'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/frame-tool.ts b/blocksuite/affine/blocks/block-frame/src/frame-tool.ts similarity index 95% rename from blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/frame-tool.ts rename to blocksuite/affine/blocks/block-frame/src/frame-tool.ts index 3bc9428825..1509b0fbba 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/frame-tool.ts +++ b/blocksuite/affine/blocks/block-frame/src/frame-tool.ts @@ -1,7 +1,3 @@ -import { - EdgelessFrameManagerIdentifier, - type FrameOverlay, -} from '@blocksuite/affine-block-frame'; import { OverlayIdentifier } from '@blocksuite/affine-block-surface'; import type { FrameBlockModel } from '@blocksuite/affine-model'; import { @@ -15,6 +11,11 @@ import { Bound, Vec } from '@blocksuite/global/gfx'; import { Text } from '@blocksuite/store'; import * as Y from 'yjs'; +import { + EdgelessFrameManagerIdentifier, + type FrameOverlay, +} from './frame-manager'; + export class FrameTool extends BaseTool { static override toolName = 'frame'; @@ -40,6 +41,7 @@ export class FrameTool extends BaseTool { this.doc.transact(() => { frame.pop('xywh'); }); + // @ts-expect-error TODO: refactor gfx tool this.gfx.tool.setTool('default'); this.gfx.selection.set({ elements: [frame.id], @@ -106,9 +108,3 @@ export class FrameTool extends BaseTool { this._startPoint = this._toModelCoord(point); } } - -declare module '@blocksuite/block-std/gfx' { - interface GfxToolsMap { - frame: FrameTool; - } -} diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/frame.ts b/blocksuite/affine/blocks/block-frame/src/frame-toolbar.ts similarity index 82% rename from blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/frame.ts rename to blocksuite/affine/blocks/block-frame/src/frame-toolbar.ts index a8e4abdfe7..57e8c897da 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/frame.ts +++ b/blocksuite/affine/blocks/block-frame/src/frame-toolbar.ts @@ -1,4 +1,3 @@ -import { EdgelessFrameManagerIdentifier } from '@blocksuite/affine-block-frame'; import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import { packColor, @@ -9,6 +8,7 @@ import { DEFAULT_NOTE_HEIGHT, DefaultTheme, FrameBlockModel, + FrameBlockSchema, NoteBlockModel, NoteBlockSchema, NoteDisplayMode, @@ -16,6 +16,7 @@ import { SurfaceRefBlockSchema, } from '@blocksuite/affine-model'; import { + type ToolbarContext, type ToolbarModuleConfig, ToolbarModuleExtension, } from '@blocksuite/affine-shared/services'; @@ -23,14 +24,25 @@ import { getMostCommonResolvedValue, matchModels, } from '@blocksuite/affine-shared/utils'; -import { BlockFlavourIdentifier } from '@blocksuite/block-std'; +import { mountFrameTitleEditor } from '@blocksuite/affine-widget-frame-title'; +import { + type BlockComponent, + BlockFlavourIdentifier, +} from '@blocksuite/block-std'; +import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { Bound } from '@blocksuite/global/gfx'; import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit'; import type { ExtensionType } from '@blocksuite/store'; import { html } from 'lit'; -import { mountFrameTitleEditor } from '../../utils/text'; -import { getEdgelessWith } from './utils'; +import { EdgelessFrameManagerIdentifier } from './frame-manager'; + +function getRootBlock(ctx: ToolbarContext): BlockComponent | null { + const rootModel = ctx.store.root; + if (!rootModel) return null; + + return ctx.view.getBlock(rootModel.id); +} const builtinSurfaceToolbarConfig = { actions: [ @@ -87,10 +99,10 @@ const builtinSurfaceToolbarConfig = { const model = ctx.getCurrentModelByType(FrameBlockModel); if (!model) return; - const edgeless = getEdgelessWith(ctx); - if (!edgeless) return; + const rootBlock = getRootBlock(ctx); + if (!rootBlock) return; - mountFrameTitleEditor(model, edgeless); + mountFrameTitleEditor(model, rootBlock); }, }, { @@ -101,8 +113,8 @@ const builtinSurfaceToolbarConfig = { const models = ctx.getSurfaceModelsByType(FrameBlockModel); if (!models.length) return; - const edgeless = getEdgelessWith(ctx); - if (!edgeless) return; + const crud = ctx.std.get(EdgelessCRUDIdentifier); + const gfx = ctx.std.get(GfxControllerIdentifier); ctx.store.captureSync(); @@ -113,10 +125,10 @@ const builtinSurfaceToolbarConfig = { } for (const model of models) { - edgeless.service.removeElement(model); + crud.removeElement(model.id); } - edgeless.service.selection.clear(); + gfx.selection.clear(); }, }, { @@ -172,7 +184,7 @@ const builtinSurfaceToolbarConfig = { when: ctx => ctx.getSurfaceModelsByType(FrameBlockModel).length > 0, } as const satisfies ToolbarModuleConfig; -export const createFrameToolbarConfig = (flavour: string): ExtensionType => { +const createFrameToolbarConfig = (flavour: string): ExtensionType => { const name = flavour.split(':').pop(); return ToolbarModuleExtension({ @@ -180,3 +192,7 @@ export const createFrameToolbarConfig = (flavour: string): ExtensionType => { config: builtinSurfaceToolbarConfig, }); }; + +export const frameToolbarExtension = createFrameToolbarConfig( + FrameBlockSchema.model.flavour +); diff --git a/blocksuite/affine/blocks/block-frame/src/index.ts b/blocksuite/affine/blocks/block-frame/src/index.ts index 4f3971956a..aca317812f 100644 --- a/blocksuite/affine/blocks/block-frame/src/index.ts +++ b/blocksuite/affine/blocks/block-frame/src/index.ts @@ -1,4 +1,21 @@ -export * from './frame-block.js'; -export * from './frame-manager.js'; -export * from './frame-spec.js'; -export * from './tool.js'; +import type { FrameTool } from './frame-tool'; +import type { PresentTool, PresentToolOption } from './preset-tool'; + +export * from './frame-block'; +export * from './frame-highlight-manager'; +export * from './frame-manager'; +export * from './frame-spec'; +export * from './frame-tool'; +export * from './frame-toolbar'; +export * from './preset-tool'; + +declare module '@blocksuite/block-std/gfx' { + interface GfxToolsMap { + frameNavigator: PresentTool; + frame: FrameTool; + } + + interface GfxToolsOption { + frameNavigator: PresentToolOption; + } +} diff --git a/blocksuite/affine/blocks/block-frame/src/tool.ts b/blocksuite/affine/blocks/block-frame/src/preset-tool.ts similarity index 55% rename from blocksuite/affine/blocks/block-frame/src/tool.ts rename to blocksuite/affine/blocks/block-frame/src/preset-tool.ts index 83d33a4e52..236e916612 100644 --- a/blocksuite/affine/blocks/block-frame/src/tool.ts +++ b/blocksuite/affine/blocks/block-frame/src/preset-tool.ts @@ -2,20 +2,10 @@ import { BaseTool } from '@blocksuite/block-std/gfx'; import type { NavigatorMode } from './frame-manager'; -type PresentToolOption = { +export type PresentToolOption = { mode?: NavigatorMode; }; export class PresentTool extends BaseTool { static override toolName: string = 'frameNavigator'; } - -declare module '@blocksuite/block-std/gfx' { - interface GfxToolsMap { - frameNavigator: PresentTool; - } - - interface GfxToolsOption { - frameNavigator: PresentToolOption; - } -} diff --git a/blocksuite/affine/blocks/block-frame/tsconfig.json b/blocksuite/affine/blocks/block-frame/tsconfig.json index 0e78cef97d..11dda846b8 100644 --- a/blocksuite/affine/blocks/block-frame/tsconfig.json +++ b/blocksuite/affine/blocks/block-frame/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../../components" }, { "path": "../../model" }, { "path": "../../shared" }, + { "path": "../../widgets/widget-frame-title" }, { "path": "../../../framework/block-std" }, { "path": "../../../framework/global" }, { "path": "../../../framework/inline" }, diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/connector.ts b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/connector.ts index 8a64f06a14..1c2bb71398 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/connector.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/connector.ts @@ -54,7 +54,7 @@ import { mountConnectorLabelEditor } from '../../utils/text'; import { LINE_STYLE_LIST } from './consts'; import { createTextActions } from './text-common'; import type { MenuItem } from './types'; -import { getEdgelessWith, renderMenu } from './utils'; +import { getRootBlock, renderMenu } from './utils'; const FRONT_ENDPOINT_STYLE_LIST = [ { @@ -333,10 +333,10 @@ export const builtinConnectorToolbarConfig = { const rootModel = ctx.store.root; if (!rootModel) return; - const edgeless = getEdgelessWith(ctx); - if (!edgeless) return; + const rootBlock = getRootBlock(ctx); + if (!rootBlock) return; - mountConnectorLabelEditor(model, edgeless); + mountConnectorLabelEditor(model, rootBlock); }, }, // id: `g.text` diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/group.ts b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/group.ts index ec63931b17..8a96e6e390 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/group.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/group.ts @@ -13,7 +13,7 @@ import { Bound } from '@blocksuite/global/gfx'; import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit'; import { mountGroupTitleEditor } from '../../utils/text'; -import { getEdgelessWith } from './utils'; +import { getEdgelessWith, getRootBlock } from './utils'; export const builtinGroupToolbarConfig = { actions: [ @@ -70,10 +70,10 @@ export const builtinGroupToolbarConfig = { const model = ctx.getCurrentModelByType(GroupElementModel); if (!model) return; - const edgeless = getEdgelessWith(ctx); - if (!edgeless) return; + const rootBlock = getRootBlock(ctx); + if (!rootBlock) return; - mountGroupTitleEditor(model, edgeless); + mountGroupTitleEditor(model, rootBlock); }, }, { diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/index.ts b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/index.ts index b1e485ae49..a786af4039 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/index.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/index.ts @@ -1,4 +1,4 @@ -import { FrameBlockSchema } from '@blocksuite/affine-model'; +import { frameToolbarExtension } from '@blocksuite/affine-block-frame'; import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services'; import { BlockFlavourIdentifier } from '@blocksuite/block-std'; import type { ExtensionType } from '@blocksuite/store'; @@ -6,7 +6,6 @@ import type { ExtensionType } from '@blocksuite/store'; import { builtinBrushToolbarConfig } from './brush'; import { builtinConnectorToolbarConfig } from './connector'; import { builtinEdgelessTextToolbarConfig } from './edgeless-text'; -import { createFrameToolbarConfig } from './frame'; import { builtinGroupToolbarConfig } from './group'; import { builtinMindmapToolbarConfig } from './mindmap'; import { builtinLockedToolbarConfig, builtinMiscToolbarConfig } from './misc'; @@ -14,7 +13,7 @@ import { builtinShapeToolbarConfig } from './shape'; import { builtinTextToolbarConfig } from './text'; export const EdgelessElementToolbarExtension: ExtensionType[] = [ - createFrameToolbarConfig(FrameBlockSchema.model.flavour), + frameToolbarExtension, ToolbarModuleExtension({ id: BlockFlavourIdentifier('affine:surface:group'), diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/shape.ts b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/shape.ts index 73b8a41d48..4ac6e3d82c 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/shape.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/shape.ts @@ -43,7 +43,7 @@ import { createMindmapStyleActionMenu, } from './mindmap'; import { createTextActions } from './text-common'; -import { getEdgelessWith, renderMenu } from './utils'; +import { getRootBlock, renderMenu } from './utils'; export const builtinShapeToolbarConfig = { actions: [ @@ -316,10 +316,10 @@ export const builtinShapeToolbarConfig = { const model = ctx.getCurrentModelByType(ShapeElementModel); if (!model) return; - const edgeless = getEdgelessWith(ctx); - if (!edgeless) return; + const rootBlock = getRootBlock(ctx); + if (!rootBlock) return; - mountShapeTextEditor(model, edgeless); + mountShapeTextEditor(model, rootBlock); }, }, // id: `g.text` diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/utils.ts b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/utils.ts index 1dc5dbd5b3..f0c9705bda 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/utils.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/configs/toolbar/utils.ts @@ -1,5 +1,6 @@ import { EditorChevronDown } from '@blocksuite/affine-components/toolbar'; import type { ToolbarContext } from '@blocksuite/affine-shared/services'; +import type { BlockComponent } from '@blocksuite/block-std'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { repeat } from 'lit/directives/repeat.js'; @@ -77,3 +78,10 @@ export function getEdgelessWith(ctx: ToolbarContext) { return edgeless; } + +export function getRootBlock(ctx: ToolbarContext): BlockComponent | null { + const rootModel = ctx.store.root; + if (!rootModel) return null; + + return ctx.view.getBlock(rootModel.id); +} diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts index 832c4612e4..b6fb166cb0 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/edgeless-builtin-spec.ts @@ -1,4 +1,8 @@ -import { PresentTool } from '@blocksuite/affine-block-frame'; +import { + FrameHighlightManager, + FrameTool, + PresentTool, +} from '@blocksuite/affine-block-frame'; import { ConnectionOverlay } from '@blocksuite/affine-block-surface'; import { TextTool } from '@blocksuite/affine-gfx-text'; import { @@ -10,7 +14,6 @@ import type { ExtensionType } from '@blocksuite/store'; import { EdgelessElementToolbarExtension } from './configs/toolbar'; import { EdgelessRootBlockSpec } from './edgeless-root-spec.js'; import { ConnectorFilter } from './element-transform/connector-filter.js'; -import { FrameHighlightManager } from './element-transform/frame-highlight-manager.js'; import { MindMapDragExtension } from './element-transform/mind-map-drag.js'; import { SnapExtension } from './element-transform/snap-manager.js'; import { MindMapIndicatorOverlay } from './element-transform/utils/indicator-overlay.js'; @@ -19,7 +22,6 @@ import { ConnectorTool } from './gfx-tool/connector-tool.js'; import { DefaultTool } from './gfx-tool/default-tool.js'; import { EmptyTool } from './gfx-tool/empty-tool.js'; import { EraserTool } from './gfx-tool/eraser-tool.js'; -import { FrameTool } from './gfx-tool/frame-tool.js'; import { LassoTool } from './gfx-tool/lasso-tool.js'; import { NoteTool } from './gfx-tool/note-tool.js'; import { PanTool } from './gfx-tool/pan-tool.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts index 16000d0d40..873a751a50 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/default-tool.ts @@ -29,6 +29,7 @@ import { handleNativeRangeAtPoint, resetNativeSelection, } from '@blocksuite/affine-shared/utils'; +import { mountFrameTitleEditor } from '@blocksuite/affine-widget-frame-title'; import type { BlockComponent, PointerEventState } from '@blocksuite/block-std'; import { BaseTool, @@ -51,7 +52,6 @@ import { calPanDelta } from '../utils/panning-utils.js'; import { isCanvasElement, isEdgelessTextBlock } from '../utils/query.js'; import { mountConnectorLabelEditor, - mountFrameTitleEditor, mountGroupTitleEditor, mountShapeTextEditor, } from '../utils/text.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts index c789ab4f14..dd2f9ab4ce 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/gfx-tool/index.ts @@ -3,7 +3,6 @@ export { ConnectorTool, type ConnectorToolOptions } from './connector-tool.js'; export { DefaultTool } from './default-tool.js'; export { EmptyTool } from './empty-tool.js'; export { EraserTool } from './eraser-tool.js'; -export { FrameTool } from './frame-tool.js'; export { LassoTool, type LassoToolOption } from './lasso-tool.js'; export { NoteTool, type NoteToolOption } from './note-tool.js'; export { PanTool, type PanToolOption } from './pan-tool.js'; diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/utils/text.ts b/blocksuite/affine/blocks/block-root/src/edgeless/utils/text.ts index d938efa48c..6ea29c6683 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/utils/text.ts +++ b/blocksuite/affine/blocks/block-root/src/edgeless/utils/text.ts @@ -1,7 +1,6 @@ import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import type { ConnectorElementModel, - FrameBlockModel, GroupElementModel, } from '@blocksuite/affine-model'; import { ShapeElementModel } from '@blocksuite/affine-model'; @@ -13,7 +12,6 @@ import { Bound } from '@blocksuite/global/gfx'; import * as Y from 'yjs'; import { EdgelessConnectorLabelEditor } from '../components/text/edgeless-connector-label-editor.js'; -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'; @@ -60,33 +58,6 @@ export function mountShapeTextEditor( mountElm.append(shapeEditor); } -export function mountFrameTitleEditor( - frame: FrameBlockModel, - edgeless: BlockComponent -) { - const mountElm = edgeless.querySelector('.edgeless-mount-point'); - if (!mountElm) { - throw new BlockSuiteError( - ErrorCode.ValueNotExists, - "edgeless block's mount point does not exist" - ); - } - - const gfx = edgeless.std.get(GfxControllerIdentifier); - - gfx.tool.setTool('default'); - gfx.selection.set({ - elements: [frame.id], - editing: true, - }); - - const frameEditor = new EdgelessFrameTitleEditor(); - frameEditor.frameModel = frame; - frameEditor.edgeless = edgeless; - - mountElm.append(frameEditor); -} - export function mountGroupTitleEditor( group: GroupElementModel, edgeless: BlockComponent diff --git a/blocksuite/affine/blocks/block-root/src/effects.ts b/blocksuite/affine/blocks/block-root/src/effects.ts index ac81b9e5da..62d85caa58 100644 --- a/blocksuite/affine/blocks/block-root/src/effects.ts +++ b/blocksuite/affine/blocks/block-root/src/effects.ts @@ -28,7 +28,6 @@ import { EdgelessSelectedRectWidget, } from './edgeless/components/rects/edgeless-selected-rect.js'; import { EdgelessConnectorLabelEditor } from './edgeless/components/text/edgeless-connector-label-editor.js'; -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 { EdgelessBrushMenu } from './edgeless/components/toolbar/brush/brush-menu.js'; @@ -239,10 +238,6 @@ function registerEdgelessEditorComponents() { 'edgeless-group-title-editor', EdgelessGroupTitleEditor ); - customElements.define( - 'edgeless-frame-title-editor', - EdgelessFrameTitleEditor - ); } function registerMiscComponents() { @@ -324,7 +319,6 @@ declare global { 'edgeless-dragging-area-rect': EdgelessDraggingAreaRectWidget; 'edgeless-selected-rect': EdgelessSelectedRectWidget; 'edgeless-connector-label-editor': EdgelessConnectorLabelEditor; - 'edgeless-frame-title-editor': EdgelessFrameTitleEditor; 'edgeless-group-title-editor': EdgelessGroupTitleEditor; 'edgeless-shape-text-editor': EdgelessShapeTextEditor; 'edgeless-toolbar-widget': EdgelessToolbarWidget; diff --git a/blocksuite/affine/widgets/widget-frame-title/package.json b/blocksuite/affine/widgets/widget-frame-title/package.json index 3318cc20ff..8178546214 100644 --- a/blocksuite/affine/widgets/widget-frame-title/package.json +++ b/blocksuite/affine/widgets/widget-frame-title/package.json @@ -12,6 +12,7 @@ "dependencies": { "@blocksuite/affine-components": "workspace:*", "@blocksuite/affine-model": "workspace:*", + "@blocksuite/affine-rich-text": "workspace:*", "@blocksuite/affine-shared": "workspace:*", "@blocksuite/block-std": "workspace:*", "@blocksuite/global": "workspace:*", diff --git a/blocksuite/affine/widgets/widget-frame-title/src/affine-frame-title-widget.ts b/blocksuite/affine/widgets/widget-frame-title/src/affine-frame-title-widget.ts new file mode 100644 index 0000000000..71915716d4 --- /dev/null +++ b/blocksuite/affine/widgets/widget-frame-title/src/affine-frame-title-widget.ts @@ -0,0 +1,43 @@ +import { FrameBlockModel, type RootBlockModel } from '@blocksuite/affine-model'; +import { WidgetComponent, WidgetViewExtension } from '@blocksuite/block-std'; +import { html } from 'lit'; +import { repeat } from 'lit/directives/repeat.js'; +import { literal, unsafeStatic } from 'lit/static-html.js'; + +import type { AffineFrameTitle } from './frame-title.js'; + +export const AFFINE_FRAME_TITLE_WIDGET = 'affine-frame-title-widget'; + +export class AffineFrameTitleWidget extends WidgetComponent { + private get _frames() { + return Object.values(this.doc.blocks.value) + .map(({ model }) => model) + .filter(model => model instanceof FrameBlockModel); + } + + getFrameTitle(frame: FrameBlockModel | string) { + const id = typeof frame === 'string' ? frame : frame.id; + const frameTitle = this.shadowRoot?.querySelector( + `affine-frame-title[data-id="${id}"]` + ) as AffineFrameTitle | null; + return frameTitle; + } + + override render() { + return repeat( + this._frames, + ({ id }) => id, + frame => + html`` + ); + } +} + +export const frameTitleWidget = WidgetViewExtension( + 'affine:page', + AFFINE_FRAME_TITLE_WIDGET, + literal`${unsafeStatic(AFFINE_FRAME_TITLE_WIDGET)}` +); diff --git a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts b/blocksuite/affine/widgets/widget-frame-title/src/edgeless-frame-title-editor.ts similarity index 98% rename from blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts rename to blocksuite/affine/widgets/widget-frame-title/src/edgeless-frame-title-editor.ts index 81547765b2..a28886cfca 100644 --- a/blocksuite/affine/blocks/block-root/src/edgeless/components/text/edgeless-frame-title-editor.ts +++ b/blocksuite/affine/widgets/widget-frame-title/src/edgeless-frame-title-editor.ts @@ -1,10 +1,5 @@ import { FrameBlockModel } from '@blocksuite/affine-model'; import type { RichText } from '@blocksuite/affine-rich-text'; -import { - AFFINE_FRAME_TITLE_WIDGET, - type AffineFrameTitleWidget, - frameTitleStyleVars, -} from '@blocksuite/affine-widget-frame-title'; import { type BlockComponent, RANGE_SYNC_EXCLUDE_ATTR, @@ -18,6 +13,12 @@ import { css, html, nothing } from 'lit'; import { property, query } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; +import { + AFFINE_FRAME_TITLE_WIDGET, + type AffineFrameTitleWidget, +} from './affine-frame-title-widget'; +import { frameTitleStyleVars } from './styles'; + export class EdgelessFrameTitleEditor extends WithDisposable( ShadowlessElement ) { diff --git a/blocksuite/affine/widgets/widget-frame-title/src/effects.ts b/blocksuite/affine/widgets/widget-frame-title/src/effects.ts index 3f9a5ca710..bfe068a026 100644 --- a/blocksuite/affine/widgets/widget-frame-title/src/effects.ts +++ b/blocksuite/affine/widgets/widget-frame-title/src/effects.ts @@ -1,7 +1,15 @@ +import { + AFFINE_FRAME_TITLE_WIDGET, + AffineFrameTitleWidget, +} from './affine-frame-title-widget.js'; +import { EdgelessFrameTitleEditor } from './edgeless-frame-title-editor.js'; import { AFFINE_FRAME_TITLE, AffineFrameTitle } from './frame-title.js'; -import { AFFINE_FRAME_TITLE_WIDGET, AffineFrameTitleWidget } from './index.js'; export function effects() { customElements.define(AFFINE_FRAME_TITLE_WIDGET, AffineFrameTitleWidget); customElements.define(AFFINE_FRAME_TITLE, AffineFrameTitle); + customElements.define( + 'edgeless-frame-title-editor', + EdgelessFrameTitleEditor + ); } diff --git a/blocksuite/affine/widgets/widget-frame-title/src/index.ts b/blocksuite/affine/widgets/widget-frame-title/src/index.ts index 1c5f8fd518..7919ffe1e2 100644 --- a/blocksuite/affine/widgets/widget-frame-title/src/index.ts +++ b/blocksuite/affine/widgets/widget-frame-title/src/index.ts @@ -1,45 +1,4 @@ -import { FrameBlockModel, type RootBlockModel } from '@blocksuite/affine-model'; -import { WidgetComponent, WidgetViewExtension } from '@blocksuite/block-std'; -import { html } from 'lit'; -import { repeat } from 'lit/directives/repeat.js'; -import { literal, unsafeStatic } from 'lit/static-html.js'; - -import type { AffineFrameTitle } from './frame-title.js'; - -export const AFFINE_FRAME_TITLE_WIDGET = 'affine-frame-title-widget'; - -export class AffineFrameTitleWidget extends WidgetComponent { - private get _frames() { - return Object.values(this.doc.blocks.value) - .map(({ model }) => model) - .filter(model => model instanceof FrameBlockModel); - } - - getFrameTitle(frame: FrameBlockModel | string) { - const id = typeof frame === 'string' ? frame : frame.id; - const frameTitle = this.shadowRoot?.querySelector( - `affine-frame-title[data-id="${id}"]` - ) as AffineFrameTitle | null; - return frameTitle; - } - - override render() { - return repeat( - this._frames, - ({ id }) => id, - frame => - html`` - ); - } -} - +export * from './affine-frame-title-widget.js'; +export * from './edgeless-frame-title-editor.js'; +export * from './mount-frame-title-editor.js'; export * from './styles.js'; - -export const frameTitleWidget = WidgetViewExtension( - 'affine:page', - AFFINE_FRAME_TITLE_WIDGET, - literal`${unsafeStatic(AFFINE_FRAME_TITLE_WIDGET)}` -); diff --git a/blocksuite/affine/widgets/widget-frame-title/src/mount-frame-title-editor.ts b/blocksuite/affine/widgets/widget-frame-title/src/mount-frame-title-editor.ts new file mode 100644 index 0000000000..558a9958da --- /dev/null +++ b/blocksuite/affine/widgets/widget-frame-title/src/mount-frame-title-editor.ts @@ -0,0 +1,34 @@ +import type { FrameBlockModel } from '@blocksuite/affine-model'; +import type { BlockComponent } from '@blocksuite/block-std'; +import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; +import { BlockSuiteError } from '@blocksuite/global/exceptions'; + +import { EdgelessFrameTitleEditor } from './edgeless-frame-title-editor'; + +export function mountFrameTitleEditor( + frame: FrameBlockModel, + edgeless: BlockComponent +) { + const mountElm = edgeless.querySelector('.edgeless-mount-point'); + if (!mountElm) { + throw new BlockSuiteError( + BlockSuiteError.ErrorCode.ValueNotExists, + "edgeless block's mount point does not exist" + ); + } + + const gfx = edgeless.std.get(GfxControllerIdentifier); + + // @ts-expect-error TODO: refactor gfx tool + gfx.tool.setTool('default'); + gfx.selection.set({ + elements: [frame.id], + editing: true, + }); + + const frameEditor = new EdgelessFrameTitleEditor(); + frameEditor.frameModel = frame; + frameEditor.edgeless = edgeless; + + mountElm.append(frameEditor); +} diff --git a/blocksuite/affine/widgets/widget-frame-title/tsconfig.json b/blocksuite/affine/widgets/widget-frame-title/tsconfig.json index 938b8ac446..bd24c274a5 100644 --- a/blocksuite/affine/widgets/widget-frame-title/tsconfig.json +++ b/blocksuite/affine/widgets/widget-frame-title/tsconfig.json @@ -9,6 +9,7 @@ "references": [ { "path": "../../components" }, { "path": "../../model" }, + { "path": "../../rich-text" }, { "path": "../../shared" }, { "path": "../../../framework/block-std" }, { "path": "../../../framework/global" } diff --git a/tools/utils/src/workspace.gen.ts b/tools/utils/src/workspace.gen.ts index 102618bdaa..0de17f422a 100644 --- a/tools/utils/src/workspace.gen.ts +++ b/tools/utils/src/workspace.gen.ts @@ -195,6 +195,7 @@ export const PackageList = [ 'blocksuite/affine/components', 'blocksuite/affine/model', 'blocksuite/affine/shared', + 'blocksuite/affine/widgets/widget-frame-title', 'blocksuite/framework/block-std', 'blocksuite/framework/global', 'blocksuite/framework/inline', @@ -531,6 +532,7 @@ export const PackageList = [ workspaceDependencies: [ 'blocksuite/affine/components', 'blocksuite/affine/model', + 'blocksuite/affine/rich-text', 'blocksuite/affine/shared', 'blocksuite/framework/block-std', 'blocksuite/framework/global', diff --git a/yarn.lock b/yarn.lock index e68d8759f7..185e317209 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2558,8 +2558,10 @@ __metadata: "@blocksuite/affine-components": "workspace:*" "@blocksuite/affine-model": "workspace:*" "@blocksuite/affine-shared": "workspace:*" + "@blocksuite/affine-widget-frame-title": "workspace:*" "@blocksuite/block-std": "workspace:*" "@blocksuite/global": "workspace:*" + "@blocksuite/icons": "npm:^2.2.6" "@blocksuite/inline": "workspace:*" "@blocksuite/store": "workspace:*" "@floating-ui/dom": "npm:^1.6.13" @@ -3165,6 +3167,7 @@ __metadata: dependencies: "@blocksuite/affine-components": "workspace:*" "@blocksuite/affine-model": "workspace:*" + "@blocksuite/affine-rich-text": "workspace:*" "@blocksuite/affine-shared": "workspace:*" "@blocksuite/block-std": "workspace:*" "@blocksuite/global": "workspace:*"