@formicoidea/labre-core 0.58.0 → 0.60.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/architecture/code.c4 +175 -144
  2. package/architecture/domain.c4 +15 -9
  3. package/architecture/likec4.config.json +3 -3
  4. package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.d.ts +3 -2
  5. package/dist/_pkgs/affine-block-attachment/edgeless-clipboard-config.js +18 -13
  6. package/dist/_pkgs/affine-block-callout/adapters/markdown.js +4 -1
  7. package/dist/_pkgs/affine-block-code/adapters/html.js +1 -1
  8. package/dist/_pkgs/affine-block-code/adapters/markdown/preprocessor.js +13 -1
  9. package/dist/_pkgs/affine-block-code/adapters/notion-html.js +1 -1
  10. package/dist/_pkgs/affine-block-code/code-block.d.ts +17 -2
  11. package/dist/_pkgs/affine-block-code/code-block.js +28 -23
  12. package/dist/_pkgs/affine-block-code/code-toolbar/components/lang-button.js +17 -4
  13. package/dist/_pkgs/affine-block-code/code-toolbar/components/preview-button.js +1 -1
  14. package/dist/_pkgs/affine-block-data-view/data-source.js +12 -5
  15. package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.d.ts +3 -2
  16. package/dist/_pkgs/affine-block-edgeless-text/edgeless-clipboard-config.js +8 -5
  17. package/dist/_pkgs/affine-block-image/asset-picker.d.ts +23 -2
  18. package/dist/_pkgs/affine-block-image/asset-picker.js +52 -12
  19. package/dist/_pkgs/affine-block-image/configs/replace-action.d.ts +8 -5
  20. package/dist/_pkgs/affine-block-image/configs/replace-action.js +8 -8
  21. package/dist/_pkgs/affine-block-image/configs/toolbar.js +2 -1
  22. package/dist/_pkgs/affine-block-image/crop/crop-controller.d.ts +15 -0
  23. package/dist/_pkgs/affine-block-image/crop/crop-controller.js +40 -2
  24. package/dist/_pkgs/affine-block-image/crop/crop-math.d.ts +22 -0
  25. package/dist/_pkgs/affine-block-image/crop/crop-math.js +55 -2
  26. package/dist/_pkgs/affine-block-image/crop/crop-overlay.d.ts +17 -3
  27. package/dist/_pkgs/affine-block-image/crop/crop-overlay.js +64 -6
  28. package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.d.ts +3 -2
  29. package/dist/_pkgs/affine-block-image/edgeless-clipboard-config.js +20 -14
  30. package/dist/_pkgs/affine-block-image/image-block.js +1 -0
  31. package/dist/_pkgs/affine-block-image/image-edgeless-block.js +3 -0
  32. package/dist/_pkgs/affine-block-image/index.d.ts +2 -0
  33. package/dist/_pkgs/affine-block-image/index.js +2 -0
  34. package/dist/_pkgs/affine-block-image/replace/commands.d.ts +68 -0
  35. package/dist/_pkgs/affine-block-image/replace/commands.js +200 -0
  36. package/dist/_pkgs/affine-block-image/replace/replace-model.d.ts +44 -0
  37. package/dist/_pkgs/affine-block-image/replace/replace-model.js +168 -0
  38. package/dist/_pkgs/affine-block-image/replace/toolbar.d.ts +21 -0
  39. package/dist/_pkgs/affine-block-image/replace/toolbar.js +159 -0
  40. package/dist/_pkgs/affine-block-image/translations.d.ts +15 -2
  41. package/dist/_pkgs/affine-block-image/translations.js +35 -2
  42. package/dist/_pkgs/affine-block-image/utils.d.ts +7 -0
  43. package/dist/_pkgs/affine-block-image/utils.js +13 -0
  44. package/dist/_pkgs/affine-block-image/view.js +7 -0
  45. package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.d.ts +14 -5
  46. package/dist/_pkgs/affine-block-note/components/edgeless-page-block-title.js +18 -11
  47. package/dist/_pkgs/affine-block-note/config.d.ts +9 -2
  48. package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.d.ts +3 -2
  49. package/dist/_pkgs/affine-block-note/edgeless-clipboard-config.js +8 -5
  50. package/dist/_pkgs/affine-block-paragraph/adapters/markdown.js +11 -0
  51. package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.d.ts +17 -0
  52. package/dist/_pkgs/affine-block-root/commands/invisible-characters-commands.js +123 -0
  53. package/dist/_pkgs/affine-block-root/edgeless/clipboard/command.js +82 -65
  54. package/dist/_pkgs/affine-block-root/edgeless/edgeless-keyboard.js +2 -0
  55. package/dist/_pkgs/affine-block-root/index.d.ts +1 -0
  56. package/dist/_pkgs/affine-block-root/index.js +1 -0
  57. package/dist/_pkgs/affine-block-root/translations.d.ts +6 -0
  58. package/dist/_pkgs/affine-block-root/translations.js +10 -0
  59. package/dist/_pkgs/affine-block-root/view.js +6 -1
  60. package/dist/_pkgs/affine-block-surface/commands/index.d.ts +1 -1
  61. package/dist/_pkgs/affine-block-surface/commands/index.js +1 -1
  62. package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.d.ts +9 -0
  63. package/dist/_pkgs/affine-block-surface/commands/reassociate-connectors.js +21 -12
  64. package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.d.ts +33 -0
  65. package/dist/_pkgs/affine-block-surface/extensions/clipboard-config.js +53 -0
  66. package/dist/_pkgs/affine-block-surface/extensions/index.d.ts +1 -0
  67. package/dist/_pkgs/affine-block-surface/extensions/index.js +1 -0
  68. package/dist/_pkgs/affine-block-surface/extensions/legend-label.d.ts +11 -0
  69. package/dist/_pkgs/affine-block-surface/extensions/legend-label.js +16 -0
  70. package/dist/_pkgs/affine-block-surface/extensions/legend.d.ts +1 -11
  71. package/dist/_pkgs/affine-block-surface/extensions/legend.js +2 -11
  72. package/dist/_pkgs/affine-block-surface/extensions/reading-toolbar.js +12 -12
  73. package/dist/_pkgs/affine-block-surface/extensions/toolbox.d.ts +62 -0
  74. package/dist/_pkgs/affine-block-surface/extensions/toolbox.js +1 -0
  75. package/dist/_pkgs/affine-block-surface/framework-background/background-view.js +2 -1
  76. package/dist/_pkgs/affine-block-surface/framework-background/band-widths.d.ts +104 -0
  77. package/dist/_pkgs/affine-block-surface/framework-background/band-widths.js +156 -0
  78. package/dist/_pkgs/affine-block-surface/framework-background/def.d.ts +87 -4
  79. package/dist/_pkgs/affine-block-surface/framework-background/def.js +26 -7
  80. package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.d.ts +58 -0
  81. package/dist/_pkgs/affine-block-surface/framework-background/ellipsis.js +110 -0
  82. package/dist/_pkgs/affine-block-surface/framework-background/index.d.ts +3 -0
  83. package/dist/_pkgs/affine-block-surface/framework-background/index.js +3 -0
  84. package/dist/_pkgs/affine-block-surface/framework-background/labels.d.ts +12 -2
  85. package/dist/_pkgs/affine-block-surface/framework-background/labels.js +29 -5
  86. package/dist/_pkgs/affine-block-surface/framework-background/measure-text.d.ts +14 -0
  87. package/dist/_pkgs/affine-block-surface/framework-background/measure-text.js +31 -0
  88. package/dist/_pkgs/affine-block-surface/framework-background/renderer.d.ts +14 -1
  89. package/dist/_pkgs/affine-block-surface/framework-background/renderer.js +84 -31
  90. package/dist/_pkgs/affine-block-surface/interchange-headless.d.ts +2 -0
  91. package/dist/_pkgs/affine-block-surface/interchange-headless.js +2 -0
  92. package/dist/_pkgs/affine-block-table/adapters/html.js +26 -14
  93. package/dist/_pkgs/affine-block-table/adapters/utils.d.ts +1 -0
  94. package/dist/_pkgs/affine-block-table/adapters/utils.js +23 -5
  95. package/dist/_pkgs/affine-block-table/header-menu.d.ts +13 -0
  96. package/dist/_pkgs/affine-block-table/header-menu.js +25 -0
  97. package/dist/_pkgs/affine-block-table/selection-controller.d.ts +15 -0
  98. package/dist/_pkgs/affine-block-table/selection-controller.js +62 -0
  99. package/dist/_pkgs/affine-block-table/table-cell-css.d.ts +7 -0
  100. package/dist/_pkgs/affine-block-table/table-cell-css.js +10 -0
  101. package/dist/_pkgs/affine-block-table/table-cell.d.ts +8 -0
  102. package/dist/_pkgs/affine-block-table/table-cell.js +35 -3
  103. package/dist/_pkgs/affine-block-table/table-data-manager.d.ts +14 -0
  104. package/dist/_pkgs/affine-block-table/table-data-manager.js +44 -3
  105. package/dist/_pkgs/affine-block-table/translations.d.ts +14 -0
  106. package/dist/_pkgs/affine-block-table/translations.js +22 -0
  107. package/dist/_pkgs/affine-components/highlight-dropdown-menu/highlight-duotone-icon.js +8 -8
  108. package/dist/_pkgs/affine-components/highlight-dropdown-menu/text-duotone-icon.js +11 -11
  109. package/dist/_pkgs/affine-gfx-mindmap/toolbar/mindmap-tool-button.d.ts +2 -2
  110. package/dist/_pkgs/affine-gfx-template/builtin/other.d.ts +4 -0
  111. package/dist/_pkgs/affine-gfx-template/builtin/other.js +1 -1
  112. package/dist/_pkgs/affine-gfx-template/builtin/slides/build.d.ts +81 -0
  113. package/dist/_pkgs/affine-gfx-template/builtin/slides/build.js +276 -0
  114. package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.d.ts +126 -0
  115. package/dist/_pkgs/affine-gfx-template/builtin/slides/consts.js +101 -0
  116. package/dist/_pkgs/affine-gfx-template/builtin/slides/index.d.ts +8 -0
  117. package/dist/_pkgs/affine-gfx-template/builtin/slides/index.js +27 -0
  118. package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.d.ts +83 -0
  119. package/dist/_pkgs/affine-gfx-template/builtin/slides/masks.js +674 -0
  120. package/dist/_pkgs/affine-gfx-template/contribute.js +12 -17
  121. package/dist/_pkgs/affine-gfx-template/make-snapshot.d.ts +14 -2
  122. package/dist/_pkgs/affine-gfx-template/make-snapshot.js +6 -2
  123. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.d.ts +12 -0
  124. package/dist/_pkgs/affine-gfx-template/services/template-middlewares.js +48 -0
  125. package/dist/_pkgs/affine-gfx-template/services/template.js +2 -1
  126. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.d.ts +15 -1
  127. package/dist/_pkgs/affine-gfx-template/toolbar/builtin-templates.js +33 -37
  128. package/dist/_pkgs/affine-gfx-template/toolbar/template-type.d.ts +6 -0
  129. package/dist/_pkgs/affine-gfx-template/translations.d.ts +94 -0
  130. package/dist/_pkgs/affine-gfx-template/translations.js +441 -2
  131. package/dist/_pkgs/affine-model/blocks/table/table-model.d.ts +4 -0
  132. package/dist/_pkgs/affine-model/blocks/table/table-model.js +4 -0
  133. package/dist/_pkgs/affine-model/elements/bpmn/node.d.ts +46 -3
  134. package/dist/_pkgs/affine-model/elements/bpmn/node.js +47 -4
  135. package/dist/_pkgs/affine-model/elements/bpmn/pool.d.ts +20 -0
  136. package/dist/_pkgs/affine-model/elements/bpmn/pool.js +33 -4
  137. package/dist/_pkgs/affine-model/elements/c4/board.d.ts +0 -22
  138. package/dist/_pkgs/affine-model/elements/c4/board.js +1 -22
  139. package/dist/_pkgs/affine-model/elements/c4/consts.d.ts +29 -0
  140. package/dist/_pkgs/affine-model/elements/c4/consts.js +29 -0
  141. package/dist/_pkgs/affine-model/elements/c4/index.d.ts +1 -0
  142. package/dist/_pkgs/affine-model/elements/c4/index.js +1 -0
  143. package/dist/_pkgs/affine-model/headless.d.ts +1 -0
  144. package/dist/_pkgs/affine-model/headless.js +1 -0
  145. package/dist/_pkgs/affine-shared/services/edit-props-store.d.ts +3 -16
  146. package/dist/_pkgs/affine-shared/services/edit-props-store.js +16 -16
  147. package/dist/_pkgs/affine-shared/services/editor-setting-service.d.ts +3 -0
  148. package/dist/_pkgs/affine-shared/services/editor-setting-service.js +4 -0
  149. package/dist/_pkgs/affine-shared/services/index.d.ts +1 -0
  150. package/dist/_pkgs/affine-shared/services/index.js +1 -0
  151. package/dist/_pkgs/affine-shared/services/invisible-characters.d.ts +33 -0
  152. package/dist/_pkgs/affine-shared/services/invisible-characters.js +63 -0
  153. package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.d.ts +0 -9
  154. package/dist/_pkgs/affine-shared/services/link-preview-service/link-preview-cache.js +3 -9
  155. package/dist/_pkgs/affine-shared/services/telemetry-service/lifecycle.d.ts +26 -0
  156. package/dist/_pkgs/affine-shared/services/telemetry-service/telemetry-service.d.ts +4 -3
  157. package/dist/_pkgs/affine-shared/services/telemetry-service/types.d.ts +11 -0
  158. package/dist/_pkgs/affine-shared/utils/index.d.ts +1 -0
  159. package/dist/_pkgs/affine-shared/utils/index.js +1 -0
  160. package/dist/_pkgs/affine-shared/utils/invisible-characters.d.ts +42 -0
  161. package/dist/_pkgs/affine-shared/utils/invisible-characters.js +81 -0
  162. package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/index.js +26 -26
  163. package/dist/_pkgs/affine-widget-edgeless-zoom-toolbar/zoom-toolbar.js +13 -2
  164. package/dist/_pkgs/affine-widget-keyboard-toolbar/icons.js +98 -98
  165. package/dist/_pkgs/affine-widget-page-dragging-area/index.js +10 -10
  166. package/dist/_pkgs/affine-widget-viewport-overlay/index.js +13 -13
  167. package/dist/_pkgs/data-view/core/utils/menu-title.js +17 -17
  168. package/dist/_pkgs/data-view/view-presets/table/pc/header/column-header.js +6 -0
  169. package/dist/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.js +5 -2
  170. package/dist/_pkgs/std/clipboard/clipboard.d.ts +15 -1
  171. package/dist/_pkgs/std/clipboard/clipboard.js +18 -0
  172. package/dist/_pkgs/std/inline/components/embed-gap.js +1 -1
  173. package/dist/_pkgs/std/inline/components/v-line.js +1 -1
  174. package/dist/_pkgs/std/inline/components/v-text.d.ts +15 -2
  175. package/dist/_pkgs/std/inline/components/v-text.js +147 -15
  176. package/dist/_pkgs/std/inline/consts.d.ts +5 -0
  177. package/dist/_pkgs/std/inline/consts.js +5 -0
  178. package/dist/_pkgs/std/inline/utils/index.d.ts +1 -0
  179. package/dist/_pkgs/std/inline/utils/index.js +1 -0
  180. package/dist/_pkgs/std/inline/utils/invisible-characters.d.ts +57 -0
  181. package/dist/_pkgs/std/inline/utils/invisible-characters.js +162 -0
  182. package/dist/_pkgs/std/inline/utils/point-conversion.js +3 -3
  183. package/dist/_pkgs/std/inline/utils/text.d.ts +8 -0
  184. package/dist/_pkgs/std/inline/utils/text.js +11 -2
  185. package/dist/_pkgs/store/model/store/crud.d.ts +28 -0
  186. package/dist/_pkgs/store/model/store/crud.js +97 -30
  187. package/dist/_pkgs/store/model/store/query.js +3 -2
  188. package/dist/_pkgs/store/model/store/store.d.ts +21 -0
  189. package/dist/_pkgs/store/model/store/store.js +88 -21
  190. package/dist/_pkgs/store/transformer/transformer.d.ts +46 -0
  191. package/dist/_pkgs/store/transformer/transformer.js +72 -0
  192. package/dist/commands.js +6 -1
  193. package/dist/translations.js +2 -0
  194. package/package.json +3 -4
