refactor(editor): extract common toolbar config (#11069)
This commit is contained in:
@@ -6,6 +6,11 @@ import {
|
|||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
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 {
|
||||||
|
Menu,
|
||||||
|
MenuItem,
|
||||||
|
} from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
|
import { renderMenuItems } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import type { GfxModel } from '@blocksuite/block-std/gfx';
|
import type { GfxModel } from '@blocksuite/block-std/gfx';
|
||||||
import { Bound } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
import {
|
import {
|
||||||
@@ -23,9 +28,6 @@ import {
|
|||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import type { Menu, MenuItem } from './types';
|
|
||||||
import { renderMenuItems } from './utils';
|
|
||||||
|
|
||||||
enum Alignment {
|
enum Alignment {
|
||||||
None,
|
None,
|
||||||
AutoArrange,
|
AutoArrange,
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ import {
|
|||||||
getMostCommonResolvedValue,
|
getMostCommonResolvedValue,
|
||||||
getMostCommonValue,
|
getMostCommonValue,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
|
import type { MenuItem } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
|
import {
|
||||||
|
createTextActions,
|
||||||
|
getRootBlock,
|
||||||
|
LINE_STYLE_LIST,
|
||||||
|
renderMenu,
|
||||||
|
} from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import { Bound } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
import {
|
import {
|
||||||
AddTextIcon,
|
AddTextIcon,
|
||||||
@@ -51,10 +58,6 @@ import { html } from 'lit';
|
|||||||
import { styleMap } from 'lit/directives/style-map.js';
|
import { styleMap } from 'lit/directives/style-map.js';
|
||||||
|
|
||||||
import { mountConnectorLabelEditor } from '../../utils/text';
|
import { mountConnectorLabelEditor } from '../../utils/text';
|
||||||
import { LINE_STYLE_LIST } from './consts';
|
|
||||||
import { createTextActions } from './text-common';
|
|
||||||
import type { MenuItem } from './types';
|
|
||||||
import { getRootBlock, renderMenu } from './utils';
|
|
||||||
|
|
||||||
const FRONT_ENDPOINT_STYLE_LIST = [
|
const FRONT_ENDPOINT_STYLE_LIST = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { EdgelessTextBlockModel } from '@blocksuite/affine-model';
|
import { EdgelessTextBlockModel } from '@blocksuite/affine-model';
|
||||||
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
||||||
|
import { createTextActions } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import { createTextActions } from './text-common';
|
|
||||||
|
|
||||||
export const builtinEdgelessTextToolbarConfig = {
|
export const builtinEdgelessTextToolbarConfig = {
|
||||||
// No need to adjust element bounds, which updates itself using ResizeObserver
|
// No need to adjust element bounds, which updates itself using ResizeObserver
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import {
|
|||||||
} from '@blocksuite/affine-model';
|
} from '@blocksuite/affine-model';
|
||||||
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
||||||
import { matchModels } from '@blocksuite/affine-shared/utils';
|
import { matchModels } from '@blocksuite/affine-shared/utils';
|
||||||
|
import { getRootBlock } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
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 { EdgelessRootService } from '../../edgeless-root-service';
|
||||||
import { mountGroupTitleEditor } from '../../utils/text';
|
import { mountGroupTitleEditor } from '../../utils/text';
|
||||||
import { getEdgelessWith, getRootBlock } from './utils';
|
|
||||||
|
|
||||||
export const builtinGroupToolbarConfig = {
|
export const builtinGroupToolbarConfig = {
|
||||||
actions: [
|
actions: [
|
||||||
@@ -84,11 +85,10 @@ export const builtinGroupToolbarConfig = {
|
|||||||
const models = ctx.getSurfaceModelsByType(GroupElementModel);
|
const models = ctx.getSurfaceModelsByType(GroupElementModel);
|
||||||
if (!models.length) return;
|
if (!models.length) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
const edgelessService = ctx.std.get(EdgelessRootService);
|
||||||
if (!edgeless) return;
|
|
||||||
|
|
||||||
for (const model of models) {
|
for (const model of models) {
|
||||||
edgeless.service.ungroup(model);
|
edgelessService.ungroup(model);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ import type {
|
|||||||
ToolbarModuleConfig,
|
ToolbarModuleConfig,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { getMostCommonValue } from '@blocksuite/affine-shared/utils';
|
import { getMostCommonValue } from '@blocksuite/affine-shared/utils';
|
||||||
|
import {
|
||||||
|
type MenuItem,
|
||||||
|
renderMenu,
|
||||||
|
} from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import { RadiantIcon, RightLayoutIcon, StyleIcon } from '@blocksuite/icons/lit';
|
import { RadiantIcon, RightLayoutIcon, StyleIcon } from '@blocksuite/icons/lit';
|
||||||
|
|
||||||
import type { MenuItem } from './types';
|
|
||||||
import { renderMenu } from './utils';
|
|
||||||
|
|
||||||
const MINDMAP_STYLE_LIST = [
|
const MINDMAP_STYLE_LIST = [
|
||||||
{
|
{
|
||||||
value: MindmapStyle.ONE,
|
value: MindmapStyle.ONE,
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
import { EdgelessFrameManagerIdentifier } from '@blocksuite/affine-block-frame';
|
||||||
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
getSurfaceComponent,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
ConnectorElementModel,
|
ConnectorElementModel,
|
||||||
DEFAULT_CONNECTOR_MODE,
|
DEFAULT_CONNECTOR_MODE,
|
||||||
@@ -25,9 +29,9 @@ import {
|
|||||||
} from '@blocksuite/icons/lit';
|
} from '@blocksuite/icons/lit';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
|
|
||||||
|
import { EdgelessRootService } from '../../edgeless-root-service';
|
||||||
import { renderAlignmentMenu } from './alignment';
|
import { renderAlignmentMenu } from './alignment';
|
||||||
import { moreActions } from './more';
|
import { moreActions } from './more';
|
||||||
import { getEdgelessWith } from './utils';
|
|
||||||
|
|
||||||
export const builtinMiscToolbarConfig = {
|
export const builtinMiscToolbarConfig = {
|
||||||
actions: [
|
actions: [
|
||||||
@@ -88,14 +92,16 @@ export const builtinMiscToolbarConfig = {
|
|||||||
const models = ctx.getSurfaceModels();
|
const models = ctx.getSurfaceModels();
|
||||||
if (models.length < 2) return;
|
if (models.length < 2) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
const surface = getSurfaceComponent(ctx.std);
|
||||||
if (!edgeless) return;
|
if (!surface) return;
|
||||||
|
|
||||||
const frame = edgeless.service.frame.createFrameOnSelected();
|
const frameManager = ctx.std.get(EdgelessFrameManagerIdentifier);
|
||||||
|
|
||||||
|
const frame = frameManager.createFrameOnSelected();
|
||||||
if (!frame) return;
|
if (!frame) return;
|
||||||
|
|
||||||
// TODO(@fundon): should be a command
|
// TODO(@fundon): should be a command
|
||||||
edgeless.surface.fitToViewport(Bound.deserialize(frame.xywh));
|
surface.fitToViewport(Bound.deserialize(frame.xywh));
|
||||||
|
|
||||||
ctx.track('CanvasElementAdded', {
|
ctx.track('CanvasElementAdded', {
|
||||||
control: 'context-menu',
|
control: 'context-menu',
|
||||||
@@ -131,11 +137,10 @@ export const builtinMiscToolbarConfig = {
|
|||||||
const models = ctx.getSurfaceModels();
|
const models = ctx.getSurfaceModels();
|
||||||
if (models.length < 2) return;
|
if (models.length < 2) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
const service = ctx.std.get(EdgelessRootService);
|
||||||
if (!edgeless) return;
|
|
||||||
|
|
||||||
// TODO(@fundon): should be a command
|
// TODO(@fundon): should be a command
|
||||||
edgeless.service.createGroupFromSelected();
|
service.createGroupFromSelected();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -216,9 +221,6 @@ export const builtinMiscToolbarConfig = {
|
|||||||
const models = ctx.getSurfaceModels();
|
const models = ctx.getSurfaceModels();
|
||||||
if (!models.length) return;
|
if (!models.length) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
|
||||||
if (!edgeless) return;
|
|
||||||
|
|
||||||
// get most top selected elements(*) from tree, like in a tree below
|
// get most top selected elements(*) from tree, like in a tree below
|
||||||
// G0
|
// G0
|
||||||
// / \
|
// / \
|
||||||
@@ -266,10 +268,8 @@ export const builtinMiscToolbarConfig = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupId = edgeless.service.createGroup([
|
const service = ctx.std.get(EdgelessRootService);
|
||||||
topElement,
|
const groupId = service.createGroup([topElement, ...otherElements]);
|
||||||
...otherElements,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (groupId) {
|
if (groupId) {
|
||||||
const element = ctx.std
|
const element = ctx.std
|
||||||
@@ -325,9 +325,6 @@ export const builtinLockedToolbarConfig = {
|
|||||||
const models = ctx.getSurfaceModels();
|
const models = ctx.getSurfaceModels();
|
||||||
if (!models.length) return;
|
if (!models.length) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
|
||||||
if (!edgeless) return;
|
|
||||||
|
|
||||||
const elements = new Set(
|
const elements = new Set(
|
||||||
models.map(model =>
|
models.map(model =>
|
||||||
ctx.matchModel(model.group, MindmapElementModel)
|
ctx.matchModel(model.group, MindmapElementModel)
|
||||||
@@ -338,9 +335,11 @@ export const builtinLockedToolbarConfig = {
|
|||||||
|
|
||||||
ctx.store.captureSync();
|
ctx.store.captureSync();
|
||||||
|
|
||||||
|
const service = ctx.std.get(EdgelessRootService);
|
||||||
|
|
||||||
for (const element of elements) {
|
for (const element of elements) {
|
||||||
if (element instanceof GroupElementModel) {
|
if (element instanceof GroupElementModel) {
|
||||||
edgeless.service.ungroup(element);
|
service.ungroup(element);
|
||||||
} else {
|
} else {
|
||||||
element.lockedBySelf = false;
|
element.lockedBySelf = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import {
|
|||||||
} from '@blocksuite/affine-block-embed';
|
} from '@blocksuite/affine-block-embed';
|
||||||
import { EdgelessFrameManagerIdentifier } from '@blocksuite/affine-block-frame';
|
import { EdgelessFrameManagerIdentifier } from '@blocksuite/affine-block-frame';
|
||||||
import { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
import { ImageBlockComponent } from '@blocksuite/affine-block-image';
|
||||||
import { EdgelessCRUDIdentifier } from '@blocksuite/affine-block-surface';
|
import {
|
||||||
|
EdgelessCRUDIdentifier,
|
||||||
|
getSurfaceComponent,
|
||||||
|
} from '@blocksuite/affine-block-surface';
|
||||||
import {
|
import {
|
||||||
AttachmentBlockModel,
|
AttachmentBlockModel,
|
||||||
BookmarkBlockModel,
|
BookmarkBlockModel,
|
||||||
@@ -42,6 +45,7 @@ import {
|
|||||||
ResetIcon,
|
ResetIcon,
|
||||||
} from '@blocksuite/icons/lit';
|
} from '@blocksuite/icons/lit';
|
||||||
|
|
||||||
|
import { EdgelessRootService } from '../../edgeless-root-service';
|
||||||
import { duplicate } from '../../utils/clipboard-utils';
|
import { duplicate } from '../../utils/clipboard-utils';
|
||||||
import { getSortedCloneElements } from '../../utils/clone-utils';
|
import { getSortedCloneElements } from '../../utils/clone-utils';
|
||||||
import { moveConnectors } from '../../utils/connector';
|
import { moveConnectors } from '../../utils/connector';
|
||||||
@@ -67,10 +71,10 @@ export const moreActions = [
|
|||||||
.createFrameOnSelected();
|
.createFrameOnSelected();
|
||||||
if (!frame) return;
|
if (!frame) return;
|
||||||
|
|
||||||
const edgeless = getEdgelessWith(ctx);
|
const surface = getSurfaceComponent(ctx.std);
|
||||||
if (!edgeless) return;
|
if (!surface) return;
|
||||||
|
|
||||||
edgeless.surface.fitToViewport(Bound.deserialize(frame.xywh));
|
surface.fitToViewport(Bound.deserialize(frame.xywh));
|
||||||
|
|
||||||
ctx.track('CanvasElementAdded', {
|
ctx.track('CanvasElementAdded', {
|
||||||
control: 'context-menu',
|
control: 'context-menu',
|
||||||
@@ -88,10 +92,8 @@ export const moreActions = [
|
|||||||
return !models.some(model => ctx.matchModel(model, FrameBlockModel));
|
return !models.some(model => ctx.matchModel(model, FrameBlockModel));
|
||||||
},
|
},
|
||||||
run(ctx) {
|
run(ctx) {
|
||||||
const edgeless = getEdgelessWith(ctx);
|
const service = ctx.std.get(EdgelessRootService);
|
||||||
if (!edgeless) return;
|
service.createGroupFromSelected();
|
||||||
|
|
||||||
edgeless.service.createGroupFromSelected();
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -34,18 +34,21 @@ import type {
|
|||||||
ToolbarModuleConfig,
|
ToolbarModuleConfig,
|
||||||
} from '@blocksuite/affine-shared/services';
|
} from '@blocksuite/affine-shared/services';
|
||||||
import { getMostCommonValue } from '@blocksuite/affine-shared/utils';
|
import { getMostCommonValue } from '@blocksuite/affine-shared/utils';
|
||||||
|
import {
|
||||||
|
createTextActions,
|
||||||
|
getRootBlock,
|
||||||
|
LINE_STYLE_LIST,
|
||||||
|
renderMenu,
|
||||||
|
} from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import { Bound } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
import { AddTextIcon, ShapeIcon } from '@blocksuite/icons/lit';
|
import { AddTextIcon, ShapeIcon } from '@blocksuite/icons/lit';
|
||||||
import { html } from 'lit';
|
import { html } from 'lit';
|
||||||
import isEqual from 'lodash-es/isEqual';
|
import isEqual from 'lodash-es/isEqual';
|
||||||
|
|
||||||
import { LINE_STYLE_LIST } from './consts';
|
|
||||||
import {
|
import {
|
||||||
createMindmapLayoutActionMenu,
|
createMindmapLayoutActionMenu,
|
||||||
createMindmapStyleActionMenu,
|
createMindmapStyleActionMenu,
|
||||||
} from './mindmap';
|
} from './mindmap';
|
||||||
import { createTextActions } from './text-common';
|
|
||||||
import { getRootBlock, renderMenu } from './utils';
|
|
||||||
|
|
||||||
export const builtinShapeToolbarConfig = {
|
export const builtinShapeToolbarConfig = {
|
||||||
actions: [
|
actions: [
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import {
|
|||||||
} from '@blocksuite/affine-block-surface';
|
} from '@blocksuite/affine-block-surface';
|
||||||
import { TextElementModel } from '@blocksuite/affine-model';
|
import { TextElementModel } from '@blocksuite/affine-model';
|
||||||
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
import { type ToolbarModuleConfig } from '@blocksuite/affine-shared/services';
|
||||||
|
import { createTextActions } from '@blocksuite/affine-widget-edgeless-toolbar';
|
||||||
import { Bound } from '@blocksuite/global/gfx';
|
import { Bound } from '@blocksuite/global/gfx';
|
||||||
|
|
||||||
import { createTextActions } from './text-common';
|
|
||||||
|
|
||||||
export const builtinTextToolbarConfig = {
|
export const builtinTextToolbarConfig = {
|
||||||
actions: createTextActions(TextElementModel, 'text', (ctx, model, props) => {
|
actions: createTextActions(TextElementModel, 'text', (ctx, model, props) => {
|
||||||
// No need to adjust element bounds
|
// No need to adjust element bounds
|
||||||
|
|||||||
@@ -1,69 +1,6 @@
|
|||||||
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 { ifDefined } from 'lit/directives/if-defined.js';
|
|
||||||
import { repeat } from 'lit/directives/repeat.js';
|
|
||||||
|
|
||||||
import { EdgelessRootBlockComponent } from '../..';
|
import { EdgelessRootBlockComponent } from '../..';
|
||||||
import type { Menu, MenuItem } from './types';
|
|
||||||
|
|
||||||
export function renderCurrentMenuItemWith<T, F extends keyof MenuItem<T>>(
|
|
||||||
items: MenuItem<T>[],
|
|
||||||
currentValue: T,
|
|
||||||
field: F
|
|
||||||
) {
|
|
||||||
return items.find(({ value }) => value === currentValue)?.[field];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderMenu<T>({
|
|
||||||
label,
|
|
||||||
tooltip,
|
|
||||||
icon,
|
|
||||||
items,
|
|
||||||
currentValue,
|
|
||||||
onPick,
|
|
||||||
}: Menu<T>) {
|
|
||||||
return html`
|
|
||||||
<editor-menu-button
|
|
||||||
aria-label="${`${label.toLowerCase()}-menu`}"
|
|
||||||
.button=${html`
|
|
||||||
<editor-icon-button
|
|
||||||
aria-label="${label}"
|
|
||||||
.tooltip="${tooltip ?? label}"
|
|
||||||
>
|
|
||||||
${icon ?? renderCurrentMenuItemWith(items, currentValue, 'icon')}
|
|
||||||
${EditorChevronDown}
|
|
||||||
</editor-icon-button>
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
${renderMenuItems(items, currentValue, onPick)}
|
|
||||||
</editor-menu-button>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function renderMenuItems<T>(
|
|
||||||
items: MenuItem<T>[],
|
|
||||||
currentValue: T,
|
|
||||||
onPick: (value: T) => void
|
|
||||||
) {
|
|
||||||
return repeat(
|
|
||||||
items,
|
|
||||||
item => item.value,
|
|
||||||
({ key, value, icon, disabled }) => html`
|
|
||||||
<editor-icon-button
|
|
||||||
aria-label="${ifDefined(key)}"
|
|
||||||
.disabled=${ifDefined(disabled)}
|
|
||||||
.tooltip="${ifDefined(key)}"
|
|
||||||
.active="${currentValue === value}"
|
|
||||||
.activeMode="${'background'}"
|
|
||||||
@click=${() => onPick(value)}
|
|
||||||
>
|
|
||||||
${icon}
|
|
||||||
</editor-icon-button>
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(@fundon): it should be simple
|
// TODO(@fundon): it should be simple
|
||||||
export function getEdgelessWith(ctx: ToolbarContext) {
|
export function getEdgelessWith(ctx: ToolbarContext) {
|
||||||
@@ -78,10 +15,3 @@ 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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export {
|
|||||||
getBgGridGap,
|
getBgGridGap,
|
||||||
getLastPropsKey,
|
getLastPropsKey,
|
||||||
getSurfaceBlock,
|
getSurfaceBlock,
|
||||||
|
getSurfaceComponent,
|
||||||
normalizeWheelDeltaY,
|
normalizeWheelDeltaY,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
export * from './utils/mindmap/style-svg';
|
export * from './utils/mindmap/style-svg';
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
|
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||||
import type { Store } from '@blocksuite/store';
|
import type { Store } from '@blocksuite/store';
|
||||||
|
|
||||||
|
import type { SurfaceBlockComponent } from '../surface-block';
|
||||||
import type { SurfaceBlockModel } from '../surface-model';
|
import type { SurfaceBlockModel } from '../surface-model';
|
||||||
|
|
||||||
export function getSurfaceBlock(doc: Store) {
|
export function getSurfaceBlock(doc: Store) {
|
||||||
const blocks = doc.getBlocksByFlavour('affine:surface');
|
const blocks = doc.getBlocksByFlavour('affine:surface');
|
||||||
return blocks.length !== 0 ? (blocks[0].model as SurfaceBlockModel) : null;
|
return blocks.length !== 0 ? (blocks[0].model as SurfaceBlockModel) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSurfaceComponent(std: BlockStdScope) {
|
||||||
|
const surface = getSurfaceBlock(std.store);
|
||||||
|
if (!surface) return null;
|
||||||
|
return std.view.getBlock(surface.id) as SurfaceBlockComponent | null;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ export function normalizeWheelDeltaY(delta: number, zoom = 1) {
|
|||||||
export { addNote, addNoteAtPoint } from './add-note';
|
export { addNote, addNoteAtPoint } from './add-note';
|
||||||
export { getBgGridGap } from './get-bg-grip-gap';
|
export { getBgGridGap } from './get-bg-grip-gap';
|
||||||
export { getLastPropsKey } from './get-last-props-key';
|
export { getLastPropsKey } from './get-last-props-key';
|
||||||
export { getSurfaceBlock } from './get-surface-block';
|
export * from './get-surface-block';
|
||||||
export * from './mindmap/style-svg.js';
|
export * from './mindmap/style-svg.js';
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './consts.js';
|
||||||
|
export * from './text-common.js';
|
||||||
|
export * from './types.js';
|
||||||
|
export * from './utils.js';
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
import type { Menu, MenuItem } from './types';
|
||||||
|
|
||||||
|
export function renderCurrentMenuItemWith<T, F extends keyof MenuItem<T>>(
|
||||||
|
items: MenuItem<T>[],
|
||||||
|
currentValue: T,
|
||||||
|
field: F
|
||||||
|
) {
|
||||||
|
return items.find(({ value }) => value === currentValue)?.[field];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderMenu<T>({
|
||||||
|
label,
|
||||||
|
tooltip,
|
||||||
|
icon,
|
||||||
|
items,
|
||||||
|
currentValue,
|
||||||
|
onPick,
|
||||||
|
}: Menu<T>) {
|
||||||
|
return html`
|
||||||
|
<editor-menu-button
|
||||||
|
aria-label="${`${label.toLowerCase()}-menu`}"
|
||||||
|
.button=${html`
|
||||||
|
<editor-icon-button
|
||||||
|
aria-label="${label}"
|
||||||
|
.tooltip="${tooltip ?? label}"
|
||||||
|
>
|
||||||
|
${icon ?? renderCurrentMenuItemWith(items, currentValue, 'icon')}
|
||||||
|
${EditorChevronDown}
|
||||||
|
</editor-icon-button>
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
${renderMenuItems(items, currentValue, onPick)}
|
||||||
|
</editor-menu-button>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function renderMenuItems<T>(
|
||||||
|
items: MenuItem<T>[],
|
||||||
|
currentValue: T,
|
||||||
|
onPick: (value: T) => void
|
||||||
|
) {
|
||||||
|
return repeat(
|
||||||
|
items,
|
||||||
|
item => item.value,
|
||||||
|
({ key, value, icon, disabled }) => html`
|
||||||
|
<editor-icon-button
|
||||||
|
aria-label="${ifDefined(key)}"
|
||||||
|
.disabled=${ifDefined(disabled)}
|
||||||
|
.tooltip="${ifDefined(key)}"
|
||||||
|
.active="${currentValue === value}"
|
||||||
|
.activeMode="${'background'}"
|
||||||
|
@click=${() => onPick(value)}
|
||||||
|
>
|
||||||
|
${icon}
|
||||||
|
</editor-icon-button>
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getRootBlock(ctx: ToolbarContext): BlockComponent | null {
|
||||||
|
const rootModel = ctx.store.root;
|
||||||
|
if (!rootModel) return null;
|
||||||
|
|
||||||
|
return ctx.view.getBlock(rootModel.id);
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export * from './config';
|
||||||
export * from './context';
|
export * from './context';
|
||||||
export * from './create-popper';
|
export * from './create-popper';
|
||||||
export * from './draggable';
|
export * from './draggable';
|
||||||
|
|||||||
Reference in New Issue
Block a user