@ecsplico/editor 3.1.0 → 3.2.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 (270) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/dist/adapters/direct-ai.d.ts +36 -0
  3. package/dist/adapters/direct-ai.js +169 -0
  4. package/dist/adapters/direct-ai.js.map +1 -0
  5. package/dist/adapters/memory.js.map +1 -1
  6. package/dist/code/CodeSurface.vue.d.ts +2 -2
  7. package/dist/core/block-drag.js +3 -0
  8. package/dist/core/block-drag.js.map +1 -1
  9. package/dist/core/block-transfer.d.ts +44 -0
  10. package/dist/core/block-transfer.js +68 -0
  11. package/dist/core/block-transfer.js.map +1 -0
  12. package/dist/core/commands.js +5 -0
  13. package/dist/core/commands.js.map +1 -1
  14. package/dist/core/core-feature.d.ts +4 -1
  15. package/dist/core/core-feature.js +8 -3
  16. package/dist/core/core-feature.js.map +1 -1
  17. package/dist/core/editor-ui.d.ts +3 -1
  18. package/dist/core/editor-ui.js.map +1 -1
  19. package/dist/core/extension-points.d.ts +17 -1
  20. package/dist/core/feature.d.ts +6 -1
  21. package/dist/core/feature.js.map +1 -1
  22. package/dist/core/index.d.ts +4 -2
  23. package/dist/core/index.js +3 -2
  24. package/dist/core/schema/index.d.ts +24 -3
  25. package/dist/core/schema/index.js +21 -4
  26. package/dist/core/schema/index.js.map +1 -1
  27. package/dist/core/surface-session.js +3 -1
  28. package/dist/core/surface-session.js.map +1 -1
  29. package/dist/core/toolbar-items.js +1 -1
  30. package/dist/core/toolbar-items.js.map +1 -1
  31. package/dist/document/DocumentSurface.vue.d.ts +2 -2
  32. package/dist/features/ai/agent-op-review.js +1 -1
  33. package/dist/features/ai/agent-ops.js +2 -2
  34. package/dist/features/ai/ai-apply.js +1 -1
  35. package/dist/features/ai/assistant.js +1 -1
  36. package/dist/features/ai/components/AiSelectionMenu.js +2 -2
  37. package/dist/features/ai/components/AiSidebar.js +2 -2
  38. package/dist/features/ai/components/SettingsAiTab.js +1 -1
  39. package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
  40. package/dist/features/ai/document-chat-model.js +1 -1
  41. package/dist/features/ai/document-chat.js +2 -2
  42. package/dist/features/ai/ghost-autocomplete.js +1 -1
  43. package/dist/features/ai/index.d.ts +4 -3
  44. package/dist/features/ai/index.js +6 -5
  45. package/dist/features/ai/protocol/complete.d.ts +19 -0
  46. package/dist/features/ai/protocol/complete.js +27 -1
  47. package/dist/features/ai/protocol/complete.js.map +1 -1
  48. package/dist/features/ai/protocol/generate.d.ts +95 -0
  49. package/dist/features/ai/protocol/generate.js +58 -0
  50. package/dist/features/ai/protocol/generate.js.map +1 -0
  51. package/dist/features/ai/protocol/index.d.ts +4 -3
  52. package/dist/features/ai/protocol/index.js +6 -5
  53. package/dist/features/ai/protocol/tasks.d.ts +3 -1
  54. package/dist/features/ai/protocol/tasks.js +74 -2
  55. package/dist/features/ai/protocol/tasks.js.map +1 -1
  56. package/dist/features/ai/react/AiSelectionMenu.js +2 -2
  57. package/dist/features/ai/react/AiSidebar.js +2 -2
  58. package/dist/features/ai/react/SettingsAiTab.js +1 -1
  59. package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
  60. package/dist/features/ai/selection-flow.js +1 -1
  61. package/dist/features/ai/sidebar-flow.js +1 -1
  62. package/dist/features/block-ui/block-actions.d.ts +19 -3
  63. package/dist/features/block-ui/block-actions.js +49 -3
  64. package/dist/features/block-ui/block-actions.js.map +1 -1
  65. package/dist/features/block-ui/components/BlockActionsOverlay.js +24 -13
  66. package/dist/features/block-ui/components/BlockActionsOverlay.js.map +1 -1
  67. package/dist/features/block-ui/components/BlockActionsOverlay.vue.d.ts +12 -5
  68. package/dist/features/block-ui/components/BlockUi.js +52 -20
  69. package/dist/features/block-ui/components/BlockUi.js.map +1 -1
  70. package/dist/features/block-ui/components/BlockUi.vue.d.ts +6 -4
  71. package/dist/features/block-ui/feature.d.ts +8 -2
  72. package/dist/features/block-ui/feature.js +7 -2
  73. package/dist/features/block-ui/feature.js.map +1 -1
  74. package/dist/features/block-ui/index.d.ts +3 -2
  75. package/dist/features/block-ui/index.js +2 -2
  76. package/dist/features/block-ui/react/BlockActionsOverlay.d.ts +14 -7
  77. package/dist/features/block-ui/react/BlockActionsOverlay.js +25 -13
  78. package/dist/features/block-ui/react/BlockActionsOverlay.js.map +1 -1
  79. package/dist/features/block-ui/react/BlockUi.d.ts +6 -4
  80. package/dist/features/block-ui/react/BlockUi.js +43 -15
  81. package/dist/features/block-ui/react/BlockUi.js.map +1 -1
  82. package/dist/features/block-ui/react.d.ts +4 -2
  83. package/dist/features/block-ui/react.js +3 -3
  84. package/dist/features/block-ui/react.js.map +1 -1
  85. package/dist/features/block-ui/vue.d.ts +4 -2
  86. package/dist/features/block-ui/vue.js +3 -3
  87. package/dist/features/block-ui/vue.js.map +1 -1
  88. package/dist/features/composites/baskets.d.ts +27 -0
  89. package/dist/features/composites/baskets.js +46 -0
  90. package/dist/features/composites/baskets.js.map +1 -0
  91. package/dist/features/composites/components/CompositeBasketMenu.js +97 -0
  92. package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -0
  93. package/dist/features/composites/components/CompositeChrome.js +79 -23
  94. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  95. package/dist/features/composites/components/CompositeFieldEditor.js +1 -0
  96. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  97. package/dist/features/composites/components/CompositeView.js +17 -2
  98. package/dist/features/composites/components/CompositeView.js.map +1 -1
  99. package/dist/features/composites/components/DerivationBadge.js +12 -3
  100. package/dist/features/composites/components/DerivationBadge.js.map +1 -1
  101. package/dist/features/composites/components/FocusChip.js +53 -0
  102. package/dist/features/composites/components/FocusChip.js.map +1 -0
  103. package/dist/features/composites/components/FocusChip.vue.d.ts +14 -0
  104. package/dist/features/composites/components/SettingsEditingTab.js +40 -4
  105. package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
  106. package/dist/features/composites/derivation.d.ts +2 -1
  107. package/dist/features/composites/derivation.js +5 -1
  108. package/dist/features/composites/derivation.js.map +1 -1
  109. package/dist/features/composites/derived-chrome.js +13 -3
  110. package/dist/features/composites/derived-chrome.js.map +1 -1
  111. package/dist/features/composites/feature.d.ts +7 -1
  112. package/dist/features/composites/feature.js +96 -23
  113. package/dist/features/composites/feature.js.map +1 -1
  114. package/dist/features/composites/focus.d.ts +38 -0
  115. package/dist/features/composites/focus.js +86 -0
  116. package/dist/features/composites/focus.js.map +1 -0
  117. package/dist/features/composites/index.d.ts +6 -3
  118. package/dist/features/composites/index.js +6 -3
  119. package/dist/features/composites/meta-keys.d.ts +4 -0
  120. package/dist/features/composites/meta-keys.js +8 -4
  121. package/dist/features/composites/meta-keys.js.map +1 -1
  122. package/dist/features/composites/nodes.d.ts +14 -2
  123. package/dist/features/composites/nodes.js +61 -5
  124. package/dist/features/composites/nodes.js.map +1 -1
  125. package/dist/features/composites/outline.d.ts +4 -0
  126. package/dist/features/composites/outline.js +3 -0
  127. package/dist/features/composites/outline.js.map +1 -1
  128. package/dist/features/composites/react/CompositeBasketMenu.js +88 -0
  129. package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -0
  130. package/dist/features/composites/react/CompositeChrome.js +52 -4
  131. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  132. package/dist/features/composites/react/CompositeView.js +12 -2
  133. package/dist/features/composites/react/CompositeView.js.map +1 -1
  134. package/dist/features/composites/react/DerivationBadge.js +10 -1
  135. package/dist/features/composites/react/DerivationBadge.js.map +1 -1
  136. package/dist/features/composites/react/FocusChip.d.ts +11 -0
  137. package/dist/features/composites/react/FocusChip.js +50 -0
  138. package/dist/features/composites/react/FocusChip.js.map +1 -0
  139. package/dist/features/composites/react/SettingsEditingTab.js +36 -1
  140. package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
  141. package/dist/features/composites/react.d.ts +2 -1
  142. package/dist/features/composites/react.js +3 -1
  143. package/dist/features/composites/react.js.map +1 -1
  144. package/dist/features/composites/schema.d.ts +5 -3
  145. package/dist/features/composites/schema.js +8 -4
  146. package/dist/features/composites/schema.js.map +1 -1
  147. package/dist/features/composites/split.d.ts +62 -0
  148. package/dist/features/composites/split.js +172 -0
  149. package/dist/features/composites/split.js.map +1 -0
  150. package/dist/features/composites/vue.d.ts +4 -3
  151. package/dist/features/composites/vue.js +7 -5
  152. package/dist/features/composites/vue.js.map +1 -1
  153. package/dist/features/media/index.js +1 -1
  154. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  155. package/dist/features/media/react.js +1 -1
  156. package/dist/features/transfer/components/TransferMenu.js +93 -0
  157. package/dist/features/transfer/components/TransferMenu.js.map +1 -0
  158. package/dist/features/transfer/components/TransferMenu.vue.d.ts +15 -0
  159. package/dist/features/transfer/feature.d.ts +76 -0
  160. package/dist/features/transfer/feature.js +169 -0
  161. package/dist/features/transfer/feature.js.map +1 -0
  162. package/dist/features/transfer/index.d.ts +3 -0
  163. package/dist/features/transfer/index.js +3 -0
  164. package/dist/features/transfer/react/TransferMenu.d.ts +12 -0
  165. package/dist/features/transfer/react/TransferMenu.js +71 -0
  166. package/dist/features/transfer/react/TransferMenu.js.map +1 -0
  167. package/dist/features/transfer/react.d.ts +10 -0
  168. package/dist/features/transfer/react.js +11 -0
  169. package/dist/features/transfer/react.js.map +1 -0
  170. package/dist/features/transfer/transforms.d.ts +83 -0
  171. package/dist/features/transfer/transforms.js +137 -0
  172. package/dist/features/transfer/transforms.js.map +1 -0
  173. package/dist/features/transfer/vue.d.ts +9 -0
  174. package/dist/features/transfer/vue.js +11 -0
  175. package/dist/features/transfer/vue.js.map +1 -0
  176. package/dist/i18n/de/ai.js +4 -0
  177. package/dist/i18n/de/ai.js.map +1 -1
  178. package/dist/i18n/de/composites.js +20 -1
  179. package/dist/i18n/de/composites.js.map +1 -1
  180. package/dist/i18n/de/integrations.js +16 -0
  181. package/dist/i18n/de/integrations.js.map +1 -1
  182. package/dist/i18n/de/transfer.js +17 -0
  183. package/dist/i18n/de/transfer.js.map +1 -0
  184. package/dist/i18n/de/tree.js +6 -0
  185. package/dist/i18n/de/tree.js.map +1 -1
  186. package/dist/i18n/de.d.ts +55 -0
  187. package/dist/i18n/de.js +3 -1
  188. package/dist/i18n/de.js.map +1 -1
  189. package/dist/i18n/en/ai.js +4 -0
  190. package/dist/i18n/en/ai.js.map +1 -1
  191. package/dist/i18n/en/composites.js +20 -1
  192. package/dist/i18n/en/composites.js.map +1 -1
  193. package/dist/i18n/en/integrations.js +16 -0
  194. package/dist/i18n/en/integrations.js.map +1 -1
  195. package/dist/i18n/en/transfer.js +17 -0
  196. package/dist/i18n/en/transfer.js.map +1 -0
  197. package/dist/i18n/en/tree.js +6 -0
  198. package/dist/i18n/en/tree.js.map +1 -1
  199. package/dist/i18n/en.js +3 -1
  200. package/dist/i18n/en.js.map +1 -1
  201. package/dist/integrations/composite-ai/composite-fill.js +1 -1
  202. package/dist/integrations/composite-ai/composite-summary.js +1 -1
  203. package/dist/integrations/composite-ai/derive.d.ts +21 -0
  204. package/dist/integrations/composite-ai/derive.js +69 -47
  205. package/dist/integrations/composite-ai/derive.js.map +1 -1
  206. package/dist/integrations/composite-ai/index.d.ts +8 -3
  207. package/dist/integrations/composite-ai/index.js +50 -4
  208. package/dist/integrations/composite-ai/index.js.map +1 -1
  209. package/dist/integrations/composite-ai/outline-sanitize.d.ts +48 -0
  210. package/dist/integrations/composite-ai/outline-sanitize.js +175 -0
  211. package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -0
  212. package/dist/integrations/composite-ai/split.d.ts +44 -0
  213. package/dist/integrations/composite-ai/split.js +187 -0
  214. package/dist/integrations/composite-ai/split.js.map +1 -0
  215. package/dist/integrations/composite-ai/transfer-transforms.d.ts +27 -0
  216. package/dist/integrations/composite-ai/transfer-transforms.js +153 -0
  217. package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -0
  218. package/dist/integrations/transcript-ai/protocol.d.ts +13 -0
  219. package/dist/integrations/transcript-ai/protocol.js +49 -1
  220. package/dist/integrations/transcript-ai/protocol.js.map +1 -1
  221. package/dist/integrations/transcript-ai/transcript-cleanup.js +1 -1
  222. package/dist/markdown/MarkdownSurface.vue.d.ts +6 -6
  223. package/dist/nuxt/module.d.ts +110 -0
  224. package/dist/presets/compose.d.ts +24 -8
  225. package/dist/presets/compose.js +117 -58
  226. package/dist/presets/compose.js.map +1 -1
  227. package/dist/react/compose.js +6 -2
  228. package/dist/react/compose.js.map +1 -1
  229. package/dist/react/composed-surface.d.ts +9 -0
  230. package/dist/react/composed-surface.js +4 -1
  231. package/dist/react/composed-surface.js.map +1 -1
  232. package/dist/server/ai.d.ts +2 -5
  233. package/dist/server/ai.js.map +1 -1
  234. package/dist/server/handlers/ai.d.ts +7 -78
  235. package/dist/server/handlers/ai.js +30 -94
  236. package/dist/server/handlers/ai.js.map +1 -1
  237. package/dist/server/handlers/editor.d.ts +1 -0
  238. package/dist/server/handlers/index.d.ts +3 -1
  239. package/dist/server/handlers/index.js +3 -1
  240. package/dist/server/index.d.ts +2 -1
  241. package/dist/settings/index.d.ts +8 -0
  242. package/dist/settings/index.js +16 -4
  243. package/dist/settings/index.js.map +1 -1
  244. package/dist/styles/composites.css +32 -0
  245. package/dist/tree/DocumentTree.js +229 -78
  246. package/dist/tree/DocumentTree.js.map +1 -1
  247. package/dist/tree/drop-rules.js +8 -0
  248. package/dist/tree/drop-rules.js.map +1 -1
  249. package/dist/tree/react/DocumentTree.js +152 -31
  250. package/dist/tree/react/DocumentTree.js.map +1 -1
  251. package/dist/tree/tree-host.js +30 -1
  252. package/dist/tree/tree-host.js.map +1 -1
  253. package/dist/tree/tree-items.js +52 -5
  254. package/dist/tree/tree-items.js.map +1 -1
  255. package/dist/tree/tree-model.js +113 -10
  256. package/dist/tree/tree-model.js.map +1 -1
  257. package/dist/tree/tree-rows.js +20 -7
  258. package/dist/tree/tree-rows.js.map +1 -1
  259. package/dist/tree/tree-view-model.d.ts +5 -0
  260. package/dist/tree/tree-view-model.js +13 -0
  261. package/dist/tree/tree-view-model.js.map +1 -1
  262. package/dist/vue/AdvancedEditor.js +6 -0
  263. package/dist/vue/AdvancedEditor.js.map +1 -1
  264. package/dist/vue/AdvancedEditor.vue.d.ts +13 -5
  265. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  266. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  267. package/dist/vue/compose.js +6 -2
  268. package/dist/vue/compose.js.map +1 -1
  269. package/dist/vue/kit/types.d.ts +2 -0
  270. package/package.json +21 -1