@@ -1,11 +1,12 @@
1
1
  import { ExportToHtmlIcon, ExportToMarkdownIcon } from '@blocksuite/icons/lit';
2
2
  import { ViewExtensionProvider, } from '../affine-ext-loader/index.js';
3
3
  import { NoteBlockSchema } from '../affine-model/index.js';
4
- import { ToolbarModuleExtension, ViewportElementExtension, } from '../affine-shared/services/index.js';
4
+ import { InvisibleCharacters, ToolbarModuleExtension, ViewportElementExtension, } from '../affine-shared/services/index.js';
5
5
  import { BlockFlavourIdentifier, BlockViewExtension, FlavourExtension, CommandExtension, ShortcutKeymapExtension, } from '../std/index.js';
6
6
  import { literal } from 'lit/static-html.js';
7
7
  import { PageClipboard, ReadOnlyClipboard } from './clipboard/index.js';
8
8
  import { copyLinkCommands } from './commands/copy-link-commands.js';
9
+ import { invisibleCharactersCommands } from './commands/invisible-characters-commands.js';
9
10
  import { pageExportCommands } from './commands/page-export-commands.js';
10
11
  import { pivotCommands } from './commands/pivot-commands.js';
11
12
  import { readingCommands } from './commands/reading-commands.js';
