refactor(editor): move gfx frame title to widget (#11021)

This commit is contained in:
Saul-Mirone
2025-03-20 04:10:56 +00:00
parent 120e193c58
commit 75580e881b
26 changed files with 195 additions and 147 deletions

View File

@@ -14,8 +14,10 @@
"@blocksuite/affine-components": "workspace:*", "@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*", "@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*", "@blocksuite/affine-shared": "workspace:*",
"@blocksuite/affine-widget-frame-title": "workspace:*",
"@blocksuite/block-std": "workspace:*", "@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*", "@blocksuite/global": "workspace:*",
"@blocksuite/icons": "^2.2.6",
"@blocksuite/inline": "workspace:*", "@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*", "@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.13", "@floating-ui/dom": "^1.6.13",

View File

@@ -1,8 +1,3 @@
import {
type EdgelessFrameManager,
type FrameOverlay,
isFrameBlock,
} from '@blocksuite/affine-block-frame';
import { OverlayIdentifier } from '@blocksuite/affine-block-surface'; import { OverlayIdentifier } from '@blocksuite/affine-block-surface';
import { import {
type FrameBlockModel, type FrameBlockModel,
@@ -18,6 +13,12 @@ import {
TransformExtension, TransformExtension,
} from '@blocksuite/block-std/gfx'; } from '@blocksuite/block-std/gfx';
import {
type EdgelessFrameManager,
type FrameOverlay,
isFrameBlock,
} from './frame-manager';
export class FrameHighlightManager extends TransformExtension { export class FrameHighlightManager extends TransformExtension {
static override key = 'frame-highlight-manager'; static override key = 'frame-highlight-manager';

View File

@@ -1,7 +1,3 @@
import {
EdgelessFrameManagerIdentifier,
type FrameOverlay,
} from '@blocksuite/affine-block-frame';
import { OverlayIdentifier } from '@blocksuite/affine-block-surface'; import { OverlayIdentifier } from '@blocksuite/affine-block-surface';
import type { FrameBlockModel } from '@blocksuite/affine-model'; import type { FrameBlockModel } from '@blocksuite/affine-model';
import { import {
@@ -15,6 +11,11 @@ import { Bound, Vec } from '@blocksuite/global/gfx';
import { Text } from '@blocksuite/store'; import { Text } from '@blocksuite/store';
import * as Y from 'yjs'; import * as Y from 'yjs';
import {
EdgelessFrameManagerIdentifier,
type FrameOverlay,
} from './frame-manager';
export class FrameTool extends BaseTool { export class FrameTool extends BaseTool {
static override toolName = 'frame'; static override toolName = 'frame';
@@ -40,6 +41,7 @@ export class FrameTool extends BaseTool {
this.doc.transact(() => { this.doc.transact(() => {
frame.pop('xywh'); frame.pop('xywh');
}); });
// @ts-expect-error TODO: refactor gfx tool
this.gfx.tool.setTool('default'); this.gfx.tool.setTool('default');
this.gfx.selection.set({ this.gfx.selection.set({
elements: [frame.id], elements: [frame.id],
@@ -106,9 +108,3 @@ export class FrameTool extends BaseTool {
this._startPoint = this._toModelCoord(point); this._startPoint = this._toModelCoord(point);
} }
} }
declare module '@blocksuite/block-std/gfx' {
interface GfxToolsMap {
frame: FrameTool;
}
}

View File

@@ -1,4 +1,3 @@
import { EdgelessFrameManagerIdentifier } from '@blocksuite/affine-block-frame';
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
import { import {
packColor, packColor,
@@ -9,6 +8,7 @@ import {
DEFAULT_NOTE_HEIGHT, DEFAULT_NOTE_HEIGHT,
DefaultTheme, DefaultTheme,
FrameBlockModel, FrameBlockModel,
FrameBlockSchema,
NoteBlockModel, NoteBlockModel,
NoteBlockSchema, NoteBlockSchema,
NoteDisplayMode, NoteDisplayMode,
@@ -16,6 +16,7 @@ import {
SurfaceRefBlockSchema, SurfaceRefBlockSchema,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { import {
type ToolbarContext,
type ToolbarModuleConfig, type ToolbarModuleConfig,
ToolbarModuleExtension, ToolbarModuleExtension,
} from '@blocksuite/affine-shared/services'; } from '@blocksuite/affine-shared/services';
@@ -23,14 +24,25 @@ import {
getMostCommonResolvedValue, getMostCommonResolvedValue,
matchModels, matchModels,
} from '@blocksuite/affine-shared/utils'; } 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 { Bound } from '@blocksuite/global/gfx';
import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit'; import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit';
import type { ExtensionType } from '@blocksuite/store'; import type { ExtensionType } from '@blocksuite/store';
import { html } from 'lit'; import { html } from 'lit';
import { mountFrameTitleEditor } from '../../utils/text'; import { EdgelessFrameManagerIdentifier } from './frame-manager';
import { getEdgelessWith } from './utils';
function getRootBlock(ctx: ToolbarContext): BlockComponent | null {
const rootModel = ctx.store.root;
if (!rootModel) return null;
return ctx.view.getBlock(rootModel.id);
}
const builtinSurfaceToolbarConfig = { const builtinSurfaceToolbarConfig = {
actions: [ actions: [
@@ -87,10 +99,10 @@ const builtinSurfaceToolbarConfig = {
const model = ctx.getCurrentModelByType(FrameBlockModel); const model = ctx.getCurrentModelByType(FrameBlockModel);
if (!model) return; if (!model) return;
const edgeless = getEdgelessWith(ctx); const rootBlock = getRootBlock(ctx);
if (!edgeless) return; if (!rootBlock) return;
mountFrameTitleEditor(model, edgeless); mountFrameTitleEditor(model, rootBlock);
}, },
}, },
{ {
@@ -101,8 +113,8 @@ const builtinSurfaceToolbarConfig = {
const models = ctx.getSurfaceModelsByType(FrameBlockModel); const models = ctx.getSurfaceModelsByType(FrameBlockModel);
if (!models.length) return; if (!models.length) return;
const edgeless = getEdgelessWith(ctx); const crud = ctx.std.get(EdgelessCRUDIdentifier);
if (!edgeless) return; const gfx = ctx.std.get(GfxControllerIdentifier);
ctx.store.captureSync(); ctx.store.captureSync();
@@ -113,10 +125,10 @@ const builtinSurfaceToolbarConfig = {
} }
for (const model of models) { 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, when: ctx => ctx.getSurfaceModelsByType(FrameBlockModel).length > 0,
} as const satisfies ToolbarModuleConfig; } as const satisfies ToolbarModuleConfig;
export const createFrameToolbarConfig = (flavour: string): ExtensionType => { const createFrameToolbarConfig = (flavour: string): ExtensionType => {
const name = flavour.split(':').pop(); const name = flavour.split(':').pop();
return ToolbarModuleExtension({ return ToolbarModuleExtension({
@@ -180,3 +192,7 @@ export const createFrameToolbarConfig = (flavour: string): ExtensionType => {
config: builtinSurfaceToolbarConfig, config: builtinSurfaceToolbarConfig,
}); });
}; };
export const frameToolbarExtension = createFrameToolbarConfig(
FrameBlockSchema.model.flavour
);

View File

@@ -1,4 +1,21 @@
export * from './frame-block.js'; import type { FrameTool } from './frame-tool';
export * from './frame-manager.js'; import type { PresentTool, PresentToolOption } from './preset-tool';
export * from './frame-spec.js';
export * from './tool.js'; 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;
}
}

View File

@@ -2,20 +2,10 @@ import { BaseTool } from '@blocksuite/block-std/gfx';
import type { NavigatorMode } from './frame-manager'; import type { NavigatorMode } from './frame-manager';
type PresentToolOption = { export type PresentToolOption = {
mode?: NavigatorMode; mode?: NavigatorMode;
}; };
export class PresentTool extends BaseTool<PresentToolOption> { export class PresentTool extends BaseTool<PresentToolOption> {
static override toolName: string = 'frameNavigator'; static override toolName: string = 'frameNavigator';
} }
declare module '@blocksuite/block-std/gfx' {
interface GfxToolsMap {
frameNavigator: PresentTool;
}
interface GfxToolsOption {
frameNavigator: PresentToolOption;
}
}

View File

@@ -11,6 +11,7 @@
{ "path": "../../components" }, { "path": "../../components" },
{ "path": "../../model" }, { "path": "../../model" },
{ "path": "../../shared" }, { "path": "../../shared" },
{ "path": "../../widgets/widget-frame-title" },
{ "path": "../../../framework/block-std" }, { "path": "../../../framework/block-std" },
{ "path": "../../../framework/global" }, { "path": "../../../framework/global" },
{ "path": "../../../framework/inline" }, { "path": "../../../framework/inline" },

View File

@@ -54,7 +54,7 @@ import { mountConnectorLabelEditor } from '../../utils/text';
import { LINE_STYLE_LIST } from './consts'; import { LINE_STYLE_LIST } from './consts';
import { createTextActions } from './text-common'; import { createTextActions } from './text-common';
import type { MenuItem } from './types'; import type { MenuItem } from './types';
import { getEdgelessWith, renderMenu } from './utils'; import { getRootBlock, renderMenu } from './utils';
const FRONT_ENDPOINT_STYLE_LIST = [ const FRONT_ENDPOINT_STYLE_LIST = [
{ {
@@ -333,10 +333,10 @@ export const builtinConnectorToolbarConfig = {
const rootModel = ctx.store.root; const rootModel = ctx.store.root;
if (!rootModel) return; if (!rootModel) return;
const edgeless = getEdgelessWith(ctx); const rootBlock = getRootBlock(ctx);
if (!edgeless) return; if (!rootBlock) return;
mountConnectorLabelEditor(model, edgeless); mountConnectorLabelEditor(model, rootBlock);
}, },
}, },
// id: `g.text` // id: `g.text`

View File

@@ -13,7 +13,7 @@ import { Bound } from '@blocksuite/global/gfx';
import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit'; import { EditIcon, PageIcon, UngroupIcon } from '@blocksuite/icons/lit';
import { mountGroupTitleEditor } from '../../utils/text'; import { mountGroupTitleEditor } from '../../utils/text';
import { getEdgelessWith } from './utils'; import { getEdgelessWith, getRootBlock } from './utils';
export const builtinGroupToolbarConfig = { export const builtinGroupToolbarConfig = {
actions: [ actions: [
@@ -70,10 +70,10 @@ export const builtinGroupToolbarConfig = {
const model = ctx.getCurrentModelByType(GroupElementModel); const model = ctx.getCurrentModelByType(GroupElementModel);
if (!model) return; if (!model) return;
const edgeless = getEdgelessWith(ctx); const rootBlock = getRootBlock(ctx);
if (!edgeless) return; if (!rootBlock) return;
mountGroupTitleEditor(model, edgeless); mountGroupTitleEditor(model, rootBlock);
}, },
}, },
{ {

View File

@@ -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 { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
import { BlockFlavourIdentifier } from '@blocksuite/block-std'; import { BlockFlavourIdentifier } from '@blocksuite/block-std';
import type { ExtensionType } from '@blocksuite/store'; import type { ExtensionType } from '@blocksuite/store';
@@ -6,7 +6,6 @@ import type { ExtensionType } from '@blocksuite/store';
import { builtinBrushToolbarConfig } from './brush'; import { builtinBrushToolbarConfig } from './brush';
import { builtinConnectorToolbarConfig } from './connector'; import { builtinConnectorToolbarConfig } from './connector';
import { builtinEdgelessTextToolbarConfig } from './edgeless-text'; import { builtinEdgelessTextToolbarConfig } from './edgeless-text';
import { createFrameToolbarConfig } from './frame';
import { builtinGroupToolbarConfig } from './group'; import { builtinGroupToolbarConfig } from './group';
import { builtinMindmapToolbarConfig } from './mindmap'; import { builtinMindmapToolbarConfig } from './mindmap';
import { builtinLockedToolbarConfig, builtinMiscToolbarConfig } from './misc'; import { builtinLockedToolbarConfig, builtinMiscToolbarConfig } from './misc';
@@ -14,7 +13,7 @@ import { builtinShapeToolbarConfig } from './shape';
import { builtinTextToolbarConfig } from './text'; import { builtinTextToolbarConfig } from './text';
export const EdgelessElementToolbarExtension: ExtensionType[] = [ export const EdgelessElementToolbarExtension: ExtensionType[] = [
createFrameToolbarConfig(FrameBlockSchema.model.flavour), frameToolbarExtension,
ToolbarModuleExtension({ ToolbarModuleExtension({
id: BlockFlavourIdentifier('affine:surface:group'), id: BlockFlavourIdentifier('affine:surface:group'),

View File

@@ -43,7 +43,7 @@ import {
createMindmapStyleActionMenu, createMindmapStyleActionMenu,
} from './mindmap'; } from './mindmap';
import { createTextActions } from './text-common'; import { createTextActions } from './text-common';
import { getEdgelessWith, renderMenu } from './utils'; import { getRootBlock, renderMenu } from './utils';
export const builtinShapeToolbarConfig = { export const builtinShapeToolbarConfig = {
actions: [ actions: [
@@ -316,10 +316,10 @@ export const builtinShapeToolbarConfig = {
const model = ctx.getCurrentModelByType(ShapeElementModel); const model = ctx.getCurrentModelByType(ShapeElementModel);
if (!model) return; if (!model) return;
const edgeless = getEdgelessWith(ctx); const rootBlock = getRootBlock(ctx);
if (!edgeless) return; if (!rootBlock) return;
mountShapeTextEditor(model, edgeless); mountShapeTextEditor(model, rootBlock);
}, },
}, },
// id: `g.text` // id: `g.text`

View File

@@ -1,5 +1,6 @@
import { EditorChevronDown } from '@blocksuite/affine-components/toolbar'; import { EditorChevronDown } from '@blocksuite/affine-components/toolbar';
import type { ToolbarContext } from '@blocksuite/affine-shared/services'; import type { ToolbarContext } from '@blocksuite/affine-shared/services';
import type { BlockComponent } from '@blocksuite/block-std';
import { html } from 'lit'; import { html } from 'lit';
import { ifDefined } from 'lit/directives/if-defined.js'; import { ifDefined } from 'lit/directives/if-defined.js';
import { repeat } from 'lit/directives/repeat.js'; import { repeat } from 'lit/directives/repeat.js';
@@ -77,3 +78,10 @@ export function getEdgelessWith(ctx: ToolbarContext) {
return edgeless; return edgeless;
} }
export function getRootBlock(ctx: ToolbarContext): BlockComponent | null {
const rootModel = ctx.store.root;
if (!rootModel) return null;
return ctx.view.getBlock(rootModel.id);
}

View File

@@ -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 { ConnectionOverlay } from '@blocksuite/affine-block-surface';
import { TextTool } from '@blocksuite/affine-gfx-text'; import { TextTool } from '@blocksuite/affine-gfx-text';
import { import {
@@ -10,7 +14,6 @@ import type { ExtensionType } from '@blocksuite/store';
import { EdgelessElementToolbarExtension } from './configs/toolbar'; import { EdgelessElementToolbarExtension } from './configs/toolbar';
import { EdgelessRootBlockSpec } from './edgeless-root-spec.js'; import { EdgelessRootBlockSpec } from './edgeless-root-spec.js';
import { ConnectorFilter } from './element-transform/connector-filter.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 { MindMapDragExtension } from './element-transform/mind-map-drag.js';
import { SnapExtension } from './element-transform/snap-manager.js'; import { SnapExtension } from './element-transform/snap-manager.js';
import { MindMapIndicatorOverlay } from './element-transform/utils/indicator-overlay.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 { DefaultTool } from './gfx-tool/default-tool.js';
import { EmptyTool } from './gfx-tool/empty-tool.js'; import { EmptyTool } from './gfx-tool/empty-tool.js';
import { EraserTool } from './gfx-tool/eraser-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 { LassoTool } from './gfx-tool/lasso-tool.js';
import { NoteTool } from './gfx-tool/note-tool.js'; import { NoteTool } from './gfx-tool/note-tool.js';
import { PanTool } from './gfx-tool/pan-tool.js'; import { PanTool } from './gfx-tool/pan-tool.js';

View File

@@ -29,6 +29,7 @@ import {
handleNativeRangeAtPoint, handleNativeRangeAtPoint,
resetNativeSelection, resetNativeSelection,
} from '@blocksuite/affine-shared/utils'; } from '@blocksuite/affine-shared/utils';
import { mountFrameTitleEditor } from '@blocksuite/affine-widget-frame-title';
import type { BlockComponent, PointerEventState } from '@blocksuite/block-std'; import type { BlockComponent, PointerEventState } from '@blocksuite/block-std';
import { import {
BaseTool, BaseTool,
@@ -51,7 +52,6 @@ import { calPanDelta } from '../utils/panning-utils.js';
import { isCanvasElement, isEdgelessTextBlock } from '../utils/query.js'; import { isCanvasElement, isEdgelessTextBlock } from '../utils/query.js';
import { import {
mountConnectorLabelEditor, mountConnectorLabelEditor,
mountFrameTitleEditor,
mountGroupTitleEditor, mountGroupTitleEditor,
mountShapeTextEditor, mountShapeTextEditor,
} from '../utils/text.js'; } from '../utils/text.js';

View File

@@ -3,7 +3,6 @@ export { ConnectorTool, type ConnectorToolOptions } from './connector-tool.js';
export { DefaultTool } from './default-tool.js'; export { DefaultTool } from './default-tool.js';
export { EmptyTool } from './empty-tool.js'; export { EmptyTool } from './empty-tool.js';
export { EraserTool } from './eraser-tool.js'; export { EraserTool } from './eraser-tool.js';
export { FrameTool } from './frame-tool.js';
export { LassoTool, type LassoToolOption } from './lasso-tool.js'; export { LassoTool, type LassoToolOption } from './lasso-tool.js';
export { NoteTool, type NoteToolOption } from './note-tool.js'; export { NoteTool, type NoteToolOption } from './note-tool.js';
export { PanTool, type PanToolOption } from './pan-tool.js'; export { PanTool, type PanToolOption } from './pan-tool.js';

View File

@@ -1,7 +1,6 @@
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface'; import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
import type { import type {
ConnectorElementModel, ConnectorElementModel,
FrameBlockModel,
GroupElementModel, GroupElementModel,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { ShapeElementModel } 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 * as Y from 'yjs';
import { EdgelessConnectorLabelEditor } from '../components/text/edgeless-connector-label-editor.js'; 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 { EdgelessGroupTitleEditor } from '../components/text/edgeless-group-title-editor.js';
import { EdgelessShapeTextEditor } from '../components/text/edgeless-shape-text-editor.js'; import { EdgelessShapeTextEditor } from '../components/text/edgeless-shape-text-editor.js';
@@ -60,33 +58,6 @@ export function mountShapeTextEditor(
mountElm.append(shapeEditor); 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( export function mountGroupTitleEditor(
group: GroupElementModel, group: GroupElementModel,
edgeless: BlockComponent edgeless: BlockComponent

View File

@@ -28,7 +28,6 @@ import {
EdgelessSelectedRectWidget, EdgelessSelectedRectWidget,
} from './edgeless/components/rects/edgeless-selected-rect.js'; } from './edgeless/components/rects/edgeless-selected-rect.js';
import { EdgelessConnectorLabelEditor } from './edgeless/components/text/edgeless-connector-label-editor.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 { EdgelessGroupTitleEditor } from './edgeless/components/text/edgeless-group-title-editor.js';
import { EdgelessShapeTextEditor } from './edgeless/components/text/edgeless-shape-text-editor.js'; import { EdgelessShapeTextEditor } from './edgeless/components/text/edgeless-shape-text-editor.js';
import { EdgelessBrushMenu } from './edgeless/components/toolbar/brush/brush-menu.js'; import { EdgelessBrushMenu } from './edgeless/components/toolbar/brush/brush-menu.js';
@@ -239,10 +238,6 @@ function registerEdgelessEditorComponents() {
'edgeless-group-title-editor', 'edgeless-group-title-editor',
EdgelessGroupTitleEditor EdgelessGroupTitleEditor
); );
customElements.define(
'edgeless-frame-title-editor',
EdgelessFrameTitleEditor
);
} }
function registerMiscComponents() { function registerMiscComponents() {
@@ -324,7 +319,6 @@ declare global {
'edgeless-dragging-area-rect': EdgelessDraggingAreaRectWidget; 'edgeless-dragging-area-rect': EdgelessDraggingAreaRectWidget;
'edgeless-selected-rect': EdgelessSelectedRectWidget; 'edgeless-selected-rect': EdgelessSelectedRectWidget;
'edgeless-connector-label-editor': EdgelessConnectorLabelEditor; 'edgeless-connector-label-editor': EdgelessConnectorLabelEditor;
'edgeless-frame-title-editor': EdgelessFrameTitleEditor;
'edgeless-group-title-editor': EdgelessGroupTitleEditor; 'edgeless-group-title-editor': EdgelessGroupTitleEditor;
'edgeless-shape-text-editor': EdgelessShapeTextEditor; 'edgeless-shape-text-editor': EdgelessShapeTextEditor;
'edgeless-toolbar-widget': EdgelessToolbarWidget; 'edgeless-toolbar-widget': EdgelessToolbarWidget;

View File

@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"@blocksuite/affine-components": "workspace:*", "@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*", "@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-rich-text": "workspace:*",
"@blocksuite/affine-shared": "workspace:*", "@blocksuite/affine-shared": "workspace:*",
"@blocksuite/block-std": "workspace:*", "@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*", "@blocksuite/global": "workspace:*",

View File

@@ -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<RootBlockModel> {
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`<affine-frame-title
.model=${frame}
data-id=${frame.id}
></affine-frame-title>`
);
}
}
export const frameTitleWidget = WidgetViewExtension(
'affine:page',
AFFINE_FRAME_TITLE_WIDGET,
literal`${unsafeStatic(AFFINE_FRAME_TITLE_WIDGET)}`
);

View File

@@ -1,10 +1,5 @@
import { FrameBlockModel } from '@blocksuite/affine-model'; import { FrameBlockModel } from '@blocksuite/affine-model';
import type { RichText } from '@blocksuite/affine-rich-text'; import type { RichText } from '@blocksuite/affine-rich-text';
import {
AFFINE_FRAME_TITLE_WIDGET,
type AffineFrameTitleWidget,
frameTitleStyleVars,
} from '@blocksuite/affine-widget-frame-title';
import { import {
type BlockComponent, type BlockComponent,
RANGE_SYNC_EXCLUDE_ATTR, RANGE_SYNC_EXCLUDE_ATTR,
@@ -18,6 +13,12 @@ import { css, html, nothing } from 'lit';
import { property, query } from 'lit/decorators.js'; import { property, query } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.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( export class EdgelessFrameTitleEditor extends WithDisposable(
ShadowlessElement ShadowlessElement
) { ) {

View File

@@ -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, AffineFrameTitle } from './frame-title.js';
import { AFFINE_FRAME_TITLE_WIDGET, AffineFrameTitleWidget } from './index.js';
export function effects() { export function effects() {
customElements.define(AFFINE_FRAME_TITLE_WIDGET, AffineFrameTitleWidget); customElements.define(AFFINE_FRAME_TITLE_WIDGET, AffineFrameTitleWidget);
customElements.define(AFFINE_FRAME_TITLE, AffineFrameTitle); customElements.define(AFFINE_FRAME_TITLE, AffineFrameTitle);
customElements.define(
'edgeless-frame-title-editor',
EdgelessFrameTitleEditor
);
} }

View File

@@ -1,45 +1,4 @@
import { FrameBlockModel, type RootBlockModel } from '@blocksuite/affine-model'; export * from './affine-frame-title-widget.js';
import { WidgetComponent, WidgetViewExtension } from '@blocksuite/block-std'; export * from './edgeless-frame-title-editor.js';
import { html } from 'lit'; export * from './mount-frame-title-editor.js';
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<RootBlockModel> {
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`<affine-frame-title
.model=${frame}
data-id=${frame.id}
></affine-frame-title>`
);
}
}
export * from './styles.js'; export * from './styles.js';
export const frameTitleWidget = WidgetViewExtension(
'affine:page',
AFFINE_FRAME_TITLE_WIDGET,
literal`${unsafeStatic(AFFINE_FRAME_TITLE_WIDGET)}`
);

View File

@@ -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);
}

View File

@@ -9,6 +9,7 @@
"references": [ "references": [
{ "path": "../../components" }, { "path": "../../components" },
{ "path": "../../model" }, { "path": "../../model" },
{ "path": "../../rich-text" },
{ "path": "../../shared" }, { "path": "../../shared" },
{ "path": "../../../framework/block-std" }, { "path": "../../../framework/block-std" },
{ "path": "../../../framework/global" } { "path": "../../../framework/global" }

View File

@@ -195,6 +195,7 @@ export const PackageList = [
'blocksuite/affine/components', 'blocksuite/affine/components',
'blocksuite/affine/model', 'blocksuite/affine/model',
'blocksuite/affine/shared', 'blocksuite/affine/shared',
'blocksuite/affine/widgets/widget-frame-title',
'blocksuite/framework/block-std', 'blocksuite/framework/block-std',
'blocksuite/framework/global', 'blocksuite/framework/global',
'blocksuite/framework/inline', 'blocksuite/framework/inline',
@@ -531,6 +532,7 @@ export const PackageList = [
workspaceDependencies: [ workspaceDependencies: [
'blocksuite/affine/components', 'blocksuite/affine/components',
'blocksuite/affine/model', 'blocksuite/affine/model',
'blocksuite/affine/rich-text',
'blocksuite/affine/shared', 'blocksuite/affine/shared',
'blocksuite/framework/block-std', 'blocksuite/framework/block-std',
'blocksuite/framework/global', 'blocksuite/framework/global',

View File

@@ -2558,8 +2558,10 @@ __metadata:
"@blocksuite/affine-components": "workspace:*" "@blocksuite/affine-components": "workspace:*"
"@blocksuite/affine-model": "workspace:*" "@blocksuite/affine-model": "workspace:*"
"@blocksuite/affine-shared": "workspace:*" "@blocksuite/affine-shared": "workspace:*"
"@blocksuite/affine-widget-frame-title": "workspace:*"
"@blocksuite/block-std": "workspace:*" "@blocksuite/block-std": "workspace:*"
"@blocksuite/global": "workspace:*" "@blocksuite/global": "workspace:*"
"@blocksuite/icons": "npm:^2.2.6"
"@blocksuite/inline": "workspace:*" "@blocksuite/inline": "workspace:*"
"@blocksuite/store": "workspace:*" "@blocksuite/store": "workspace:*"
"@floating-ui/dom": "npm:^1.6.13" "@floating-ui/dom": "npm:^1.6.13"
@@ -3165,6 +3167,7 @@ __metadata:
dependencies: dependencies:
"@blocksuite/affine-components": "workspace:*" "@blocksuite/affine-components": "workspace:*"
"@blocksuite/affine-model": "workspace:*" "@blocksuite/affine-model": "workspace:*"
"@blocksuite/affine-rich-text": "workspace:*"
"@blocksuite/affine-shared": "workspace:*" "@blocksuite/affine-shared": "workspace:*"
"@blocksuite/block-std": "workspace:*" "@blocksuite/block-std": "workspace:*"
"@blocksuite/global": "workspace:*" "@blocksuite/global": "workspace:*"