@ecsplico/editor 3.6.0 → 4.1.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 (593) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/dist/adapters/direct-ai.d.ts +4 -4
  3. package/dist/adapters/direct-ai.js +2 -2
  4. package/dist/adapters/direct-ai.js.map +1 -1
  5. package/dist/adapters/document-state.d.ts +1 -1
  6. package/dist/adapters/document-state.js.map +1 -1
  7. package/dist/adapters/forge.d.ts +2 -2
  8. package/dist/adapters/forge.js.map +1 -1
  9. package/dist/adapters/nitro.d.ts +11 -3
  10. package/dist/adapters/nitro.js +3 -1
  11. package/dist/adapters/nitro.js.map +1 -1
  12. package/dist/adapters/shared.d.ts +6 -6
  13. package/dist/adapters/shared.js.map +1 -1
  14. package/dist/code/CodeSurface.vue.d.ts +3 -3
  15. package/dist/config/index.d.ts +14 -14
  16. package/dist/config/index.js +8 -8
  17. package/dist/config/index.js.map +1 -1
  18. package/dist/core/backend-types.d.ts +3 -3
  19. package/dist/core/backend-types.js.map +1 -1
  20. package/dist/core/backend.d.ts +4 -4
  21. package/dist/core/backend.js.map +1 -1
  22. package/dist/core/block-convert.d.ts +1 -1
  23. package/dist/core/block-convert.js +5 -5
  24. package/dist/core/block-convert.js.map +1 -1
  25. package/dist/core/block-transfer.d.ts +8 -4
  26. package/dist/core/block-transfer.js +23 -14
  27. package/dist/core/block-transfer.js.map +1 -1
  28. package/dist/core/capabilities.d.ts +113 -0
  29. package/dist/core/capabilities.js +155 -0
  30. package/dist/core/capabilities.js.map +1 -0
  31. package/dist/core/command-types.d.ts +1 -1
  32. package/dist/core/context.js.map +1 -1
  33. package/dist/core/convert.d.ts +5 -5
  34. package/dist/core/convert.js +5 -5
  35. package/dist/core/convert.js.map +1 -1
  36. package/dist/core/core-feature.js +1 -1
  37. package/dist/core/define-editor.d.ts +2 -2
  38. package/dist/core/define-editor.js +34 -6
  39. package/dist/core/define-editor.js.map +1 -1
  40. package/dist/core/derivation.d.ts +119 -0
  41. package/dist/core/derivation.js +187 -0
  42. package/dist/core/derivation.js.map +1 -0
  43. package/dist/core/derive.d.ts +61 -0
  44. package/dist/core/derive.js +69 -0
  45. package/dist/core/derive.js.map +1 -0
  46. package/dist/core/extension-points.d.ts +16 -0
  47. package/dist/core/feature-context.d.ts +5 -1
  48. package/dist/core/feature-context.js +10 -3
  49. package/dist/core/feature-context.js.map +1 -1
  50. package/dist/core/feature.d.ts +41 -19
  51. package/dist/core/feature.js.map +1 -1
  52. package/dist/core/fences.js +1 -1
  53. package/dist/core/fences.js.map +1 -1
  54. package/dist/core/index.d.ts +6 -2
  55. package/dist/core/index.js +5 -1
  56. package/dist/core/pipeline.d.ts +14 -5
  57. package/dist/core/pipeline.js +19 -7
  58. package/dist/core/pipeline.js.map +1 -1
  59. package/dist/core/properties.d.ts +22 -0
  60. package/dist/core/properties.js +17 -0
  61. package/dist/core/properties.js.map +1 -0
  62. package/dist/core/schema/block-ids.js +5 -5
  63. package/dist/core/schema/block-ids.js.map +1 -1
  64. package/dist/core/schema/index.d.ts +2 -1
  65. package/dist/core/schema/index.js +2 -1
  66. package/dist/core/schema/index.js.map +1 -1
  67. package/dist/core/schema/opaque-fence.d.ts +4 -4
  68. package/dist/core/schema/opaque-fence.js +7 -7
  69. package/dist/core/schema/opaque-fence.js.map +1 -1
  70. package/dist/core/schema/persisted-names.d.ts +58 -0
  71. package/dist/core/schema/persisted-names.js +96 -0
  72. package/dist/core/schema/persisted-names.js.map +1 -0
  73. package/dist/core/toolbar-items.js +1 -1
  74. package/dist/core/toolbar-items.js.map +1 -1
  75. package/dist/core/util.js +5 -1
  76. package/dist/core/util.js.map +1 -1
  77. package/dist/document/DocumentSurface.vue.d.ts +3 -3
  78. package/dist/features/ai/agent-ops.js +1 -1
  79. package/dist/features/ai/ai-review.js +1 -1
  80. package/dist/features/ai/assistant.d.ts +4 -4
  81. package/dist/features/ai/assistant.js +1 -1
  82. package/dist/features/ai/assistant.js.map +1 -1
  83. package/dist/features/ai/components/AiSelectionMenu.js +1 -1
  84. package/dist/features/ai/components/AiSelectionMenu.js.map +1 -1
  85. package/dist/features/ai/components/ModelQuickSwitch.js +7 -7
  86. package/dist/features/ai/components/ModelQuickSwitch.js.map +1 -1
  87. package/dist/features/ai/components/ModelQuickSwitch.vue.d.ts +4 -4
  88. package/dist/features/ai/components/SettingsAiTab.js +8 -8
  89. package/dist/features/ai/components/SettingsAiTab.js.map +1 -1
  90. package/dist/features/ai/components/SettingsModelProfiles.js +1 -1
  91. package/dist/features/ai/components/SettingsModelProfiles.js.map +1 -1
  92. package/dist/features/ai/document-chat-model.d.ts +2 -2
  93. package/dist/features/ai/document-chat-model.js +5 -5
  94. package/dist/features/ai/document-chat-model.js.map +1 -1
  95. package/dist/features/ai/document-chat.js +2 -2
  96. package/dist/features/ai/document-chat.js.map +1 -1
  97. package/dist/features/ai/feature.d.ts +2 -2
  98. package/dist/features/ai/feature.js +2 -2
  99. package/dist/features/ai/feature.js.map +1 -1
  100. package/dist/features/ai/ghost-autocomplete.d.ts +4 -4
  101. package/dist/features/ai/ghost-autocomplete.js +1 -1
  102. package/dist/features/ai/ghost-autocomplete.js.map +1 -1
  103. package/dist/features/ai/index.d.ts +3 -3
  104. package/dist/features/ai/index.js +2 -2
  105. package/dist/features/ai/model-profiles.d.ts +9 -9
  106. package/dist/features/ai/model-profiles.js +13 -13
  107. package/dist/features/ai/model-profiles.js.map +1 -1
  108. package/dist/features/ai/protocol/agent-ops.d.ts +2 -2
  109. package/dist/features/ai/protocol/agent-ops.js +1 -1
  110. package/dist/features/ai/protocol/agent-ops.js.map +1 -1
  111. package/dist/features/ai/protocol/block-lines.d.ts +7 -7
  112. package/dist/features/ai/protocol/block-lines.js +10 -10
  113. package/dist/features/ai/protocol/block-lines.js.map +1 -1
  114. package/dist/features/ai/protocol/chat.d.ts +5 -5
  115. package/dist/features/ai/protocol/chat.js +12 -12
  116. package/dist/features/ai/protocol/chat.js.map +1 -1
  117. package/dist/features/ai/protocol/generate.d.ts +1 -1
  118. package/dist/features/ai/protocol/generate.js +1 -1
  119. package/dist/features/ai/protocol/generate.js.map +1 -1
  120. package/dist/features/ai/protocol/index.d.ts +3 -3
  121. package/dist/features/ai/protocol/index.js +2 -2
  122. package/dist/features/ai/protocol/models.d.ts +3 -3
  123. package/dist/features/ai/protocol/models.js +3 -3
  124. package/dist/features/ai/protocol/models.js.map +1 -1
  125. package/dist/features/ai/protocol/schemas.d.ts +1 -1
  126. package/dist/features/ai/protocol/schemas.js +1 -1
  127. package/dist/features/ai/protocol/schemas.js.map +1 -1
  128. package/dist/features/ai/protocol/tasks.d.ts +5 -5
  129. package/dist/features/ai/protocol/tasks.js +12 -12
  130. package/dist/features/ai/protocol/tasks.js.map +1 -1
  131. package/dist/features/ai/react/AiSelectionMenu.js.map +1 -1
  132. package/dist/features/ai/react/ModelQuickSwitch.d.ts +4 -4
  133. package/dist/features/ai/react/ModelQuickSwitch.js +6 -6
  134. package/dist/features/ai/react/ModelQuickSwitch.js.map +1 -1
  135. package/dist/features/ai/react/SettingsAiTab.d.ts +1 -1
  136. package/dist/features/ai/react/SettingsAiTab.js +8 -8
  137. package/dist/features/ai/react/SettingsAiTab.js.map +1 -1
  138. package/dist/features/ai/react/SettingsModelProfiles.d.ts +1 -1
  139. package/dist/features/ai/react/SettingsModelProfiles.js +1 -1
  140. package/dist/features/ai/react/SettingsModelProfiles.js.map +1 -1
  141. package/dist/features/ai/react/use-ai-assistant.d.ts +1 -1
  142. package/dist/features/ai/react/use-ai-assistant.js +1 -1
  143. package/dist/features/ai/react/use-ai-assistant.js.map +1 -1
  144. package/dist/features/ai/react/use-model-profiles.d.ts +5 -5
  145. package/dist/features/ai/react/use-model-profiles.js +2 -2
  146. package/dist/features/ai/react/use-model-profiles.js.map +1 -1
  147. package/dist/features/ai/use-ai-assistant.d.ts +1 -1
  148. package/dist/features/ai/use-ai-assistant.js +1 -1
  149. package/dist/features/ai/use-ai-assistant.js.map +1 -1
  150. package/dist/features/ai/use-model-profiles.d.ts +4 -4
  151. package/dist/features/ai/use-model-profiles.js +2 -2
  152. package/dist/features/ai/use-model-profiles.js.map +1 -1
  153. package/dist/features/block-ui/block-actions.d.ts +8 -4
  154. package/dist/features/block-ui/block-actions.js +38 -22
  155. package/dist/features/block-ui/block-actions.js.map +1 -1
  156. package/dist/features/block-ui/block-target.d.ts +29 -0
  157. package/dist/features/block-ui/block-target.js +63 -0
  158. package/dist/features/block-ui/block-target.js.map +1 -0
  159. package/dist/features/block-ui/components/BlockHandles.js +3 -3
  160. package/dist/features/block-ui/components/BlockHandles.js.map +1 -1
  161. package/dist/features/block-ui/components/BlockUi.js +11 -23
  162. package/dist/features/block-ui/components/BlockUi.js.map +1 -1
  163. package/dist/features/block-ui/feature.d.ts +3 -2
  164. package/dist/features/block-ui/feature.js +3 -2
  165. package/dist/features/block-ui/feature.js.map +1 -1
  166. package/dist/features/block-ui/handle-geometry.js +12 -23
  167. package/dist/features/block-ui/handle-geometry.js.map +1 -1
  168. package/dist/features/block-ui/index.d.ts +2 -1
  169. package/dist/features/block-ui/index.js +2 -1
  170. package/dist/features/block-ui/react/BlockHandles.d.ts +1 -1
  171. package/dist/features/block-ui/react/BlockHandles.js +4 -4
  172. package/dist/features/block-ui/react/BlockHandles.js.map +1 -1
  173. package/dist/features/block-ui/react/BlockUi.js +13 -25
  174. package/dist/features/block-ui/react/BlockUi.js.map +1 -1
  175. package/dist/features/comments/model.js +1 -1
  176. package/dist/features/composites/accepted-children.d.ts +5 -4
  177. package/dist/features/composites/accepted-children.js +26 -26
  178. package/dist/features/composites/accepted-children.js.map +1 -1
  179. package/dist/features/composites/ai-brief.d.ts +4 -4
  180. package/dist/features/composites/ai-brief.js +14 -12
  181. package/dist/features/composites/ai-brief.js.map +1 -1
  182. package/dist/features/composites/anchors.d.ts +1 -1
  183. package/dist/features/composites/anchors.js.map +1 -1
  184. package/dist/features/composites/baskets.d.ts +1 -1
  185. package/dist/features/composites/baskets.js.map +1 -1
  186. package/dist/features/composites/bibliography-command.d.ts +1 -1
  187. package/dist/features/composites/bibliography-form.js +1 -1
  188. package/dist/features/composites/bibliography-form.js.map +1 -1
  189. package/dist/features/composites/bibliography.js.map +1 -1
  190. package/dist/features/composites/block-types-json.d.ts +38 -0
  191. package/dist/features/composites/block-types-json.js +122 -0
  192. package/dist/features/composites/block-types-json.js.map +1 -0
  193. package/dist/features/composites/block-types.d.ts +119 -0
  194. package/dist/features/composites/block-types.js +343 -0
  195. package/dist/features/composites/block-types.js.map +1 -0
  196. package/dist/features/composites/capabilities.js +109 -0
  197. package/dist/features/composites/capabilities.js.map +1 -0
  198. package/dist/features/composites/components/BibliographyEditor.js +5 -5
  199. package/dist/features/composites/components/BibliographyEditor.js.map +1 -1
  200. package/dist/features/composites/components/CompositeBasketMenu.js +2 -2
  201. package/dist/features/composites/components/CompositeBasketMenu.js.map +1 -1
  202. package/dist/features/composites/components/CompositeChrome.js +18 -8
  203. package/dist/features/composites/components/CompositeChrome.js.map +1 -1
  204. package/dist/features/composites/components/CompositeChrome.vue.d.ts +1 -1
  205. package/dist/features/composites/components/CompositeDetails.js +11 -10
  206. package/dist/features/composites/components/CompositeDetails.js.map +1 -1
  207. package/dist/features/composites/components/CompositeDetails.vue.d.ts +1 -1
  208. package/dist/features/composites/components/CompositeFieldEditor.js +7 -7
  209. package/dist/features/composites/components/CompositeFieldEditor.js.map +1 -1
  210. package/dist/features/composites/components/CompositeFieldEditor.vue.d.ts +5 -5
  211. package/dist/features/composites/components/CompositeInspector.js +136 -113
  212. package/dist/features/composites/components/CompositeInspector.js.map +1 -1
  213. package/dist/features/composites/components/CompositeInspector.vue.d.ts +3 -3
  214. package/dist/features/composites/components/CompositeStatusMenu.js +2 -2
  215. package/dist/features/composites/components/CompositeStatusMenu.js.map +1 -1
  216. package/dist/features/composites/components/CompositeSummaryEditor.js +1 -1
  217. package/dist/features/composites/components/CompositeSummaryEditor.js.map +1 -1
  218. package/dist/features/composites/components/CompositeSummaryEditor.vue.d.ts +1 -1
  219. package/dist/features/composites/components/CompositeTable.js +2 -2
  220. package/dist/features/composites/components/CompositeTable.js.map +1 -1
  221. package/dist/features/composites/components/CompositeTagsEditor.js +1 -1
  222. package/dist/features/composites/components/CompositeTagsEditor.js.map +1 -1
  223. package/dist/features/composites/components/CompositeTagsEditor.vue.d.ts +1 -1
  224. package/dist/features/composites/components/CompositeView.js +19 -17
  225. package/dist/features/composites/components/CompositeView.js.map +1 -1
  226. package/dist/features/composites/components/DerivationBadge.js +15 -6
  227. package/dist/features/composites/components/DerivationBadge.js.map +1 -1
  228. package/dist/features/composites/components/FocusChip.js +1 -1
  229. package/dist/features/composites/components/FocusChip.js.map +1 -1
  230. package/dist/features/composites/components/FocusChip.vue.d.ts +1 -1
  231. package/dist/features/composites/components/ReferenceFieldSelect.js +3 -3
  232. package/dist/features/composites/components/ReferenceFieldSelect.js.map +1 -1
  233. package/dist/features/composites/components/ReferenceView.js +1 -1
  234. package/dist/features/composites/components/ReferenceView.js.map +1 -1
  235. package/dist/features/composites/components/SettingsEditingTab.js +18 -18
  236. package/dist/features/composites/components/SettingsEditingTab.js.map +1 -1
  237. package/dist/features/composites/components/SettingsEditingTab.vue.d.ts +3 -3
  238. package/dist/features/composites/convert.d.ts +4 -4
  239. package/dist/features/composites/convert.js +27 -28
  240. package/dist/features/composites/convert.js.map +1 -1
  241. package/dist/features/composites/derived-chrome.js +34 -28
  242. package/dist/features/composites/derived-chrome.js.map +1 -1
  243. package/dist/features/composites/editing-settings-keys.js +6 -6
  244. package/dist/features/composites/editing-settings-keys.js.map +1 -1
  245. package/dist/features/composites/feature.d.ts +10 -10
  246. package/dist/features/composites/feature.js +58 -46
  247. package/dist/features/composites/feature.js.map +1 -1
  248. package/dist/features/composites/fences.d.ts +3 -3
  249. package/dist/features/composites/fences.js +18 -13
  250. package/dist/features/composites/fences.js.map +1 -1
  251. package/dist/features/composites/focus.d.ts +10 -10
  252. package/dist/features/composites/focus.js +11 -11
  253. package/dist/features/composites/focus.js.map +1 -1
  254. package/dist/features/composites/heading-composites.d.ts +5 -5
  255. package/dist/features/composites/heading-composites.js +13 -16
  256. package/dist/features/composites/heading-composites.js.map +1 -1
  257. package/dist/features/composites/index.d.ts +20 -18
  258. package/dist/features/composites/index.js +9 -7
  259. package/dist/features/composites/inspector-model.d.ts +45 -22
  260. package/dist/features/composites/inspector-model.js +53 -14
  261. package/dist/features/composites/inspector-model.js.map +1 -1
  262. package/dist/features/composites/legacy.d.ts +5 -4
  263. package/dist/features/composites/legacy.js +16 -23
  264. package/dist/features/composites/legacy.js.map +1 -1
  265. package/dist/features/composites/markdown-export.js +3 -3
  266. package/dist/features/composites/markdown-export.js.map +1 -1
  267. package/dist/features/composites/merge.d.ts +8 -8
  268. package/dist/features/composites/merge.js +23 -22
  269. package/dist/features/composites/merge.js.map +1 -1
  270. package/dist/features/composites/meta-display.js +5 -5
  271. package/dist/features/composites/meta-display.js.map +1 -1
  272. package/dist/features/composites/meta-keys.d.ts +5 -5
  273. package/dist/features/composites/meta-keys.js +8 -8
  274. package/dist/features/composites/meta-keys.js.map +1 -1
  275. package/dist/features/composites/node-views.d.ts +3 -3
  276. package/dist/features/composites/node-views.js +2 -2
  277. package/dist/features/composites/node-views.js.map +1 -1
  278. package/dist/features/composites/nodes.d.ts +13 -13
  279. package/dist/features/composites/nodes.js +100 -77
  280. package/dist/features/composites/nodes.js.map +1 -1
  281. package/dist/features/composites/outline.d.ts +15 -12
  282. package/dist/features/composites/outline.js +24 -21
  283. package/dist/features/composites/outline.js.map +1 -1
  284. package/dist/features/composites/properties.d.ts +51 -0
  285. package/dist/features/composites/properties.js +89 -0
  286. package/dist/features/composites/properties.js.map +1 -0
  287. package/dist/features/composites/react/BibliographyEditor.js +5 -5
  288. package/dist/features/composites/react/BibliographyEditor.js.map +1 -1
  289. package/dist/features/composites/react/CompositeBasketMenu.js +2 -2
  290. package/dist/features/composites/react/CompositeBasketMenu.js.map +1 -1
  291. package/dist/features/composites/react/CompositeChrome.d.ts +1 -1
  292. package/dist/features/composites/react/CompositeChrome.js +15 -6
  293. package/dist/features/composites/react/CompositeChrome.js.map +1 -1
  294. package/dist/features/composites/react/CompositeDetails.d.ts +1 -1
  295. package/dist/features/composites/react/CompositeDetails.js +11 -10
  296. package/dist/features/composites/react/CompositeDetails.js.map +1 -1
  297. package/dist/features/composites/react/CompositeFieldEditor.d.ts +5 -5
  298. package/dist/features/composites/react/CompositeFieldEditor.js +6 -6
  299. package/dist/features/composites/react/CompositeFieldEditor.js.map +1 -1
  300. package/dist/features/composites/react/CompositeInspector.d.ts +3 -3
  301. package/dist/features/composites/react/CompositeInspector.js +142 -128
  302. package/dist/features/composites/react/CompositeInspector.js.map +1 -1
  303. package/dist/features/composites/react/CompositeStatusMenu.js +2 -2
  304. package/dist/features/composites/react/CompositeStatusMenu.js.map +1 -1
  305. package/dist/features/composites/react/CompositeSummaryEditor.d.ts +1 -1
  306. package/dist/features/composites/react/CompositeSummaryEditor.js +1 -1
  307. package/dist/features/composites/react/CompositeSummaryEditor.js.map +1 -1
  308. package/dist/features/composites/react/CompositeTable.d.ts +1 -1
  309. package/dist/features/composites/react/CompositeTable.js +3 -3
  310. package/dist/features/composites/react/CompositeTable.js.map +1 -1
  311. package/dist/features/composites/react/CompositeTagsEditor.d.ts +1 -1
  312. package/dist/features/composites/react/CompositeTagsEditor.js +1 -1
  313. package/dist/features/composites/react/CompositeTagsEditor.js.map +1 -1
  314. package/dist/features/composites/react/CompositeView.js +17 -15
  315. package/dist/features/composites/react/CompositeView.js.map +1 -1
  316. package/dist/features/composites/react/DerivationBadge.js +13 -4
  317. package/dist/features/composites/react/DerivationBadge.js.map +1 -1
  318. package/dist/features/composites/react/FocusChip.d.ts +1 -1
  319. package/dist/features/composites/react/FocusChip.js +1 -1
  320. package/dist/features/composites/react/FocusChip.js.map +1 -1
  321. package/dist/features/composites/react/ReferenceFieldSelect.js +3 -3
  322. package/dist/features/composites/react/ReferenceFieldSelect.js.map +1 -1
  323. package/dist/features/composites/react/ReferenceView.d.ts +1 -1
  324. package/dist/features/composites/react/ReferenceView.js +1 -1
  325. package/dist/features/composites/react/ReferenceView.js.map +1 -1
  326. package/dist/features/composites/react/SettingsEditingTab.d.ts +4 -4
  327. package/dist/features/composites/react/SettingsEditingTab.js +20 -20
  328. package/dist/features/composites/react/SettingsEditingTab.js.map +1 -1
  329. package/dist/features/composites/react.js +1 -1
  330. package/dist/features/composites/react.js.map +1 -1
  331. package/dist/features/composites/reference-ai.js +1 -1
  332. package/dist/features/composites/reference-ai.js.map +1 -1
  333. package/dist/features/composites/reference-label.d.ts +3 -3
  334. package/dist/features/composites/reference-label.js +6 -6
  335. package/dist/features/composites/reference-label.js.map +1 -1
  336. package/dist/features/composites/reference-suggestion.d.ts +1 -1
  337. package/dist/features/composites/reference-suggestion.js +3 -3
  338. package/dist/features/composites/reference-suggestion.js.map +1 -1
  339. package/dist/features/composites/reference-text.d.ts +2 -2
  340. package/dist/features/composites/reference-text.js +4 -4
  341. package/dist/features/composites/reference-text.js.map +1 -1
  342. package/dist/features/composites/reference.d.ts +3 -3
  343. package/dist/features/composites/reference.js +1 -1
  344. package/dist/features/composites/reference.js.map +1 -1
  345. package/dist/features/composites/reveal-source.d.ts +3 -3
  346. package/dist/features/composites/reveal-source.js +6 -6
  347. package/dist/features/composites/reveal-source.js.map +1 -1
  348. package/dist/features/composites/rows-model.d.ts +2 -2
  349. package/dist/features/composites/rows-model.js +4 -3
  350. package/dist/features/composites/rows-model.js.map +1 -1
  351. package/dist/features/composites/rows.d.ts +16 -28
  352. package/dist/features/composites/rows.js +20 -54
  353. package/dist/features/composites/rows.js.map +1 -1
  354. package/dist/features/composites/schema.d.ts +12 -11
  355. package/dist/features/composites/schema.js +10 -9
  356. package/dist/features/composites/schema.js.map +1 -1
  357. package/dist/features/composites/source.d.ts +20 -0
  358. package/dist/features/composites/source.js +40 -0
  359. package/dist/features/composites/source.js.map +1 -0
  360. package/dist/features/composites/split.d.ts +11 -11
  361. package/dist/features/composites/split.js +20 -20
  362. package/dist/features/composites/split.js.map +1 -1
  363. package/dist/features/composites/structure-mode.js +3 -3
  364. package/dist/features/composites/structure-mode.js.map +1 -1
  365. package/dist/features/composites/table-model.js +2 -2
  366. package/dist/features/composites/table-model.js.map +1 -1
  367. package/dist/features/composites/use-composite-inspector.js +3 -1
  368. package/dist/features/composites/use-composite-inspector.js.map +1 -1
  369. package/dist/features/composites/use-composite-rows.d.ts +2 -2
  370. package/dist/features/composites/use-composite-rows.js.map +1 -1
  371. package/dist/features/composites/vue.js +1 -1
  372. package/dist/features/composites/vue.js.map +1 -1
  373. package/dist/features/image-studio/components/ImageStudioDialog.js +150 -87
  374. package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
  375. package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +5 -1
  376. package/dist/features/image-studio/components/ImageStudioLibraryPanel.js +186 -0
  377. package/dist/features/image-studio/components/ImageStudioLibraryPanel.js.map +1 -0
  378. package/dist/features/image-studio/components/ImageStudioLibraryTile.js +134 -0
  379. package/dist/features/image-studio/components/ImageStudioLibraryTile.js.map +1 -0
  380. package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
  381. package/dist/features/image-studio/feature.d.ts +1 -1
  382. package/dist/features/image-studio/feature.js +1 -1
  383. package/dist/features/image-studio/feature.js.map +1 -1
  384. package/dist/features/image-studio/index.d.ts +3 -2
  385. package/dist/features/image-studio/index.js +2 -2
  386. package/dist/features/image-studio/library.d.ts +35 -0
  387. package/dist/features/image-studio/node-core.d.ts +3 -3
  388. package/dist/features/image-studio/node-core.js +1 -1
  389. package/dist/features/image-studio/node-core.js.map +1 -1
  390. package/dist/features/image-studio/node-store.d.ts +1 -1
  391. package/dist/features/image-studio/node-store.js +1 -1
  392. package/dist/features/image-studio/node-store.js.map +1 -1
  393. package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
  394. package/dist/features/image-studio/react/ImageStudioDialog.js +46 -5
  395. package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
  396. package/dist/features/image-studio/react/ImageStudioLibraryPanel.js +141 -0
  397. package/dist/features/image-studio/react/ImageStudioLibraryPanel.js.map +1 -0
  398. package/dist/features/image-studio/react/ImageStudioLibraryTile.js +105 -0
  399. package/dist/features/image-studio/react/ImageStudioLibraryTile.js.map +1 -0
  400. package/dist/features/image-studio/react/ImageStudioView.js +1 -1
  401. package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
  402. package/dist/features/image-studio/react/store.d.ts +8 -3
  403. package/dist/features/image-studio/react/store.js.map +1 -1
  404. package/dist/features/image-studio/react.d.ts +4 -3
  405. package/dist/features/image-studio/react.js +3 -3
  406. package/dist/features/image-studio/react.js.map +1 -1
  407. package/dist/features/image-studio/schema.d.ts +1 -1
  408. package/dist/features/image-studio/schema.js +1 -1
  409. package/dist/features/image-studio/schema.js.map +1 -1
  410. package/dist/features/image-studio/state.d.ts +8 -3
  411. package/dist/features/image-studio/state.js +11 -3
  412. package/dist/features/image-studio/state.js.map +1 -1
  413. package/dist/features/image-studio/store.d.ts +8 -3
  414. package/dist/features/image-studio/vue.d.ts +4 -3
  415. package/dist/features/image-studio/vue.js +3 -3
  416. package/dist/features/image-studio/vue.js.map +1 -1
  417. package/dist/features/mentions/tag.js +2 -1
  418. package/dist/features/mentions/tag.js.map +1 -1
  419. package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
  420. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  421. package/dist/features/themes/feature.d.ts +1 -1
  422. package/dist/features/themes/feature.js.map +1 -1
  423. package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
  424. package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
  425. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  426. package/dist/features/themes/theme-runtime.js +1 -1
  427. package/dist/features/themes/theme-runtime.js.map +1 -1
  428. package/dist/features/transcript/TranscriptSegmentView.js +1 -1
  429. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  430. package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
  431. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  432. package/dist/features/transcript/segment-node.js.map +1 -1
  433. package/dist/features/transfer/feature.js +1 -1
  434. package/dist/features/transfer/feature.js.map +1 -1
  435. package/dist/features/transfer/transforms.d.ts +4 -4
  436. package/dist/features/transfer/transforms.js +12 -12
  437. package/dist/features/transfer/transforms.js.map +1 -1
  438. package/dist/i18n/de/ai.js +4 -4
  439. package/dist/i18n/de/ai.js.map +1 -1
  440. package/dist/i18n/de/authors.js +1 -1
  441. package/dist/i18n/de/authors.js.map +1 -1
  442. package/dist/i18n/de/comments.js +1 -1
  443. package/dist/i18n/de/comments.js.map +1 -1
  444. package/dist/i18n/de/composites.js +62 -59
  445. package/dist/i18n/de/composites.js.map +1 -1
  446. package/dist/i18n/de/image-studio.js +11 -2
  447. package/dist/i18n/de/image-studio.js.map +1 -1
  448. package/dist/i18n/de/integrations.js +20 -20
  449. package/dist/i18n/de/integrations.js.map +1 -1
  450. package/dist/i18n/de/markdown.js +1 -1
  451. package/dist/i18n/de/markdown.js.map +1 -1
  452. package/dist/i18n/de/palette.js +1 -1
  453. package/dist/i18n/de/palette.js.map +1 -1
  454. package/dist/i18n/de/themes.js +3 -3
  455. package/dist/i18n/de/themes.js.map +1 -1
  456. package/dist/i18n/de/transfer.js +2 -2
  457. package/dist/i18n/de/transfer.js.map +1 -1
  458. package/dist/i18n/de/tree.js +6 -6
  459. package/dist/i18n/de/tree.js.map +1 -1
  460. package/dist/i18n/de.d.ts +110 -98
  461. package/dist/i18n/en/ai.js +2 -2
  462. package/dist/i18n/en/ai.js.map +1 -1
  463. package/dist/i18n/en/composites.js +64 -61
  464. package/dist/i18n/en/composites.js.map +1 -1
  465. package/dist/i18n/en/image-studio.js +9 -0
  466. package/dist/i18n/en/image-studio.js.map +1 -1
  467. package/dist/i18n/en/integrations.js +9 -9
  468. package/dist/i18n/en/integrations.js.map +1 -1
  469. package/dist/i18n/en/markdown.js +1 -1
  470. package/dist/i18n/en/markdown.js.map +1 -1
  471. package/dist/i18n/en/palette.js +1 -1
  472. package/dist/i18n/en/palette.js.map +1 -1
  473. package/dist/i18n/en/themes.js +4 -4
  474. package/dist/i18n/en/themes.js.map +1 -1
  475. package/dist/i18n/en/tree.js +5 -5
  476. package/dist/i18n/en/tree.js.map +1 -1
  477. package/dist/index.d.ts +4 -1
  478. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
  479. package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
  480. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
  481. package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
  482. package/dist/integrations/composite-ai/composite-fill.js +5 -5
  483. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  484. package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
  485. package/dist/integrations/composite-ai/composite-summary.js +5 -5
  486. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  487. package/dist/integrations/composite-ai/derive.d.ts +17 -17
  488. package/dist/integrations/composite-ai/derive.js +27 -26
  489. package/dist/integrations/composite-ai/derive.js.map +1 -1
  490. package/dist/integrations/composite-ai/index.d.ts +14 -15
  491. package/dist/integrations/composite-ai/index.js +98 -77
  492. package/dist/integrations/composite-ai/index.js.map +1 -1
  493. package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
  494. package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
  495. package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
  496. package/dist/integrations/composite-ai/rendition.d.ts +9 -9
  497. package/dist/integrations/composite-ai/rendition.js +27 -27
  498. package/dist/integrations/composite-ai/rendition.js.map +1 -1
  499. package/dist/integrations/composite-ai/split.d.ts +8 -8
  500. package/dist/integrations/composite-ai/split.js +12 -12
  501. package/dist/integrations/composite-ai/split.js.map +1 -1
  502. package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
  503. package/dist/integrations/composite-ai/transfer-transforms.js +11 -11
  504. package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
  505. package/dist/integrations/composite-media/index.d.ts +4 -3
  506. package/dist/integrations/composite-media/index.js +20 -14
  507. package/dist/integrations/composite-media/index.js.map +1 -1
  508. package/dist/markdown/MarkdownSurface.vue.d.ts +7 -7
  509. package/dist/markdown/document.js +1 -1
  510. package/dist/markdown/document.js.map +1 -1
  511. package/dist/nuxt/module.d.ts +48 -24
  512. package/dist/nuxt/module.js.map +1 -1
  513. package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
  514. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  515. package/dist/presets/compose.d.ts +6 -6
  516. package/dist/presets/compose.js +7 -4
  517. package/dist/presets/compose.js.map +1 -1
  518. package/dist/react/AdvancedEditor.d.ts +2 -2
  519. package/dist/react/AdvancedEditor.js +1 -1
  520. package/dist/react/AdvancedEditor.js.map +1 -1
  521. package/dist/react/compose.d.ts +1 -1
  522. package/dist/react/compose.js +1 -1
  523. package/dist/react/compose.js.map +1 -1
  524. package/dist/react/composed-surface.d.ts +5 -5
  525. package/dist/react/composed-surface.js +2 -2
  526. package/dist/react/composed-surface.js.map +1 -1
  527. package/dist/server/ai.d.ts +7 -7
  528. package/dist/server/ai.js +1 -1
  529. package/dist/server/ai.js.map +1 -1
  530. package/dist/server/auth.d.ts +1 -1
  531. package/dist/server/collab-state.d.ts +1 -1
  532. package/dist/server/collab-state.js.map +1 -1
  533. package/dist/server/collab.d.ts +4 -4
  534. package/dist/server/collab.js +22 -17
  535. package/dist/server/collab.js.map +1 -1
  536. package/dist/server/handlers/ai.d.ts +9 -6
  537. package/dist/server/handlers/ai.js +13 -17
  538. package/dist/server/handlers/ai.js.map +1 -1
  539. package/dist/server/handlers/context.d.ts +4 -0
  540. package/dist/server/handlers/context.js.map +1 -1
  541. package/dist/server/handlers/editor.d.ts +33 -32
  542. package/dist/server/handlers/editor.js +13 -8
  543. package/dist/server/handlers/editor.js.map +1 -1
  544. package/dist/server/handlers/images.d.ts +1 -1
  545. package/dist/server/handlers/images.js +1 -1
  546. package/dist/server/handlers/images.js.map +1 -1
  547. package/dist/server/host.d.ts +4 -0
  548. package/dist/server/host.js +10 -2
  549. package/dist/server/host.js.map +1 -1
  550. package/dist/server/index.d.ts +3 -3
  551. package/dist/server/ports.d.ts +8 -8
  552. package/dist/server/ports.js.map +1 -1
  553. package/dist/settings/index.d.ts +20 -19
  554. package/dist/settings/index.js +25 -24
  555. package/dist/settings/index.js.map +1 -1
  556. package/dist/settings/migrate.d.ts +18 -0
  557. package/dist/settings/migrate.js +46 -0
  558. package/dist/settings/migrate.js.map +1 -0
  559. package/dist/settings/values.d.ts +12 -12
  560. package/dist/settings/values.js +11 -11
  561. package/dist/settings/values.js.map +1 -1
  562. package/dist/styles/composites.css +10 -10
  563. package/dist/tree/DocumentTree.js +12 -5
  564. package/dist/tree/DocumentTree.js.map +1 -1
  565. package/dist/tree/drop-rules.js +5 -5
  566. package/dist/tree/drop-rules.js.map +1 -1
  567. package/dist/tree/react/DocumentTree.js +14 -5
  568. package/dist/tree/react/DocumentTree.js.map +1 -1
  569. package/dist/tree/tree-host.js +5 -5
  570. package/dist/tree/tree-host.js.map +1 -1
  571. package/dist/tree/tree-items.js +34 -28
  572. package/dist/tree/tree-items.js.map +1 -1
  573. package/dist/tree/tree-model.js +16 -16
  574. package/dist/tree/tree-model.js.map +1 -1
  575. package/dist/tree/tree-rows.js +2 -2
  576. package/dist/tree/tree-rows.js.map +1 -1
  577. package/dist/tree/tree-view-model.d.ts +2 -2
  578. package/dist/tree/tree-view-model.js.map +1 -1
  579. package/dist/vue/AdvancedEditor.js +2 -2
  580. package/dist/vue/AdvancedEditor.js.map +1 -1
  581. package/dist/vue/AdvancedEditor.vue.d.ts +10 -10
  582. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  583. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  584. package/dist/vue/compose.d.ts +1 -1
  585. package/dist/vue/compose.js +1 -1
  586. package/dist/vue/compose.js.map +1 -1
  587. package/package.json +1 -1
  588. package/dist/features/composites/derivation.d.ts +0 -62
  589. package/dist/features/composites/derivation.js +0 -102
  590. package/dist/features/composites/derivation.js.map +0 -1
  591. package/dist/features/composites/kinds.d.ts +0 -89
  592. package/dist/features/composites/kinds.js +0 -285
  593. package/dist/features/composites/kinds.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tree-model.js","names":[],"sources":["../../src/tree/tree-model.ts"],"sourcesContent":["import type { BlockTransfer } from '../core/block-transfer'\nimport { createStore, type ReadonlyStore } from '../core/store'\nimport { type Basket, basketById, type CompositeKind, kindAccepts } from '../features/composites'\nimport type { Translate } from '../i18n'\nimport { type DropEnv, dropVerdict, type DropVerdict } from './drop-rules'\nimport { remapFolderPath } from './folder-paths'\nimport type { DocumentStore } from './store'\nimport {\n ancestorKeys,\n collectFolderPaths,\n creatableBelow,\n type DragPayload,\n dragPayloadOf,\n EMPTY_OUTLINE,\n filterKinds,\n folderNamesIn,\n isDraggable,\n joinPath,\n type Outline,\n parentPath,\n type TreeItem,\n VIRTUAL_ROOT,\n} from './tree-items'\nimport { deriveTree, filterQuery, type TreeRow, type TreeView } from './tree-rows'\nimport type { NodeFilters, TreeViewModel } from './tree-view-model'\nimport type { DocumentSummary, TreeFolder } from './types'\n\n// One framework-free model per `DocumentTree`, rendered by the Vue and the React component alike. It owns what the\n// tree remembers (open rows, kind filters, the title filter, the selection, a drag, a folder being renamed or created)\n// and checks all of it against the tree after every change of the store, the outline or the view state, so a key of\n// something that moved or vanished never lingers. It never calls the store or the editor to change something: it emits\n// `TreeCommand`s to the `execute` it was given and follows their result.\n\n/** What the model asks its host to do; the host reports whether it happened. */\nexport type TreeCommand\n = | { type: 'openDocument', id: string }\n | { type: 'createDocument', folder: string }\n | { type: 'moveDocument', id: string, folder: string }\n | { type: 'removeDocument', id: string, folder: string }\n | { type: 'createFolder', path: string }\n | { type: 'moveFolder', from: string, to: string }\n | { type: 'removeFolder', path: string }\n /** Moves the block into the Baustein `targetId` (`null` = the end of the document). */\n | { type: 'moveBlock', id: string, targetId: string | null }\n | { type: 'revealBlock', id: string | null, pos: number }\n /** Adds an Ordner-Baustein to the Baustein `targetId` (`null` = the end of the document). */\n | { type: 'createBausteinFolder', targetId: string | null }\n /** Lets the user pick files and imports them into the Baustein `targetId` (`null` = the end of the document); `false` when none were imported. */\n | { type: 'importFiles', targetId: string | null }\n | { type: 'warn', title: string, description: string }\n /** Inserts a Baustein dragged in from another surface or tree at the end of the Baustein `targetId` (`null` = the end of the document); `menu`: offer the transforms at `x`, `y` first. */\n | { type: 'transferBlock', payload: BlockTransfer, targetId: string | null, menu: boolean, x: number, y: number }\n /** Puts the editor into focus mode on the Baustein `id` (`null` = leaves focus mode); sent after the tree's own focus changed. */\n | { type: 'focusBlock', id: string | null }\n /** The Baustein `id` absorbs the Baustein that follows it (`mergeCompositeWithNext`); `false` when the editor refuses. */\n | { type: 'mergeBlock', id: string }\n\n/** Runs a command and resolves whether it happened. Never rejects: the host reports its own failures. */\nexport type TreeExecutor = (command: TreeCommand) => boolean | Promise<boolean>\n\n/** What the model needs from the open document's editor. */\nexport interface TreeEditor {\n kinds: readonly CompositeKind[]\n /** The baskets a Baustein can be put into (colour dots on the rows). */\n baskets: readonly Basket[]\n /** The outline in `structure`: Bausteine in `'composite'` structure, else the headings. Empty once the editor is gone. */\n outline: (structure: string) => Outline\n /** Whether a block may move into a Baustein, judged on the live document. */\n moveVerdict: NonNullable<DropEnv['moveVerdict']>\n /** Whether the editor takes blocks from outside: it has the transfer feature's drop target and its `transferBlock` command. */\n canTransfer: () => boolean\n /** The block id of the Baustein the editor is focused on (focus mode), `null` without focus. The model mirrors it into the tree. */\n focusedId: () => string | null\n /** Whether the Baustein `id` can absorb the Baustein that follows it, judged on the live document. */\n canMerge: (id: string) => boolean\n /** `listener` runs after the document or the editor's focus changed; returns the unsubscribe function. */\n onChange: (listener: () => void) => () => void\n}\n\n/** What the surrounding app decides: the open editor and the `blocks.structure` / `blocks.treeRoot` settings. */\nexport interface TreeContext {\n editor: TreeEditor | undefined\n structure: string\n treeRoot: string\n}\n\nexport interface TreeModelOptions {\n /** Words the menus, the drop refusals and the label of an untitled open document; the framework layer passes the context's `t`. */\n t: Translate\n store: DocumentStore\n /** The view state shared by the trees of one app: open store items and kind filters (persisted). */\n view: TreeViewModel\n execute: TreeExecutor\n context: TreeContext\n /** The folder new documents and folders go to; default the root. */\n selectedFolder?: string\n /** How long the outline waits for the document to settle before it is read again; default 150 ms. */\n outlineDebounceMs?: number\n}\n\n/** A drag in progress. */\nexport interface TreeDrag {\n source: DragPayload\n /** Key of the dragged row (`''` for a `foreign-block`, which has no row here) */\n sourceKey: string\n /** Key of the row under the pointer */\n hover: string | null\n /** What dropping on `hover` would do; `null` without a `hover` */\n verdict: DropVerdict | null\n}\n\n/** A folder being renamed. */\nexport interface TreeRename {\n /** Key of the folder's row */\n key: string\n path: string\n /** Its name when renaming started */\n base: string\n draft: string\n error: string | null\n}\n\n/** A folder being named. */\nexport interface TreeCreateFolder {\n /** Folder path the folder is created in */\n parent: string\n draft: string\n error: string | null\n}\n\n/** Everything a renderer needs. Fields below `view` are what the derived `view` was computed from and what `rowOf` reads. */\nexport interface TreeState {\n /** The loaded folder tree: `undefined` = not loaded yet, `null` = loading failed. */\n tree: TreeFolder | null | undefined\n documents: readonly DocumentSummary[]\n activeId: string | undefined\n /** The open document is the root (virtual mode) instead of the store's folders. */\n virtual: boolean\n structure: string\n kinds: readonly CompositeKind[]\n /** The open editor's baskets (colours of the row dots). */\n baskets: readonly Basket[]\n hasEditor: boolean\n outline: Outline\n nodeFilters: NodeFilters\n /** The basket ids the tree shows (`[]` = all). */\n basketFilter: readonly string[]\n /** Key of the focused row: the tree lists only its children. `null` = no focus. */\n focusKey: string | null\n expanded: readonly string[]\n collapsedOutline: readonly string[]\n /** What the title filter input holds. */\n filterText: string\n filterOverrides: Readonly<Record<string, boolean>>\n /** The folder new documents, folders and host imports go to. */\n selectedFolder: string\n /** Virtual mode: block ID of the selected Baustein that takes Bausteine; `null` = the document itself. */\n virtualTarget: string | null\n drag: TreeDrag | null\n renaming: TreeRename | null\n creatingFolder: TreeCreateFolder | null\n /** Key of the row whose deletion is running. */\n removing: string | null\n view: TreeView\n /** The unfiltered items from the top down to the focused one (the breadcrumb); empty without a focus. Derived with `view`. */\n focusPath: readonly TreeItem[]\n}\n\n/** One row of a row's menu. */\nexport interface TreeMenuEntry {\n label: string\n icon: string\n run: () => void\n}\n\n/** How a renderer draws one row. */\nexport interface TreeRowState extends TreeRow {\n /** The row's document is the open one. */\n active: boolean\n /** The row is the selected folder, or (virtual mode) the selected Baustein. */\n selected: boolean\n /** What dropping the drag on this row would do, while the pointer is over it. */\n drop: DropVerdict | null\n renaming: TreeRename | null\n removing: boolean\n /** The kinds the row's kind filter can hide below it, and the ones it hides. */\n filterKinds: readonly CompositeKind[]\n hiddenKinds: readonly string[]\n /** The row offers a kind filter. */\n showFilter: boolean\n}\n\nexport interface TreeModel {\n readonly state: ReadonlyStore<TreeState>\n /** The open editor or a setting changed. */\n setContext: (context: TreeContext) => void\n /** The host selected another folder (it controls the value). */\n setSelectedFolder: (path: string) => void\n\n // --- what is open, filtered, typed\n /** Opens or closes a row; while the title filter is set the choice is discarded when it is cleared. */\n setOpen: (key: string, open: boolean) => void\n toggle: (key: string) => void\n /** Opens the rows (also during a title filter); closed rows are left alone otherwise. */\n expand: (keys: readonly string[]) => void\n /** Filters the rows by title (case-insensitive substring); `''` clears it and restores the opened rows from before. */\n setFilterText: (text: string) => void\n setKindHidden: (key: string, kind: string, hidden: boolean) => void\n clearFilter: (key: string) => void\n clearAllFilters: () => void\n /** Shows (`shown`) or stops showing the Bausteine of the basket; no basket shown = no filter. */\n setBasketShown: (id: string, shown: boolean) => void\n clearBasketFilter: () => void\n /** Focuses a Baustein row: the tree lists only its children and the editor hides everything else. */\n focus: (key: string) => void\n /** Leaves focus mode (tree and editor). */\n defocus: () => void\n /** Whether the Baustein row can be merged with the Baustein after it (it has a block ID and the editor accepts the merge). */\n canMerge: (item: TreeItem) => boolean\n /** Merges the Baustein row with the Baustein after it: the row keeps its title, id and meta and takes over the other one's body and sub-Bausteine. */\n merge: (item: TreeItem) => void\n\n // --- rows\n /** A row was chosen (click, Enter). */\n select: (item: TreeItem) => void\n /** `select`, and a folder or the root toggles. */\n activate: (item: TreeItem) => void\n addMenu: (item: TreeItem) => TreeMenuEntry[][]\n remove: (item: TreeItem) => Promise<void>\n\n // --- drag and drop\n isDraggable: (item: TreeItem) => boolean\n /** Starts dragging `item`; returns what the drag carries, `null` when `item` cannot be dragged. */\n dragStart: (item: TreeItem) => DragPayload | null\n /** The pointer is over `item`; returns the verdict (`null` without a drag). Only an `ok` one is a drop target. */\n dragOver: (item: TreeItem) => DropVerdict | null\n /** The pointer left `item` for good (not into one of its parts). */\n dragLeave: (item: TreeItem) => void\n dragEnd: () => void\n drop: (item: TreeItem) => Promise<void>\n /**\n * A Baustein from another surface or tree (`BLOCK_MIME`) is over `item`; returns the verdict, `null` while this\n * tree's own drag is running. Only an `ok` one is a drop target.\n */\n foreignDragOver: (item: TreeItem) => DropVerdict | null\n /** Drops the foreign Baustein `payload` on `item`: inserts a copy at the end of that Baustein (`menu`: offers the transforms at `x`, `y` instead). */\n dropForeign: (item: TreeItem, payload: BlockTransfer, menu: boolean, x: number, y: number) => Promise<void>\n\n // --- renaming and creating folders\n startRename: (item: TreeItem) => void\n setRenameDraft: (text: string) => void\n cancelRename: () => void\n commitRename: () => Promise<void>\n /** The rename field lost focus: commit, or give up with a warning when the name is invalid. */\n blurRename: () => Promise<void>\n startCreateFolder: (parent: string) => void\n setFolderDraft: (text: string) => void\n cancelCreateFolder: () => void\n commitCreateFolder: () => Promise<void>\n\n dispose: () => void\n}\n\nconst NO_DOCUMENTS: readonly DocumentSummary[] = []\nconst NO_KINDS: readonly CompositeKind[] = []\nconst NO_BASKETS: readonly Basket[] = []\nconst NO_FILTERS: Readonly<Record<string, boolean>> = {}\nconst UNSET = Symbol('unset')\n\nconst isOutlineKey = (key: string) => key.startsWith('outline:')\n\n/** The state `core` holds: everything of `TreeState` but what is derived from the view. */\ntype TreeCore = Omit<TreeState, 'view' | 'focusPath'>\n\nconst withView = (c: TreeCore, view: TreeView): TreeState => ({ ...c, view, focusPath: view.focusPath })\n\nfunction sameVerdict(a: DropVerdict | null, b: DropVerdict | null): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return a.ok ? b.ok : !b.ok && a.reason === b.reason\n}\n\n/** A row's state in `state` (`item` is one of `state.view.items`). */\nexport function rowOf(state: TreeState, item: TreeItem, t: Translate): TreeRowState {\n const hidden = state.nodeFilters[item.key] ?? []\n const kinds = filterKinds(item, { structure: state.structure, activeId: state.activeId, kinds: state.kinds, t })\n const virtualTarget = state.virtual && (item.key === VIRTUAL_ROOT ? state.virtualTarget === null : !!item.blockId && item.blockId === state.virtualTarget)\n return {\n ...state.view.rows.get(item.key)!,\n active: item.id !== undefined && item.id === state.activeId,\n selected: (item.type !== 'document' && item.path === state.selectedFolder) || virtualTarget,\n drop: state.drag?.hover === item.key ? state.drag.verdict : null,\n renaming: state.renaming?.key === item.key ? state.renaming : null,\n removing: state.removing === item.key,\n filterKinds: kinds,\n hiddenKinds: hidden,\n showFilter: kinds.length > 0 && (item.type === 'root' || item.type === 'folder' || !!item.children?.length || hidden.length > 0),\n }\n}\n\n/** A tree model over `options.store`; call `dispose` when its tree goes away. */\nexport function createTreeModel(options: TreeModelOptions): TreeModel {\n const { store, view: shared, execute, t } = options\n const debounceMs = options.outlineDebounceMs ?? 150\n\n let editor = options.context.editor\n let structure = options.context.structure\n let treeRoot = options.context.treeRoot\n let unwatchEditor = editor?.onChange(onEditorChange)\n /** The focus the editor last showed that the tree took over (or already had); a change of the editor's focus is told apart from the tree's own by comparing against it. */\n let seenFocus: string | null = null\n let outlineTimer: ReturnType<typeof setTimeout> | undefined\n /** A folder move the host is running: until it is done, a selected folder at the old path follows to the new one. */\n let pendingMove: { from: string, to: string } | undefined\n let disposed = false\n\n const isVirtual = () => treeRoot === 'file' && structure === 'composite' && !!editor\n\n let core: TreeCore = {\n tree: store.tree.get(),\n documents: store.documents.get() ?? NO_DOCUMENTS,\n activeId: store.activeId.get(),\n virtual: isVirtual(),\n structure,\n kinds: editor?.kinds ?? NO_KINDS,\n baskets: editor?.baskets ?? NO_BASKETS,\n hasEditor: !!editor,\n outline: editor ? editor.outline(structure) : EMPTY_OUTLINE,\n nodeFilters: shared.nodeFilters.get(),\n basketFilter: shared.basketFilter.get(),\n focusKey: null,\n expanded: shared.expanded.get(),\n collapsedOutline: [],\n filterText: '',\n filterOverrides: NO_FILTERS,\n selectedFolder: options.selectedFolder ?? '',\n virtualTarget: null,\n drag: null,\n renaming: null,\n creatingFolder: null,\n removing: null,\n }\n let lastView: { deps: readonly unknown[], view: TreeView } | undefined\n let lastTree: TreeFolder | null | undefined | typeof UNSET = UNSET\n let folderPaths = new Set<string>()\n let lastActiveFolder: string | undefined | typeof UNSET = UNSET\n let lastActiveId: string | undefined | typeof UNSET = UNSET\n\n const dropEnv = (): DropEnv => ({ virtual: core.virtual, moveVerdict: editor?.moveVerdict, canTransfer: editor?.canTransfer() ?? false, t })\n\n function viewOf(c: TreeCore): TreeView {\n const deps = [c.tree, c.documents, c.activeId, c.virtual, c.outline, c.kinds, c.nodeFilters, c.basketFilter, c.baskets, c.focusKey, c.expanded, c.collapsedOutline, c.filterText, c.filterOverrides]\n if (lastView && deps.every((dep, i) => Object.is(dep, lastView!.deps[i]))) return lastView.view\n // A basket the open editor does not offer cannot be unchecked in the filter menu, so it never filters.\n const basketFilter = c.basketFilter.filter(id => basketById(c.baskets, id) !== undefined)\n const view = deriveTree({ ...c, basketFilter, t, select: selectItem })\n lastView = { deps, view }\n return view\n }\n\n const renameError = (draft: string, path: string, base: string, tree: TreeFolder | null | undefined) =>\n draft.trim() === base ? null : store.validateName(draft, folderNamesIn(tree, parentPath(path), path))\n const folderError = (draft: string, parent: string, tree: TreeFolder | null | undefined) =>\n draft.trim() ? store.validateName(draft, folderNamesIn(tree, parent)) : null\n\n /** Measures everything the tree remembers against the current tree: what is gone is dropped, what depends on the tree is recomputed. */\n function reconcile(c: TreeCore, view: TreeView): TreeCore {\n let next = c\n if (c.tree !== lastTree) {\n lastTree = c.tree\n folderPaths = new Set<string>()\n if (c.tree) collectFolderPaths(c.tree, folderPaths)\n if (c.tree && !folderPaths.has(next.selectedFolder)) {\n const followed = pendingMove ? remapFolderPath(next.selectedFolder, pendingMove.from, pendingMove.to) : ''\n next = { ...next, selectedFolder: folderPaths.has(followed) ? followed : '' }\n }\n }\n if (next.virtualTarget !== null && (!next.virtual || !view.keys.has(`outline:${next.virtualTarget}`))) next = { ...next, virtualTarget: null }\n if (next.focusKey !== null && !view.keys.has(next.focusKey)) next = { ...next, focusKey: null }\n if (next.renaming) {\n const r = next.renaming\n if (!view.keys.has(r.key)) next = { ...next, renaming: null }\n else {\n const error = renameError(r.draft, r.path, r.base, next.tree)\n if (error !== r.error) next = { ...next, renaming: { ...r, error } }\n }\n }\n if (next.creatingFolder) {\n const f = next.creatingFolder\n if (next.tree && !folderPaths.has(f.parent)) next = { ...next, creatingFolder: null }\n else {\n const error = folderError(f.draft, f.parent, next.tree)\n if (error !== f.error) next = { ...next, creatingFolder: { ...f, error } }\n }\n }\n if (next.drag) {\n const d = next.drag\n if ((d.source.type !== 'foreign-block' && !view.keys.has(d.sourceKey)) || (d.hover !== null && !view.keys.has(d.hover))) next = { ...next, drag: null }\n else if (d.hover !== null) {\n const target = view.rows.get(d.hover)?.item\n const verdict = target ? dropVerdict(d.source, target, dropEnv()) : d.verdict\n if (!sameVerdict(verdict, d.verdict)) next = { ...next, drag: { ...d, verdict } }\n }\n }\n return next\n }\n\n const state = createStore<TreeState>(withView(core, viewOf(core)))\n\n function publish(c: TreeCore) {\n if (disposed) return\n const view = viewOf(c)\n core = reconcile(c, view)\n const next = withView(core, view)\n const current = state.get()\n if ((Object.keys(next) as (keyof TreeState)[]).every(key => Object.is(next[key], current[key]))) return\n state.set(next)\n }\n\n const patch = (changes: Partial<TreeCore>) => publish({ ...core, ...changes })\n\n // --- sources ---------------------------------------------------------------------------------------------------\n\n /** Reads the store and the shared view state; what opening a document shows is opened. */\n function sync() {\n if (disposed) return\n const documents = store.documents.get() ?? NO_DOCUMENTS\n const activeId = store.activeId.get()\n publish({ ...core, tree: store.tree.get(), documents, activeId, nodeFilters: shared.nodeFilters.get(), basketFilter: shared.basketFilter.get(), expanded: shared.expanded.get() })\n // Opening a document (also by URL, or after a move) shows it: its folders open and its folder becomes the selected one.\n const activeFolder = documents.find(d => d.id === activeId)?.folder\n if (activeFolder !== lastActiveFolder) {\n lastActiveFolder = activeFolder\n expand(ancestorKeys(activeFolder ?? ''))\n if (activeFolder !== undefined) setSelectedFolder(activeFolder)\n }\n if (activeId !== lastActiveId) {\n lastActiveId = activeId\n if (activeId) expand([`doc:${activeId}`])\n }\n }\n\n const unsubscribe = [\n store.tree.subscribe(sync),\n store.documents.subscribe(sync),\n store.activeId.subscribe(sync),\n shared.nodeFilters.subscribe(sync),\n shared.basketFilter.subscribe(sync),\n shared.expanded.subscribe(sync),\n ]\n\n function readOutline() {\n patch({ outline: editor ? editor.outline(structure) : EMPTY_OUTLINE })\n mirrorFocus()\n }\n\n /**\n * The editor's focus mode changed on its own (the focus chip, a block's „Fokussieren“, the focused Baustein vanished):\n * the tree follows without a command. A Baustein the outline does not know yet is retried after the next outline read.\n */\n function mirrorFocus() {\n const id = editor?.focusedId() ?? null\n if (id === seenFocus) return\n if (id === null) {\n seenFocus = null\n if (core.focusKey !== null) patch({ focusKey: null })\n return\n }\n const key = `outline:${id}`\n if (core.focusKey !== key) {\n const item = state.get().view.index.get(key)?.item\n if (item?.type !== 'composite') return\n patch({ focusKey: key })\n }\n seenFocus = id\n }\n\n // The outline is read when the document changed and has been quiet for a moment; a drag in progress is checked at once, and so is the editor's focus.\n function onEditorChange() {\n clearTimeout(outlineTimer)\n outlineTimer = setTimeout(readOutline, debounceMs)\n if (core.drag) publish(core)\n mirrorFocus()\n }\n\n function setContext(context: TreeContext) {\n if (context.editor === editor && context.structure === structure && context.treeRoot === treeRoot) return\n const editorChanged = context.editor !== editor\n const wasVirtual = core.virtual\n editor = context.editor\n structure = context.structure\n treeRoot = context.treeRoot\n clearTimeout(outlineTimer)\n if (editorChanged) {\n seenFocus = null\n unwatchEditor?.()\n unwatchEditor = editor?.onChange(onEditorChange)\n }\n patch({\n virtual: isVirtual(),\n structure,\n kinds: editor?.kinds ?? NO_KINDS,\n baskets: editor?.baskets ?? NO_BASKETS,\n ...(editorChanged ? { focusKey: null } : {}),\n hasEditor: !!editor,\n outline: editor ? editor.outline(structure) : EMPTY_OUTLINE,\n })\n if (core.virtual && !wasVirtual) expand([VIRTUAL_ROOT])\n mirrorFocus()\n }\n\n // --- open, filtered, typed -------------------------------------------------------------------------------------\n\n const filtering = () => filterQuery(core.filterText) !== ''\n\n function setOpen(key: string, open: boolean) {\n if (filtering()) patch({ filterOverrides: { ...core.filterOverrides, [key]: open } })\n else if (isOutlineKey(key)) patch({ collapsedOutline: open ? core.collapsedOutline.filter(k => k !== key) : [...core.collapsedOutline.filter(k => k !== key), key] })\n else if (open) shared.expand([key])\n else shared.expanded.set(shared.expanded.get().filter(k => k !== key))\n }\n\n function expand(keys: readonly string[]) {\n const outlineKeys = keys.filter(isOutlineKey)\n const { filterOverrides } = core\n const overridden = keys.some(key => key in filterOverrides)\n if (overridden || outlineKeys.some(key => core.collapsedOutline.includes(key))) {\n patch({\n collapsedOutline: core.collapsedOutline.filter(key => !outlineKeys.includes(key)),\n filterOverrides: overridden ? Object.fromEntries(Object.entries(filterOverrides).filter(([key]) => !keys.includes(key))) : filterOverrides,\n })\n }\n shared.expand(keys.filter(key => !isOutlineKey(key)))\n }\n\n function setFilterText(text: string) {\n patch({ filterText: text, filterOverrides: filterQuery(text) ? core.filterOverrides : NO_FILTERS })\n }\n\n // --- focus -----------------------------------------------------------------------------------------------------\n\n /** Only a Baustein the editor can address (it has a block ID) can be focused. */\n function focus(key: string) {\n const item = state.get().view.index.get(key)?.item\n if (item?.type !== 'composite' || !item.blockId) return\n patch({ focusKey: key })\n void execute({ type: 'focusBlock', id: item.blockId })\n }\n\n function defocus() {\n if (core.focusKey === null) return\n patch({ focusKey: null })\n void execute({ type: 'focusBlock', id: null })\n }\n\n // --- merge -----------------------------------------------------------------------------------------------------\n\n const canMerge = (item: TreeItem) => item.type === 'composite' && !!item.blockId && !!editor?.canMerge(item.blockId)\n\n function merge(item: TreeItem) {\n if (canMerge(item)) void execute({ type: 'mergeBlock', id: item.blockId! })\n }\n\n // --- selection -------------------------------------------------------------------------------------------------\n\n function setSelectedFolder(path: string) {\n patch({ selectedFolder: path })\n }\n\n function selectItem(item: TreeItem) {\n if (core.renaming?.key === item.key) return\n if (item.key === VIRTUAL_ROOT) return patch({ virtualTarget: null })\n if (item.type === 'document') {\n setSelectedFolder(item.folder ?? '')\n void execute({ type: 'openDocument', id: item.id! })\n }\n else if (item.type === 'composite' || item.type === 'heading') {\n void execute({ type: 'revealBlock', id: item.blockId ?? null, pos: item.pos! })\n const takesBausteine = !!item.kind && core.kinds.some(kind => kindAccepts(core.kinds, item.kind!, kind.id))\n if (core.virtual && item.blockId && takesBausteine) patch({ virtualTarget: item.blockId })\n }\n else {\n setSelectedFolder(item.path ?? '')\n }\n }\n\n function toggle(key: string) {\n setOpen(key, !state.get().view.rows.get(key)?.open)\n }\n\n /** A folder moved from `from` to `to`: its open/selected state follows it. */\n function followFolderMove(from: string, to: string) {\n shared.followFolderMove(from, to)\n patch({\n selectedFolder: remapFolderPath(core.selectedFolder, from, to),\n filterOverrides: Object.fromEntries(Object.entries(core.filterOverrides).map(([key, open]) => [key.startsWith('folder:') ? `folder:${remapFolderPath(key.slice(7), from, to)}` : key, open])),\n })\n expand(ancestorKeys(parentPath(to)))\n }\n\n async function moveFolder(from: string, to: string) {\n pendingMove = { from, to }\n const moved = await execute({ type: 'moveFolder', from, to })\n pendingMove = undefined\n if (moved) followFolderMove(from, to)\n }\n\n // --- drag and drop ---------------------------------------------------------------------------------------------\n\n function dragStart(item: TreeItem) {\n if (core.renaming?.key === item.key || !isDraggable(item, core.virtual)) return null\n const source = dragPayloadOf(item)\n patch({ drag: { source, sourceKey: item.key, hover: null, verdict: null } })\n return source\n }\n\n function dragOver(item: TreeItem) {\n const drag = core.drag\n if (!drag) return null\n const verdict = dropVerdict(drag.source, item, dropEnv())\n if (drag.hover !== item.key || !sameVerdict(drag.verdict, verdict)) patch({ drag: { ...drag, hover: item.key, verdict } })\n return verdict\n }\n\n function foreignDragOver(item: TreeItem) {\n const drag = core.drag\n if (drag && drag.source.type !== 'foreign-block') return null\n const source: DragPayload = { type: 'foreign-block' }\n const verdict = dropVerdict(source, item, dropEnv())\n if (!drag || drag.hover !== item.key || !sameVerdict(drag.verdict, verdict)) patch({ drag: { source, sourceKey: '', hover: item.key, verdict } })\n return verdict\n }\n\n async function dropForeign(item: TreeItem, payload: BlockTransfer, menu: boolean, x: number, y: number) {\n // This tree's own drag (a row also writes the block payload) is a move, not a transfer.\n if (core.drag && core.drag.source.type !== 'foreign-block') return\n patch({ drag: null })\n if (!dropVerdict({ type: 'foreign-block' }, item, dropEnv()).ok) return\n const targetId = item.key === VIRTUAL_ROOT ? null : item.blockId!\n // A throwing executor (the contract says it never does) must not leave the drop handler with an unhandled rejection.\n let done = false\n try {\n done = await execute({ type: 'transferBlock', payload, targetId, menu, x, y })\n }\n catch {\n return\n }\n if (done && targetId && !menu) expand([`outline:${targetId}`])\n }\n\n async function drop(item: TreeItem) {\n const drag = core.drag\n patch({ drag: null })\n if (!drag || !dropVerdict(drag.source, item, dropEnv()).ok) return\n const { source } = drag\n if (source.type === 'composite') {\n const targetId = item.key === VIRTUAL_ROOT ? null : item.blockId!\n if (await execute({ type: 'moveBlock', id: source.blockId, targetId }) && targetId) expand([`outline:${targetId}`])\n return\n }\n // A foreign Baustein is dropped through `dropForeign`, which reads its payload; it is no move of this tree.\n if (source.type === 'foreign-block') return\n const targetPath = item.path!\n if (source.type === 'document') {\n if (await execute({ type: 'moveDocument', id: source.id!, folder: targetPath })) expand(ancestorKeys(targetPath))\n return\n }\n await moveFolder(source.path, joinPath(targetPath, source.path.slice(source.path.lastIndexOf('/') + 1)))\n }\n\n // --- renaming, creating ----------------------------------------------------------------------------------------\n\n function startRename(item: TreeItem) {\n if (item.type !== 'folder') return\n patch({ renaming: { key: item.key, path: item.path!, base: item.label, draft: item.label, error: null } })\n }\n\n async function commitRename() {\n const r = core.renaming\n // An invalid name keeps the field open with its inline error.\n if (!r || r.error) return\n const name = r.draft.trim()\n patch({ renaming: null })\n if (name !== r.base) await moveFolder(r.path, joinPath(parentPath(r.path), name))\n }\n\n async function blurRename() {\n const r = core.renaming\n if (!r) return\n if (r.error) {\n void execute({ type: 'warn', title: t('tree.folder.renameFailed'), description: r.error })\n patch({ renaming: null })\n return\n }\n await commitRename()\n }\n\n function startCreateFolder(parent: string) {\n patch({ selectedFolder: parent, creatingFolder: { parent, draft: '', error: null } })\n }\n\n async function commitCreateFolder() {\n const f = core.creatingFolder\n if (!f) return\n if (!f.draft.trim()) return patch({ creatingFolder: null })\n if (f.error) return\n patch({ creatingFolder: null })\n if (await execute({ type: 'createFolder', path: joinPath(f.parent, f.draft.trim()) })) expand(ancestorKeys(f.parent))\n }\n\n // --- menus, deleting -------------------------------------------------------------------------------------------\n\n async function createDocumentIn(folder: string) {\n setSelectedFolder(folder)\n if (await execute({ type: 'createDocument', folder })) expand(ancestorKeys(folder))\n }\n\n /** Runs `command` for the Baustein of `item` (the file itself when it has none) and shows the result. */\n async function inComposite(item: TreeItem, command: TreeCommand) {\n if (await execute(command)) expand([item.blockId ? `outline:${item.blockId}` : item.key])\n }\n\n /**\n * What can be created below `item`: folders of the store take documents and sub-folders, the open file (as the root or\n * as a document row) and its Bausteine take what their kind accepts. Other rows take nothing. Folders also list\n * „Umbenennen“ here: renaming a document happens in the editor's title field.\n */\n function addMenu(item: TreeItem): TreeMenuEntry[][] {\n const groups: TreeMenuEntry[][] = []\n if (item.key !== VIRTUAL_ROOT && (item.type === 'root' || item.type === 'folder')) {\n const path = item.path!\n groups.push([\n { label: t('tree.menu.newDocument'), icon: 'i-lucide-file-plus', run: () => void createDocumentIn(path) },\n { label: item.type === 'root' ? t('tree.menu.newFolder') : t('tree.menu.newSubfolder'), icon: 'i-lucide-folder-plus', run: () => startCreateFolder(path) },\n ])\n }\n else {\n const can = creatableBelow(item, { structure: core.structure, hasEditor: core.hasEditor, activeId: core.activeId, kinds: core.kinds })\n const targetId = item.blockId ?? null\n const entries: TreeMenuEntry[] = []\n if (can.folder) entries.push({ label: t('tree.menu.newCompositeFolder'), icon: 'i-lucide-folder-plus', run: () => void inComposite(item, { type: 'createBausteinFolder', targetId }) })\n if (can.document) entries.push({ label: t('tree.menu.importFile'), icon: 'i-lucide-file-up', run: () => void inComposite(item, { type: 'importFiles', targetId }) })\n if (entries.length) groups.push(entries)\n }\n if (item.type === 'folder') groups.push([{ label: t('tree.menu.rename'), icon: 'i-lucide-pencil', run: () => startRename(item) }])\n return groups\n }\n\n async function remove(item: TreeItem) {\n patch({ removing: item.key })\n try {\n await execute(item.type === 'document' ? { type: 'removeDocument', id: item.id!, folder: item.folder ?? '' } : { type: 'removeFolder', path: item.path! })\n }\n finally {\n patch({ removing: null })\n }\n }\n\n sync()\n mirrorFocus()\n\n return {\n state,\n setContext,\n setSelectedFolder,\n setOpen,\n toggle,\n expand,\n setFilterText,\n setKindHidden: (key, kind, hidden) => shared.setKindHidden(key, kind, hidden),\n clearFilter: key => shared.clearFilter(key),\n clearAllFilters: () => shared.clearAllFilters(),\n setBasketShown: (id, shown) => shared.setBasketShown(id, shown),\n clearBasketFilter: () => shared.clearBasketFilter(),\n focus,\n defocus,\n canMerge,\n merge,\n select: selectItem,\n activate(item) {\n selectItem(item)\n if (item.type === 'root' || item.type === 'folder') toggle(item.key)\n },\n addMenu,\n remove,\n isDraggable: item => core.renaming?.key !== item.key && isDraggable(item, core.virtual),\n dragStart,\n dragOver,\n dragLeave(item) {\n // A foreign drag only exists while it is over this tree (no `dragend` reaches here), so leaving a row ends it; the next row's `foreignDragOver` starts it again.\n if (core.drag?.source.type === 'foreign-block') patch({ drag: null })\n else if (core.drag?.hover === item.key) patch({ drag: { ...core.drag, hover: null, verdict: null } })\n },\n dragEnd: () => patch({ drag: null }),\n drop,\n foreignDragOver,\n dropForeign,\n startRename,\n setRenameDraft(text) {\n const r = core.renaming\n if (r) patch({ renaming: { ...r, draft: text, error: renameError(text, r.path, r.base, core.tree) } })\n },\n cancelRename: () => patch({ renaming: null }),\n commitRename,\n blurRename,\n startCreateFolder,\n setFolderDraft(text) {\n const f = core.creatingFolder\n if (f) patch({ creatingFolder: { ...f, draft: text, error: folderError(text, f.parent, core.tree) } })\n },\n cancelCreateFolder: () => patch({ creatingFolder: null }),\n commitCreateFolder,\n dispose() {\n disposed = true\n clearTimeout(outlineTimer)\n unwatchEditor?.()\n for (const stop of unsubscribe) stop()\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree-model.js","names":[],"sources":["../../src/tree/tree-model.ts"],"sourcesContent":["import type { BlockTransfer } from '../core/block-transfer'\nimport { createStore, type ReadonlyStore } from '../core/store'\nimport { acceptsChild, type Basket, basketById, type BlockType } from '../features/composites'\nimport type { Translate } from '../i18n'\nimport { type DropEnv, dropVerdict, type DropVerdict } from './drop-rules'\nimport { remapFolderPath } from './folder-paths'\nimport type { DocumentStore } from './store'\nimport {\n ancestorKeys,\n collectFolderPaths,\n creatableBelow,\n type DragPayload,\n dragPayloadOf,\n EMPTY_OUTLINE,\n filterKinds,\n folderNamesIn,\n isDraggable,\n joinPath,\n type Outline,\n parentPath,\n type TreeItem,\n VIRTUAL_ROOT,\n} from './tree-items'\nimport { deriveTree, filterQuery, type TreeRow, type TreeView } from './tree-rows'\nimport type { NodeFilters, TreeViewModel } from './tree-view-model'\nimport type { DocumentSummary, TreeFolder } from './types'\n\n// One framework-free model per `DocumentTree`, rendered by the Vue and the React component alike. It owns what the\n// tree remembers (open rows, kind filters, the title filter, the selection, a drag, a folder being renamed or created)\n// and checks all of it against the tree after every change of the store, the outline or the view state, so a key of\n// something that moved or vanished never lingers. It never calls the store or the editor to change something: it emits\n// `TreeCommand`s to the `execute` it was given and follows their result.\n\n/** What the model asks its host to do; the host reports whether it happened. */\nexport type TreeCommand\n = | { type: 'openDocument', id: string }\n | { type: 'createDocument', folder: string }\n | { type: 'moveDocument', id: string, folder: string }\n | { type: 'removeDocument', id: string, folder: string }\n | { type: 'createFolder', path: string }\n | { type: 'moveFolder', from: string, to: string }\n | { type: 'removeFolder', path: string }\n /** Moves the block into the Typed block `targetId` (`null` = the end of the document). */\n | { type: 'moveBlock', id: string, targetId: string | null }\n | { type: 'revealBlock', id: string | null, pos: number }\n /** Adds an Folder block to the Typed block `targetId` (`null` = the end of the document). */\n | { type: 'createFolderBlock', targetId: string | null }\n /** Lets the user pick files and imports them into the Typed block `targetId` (`null` = the end of the document); `false` when none were imported. */\n | { type: 'importFiles', targetId: string | null }\n | { type: 'warn', title: string, description: string }\n /** Inserts a Typed block dragged in from another surface or tree at the end of the Typed block `targetId` (`null` = the end of the document); `menu`: offer the transforms at `x`, `y` first. */\n | { type: 'transferBlock', payload: BlockTransfer, targetId: string | null, menu: boolean, x: number, y: number }\n /** Puts the editor into focus mode on the Typed block `id` (`null` = leaves focus mode); sent after the tree's own focus changed. */\n | { type: 'focusBlock', id: string | null }\n /** The Typed block `id` absorbs the Typed block that follows it (`mergeCompositeWithNext`); `false` when the editor refuses. */\n | { type: 'mergeBlock', id: string }\n\n/** Runs a command and resolves whether it happened. Never rejects: the host reports its own failures. */\nexport type TreeExecutor = (command: TreeCommand) => boolean | Promise<boolean>\n\n/** What the model needs from the open document's editor. */\nexport interface TreeEditor {\n kinds: readonly BlockType[]\n /** The baskets a Typed block can be put into (colour dots on the rows). */\n baskets: readonly Basket[]\n /** The outline in `structure`: Typed blocks in `'structured'` structure, else the headings. Empty once the editor is gone. */\n outline: (structure: string) => Outline\n /** Whether a block may move into a Typed block, judged on the live document. */\n moveVerdict: NonNullable<DropEnv['moveVerdict']>\n /** Whether the editor takes blocks from outside: it has the transfer feature's drop target and its `transferBlock` command. */\n canTransfer: () => boolean\n /** The block id of the Typed block the editor is focused on (focus mode), `null` without focus. The model mirrors it into the tree. */\n focusedId: () => string | null\n /** Whether the Typed block `id` can absorb the Typed block that follows it, judged on the live document. */\n canMerge: (id: string) => boolean\n /** `listener` runs after the document or the editor's focus changed; returns the unsubscribe function. */\n onChange: (listener: () => void) => () => void\n}\n\n/** What the surrounding app decides: the open editor and the `blocks.structure` / `blocks.treeRoot` settings. */\nexport interface TreeContext {\n editor: TreeEditor | undefined\n structure: string\n treeRoot: string\n}\n\nexport interface TreeModelOptions {\n /** Words the menus, the drop refusals and the label of an untitled open document; the framework layer passes the context's `t`. */\n t: Translate\n store: DocumentStore\n /** The view state shared by the trees of one app: open store items and kind filters (persisted). */\n view: TreeViewModel\n execute: TreeExecutor\n context: TreeContext\n /** The folder new documents and folders go to; default the root. */\n selectedFolder?: string\n /** How long the outline waits for the document to settle before it is read again; default 150 ms. */\n outlineDebounceMs?: number\n}\n\n/** A drag in progress. */\nexport interface TreeDrag {\n source: DragPayload\n /** Key of the dragged row (`''` for a `foreign-block`, which has no row here) */\n sourceKey: string\n /** Key of the row under the pointer */\n hover: string | null\n /** What dropping on `hover` would do; `null` without a `hover` */\n verdict: DropVerdict | null\n}\n\n/** A folder being renamed. */\nexport interface TreeRename {\n /** Key of the folder's row */\n key: string\n path: string\n /** Its name when renaming started */\n base: string\n draft: string\n error: string | null\n}\n\n/** A folder being named. */\nexport interface TreeCreateFolder {\n /** Folder path the folder is created in */\n parent: string\n draft: string\n error: string | null\n}\n\n/** Everything a renderer needs. Fields below `view` are what the derived `view` was computed from and what `rowOf` reads. */\nexport interface TreeState {\n /** The loaded folder tree: `undefined` = not loaded yet, `null` = loading failed. */\n tree: TreeFolder | null | undefined\n documents: readonly DocumentSummary[]\n activeId: string | undefined\n /** The open document is the root (virtual mode) instead of the store's folders. */\n virtual: boolean\n structure: string\n kinds: readonly BlockType[]\n /** The open editor's baskets (colours of the row dots). */\n baskets: readonly Basket[]\n hasEditor: boolean\n outline: Outline\n nodeFilters: NodeFilters\n /** The basket ids the tree shows (`[]` = all). */\n basketFilter: readonly string[]\n /** Key of the focused row: the tree lists only its children. `null` = no focus. */\n focusKey: string | null\n expanded: readonly string[]\n collapsedOutline: readonly string[]\n /** What the title filter input holds. */\n filterText: string\n filterOverrides: Readonly<Record<string, boolean>>\n /** The folder new documents, folders and host imports go to. */\n selectedFolder: string\n /** Virtual mode: block ID of the selected Typed block that takes Typed blocks; `null` = the document itself. */\n virtualTarget: string | null\n drag: TreeDrag | null\n renaming: TreeRename | null\n creatingFolder: TreeCreateFolder | null\n /** Key of the row whose deletion is running. */\n removing: string | null\n view: TreeView\n /** The unfiltered items from the top down to the focused one (the breadcrumb); empty without a focus. Derived with `view`. */\n focusPath: readonly TreeItem[]\n}\n\n/** One row of a row's menu. */\nexport interface TreeMenuEntry {\n label: string\n icon: string\n run: () => void\n}\n\n/** How a renderer draws one row. */\nexport interface TreeRowState extends TreeRow {\n /** The row's document is the open one. */\n active: boolean\n /** The row is the selected folder, or (virtual mode) the selected Typed block. */\n selected: boolean\n /** What dropping the drag on this row would do, while the pointer is over it. */\n drop: DropVerdict | null\n renaming: TreeRename | null\n removing: boolean\n /** The kinds the row's kind filter can hide below it, and the ones it hides. */\n filterKinds: readonly BlockType[]\n hiddenKinds: readonly string[]\n /** The row offers a kind filter. */\n showFilter: boolean\n}\n\nexport interface TreeModel {\n readonly state: ReadonlyStore<TreeState>\n /** The open editor or a setting changed. */\n setContext: (context: TreeContext) => void\n /** The host selected another folder (it controls the value). */\n setSelectedFolder: (path: string) => void\n\n // --- what is open, filtered, typed\n /** Opens or closes a row; while the title filter is set the choice is discarded when it is cleared. */\n setOpen: (key: string, open: boolean) => void\n toggle: (key: string) => void\n /** Opens the rows (also during a title filter); closed rows are left alone otherwise. */\n expand: (keys: readonly string[]) => void\n /** Filters the rows by title (case-insensitive substring); `''` clears it and restores the opened rows from before. */\n setFilterText: (text: string) => void\n setKindHidden: (key: string, kind: string, hidden: boolean) => void\n clearFilter: (key: string) => void\n clearAllFilters: () => void\n /** Shows (`shown`) or stops showing the Typed blocks of the basket; no basket shown = no filter. */\n setBasketShown: (id: string, shown: boolean) => void\n clearBasketFilter: () => void\n /** Focuses a Typed block row: the tree lists only its children and the editor hides everything else. */\n focus: (key: string) => void\n /** Leaves focus mode (tree and editor). */\n defocus: () => void\n /** Whether the Typed block row can be merged with the Typed block after it (it has a block ID and the editor accepts the merge). */\n canMerge: (item: TreeItem) => boolean\n /** Merges the Typed block row with the Typed block after it: the row keeps its title, id and meta and takes over the other one's body and nested Typed blocks. */\n merge: (item: TreeItem) => void\n\n // --- rows\n /** A row was chosen (click, Enter). */\n select: (item: TreeItem) => void\n /** `select`, and a folder or the root toggles. */\n activate: (item: TreeItem) => void\n addMenu: (item: TreeItem) => TreeMenuEntry[][]\n remove: (item: TreeItem) => Promise<void>\n\n // --- drag and drop\n isDraggable: (item: TreeItem) => boolean\n /** Starts dragging `item`; returns what the drag carries, `null` when `item` cannot be dragged. */\n dragStart: (item: TreeItem) => DragPayload | null\n /** The pointer is over `item`; returns the verdict (`null` without a drag). Only an `ok` one is a drop target. */\n dragOver: (item: TreeItem) => DropVerdict | null\n /** The pointer left `item` for good (not into one of its parts). */\n dragLeave: (item: TreeItem) => void\n dragEnd: () => void\n drop: (item: TreeItem) => Promise<void>\n /**\n * A Typed block from another surface or tree (`BLOCK_MIME`) is over `item`; returns the verdict, `null` while this\n * tree's own drag is running. Only an `ok` one is a drop target.\n */\n foreignDragOver: (item: TreeItem) => DropVerdict | null\n /** Drops the foreign Typed block `payload` on `item`: inserts a copy at the end of that Typed block (`menu`: offers the transforms at `x`, `y` instead). */\n dropForeign: (item: TreeItem, payload: BlockTransfer, menu: boolean, x: number, y: number) => Promise<void>\n\n // --- renaming and creating folders\n startRename: (item: TreeItem) => void\n setRenameDraft: (text: string) => void\n cancelRename: () => void\n commitRename: () => Promise<void>\n /** The rename field lost focus: commit, or give up with a warning when the name is invalid. */\n blurRename: () => Promise<void>\n startCreateFolder: (parent: string) => void\n setFolderDraft: (text: string) => void\n cancelCreateFolder: () => void\n commitCreateFolder: () => Promise<void>\n\n dispose: () => void\n}\n\nconst NO_DOCUMENTS: readonly DocumentSummary[] = []\nconst NO_KINDS: readonly BlockType[] = []\nconst NO_BASKETS: readonly Basket[] = []\nconst NO_FILTERS: Readonly<Record<string, boolean>> = {}\nconst UNSET = Symbol('unset')\n\nconst isOutlineKey = (key: string) => key.startsWith('outline:')\n\n/** The state `core` holds: everything of `TreeState` but what is derived from the view. */\ntype TreeCore = Omit<TreeState, 'view' | 'focusPath'>\n\nconst withView = (c: TreeCore, view: TreeView): TreeState => ({ ...c, view, focusPath: view.focusPath })\n\nfunction sameVerdict(a: DropVerdict | null, b: DropVerdict | null): boolean {\n if (a === b) return true\n if (!a || !b) return false\n return a.ok ? b.ok : !b.ok && a.reason === b.reason\n}\n\n/** A row's state in `state` (`item` is one of `state.view.items`). */\nexport function rowOf(state: TreeState, item: TreeItem, t: Translate): TreeRowState {\n const hidden = state.nodeFilters[item.key] ?? []\n const kinds = filterKinds(item, { structure: state.structure, activeId: state.activeId, kinds: state.kinds, t })\n const virtualTarget = state.virtual && (item.key === VIRTUAL_ROOT ? state.virtualTarget === null : !!item.blockId && item.blockId === state.virtualTarget)\n return {\n ...state.view.rows.get(item.key)!,\n active: item.id !== undefined && item.id === state.activeId,\n selected: (item.type !== 'document' && item.path === state.selectedFolder) || virtualTarget,\n drop: state.drag?.hover === item.key ? state.drag.verdict : null,\n renaming: state.renaming?.key === item.key ? state.renaming : null,\n removing: state.removing === item.key,\n filterKinds: kinds,\n hiddenKinds: hidden,\n showFilter: kinds.length > 0 && (item.type === 'root' || item.type === 'folder' || !!item.children?.length || hidden.length > 0),\n }\n}\n\n/** A tree model over `options.store`; call `dispose` when its tree goes away. */\nexport function createTreeModel(options: TreeModelOptions): TreeModel {\n const { store, view: shared, execute, t } = options\n const debounceMs = options.outlineDebounceMs ?? 150\n\n let editor = options.context.editor\n let structure = options.context.structure\n let treeRoot = options.context.treeRoot\n let unwatchEditor = editor?.onChange(onEditorChange)\n /** The focus the editor last showed that the tree took over (or already had); a change of the editor's focus is told apart from the tree's own by comparing against it. */\n let seenFocus: string | null = null\n let outlineTimer: ReturnType<typeof setTimeout> | undefined\n /** A folder move the host is running: until it is done, a selected folder at the old path follows to the new one. */\n let pendingMove: { from: string, to: string } | undefined\n let disposed = false\n\n const isVirtual = () => treeRoot === 'file' && structure === 'structured' && !!editor\n\n let core: TreeCore = {\n tree: store.tree.get(),\n documents: store.documents.get() ?? NO_DOCUMENTS,\n activeId: store.activeId.get(),\n virtual: isVirtual(),\n structure,\n kinds: editor?.kinds ?? NO_KINDS,\n baskets: editor?.baskets ?? NO_BASKETS,\n hasEditor: !!editor,\n outline: editor ? editor.outline(structure) : EMPTY_OUTLINE,\n nodeFilters: shared.nodeFilters.get(),\n basketFilter: shared.basketFilter.get(),\n focusKey: null,\n expanded: shared.expanded.get(),\n collapsedOutline: [],\n filterText: '',\n filterOverrides: NO_FILTERS,\n selectedFolder: options.selectedFolder ?? '',\n virtualTarget: null,\n drag: null,\n renaming: null,\n creatingFolder: null,\n removing: null,\n }\n let lastView: { deps: readonly unknown[], view: TreeView } | undefined\n let lastTree: TreeFolder | null | undefined | typeof UNSET = UNSET\n let folderPaths = new Set<string>()\n let lastActiveFolder: string | undefined | typeof UNSET = UNSET\n let lastActiveId: string | undefined | typeof UNSET = UNSET\n\n const dropEnv = (): DropEnv => ({ virtual: core.virtual, moveVerdict: editor?.moveVerdict, canTransfer: editor?.canTransfer() ?? false, t })\n\n function viewOf(c: TreeCore): TreeView {\n const deps = [c.tree, c.documents, c.activeId, c.virtual, c.outline, c.kinds, c.nodeFilters, c.basketFilter, c.baskets, c.focusKey, c.expanded, c.collapsedOutline, c.filterText, c.filterOverrides]\n if (lastView && deps.every((dep, i) => Object.is(dep, lastView!.deps[i]))) return lastView.view\n // A basket the open editor does not offer cannot be unchecked in the filter menu, so it never filters.\n const basketFilter = c.basketFilter.filter(id => basketById(c.baskets, id) !== undefined)\n const view = deriveTree({ ...c, basketFilter, t, select: selectItem })\n lastView = { deps, view }\n return view\n }\n\n const renameError = (draft: string, path: string, base: string, tree: TreeFolder | null | undefined) =>\n draft.trim() === base ? null : store.validateName(draft, folderNamesIn(tree, parentPath(path), path))\n const folderError = (draft: string, parent: string, tree: TreeFolder | null | undefined) =>\n draft.trim() ? store.validateName(draft, folderNamesIn(tree, parent)) : null\n\n /** Measures everything the tree remembers against the current tree: what is gone is dropped, what depends on the tree is recomputed. */\n function reconcile(c: TreeCore, view: TreeView): TreeCore {\n let next = c\n if (c.tree !== lastTree) {\n lastTree = c.tree\n folderPaths = new Set<string>()\n if (c.tree) collectFolderPaths(c.tree, folderPaths)\n if (c.tree && !folderPaths.has(next.selectedFolder)) {\n const followed = pendingMove ? remapFolderPath(next.selectedFolder, pendingMove.from, pendingMove.to) : ''\n next = { ...next, selectedFolder: folderPaths.has(followed) ? followed : '' }\n }\n }\n if (next.virtualTarget !== null && (!next.virtual || !view.keys.has(`outline:${next.virtualTarget}`))) next = { ...next, virtualTarget: null }\n if (next.focusKey !== null && !view.keys.has(next.focusKey)) next = { ...next, focusKey: null }\n if (next.renaming) {\n const r = next.renaming\n if (!view.keys.has(r.key)) next = { ...next, renaming: null }\n else {\n const error = renameError(r.draft, r.path, r.base, next.tree)\n if (error !== r.error) next = { ...next, renaming: { ...r, error } }\n }\n }\n if (next.creatingFolder) {\n const f = next.creatingFolder\n if (next.tree && !folderPaths.has(f.parent)) next = { ...next, creatingFolder: null }\n else {\n const error = folderError(f.draft, f.parent, next.tree)\n if (error !== f.error) next = { ...next, creatingFolder: { ...f, error } }\n }\n }\n if (next.drag) {\n const d = next.drag\n if ((d.source.type !== 'foreign-block' && !view.keys.has(d.sourceKey)) || (d.hover !== null && !view.keys.has(d.hover))) next = { ...next, drag: null }\n else if (d.hover !== null) {\n const target = view.rows.get(d.hover)?.item\n const verdict = target ? dropVerdict(d.source, target, dropEnv()) : d.verdict\n if (!sameVerdict(verdict, d.verdict)) next = { ...next, drag: { ...d, verdict } }\n }\n }\n return next\n }\n\n const state = createStore<TreeState>(withView(core, viewOf(core)))\n\n function publish(c: TreeCore) {\n if (disposed) return\n const view = viewOf(c)\n core = reconcile(c, view)\n const next = withView(core, view)\n const current = state.get()\n if ((Object.keys(next) as (keyof TreeState)[]).every(key => Object.is(next[key], current[key]))) return\n state.set(next)\n }\n\n const patch = (changes: Partial<TreeCore>) => publish({ ...core, ...changes })\n\n // --- sources ---------------------------------------------------------------------------------------------------\n\n /** Reads the store and the shared view state; what opening a document shows is opened. */\n function sync() {\n if (disposed) return\n const documents = store.documents.get() ?? NO_DOCUMENTS\n const activeId = store.activeId.get()\n publish({ ...core, tree: store.tree.get(), documents, activeId, nodeFilters: shared.nodeFilters.get(), basketFilter: shared.basketFilter.get(), expanded: shared.expanded.get() })\n // Opening a document (also by URL, or after a move) shows it: its folders open and its folder becomes the selected one.\n const activeFolder = documents.find(d => d.id === activeId)?.folder\n if (activeFolder !== lastActiveFolder) {\n lastActiveFolder = activeFolder\n expand(ancestorKeys(activeFolder ?? ''))\n if (activeFolder !== undefined) setSelectedFolder(activeFolder)\n }\n if (activeId !== lastActiveId) {\n lastActiveId = activeId\n if (activeId) expand([`doc:${activeId}`])\n }\n }\n\n const unsubscribe = [\n store.tree.subscribe(sync),\n store.documents.subscribe(sync),\n store.activeId.subscribe(sync),\n shared.nodeFilters.subscribe(sync),\n shared.basketFilter.subscribe(sync),\n shared.expanded.subscribe(sync),\n ]\n\n function readOutline() {\n patch({ outline: editor ? editor.outline(structure) : EMPTY_OUTLINE })\n mirrorFocus()\n }\n\n /**\n * The editor's focus mode changed on its own (the focus chip, a block's „Fokussieren“, the focused Typed block vanished):\n * the tree follows without a command. A Typed block the outline does not know yet is retried after the next outline read.\n */\n function mirrorFocus() {\n const id = editor?.focusedId() ?? null\n if (id === seenFocus) return\n if (id === null) {\n seenFocus = null\n if (core.focusKey !== null) patch({ focusKey: null })\n return\n }\n const key = `outline:${id}`\n if (core.focusKey !== key) {\n const item = state.get().view.index.get(key)?.item\n if (item?.type !== 'typedBlock') return\n patch({ focusKey: key })\n }\n seenFocus = id\n }\n\n // The outline is read when the document changed and has been quiet for a moment; a drag in progress is checked at once, and so is the editor's focus.\n function onEditorChange() {\n clearTimeout(outlineTimer)\n outlineTimer = setTimeout(readOutline, debounceMs)\n if (core.drag) publish(core)\n mirrorFocus()\n }\n\n function setContext(context: TreeContext) {\n if (context.editor === editor && context.structure === structure && context.treeRoot === treeRoot) return\n const editorChanged = context.editor !== editor\n const wasVirtual = core.virtual\n editor = context.editor\n structure = context.structure\n treeRoot = context.treeRoot\n clearTimeout(outlineTimer)\n if (editorChanged) {\n seenFocus = null\n unwatchEditor?.()\n unwatchEditor = editor?.onChange(onEditorChange)\n }\n patch({\n virtual: isVirtual(),\n structure,\n kinds: editor?.kinds ?? NO_KINDS,\n baskets: editor?.baskets ?? NO_BASKETS,\n ...(editorChanged ? { focusKey: null } : {}),\n hasEditor: !!editor,\n outline: editor ? editor.outline(structure) : EMPTY_OUTLINE,\n })\n if (core.virtual && !wasVirtual) expand([VIRTUAL_ROOT])\n mirrorFocus()\n }\n\n // --- open, filtered, typed -------------------------------------------------------------------------------------\n\n const filtering = () => filterQuery(core.filterText) !== ''\n\n function setOpen(key: string, open: boolean) {\n if (filtering()) patch({ filterOverrides: { ...core.filterOverrides, [key]: open } })\n else if (isOutlineKey(key)) patch({ collapsedOutline: open ? core.collapsedOutline.filter(k => k !== key) : [...core.collapsedOutline.filter(k => k !== key), key] })\n else if (open) shared.expand([key])\n else shared.expanded.set(shared.expanded.get().filter(k => k !== key))\n }\n\n function expand(keys: readonly string[]) {\n const outlineKeys = keys.filter(isOutlineKey)\n const { filterOverrides } = core\n const overridden = keys.some(key => key in filterOverrides)\n if (overridden || outlineKeys.some(key => core.collapsedOutline.includes(key))) {\n patch({\n collapsedOutline: core.collapsedOutline.filter(key => !outlineKeys.includes(key)),\n filterOverrides: overridden ? Object.fromEntries(Object.entries(filterOverrides).filter(([key]) => !keys.includes(key))) : filterOverrides,\n })\n }\n shared.expand(keys.filter(key => !isOutlineKey(key)))\n }\n\n function setFilterText(text: string) {\n patch({ filterText: text, filterOverrides: filterQuery(text) ? core.filterOverrides : NO_FILTERS })\n }\n\n // --- focus -----------------------------------------------------------------------------------------------------\n\n /** Only a Typed block the editor can address (it has a block ID) can be focused. */\n function focus(key: string) {\n const item = state.get().view.index.get(key)?.item\n if (item?.type !== 'typedBlock' || !item.blockId) return\n patch({ focusKey: key })\n void execute({ type: 'focusBlock', id: item.blockId })\n }\n\n function defocus() {\n if (core.focusKey === null) return\n patch({ focusKey: null })\n void execute({ type: 'focusBlock', id: null })\n }\n\n // --- merge -----------------------------------------------------------------------------------------------------\n\n const canMerge = (item: TreeItem) => item.type === 'typedBlock' && !!item.blockId && !!editor?.canMerge(item.blockId)\n\n function merge(item: TreeItem) {\n if (canMerge(item)) void execute({ type: 'mergeBlock', id: item.blockId! })\n }\n\n // --- selection -------------------------------------------------------------------------------------------------\n\n function setSelectedFolder(path: string) {\n patch({ selectedFolder: path })\n }\n\n function selectItem(item: TreeItem) {\n if (core.renaming?.key === item.key) return\n if (item.key === VIRTUAL_ROOT) return patch({ virtualTarget: null })\n if (item.type === 'document') {\n setSelectedFolder(item.folder ?? '')\n void execute({ type: 'openDocument', id: item.id! })\n }\n else if (item.type === 'typedBlock' || item.type === 'heading') {\n void execute({ type: 'revealBlock', id: item.blockId ?? null, pos: item.pos! })\n const takesTypedBlocks = !!item.kind && core.kinds.some(kind => acceptsChild(core.kinds, item.kind!, kind.id))\n if (core.virtual && item.blockId && takesTypedBlocks) patch({ virtualTarget: item.blockId })\n }\n else {\n setSelectedFolder(item.path ?? '')\n }\n }\n\n function toggle(key: string) {\n setOpen(key, !state.get().view.rows.get(key)?.open)\n }\n\n /** A folder moved from `from` to `to`: its open/selected state follows it. */\n function followFolderMove(from: string, to: string) {\n shared.followFolderMove(from, to)\n patch({\n selectedFolder: remapFolderPath(core.selectedFolder, from, to),\n filterOverrides: Object.fromEntries(Object.entries(core.filterOverrides).map(([key, open]) => [key.startsWith('folder:') ? `folder:${remapFolderPath(key.slice(7), from, to)}` : key, open])),\n })\n expand(ancestorKeys(parentPath(to)))\n }\n\n async function moveFolder(from: string, to: string) {\n pendingMove = { from, to }\n const moved = await execute({ type: 'moveFolder', from, to })\n pendingMove = undefined\n if (moved) followFolderMove(from, to)\n }\n\n // --- drag and drop ---------------------------------------------------------------------------------------------\n\n function dragStart(item: TreeItem) {\n if (core.renaming?.key === item.key || !isDraggable(item, core.virtual)) return null\n const source = dragPayloadOf(item)\n patch({ drag: { source, sourceKey: item.key, hover: null, verdict: null } })\n return source\n }\n\n function dragOver(item: TreeItem) {\n const drag = core.drag\n if (!drag) return null\n const verdict = dropVerdict(drag.source, item, dropEnv())\n if (drag.hover !== item.key || !sameVerdict(drag.verdict, verdict)) patch({ drag: { ...drag, hover: item.key, verdict } })\n return verdict\n }\n\n function foreignDragOver(item: TreeItem) {\n const drag = core.drag\n if (drag && drag.source.type !== 'foreign-block') return null\n const source: DragPayload = { type: 'foreign-block' }\n const verdict = dropVerdict(source, item, dropEnv())\n if (!drag || drag.hover !== item.key || !sameVerdict(drag.verdict, verdict)) patch({ drag: { source, sourceKey: '', hover: item.key, verdict } })\n return verdict\n }\n\n async function dropForeign(item: TreeItem, payload: BlockTransfer, menu: boolean, x: number, y: number) {\n // This tree's own drag (a row also writes the block payload) is a move, not a transfer.\n if (core.drag && core.drag.source.type !== 'foreign-block') return\n patch({ drag: null })\n if (!dropVerdict({ type: 'foreign-block' }, item, dropEnv()).ok) return\n const targetId = item.key === VIRTUAL_ROOT ? null : item.blockId!\n // A throwing executor (the contract says it never does) must not leave the drop handler with an unhandled rejection.\n let done = false\n try {\n done = await execute({ type: 'transferBlock', payload, targetId, menu, x, y })\n }\n catch {\n return\n }\n if (done && targetId && !menu) expand([`outline:${targetId}`])\n }\n\n async function drop(item: TreeItem) {\n const drag = core.drag\n patch({ drag: null })\n if (!drag || !dropVerdict(drag.source, item, dropEnv()).ok) return\n const { source } = drag\n if (source.type === 'typedBlock') {\n const targetId = item.key === VIRTUAL_ROOT ? null : item.blockId!\n if (await execute({ type: 'moveBlock', id: source.blockId, targetId }) && targetId) expand([`outline:${targetId}`])\n return\n }\n // A foreign Typed block is dropped through `dropForeign`, which reads its payload; it is no move of this tree.\n if (source.type === 'foreign-block') return\n const targetPath = item.path!\n if (source.type === 'document') {\n if (await execute({ type: 'moveDocument', id: source.id!, folder: targetPath })) expand(ancestorKeys(targetPath))\n return\n }\n await moveFolder(source.path, joinPath(targetPath, source.path.slice(source.path.lastIndexOf('/') + 1)))\n }\n\n // --- renaming, creating ----------------------------------------------------------------------------------------\n\n function startRename(item: TreeItem) {\n if (item.type !== 'folder') return\n patch({ renaming: { key: item.key, path: item.path!, base: item.label, draft: item.label, error: null } })\n }\n\n async function commitRename() {\n const r = core.renaming\n // An invalid name keeps the field open with its inline error.\n if (!r || r.error) return\n const name = r.draft.trim()\n patch({ renaming: null })\n if (name !== r.base) await moveFolder(r.path, joinPath(parentPath(r.path), name))\n }\n\n async function blurRename() {\n const r = core.renaming\n if (!r) return\n if (r.error) {\n void execute({ type: 'warn', title: t('tree.folder.renameFailed'), description: r.error })\n patch({ renaming: null })\n return\n }\n await commitRename()\n }\n\n function startCreateFolder(parent: string) {\n patch({ selectedFolder: parent, creatingFolder: { parent, draft: '', error: null } })\n }\n\n async function commitCreateFolder() {\n const f = core.creatingFolder\n if (!f) return\n if (!f.draft.trim()) return patch({ creatingFolder: null })\n if (f.error) return\n patch({ creatingFolder: null })\n if (await execute({ type: 'createFolder', path: joinPath(f.parent, f.draft.trim()) })) expand(ancestorKeys(f.parent))\n }\n\n // --- menus, deleting -------------------------------------------------------------------------------------------\n\n async function createDocumentIn(folder: string) {\n setSelectedFolder(folder)\n if (await execute({ type: 'createDocument', folder })) expand(ancestorKeys(folder))\n }\n\n /** Runs `command` for the Typed block of `item` (the file itself when it has none) and shows the result. */\n async function inComposite(item: TreeItem, command: TreeCommand) {\n if (await execute(command)) expand([item.blockId ? `outline:${item.blockId}` : item.key])\n }\n\n /**\n * What can be created below `item`: folders of the store take documents and sub-folders, the open file (as the root or\n * as a document row) and its Typed blocks take what their Block type accepts. Other rows take nothing. Folders also list\n * „Umbenennen“ here: renaming a document happens in the editor's title field.\n */\n function addMenu(item: TreeItem): TreeMenuEntry[][] {\n const groups: TreeMenuEntry[][] = []\n if (item.key !== VIRTUAL_ROOT && (item.type === 'root' || item.type === 'folder')) {\n const path = item.path!\n groups.push([\n { label: t('tree.menu.newDocument'), icon: 'i-lucide-file-plus', run: () => void createDocumentIn(path) },\n { label: item.type === 'root' ? t('tree.menu.newFolder') : t('tree.menu.newSubfolder'), icon: 'i-lucide-folder-plus', run: () => startCreateFolder(path) },\n ])\n }\n else {\n const can = creatableBelow(item, { structure: core.structure, hasEditor: core.hasEditor, activeId: core.activeId, kinds: core.kinds })\n const targetId = item.blockId ?? null\n const entries: TreeMenuEntry[] = []\n if (can.folder) entries.push({ label: t('tree.menu.newCompositeFolder'), icon: 'i-lucide-folder-plus', run: () => void inComposite(item, { type: 'createFolderBlock', targetId }) })\n if (can.files) entries.push({ label: t('tree.menu.importFile'), icon: 'i-lucide-file-up', run: () => void inComposite(item, { type: 'importFiles', targetId }) })\n if (entries.length) groups.push(entries)\n }\n if (item.type === 'folder') groups.push([{ label: t('tree.menu.rename'), icon: 'i-lucide-pencil', run: () => startRename(item) }])\n return groups\n }\n\n async function remove(item: TreeItem) {\n patch({ removing: item.key })\n try {\n await execute(item.type === 'document' ? { type: 'removeDocument', id: item.id!, folder: item.folder ?? '' } : { type: 'removeFolder', path: item.path! })\n }\n finally {\n patch({ removing: null })\n }\n }\n\n sync()\n mirrorFocus()\n\n return {\n state,\n setContext,\n setSelectedFolder,\n setOpen,\n toggle,\n expand,\n setFilterText,\n setKindHidden: (key, kind, hidden) => shared.setKindHidden(key, kind, hidden),\n clearFilter: key => shared.clearFilter(key),\n clearAllFilters: () => shared.clearAllFilters(),\n setBasketShown: (id, shown) => shared.setBasketShown(id, shown),\n clearBasketFilter: () => shared.clearBasketFilter(),\n focus,\n defocus,\n canMerge,\n merge,\n select: selectItem,\n activate(item) {\n selectItem(item)\n if (item.type === 'root' || item.type === 'folder') toggle(item.key)\n },\n addMenu,\n remove,\n isDraggable: item => core.renaming?.key !== item.key && isDraggable(item, core.virtual),\n dragStart,\n dragOver,\n dragLeave(item) {\n // A foreign drag only exists while it is over this tree (no `dragend` reaches here), so leaving a row ends it; the next row's `foreignDragOver` starts it again.\n if (core.drag?.source.type === 'foreign-block') patch({ drag: null })\n else if (core.drag?.hover === item.key) patch({ drag: { ...core.drag, hover: null, verdict: null } })\n },\n dragEnd: () => patch({ drag: null }),\n drop,\n foreignDragOver,\n dropForeign,\n startRename,\n setRenameDraft(text) {\n const r = core.renaming\n if (r) patch({ renaming: { ...r, draft: text, error: renameError(text, r.path, r.base, core.tree) } })\n },\n cancelRename: () => patch({ renaming: null }),\n commitRename,\n blurRename,\n startCreateFolder,\n setFolderDraft(text) {\n const f = core.creatingFolder\n if (f) patch({ creatingFolder: { ...f, draft: text, error: folderError(text, f.parent, core.tree) } })\n },\n cancelCreateFolder: () => patch({ creatingFolder: null }),\n commitCreateFolder,\n dispose() {\n disposed = true\n clearTimeout(outlineTimer)\n unwatchEditor?.()\n for (const stop of unsubscribe) stop()\n },\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { applyBasketFilter, applyNodeFilters, folderItem, indexItems, outlineItems, pathTo, virtualRootItem } from "./tree-items.js";