@@ -74,6 +75,7 @@ export class RootViewExtension extends ViewExtensionProvider {
74
75
  ...tagCommands,
75
76
  ...readingCommands,
76
77
  ...copyLinkCommands,
78
+ ...invisibleCharactersCommands,
77
79
  ]),
78
80
  // The page as Markdown or HTML (ADR 0034, amendment of 2026-10-14):
79
81
  // view actions of both views, never gated — the page's own text.
@@ -82,6 +84,9 @@ export class RootViewExtension extends ViewExtensionProvider {
82
84
  'page.export.html': ExportToHtmlIcon(),
83
85
  }),
84
86
  ShortcutKeymapExtension('global'),
87
+ // "Show special characters", this viewer's display choice, read by
88
+ // every `v-text` under the host; both views, previews included.
89
+ InvisibleCharacters,
85
90
  ToolbarModuleExtension({
86
91
  id: BlockFlavourIdentifier(NoteBlockSchema.model.flavour),
87
92
  config: builtinToolbarConfig,
@@ -1,2 +1,2 @@
1
1
  export { autoArrangeElementsCommand, autoResizeElementsCommand, } from './auto-align.js';
2
- export { reassociateConnectorsCommand } from './reassociate-connectors.js';
2
+ export { reassociateConnectors, reassociateConnectorsCommand, } from './reassociate-connectors.js';
@@ -1,2 +1,2 @@
1
1
  export { autoArrangeElementsCommand, autoResizeElementsCommand, } from './auto-align.js';
2
- export { reassociateConnectorsCommand } from './reassociate-connectors.js';
2
+ export { reassociateConnectors, reassociateConnectorsCommand, } from './reassociate-connectors.js';
@@ -1,4 +1,13 @@
1
1
  import type { Command } from '../../std/index.js';
2
+ import type { SurfaceBlockModel } from '../surface-model.js';
3
+ /**
4
+ * Re-point every connector end bound to `oldId` at `newId`, keeping the rest
5
+ * of the endpoint (its `position`). The caller owns the transaction and the
6
+ * undo step: a model converted into another (a bookmark into an embed, a
7
+ * shape into an image, ADR 0044) re-points its connectors before the old one
8
+ * is deleted.
9
+ */
10
+ export declare function reassociateConnectors(surface: Pick<SurfaceBlockModel, 'getConnectors' | 'updateElement'>, oldId: string, newId: string): void;
2
11
  /**
3
12
  * Re-associate bindings for block that have been converted.
4
13
  *
@@ -1,18 +1,12 @@
1
1
  import { GfxControllerIdentifier } from '../../std/gfx/index.js';
2
2
  /**
3
- * Re-associate bindings for block that have been converted.
4
- *
5
- * @param oldId - the old block id
6
- * @param newId - the new block id
3
+ * Re-point every connector end bound to `oldId` at `newId`, keeping the rest
4
+ * of the endpoint (its `position`). The caller owns the transaction and the
5
+ * undo step: a model converted into another (a bookmark into an embed, a
6
+ * shape into an image, ADR 0044) re-points its connectors before the old one
7
+ * is deleted.
7
8
  */
8
- export const reassociateConnectorsCommand = (ctx, next) => {
9
- const { oldId, newId } = ctx;
10
- const gfx = ctx.std.get(GfxControllerIdentifier);
11
- if (!oldId || !newId || !gfx.surface) {
12
- next();
13
- return;
14
- }
15
- const surface = gfx.surface;
9
+ export function reassociateConnectors(surface, oldId, newId) {
16
10
  const connectors = surface.getConnectors(oldId);
17
11
  for (const { id, source, target } of connectors) {
18
12
  if (source.id === oldId) {
@@ -32,5 +26,20 @@ export const reassociateConnectorsCommand = (ctx, next) => {
32
26
  });
33
27
  }
34
28
  }
29
+ }
30
+ /**
31
+ * Re-associate bindings for block that have been converted.
32
+ *
33
+ * @param oldId - the old block id
34
+ * @param newId - the new block id
35
+ */
36
+ export const reassociateConnectorsCommand = (ctx, next) => {
37
+ const { oldId, newId } = ctx;
38
+ const gfx = ctx.std.get(GfxControllerIdentifier);
39
+ if (!oldId || !newId || !gfx.surface) {
40
+ next();
41
+ return;
42
+ }
43
+ reassociateConnectors(gfx.surface, oldId, newId);
35
44
  next();
36
45
  };
@@ -15,6 +15,15 @@ export type ClipboardConfigCreationContext = {
15
15
  */
16
16
  newPresentationIndexes: Map<string, string>;
17
17
  };
18
+ /**
19
+ * A block a paste is ready to write (`EdgelessClipboardConfig.prepare`).
20
+ * `write` is synchronous for a config that follows the contract; a Promise is
21
+ * the legacy `createBlock` behind the default `prepare`.
22
+ */
23
+ export interface PreparedClipboardBlock {
24
+ write(): string | null | Promise<string | null>;
25
+ afterWrite?(): void;
26
+ }
18
27
  export declare const EdgelessClipboardConfigIdentifier: import("../../global/di/types.js").ServiceIdentifier<EdgelessClipboardConfig> & (<U extends EdgelessClipboardConfig = EdgelessClipboardConfig>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
19
28
  export declare abstract class EdgelessClipboardConfig extends Extension {
20
29
  readonly std: BlockStdScope;
@@ -23,6 +32,30 @@ export declare abstract class EdgelessClipboardConfig extends Extension {
23
32
  get surface(): import("../surface-block.js").SurfaceBlockComponent | null;
24
33
  get crud(): import("./crud-extension.js").EdgelessCRUDExtension;
25
34
  onBlockSnapshotPaste: (snapshot: BlockSnapshot, doc: Store, parent?: string, index?: number) => Promise<string | null>;
35
+ /**
36
+ * `onBlockSnapshotPaste` in two halves, for `prepare`: the snapshot is
37
+ * converted now, the blocks are written by `write`, and the import
38
+ * middlewares run in `afterWrite`.
39
+ */
40
+ prepareBlockSnapshotPaste: (snapshot: BlockSnapshot, doc: Store, parent?: string, index?: number) => Promise<PreparedClipboardBlock | null>;
26
41
  abstract createBlock(snapshot: BlockSnapshot, context: ClipboardConfigCreationContext): string | null | Promise<string | null>;
42
+ /**
43
+ * The paste's two-phase contract (ADR 0042): everything slow (a blob fetch,
44
+ * a snapshot conversion) happens here and writes nothing; the returned
45
+ * `write` adds the block synchronously, because the paste calls every
46
+ * block's `write` and creates every canvas element in ONE transaction, which
47
+ * is one undo step and one update for a peer. `afterWrite` runs in the
48
+ * paste's second transaction, once every pasted model exists.
49
+ *
50
+ * The default defers to `createBlock`, so a config written before the
51
+ * contract keeps working; an async `createBlock` then still writes after
52
+ * the paste's transaction and may cost its own undo step.
53
+ */
54
+ prepare(snapshot: BlockSnapshot, context: ClipboardConfigCreationContext): PreparedClipboardBlock | null | Promise<PreparedClipboardBlock | null>;
55
+ /**
56
+ * `createBlock` for a config that implements `prepare`: prepares, then
57
+ * writes in one transaction of its own.
58
+ */
59
+ protected createPreparedBlock(snapshot: BlockSnapshot, context: ClipboardConfigCreationContext): Promise<string | null>;
27
60
  static setup(di: Container): void;
28
61
  }
@@ -17,6 +17,26 @@ export class EdgelessClipboardConfig extends Extension {
17
17
  const block = await this.std.clipboard.pasteBlockSnapshot(snapshot, doc, parent, index);
18
18
  return block?.id ?? null;
19
19
  };
20
+ /**
21
+ * `onBlockSnapshotPaste` in two halves, for `prepare`: the snapshot is
22
+ * converted now, the blocks are written by `write`, and the import
23
+ * middlewares run in `afterWrite`.
24
+ */
25
+ this.prepareBlockSnapshotPaste = async (snapshot, doc, parent, index) => {
26
+ applyCreationLayer(this.std, snapshot.props);
27
+ const prepared = await this.std.clipboard.prepareBlockSnapshot(snapshot, parent, index);
28
+ if (!prepared)
29
+ return null;
30
+ let flush;
31
+ return {
32
+ write: () => {
33
+ const inserted = prepared.insert(doc);
34
+ flush = inserted?.flushAfterImport;
35
+ return inserted?.id ?? null;
36
+ },
37
+ afterWrite: () => flush?.(),
38
+ };
39
+ };
20
40
  }
21
41
  get surface() {
22
42
  return getSurfaceComponent(this.std);
@@ -24,6 +44,39 @@ export class EdgelessClipboardConfig extends Extension {
24
44
  get crud() {
25
45
  return this.std.get(EdgelessCRUDIdentifier);
26
46
  }
47
+ /**
48
+ * The paste's two-phase contract (ADR 0042): everything slow (a blob fetch,
49
+ * a snapshot conversion) happens here and writes nothing; the returned
50
+ * `write` adds the block synchronously, because the paste calls every
51
+ * block's `write` and creates every canvas element in ONE transaction, which
52
+ * is one undo step and one update for a peer. `afterWrite` runs in the
53
+ * paste's second transaction, once every pasted model exists.
54
+ *
55
+ * The default defers to `createBlock`, so a config written before the
56
+ * contract keeps working; an async `createBlock` then still writes after
57
+ * the paste's transaction and may cost its own undo step.
58
+ */
59
+ prepare(snapshot, context) {
60
+ return { write: () => this.createBlock(snapshot, context) };
61
+ }
62
+ /**
63
+ * `createBlock` for a config that implements `prepare`: prepares, then
64
+ * writes in one transaction of its own.
65
+ */
66
+ async createPreparedBlock(snapshot, context) {
67
+ const prepared = await this.prepare(snapshot, context);
68
+ if (!prepared)
69
+ return null;
70
+ const result = {
71
+ id: null,
72
+ };
73
+ this.std.store.transact(() => {
74
+ result.id = prepared.write();
75
+ });
76
+ const id = await result.id;
77
+ prepared.afterWrite?.();
78
+ return id;
79
+ }
27
80
  static setup(di) {
28
81
  if (!this.key) {
29
82
  throw new BlockSuiteError(BlockSuiteError.ErrorCode.ValueNotExists, 'Key is not defined in the EdgelessClipboardConfig');
@@ -10,6 +10,7 @@ export * from './element-renderer.js';
10
10
  export * from './export-manager/index.js';
11
11
  export * from './export-svg/index.js';
12
12
  export * from './interchange.js';
13
+ export * from './toolbox.js';
13
14
  export * from './interchange-export.js';
14
15
  export * from './interchange-import.js';
15
16
  export * from './legacy-slot-extension.js';
@@ -10,6 +10,7 @@ export * from './element-renderer.js';
10
10
  export * from './export-manager/index.js';
11
11
  export * from './export-svg/index.js';
12
12
  export * from './interchange.js';
13
+ export * from './toolbox.js';
13
14
  export * from './interchange-export.js';
14
15
  export * from './interchange-import.js';
15
16
  export * from './legacy-slot-extension.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * The ink and the type a notation writes its labels in: the legend box's rows,
3
+ * and the words the DDD prefabs set beside a dot or a marker.
4
+ *
5
+ * Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
6
+ * the other way round, because that bundle depends on this one and a legend
7
+ * must not depend on a DDD bundle to be drawn.
8
+ */
9
+ export declare const LABEL_COLOR: string;
10
+ export declare const LABEL_FONT = "blocksuite:surface:Inter";
11
+ export declare const LABEL_FONT_SIZE = 14;
@@ -0,0 +1,16 @@
1
+ import { NOTATION_NEUTRALS } from '../../affine-shared/headless.js';
2
+ // Its own module so the headless interchange entry (`./interchange`) can read
3
+ // it without the legend's editor graph: the DDD element builders of
4
+ // `@labre/affine-gfx-ddd-shared/headless` write their captions in these three
5
+ // values (`docs/adr/0045`). `legend.ts` re-exports them unchanged.
6
+ /**
7
+ * The ink and the type a notation writes its labels in: the legend box's rows,
8
+ * and the words the DDD prefabs set beside a dot or a marker.
9
+ *
10
+ * Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
11
+ * the other way round, because that bundle depends on this one and a legend
12
+ * must not depend on a DDD bundle to be drawn.
13
+ */
14
+ export const LABEL_COLOR = NOTATION_NEUTRALS.ink;
15
+ export const LABEL_FONT = 'blocksuite:surface:Inter';
16
+ export const LABEL_FONT_SIZE = 14;
@@ -46,17 +46,7 @@ export interface LegendLayout {
46
46
  }
47
47
  /** A block of the box that is not a row. See {@link CommandLegendBox.extras}. */
48
48
  export type LegendExtra = CommandLegendExtra;
49
- /**
50
- * The ink and the type a notation writes its labels in: this box's rows, and
51
- * the words the DDD prefabs set beside a dot or a marker.
52
- *
53
- * Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
54
- * the other way round, because that bundle depends on this one and a legend
55
- * must not depend on a DDD bundle to be drawn.
56
- */
57
- export declare const LABEL_COLOR: string;
58
- export declare const LABEL_FONT = "blocksuite:surface:Inter";
59
- export declare const LABEL_FONT_SIZE = 14;
49
+ export { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
60
50
  export { LEGEND_ROLE };
61
51
  /**
62
52
  * How big the box {@link addLegend} would draw for these sections is — without
@@ -5,18 +5,9 @@ import { Bound } from '../../global/gfx/index.js';
5
5
  import { CATALOGUE_CATEGORY_KEY_PREFIX, getRegisteredCommands, humanizeCategory, } from '../../std/index.js';
6
6
  import { GfxControllerIdentifier, roleIsA, RoleVocabularyIdentifier, } from '../../std/gfx/index.js';
7
7
  import { EdgelessCRUDIdentifier } from './crud-extension.js';
8
+ import { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
8
9
  import { LEGEND_ROLE } from './legend-role.js';
9
- /**
10
- * The ink and the type a notation writes its labels in: this box's rows, and
11
- * the words the DDD prefabs set beside a dot or a marker.
12
- *
13
- * Declared HERE and re-exported by `@labre/affine-gfx-ddd-shared`, rather than
14
- * the other way round, because that bundle depends on this one and a legend
15
- * must not depend on a DDD bundle to be drawn.
16
- */
17
- export const LABEL_COLOR = NOTATION_NEUTRALS.ink;
18
- export const LABEL_FONT = 'blocksuite:surface:Inter';
19
- export const LABEL_FONT_SIZE = 14;
10
+ export { LABEL_COLOR, LABEL_FONT, LABEL_FONT_SIZE } from './legend-label.js';
20
11
  const NO_STROKE = '#00000000';
21
12
  /**
22
13
  * The box's geometry, in one place because two callers need it: the one that
@@ -58,18 +58,18 @@ const READ_LABEL_FALLBACK = 'Read this component';
58
58
  * Drawn inline like its neighbours: this package does not depend on
59
59
  * `@blocksuite/icons` and one glyph is not worth a new dependency.
60
60
  */
61
- const ReadIcon = html `<svg
62
- width="20"
63
- height="20"
64
- viewBox="0 0 24 24"
65
- fill="none"
66
- stroke="currentColor"
67
- stroke-width="2"
68
- stroke-linecap="round"
69
- stroke-linejoin="round"
70
- >
71
- <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z" />
72
- <circle cx="12" cy="12" r="3" />
61
+ const ReadIcon = html `<svg
62
+ width="20"
63
+ height="20"
64
+ viewBox="0 0 24 24"
65
+ fill="none"
66
+ stroke="currentColor"
67
+ stroke-width="2"
68
+ stroke-linecap="round"
69
+ stroke-linejoin="round"
70
+ >
71
+ <path d="M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z" />
72
+ <circle cx="12" cy="12" r="3" />
73
73
  </svg>`;
74
74
  /** The command this module drives. Spelled once. */
75
75
  const ELEMENT_READ_ID = 'element.read';
@@ -0,0 +1,62 @@
1
+ import type { SerializedElementProps } from './interchange.js';
2
+ /**
3
+ * A framework's TOOLBOX, with no editor behind it (`docs/adr/0045`): every
4
+ * item of its toolbar as a pure builder, so a host with no editor — the Labre
5
+ * workspace connector, labre-mcp — places the very elements a user places
6
+ * from the toolbar, never shapes that imitate them.
7
+ *
8
+ * ## The same contract as a reader's result
9
+ *
10
+ * A builder returns what an import capability returns (ADR 0012 D3): element
11
+ * props in painting order, each composite's members before the group that
12
+ * holds them, and LOCAL `id`s the group's `children` and a link's ends name.
13
+ * `surface.addElement` mints the real ids and the materializer
14
+ * (`materializeInterchangeImport`) rewrites the references, so one writer
15
+ * serves a whole file read by a reader and one item built here.
16
+ *
17
+ * ## What a builder does not do
18
+ *
19
+ * It places ONE item at the point it is given: where things go on a board is
20
+ * the caller's. It writes the texts it is given, or the English seed: a seed
21
+ * in the host's language is resolved by the editor's creation site, which has
22
+ * the catalogue (ADR 0023). It persists nothing.
23
+ */
24
+ /** Where an item lands: the top-left of its box, in canvas units. */
25
+ export interface ToolboxPoint {
26
+ x: number;
27
+ y: number;
28
+ }
29
+ /** One toolbar item that places elements. */
30
+ export interface ToolboxItem {
31
+ /** Stable within the framework, kebab-case: `container`, `system-boundary`. */
32
+ readonly id: string;
33
+ /** The toolbar command's own label, so a host names it as the toolbar does. */
34
+ readonly labelKey: string;
35
+ readonly labelFallback: string;
36
+ /** The text slots `build` fills, in reading order (`title`, `description`…). */
37
+ readonly texts: readonly string[];
38
+ /** The box the item is born with. */
39
+ readonly size: {
40
+ readonly w: number;
41
+ readonly h: number;
42
+ };
43
+ /**
44
+ * The elements, with local ids and the group last. `local` prefixes those
45
+ * ids, so two items built for one batch never share a name.
46
+ */
47
+ build(at: ToolboxPoint, texts?: Readonly<Record<string, string>>, local?: string): SerializedElementProps[];
48
+ }
49
+ /** One relation style of the framework: a connector between two elements. */
50
+ export interface ToolboxLink {
51
+ readonly id: string;
52
+ readonly labelKey: string;
53
+ readonly labelFallback: string;
54
+ /** The connector props; `from` and `to` are element ids or local ids. */
55
+ build(from: string, to: string, label?: string): SerializedElementProps;
56
+ }
57
+ export interface FrameworkToolbox {
58
+ /** The framework's descriptor id (`c4`, `bpmn`…). */
59
+ readonly framework: string;
60
+ readonly items: readonly ToolboxItem[];
61
+ readonly links: readonly ToolboxLink[];
62
+ }
@@ -3,6 +3,7 @@ import { rotatePoint } from '../../global/gfx/index.js';
3
3
  import { GfxElementModelView } from '../../std/gfx/index.js';
4
4
  import { EdgelessCRUDIdentifier } from '../extensions/crud-extension.js';
5
5
  import { backgroundLabelHits, hitTestBackgroundLabel } from './labels.js';
6
+ import { measureBackgroundText } from './measure-text.js';
6
7
  /**
7
8
  * The rename gesture every framework background shares: double-click a label,
8
9
  * type, Enter or click away.
@@ -179,7 +180,7 @@ export class FrameworkBackgroundView extends GfxElementModelView {
179
180
  */
180
181
  export class DeclaredBackgroundView extends FrameworkBackgroundView {
181
182
  labelAt(lx, ly, w, h) {
182
- const hit = hitTestBackgroundLabel(backgroundLabelHits(this.def, this.model, w, h, this.gfx.std.getOptional(TranslationProvider)), lx, ly);
183
+ const hit = hitTestBackgroundLabel(backgroundLabelHits(this.def, this.model, w, h, this.gfx.std.getOptional(TranslationProvider), measureBackgroundText), lx, ly);
183
184
  return hit ? { prop: hit.prop, text: hit.text } : null;
184
185
  }
185
186
  }
@@ -0,0 +1,104 @@
1
+ import type { TranslationService } from '../../affine-shared/services/index.js';
2
+ import type { BackgroundInset, BackgroundTextDef, BackgroundTextStyle, FrameworkBackgroundDef } from './def.js';
3
+ import type { BackgroundModelLike } from './labels.js';
4
+ /**
5
+ * How thick a background's bands are, once their labels have been measured.
6
+ *
7
+ * A band whose label declares `fit: 'wrap'` is as thick as its declaration says
8
+ * OR as thick as its wrapped words need, whichever is more (PO, 2026-10-27: a
9
+ * BPMN pool's title band grows with its name instead of cutting it). That is a
10
+ * function of measured text, so it cannot live in the declaration, and it must
11
+ * not be computed twice: the renderer paints the band, the label hit boxes
12
+ * (`labels.ts`) and a framework's own hit tests (`gfx/bpmn/src/pool-hit.ts`)
13
+ * aim at it, and the three disagreeing by a unit is a double-click that lands
14
+ * on the flow area beside the name it was aimed at. {@link backgroundBandWidths}
15
+ * is the one resolver they all read.
16
+ *
17
+ * Nothing is written to the document. The stored geometry is the declared one,
18
+ * and so is the plot the SEMANTIC readers use (facts, audit, rules, exports):
19
+ * where an artefact sits in a frame must not move because a title was renamed.
20
+ * Only the chrome — what is painted and what is aimed at — reads the grown
21
+ * widths.
22
+ *
23
+ * Kept beside `def.ts` rather than in it because it needs the label resolution
24
+ * of `labels.ts`, which itself reads `def.ts`.
25
+ */
26
+ /** Width of `text` in model units when drawn in the CSS `font`. */
27
+ export type BackgroundTextMeasure = (text: string, font: string) => number;
28
+ /**
29
+ * The line height of a wrapped label, as a multiple of its font size: the CSS
30
+ * `normal` line height. Not the 1.25 the slides use — at 1.25 a single 13-unit
31
+ * lane name would need 24.25 units and widen the BPMN pool's 24-unit lane strip
32
+ * by a quarter unit for a name that fits it; a band only grows for a SECOND
33
+ * line.
34
+ */
35
+ export declare const BACKGROUND_WRAP_LINE_HEIGHT = 1.2;
36
+ /** The family a declaration that names none falls back to. */
37
+ export declare const DEFAULT_BACKGROUND_FONT_FAMILY = "Inter, sans-serif";
38
+ /** The CSS font a background text is drawn in. */
39
+ export declare function backgroundFont(style: BackgroundTextStyle, fallbackFamily?: string): string;
40
+ /** Distance between two wrapped lines of this style, in model units. */
41
+ export declare function backgroundWrapLineHeight(style: BackgroundTextStyle): number;
42
+ /**
43
+ * The room a fitted declared text has: from its anchor to the card's edges
44
+ * along the direction it reads, on the side(s) its alignment grows towards,
45
+ * less {@link BACKGROUND_TEXT_FIT_PADDING} at each end. A vertical text reads
46
+ * bottom-to-top, so `left` grows UP from its anchor.
47
+ */
48
+ export declare function backgroundTextRoom(ax: number, ay: number, align: BackgroundTextDef['align'], vertical: boolean, w: number, h: number): number;
49
+ /**
50
+ * A rough width with no canvas at all: 0.55 × the font size per code point, the
51
+ * ratio `svg-sketch.ts` estimates with. The default of every headless caller
52
+ * (this file is reachable from the `./interchange` entry, which loads no DOM);
53
+ * a caller with a document passes `measureBackgroundText` (`measure-text.ts`),
54
+ * which measures with the canvas's own metrics.
55
+ */
56
+ export declare function estimateBackgroundText(text: string, font: string): number;
57
+ /** A side band's label once wrapped: what to draw and where. */
58
+ export interface BackgroundWrappedLabel {
59
+ lines: readonly string[];
60
+ /**
61
+ * Model units to add to the label's anchor, resolved against the GROWN plot,
62
+ * so it keeps its offset from the middle of its band: half the growth, back
63
+ * towards the card edge.
64
+ */
65
+ shift: readonly [number, number];
66
+ }
67
+ /** The bands of one instance, sized by what they hold. */
68
+ export interface BackgroundBandLayout {
69
+ /** The margins, each side band grown to what its wrapped label needs. */
70
+ margin: BackgroundInset;
71
+ /**
72
+ * Thickness of every instance-zone strip — the declared width or the one the
73
+ * most demanding wrapped name needs. `undefined` without a strip.
74
+ */
75
+ zoneBandWidth: number | undefined;
76
+ /** Each wrapped side-band label, by its declaration. */
77
+ labels: ReadonlyMap<BackgroundTextDef, BackgroundWrappedLabel>;
78
+ /** Each wrapped instance-zone name, by reported zone id. */
79
+ zoneLines: ReadonlyMap<string, readonly string[]>;
80
+ }
81
+ /**
82
+ * THE resolver of band thickness. Pure in its inputs: the declaration, the
83
+ * instance's props, its size, and how to measure text — the renderer passes its
84
+ * context, a hit test outside a paint `measureBackgroundText` (the same metrics
85
+ * from an offscreen canvas), and a caller with no DOM gets the estimate.
86
+ *
87
+ * - a SIDE band whose label wraps is `max(declared margin, lines × line height
88
+ * + 2 × padding)` thick, the lines broken over the room the label has along
89
+ * the band (`backgroundTextRoom`, from its anchor in the declared plot);
90
+ * - every INSTANCE-ZONE strip is one thickness: the declared width, or the
91
+ * most any zone's wrapped name needs, each name broken over its own zone's
92
+ * length less the padding. A lane with a long name widens every lane's strip,
93
+ * so the leading edges stay aligned.
94
+ *
95
+ * A declaration with no `'wrap'` anywhere gets its declared numbers back
96
+ * without a single measurement, so the frameworks that never asked for this
97
+ * pay nothing for it.
98
+ *
99
+ * ponytail: a text's room is measured against the DECLARED plot, so a
100
+ * declaration wrapping both a left and a top band would size each without the
101
+ * other's growth. Nothing declares two; upgrade by resolving the sides in turn
102
+ * against the plot resolved so far, the day one does.
103
+ */
104
+ export declare function backgroundBandWidths(def: FrameworkBackgroundDef, model: BackgroundModelLike, w: number, h: number, measure?: BackgroundTextMeasure, translation?: TranslationService | null): BackgroundBandLayout;