@@ -41,24 +41,24 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
41
41
  settingsOpen: import("vue").WritableComputedRef<boolean, boolean>;
42
42
  settingsTab: import("vue").WritableComputedRef<string | undefined, string | undefined>;
43
43
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
44
+ settingsOpen: (tab?: string | undefined) => any;
44
45
  "update:sidebarOpen": (value: boolean) => any;
45
46
  "update:commentsOpen": (value: boolean) => any;
46
- ready: (editor: Editor) => any;
47
47
  "update:modelValue": (markdown: string) => any;
48
+ frontmatter: (frontmatter: string | null) => any;
49
+ ready: (editor: Editor) => any;
48
50
  metadataCreate: (list: string, item: MetadataItem) => any;
49
51
  contentError: (error: Error) => any;
50
- settingsOpen: (tab?: string | undefined) => any;
51
- frontmatter: (frontmatter: string | null) => any;
52
52
  diagnostics: (diagnostics: MarkdownDiagnostic[]) => any;
53
53
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
54
+ onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
54
55
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
55
56
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
56
- onReady?: ((editor: Editor) => any) | undefined;
57
57
  "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
58
+ onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
59
+ onReady?: ((editor: Editor) => any) | undefined;
58
60
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
59
61
  onContentError?: ((error: Error) => any) | undefined;
60
- onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
61
- onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
62
62
  onDiagnostics?: ((diagnostics: MarkdownDiagnostic[]) => any) | undefined;