2
2
  //#region src/tree/tree-rows.ts
3
- const isOutlineItem = (item) => item.type === "composite" || item.type === "heading";
3
+ const isOutlineItem = (item) => item.type === "typedBlock" || item.type === "heading";
4
4
  /** The normalized filter text: trimmed and lower-cased; empty = no filter. */
5
5
  const filterQuery = (filterText) => filterText.trim().toLowerCase();
6
6
  /**
@@ -22,7 +22,7 @@ function pruneByText(list, query, matched, below) {
22
22
  }
23
23
  /**
24
24
  * The tree to show. In the store's folders: the `Dokumente` root with folders and documents, the open document listing
25
- * its outline; in virtual mode: the open document as the root with its Bausteine. The kind filters (hidden kinds per
25
+ * its outline; in virtual mode: the open document as the root with its Typed blocks. The Block type filters (hidden Block types per
26
26
  * item) apply first (on the children of the focused item while a focus is set), then the basket filter (composites of
27
27
  * other baskets go unless a descendant stays; those ancestors are `dimmed`), then the filter text: only matching rows and
28
28
  * their ancestors stay, and the ancestors of a match show open (without being written to `expanded`) until the filter
@@ -1 +1 @@
1
- {"version":3,"file":"tree-rows.js","names":[],"sources":["../../src/tree/tree-rows.ts"],"sourcesContent":["import type { CompositeKind } from '../features/composites'\nimport type { Translate } from '../i18n'\nimport {\n applyBasketFilter,\n applyNodeFilters,\n folderItem,\n type IndexedItem,\n indexItems,\n type Outline,\n outlineItems,\n pathTo,\n type TreeItem,\n virtualRootItem,\n} from './tree-items'\nimport type { NodeFilters } from './tree-view-model'\nimport type { DocumentSummary, TreeFolder } from './types'\n\n// The visible rows of the document tree as one pure function of what the tree has loaded and what the user opened,\n// filtered and typed. No framework, no editor, no store.\n\n/** Everything `deriveTree` reads. */\nexport interface TreeInput {\n /** Words the root's label while the open document has no title in `documents`. */\n t: Translate\n /** `null` = loading failed, `undefined` = not loaded yet */\n tree: TreeFolder | null | undefined\n documents: readonly DocumentSummary[]\n activeId: string | undefined\n /** The open document is the root (virtual mode) instead of the store's folders. */\n virtual: boolean\n outline: Outline\n kinds: readonly CompositeKind[]\n /** Hidden kinds per item key */\n nodeFilters: NodeFilters\n /** The basket ids to show (`[]` = no basket filter): composites of other baskets without a visible descendant are hidden. */\n basketFilter: readonly string[]\n /** Key of the focused item: the tree then lists only its children. A key the tree no longer has is ignored. */\n focusKey: string | null\n /** Keys of the open store items (folders, documents, the roots) */\n expanded: readonly string[]\n /** Outline entries start open: only the closed ones are listed. */\n collapsedOutline: readonly string[]\n /** What the title filter shows; blank = no filter */\n filterText: string\n /** While a filter text is set: open (`true`) or closed (`false`) choices made meanwhile, by item key. Ignored without a filter text. */\n filterOverrides: Readonly<Record<string, boolean>>\n /** Chosen on an item (a row click, Enter). */\n select: (item: TreeItem) => void\n}\n\n/** What the tree knows about one visible row. */\nexport interface TreeRow {\n /** The (filtered) item of the row. */\n item: TreeItem\n depth: number\n /** The item has (or may get) children and shows a chevron. */\n expandable: boolean\n open: boolean\n /** Open only because the filter text matches below it. */\n forcedOpen: boolean\n /** `[start, length]` of the filter text in the label when this row's title matches. */\n match: readonly [number, number] | null\n /** A composite kept only because a descendant is shown by the basket filter. */\n dimmed: boolean\n}\n\nexport interface TreeView {\n /** The items to render: the focus, the kind filters, the basket filter and the filter text applied. */\n items: TreeItem[]\n /** Per key of the items in `items`. */\n rows: ReadonlyMap<string, TreeRow>\n /** Keys of the open rows, for a host tree that wants a list. */\n open: string[]\n /** Every key the unfiltered tree has: what a stale key is measured against. */\n keys: ReadonlySet<string>\n /** Every item of the unfiltered tree by key, with its parent's key. */\n index: ReadonlyMap<string, IndexedItem>\n /** The unfiltered items from the top down to the focused one; empty without a (known) focus. */\n focusPath: TreeItem[]\n /** A kind filter of an existing item hides something. */\n hasKindFilters: boolean\n /** The store has no folder and no document. */\n isEmpty: boolean\n /** A filter text is set and nothing matches it. */\n noMatches: boolean\n}\n\nconst isOutlineItem = (item: TreeItem) => item.type === 'composite' || item.type === 'heading'\n\n/** The normalized filter text: trimmed and lower-cased; empty = no filter. */\nexport const filterQuery = (filterText: string) => filterText.trim().toLowerCase()\n\n/**\n * Keeps the items whose label contains `query` and the ancestors of such items; everything else goes, also below a\n * match. `matched` collects the keys of the matches, `below` those that have a match among their descendants.\n */\nfunction pruneByText(list: readonly TreeItem[], query: string, matched: Set<string>, below: Set<string>): TreeItem[] {\n return list.flatMap((item) => {\n const hit = item.label.toLowerCase().includes(query)\n const children = item.children ? pruneByText(item.children, query, matched, below) : []\n if (hit) matched.add(item.key)\n if (children.length) below.add(item.key)\n if (!hit && !children.length) return []\n return [{ ...item, children: children.length ? children : undefined }]\n })\n}\n\n/**\n * The tree to show. In the store's folders: the `Dokumente` root with folders and documents, the open document listing\n * its outline; in virtual mode: the open document as the root with its Bausteine. The kind filters (hidden kinds per\n * item) apply first (on the children of the focused item while a focus is set), then the basket filter (composites of\n * other baskets go unless a descendant stays; those ancestors are `dimmed`), then the filter text: only matching rows and\n * their ancestors stay, and the ancestors of a match show open (without being written to `expanded`) until the filter\n * text is cleared. A choice to open or close a row made meanwhile lives in `filterOverrides`.\n */\nexport function deriveTree(input: TreeInput): TreeView {\n const { tree, virtual, activeId, nodeFilters, select } = input\n const outline = outlineItems(input.outline.nodes, input.kinds, select)\n const unfiltered: TreeItem[] = virtual\n ? [virtualRootItem(input.documents.find(d => d.id === activeId)?.title ?? input.t('tree.rootFallback'), outline, select)]\n : tree ? [folderItem(tree, activeId, outline, select)] : []\n const index = indexItems(unfiltered, new Map())\n const keys = new Set(index.keys())\n\n // A focus lists the children of the focused item; the filters of the items on the way down still apply to them.\n const focusPath = input.focusKey !== null ? pathTo(index, input.focusKey) : []\n const focused = focusPath.at(-1)\n let items: TreeItem[]\n if (focused) {\n const inherited = new Set(focusPath.flatMap(item => nodeFilters[item.key] ?? []))\n items = applyNodeFilters(focused.children ?? [], nodeFilters, inherited)\n }\n else {\n items = applyNodeFilters(unfiltered, nodeFilters)\n }\n const dimmed = new Set<string>()\n if (input.basketFilter.length) items = applyBasketFilter(items, new Set(input.basketFilter), dimmed)\n const query = filterQuery(input.filterText)\n const matched = new Set<string>()\n const below = new Set<string>()\n if (query) items = pruneByText(items, query, matched, below)\n\n const expanded = new Set(input.expanded)\n const collapsed = new Set(input.collapsedOutline)\n const rows = new Map<string, TreeRow>()\n const open: string[] = []\n const walk = (list: readonly TreeItem[], depth: number) => {\n for (const item of list) {\n const expandable = item.type === 'root' || item.type === 'folder' || !!item.children?.length\n const stored = isOutlineItem(item) ? !collapsed.has(item.key) : expanded.has(item.key)\n const forced = below.has(item.key)\n const isOpen = expandable && ((query ? input.filterOverrides[item.key] : undefined) ?? (forced || stored))\n const at = matched.has(item.key) ? item.label.toLowerCase().indexOf(query) : -1\n rows.set(item.key, { item, depth, expandable, open: isOpen, forcedOpen: isOpen && forced && !stored, match: at >= 0 ? [at, query.length] : null, dimmed: dimmed.has(item.key) })\n if (isOpen) open.push(item.key)\n if (item.children) walk(item.children, depth + 1)\n }\n }\n walk(items, 0)\n\n return {\n items,\n rows,\n open,\n keys,\n index,\n focusPath,\n hasKindFilters: Object.entries(nodeFilters).some(([key, hidden]) => hidden.length > 0 && keys.has(key)),\n isEmpty: !virtual && !!tree && !tree.folders.length && !tree.documents.length,\n noMatches: !!query && items.length === 0 && (virtual || !!tree),\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree-rows.js","names":[],"sources":["../../src/tree/tree-rows.ts"],"sourcesContent":["import type { BlockType } from '../features/composites'\nimport type { Translate } from '../i18n'\nimport {\n applyBasketFilter,\n applyNodeFilters,\n folderItem,\n type IndexedItem,\n indexItems,\n type Outline,\n outlineItems,\n pathTo,\n type TreeItem,\n virtualRootItem,\n} from './tree-items'\nimport type { NodeFilters } from './tree-view-model'\nimport type { DocumentSummary, TreeFolder } from './types'\n\n// The visible rows of the document tree as one pure function of what the tree has loaded and what the user opened,\n// filtered and typed. No framework, no editor, no store.\n\n/** Everything `deriveTree` reads. */\nexport interface TreeInput {\n /** Words the root's label while the open document has no title in `documents`. */\n t: Translate\n /** `null` = loading failed, `undefined` = not loaded yet */\n tree: TreeFolder | null | undefined\n documents: readonly DocumentSummary[]\n activeId: string | undefined\n /** The open document is the root (virtual mode) instead of the store's folders. */\n virtual: boolean\n outline: Outline\n kinds: readonly BlockType[]\n /** Hidden kinds per item key */\n nodeFilters: NodeFilters\n /** The basket ids to show (`[]` = no basket filter): composites of other baskets without a visible descendant are hidden. */\n basketFilter: readonly string[]\n /** Key of the focused item: the tree then lists only its children. A key the tree no longer has is ignored. */\n focusKey: string | null\n /** Keys of the open store items (folders, documents, the roots) */\n expanded: readonly string[]\n /** Outline entries start open: only the closed ones are listed. */\n collapsedOutline: readonly string[]\n /** What the title filter shows; blank = no filter */\n filterText: string\n /** While a filter text is set: open (`true`) or closed (`false`) choices made meanwhile, by item key. Ignored without a filter text. */\n filterOverrides: Readonly<Record<string, boolean>>\n /** Chosen on an item (a row click, Enter). */\n select: (item: TreeItem) => void\n}\n\n/** What the tree knows about one visible row. */\nexport interface TreeRow {\n /** The (filtered) item of the row. */\n item: TreeItem\n depth: number\n /** The item has (or may get) children and shows a chevron. */\n expandable: boolean\n open: boolean\n /** Open only because the filter text matches below it. */\n forcedOpen: boolean\n /** `[start, length]` of the filter text in the label when this row's title matches. */\n match: readonly [number, number] | null\n /** A composite kept only because a descendant is shown by the basket filter. */\n dimmed: boolean\n}\n\nexport interface TreeView {\n /** The items to render: the focus, the kind filters, the basket filter and the filter text applied. */\n items: TreeItem[]\n /** Per key of the items in `items`. */\n rows: ReadonlyMap<string, TreeRow>\n /** Keys of the open rows, for a host tree that wants a list. */\n open: string[]\n /** Every key the unfiltered tree has: what a stale key is measured against. */\n keys: ReadonlySet<string>\n /** Every item of the unfiltered tree by key, with its parent's key. */\n index: ReadonlyMap<string, IndexedItem>\n /** The unfiltered items from the top down to the focused one; empty without a (known) focus. */\n focusPath: TreeItem[]\n /** A kind filter of an existing item hides something. */\n hasKindFilters: boolean\n /** The store has no folder and no document. */\n isEmpty: boolean\n /** A filter text is set and nothing matches it. */\n noMatches: boolean\n}\n\nconst isOutlineItem = (item: TreeItem) => item.type === 'typedBlock' || item.type === 'heading'\n\n/** The normalized filter text: trimmed and lower-cased; empty = no filter. */\nexport const filterQuery = (filterText: string) => filterText.trim().toLowerCase()\n\n/**\n * Keeps the items whose label contains `query` and the ancestors of such items; everything else goes, also below a\n * match. `matched` collects the keys of the matches, `below` those that have a match among their descendants.\n */\nfunction pruneByText(list: readonly TreeItem[], query: string, matched: Set<string>, below: Set<string>): TreeItem[] {\n return list.flatMap((item) => {\n const hit = item.label.toLowerCase().includes(query)\n const children = item.children ? pruneByText(item.children, query, matched, below) : []\n if (hit) matched.add(item.key)\n if (children.length) below.add(item.key)\n if (!hit && !children.length) return []\n return [{ ...item, children: children.length ? children : undefined }]\n })\n}\n\n/**\n * The tree to show. In the store's folders: the `Dokumente` root with folders and documents, the open document listing\n * its outline; in virtual mode: the open document as the root with its Typed blocks. The Block type filters (hidden Block types per\n * item) apply first (on the children of the focused item while a focus is set), then the basket filter (composites of\n * other baskets go unless a descendant stays; those ancestors are `dimmed`), then the filter text: only matching rows and\n * their ancestors stay, and the ancestors of a match show open (without being written to `expanded`) until the filter\n * text is cleared. A choice to open or close a row made meanwhile lives in `filterOverrides`.\n */\nexport function deriveTree(input: TreeInput): TreeView {\n const { tree, virtual, activeId, nodeFilters, select } = input\n const outline = outlineItems(input.outline.nodes, input.kinds, select)\n const unfiltered: TreeItem[] = virtual\n ? [virtualRootItem(input.documents.find(d => d.id === activeId)?.title ?? input.t('tree.rootFallback'), outline, select)]\n : tree ? [folderItem(tree, activeId, outline, select)] : []\n const index = indexItems(unfiltered, new Map())\n const keys = new Set(index.keys())\n\n // A focus lists the children of the focused item; the filters of the items on the way down still apply to them.\n const focusPath = input.focusKey !== null ? pathTo(index, input.focusKey) : []\n const focused = focusPath.at(-1)\n let items: TreeItem[]\n if (focused) {\n const inherited = new Set(focusPath.flatMap(item => nodeFilters[item.key] ?? []))\n items = applyNodeFilters(focused.children ?? [], nodeFilters, inherited)\n }\n else {\n items = applyNodeFilters(unfiltered, nodeFilters)\n }\n const dimmed = new Set<string>()\n if (input.basketFilter.length) items = applyBasketFilter(items, new Set(input.basketFilter), dimmed)\n const query = filterQuery(input.filterText)\n const matched = new Set<string>()\n const below = new Set<string>()\n if (query) items = pruneByText(items, query, matched, below)\n\n const expanded = new Set(input.expanded)\n const collapsed = new Set(input.collapsedOutline)\n const rows = new Map<string, TreeRow>()\n const open: string[] = []\n const walk = (list: readonly TreeItem[], depth: number) => {\n for (const item of list) {\n const expandable = item.type === 'root' || item.type === 'folder' || !!item.children?.length\n const stored = isOutlineItem(item) ? !collapsed.has(item.key) : expanded.has(item.key)\n const forced = below.has(item.key)\n const isOpen = expandable && ((query ? input.filterOverrides[item.key] : undefined) ?? (forced || stored))\n const at = matched.has(item.key) ? item.label.toLowerCase().indexOf(query) : -1\n rows.set(item.key, { item, depth, expandable, open: isOpen, forcedOpen: isOpen && forced && !stored, match: at >= 0 ? [at, query.length] : null, dimmed: dimmed.has(item.key) })\n if (isOpen) open.push(item.key)\n if (item.children) walk(item.children, depth + 1)\n }\n }\n walk(items, 0)\n\n return {\n items,\n rows,\n open,\n keys,\n index,\n focusPath,\n hasKindFilters: Object.entries(nodeFilters).some(([key, hidden]) => hidden.length > 0 && keys.has(key)),\n isEmpty: !virtual && !!tree && !tree.folders.length && !tree.documents.length,\n noMatches: !!query && items.length === 0 && (virtual || !!tree),\n }\n}\n"],"mappings":"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"}
@@ -7,7 +7,7 @@ export type NodeFilters = Record<string, string[]>;
7
7
  export interface TreeViewModel {
8
8
  /** The kinds hidden below each tree item, by item key. Persists in localStorage. Replace, never mutate. */
9
9
  nodeFilters: Store<NodeFilters>;
10
- /** The basket ids whose Bausteine the tree shows; `[]` = all of them. Persists in localStorage. Replace, never mutate. */
10
+ /** The basket ids whose Typed blocks the tree shows; `[]` = all of them. Persists in localStorage. Replace, never mutate. */
11
11
  basketFilter: Store<string[]>;
12
12
  /** Keys of the open tree items; lasts for the session. Replace, never mutate. */
13
13
  expanded: Store<string[]>;
@@ -17,7 +17,7 @@ export interface TreeViewModel {
17
17
  setKindHidden(key: string, kind: string, hidden: boolean): void;
18
18
  clearFilter(key: string): void;
19
19
  clearAllFilters(): void;
20
- /** Shows (`shown`) or stops showing the Bausteine of the basket. */
20
+ /** Shows (`shown`) or stops showing the Typed blocks of the basket. */
21
21
  setBasketShown(id: string, shown: boolean): void;
22
22
  clearBasketFilter(): void;
23
23
  /** Follows a folder moved from `from` to `to`: open folder items of it and below it get the new path. */
@@ -1 +1 @@
1
- {"version":3,"file":"tree-view-model.js","names":[],"sources":["../../src/tree/tree-view-model.ts"],"sourcesContent":["import type { EditorContext } from '../core/context'\nimport { createStore, type Store } from '../core/store'\nimport { FOLDER_KEY_PREFIX, folderKey, remapFolderPath } from './folder-paths'\n\nconst NODE_FILTERS_KEY = 'tip-tree:node-filters'\nconst BASKET_FILTER_KEY = 'tip-tree:basket-filter'\n\n/** Hidden kind ids per tree item key. */\nexport type NodeFilters = Record<string, string[]>\n\nfunction readStored<T>(key: string, fallback: T, isValid: (value: unknown) => value is T): T {\n try {\n const raw = localStorage.getItem(key)\n if (raw !== null) {\n const value: unknown = JSON.parse(raw)\n if (isValid(value)) return value\n }\n } catch { /* unavailable or corrupt storage: use the default */ }\n return fallback\n}\n\nfunction writeStored(key: string, value: unknown) {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch { /* storage full or blocked: the setting then lasts for this session only */ }\n}\n\nconst isNodeFilters = (value: unknown): value is NodeFilters =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n && Object.values(value).every(kinds => Array.isArray(kinds) && kinds.every(kind => typeof kind === 'string'))\n\nconst isStringList = (value: unknown): value is string[] => Array.isArray(value) && value.every(item => typeof item === 'string')\n\n/** The view state of the file browser; see `createTreeView`. */\nexport interface TreeViewModel {\n /** The kinds hidden below each tree item, by item key. Persists in localStorage. Replace, never mutate. */\n nodeFilters: Store<NodeFilters>\n /** The basket ids whose Bausteine the tree shows; `[]` = all of them. Persists in localStorage. Replace, never mutate. */\n basketFilter: Store<string[]>\n /** Keys of the open tree items; lasts for the session. Replace, never mutate. */\n expanded: Store<string[]>\n /** Opens the items (already open ones are left alone). */\n expand(keys: readonly string[]): void\n /** Hides (`hidden`) or shows `kind` below the item. */\n setKindHidden(key: string, kind: string, hidden: boolean): void\n clearFilter(key: string): void\n clearAllFilters(): void\n /** Shows (`shown`) or stops showing the Bausteine of the basket. */\n setBasketShown(id: string, shown: boolean): void\n clearBasketFilter(): void\n /** Follows a folder moved from `from` to `to`: open folder items of it and below it get the new path. */\n followFolderMove(from: string, to: string): void\n}\n\n/**\n * A view model of its own: `nodeFilters` is read from localStorage once and written back on every change (a model that\n * is dropped takes its subscription with it, there is nothing to dispose).\n */\nexport function createTreeView(): TreeViewModel {\n const nodeFilters = createStore<NodeFilters>('window' in globalThis ? readStored<NodeFilters>(NODE_FILTERS_KEY, {}, isNodeFilters) : {})\n nodeFilters.subscribe(value => writeStored(NODE_FILTERS_KEY, value))\n const basketFilter = createStore<string[]>('window' in globalThis ? readStored<string[]>(BASKET_FILTER_KEY, [], isStringList) : [])\n basketFilter.subscribe(value => writeStored(BASKET_FILTER_KEY, value))\n const expanded = createStore<string[]>([])\n return {\n nodeFilters,\n basketFilter,\n expanded,\n expand(keys) {\n const current = expanded.get()\n const missing = keys.filter(key => !current.includes(key))\n if (missing.length) expanded.set([...current, ...missing])\n },\n setKindHidden(key, kind, hidden) {\n const filters = nodeFilters.get()\n const rest = (filters[key] ?? []).filter(id => id !== kind)\n const { [key]: _previous, ...others } = filters\n nodeFilters.set(rest.length || hidden ? { ...others, [key]: hidden ? [...rest, kind] : rest } : others)\n },\n clearFilter(key) {\n const { [key]: _previous, ...others } = nodeFilters.get()\n nodeFilters.set(others)\n },\n setBasketShown(id, shown) {\n const current = basketFilter.get()\n if (current.includes(id) === shown) return\n basketFilter.set(shown ? [...current, id] : current.filter(other => other !== id))\n },\n clearBasketFilter() {\n if (basketFilter.get().length) basketFilter.set([])\n },\n clearAllFilters() {\n nodeFilters.set({})\n },\n followFolderMove(from, to) {\n expanded.set(expanded.get().map(key => (key.startsWith(FOLDER_KEY_PREFIX) ? folderKey(remapFolderPath(key.slice(FOLDER_KEY_PREFIX.length), from, to)) : key)))\n },\n }\n}\n\nconst views = new WeakMap<EditorContext, TreeViewModel>()\n\n/** The view model shared by every tree of one editor context (one app): created on first use, then cached. */\nexport function treeView(ctx: EditorContext): TreeViewModel {\n let view = views.get(ctx)\n if (!view) {\n view = createTreeView()\n views.set(ctx, view)\n }\n return view\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree-view-model.js","names":[],"sources":["../../src/tree/tree-view-model.ts"],"sourcesContent":["import type { EditorContext } from '../core/context'\nimport { createStore, type Store } from '../core/store'\nimport { FOLDER_KEY_PREFIX, folderKey, remapFolderPath } from './folder-paths'\n\nconst NODE_FILTERS_KEY = 'tip-tree:node-filters'\nconst BASKET_FILTER_KEY = 'tip-tree:basket-filter'\n\n/** Hidden kind ids per tree item key. */\nexport type NodeFilters = Record<string, string[]>\n\nfunction readStored<T>(key: string, fallback: T, isValid: (value: unknown) => value is T): T {\n try {\n const raw = localStorage.getItem(key)\n if (raw !== null) {\n const value: unknown = JSON.parse(raw)\n if (isValid(value)) return value\n }\n } catch { /* unavailable or corrupt storage: use the default */ }\n return fallback\n}\n\nfunction writeStored(key: string, value: unknown) {\n try {\n localStorage.setItem(key, JSON.stringify(value))\n } catch { /* storage full or blocked: the setting then lasts for this session only */ }\n}\n\nconst isNodeFilters = (value: unknown): value is NodeFilters =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n && Object.values(value).every(kinds => Array.isArray(kinds) && kinds.every(kind => typeof kind === 'string'))\n\nconst isStringList = (value: unknown): value is string[] => Array.isArray(value) && value.every(item => typeof item === 'string')\n\n/** The view state of the file browser; see `createTreeView`. */\nexport interface TreeViewModel {\n /** The kinds hidden below each tree item, by item key. Persists in localStorage. Replace, never mutate. */\n nodeFilters: Store<NodeFilters>\n /** The basket ids whose Typed blocks the tree shows; `[]` = all of them. Persists in localStorage. Replace, never mutate. */\n basketFilter: Store<string[]>\n /** Keys of the open tree items; lasts for the session. Replace, never mutate. */\n expanded: Store<string[]>\n /** Opens the items (already open ones are left alone). */\n expand(keys: readonly string[]): void\n /** Hides (`hidden`) or shows `kind` below the item. */\n setKindHidden(key: string, kind: string, hidden: boolean): void\n clearFilter(key: string): void\n clearAllFilters(): void\n /** Shows (`shown`) or stops showing the Typed blocks of the basket. */\n setBasketShown(id: string, shown: boolean): void\n clearBasketFilter(): void\n /** Follows a folder moved from `from` to `to`: open folder items of it and below it get the new path. */\n followFolderMove(from: string, to: string): void\n}\n\n/**\n * A view model of its own: `nodeFilters` is read from localStorage once and written back on every change (a model that\n * is dropped takes its subscription with it, there is nothing to dispose).\n */\nexport function createTreeView(): TreeViewModel {\n const nodeFilters = createStore<NodeFilters>('window' in globalThis ? readStored<NodeFilters>(NODE_FILTERS_KEY, {}, isNodeFilters) : {})\n nodeFilters.subscribe(value => writeStored(NODE_FILTERS_KEY, value))\n const basketFilter = createStore<string[]>('window' in globalThis ? readStored<string[]>(BASKET_FILTER_KEY, [], isStringList) : [])\n basketFilter.subscribe(value => writeStored(BASKET_FILTER_KEY, value))\n const expanded = createStore<string[]>([])\n return {\n nodeFilters,\n basketFilter,\n expanded,\n expand(keys) {\n const current = expanded.get()\n const missing = keys.filter(key => !current.includes(key))\n if (missing.length) expanded.set([...current, ...missing])\n },\n setKindHidden(key, kind, hidden) {\n const filters = nodeFilters.get()\n const rest = (filters[key] ?? []).filter(id => id !== kind)\n const { [key]: _previous, ...others } = filters\n nodeFilters.set(rest.length || hidden ? { ...others, [key]: hidden ? [...rest, kind] : rest } : others)\n },\n clearFilter(key) {\n const { [key]: _previous, ...others } = nodeFilters.get()\n nodeFilters.set(others)\n },\n setBasketShown(id, shown) {\n const current = basketFilter.get()\n if (current.includes(id) === shown) return\n basketFilter.set(shown ? [...current, id] : current.filter(other => other !== id))\n },\n clearBasketFilter() {\n if (basketFilter.get().length) basketFilter.set([])\n },\n clearAllFilters() {\n nodeFilters.set({})\n },\n followFolderMove(from, to) {\n expanded.set(expanded.get().map(key => (key.startsWith(FOLDER_KEY_PREFIX) ? folderKey(remapFolderPath(key.slice(FOLDER_KEY_PREFIX.length), from, to)) : key)))\n },\n }\n}\n\nconst views = new WeakMap<EditorContext, TreeViewModel>()\n\n/** The view model shared by every tree of one editor context (one app): created on first use, then cached. */\nexport function treeView(ctx: EditorContext): TreeViewModel {\n let view = views.get(ctx)\n if (!view) {\n view = createTreeView()\n views.set(ctx, view)\n }\n return view\n}\n"],"mappings":";;;AAIA,MAAM,mBAAmB;AACzB,MAAM,oBAAoB;AAK1B,SAAS,WAAc,KAAa,UAAa,SAA4C;CAC3F,IAAI;EACF,MAAM,MAAM,aAAa,QAAQ,GAAG;EACpC,IAAI,QAAQ,MAAM;GAChB,MAAM,QAAiB,KAAK,MAAM,GAAG;GACrC,IAAI,QAAQ,KAAK,GAAG,OAAO;EAC7B;CACF,QAAQ,CAAwD;CAChE,OAAO;AACT;AAEA,SAAS,YAAY,KAAa,OAAgB;CAChD,IAAI;EACF,aAAa,QAAQ,KAAK,KAAK,UAAU,KAAK,CAAC;CACjD,QAAQ,CAA8E;AACxF;AAEA,MAAM,iBAAiB,UACrB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK,KAChE,OAAO,OAAO,KAAK,CAAC,CAAC,OAAM,UAAS,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAM,SAAQ,OAAO,SAAS,QAAQ,CAAC;AAE9G,MAAM,gBAAgB,UAAsC,MAAM,QAAQ,KAAK,KAAK,MAAM,OAAM,SAAQ,OAAO,SAAS,QAAQ;;;;;AA2BhI,SAAgB,iBAAgC;CAC9C,MAAM,cAAc,YAAyB,YAAY,aAAa,WAAwB,kBAAkB,CAAC,GAAG,aAAa,IAAI,CAAC,CAAC;CACvI,YAAY,WAAU,UAAS,YAAY,kBAAkB,KAAK,CAAC;CACnE,MAAM,eAAe,YAAsB,YAAY,aAAa,WAAqB,mBAAmB,CAAC,GAAG,YAAY,IAAI,CAAC,CAAC;CAClI,aAAa,WAAU,UAAS,YAAY,mBAAmB,KAAK,CAAC;CACrE,MAAM,WAAW,YAAsB,CAAC,CAAC;CACzC,OAAO;EACL;EACA;EACA;EACA,OAAO,MAAM;GACX,MAAM,UAAU,SAAS,IAAI;GAC7B,MAAM,UAAU,KAAK,QAAO,QAAO,CAAC,QAAQ,SAAS,GAAG,CAAC;GACzD,IAAI,QAAQ,QAAQ,SAAS,IAAI,CAAC,GAAG,SAAS,GAAG,OAAO,CAAC;EAC3D;EACA,cAAc,KAAK,MAAM,QAAQ;GAC/B,MAAM,UAAU,YAAY,IAAI;GAChC,MAAM,QAAQ,QAAQ,QAAQ,CAAC,EAAA,CAAG,QAAO,OAAM,OAAO,IAAI;GAC1D,MAAM,GAAG,MAAM,WAAW,GAAG,WAAW;GACxC,YAAY,IAAI,KAAK,UAAU,SAAS;IAAE,GAAG;KAAS,MAAM,SAAS,CAAC,GAAG,MAAM,IAAI,IAAI;GAAK,IAAI,MAAM;EACxG;EACA,YAAY,KAAK;GACf,MAAM,GAAG,MAAM,WAAW,GAAG,WAAW,YAAY,IAAI;GACxD,YAAY,IAAI,MAAM;EACxB;EACA,eAAe,IAAI,OAAO;GACxB,MAAM,UAAU,aAAa,IAAI;GACjC,IAAI,QAAQ,SAAS,EAAE,MAAM,OAAO;GACpC,aAAa,IAAI,QAAQ,CAAC,GAAG,SAAS,EAAE,IAAI,QAAQ,QAAO,UAAS,UAAU,EAAE,CAAC;EACnF;EACA,oBAAoB;GAClB,IAAI,aAAa,IAAI,CAAC,CAAC,QAAQ,aAAa,IAAI,CAAC,CAAC;EACpD;EACA,kBAAkB;GAChB,YAAY,IAAI,CAAC,CAAC;EACpB;EACA,iBAAiB,MAAM,IAAI;GACzB,SAAS,IAAI,SAAS,IAAI,CAAC,CAAC,KAAI,QAAQ,IAAI,WAAA,SAA4B,IAAI,UAAU,gBAAgB,IAAI,MAAM,kBAAkB,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,GAAI,CAAC;EAC/J;CACF;AACF;AAEA,MAAM,wBAAQ,IAAI,QAAsC;;AAGxD,SAAgB,SAAS,KAAmC;CAC1D,IAAI,OAAO,MAAM,IAAI,GAAG;CACxB,IAAI,CAAC,MAAM;EACT,OAAO,eAAe;EACtB,MAAM,IAAI,KAAK,IAAI;CACrB;CACA,OAAO;AACT"}
@@ -13,7 +13,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
13
13
  abilities: {},
14
14
  extensions: {},
15
15
  blockActions: {},
16
- compositeKinds: {},
16
+ blockTypes: {},
17
17
  compositeBaskets: {},
18
18
  blockUi: {},
19
19
  coreContent: {},
@@ -66,7 +66,7 @@ const _sfc_main = /*@__PURE__*/ defineComponent({
66
66
  ai: props.ai,
67
67
  backend: props.backend ?? app.backend,
68
68
  collaboration: props.collaboration !== void 0,
69
- ...props.compositeKinds && { compositeKinds: props.compositeKinds },
69
+ ...props.blockTypes && { blockTypes: props.blockTypes },
70
70
  ...props.compositeBaskets && { compositeBaskets: props.compositeBaskets },
71
71
  ...props.blockUi && { blockUi: props.blockUi },
72
72
  ...props.coreContent && { coreContent: props.coreContent },
@@ -1 +1 @@
1
- {"version":3,"file":"AdvancedEditor.js","names":["_useModel","_openBlock","_createBlock","EditorSurface","_unref"],"sources":["../../src/vue/AdvancedEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AnyExtension, Editor, JSONContent } from '@tiptap/vue-3'\nimport { type Component, computed, useTemplateRef } from 'vue'\nimport EditorSurface from './components/EditorSurface.vue'\nimport type { CommandDef } from '../core/commands'\nimport type { AbilitiesOptions, BlockAction, BlockUiOptions } from '../core/extension-points'\nimport type { EditorBackend } from '../core/backend'\nimport type { CollaborationSession, EditorFeature } from '../core/feature'\nimport type { EditorMetadata, MetadataItem } from '../core/metadata-types'\nimport type { CoreContentOptions } from '../core/schema'\nimport type { Basket, CompositeKind } from '../features/composites'\nimport type { ContentLevel, FeatureId, InteractionLevel } from '../presets/compose'\nimport { useEditorContext } from './context'\nimport { composeEditor } from './compose'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n /** Collaborative mode: the Y.Doc is the document; `provider` adds remote carets, labelled with `user`. Fixed at mount. */\n collaboration?: CollaborationSession\n /** Standalone mode (without `collaboration`): TipTap JSON via `v-model`; the editor keeps its own undo history. */\n modelValue?: JSONContent\n /** Host lists (`mentions`, `hashtags`, `speakers`, custom); missing ones fall back to the features' built-in lists. */\n metadata?: EditorMetadata\n /**\n * Deep-merged into the `Abilities` defaults (`configure()`): `root` replaces `ROOT_ABILITIES`, `rules` add to or\n * override `DEFAULT_ABILITY_RULES` per type. Read once at setup.\n */\n abilities?: Partial<AbilitiesOptions>\n /** Added after the built-in extensions; read once at setup. */\n extensions?: AnyExtension[]\n /** Hover actions shown after the defaults (AI, convert, duplicate, delete, composite actions), on blocks with their `ability`. */\n blockActions?: BlockAction[]\n /** Composite kinds („Bausteine“) offered in the editor (default: `defaultCompositeKinds(t)`); read once at setup. */\n compositeKinds?: CompositeKind[]\n /** Colour baskets a Baustein can sit in (default: `defaultBaskets(t)`); read once at setup. */\n compositeBaskets?: Basket[]\n /** Which surfaces render block actions: the hover bar (default), the selected-block toolbar, `'both'` or `'none'` (`BlockUiOptions`); read once at setup. */\n blockUi?: BlockUiOptions\n /** Optional structures the content base drops from the schema: headings or heading levels, lists, blockquote, code block, rule (`CoreContentOptions`); read once at setup. */\n coreContent?: CoreContentOptions\n /** Document model: a level (`basic`, `rich`) or the content feature ids to install; read once at setup. */\n content?: ContentLevel | readonly FeatureId[]\n /** Editing UX: a level (`minimal`, `full`) or the interaction feature ids; `[]` = no interaction (a viewer); read once at setup. */\n interaction?: InteractionLevel | readonly FeatureId[]\n /** Installs the AI feature and the integrations whose content is present; read once at setup. */\n ai?: boolean\n /** Host features, appended after the catalog; read once at setup. */\n add?: readonly EditorFeature<Component>[]\n /** Features (catalog or host) left out, with the features that require them; read once at setup. */\n remove?: readonly FeatureId[]\n /** The backend the composition is pruned by (default: the editor context's backend); read once at setup. */\n backend?: EditorBackend\n /**\n * Builds the final commands (toolbar, `/` menu) from the default ones (incl. one per composite kind); absent = the\n * defaults. Host commands with an `ability` are enabled only where the caret has it, like the defaults. Read once at setup.\n */\n commands?: (defaults: CommandDef[]) => CommandDef[]\n /** Document whose package stores the uploads (`backend.assets`); standalone editors use the shared `scratch` owner. Read once at setup. */\n documentId?: string\n editable?: boolean\n /** `internal`: the editor owns its settings modal; `external`: it emits `settingsOpen` and the host shows `EditorSettingsPanel`/`Modal`. */\n settingsUi?: 'internal' | 'external'\n}>(), { editable: true, settingsUi: 'internal', content: 'rich', interaction: 'full', ai: true })\n\nconst emit = defineEmits<{\n 'ready': [editor: Editor]\n 'update:modelValue': [content: JSONContent]\n 'metadataCreate': [list: string, item: MetadataItem]\n /** The JSON handed in (initially or later) does not fit the advanced schema; the last valid document stays. */\n 'contentError': [error: Error]\n /** `settingsUi: 'external'`: the editor asks the host to open its settings (on `tab` when given). */\n 'settingsOpen': [tab?: string]\n}>()\n\n/** Whether this editor's AI sidebar is open (`toggleSidebar`, Mod-Shift-k): hosts bind it (`v-model:sidebar-open`) and show their `AiSidebar` beside the editor while it is true. */\nconst sidebarOpen = defineModel<boolean>('sidebarOpen', { default: false })\n/** Whether this editor's comments margin is open (`toggleComments`, Mod-Shift-m; margin layout of a collaborative editor): hosts bind it (`v-model:comments-open`) and show their `CommentsMargin` beside the text while it is true. Opening it closes the AI sidebar and vice versa. */\nconst commentsOpen = defineModel<boolean>('commentsOpen', { default: false })\n\n// The preset is fixed at setup like the kinds it is built from; hosts remount (`key`) to change it.\nconst app = useEditorContext()\nconst preset = composeEditor({\n content: props.content,\n interaction: props.interaction,\n ai: props.ai,\n backend: props.backend ?? app.backend,\n // A `collaboration` session is the host's own: `collab` and `comments` stay whatever the backend offers.\n collaboration: props.collaboration !== undefined,\n ...(props.compositeKinds && { compositeKinds: props.compositeKinds }),\n ...(props.compositeBaskets && { compositeBaskets: props.compositeBaskets }),\n ...(props.blockUi && { blockUi: props.blockUi }),\n ...(props.coreContent && { coreContent: props.coreContent }),\n ...(props.add && { add: props.add }),\n ...(props.remove && { remove: props.remove }),\n})\nconst surface = useTemplateRef<InstanceType<typeof EditorSurface>>('surface')\n\n/** `editor`: the surface's editor once mounted. `preset`: the composed preset (its `omitted` lists what the backend or `remove` dropped). */\ndefineExpose({ editor: computed(() => surface.value?.editor), preset })\n</script>\n\n<template>\n <EditorSurface\n ref=\"surface\"\n v-model:sidebar-open=\"sidebarOpen\"\n v-model:comments-open=\"commentsOpen\"\n :preset=\"preset\"\n :collaboration=\"props.collaboration\"\n :model-value=\"props.modelValue\"\n :metadata=\"props.metadata\"\n :abilities=\"props.abilities\"\n :extensions=\"props.extensions\"\n :block-actions=\"props.blockActions\"\n :commands=\"props.commands\"\n :document-id=\"props.documentId\"\n :editable=\"props.editable\"\n :settings-ui=\"props.settingsUi\"\n @ready=\"emit('ready', $event)\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @metadata-create=\"(list, item) => emit('metadataCreate', list, item)\"\n @content-error=\"emit('contentError', $event)\"\n @settings-open=\"emit('settingsOpen', $event)\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,QAAQ;EAgDd,MAAM,OAAO;;EAWb,MAAM,cAAcA,SAAoB,SAAC,aAAiC;;EAE1E,MAAM,eAAeA,SAAoB,SAAC,cAAkC;EAG5E,MAAM,MAAM,iBAAiB;EAC7B,MAAM,SAAS,cAAc;GAC3B,SAAS,MAAM;GACf,aAAa,MAAM;GACnB,IAAI,MAAM;GACV,SAAS,MAAM,WAAW,IAAI;GAE9B,eAAe,MAAM,kBAAkB,KAAA;GACvC,GAAI,MAAM,kBAAkB,EAAE,gBAAgB,MAAM,eAAe;GACnE,GAAI,MAAM,oBAAoB,EAAE,kBAAkB,MAAM,iBAAiB;GACzE,GAAI,MAAM,WAAW,EAAE,SAAS,MAAM,QAAQ;GAC9C,GAAI,MAAM,eAAe,EAAE,aAAa,MAAM,YAAY;GAC1D,GAAI,MAAM,OAAO,EAAE,KAAK,MAAM,IAAI;GAClC,GAAI,MAAM,UAAU,EAAE,QAAQ,MAAM,OAAO;EAC7C,CAAC;EACD,MAAM,UAAU,eAAmD,SAAS;;EAG5E,SAAa;GAAE,QAAQ,eAAe,QAAQ,OAAO,MAAM;GAAG;EAAO,CAAC;;GAIpE,OAAAC,UAAA,GAAAC,YAoBEC,aAAA;IAnBI,SAAA;IAAJ,KAAI;IACI,gBAAc,YAAA;IAAA,wBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,YAAW,QAAA;IACzB,iBAAe,aAAA;IAAA,yBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,aAAY,QAAA;IAClC,QAAQC,MAAA,MAAA;IACR,eAAe,MAAM;IACrB,eAAa,MAAM;IACnB,UAAU,MAAM;IAChB,WAAW,MAAM;IACjB,YAAY,MAAM;IAClB,iBAAe,MAAM;IACrB,UAAU,MAAM;IAChB,eAAa,MAAM;IACnB,UAAU,MAAM;IAChB,eAAa,MAAM;IACnB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAU,MAAM;IAC3B,uBAAkB,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,qBAAsB,MAAM;IACpD,kBAAe,OAAA,OAAA,OAAA,MAAG,MAAM,SAAS,KAAI,kBAAmB,MAAM,IAAI;IAClE,gBAAa,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,gBAAiB,MAAM;IAC1C,gBAAa,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,gBAAiB,MAAM"}
1
+ {"version":3,"file":"AdvancedEditor.js","names":["_useModel","_openBlock","_createBlock","EditorSurface","_unref"],"sources":["../../src/vue/AdvancedEditor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { AnyExtension, Editor, JSONContent } from '@tiptap/vue-3'\nimport { type Component, computed, useTemplateRef } from 'vue'\nimport EditorSurface from './components/EditorSurface.vue'\nimport type { CommandDef } from '../core/commands'\nimport type { AbilitiesOptions, BlockAction, BlockUiOptions } from '../core/extension-points'\nimport type { EditorBackend } from '../core/backend'\nimport type { CollaborationSession, EditorFeature } from '../core/feature'\nimport type { EditorMetadata, MetadataItem } from '../core/metadata-types'\nimport type { CoreContentOptions } from '../core/schema'\nimport type { Basket, BlockType } from '../features/composites'\nimport type { ContentLevel, FeatureId, InteractionLevel } from '../presets/compose'\nimport { useEditorContext } from './context'\nimport { composeEditor } from './compose'\n\ndefineOptions({ inheritAttrs: false })\n\nconst props = withDefaults(defineProps<{\n /** Collaborative mode: the Y.Doc is the document; `provider` adds remote carets, labelled with `user`. Fixed at mount. */\n collaboration?: CollaborationSession\n /** Standalone mode (without `collaboration`): TipTap JSON via `v-model`; the editor keeps its own undo history. */\n modelValue?: JSONContent\n /** Host lists (`mentions`, `hashtags`, `speakers`, custom); missing ones fall back to the features' built-in lists. */\n metadata?: EditorMetadata\n /**\n * Deep-merged into the `Abilities` defaults (`configure()`): `root` replaces `ROOT_ABILITIES`, `rules` add to or\n * override `DEFAULT_ABILITY_RULES` per type. Read once at setup.\n */\n abilities?: Partial<AbilitiesOptions>\n /** Added after the built-in extensions; read once at setup. */\n extensions?: AnyExtension[]\n /** Hover actions shown after the defaults (AI, convert, duplicate, delete, composite actions), on blocks with their `ability`. */\n blockActions?: BlockAction[]\n /** Block types offered in the editor (default: `defaultBlockTypes(t)`); read once at setup. */\n blockTypes?: BlockType[]\n /** Colour baskets a Typed block can sit in (default: `defaultBaskets(t)`); read once at setup. */\n compositeBaskets?: Basket[]\n /** Which surfaces render block actions: the hover bar (default), the selected-block toolbar, `'both'` or `'none'` (`BlockUiOptions`); read once at setup. */\n blockUi?: BlockUiOptions\n /** Optional structures the content base drops from the schema: headings or heading levels, lists, blockquote, code block, rule (`CoreContentOptions`); read once at setup. */\n coreContent?: CoreContentOptions\n /** Document model: a level (`basic`, `rich`) or the content feature ids to install; read once at setup. */\n content?: ContentLevel | readonly FeatureId[]\n /** Editing UX: a level (`minimal`, `full`) or the interaction feature ids; `[]` = no interaction (a viewer); read once at setup. */\n interaction?: InteractionLevel | readonly FeatureId[]\n /** Installs the AI feature and the integrations whose content is present; read once at setup. */\n ai?: boolean\n /** Host features, appended after the catalog; read once at setup. */\n add?: readonly EditorFeature<Component>[]\n /** Features (catalog or host) left out, with the features that require them; read once at setup. */\n remove?: readonly FeatureId[]\n /** The backend the composition is pruned by (default: the editor context's backend); read once at setup. */\n backend?: EditorBackend\n /**\n * Builds the final commands (toolbar, `/` menu) from the default ones (incl. one per Block type); absent = the\n * defaults. Host commands with an `ability` are enabled only where the caret has it, like the defaults. Read once at setup.\n */\n commands?: (defaults: CommandDef[]) => CommandDef[]\n /** Document whose package stores the uploads (`backend.assets`); standalone editors use the shared `scratch` owner. Read once at setup. */\n documentId?: string\n editable?: boolean\n /** `internal`: the editor owns its settings modal; `external`: it emits `settingsOpen` and the host shows `EditorSettingsPanel`/`Modal`. */\n settingsUi?: 'internal' | 'external'\n}>(), { editable: true, settingsUi: 'internal', content: 'rich', interaction: 'full', ai: true })\n\nconst emit = defineEmits<{\n 'ready': [editor: Editor]\n 'update:modelValue': [content: JSONContent]\n 'metadataCreate': [list: string, item: MetadataItem]\n /** The JSON handed in (initially or later) does not fit the advanced schema; the last valid document stays. */\n 'contentError': [error: Error]\n /** `settingsUi: 'external'`: the editor asks the host to open its settings (on `tab` when given). */\n 'settingsOpen': [tab?: string]\n}>()\n\n/** Whether this editor's AI sidebar is open (`toggleSidebar`, Mod-Shift-k): hosts bind it (`v-model:sidebar-open`) and show their `AiSidebar` beside the editor while it is true. */\nconst sidebarOpen = defineModel<boolean>('sidebarOpen', { default: false })\n/** Whether this editor's comments margin is open (`toggleComments`, Mod-Shift-m; margin layout of a collaborative editor): hosts bind it (`v-model:comments-open`) and show their `CommentsMargin` beside the text while it is true. Opening it closes the AI sidebar and vice versa. */\nconst commentsOpen = defineModel<boolean>('commentsOpen', { default: false })\n\n// The preset is fixed at setup like the Block types it is built from; hosts remount (`key`) to change it.\nconst app = useEditorContext()\nconst preset = composeEditor({\n content: props.content,\n interaction: props.interaction,\n ai: props.ai,\n backend: props.backend ?? app.backend,\n // A `collaboration` session is the host's own: `collab` and `comments` stay whatever the backend offers.\n collaboration: props.collaboration !== undefined,\n ...(props.blockTypes && { blockTypes: props.blockTypes }),\n ...(props.compositeBaskets && { compositeBaskets: props.compositeBaskets }),\n ...(props.blockUi && { blockUi: props.blockUi }),\n ...(props.coreContent && { coreContent: props.coreContent }),\n ...(props.add && { add: props.add }),\n ...(props.remove && { remove: props.remove }),\n})\nconst surface = useTemplateRef<InstanceType<typeof EditorSurface>>('surface')\n\n/** `editor`: the surface's editor once mounted. `preset`: the composed preset (its `omitted` lists what the backend or `remove` dropped). */\ndefineExpose({ editor: computed(() => surface.value?.editor), preset })\n</script>\n\n<template>\n <EditorSurface\n ref=\"surface\"\n v-model:sidebar-open=\"sidebarOpen\"\n v-model:comments-open=\"commentsOpen\"\n :preset=\"preset\"\n :collaboration=\"props.collaboration\"\n :model-value=\"props.modelValue\"\n :metadata=\"props.metadata\"\n :abilities=\"props.abilities\"\n :extensions=\"props.extensions\"\n :block-actions=\"props.blockActions\"\n :commands=\"props.commands\"\n :document-id=\"props.documentId\"\n :editable=\"props.editable\"\n :settings-ui=\"props.settingsUi\"\n @ready=\"emit('ready', $event)\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @metadata-create=\"(list, item) => emit('metadataCreate', list, item)\"\n @content-error=\"emit('contentError', $event)\"\n @settings-open=\"emit('settingsOpen', $event)\"\n />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiBA,MAAM,QAAQ;EAgDd,MAAM,OAAO;;EAWb,MAAM,cAAcA,SAAoB,SAAC,aAAiC;;EAE1E,MAAM,eAAeA,SAAoB,SAAC,cAAkC;EAG5E,MAAM,MAAM,iBAAiB;EAC7B,MAAM,SAAS,cAAc;GAC3B,SAAS,MAAM;GACf,aAAa,MAAM;GACnB,IAAI,MAAM;GACV,SAAS,MAAM,WAAW,IAAI;GAE9B,eAAe,MAAM,kBAAkB,KAAA;GACvC,GAAI,MAAM,cAAc,EAAE,YAAY,MAAM,WAAW;GACvD,GAAI,MAAM,oBAAoB,EAAE,kBAAkB,MAAM,iBAAiB;GACzE,GAAI,MAAM,WAAW,EAAE,SAAS,MAAM,QAAQ;GAC9C,GAAI,MAAM,eAAe,EAAE,aAAa,MAAM,YAAY;GAC1D,GAAI,MAAM,OAAO,EAAE,KAAK,MAAM,IAAI;GAClC,GAAI,MAAM,UAAU,EAAE,QAAQ,MAAM,OAAO;EAC7C,CAAC;EACD,MAAM,UAAU,eAAmD,SAAS;;EAG5E,SAAa;GAAE,QAAQ,eAAe,QAAQ,OAAO,MAAM;GAAG;EAAO,CAAC;;GAIpE,OAAAC,UAAA,GAAAC,YAoBEC,aAAA;IAnBI,SAAA;IAAJ,KAAI;IACI,gBAAc,YAAA;IAAA,wBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,YAAW,QAAA;IACzB,iBAAe,aAAA;IAAA,yBAAA,OAAA,OAAA,OAAA,MAAA,WAAA,aAAY,QAAA;IAClC,QAAQC,MAAA,MAAA;IACR,eAAe,MAAM;IACrB,eAAa,MAAM;IACnB,UAAU,MAAM;IAChB,WAAW,MAAM;IACjB,YAAY,MAAM;IAClB,iBAAe,MAAM;IACrB,UAAU,MAAM;IAChB,eAAa,MAAM;IACnB,UAAU,MAAM;IAChB,eAAa,MAAM;IACnB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAU,MAAM;IAC3B,uBAAkB,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,qBAAsB,MAAM;IACpD,kBAAe,OAAA,OAAA,OAAA,MAAG,MAAM,SAAS,KAAI,kBAAmB,MAAM,IAAI;IAClE,gBAAa,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,gBAAiB,MAAM;IAC1C,gBAAa,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,gBAAiB,MAAM"}
@@ -3,10 +3,10 @@ import { CommandDef } from "../core/command-types.js";
3
3
  import { AbilitiesOptions, BlockAction, BlockUiOptions } from "../core/extension-points.js";
4
4
  import { EditorMetadata, MetadataItem } from "../core/metadata-types.js";
5
5
  import { CollaborationSession, EditorFeature } from "../core/feature.js";
6
+ import { Basket } from "../features/composites/baskets.js";
7
+ import { BlockType } from "../features/composites/block-types.js";
6
8
  import { CoreContentOptions } from "../core/schema/index.js";
7
9
  import "../core/commands.js";
8
- import { CompositeKind } from "../features/composites/kinds.js";
9
- import { Basket } from "../features/composites/baskets.js";
10
10
  import "../features/composites/index.js";
11
11
  import { ComposedEditor, ContentLevel, FeatureId, InteractionLevel } from "../presets/compose.js";
12
12
  import "./advanced.js";
@@ -29,9 +29,9 @@ type __VLS_Props = {
29
29
  extensions?: AnyExtension[];
30
30
  /** Hover actions shown after the defaults (AI, convert, duplicate, delete, composite actions), on blocks with their `ability`. */
31
31
  blockActions?: BlockAction[];
32
- /** Composite kinds („Bausteine“) offered in the editor (default: `defaultCompositeKinds(t)`); read once at setup. */
33
- compositeKinds?: CompositeKind[];
34
- /** Colour baskets a Baustein can sit in (default: `defaultBaskets(t)`); read once at setup. */
32
+ /** Block types offered in the editor (default: `defaultBlockTypes(t)`); read once at setup. */
33
+ blockTypes?: BlockType[];
34
+ /** Colour baskets a Typed block can sit in (default: `defaultBaskets(t)`); read once at setup. */
35
35
  compositeBaskets?: Basket[];
36
36
  /** Which surfaces render block actions: the hover bar (default), the selected-block toolbar, `'both'` or `'none'` (`BlockUiOptions`); read once at setup. */
37
37
  blockUi?: BlockUiOptions;
@@ -50,7 +50,7 @@ type __VLS_Props = {
50
50
  /** The backend the composition is pruned by (default: the editor context's backend); read once at setup. */
51
51
  backend?: EditorBackend;
52
52
  /**
53
- * Builds the final commands (toolbar, `/` menu) from the default ones (incl. one per composite kind); absent = the
53
+ * Builds the final commands (toolbar, `/` menu) from the default ones (incl. one per Block type); absent = the
54
54
  * defaults. Host commands with an `ability` are enabled only where the caret has it, like the defaults. Read once at setup.
55
55
  */
56
56
  commands?: (defaults: CommandDef[]) => CommandDef[];
@@ -71,21 +71,21 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
71
71
  editor: import("vue").ComputedRef<Editor | undefined>;
72
72
  preset: ComposedEditor<Component>;
73
73
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
74
- settingsOpen: (tab?: string | undefined) => any;
75
74
  "update:sidebarOpen": (value: boolean) => any;
76
75
  "update:commentsOpen": (value: boolean) => any;
77
- "update:modelValue": (content: JSONContent) => any;
78
76
  ready: (editor: Editor) => any;
77
+ "update:modelValue": (content: JSONContent) => any;
79
78
  metadataCreate: (list: string, item: MetadataItem) => any;
80
79
  contentError: (error: Error) => any;
80
+ settingsOpen: (tab?: string | undefined) => any;
81
81
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
82
- onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
83
82
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
84
83
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
85
- "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
86
84
  onReady?: ((editor: Editor) => any) | undefined;
85
+ "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
87
86
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
88
87
  onContentError?: ((error: Error) => any) | undefined;
88
+ onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
89
89
  }>, {
90
90
  content: ContentLevel | readonly FeatureId[];
91
91
  ai: boolean;
@@ -41,21 +41,21 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
41
41
  editor: import("vue").ComputedRef<Editor | undefined>;
42
42
  preset: EditorPreset<Component>;
43
43
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
44
- settingsOpen: (tab?: string | undefined) => any;
45
44
  "update:sidebarOpen": (value: boolean) => any;
46
45
  "update:commentsOpen": (value: boolean) => any;
47
- "update:modelValue": (content: JSONContent) => any;
48
46
  ready: (editor: Editor) => any;
47
+ "update:modelValue": (content: JSONContent) => any;
49
48
  metadataCreate: (list: string, item: MetadataItem) => any;
50
49
  contentError: (error: Error) => any;
50
+ settingsOpen: (tab?: string | undefined) => any;
51
51
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
52
- onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
53
52
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
54
53
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
55
- "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
56
54
  onReady?: ((editor: Editor) => any) | undefined;
55
+ "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
57
56
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
58
57
  onContentError?: ((error: Error) => any) | undefined;
58
+ onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
59
59
  }>, {
60
60
  editable: boolean;
61
61
  settingsUi: "internal" | "external";
@@ -43,21 +43,21 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
43
43
  settingsOpen: import("vue").Ref<boolean, boolean>;
44
44
  settingsTab: import("vue").Ref<string | undefined, string | undefined>;
45
45
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
46
- settingsOpen: (tab?: string | undefined) => any;
47
46
  "update:sidebarOpen": (value: boolean) => any;
48
47
  "update:commentsOpen": (value: boolean) => any;
49
- "update:modelValue": (content: JSONContent) => any;
50
48
  ready: (editor: Editor) => any;
49
+ "update:modelValue": (content: JSONContent) => any;
51
50
  metadataCreate: (list: string, item: MetadataItem) => any;
52
51
  contentError: (error: Error) => any;
52
+ settingsOpen: (tab?: string | undefined) => any;
53
53
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
54
- onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
55
54
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
56
55
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
57
- "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
58
56
  onReady?: ((editor: Editor) => any) | undefined;
57
+ "onUpdate:modelValue"?: ((content: JSONContent) => any) | undefined;
59
58
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
60
59
  onContentError?: ((error: Error) => any) | undefined;
60
+ onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
61
61
  }>, {
62
62
  editable: boolean;
63
63
  settingsUi: "internal" | "external";
@@ -9,7 +9,7 @@ import { Component } from "vue";
9
9
  export declare const composeEditor: (options: ComposeOptions<Component>) => ComposedEditor<Component>;
10
10
  /**
11
11
  * The advanced editor on the Vue surface: `{ content: 'rich', interaction: 'full', ai: true }`, every dimension option
12
- * overridable (`compositeKinds`, `backend`, `add`, `remove`, ...). Collaboration is active only when a session is passed
12
+ * overridable (`blockTypes`, `backend`, `add`, `remove`, ...). Collaboration is active only when a session is passed
13
13
  * to the surface.
14
14
  */
15
15
  export declare const advancedEditor: (options?: Partial<ComposeOptions<Component>>) => ComposedEditor<Component>;
@@ -40,7 +40,7 @@ const VUE_BINDINGS = {
40
40
  const composeEditor = (options) => composeEditor$1(VUE_BINDINGS, options);
41
41
  /**
42
42
  * The advanced editor on the Vue surface: `{ content: 'rich', interaction: 'full', ai: true }`, every dimension option
43
- * overridable (`compositeKinds`, `backend`, `add`, `remove`, ...). Collaboration is active only when a session is passed
43
+ * overridable (`blockTypes`, `backend`, `add`, `remove`, ...). Collaboration is active only when a session is passed
44
44
  * to the surface.
45
45
  */
46
46
  const advancedEditor = (options = {}) => composeEditor({