63
63
  }>, {
64
64
  editable: boolean;
@@ -11,6 +11,16 @@ export type ModuleOptions = EditorConfigInput;
11
11
  declare const _default: import("@nuxt/schema").NuxtModule<{
12
12
  locale?: "de" | "en" | undefined;
13
13
  messages?: {
14
+ "transfer.copy"?: string | undefined;
15
+ "transfer.summary"?: string | undefined;
16
+ "transfer.bullets"?: string | undefined;
17
+ "transfer.summaryTitle"?: string | undefined;
18
+ "transfer.bulletsTitle"?: string | undefined;
19
+ "transfer.refused"?: string | undefined;
20
+ "transfer.selfDrop"?: string | undefined;
21
+ "transfer.running"?: string | undefined;
22
+ "transfer.done"?: string | undefined;
23
+ "transfer.menu.title"?: string | undefined;
14
24
  "palette.title"?: string | undefined;
15
25
  "palette.description"?: string | undefined;
16
26
  "palette.placeholder"?: string | undefined;
@@ -58,6 +68,22 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
58
68
  "integrations.compositeSummary.gone.title"?: string | undefined;
59
69
  "integrations.compositeSummary.gone.description"?: string | undefined;
60
70
  "integrations.compositeSummary.done"?: string | undefined;
71
+ "integrations.compositeSplit.ai.children"?: string | undefined;
72
+ "integrations.compositeSplit.ai.siblings"?: string | undefined;
73
+ "integrations.compositeSplit.changed"?: string | undefined;
74
+ "integrations.compositeSplit.running"?: string | undefined;
75
+ "integrations.compositeSplit.failed"?: string | undefined;
76
+ "integrations.compositeSplit.notPossible"?: string | undefined;
77
+ "integrations.compositeSplit.tooLong"?: string | undefined;
78
+ "integrations.compositeSplit.gone"?: string | undefined;
79
+ "integrations.outlineSanitize.label"?: string | undefined;
80
+ "integrations.outlineSanitize.none"?: string | undefined;
81
+ "integrations.outlineSanitize.invalid"?: string | undefined;
82
+ "integrations.outlineSanitize.running"?: string | undefined;
83
+ "integrations.outlineSanitize.done"?: string | undefined;
84
+ "integrations.outlineSanitize.failed"?: string | undefined;
85
+ "integrations.outlineSanitize.tooLong"?: string | undefined;
86
+ "integrations.outlineSanitize.gone"?: string | undefined;
61
87
  "integrations.rendition.action"?: string | undefined;
62
88
  "integrations.rendition.regenerate"?: string | undefined;
63
89
  "integrations.rendition.running"?: string | undefined;
@@ -154,6 +180,11 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
154
180
  "tree.filterText.placeholder"?: string | undefined;
155
181
  "tree.filterText.clear"?: string | undefined;
156
182
  "tree.noMatches"?: string | undefined;
183
+ "tree.basketFilter.label"?: string | undefined;
184
+ "tree.basketFilter.reset"?: string | undefined;
185
+ "tree.focus.root"?: string | undefined;
186
+ "tree.focus.enter"?: string | undefined;
187
+ "tree.focus.leave"?: string | undefined;
157
188
  "tree.root.folders"?: string | undefined;
158
189
  "tree.root.file"?: string | undefined;
159
190
  "tree.root.unavailable"?: string | undefined;
@@ -165,6 +196,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
165
196
  "tree.drop.folderInFolder"?: string | undefined;
166
197
  "tree.drop.blocksOnlyInDocument"?: string | undefined;
167
198
  "tree.drop.noBlocksHere"?: string | undefined;
199
+ "tree.drop.noTransfer"?: string | undefined;
168
200
  "tree.drop.blockWithoutId"?: string | undefined;
169
201
  "tree.drop.editorClosed"?: string | undefined;
170
202
  "themes.tab"?: string | undefined;
@@ -308,6 +340,11 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
308
340
  "composites.slash.flattenAll"?: string | undefined;
309
341
  "composites.blockAction.export"?: string | undefined;
310
342
  "composites.blockAction.bibtex"?: string | undefined;
343
+ "composites.split.here"?: string | undefined;
344
+ "composites.split.children"?: string | undefined;
345
+ "composites.split.lengthChildren"?: string | undefined;
346
+ "composites.split.lengthSiblings"?: string | undefined;
347
+ "settings.editing.splitTargetChars"?: string | undefined;
311
348
  "composites.toolbar.toKind"?: string | undefined;
312
349
  "composites.toolbar.structure"?: string | undefined;
313
350
  "composites.menu.kindHeading"?: string | undefined;
@@ -344,6 +381,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
344
381
  "composites.reference.backlinks"?: string | undefined;
345
382
  "composites.derivation.badge"?: string | undefined;
346
383
  "composites.derivation.stale"?: string | undefined;
384
+ "composites.derivation.foreign"?: string | undefined;
347
385
  "composites.derivation.edited"?: string | undefined;
348
386
  "composites.derivation.expand"?: string | undefined;
349
387
  "composites.derivation.collapse"?: string | undefined;
@@ -438,6 +476,19 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
438
476
  "composites.move.targetNotBlock"?: string | undefined;
439
477
  "composites.move.intoSelf"?: string | undefined;
440
478
  "composites.move.intoOwn"?: string | undefined;
479
+ "composites.basket.label"?: string | undefined;
480
+ "composites.basket.none"?: string | undefined;
481
+ "composites.basket.red"?: string | undefined;
482
+ "composites.basket.orange"?: string | undefined;
483
+ "composites.basket.yellow"?: string | undefined;
484
+ "composites.basket.green"?: string | undefined;
485
+ "composites.basket.blue"?: string | undefined;
486
+ "composites.titleHidden.hide"?: string | undefined;
487
+ "composites.titleHidden.show"?: string | undefined;
488
+ "composites.focus.action"?: string | undefined;
489
+ "composites.focus.leave"?: string | undefined;
490
+ "composites.focus.chip"?: string | undefined;
491
+ "composites.focus.release"?: string | undefined;
441
492
  "authors.tab"?: string | undefined;
442
493
  "authors.title"?: string | undefined;
443
494
  "authors.switch.label"?: string | undefined;
@@ -499,6 +550,10 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
499
550
  "ai.task.continue.label"?: string | undefined;
500
551
  "ai.task.fillBlock.label"?: string | undefined;
501
552
  "ai.task.fillBlock.promptLabel"?: string | undefined;
553
+ "ai.task.splitBlock.label"?: string | undefined;
554
+ "ai.task.outlineSanitize.label"?: string | undefined;
555
+ "ai.task.transferSummary.label"?: string | undefined;
556
+ "ai.task.transferBullets.label"?: string | undefined;
502
557
  "ai.slot.complete.label"?: string | undefined;
503
558
  "ai.slot.complete.description"?: string | undefined;
504
559
  "ai.slot.rewrite.label"?: string | undefined;
@@ -709,6 +764,16 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
709
764
  }, {
710
765
  locale?: "de" | "en" | undefined;
711
766
  messages?: {
767
+ "transfer.copy"?: string | undefined;
768
+ "transfer.summary"?: string | undefined;
769
+ "transfer.bullets"?: string | undefined;
770
+ "transfer.summaryTitle"?: string | undefined;
771
+ "transfer.bulletsTitle"?: string | undefined;
772
+ "transfer.refused"?: string | undefined;
773
+ "transfer.selfDrop"?: string | undefined;
774
+ "transfer.running"?: string | undefined;
775
+ "transfer.done"?: string | undefined;
776
+ "transfer.menu.title"?: string | undefined;
712
777
  "palette.title"?: string | undefined;
713
778
  "palette.description"?: string | undefined;
714
779
  "palette.placeholder"?: string | undefined;
@@ -756,6 +821,22 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
756
821
  "integrations.compositeSummary.gone.title"?: string | undefined;
757
822
  "integrations.compositeSummary.gone.description"?: string | undefined;
758
823
  "integrations.compositeSummary.done"?: string | undefined;
824
+ "integrations.compositeSplit.ai.children"?: string | undefined;
825
+ "integrations.compositeSplit.ai.siblings"?: string | undefined;
826
+ "integrations.compositeSplit.changed"?: string | undefined;
827
+ "integrations.compositeSplit.running"?: string | undefined;
828
+ "integrations.compositeSplit.failed"?: string | undefined;
829
+ "integrations.compositeSplit.notPossible"?: string | undefined;
830
+ "integrations.compositeSplit.tooLong"?: string | undefined;
831
+ "integrations.compositeSplit.gone"?: string | undefined;
832
+ "integrations.outlineSanitize.label"?: string | undefined;
833
+ "integrations.outlineSanitize.none"?: string | undefined;
834
+ "integrations.outlineSanitize.invalid"?: string | undefined;
835
+ "integrations.outlineSanitize.running"?: string | undefined;
836
+ "integrations.outlineSanitize.done"?: string | undefined;
837
+ "integrations.outlineSanitize.failed"?: string | undefined;
838
+ "integrations.outlineSanitize.tooLong"?: string | undefined;
839
+ "integrations.outlineSanitize.gone"?: string | undefined;
759
840
  "integrations.rendition.action"?: string | undefined;
760
841
  "integrations.rendition.regenerate"?: string | undefined;
761
842
  "integrations.rendition.running"?: string | undefined;
@@ -852,6 +933,11 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
852
933
  "tree.filterText.placeholder"?: string | undefined;
853
934
  "tree.filterText.clear"?: string | undefined;
854
935
  "tree.noMatches"?: string | undefined;
936
+ "tree.basketFilter.label"?: string | undefined;
937
+ "tree.basketFilter.reset"?: string | undefined;
938
+ "tree.focus.root"?: string | undefined;
939
+ "tree.focus.enter"?: string | undefined;
940
+ "tree.focus.leave"?: string | undefined;
855
941
  "tree.root.folders"?: string | undefined;
856
942
  "tree.root.file"?: string | undefined;
857
943
  "tree.root.unavailable"?: string | undefined;
@@ -863,6 +949,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
863
949
  "tree.drop.folderInFolder"?: string | undefined;
864
950
  "tree.drop.blocksOnlyInDocument"?: string | undefined;
865
951
  "tree.drop.noBlocksHere"?: string | undefined;
952
+ "tree.drop.noTransfer"?: string | undefined;
866
953
  "tree.drop.blockWithoutId"?: string | undefined;
867
954
  "tree.drop.editorClosed"?: string | undefined;
868
955
  "themes.tab"?: string | undefined;
@@ -1006,6 +1093,11 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1006
1093
  "composites.slash.flattenAll"?: string | undefined;
1007
1094
  "composites.blockAction.export"?: string | undefined;
1008
1095
  "composites.blockAction.bibtex"?: string | undefined;
1096
+ "composites.split.here"?: string | undefined;
1097
+ "composites.split.children"?: string | undefined;
1098
+ "composites.split.lengthChildren"?: string | undefined;
1099
+ "composites.split.lengthSiblings"?: string | undefined;
1100
+ "settings.editing.splitTargetChars"?: string | undefined;
1009
1101
  "composites.toolbar.toKind"?: string | undefined;
1010
1102
  "composites.toolbar.structure"?: string | undefined;
1011
1103
  "composites.menu.kindHeading"?: string | undefined;
@@ -1042,6 +1134,7 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1042
1134
  "composites.reference.backlinks"?: string | undefined;
1043
1135
  "composites.derivation.badge"?: string | undefined;
1044
1136
  "composites.derivation.stale"?: string | undefined;
1137
+ "composites.derivation.foreign"?: string | undefined;
1045
1138
  "composites.derivation.edited"?: string | undefined;
1046
1139
  "composites.derivation.expand"?: string | undefined;
1047
1140
  "composites.derivation.collapse"?: string | undefined;
@@ -1136,6 +1229,19 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1136
1229
  "composites.move.targetNotBlock"?: string | undefined;
1137
1230
  "composites.move.intoSelf"?: string | undefined;
1138
1231
  "composites.move.intoOwn"?: string | undefined;
1232
+ "composites.basket.label"?: string | undefined;
1233
+ "composites.basket.none"?: string | undefined;
1234
+ "composites.basket.red"?: string | undefined;
1235
+ "composites.basket.orange"?: string | undefined;
1236
+ "composites.basket.yellow"?: string | undefined;
1237
+ "composites.basket.green"?: string | undefined;
1238
+ "composites.basket.blue"?: string | undefined;
1239
+ "composites.titleHidden.hide"?: string | undefined;
1240
+ "composites.titleHidden.show"?: string | undefined;
1241
+ "composites.focus.action"?: string | undefined;
1242
+ "composites.focus.leave"?: string | undefined;
1243
+ "composites.focus.chip"?: string | undefined;
1244
+ "composites.focus.release"?: string | undefined;
1139
1245
  "authors.tab"?: string | undefined;
1140
1246
  "authors.title"?: string | undefined;
1141
1247
  "authors.switch.label"?: string | undefined;
@@ -1197,6 +1303,10 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1197
1303
  "ai.task.continue.label"?: string | undefined;
1198
1304
  "ai.task.fillBlock.label"?: string | undefined;
1199
1305
  "ai.task.fillBlock.promptLabel"?: string | undefined;
1306
+ "ai.task.splitBlock.label"?: string | undefined;
1307
+ "ai.task.outlineSanitize.label"?: string | undefined;
1308
+ "ai.task.transferSummary.label"?: string | undefined;
1309
+ "ai.task.transferBullets.label"?: string | undefined;
1200
1310
  "ai.slot.complete.label"?: string | undefined;
1201
1311
  "ai.slot.complete.description"?: string | undefined;
1202
1312
  "ai.slot.rewrite.label"?: string | undefined;
@@ -1,8 +1,13 @@
1
1
  import { EditorBackend } from "../core/backend.js";
2
+ import { BlockUiOptions } from "../core/extension-points.js";
2
3
  import { EditorFeature, EditorPreset } from "../core/feature.js";
4
+ import { CoreContentOptions } from "../core/schema/index.js";
3
5
  import { CommentsFeatureOptions } from "../features/comments/feature.js";
4
6
  import { CompositeKind } from "../features/composites/kinds.js";
7
+ import { Basket } from "../features/composites/baskets.js";
5
8
  import { CompositeFeatureOptions } from "../features/composites/feature.js";
9
+ import { BlockTransform } from "../features/transfer/transforms.js";
10
+ import { TransferFeatureOptions } from "../features/transfer/feature.js";
6
11
  //#region src/presets/compose.d.ts
7
12
  /** The id of a catalog feature (`CONTENT`, `INTERACTION`, `AI`) or of a host feature passed to `remove`. */
8
13
  export type FeatureId = string;
@@ -10,18 +15,12 @@ export type FeatureId = string;
10
15
  export type ContentLevel = 'basic' | 'rich';
11
16
  /** How much editing UX the editor has: `minimal` = `core-ui`, `full` = every interaction feature. */
12
17
  export type InteractionLevel = 'minimal' | 'full';
13
- /** The content features of each level, in canonical (schema) order. */
14
- export declare const CONTENT: Record<ContentLevel, readonly FeatureId[]>;
15
- /** The interaction features of each level, in canonical order. */
16
- export declare const INTERACTION: Record<InteractionLevel, readonly FeatureId[]>;
17
- /** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */
18
- export declare const AI: readonly FeatureId[];
19
18
  /**
20
19
  * The features a UI layer binds, keyed by id; the other catalog features are framework-free and built here. The AI
21
20
  * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of
22
21
  * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a
23
22
  * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so
24
- * unselected features are never built). `composites` receives the composition's `compositeKinds`, `comments` its
23
+ * unselected features are never built). `composites` receives the composition's `compositeKinds` and `compositeBaskets`, `comments` its
25
24
  * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;
26
25
  * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.
27
26
  */
@@ -36,8 +35,11 @@ export interface UiBindings<C> {
36
35
  'composite-ai': () => EditorFeature<C>;
37
36
  'transcript-ai': () => EditorFeature<C>;
38
37
  'collab': () => EditorFeature<C>;
39
- 'block-ui': () => EditorFeature<C>;
38
+ 'block-ui': (options: BlockUiOptions) => EditorFeature<C>;
40
39
  'themes': () => EditorFeature<C>;
40
+ 'transfer': (options: TransferFeatureOptions) => EditorFeature<C>;
41
+ /** The AI transforms of the transfer menu (`summaryTransform`, `bulletsTransform` of `integrations/composite-ai`); called only when `ai` is on and the host passes no `transfer.transforms`. */
42
+ 'transfer-ai': () => readonly BlockTransform[];
41
43
  }
42
44
  /** What `composeEditor` builds the editor from. */
43
45
  export interface ComposeOptions<C> {
@@ -61,8 +63,16 @@ export interface ComposeOptions<C> {
61
63
  remove?: readonly FeatureId[];
62
64
  /** The composite kinds („Bausteine“) offered in the editor (default: the built-in kinds); read once. */
63
65
  compositeKinds?: readonly CompositeKind[];
66
+ /** The colour baskets a Baustein can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */
67
+ compositeBaskets?: readonly Basket[];
64
68
  /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */
65
69
  comments?: CommentsFeatureOptions;
70
+ /** Optional structures the content base drops (headings or heading levels, lists, blockquote, code block, rule); everything is on by default. Applies to the editor and to the server schema built from the preset's `schemaExtensions`. */
71
+ coreContent?: CoreContentOptions;
72
+ /** Options of the block UI (`block-ui`, `interaction: 'full'`): which surfaces render block actions (hover bar, selected-block toolbar, both, none); the hover bar by default. */
73
+ blockUi?: BlockUiOptions;
74
+ /** Options of the transfer feature (`interaction: [..., 'transfer']`; in no level list): the transforms a drop offers (default: the copy, plus the AI transforms when `ai` is on) and the default one. */
75
+ transfer?: TransferFeatureOptions;
66
76
  }
67
77
  /** The composed preset and the features that were selected but dropped, in composition order, with the reason. */
68
78
  export interface ComposedEditor<C> extends EditorPreset<C> {
@@ -71,6 +81,12 @@ export interface ComposedEditor<C> extends EditorPreset<C> {
71
81
  reason: string;
72
82
  }[];
73
83
  }
84
+ /** The content features of each level, in canonical (schema) order. */
85
+ export declare const CONTENT: Record<ContentLevel, readonly FeatureId[]>;
86
+ /** The interaction features of each level, in canonical order. */
87
+ export declare const INTERACTION: Record<InteractionLevel, readonly FeatureId[]>;
88
+ /** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */
89
+ export declare const AI: readonly FeatureId[];
74
90
  /**
75
91
  * Composes an editor from three dimensions plus the backend's capabilities, over the UI bindings of a layer.
76
92
  *
@@ -2,75 +2,134 @@ import { defineEditor } from "../core/define-editor.js";
2
2
  import { coreContentFeature, coreUiFeature } from "../core/core-feature.js";
3
3
  import { CommentMark } from "../features/comments/schema.js";
4
4
  import { mentionsFeature } from "../features/mentions/index.js";
5
+ import { copyTransform } from "../features/transfer/transforms.js";
5
6
  import { tablesFeature } from "../features/tables/feature.js";
6
7
  import { compositeMediaFeature } from "../integrations/composite-media/index.js";
7
8
  //#region src/presets/compose.ts
9
+ function fail(message) {
10
+ throw new Error(`@ecsplico/editor: composeEditor: ${message}`);
11
+ }
12
+ /** The binding `key` of `ui`; a framework binding the composition needs but `ui` lacks fails here, naming it. */
13
+ function bound(ui, key) {
14
+ return ui[key] ?? fail(`no UI binding for feature "${key}"`);
15
+ }
16
+ /**
17
+ * The catalog: the one table that drives composition. Its key order is the canonical order (content, interaction, AI):
18
+ * the composed feature list, its schema order and its toolbar order follow it, and `CONTENT`, `INTERACTION`, `AI` are
19
+ * derived from it. Adding a catalog feature is one row here, plus, for a UI-bound feature, a key in `UiBindings` and an
20
+ * entry in both binding records (`vue/compose.ts`, `react/compose.ts`; their `satisfies UiBindings` check fails until
21
+ * they hold it). Framework-free features are called directly, UI-bound ones go through `bound`.
22
+ */
23
+ const CATALOG = {
24
+ "core-content": {
25
+ dimension: "content",
26
+ levels: ["basic", "rich"],
27
+ build: (_, options) => coreContentFeature(options.coreContent)
28
+ },
29
+ "media": {
30
+ dimension: "content",
31
+ levels: ["rich"],
32
+ build: (ui) => bound(ui, "media")()
33
+ },
34
+ "transcript": {
35
+ dimension: "content",
36
+ levels: ["rich"],
37
+ build: (ui) => bound(ui, "transcript")()
38
+ },
39
+ "composites": {
40
+ dimension: "content",
41
+ levels: ["rich"],
42
+ build: (ui, options) => bound(ui, "composites")({
43
+ ...options.compositeKinds && { kinds: options.compositeKinds },
44
+ ...options.compositeBaskets && { baskets: options.compositeBaskets }
45
+ })
46
+ },
47
+ "mentions": {
48
+ dimension: "content",
49
+ levels: ["rich"],
50
+ build: () => mentionsFeature()
51
+ },
52
+ "authors": {
53
+ dimension: "content",
54
+ levels: ["rich"],
55
+ build: (ui) => bound(ui, "authors")()
56
+ },
57
+ "tables": {
58
+ dimension: "content",
59
+ levels: ["rich"],
60
+ build: () => tablesFeature()
61
+ },
62
+ "composite-media": {
63
+ dimension: "content",
64
+ levels: ["rich"],
65
+ build: () => compositeMediaFeature()
66
+ },
67
+ "core-ui": {
68
+ dimension: "interaction",
69
+ levels: ["minimal", "full"],
70
+ build: (ui) => bound(ui, "core-ui")()
71
+ },
72
+ "collab": {
73
+ dimension: "interaction",
74
+ levels: ["full"],
75
+ build: (ui) => bound(ui, "collab")()
76
+ },
77
+ "comments": {
78
+ dimension: "interaction",
79
+ levels: ["full"],
80
+ build: (ui, options) => bound(ui, "comments")(options.comments ?? {})
81
+ },
82
+ "block-ui": {
83
+ dimension: "interaction",
84
+ levels: ["full"],
85
+ build: (ui, options) => bound(ui, "block-ui")(options.blockUi ?? {})
86
+ },
87
+ "themes": {
88
+ dimension: "interaction",
89
+ levels: ["full"],
90
+ build: (ui) => bound(ui, "themes")()
91
+ },
92
+ "transfer": {
93
+ dimension: "interaction",
94
+ build: (ui, options) => bound(ui, "transfer")({
95
+ ...options.transfer,
96
+ ...!options.transfer?.transforms && options.ai && { transforms: [copyTransform, ...bound(ui, "transfer-ai")()] }
97
+ })
98
+ },
99
+ "ai": {
100
+ dimension: "ai",
101
+ build: (ui) => bound(ui, "ai")()
102
+ },
103
+ "composite-ai": {
104
+ dimension: "ai",
105
+ build: (ui) => bound(ui, "composite-ai")()
106
+ },
107
+ "transcript-ai": {
108
+ dimension: "ai",
109
+ build: (ui) => bound(ui, "transcript-ai")()
110
+ }
111
+ };
112
+ const catalogIds = (include) => Object.entries(CATALOG).filter(([, entry]) => include(entry)).map(([id]) => id);
113
+ const levelIds = (level) => catalogIds((entry) => entry.levels?.includes(level) ?? false);
8
114
  /** The content features of each level, in canonical (schema) order. */
9
115
  const CONTENT = {
10
- basic: ["core-content"],
11
- rich: [
12
- "core-content",
13
- "media",
14
- "transcript",
15
- "composites",
16
- "mentions",
17
- "authors",
18
- "tables",
19
- "composite-media"
20
- ]
116
+ basic: levelIds("basic"),
117
+ rich: levelIds("rich")
21
118
  };
22
119
  /** The interaction features of each level, in canonical order. */
23
120
  const INTERACTION = {
24
- minimal: ["core-ui"],
25
- full: [
26
- "core-ui",
27
- "collab",
28
- "comments",
29
- "block-ui",
30
- "themes"
31
- ]
121
+ minimal: levelIds("minimal"),
122
+ full: levelIds("full")
32
123
  };
33
124
  /** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */
34
- const AI = [
35
- "ai",
36
- "composite-ai",
37
- "transcript-ai"
38
- ];
39
- /** Canonical feature order: content, interaction, AI. The composed feature list, its schema order and its toolbar order follow it. */
40
- const CANONICAL = [
41
- ...CONTENT.rich,
42
- ...INTERACTION.full,
43
- ...AI
44
- ];
45
- function fail(message) {
46
- throw new Error(`@ecsplico/editor: composeEditor: ${message}`);
47
- }
48
- /**
49
- * Builds the catalog feature `id`. A framework binding the composition needs but `ui` lacks fails here, naming it.
50
- * `ui` is partial on purpose: a host that never selects a feature (a viewer has no `block-ui`) binds only the rest, so
51
- * the bundle holds no code of the others.
52
- */
125
+ const AI = catalogIds((entry) => entry.dimension === "ai");
126
+ /** Canonical feature order: the key order of the catalog (content, interaction, AI). */
127
+ const CANONICAL = Object.keys(CATALOG);
128
+ /** Builds the catalog feature `id`; an id outside the catalog or a missing binding fails, naming it. */
53
129
  function build(id, ui, options) {
54
- const bound = (key) => ui[key] ?? fail(`no UI binding for feature "${key}"`);
55
- switch (id) {
56
- case "core-content": return coreContentFeature();
57
- case "mentions": return mentionsFeature();
58
- case "tables": return tablesFeature();
59
- case "composite-media": return compositeMediaFeature();
60
- case "core-ui": return bound("core-ui")();
61
- case "composite-ai": return bound("composite-ai")();
62
- case "transcript-ai": return bound("transcript-ai")();
63
- case "media": return bound("media")();
64
- case "transcript": return bound("transcript")();
65
- case "composites": return bound("composites")(options.compositeKinds ? { kinds: options.compositeKinds } : {});
66
- case "authors": return bound("authors")();
67
- case "comments": return bound("comments")(options.comments ?? {});
68
- case "ai": return bound("ai")();
69
- case "collab": return bound("collab")();
70
- case "block-ui": return bound("block-ui")();
71
- case "themes": return bound("themes")();
72
- default: return fail(`unknown catalog feature "${id}" (host features go in \`add\`)`);
73
- }
130
+ const entry = Object.hasOwn(CATALOG, id) ? CATALOG[id] : void 0;
131
+ if (!entry) fail(`unknown catalog feature "${id}" (host features go in \`add\`)`);
132
+ return entry.build(ui, options);
74
133
  }
75
134
  /** Why `feature` cannot stay in a composition holding `ids` over `backend`, or `undefined`. A host session satisfies `collaboration`. */
76
135
  function unmet(feature, ids, options) {
@@ -1 +1 @@
1
- {"version":3,"file":"compose.js","names":[],"sources":["../../src/presets/compose.ts"],"sourcesContent":["import type { EditorBackend } from '../core/backend'\nimport { coreContentFeature, coreUiFeature } from '../core/core-feature'\nimport { defineEditor } from '../core/define-editor'\nimport type { EditorFeature, EditorPreset } from '../core/feature'\nimport type { CommentsFeatureOptions } from '../features/comments/feature'\nimport { CommentMark } from '../features/comments/schema'\nimport type { CompositeFeatureOptions } from '../features/composites/feature'\nimport type { CompositeKind } from '../features/composites/kinds'\nimport { mentionsFeature } from '../features/mentions'\nimport { tablesFeature } from '../features/tables'\nimport { compositeMediaFeature } from '../integrations/composite-media'\n\n/** The id of a catalog feature (`CONTENT`, `INTERACTION`, `AI`) or of a host feature passed to `remove`. */\nexport type FeatureId = string\n\n/** How much document model the editor has: `basic` = `core-content`, `rich` = the full content catalog. */\nexport type ContentLevel = 'basic' | 'rich'\n\n/** How much editing UX the editor has: `minimal` = `core-ui`, `full` = every interaction feature. */\nexport type InteractionLevel = 'minimal' | 'full'\n\n/** The content features of each level, in canonical (schema) order. */\nexport const CONTENT: Record<ContentLevel, readonly FeatureId[]> = {\n basic: ['core-content'],\n rich: ['core-content', 'media', 'transcript', 'composites', 'mentions', 'authors', 'tables', 'composite-media'],\n}\n\n/** The interaction features of each level, in canonical order. */\nexport const INTERACTION: Record<InteractionLevel, readonly FeatureId[]> = {\n minimal: ['core-ui'],\n full: ['core-ui', 'collab', 'comments', 'block-ui', 'themes'],\n}\n\n/** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */\nexport const AI: readonly FeatureId[] = ['ai', 'composite-ai', 'transcript-ai']\n\n/** Canonical feature order: content, interaction, AI. The composed feature list, its schema order and its toolbar order follow it. */\nconst CANONICAL: readonly FeatureId[] = [...CONTENT.rich, ...INTERACTION.full, ...AI]\n\n/**\n * The features a UI layer binds, keyed by id; the other catalog features are framework-free and built here. The AI\n * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of\n * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a\n * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so\n * unselected features are never built). `composites` receives the composition's `compositeKinds`, `comments` its\n * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;\n * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.\n */\nexport interface UiBindings<C> {\n 'core-ui': () => EditorFeature<C>\n 'media': () => EditorFeature<C>\n 'transcript': () => EditorFeature<C>\n 'composites': (options: CompositeFeatureOptions) => EditorFeature<C>\n 'authors': () => EditorFeature<C>\n 'comments': (options: CommentsFeatureOptions) => EditorFeature<C>\n 'ai': () => EditorFeature<C>\n 'composite-ai': () => EditorFeature<C>\n 'transcript-ai': () => EditorFeature<C>\n 'collab': () => EditorFeature<C>\n 'block-ui': () => EditorFeature<C>\n 'themes': () => EditorFeature<C>\n}\n\n/** What `composeEditor` builds the editor from. */\nexport interface ComposeOptions<C> {\n /** The document model: a level or the content feature ids to install (`core-content` is always installed). */\n content: ContentLevel | readonly FeatureId[]\n /** The editing UX: a level or the interaction feature ids (`core-ui` is installed with any non-empty list); `[]` = a viewer without any interaction feature. */\n interaction: InteractionLevel | readonly FeatureId[]\n /** Installs `ai` and every integration whose `requires` are met (composite-AI iff composites, transcript-AI iff transcript). */\n ai: boolean\n /** The backend the editor runs on: features needing a capability it lacks are omitted. Absent = nothing is pruned by capability. */\n backend?: EditorBackend\n /**\n * The host supplies the collaboration session itself (the surface's `collaboration` prop, e.g. from its own Hocuspocus\n * provider), so `collab` and `comments` need no `collaboration` capability from the backend. Only a backend that must\n * open the collaboration (`useEditorDocument(id, { collaboration: true })`) has to offer it. Default `false`.\n */\n collaboration?: boolean\n /** Host features, appended after the catalog in the given order. */\n add?: readonly EditorFeature<C>[]\n /** Features left out (catalog or host); features that require them are omitted as well. */\n remove?: readonly FeatureId[]\n /** The composite kinds („Bausteine“) offered in the editor (default: the built-in kinds); read once. */\n compositeKinds?: readonly CompositeKind[]\n /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */\n comments?: CommentsFeatureOptions\n}\n\n/** The composed preset and the features that were selected but dropped, in composition order, with the reason. */\nexport interface ComposedEditor<C> extends EditorPreset<C> {\n readonly omitted: readonly { id: FeatureId, reason: string }[]\n}\n\nfunction fail(message: string): never {\n throw new Error(`@ecsplico/editor: composeEditor: ${message}`)\n}\n\n/**\n * Builds the catalog feature `id`. A framework binding the composition needs but `ui` lacks fails here, naming it.\n * `ui` is partial on purpose: a host that never selects a feature (a viewer has no `block-ui`) binds only the rest, so\n * the bundle holds no code of the others.\n */\nfunction build<C>(id: FeatureId, ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): EditorFeature<C> {\n const bound = <K extends keyof UiBindings<C>>(key: K): UiBindings<C>[K] => ui[key] ?? fail(`no UI binding for feature \"${key}\"`)\n switch (id) {\n case 'core-content': return coreContentFeature()\n case 'mentions': return mentionsFeature()\n case 'tables': return tablesFeature()\n case 'composite-media': return compositeMediaFeature()\n case 'core-ui': return bound('core-ui')()\n case 'composite-ai': return bound('composite-ai')()\n case 'transcript-ai': return bound('transcript-ai')()\n case 'media': return bound('media')()\n case 'transcript': return bound('transcript')()\n case 'composites': return bound('composites')(options.compositeKinds ? { kinds: options.compositeKinds } : {})\n case 'authors': return bound('authors')()\n case 'comments': return bound('comments')(options.comments ?? {})\n case 'ai': return bound('ai')()\n case 'collab': return bound('collab')()\n case 'block-ui': return bound('block-ui')()\n case 'themes': return bound('themes')()\n default: return fail(`unknown catalog feature \"${id}\" (host features go in \\`add\\`)`)\n }\n}\n\n/** Why `feature` cannot stay in a composition holding `ids` over `backend`, or `undefined`. A host session satisfies `collaboration`. */\nfunction unmet(feature: Pick<EditorFeature, 'backend' | 'requires'>, ids: ReadonlySet<FeatureId>, options: Pick<ComposeOptions<unknown>, 'backend' | 'collaboration'>): string | undefined {\n const { backend } = options\n for (const capability of feature.backend ?? []) {\n if (capability === 'collaboration' && options.collaboration) continue\n if (backend && backend[capability] === undefined) return `backend \"${backend.name}\" lacks \"${capability}\"`\n }\n for (const required of feature.requires ?? []) {\n if (!ids.has(required)) return `requires \"${required}\"`\n }\n return undefined\n}\n\n/**\n * The comment mark is part of the document model (stored documents carry it), but only the `comments` feature brings it.\n * A composition that keeps `authors` (every rich one) yet has no `comments` (a viewer, a backend without collaboration,\n * `remove`) gets the mark through `authors`, inert there, so such documents still load. The catalog is the one place\n * that may couple the two features; each stays importable on its own.\n */\nfunction withCommentMark<C>(features: readonly EditorFeature<C>[]): EditorFeature<C>[] {\n if (features.some(feature => feature.id === 'comments')) return [...features]\n return features.map(feature => feature.id !== 'authors'\n ? feature\n : {\n ...feature,\n schemaExtensions: () => [...(feature.schemaExtensions?.() ?? []), CommentMark],\n extensions: ctx => [...(feature.extensions?.(ctx) ?? []), CommentMark],\n })\n}\n\n/**\n * Composes an editor from three dimensions plus the backend's capabilities, over the UI bindings of a layer.\n *\n * The feature list is `content` + `interaction` (+ the AI features when `ai`) + `add`, minus `remove`. `core-content` is\n * always part of it and `core-ui` of every non-empty interaction list. Features that require a missing feature, or a\n * backend capability `options.backend` lacks, are dropped until the list is stable and reported in `omitted` (so\n * `ai: true` over a backend without `ai` installs no AI and says why). The catalog features keep their canonical order\n * (content, interaction, AI), host features follow in the order given; the result is validated by `defineEditor`.\n * Throws when an id of `content` is not a content feature, an id of `interaction` not an interaction feature, an id\n * names no catalog feature, `remove` names `core-content`, or a selected feature has no binding in `ui`.\n */\nexport function composeEditor<C>(ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): ComposedEditor<C> {\n if (options.remove?.includes('core-content')) fail('\"core-content\" cannot be removed')\n const removed = new Set(options.remove ?? [])\n const catalog = new Map<FeatureId, EditorFeature<C>>()\n const select = (ids: readonly FeatureId[], dimension: 'content' | 'interaction' | 'ai') => {\n for (const id of ids) {\n if (removed.has(id) || catalog.has(id)) continue\n const feature = build(id, ui, options)\n if (feature.dimension !== dimension) fail(`\"${id}\" is not ${dimension === 'ai' ? 'an AI' : `a${dimension === 'interaction' ? 'n' : ''} ${dimension}`} feature`)\n catalog.set(id, feature)\n }\n }\n const content = typeof options.content === 'string' ? CONTENT[options.content] : options.content\n const interaction = typeof options.interaction === 'string' ? INTERACTION[options.interaction] : options.interaction\n select(['core-content', ...content], 'content')\n select(interaction.length ? ['core-ui', ...interaction] : [], 'interaction')\n select(options.ai ? AI : [], 'ai')\n\n const ordered = [...catalog.values()].sort((a, b) => CANONICAL.indexOf(a.id) - CANONICAL.indexOf(b.id))\n const all: EditorFeature<C>[] = [...ordered, ...(options.add ?? []).filter(feature => !removed.has(feature.id))]\n\n const reasons = new Map<FeatureId, string>()\n let alive = all\n for (;;) {\n const ids = new Set(alive.map(feature => feature.id))\n const dropped = new Map<FeatureId, string>()\n for (const feature of alive) {\n const reason = unmet(feature, ids, options)\n if (reason) dropped.set(feature.id, reason)\n }\n if (!dropped.size) break\n for (const [id, reason] of dropped) reasons.set(id, reason)\n alive = alive.filter(feature => !dropped.has(feature.id))\n }\n\n const preset = defineEditor({ features: withCommentMark(alive) })\n const omitted = all.flatMap(feature => reasons.has(feature.id) ? [{ id: feature.id, reason: reasons.get(feature.id)! }] : [])\n return Object.freeze({ ...preset, omitted: Object.freeze(omitted) })\n}\n\n/**\n * The simple editor: `core-content` and `core-ui` (formatting, headings, lists, quotes, code, undo/redo). No backend, no AI,\n * no collaboration, and no ⌘K command palette (`coreUiFeature()` gets no `palette` component here, the framework-free\n * layer has none; the `SimpleEditor` components and the `composeEditor` of `/vue/advanced` and `/react/advanced` bind it).\n * Component-free (`ComposedEditor<never>`), so both the Vue and the React surface accept it.\n */\nexport const simpleEditor = (): ComposedEditor<never> => composeEditor<never>({ 'core-ui': coreUiFeature }, { content: 'basic', interaction: 'minimal', ai: false })\n"],"mappings":";;;;;;;;AAsBA,MAAa,UAAsD;CACjE,OAAO,CAAC,cAAc;CACtB,MAAM;EAAC;EAAgB;EAAS;EAAc;EAAc;EAAY;EAAW;EAAU;CAAiB;AAChH;;AAGA,MAAa,cAA8D;CACzE,SAAS,CAAC,SAAS;CACnB,MAAM;EAAC;EAAW;EAAU;EAAY;EAAY;CAAQ;AAC9D;;AAGA,MAAa,KAA2B;CAAC;CAAM;CAAgB;AAAe;;AAG9E,MAAM,YAAkC;CAAC,GAAG,QAAQ;CAAM,GAAG,YAAY;CAAM,GAAG;AAAE;AAyDpF,SAAS,KAAK,SAAwB;CACpC,MAAM,IAAI,MAAM,oCAAoC,SAAS;AAC/D;;;;;;AAOA,SAAS,MAAS,IAAe,IAA4B,SAA8C;CACzG,MAAM,SAAwC,QAA6B,GAAG,QAAQ,KAAK,8BAA8B,IAAI,EAAE;CAC/H,QAAQ,IAAR;EACE,KAAK,gBAAgB,OAAO,mBAAmB;EAC/C,KAAK,YAAY,OAAO,gBAAgB;EACxC,KAAK,UAAU,OAAO,cAAc;EACpC,KAAK,mBAAmB,OAAO,sBAAsB;EACrD,KAAK,WAAW,OAAO,MAAM,SAAS,CAAC,CAAC;EACxC,KAAK,gBAAgB,OAAO,MAAM,cAAc,CAAC,CAAC;EAClD,KAAK,iBAAiB,OAAO,MAAM,eAAe,CAAC,CAAC;EACpD,KAAK,SAAS,OAAO,MAAM,OAAO,CAAC,CAAC;EACpC,KAAK,cAAc,OAAO,MAAM,YAAY,CAAC,CAAC;EAC9C,KAAK,cAAc,OAAO,MAAM,YAAY,CAAC,CAAC,QAAQ,iBAAiB,EAAE,OAAO,QAAQ,eAAe,IAAI,CAAC,CAAC;EAC7G,KAAK,WAAW,OAAO,MAAM,SAAS,CAAC,CAAC;EACxC,KAAK,YAAY,OAAO,MAAM,UAAU,CAAC,CAAC,QAAQ,YAAY,CAAC,CAAC;EAChE,KAAK,MAAM,OAAO,MAAM,IAAI,CAAC,CAAC;EAC9B,KAAK,UAAU,OAAO,MAAM,QAAQ,CAAC,CAAC;EACtC,KAAK,YAAY,OAAO,MAAM,UAAU,CAAC,CAAC;EAC1C,KAAK,UAAU,OAAO,MAAM,QAAQ,CAAC,CAAC;EACtC,SAAS,OAAO,KAAK,4BAA4B,GAAG,gCAAgC;CACtF;AACF;;AAGA,SAAS,MAAM,SAAsD,KAA6B,SAAyF;CACzL,MAAM,EAAE,YAAY;CACpB,KAAK,MAAM,cAAc,QAAQ,WAAW,CAAC,GAAG;EAC9C,IAAI,eAAe,mBAAmB,QAAQ,eAAe;EAC7D,IAAI,WAAW,QAAQ,gBAAgB,KAAA,GAAW,OAAO,YAAY,QAAQ,KAAK,WAAW,WAAW;CAC1G;CACA,KAAK,MAAM,YAAY,QAAQ,YAAY,CAAC,GAC1C,IAAI,CAAC,IAAI,IAAI,QAAQ,GAAG,OAAO,aAAa,SAAS;AAGzD;;;;;;;AAQA,SAAS,gBAAmB,UAA2D;CACrF,IAAI,SAAS,MAAK,YAAW,QAAQ,OAAO,UAAU,GAAG,OAAO,CAAC,GAAG,QAAQ;CAC5E,OAAO,SAAS,KAAI,YAAW,QAAQ,OAAO,YAC1C,UACA;EACE,GAAG;EACH,wBAAwB,CAAC,GAAI,QAAQ,mBAAmB,KAAK,CAAC,GAAI,WAAW;EAC7E,aAAY,QAAO,CAAC,GAAI,QAAQ,aAAa,GAAG,KAAK,CAAC,GAAI,WAAW;CACvE,CAAC;AACP;;;;;;;;;;;;AAaA,SAAgB,cAAiB,IAA4B,SAA+C;CAC1G,IAAI,QAAQ,QAAQ,SAAS,cAAc,GAAG,KAAK,oCAAkC;CACrF,MAAM,UAAU,IAAI,IAAI,QAAQ,UAAU,CAAC,CAAC;CAC5C,MAAM,0BAAU,IAAI,IAAiC;CACrD,MAAM,UAAU,KAA2B,cAAgD;EACzF,KAAK,MAAM,MAAM,KAAK;GACpB,IAAI,QAAQ,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE,GAAG;GACxC,MAAM,UAAU,MAAM,IAAI,IAAI,OAAO;GACrC,IAAI,QAAQ,cAAc,WAAW,KAAK,IAAI,GAAG,WAAW,cAAc,OAAO,UAAU,IAAI,cAAc,gBAAgB,MAAM,GAAG,GAAG,YAAY,SAAS;GAC9J,QAAQ,IAAI,IAAI,OAAO;EACzB;CACF;CACA,MAAM,UAAU,OAAO,QAAQ,YAAY,WAAW,QAAQ,QAAQ,WAAW,QAAQ;CACzF,MAAM,cAAc,OAAO,QAAQ,gBAAgB,WAAW,YAAY,QAAQ,eAAe,QAAQ;CACzG,OAAO,CAAC,gBAAgB,GAAG,OAAO,GAAG,SAAS;CAC9C,OAAO,YAAY,SAAS,CAAC,WAAW,GAAG,WAAW,IAAI,CAAC,GAAG,aAAa;CAC3E,OAAO,QAAQ,KAAK,KAAK,CAAC,GAAG,IAAI;CAGjC,MAAM,MAA0B,CAAC,GADjB,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,UAAU,QAAQ,EAAE,EAAE,IAAI,UAAU,QAAQ,EAAE,EAAE,CAC3D,GAAG,IAAI,QAAQ,OAAO,CAAC,EAAA,CAAG,QAAO,YAAW,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC;CAE/G,MAAM,0BAAU,IAAI,IAAuB;CAC3C,IAAI,QAAQ;CACZ,SAAS;EACP,MAAM,MAAM,IAAI,IAAI,MAAM,KAAI,YAAW,QAAQ,EAAE,CAAC;EACpD,MAAM,0BAAU,IAAI,IAAuB;EAC3C,KAAK,MAAM,WAAW,OAAO;GAC3B,MAAM,SAAS,MAAM,SAAS,KAAK,OAAO;GAC1C,IAAI,QAAQ,QAAQ,IAAI,QAAQ,IAAI,MAAM;EAC5C;EACA,IAAI,CAAC,QAAQ,MAAM;EACnB,KAAK,MAAM,CAAC,IAAI,WAAW,SAAS,QAAQ,IAAI,IAAI,MAAM;EAC1D,QAAQ,MAAM,QAAO,YAAW,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;CAC1D;CAEA,MAAM,SAAS,aAAa,EAAE,UAAU,gBAAgB,KAAK,EAAE,CAAC;CAChE,MAAM,UAAU,IAAI,SAAQ,YAAW,QAAQ,IAAI,QAAQ,EAAE,IAAI,CAAC;EAAE,IAAI,QAAQ;EAAI,QAAQ,QAAQ,IAAI,QAAQ,EAAE;CAAG,CAAC,IAAI,CAAC,CAAC;CAC5H,OAAO,OAAO,OAAO;EAAE,GAAG;EAAQ,SAAS,OAAO,OAAO,OAAO;CAAE,CAAC;AACrE;;;;;;;AAQA,MAAa,qBAA4C,cAAqB,EAAE,WAAW,cAAc,GAAG;CAAE,SAAS;CAAS,aAAa;CAAW,IAAI;AAAM,CAAC"}
1
+ {"version":3,"file":"compose.js","names":[],"sources":["../../src/presets/compose.ts"],"sourcesContent":["import type { EditorBackend } from '../core/backend'\nimport { coreContentFeature, coreUiFeature } from '../core/core-feature'\nimport { defineEditor } from '../core/define-editor'\nimport type { BlockUiOptions } from '../core/extension-points'\nimport type { Dimension, EditorFeature, EditorPreset } from '../core/feature'\nimport type { CoreContentOptions } from '../core/schema'\nimport type { CommentsFeatureOptions } from '../features/comments/feature'\nimport { CommentMark } from '../features/comments/schema'\nimport type { CompositeFeatureOptions } from '../features/composites/feature'\nimport type { Basket } from '../features/composites/baskets'\nimport type { CompositeKind } from '../features/composites/kinds'\nimport { mentionsFeature } from '../features/mentions'\nimport type { TransferFeatureOptions } from '../features/transfer/feature'\nimport { type BlockTransform, copyTransform } from '../features/transfer/transforms'\nimport { tablesFeature } from '../features/tables'\nimport { compositeMediaFeature } from '../integrations/composite-media'\n\n/** The id of a catalog feature (`CONTENT`, `INTERACTION`, `AI`) or of a host feature passed to `remove`. */\nexport type FeatureId = string\n\n/** How much document model the editor has: `basic` = `core-content`, `rich` = the full content catalog. */\nexport type ContentLevel = 'basic' | 'rich'\n\n/** How much editing UX the editor has: `minimal` = `core-ui`, `full` = every interaction feature. */\nexport type InteractionLevel = 'minimal' | 'full'\n\n/**\n * The features a UI layer binds, keyed by id; the other catalog features are framework-free and built here. The AI\n * features are bound too, although `composite-ai` and `transcript-ai` have no components: the layer owns every import of\n * `features/ai`, so a composition without `ai` binds none of them and its bundle holds no AI code. Each binding is a\n * factory, called only for a feature the composition selects (`themes` reads the current Vue app when built, so\n * unselected features are never built). `composites` receives the composition's `compositeKinds` and `compositeBaskets`, `comments` its\n * `comments` options. `core-ui` takes no parameter here: the framework-free `simpleEditor()` has no command palette;\n * a layer that has one (the `SimpleEditor` surfaces) builds `coreUiFeature({ palette })` itself.\n */\nexport interface UiBindings<C> {\n 'core-ui': () => EditorFeature<C>\n 'media': () => EditorFeature<C>\n 'transcript': () => EditorFeature<C>\n 'composites': (options: CompositeFeatureOptions) => EditorFeature<C>\n 'authors': () => EditorFeature<C>\n 'comments': (options: CommentsFeatureOptions) => EditorFeature<C>\n 'ai': () => EditorFeature<C>\n 'composite-ai': () => EditorFeature<C>\n 'transcript-ai': () => EditorFeature<C>\n 'collab': () => EditorFeature<C>\n 'block-ui': (options: BlockUiOptions) => EditorFeature<C>\n 'themes': () => EditorFeature<C>\n 'transfer': (options: TransferFeatureOptions) => EditorFeature<C>\n /** The AI transforms of the transfer menu (`summaryTransform`, `bulletsTransform` of `integrations/composite-ai`); called only when `ai` is on and the host passes no `transfer.transforms`. */\n 'transfer-ai': () => readonly BlockTransform[]\n}\n\n/** What `composeEditor` builds the editor from. */\nexport interface ComposeOptions<C> {\n /** The document model: a level or the content feature ids to install (`core-content` is always installed). */\n content: ContentLevel | readonly FeatureId[]\n /** The editing UX: a level or the interaction feature ids (`core-ui` is installed with any non-empty list); `[]` = a viewer without any interaction feature. */\n interaction: InteractionLevel | readonly FeatureId[]\n /** Installs `ai` and every integration whose `requires` are met (composite-AI iff composites, transcript-AI iff transcript). */\n ai: boolean\n /** The backend the editor runs on: features needing a capability it lacks are omitted. Absent = nothing is pruned by capability. */\n backend?: EditorBackend\n /**\n * The host supplies the collaboration session itself (the surface's `collaboration` prop, e.g. from its own Hocuspocus\n * provider), so `collab` and `comments` need no `collaboration` capability from the backend. Only a backend that must\n * open the collaboration (`useEditorDocument(id, { collaboration: true })`) has to offer it. Default `false`.\n */\n collaboration?: boolean\n /** Host features, appended after the catalog in the given order. */\n add?: readonly EditorFeature<C>[]\n /** Features left out (catalog or host); features that require them are omitted as well. */\n remove?: readonly FeatureId[]\n /** The composite kinds („Bausteine“) offered in the editor (default: the built-in kinds); read once. */\n compositeKinds?: readonly CompositeKind[]\n /** The colour baskets a Baustein can be put into (default: the built-in red/orange/yellow/green/blue set); read once. */\n compositeBaskets?: readonly Basket[]\n /** Options of the comments feature, e.g. a host `model` (then comments need no `collab`). */\n comments?: CommentsFeatureOptions\n /** Optional structures the content base drops (headings or heading levels, lists, blockquote, code block, rule); everything is on by default. Applies to the editor and to the server schema built from the preset's `schemaExtensions`. */\n coreContent?: CoreContentOptions\n /** Options of the block UI (`block-ui`, `interaction: 'full'`): which surfaces render block actions (hover bar, selected-block toolbar, both, none); the hover bar by default. */\n blockUi?: BlockUiOptions\n /** Options of the transfer feature (`interaction: [..., 'transfer']`; in no level list): the transforms a drop offers (default: the copy, plus the AI transforms when `ai` is on) and the default one. */\n transfer?: TransferFeatureOptions\n}\n\n/** The composed preset and the features that were selected but dropped, in composition order, with the reason. */\nexport interface ComposedEditor<C> extends EditorPreset<C> {\n readonly omitted: readonly { id: FeatureId, reason: string }[]\n}\n\nfunction fail(message: string): never {\n throw new Error(`@ecsplico/editor: composeEditor: ${message}`)\n}\n\n/** The binding `key` of `ui`; a framework binding the composition needs but `ui` lacks fails here, naming it. */\nfunction bound<C, K extends keyof UiBindings<C>>(ui: Partial<UiBindings<C>>, key: K): UiBindings<C>[K] {\n return ui[key] ?? fail(`no UI binding for feature \"${key}\"`)\n}\n\n/** One row of the catalog: where the feature sits, which level lists hold it, and how it is built from the options. */\ninterface CatalogEntry<C> {\n dimension: Dimension\n /** The level lists (`CONTENT`, `INTERACTION`) that include it; none for AI features, which `ai: true` installs. */\n levels?: readonly (ContentLevel | InteractionLevel)[]\n /** `ui` is partial on purpose: a host that never selects a feature (a viewer has no `block-ui`) binds only the rest, so the bundle holds no code of the others. */\n build: (ui: Partial<UiBindings<C>>, options: ComposeOptions<C>) => EditorFeature<C>\n}\n\n/**\n * The catalog: the one table that drives composition. Its key order is the canonical order (content, interaction, AI):\n * the composed feature list, its schema order and its toolbar order follow it, and `CONTENT`, `INTERACTION`, `AI` are\n * derived from it. Adding a catalog feature is one row here, plus, for a UI-bound feature, a key in `UiBindings` and an\n * entry in both binding records (`vue/compose.ts`, `react/compose.ts`; their `satisfies UiBindings` check fails until\n * they hold it). Framework-free features are called directly, UI-bound ones go through `bound`.\n */\n// `any`: the table is module-level and shared by every UI layer; each `build` is typed by `UiBindings<C>` of its caller.\nconst CATALOG: Record<FeatureId, CatalogEntry<any>> = {\n 'core-content': { dimension: 'content', levels: ['basic', 'rich'], build: (_, options) => coreContentFeature(options.coreContent) },\n 'media': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'media')() },\n 'transcript': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'transcript')() },\n 'composites': { dimension: 'content', levels: ['rich'], build: (ui, options) => bound(ui, 'composites')({ ...(options.compositeKinds && { kinds: options.compositeKinds }), ...(options.compositeBaskets && { baskets: options.compositeBaskets }) }) },\n 'mentions': { dimension: 'content', levels: ['rich'], build: () => mentionsFeature() },\n 'authors': { dimension: 'content', levels: ['rich'], build: ui => bound(ui, 'authors')() },\n 'tables': { dimension: 'content', levels: ['rich'], build: () => tablesFeature() },\n 'composite-media': { dimension: 'content', levels: ['rich'], build: () => compositeMediaFeature() },\n 'core-ui': { dimension: 'interaction', levels: ['minimal', 'full'], build: ui => bound(ui, 'core-ui')() },\n 'collab': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'collab')() },\n 'comments': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'comments')(options.comments ?? {}) },\n 'block-ui': { dimension: 'interaction', levels: ['full'], build: (ui, options) => bound(ui, 'block-ui')(options.blockUi ?? {}) },\n 'themes': { dimension: 'interaction', levels: ['full'], build: ui => bound(ui, 'themes')() },\n // In no level list: a host opts in with `interaction: [...INTERACTION.full, 'transfer']`. With `ai` on the menu also offers the AI transforms (bound by the layer, which owns every import of `features/ai`), unless the host passes its own `transfer.transforms`.\n 'transfer': { dimension: 'interaction', build: (ui, options) => bound(ui, 'transfer')({ ...options.transfer, ...(!options.transfer?.transforms && options.ai && { transforms: [copyTransform, ...bound(ui, 'transfer-ai')()] }) }) },\n 'ai': { dimension: 'ai', build: ui => bound(ui, 'ai')() },\n 'composite-ai': { dimension: 'ai', build: ui => bound(ui, 'composite-ai')() },\n 'transcript-ai': { dimension: 'ai', build: ui => bound(ui, 'transcript-ai')() },\n}\n\nconst catalogIds = (include: (entry: CatalogEntry<unknown>) => boolean): readonly FeatureId[] =>\n Object.entries(CATALOG).filter(([, entry]) => include(entry)).map(([id]) => id)\nconst levelIds = (level: ContentLevel | InteractionLevel) => catalogIds(entry => entry.levels?.includes(level) ?? false)\n\n/** The content features of each level, in canonical (schema) order. */\nexport const CONTENT: Record<ContentLevel, readonly FeatureId[]> = { basic: levelIds('basic'), rich: levelIds('rich') }\n\n/** The interaction features of each level, in canonical order. */\nexport const INTERACTION: Record<InteractionLevel, readonly FeatureId[]> = { minimal: levelIds('minimal'), full: levelIds('full') }\n\n/** The AI features (`ai: true`): the AI feature and the integrations that need it; each is installed when its `requires` are met. */\nexport const AI: readonly FeatureId[] = catalogIds(entry => entry.dimension === 'ai')\n\n/** Canonical feature order: the key order of the catalog (content, interaction, AI). */\nconst CANONICAL: readonly FeatureId[] = Object.keys(CATALOG)\n\n/** Builds the catalog feature `id`; an id outside the catalog or a missing binding fails, naming it. */\nfunction build<C>(id: FeatureId, ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): EditorFeature<C> {\n const entry = Object.hasOwn(CATALOG, id) ? CATALOG[id] : undefined\n if (!entry) fail(`unknown catalog feature \"${id}\" (host features go in \\`add\\`)`)\n return entry.build(ui, options)\n}\n\n/** Why `feature` cannot stay in a composition holding `ids` over `backend`, or `undefined`. A host session satisfies `collaboration`. */\nfunction unmet(feature: Pick<EditorFeature, 'backend' | 'requires'>, ids: ReadonlySet<FeatureId>, options: Pick<ComposeOptions<unknown>, 'backend' | 'collaboration'>): string | undefined {\n const { backend } = options\n for (const capability of feature.backend ?? []) {\n if (capability === 'collaboration' && options.collaboration) continue\n if (backend && backend[capability] === undefined) return `backend \"${backend.name}\" lacks \"${capability}\"`\n }\n for (const required of feature.requires ?? []) {\n if (!ids.has(required)) return `requires \"${required}\"`\n }\n return undefined\n}\n\n/**\n * The comment mark is part of the document model (stored documents carry it), but only the `comments` feature brings it.\n * A composition that keeps `authors` (every rich one) yet has no `comments` (a viewer, a backend without collaboration,\n * `remove`) gets the mark through `authors`, inert there, so such documents still load. The catalog is the one place\n * that may couple the two features; each stays importable on its own.\n */\nfunction withCommentMark<C>(features: readonly EditorFeature<C>[]): EditorFeature<C>[] {\n if (features.some(feature => feature.id === 'comments')) return [...features]\n return features.map(feature => feature.id !== 'authors'\n ? feature\n : {\n ...feature,\n schemaExtensions: () => [...(feature.schemaExtensions?.() ?? []), CommentMark],\n extensions: ctx => [...(feature.extensions?.(ctx) ?? []), CommentMark],\n })\n}\n\n/**\n * Composes an editor from three dimensions plus the backend's capabilities, over the UI bindings of a layer.\n *\n * The feature list is `content` + `interaction` (+ the AI features when `ai`) + `add`, minus `remove`. `core-content` is\n * always part of it and `core-ui` of every non-empty interaction list. Features that require a missing feature, or a\n * backend capability `options.backend` lacks, are dropped until the list is stable and reported in `omitted` (so\n * `ai: true` over a backend without `ai` installs no AI and says why). The catalog features keep their canonical order\n * (content, interaction, AI), host features follow in the order given; the result is validated by `defineEditor`.\n * Throws when an id of `content` is not a content feature, an id of `interaction` not an interaction feature, an id\n * names no catalog feature, `remove` names `core-content`, or a selected feature has no binding in `ui`.\n */\nexport function composeEditor<C>(ui: Partial<UiBindings<C>>, options: ComposeOptions<C>): ComposedEditor<C> {\n if (options.remove?.includes('core-content')) fail('\"core-content\" cannot be removed')\n const removed = new Set(options.remove ?? [])\n const catalog = new Map<FeatureId, EditorFeature<C>>()\n const select = (ids: readonly FeatureId[], dimension: 'content' | 'interaction' | 'ai') => {\n for (const id of ids) {\n if (removed.has(id) || catalog.has(id)) continue\n const feature = build(id, ui, options)\n if (feature.dimension !== dimension) fail(`\"${id}\" is not ${dimension === 'ai' ? 'an AI' : `a${dimension === 'interaction' ? 'n' : ''} ${dimension}`} feature`)\n catalog.set(id, feature)\n }\n }\n const content = typeof options.content === 'string' ? CONTENT[options.content] : options.content\n const interaction = typeof options.interaction === 'string' ? INTERACTION[options.interaction] : options.interaction\n select(['core-content', ...content], 'content')\n select(interaction.length ? ['core-ui', ...interaction] : [], 'interaction')\n select(options.ai ? AI : [], 'ai')\n\n const ordered = [...catalog.values()].sort((a, b) => CANONICAL.indexOf(a.id) - CANONICAL.indexOf(b.id))\n const all: EditorFeature<C>[] = [...ordered, ...(options.add ?? []).filter(feature => !removed.has(feature.id))]\n\n const reasons = new Map<FeatureId, string>()\n let alive = all\n for (;;) {\n const ids = new Set(alive.map(feature => feature.id))\n const dropped = new Map<FeatureId, string>()\n for (const feature of alive) {\n const reason = unmet(feature, ids, options)\n if (reason) dropped.set(feature.id, reason)\n }\n if (!dropped.size) break\n for (const [id, reason] of dropped) reasons.set(id, reason)\n alive = alive.filter(feature => !dropped.has(feature.id))\n }\n\n const preset = defineEditor({ features: withCommentMark(alive) })\n const omitted = all.flatMap(feature => reasons.has(feature.id) ? [{ id: feature.id, reason: reasons.get(feature.id)! }] : [])\n return Object.freeze({ ...preset, omitted: Object.freeze(omitted) })\n}\n\n/**\n * The simple editor: `core-content` and `core-ui` (formatting, headings, lists, quotes, code, undo/redo). No backend, no AI,\n * no collaboration, and no ⌘K command palette (`coreUiFeature()` gets no `palette` component here, the framework-free\n * layer has none; the `SimpleEditor` components and the `composeEditor` of `/vue/advanced` and `/react/advanced` bind it).\n * Component-free (`ComposedEditor<never>`), so both the Vue and the React surface accept it.\n */\nexport const simpleEditor = (): ComposedEditor<never> => composeEditor<never>({ 'core-ui': coreUiFeature }, { content: 'basic', interaction: 'minimal', ai: false })\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { coreUiFeature } from "../core/core-feature.js";
2
+ import { composeEditor as composeEditor$1 } from "../presets/compose.js";
2
3
  import { EditorCommandPalette } from "./EditorCommandPalette.js";
3
4
  import { aiFeature } from "../features/ai/react.js";
4
5
  import { authorsFeature } from "../features/authors/react.js";
@@ -8,10 +9,11 @@ import { commentsFeature } from "../features/comments/react.js";
8
9
  import { compositeFeature } from "../features/composites/react.js";
9
10
  import { mediaFeature } from "../features/media/react.js";
10
11
  import { themesFeature } from "../features/themes/react.js";
12
+ import { transferFeature } from "../features/transfer/react.js";
11
13
  import { transcriptFeature } from "../features/transcript/react.js";
14
+ import { bulletsTransform, summaryTransform } from "../integrations/composite-ai/transfer-transforms.js";
12
15
  import { compositeAiFeature } from "../integrations/composite-ai/index.js";
13
16
  import { transcriptAiFeature } from "../integrations/transcript-ai/index.js";
14
- import { composeEditor as composeEditor$1 } from "../presets/compose.js";
15
17
  //#region src/react/compose.ts
16
18
  /** The React bindings of every UI-bound catalog feature. */
17
19
  const REACT_BINDINGS = {
@@ -26,7 +28,9 @@ const REACT_BINDINGS = {
26
28
  "transcript-ai": transcriptAiFeature,
27
29
  "collab": collabFeature,
28
30
  "block-ui": blockUiFeature,
29
- "themes": themesFeature
31
+ "themes": themesFeature,
32
+ "transfer": transferFeature,
33
+ "transfer-ai": () => [summaryTransform, bulletsTransform]
30
34
  };
31
35
  /**
32
36
  * `composeEditor` of `presets/compose` over the React bindings: the editor of the three dimensions (`content`,