@ecsplico/editor 3.5.1 → 4.0.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 (583) hide show
  1. package/CHANGELOG.md +71 -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 -7
  268. package/dist/features/composites/merge.js +39 -12
  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 +1 -1
  374. package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
  375. package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +1 -1
  376. package/dist/features/image-studio/components/ImageStudioView.js.map +1 -1
  377. package/dist/features/image-studio/feature.d.ts +1 -1
  378. package/dist/features/image-studio/feature.js +1 -1
  379. package/dist/features/image-studio/feature.js.map +1 -1
  380. package/dist/features/image-studio/node-core.d.ts +3 -3
  381. package/dist/features/image-studio/node-core.js +1 -1
  382. package/dist/features/image-studio/node-core.js.map +1 -1
  383. package/dist/features/image-studio/node-store.d.ts +1 -1
  384. package/dist/features/image-studio/node-store.js +1 -1
  385. package/dist/features/image-studio/node-store.js.map +1 -1
  386. package/dist/features/image-studio/react/ImageStudioDialog.d.ts +1 -1
  387. package/dist/features/image-studio/react/ImageStudioDialog.js +1 -1
  388. package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
  389. package/dist/features/image-studio/react/ImageStudioView.js +1 -1
  390. package/dist/features/image-studio/react/ImageStudioView.js.map +1 -1
  391. package/dist/features/image-studio/react/store.d.ts +3 -3
  392. package/dist/features/image-studio/react/store.js.map +1 -1
  393. package/dist/features/image-studio/react.d.ts +1 -1
  394. package/dist/features/image-studio/react.js +1 -1
  395. package/dist/features/image-studio/react.js.map +1 -1
  396. package/dist/features/image-studio/schema.d.ts +1 -1
  397. package/dist/features/image-studio/schema.js +1 -1
  398. package/dist/features/image-studio/schema.js.map +1 -1
  399. package/dist/features/image-studio/state.d.ts +3 -3
  400. package/dist/features/image-studio/state.js +2 -2
  401. package/dist/features/image-studio/state.js.map +1 -1
  402. package/dist/features/image-studio/store.d.ts +3 -3
  403. package/dist/features/image-studio/vue.d.ts +1 -1
  404. package/dist/features/image-studio/vue.js +1 -1
  405. package/dist/features/image-studio/vue.js.map +1 -1
  406. package/dist/features/media/index.js +1 -1
  407. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  408. package/dist/features/media/react.js +1 -1
  409. package/dist/features/mentions/tag.js +2 -1
  410. package/dist/features/mentions/tag.js.map +1 -1
  411. package/dist/features/themes/components/SettingsAppearanceTab.js +1 -1
  412. package/dist/features/themes/components/SettingsAppearanceTab.js.map +1 -1
  413. package/dist/features/themes/feature.d.ts +1 -1
  414. package/dist/features/themes/feature.js.map +1 -1
  415. package/dist/features/themes/react/SettingsAppearanceTab.d.ts +1 -1
  416. package/dist/features/themes/react/SettingsAppearanceTab.js +1 -1
  417. package/dist/features/themes/react/SettingsAppearanceTab.js.map +1 -1
  418. package/dist/features/themes/theme-runtime.js +1 -1
  419. package/dist/features/themes/theme-runtime.js.map +1 -1
  420. package/dist/features/transcript/TranscriptSegmentView.js +1 -1
  421. package/dist/features/transcript/TranscriptSegmentView.js.map +1 -1
  422. package/dist/features/transcript/react/TranscriptSegmentView.js +1 -1
  423. package/dist/features/transcript/react/TranscriptSegmentView.js.map +1 -1
  424. package/dist/features/transcript/segment-node.js.map +1 -1
  425. package/dist/features/transfer/feature.js +1 -1
  426. package/dist/features/transfer/feature.js.map +1 -1
  427. package/dist/features/transfer/transforms.d.ts +4 -4
  428. package/dist/features/transfer/transforms.js +12 -12
  429. package/dist/features/transfer/transforms.js.map +1 -1
  430. package/dist/i18n/de/ai.js +4 -4
  431. package/dist/i18n/de/ai.js.map +1 -1
  432. package/dist/i18n/de/authors.js +1 -1
  433. package/dist/i18n/de/authors.js.map +1 -1
  434. package/dist/i18n/de/comments.js +1 -1
  435. package/dist/i18n/de/comments.js.map +1 -1
  436. package/dist/i18n/de/composites.js +62 -59
  437. package/dist/i18n/de/composites.js.map +1 -1
  438. package/dist/i18n/de/image-studio.js +2 -2
  439. package/dist/i18n/de/image-studio.js.map +1 -1
  440. package/dist/i18n/de/integrations.js +20 -20
  441. package/dist/i18n/de/integrations.js.map +1 -1
  442. package/dist/i18n/de/markdown.js +1 -1
  443. package/dist/i18n/de/markdown.js.map +1 -1
  444. package/dist/i18n/de/palette.js +1 -1
  445. package/dist/i18n/de/palette.js.map +1 -1
  446. package/dist/i18n/de/themes.js +3 -3
  447. package/dist/i18n/de/themes.js.map +1 -1
  448. package/dist/i18n/de/transfer.js +2 -2
  449. package/dist/i18n/de/transfer.js.map +1 -1
  450. package/dist/i18n/de/tree.js +6 -6
  451. package/dist/i18n/de/tree.js.map +1 -1
  452. package/dist/i18n/de.d.ts +101 -98
  453. package/dist/i18n/en/ai.js +2 -2
  454. package/dist/i18n/en/ai.js.map +1 -1
  455. package/dist/i18n/en/composites.js +64 -61
  456. package/dist/i18n/en/composites.js.map +1 -1
  457. package/dist/i18n/en/integrations.js +9 -9
  458. package/dist/i18n/en/integrations.js.map +1 -1
  459. package/dist/i18n/en/markdown.js +1 -1
  460. package/dist/i18n/en/markdown.js.map +1 -1
  461. package/dist/i18n/en/palette.js +1 -1
  462. package/dist/i18n/en/palette.js.map +1 -1
  463. package/dist/i18n/en/themes.js +4 -4
  464. package/dist/i18n/en/themes.js.map +1 -1
  465. package/dist/i18n/en/tree.js +5 -5
  466. package/dist/i18n/en/tree.js.map +1 -1
  467. package/dist/index.d.ts +4 -1
  468. package/dist/integrations/composite-ai/bibliography-fetch.d.ts +6 -6
  469. package/dist/integrations/composite-ai/bibliography-fetch.js +19 -19
  470. package/dist/integrations/composite-ai/bibliography-fetch.js.map +1 -1
  471. package/dist/integrations/composite-ai/composite-fill.d.ts +4 -4
  472. package/dist/integrations/composite-ai/composite-fill.js +5 -5
  473. package/dist/integrations/composite-ai/composite-fill.js.map +1 -1
  474. package/dist/integrations/composite-ai/composite-summary.d.ts +2 -2
  475. package/dist/integrations/composite-ai/composite-summary.js +5 -5
  476. package/dist/integrations/composite-ai/composite-summary.js.map +1 -1
  477. package/dist/integrations/composite-ai/derive.d.ts +17 -17
  478. package/dist/integrations/composite-ai/derive.js +27 -26
  479. package/dist/integrations/composite-ai/derive.js.map +1 -1
  480. package/dist/integrations/composite-ai/index.d.ts +14 -15
  481. package/dist/integrations/composite-ai/index.js +98 -77
  482. package/dist/integrations/composite-ai/index.js.map +1 -1
  483. package/dist/integrations/composite-ai/outline-sanitize.d.ts +1 -1
  484. package/dist/integrations/composite-ai/outline-sanitize.js +1 -1
  485. package/dist/integrations/composite-ai/outline-sanitize.js.map +1 -1
  486. package/dist/integrations/composite-ai/rendition.d.ts +9 -9
  487. package/dist/integrations/composite-ai/rendition.js +27 -27
  488. package/dist/integrations/composite-ai/rendition.js.map +1 -1
  489. package/dist/integrations/composite-ai/split.d.ts +8 -8
  490. package/dist/integrations/composite-ai/split.js +12 -12
  491. package/dist/integrations/composite-ai/split.js.map +1 -1
  492. package/dist/integrations/composite-ai/transfer-transforms.d.ts +2 -2
  493. package/dist/integrations/composite-ai/transfer-transforms.js +12 -12
  494. package/dist/integrations/composite-ai/transfer-transforms.js.map +1 -1
  495. package/dist/integrations/composite-media/index.d.ts +4 -3
  496. package/dist/integrations/composite-media/index.js +20 -14
  497. package/dist/integrations/composite-media/index.js.map +1 -1
  498. package/dist/markdown/MarkdownSurface.vue.d.ts +7 -7
  499. package/dist/markdown/document.js +1 -1
  500. package/dist/markdown/document.js.map +1 -1
  501. package/dist/nuxt/module.d.ts +30 -24
  502. package/dist/nuxt/module.js.map +1 -1
  503. package/dist/nuxt/runtime/server/plugins/editor-server.js +3 -2
  504. package/dist/nuxt/runtime/server/plugins/editor-server.js.map +1 -1
  505. package/dist/presets/compose.d.ts +6 -6
  506. package/dist/presets/compose.js +8 -5
  507. package/dist/presets/compose.js.map +1 -1
  508. package/dist/react/AdvancedEditor.d.ts +2 -2
  509. package/dist/react/AdvancedEditor.js +1 -1
  510. package/dist/react/AdvancedEditor.js.map +1 -1
  511. package/dist/react/compose.d.ts +1 -1
  512. package/dist/react/compose.js +2 -2
  513. package/dist/react/compose.js.map +1 -1
  514. package/dist/react/composed-surface.d.ts +5 -5
  515. package/dist/react/composed-surface.js +2 -2
  516. package/dist/react/composed-surface.js.map +1 -1
  517. package/dist/server/ai.d.ts +7 -7
  518. package/dist/server/ai.js +1 -1
  519. package/dist/server/ai.js.map +1 -1
  520. package/dist/server/auth.d.ts +1 -1
  521. package/dist/server/collab-state.d.ts +1 -1
  522. package/dist/server/collab-state.js.map +1 -1
  523. package/dist/server/collab.d.ts +4 -4
  524. package/dist/server/collab.js +22 -17
  525. package/dist/server/collab.js.map +1 -1
  526. package/dist/server/handlers/ai.d.ts +9 -6
  527. package/dist/server/handlers/ai.js +13 -17
  528. package/dist/server/handlers/ai.js.map +1 -1
  529. package/dist/server/handlers/context.d.ts +4 -0
  530. package/dist/server/handlers/context.js.map +1 -1
  531. package/dist/server/handlers/editor.d.ts +33 -32
  532. package/dist/server/handlers/editor.js +13 -8
  533. package/dist/server/handlers/editor.js.map +1 -1
  534. package/dist/server/handlers/images.d.ts +1 -1
  535. package/dist/server/handlers/images.js +1 -1
  536. package/dist/server/handlers/images.js.map +1 -1
  537. package/dist/server/host.d.ts +4 -0
  538. package/dist/server/host.js +10 -2
  539. package/dist/server/host.js.map +1 -1
  540. package/dist/server/index.d.ts +3 -3
  541. package/dist/server/ports.d.ts +8 -8
  542. package/dist/server/ports.js.map +1 -1
  543. package/dist/settings/index.d.ts +20 -19
  544. package/dist/settings/index.js +25 -24
  545. package/dist/settings/index.js.map +1 -1
  546. package/dist/settings/migrate.d.ts +18 -0
  547. package/dist/settings/migrate.js +46 -0
  548. package/dist/settings/migrate.js.map +1 -0
  549. package/dist/settings/values.d.ts +12 -12
  550. package/dist/settings/values.js +11 -11
  551. package/dist/settings/values.js.map +1 -1
  552. package/dist/styles/composites.css +10 -10
  553. package/dist/tree/DocumentTree.js +12 -5
  554. package/dist/tree/DocumentTree.js.map +1 -1
  555. package/dist/tree/drop-rules.js +5 -5
  556. package/dist/tree/drop-rules.js.map +1 -1
  557. package/dist/tree/react/DocumentTree.js +14 -5
  558. package/dist/tree/react/DocumentTree.js.map +1 -1
  559. package/dist/tree/tree-host.js +6 -6
  560. package/dist/tree/tree-host.js.map +1 -1
  561. package/dist/tree/tree-items.js +34 -28
  562. package/dist/tree/tree-items.js.map +1 -1
  563. package/dist/tree/tree-model.js +16 -16
  564. package/dist/tree/tree-model.js.map +1 -1
  565. package/dist/tree/tree-rows.js +2 -2
  566. package/dist/tree/tree-rows.js.map +1 -1
  567. package/dist/tree/tree-view-model.d.ts +2 -2
  568. package/dist/tree/tree-view-model.js.map +1 -1
  569. package/dist/vue/AdvancedEditor.js +2 -2
  570. package/dist/vue/AdvancedEditor.js.map +1 -1
  571. package/dist/vue/AdvancedEditor.vue.d.ts +10 -10
  572. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  573. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  574. package/dist/vue/compose.d.ts +1 -1
  575. package/dist/vue/compose.js +2 -2
  576. package/dist/vue/compose.js.map +1 -1
  577. package/package.json +1 -1
  578. package/dist/features/composites/derivation.d.ts +0 -62
  579. package/dist/features/composites/derivation.js +0 -102
  580. package/dist/features/composites/derivation.js.map +0 -1
  581. package/dist/features/composites/kinds.d.ts +0 -83
  582. package/dist/features/composites/kinds.js +0 -285
  583. package/dist/features/composites/kinds.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  import { bibtexOf, cslOf, cslTypeOptions } from "../bibliography.js";
2
+ import { propertyHostOf, setBlockProperty } from "../properties.js";
2
3
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
3
4
  import { Icon } from "../../../react/Icon.js";
4
5
  import { Button } from "../../../react/ui/button.js";
5
6
  import { Input } from "../../../react/ui/input.js";
6
7
  import { Textarea } from "../../../react/ui/textarea.js";
7
8
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
8
- import { compositeOfRow, setCompositeMetaField } from "../rows.js";
9
9
  import { bibFormOf, bibItemOf } from "../bibliography-form.js";
10
10
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
11
11
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -51,7 +51,7 @@ const LINES = [
51
51
  /**
52
52
  * The structured editor of a `bibliography` field (CSL-JSON item, `meta.bib`): type, authors, year, container, volume,
53
53
  * issue, pages, publisher, DOI, ISBN, URL and abstract. Inputs keep a local draft; every commit (blur, Enter, choosing
54
- * a type, unmount, another row) writes the whole item through `setCompositeMetaField`. The title is the Baustein's and
54
+ * a type, unmount, another row) writes the whole item through `setBlockProperty`. The title is the Typed block's and
55
55
  * never stored.
56
56
  */
57
57
  function BibliographyEditor({ editor, row, field, disabled }) {
@@ -87,7 +87,7 @@ function BibliographyEditor({ editor, row, field, disabled }) {
87
87
  if (!dirty.current) return;
88
88
  dirty.current = false;
89
89
  const current = target.current;
90
- if (!current.editor.isDestroyed) setCompositeMetaField(current.editor, current.row, current.field.key, bibItemOf(formRef.current, current.stored));
90
+ if (!current.editor.isDestroyed) setBlockProperty(current.editor, current.row, current.field.key, bibItemOf(formRef.current, current.stored));
91
91
  }, []);
92
92
  useEffect(() => commit, [
93
93
  commit,
@@ -114,7 +114,7 @@ function BibliographyEditor({ editor, row, field, disabled }) {
114
114
  }
115
115
  async function copyBibtex() {
116
116
  commit();
117
- const node = compositeOfRow(editor.state.doc, row)?.node;
117
+ const node = propertyHostOf(editor.state.doc, row)?.node;
118
118
  const csl = node && cslOf(node);
119
119
  if (!csl) return;
120
120
  await navigator.clipboard.writeText(bibtexOf(csl));
@@ -124,7 +124,7 @@ function BibliographyEditor({ editor, row, field, disabled }) {
124
124
  const hasDoi = form.doi.trim() !== "" || typeof row.meta.doi === "string" && row.meta.doi.trim() !== "";
125
125
  function fetchByDoi() {
126
126
  commit();
127
- const found = compositeOfRow(editor.state.doc, row);
127
+ const found = propertyHostOf(editor.state.doc, row);
128
128
  if (found) editor.commands.fetchCompositeBibliography(found.pos);
129
129
  }
130
130
  const typeOptions = useMemo(() => cslTypeOptions(t), [t]);
@@ -1 +1 @@
1
- {"version":3,"file":"BibliographyEditor.js","names":[],"sources":["../../../../src/features/composites/react/BibliographyEditor.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Button } from '../../../react/ui/button'\nimport { Input } from '../../../react/ui/input'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { Textarea } from '../../../react/ui/textarea'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { bibtexOf, type CslItem, type CslType, cslOf, cslTypeOptions } from '../bibliography'\nimport { type BibForm, bibFormOf, bibItemOf } from '../bibliography-form'\nimport type { CompositeMetaField } from '../kinds'\nimport { compositeOfRow, type CompositeRow, setCompositeMetaField } from '../rows'\nimport '../bibliography-command'\n\nconst INPUT_CLASS = 'h-6 w-full px-2 text-xs md:text-xs'\nconst TEXTAREA_CLASS = 'max-h-[8.5rem] min-h-0 w-full px-2 py-1 text-xs md:text-xs'\n\nconst COUNTERS = [\n { key: 'volume', labelKey: 'composites.bib.field.volume' },\n { key: 'issue', labelKey: 'composites.bib.field.issue' },\n { key: 'page', labelKey: 'composites.bib.field.page' },\n] as const\nconst LINES = [\n { key: 'containerTitle', labelKey: 'composites.bib.field.containerTitle' },\n { key: 'publisher', labelKey: 'composites.bib.field.publisher' },\n { key: 'doi', labelKey: 'composites.bib.field.doi' },\n { key: 'isbn', labelKey: 'composites.bib.field.isbn' },\n { key: 'url', labelKey: 'composites.bib.field.url' },\n] as const\n\n/**\n * The structured editor of a `bibliography` field (CSL-JSON item, `meta.bib`): type, authors, year, container, volume,\n * issue, pages, publisher, DOI, ISBN, URL and abstract. Inputs keep a local draft; every commit (blur, Enter, choosing\n * a type, unmount, another row) writes the whole item through `setCompositeMetaField`. The title is the Baustein's and\n * never stored.\n */\nexport function BibliographyEditor({ editor, row, field, disabled }: {\n editor: Editor\n row: CompositeRow\n field: CompositeMetaField\n disabled?: boolean\n}) {\n const { t } = useEditorI18n()\n const value = row.meta[field.key] as Partial<CslItem> | null | undefined\n const stored = value && typeof value === 'object' && typeof value.type === 'string' ? value as CslItem : null\n const [form, setForm] = useState<BibForm>(() => bibFormOf(stored))\n const formRef = useRef(form)\n const dirty = useRef(false)\n const [copied, setCopied] = useState(false)\n // The latest props for the commit on unmount; updated after every render, so the cleanup of a changed `row.key` still sees the previous row.\n const target = useRef({ editor, row, field, stored })\n useEffect(() => {\n target.current = { editor, row, field, stored }\n })\n\n useEffect(() => {\n if (!dirty.current) {\n const next = bibFormOf(stored)\n formRef.current = next\n setForm(next)\n }\n }, [stored, row.key])\n\n const commit = useCallback(() => {\n if (!dirty.current) return\n dirty.current = false\n const current = target.current\n if (!current.editor.isDestroyed) setCompositeMetaField(current.editor, current.row, current.field.key, bibItemOf(formRef.current, current.stored))\n }, [])\n\n // Flush on unmount and when the editor is bound to another row.\n useEffect(() => commit, [commit, editor, row.key, field.key])\n\n useEffect(() => {\n if (!copied) return\n const timer = window.setTimeout(() => setCopied(false), 1500)\n return () => window.clearTimeout(timer)\n }, [copied])\n\n function onInput<K extends keyof BibForm>(key: K, next: BibForm[K]) {\n formRef.current = { ...formRef.current, [key]: next }\n setForm(formRef.current)\n dirty.current = true\n }\n\n function onType(next: string) {\n onInput('type', next as CslType)\n commit()\n }\n\n async function copyBibtex() {\n commit()\n const node = compositeOfRow(editor.state.doc, row)?.node\n const csl = node && cslOf(node)\n if (!csl) return\n await navigator.clipboard.writeText(bibtexOf(csl))\n setCopied(true)\n }\n\n // Registered by the AI integration (`composite-ai`); without it there is nothing to fetch with.\n const canFetch = typeof editor.commands.fetchCompositeBibliography === 'function'\n const hasDoi = form.doi.trim() !== '' || (typeof row.meta.doi === 'string' && row.meta.doi.trim() !== '')\n\n function fetchByDoi() {\n commit()\n const found = compositeOfRow(editor.state.doc, row)\n if (found) editor.commands.fetchCompositeBibliography(found.pos)\n }\n\n const typeOptions = useMemo(() => cslTypeOptions(t), [t])\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <Select value={form.type} onValueChange={onType} disabled={disabled}>\n <SelectTrigger size=\"sm\" className=\"w-full text-xs data-[size=sm]:h-6\" aria-label={t('composites.bib.field.type')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {typeOptions.map(option => (\n <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Textarea\n value={form.authors}\n placeholder={t('composites.bib.field.authorsHelp')}\n aria-label={t('composites.bib.field.authors')}\n disabled={disabled}\n rows={2}\n className={TEXTAREA_CLASS}\n onBlur={commit}\n onChange={event => onInput('authors', event.target.value)}\n />\n <div className=\"grid grid-cols-4 gap-1.5\">\n <Input\n value={form.year}\n type=\"number\"\n placeholder={t('composites.bib.field.year')}\n aria-label={t('composites.bib.field.year')}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput('year', event.target.value)}\n />\n {COUNTERS.map(input => (\n <Input\n key={input.key}\n value={form[input.key]}\n placeholder={t(input.labelKey)}\n aria-label={t(input.labelKey)}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput(input.key, event.target.value)}\n />\n ))}\n </div>\n {LINES.map(input => (\n <Input\n key={input.key}\n value={form[input.key]}\n placeholder={t(input.labelKey)}\n aria-label={t(input.labelKey)}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput(input.key, event.target.value)}\n />\n ))}\n <Textarea\n value={form.abstract}\n placeholder={t('composites.bib.field.abstract')}\n aria-label={t('composites.bib.field.abstract')}\n disabled={disabled}\n rows={2}\n className={TEXTAREA_CLASS}\n onBlur={commit}\n onChange={event => onInput('abstract', event.target.value)}\n />\n <div className=\"flex justify-end gap-1.5\">\n {canFetch && (\n <Button size=\"xs\" variant=\"ghost\" disabled={disabled || !hasDoi} onClick={fetchByDoi}>\n <Icon name=\"i-lucide-book-marked\" />\n {t('composites.bib.fetchDoi')}\n </Button>\n )}\n <Button size=\"xs\" variant=\"ghost\" disabled={!stored} onClick={() => void copyBibtex()}>\n <Icon name=\"i-lucide-copy\" />\n {copied ? t('composites.bib.copied') : t('composites.bib.copyBibtex')}\n </Button>\n </div>\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;AAcA,MAAM,cAAc;AACpB,MAAM,iBAAiB;AAEvB,MAAM,WAAW;CACf;EAAE,KAAK;EAAU,UAAU;CAA8B;CACzD;EAAE,KAAK;EAAS,UAAU;CAA6B;CACvD;EAAE,KAAK;EAAQ,UAAU;CAA4B;AACvD;AACA,MAAM,QAAQ;CACZ;EAAE,KAAK;EAAkB,UAAU;CAAsC;CACzE;EAAE,KAAK;EAAa,UAAU;CAAiC;CAC/D;EAAE,KAAK;EAAO,UAAU;CAA2B;CACnD;EAAE,KAAK;EAAQ,UAAU;CAA4B;CACrD;EAAE,KAAK;EAAO,UAAU;CAA2B;AACrD;;;;;;;AAQA,SAAgB,mBAAmB,EAAE,QAAQ,KAAK,OAAO,YAKtD;CACD,MAAM,EAAE,MAAM,cAAc;CAC5B,MAAM,QAAQ,IAAI,KAAK,MAAM;CAC7B,MAAM,SAAS,SAAS,OAAO,UAAU,YAAY,OAAO,MAAM,SAAS,WAAW,QAAmB;CACzG,MAAM,CAAC,MAAM,WAAW,eAAwB,UAAU,MAAM,CAAC;CACjE,MAAM,UAAU,OAAO,IAAI;CAC3B,MAAM,QAAQ,OAAO,KAAK;CAC1B,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK;CAE1C,MAAM,SAAS,OAAO;EAAE;EAAQ;EAAK;EAAO;CAAO,CAAC;CACpD,gBAAgB;EACd,OAAO,UAAU;GAAE;GAAQ;GAAK;GAAO;EAAO;CAChD,CAAC;CAED,gBAAgB;EACd,IAAI,CAAC,MAAM,SAAS;GAClB,MAAM,OAAO,UAAU,MAAM;GAC7B,QAAQ,UAAU;GAClB,QAAQ,IAAI;EACd;CACF,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC;CAEpB,MAAM,SAAS,kBAAkB;EAC/B,IAAI,CAAC,MAAM,SAAS;EACpB,MAAM,UAAU;EAChB,MAAM,UAAU,OAAO;EACvB,IAAI,CAAC,QAAQ,OAAO,aAAa,sBAAsB,QAAQ,QAAQ,QAAQ,KAAK,QAAQ,MAAM,KAAK,UAAU,QAAQ,SAAS,QAAQ,MAAM,CAAC;CACnJ,GAAG,CAAC,CAAC;CAGL,gBAAgB,QAAQ;EAAC;EAAQ;EAAQ,IAAI;EAAK,MAAM;CAAG,CAAC;CAE5D,gBAAgB;EACd,IAAI,CAAC,QAAQ;EACb,MAAM,QAAQ,OAAO,iBAAiB,UAAU,KAAK,GAAG,IAAI;EAC5D,aAAa,OAAO,aAAa,KAAK;CACxC,GAAG,CAAC,MAAM,CAAC;CAEX,SAAS,QAAiC,KAAQ,MAAkB;EAClE,QAAQ,UAAU;GAAE,GAAG,QAAQ;IAAU,MAAM;EAAK;EACpD,QAAQ,QAAQ,OAAO;EACvB,MAAM,UAAU;CAClB;CAEA,SAAS,OAAO,MAAc;EAC5B,QAAQ,QAAQ,IAAe;EAC/B,OAAO;CACT;CAEA,eAAe,aAAa;EAC1B,OAAO;EACP,MAAM,OAAO,eAAe,OAAO,MAAM,KAAK,GAAG,CAAC,EAAE;EACpD,MAAM,MAAM,QAAQ,MAAM,IAAI;EAC9B,IAAI,CAAC,KAAK;EACV,MAAM,UAAU,UAAU,UAAU,SAAS,GAAG,CAAC;EACjD,UAAU,IAAI;CAChB;CAGA,MAAM,WAAW,OAAO,OAAO,SAAS,+BAA+B;CACvE,MAAM,SAAS,KAAK,IAAI,KAAK,MAAM,MAAO,OAAO,IAAI,KAAK,QAAQ,YAAY,IAAI,KAAK,IAAI,KAAK,MAAM;CAEtG,SAAS,aAAa;EACpB,OAAO;EACP,MAAM,QAAQ,eAAe,OAAO,MAAM,KAAK,GAAG;EAClD,IAAI,OAAO,OAAO,SAAS,2BAA2B,MAAM,GAAG;CACjE;CAEA,MAAM,cAAc,cAAc,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;CAExD,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,qBAAC,QAAD;IAAQ,OAAO,KAAK;IAAM,eAAe;IAAkB;IAA3D,UAAA,CACE,oBAAC,eAAD;KAAe,MAAK;KAAK,WAAU;KAAoC,cAAY,EAAE,2BAA2B;KAC9G,UAAA,oBAAC,aAAD,CAAc,CAAA;IACD,CAAA,GACf,oBAAC,eAAD,EAAA,UACG,YAAY,KAAI,WACf,oBAAC,YAAD;KAA+B,OAAO,OAAO;KAAQ,UAAA,OAAO;IAAkB,GAA7D,OAAO,KAAsD,CAC/E,EACY,CAAA,CACT;;GACR,oBAAC,UAAD;IACE,OAAO,KAAK;IACZ,aAAa,EAAE,kCAAkC;IACjD,cAAY,EAAE,8BAA8B;IAClC;IACV,MAAM;IACN,WAAW;IACX,QAAQ;IACR,WAAU,UAAS,QAAQ,WAAW,MAAM,OAAO,KAAK;GACzD,CAAA;GACD,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,OAAD;KACE,OAAO,KAAK;KACZ,MAAK;KACL,aAAa,EAAE,2BAA2B;KAC1C,cAAY,EAAE,2BAA2B;KAC/B;KACV,WAAW;KACX,QAAQ;KACR,YAAY,UAAU;MACpB,IAAI,MAAM,QAAQ,SAAS,OAAO;KACpC;KACA,WAAU,UAAS,QAAQ,QAAQ,MAAM,OAAO,KAAK;IACtD,CAAA,GACA,SAAS,KAAI,UACZ,oBAAC,OAAD;KAEE,OAAO,KAAK,MAAM;KAClB,aAAa,EAAE,MAAM,QAAQ;KAC7B,cAAY,EAAE,MAAM,QAAQ;KAClB;KACV,WAAW;KACX,QAAQ;KACR,YAAY,UAAU;MACpB,IAAI,MAAM,QAAQ,SAAS,OAAO;KACpC;KACA,WAAU,UAAS,QAAQ,MAAM,KAAK,MAAM,OAAO,KAAK;IACzD,GAXM,MAAM,GAWZ,CACF,CACE;;GACJ,MAAM,KAAI,UACT,oBAAC,OAAD;IAEE,OAAO,KAAK,MAAM;IAClB,aAAa,EAAE,MAAM,QAAQ;IAC7B,cAAY,EAAE,MAAM,QAAQ;IAClB;IACV,WAAW;IACX,QAAQ;IACR,YAAY,UAAU;KACpB,IAAI,MAAM,QAAQ,SAAS,OAAO;IACpC;IACA,WAAU,UAAS,QAAQ,MAAM,KAAK,MAAM,OAAO,KAAK;GACzD,GAXM,MAAM,GAWZ,CACF;GACD,oBAAC,UAAD;IACE,OAAO,KAAK;IACZ,aAAa,EAAE,+BAA+B;IAC9C,cAAY,EAAE,+BAA+B;IACnC;IACV,MAAM;IACN,WAAW;IACX,QAAQ;IACR,WAAU,UAAS,QAAQ,YAAY,MAAM,OAAO,KAAK;GAC1D,CAAA;GACD,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACG,YACC,qBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAQ,UAAU,YAAY,CAAC;KAAQ,SAAS;KAA1E,UAAA,CACE,oBAAC,MAAD,EAAM,MAAK,uBAAwB,CAAA,GAClC,EAAE,yBAAyB,CACtB;IAEV,CAAA,GAAA,qBAAC,QAAD;KAAQ,MAAK;KAAK,SAAQ;KAAQ,UAAU,CAAC;KAAQ,eAAe,KAAK,WAAW;KAApF,UAAA,CACE,oBAAC,MAAD,EAAM,MAAK,gBAAiB,CAAA,GAC3B,SAAS,EAAE,uBAAuB,IAAI,EAAE,2BAA2B,CAC9D;IACL,CAAA,CAAA;;EACF;;AAET"}
1
+ {"version":3,"file":"BibliographyEditor.js","names":[],"sources":["../../../../src/features/composites/react/BibliographyEditor.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Button } from '../../../react/ui/button'\nimport { Input } from '../../../react/ui/input'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { Textarea } from '../../../react/ui/textarea'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { bibtexOf, type CslItem, type CslType, cslOf, cslTypeOptions } from '../bibliography'\nimport { type BibForm, bibFormOf, bibItemOf } from '../bibliography-form'\nimport type { PropertyDefinition } from '../../../core/properties'\nimport { type BlockProperties, propertyHostOf, setBlockProperty } from '../properties'\nimport '../bibliography-command'\n\nconst INPUT_CLASS = 'h-6 w-full px-2 text-xs md:text-xs'\nconst TEXTAREA_CLASS = 'max-h-[8.5rem] min-h-0 w-full px-2 py-1 text-xs md:text-xs'\n\nconst COUNTERS = [\n { key: 'volume', labelKey: 'composites.bib.field.volume' },\n { key: 'issue', labelKey: 'composites.bib.field.issue' },\n { key: 'page', labelKey: 'composites.bib.field.page' },\n] as const\nconst LINES = [\n { key: 'containerTitle', labelKey: 'composites.bib.field.containerTitle' },\n { key: 'publisher', labelKey: 'composites.bib.field.publisher' },\n { key: 'doi', labelKey: 'composites.bib.field.doi' },\n { key: 'isbn', labelKey: 'composites.bib.field.isbn' },\n { key: 'url', labelKey: 'composites.bib.field.url' },\n] as const\n\n/**\n * The structured editor of a `bibliography` field (CSL-JSON item, `meta.bib`): type, authors, year, container, volume,\n * issue, pages, publisher, DOI, ISBN, URL and abstract. Inputs keep a local draft; every commit (blur, Enter, choosing\n * a type, unmount, another row) writes the whole item through `setBlockProperty`. The title is the Typed block's and\n * never stored.\n */\nexport function BibliographyEditor({ editor, row, field, disabled }: {\n editor: Editor\n row: BlockProperties\n field: PropertyDefinition\n disabled?: boolean\n}) {\n const { t } = useEditorI18n()\n const value = row.meta[field.key] as Partial<CslItem> | null | undefined\n const stored = value && typeof value === 'object' && typeof value.type === 'string' ? value as CslItem : null\n const [form, setForm] = useState<BibForm>(() => bibFormOf(stored))\n const formRef = useRef(form)\n const dirty = useRef(false)\n const [copied, setCopied] = useState(false)\n // The latest props for the commit on unmount; updated after every render, so the cleanup of a changed `row.key` still sees the previous row.\n const target = useRef({ editor, row, field, stored })\n useEffect(() => {\n target.current = { editor, row, field, stored }\n })\n\n useEffect(() => {\n if (!dirty.current) {\n const next = bibFormOf(stored)\n formRef.current = next\n setForm(next)\n }\n }, [stored, row.key])\n\n const commit = useCallback(() => {\n if (!dirty.current) return\n dirty.current = false\n const current = target.current\n if (!current.editor.isDestroyed) setBlockProperty(current.editor, current.row, current.field.key, bibItemOf(formRef.current, current.stored))\n }, [])\n\n // Flush on unmount and when the editor is bound to another row.\n useEffect(() => commit, [commit, editor, row.key, field.key])\n\n useEffect(() => {\n if (!copied) return\n const timer = window.setTimeout(() => setCopied(false), 1500)\n return () => window.clearTimeout(timer)\n }, [copied])\n\n function onInput<K extends keyof BibForm>(key: K, next: BibForm[K]) {\n formRef.current = { ...formRef.current, [key]: next }\n setForm(formRef.current)\n dirty.current = true\n }\n\n function onType(next: string) {\n onInput('type', next as CslType)\n commit()\n }\n\n async function copyBibtex() {\n commit()\n const node = propertyHostOf(editor.state.doc, row)?.node\n const csl = node && cslOf(node)\n if (!csl) return\n await navigator.clipboard.writeText(bibtexOf(csl))\n setCopied(true)\n }\n\n // Registered by the AI integration (`composite-ai`); without it there is nothing to fetch with.\n const canFetch = typeof editor.commands.fetchCompositeBibliography === 'function'\n const hasDoi = form.doi.trim() !== '' || (typeof row.meta.doi === 'string' && row.meta.doi.trim() !== '')\n\n function fetchByDoi() {\n commit()\n const found = propertyHostOf(editor.state.doc, row)\n if (found) editor.commands.fetchCompositeBibliography(found.pos)\n }\n\n const typeOptions = useMemo(() => cslTypeOptions(t), [t])\n\n return (\n <div className=\"flex flex-col gap-1.5\">\n <Select value={form.type} onValueChange={onType} disabled={disabled}>\n <SelectTrigger size=\"sm\" className=\"w-full text-xs data-[size=sm]:h-6\" aria-label={t('composites.bib.field.type')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {typeOptions.map(option => (\n <SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>\n ))}\n </SelectContent>\n </Select>\n <Textarea\n value={form.authors}\n placeholder={t('composites.bib.field.authorsHelp')}\n aria-label={t('composites.bib.field.authors')}\n disabled={disabled}\n rows={2}\n className={TEXTAREA_CLASS}\n onBlur={commit}\n onChange={event => onInput('authors', event.target.value)}\n />\n <div className=\"grid grid-cols-4 gap-1.5\">\n <Input\n value={form.year}\n type=\"number\"\n placeholder={t('composites.bib.field.year')}\n aria-label={t('composites.bib.field.year')}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput('year', event.target.value)}\n />\n {COUNTERS.map(input => (\n <Input\n key={input.key}\n value={form[input.key]}\n placeholder={t(input.labelKey)}\n aria-label={t(input.labelKey)}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput(input.key, event.target.value)}\n />\n ))}\n </div>\n {LINES.map(input => (\n <Input\n key={input.key}\n value={form[input.key]}\n placeholder={t(input.labelKey)}\n aria-label={t(input.labelKey)}\n disabled={disabled}\n className={INPUT_CLASS}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') commit()\n }}\n onChange={event => onInput(input.key, event.target.value)}\n />\n ))}\n <Textarea\n value={form.abstract}\n placeholder={t('composites.bib.field.abstract')}\n aria-label={t('composites.bib.field.abstract')}\n disabled={disabled}\n rows={2}\n className={TEXTAREA_CLASS}\n onBlur={commit}\n onChange={event => onInput('abstract', event.target.value)}\n />\n <div className=\"flex justify-end gap-1.5\">\n {canFetch && (\n <Button size=\"xs\" variant=\"ghost\" disabled={disabled || !hasDoi} onClick={fetchByDoi}>\n <Icon name=\"i-lucide-book-marked\" />\n {t('composites.bib.fetchDoi')}\n </Button>\n )}\n <Button size=\"xs\" variant=\"ghost\" disabled={!stored} onClick={() => void copyBibtex()}>\n <Icon name=\"i-lucide-copy\" />\n {copied ? t('composites.bib.copied') : t('composites.bib.copyBibtex')}\n </Button>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
@@ -9,8 +9,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  //#region src/features/composites/react/CompositeBasketMenu.tsx
10
10
  const OPTION = "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors duration-150 hover:bg-muted focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary";
11
11
  /**
12
- * Basket choice of a Baustein: the child (a button) opens a list of the editor's baskets (a dot in the basket's colour
13
- * and its label) and „Kein Korb“. The menu is a popover, not a dropdown menu: a dropdown item cannot show a dot in an
12
+ * Basket choice of a Typed block: the child (a button) opens a list of the editor's baskets (a dot in the basket's colour
13
+ * and its label) and a „none“ entry. The menu is a popover, not a dropdown menu: a dropdown item cannot show a dot in an
14
14
  * arbitrary CSS colour.
15
15
  */
16
16
  function CompositeBasketMenu({ editor, row, children }) {
@@ -1 +1 @@
1
- {"version":3,"file":"CompositeBasketMenu.js","names":[],"sources":["../../../../src/features/composites/react/CompositeBasketMenu.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type ReactNode, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../../react/ui/popover'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { basketOf } from '../baskets'\nimport { compositeBasketsOf } from '../nodes'\nimport { compositeOfRow, type CompositeRow } from '../rows'\n\nconst OPTION = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors duration-150 hover:bg-muted focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary'\n\n/**\n * Basket choice of a Baustein: the child (a button) opens a list of the editor's baskets (a dot in the basket's colour\n * and its label) and „Kein Korb“. The menu is a popover, not a dropdown menu: a dropdown item cannot show a dot in an\n * arbitrary CSS colour.\n */\nexport function CompositeBasketMenu({ editor, row, children }: { editor: Editor, row: CompositeRow, children: ReactNode }) {\n const { t } = useEditorI18n()\n const [open, setOpen] = useState(false)\n\n const current = basketOf(row)\n\n function choose(next: string | null) {\n setOpen(false)\n const found = compositeOfRow(editor.state.doc, row)\n if (found) editor.commands.setCompositeBasket(next, found.pos)\n }\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n className=\"w-40 gap-0 p-1\"\n onCloseAutoFocus={event => event.preventDefault()}\n >\n <div role=\"menu\" aria-label={t('composites.basket.label')}>\n {compositeBasketsOf(editor).map(candidate => (\n <button\n key={candidate.id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={current === candidate.id}\n className={OPTION}\n onClick={() => choose(candidate.id)}\n >\n <span className=\"size-2.5 shrink-0 rounded-full\" style={{ backgroundColor: candidate.color }} />\n <span className=\"truncate\">{candidate.label}</span>\n {current === candidate.id && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n ))}\n <button type=\"button\" role=\"menuitemradio\" aria-checked={current === null} className={OPTION} onClick={() => choose(null)}>\n <Icon name=\"i-lucide-circle-dashed\" className=\"size-3 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{t('composites.basket.none')}</span>\n {current === null && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,SAAS;;;;;;AAOf,SAAgB,oBAAoB,EAAE,QAAQ,KAAK,YAAwE;CACzH,MAAM,EAAE,MAAM,cAAc;CAC5B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,MAAM,UAAU,SAAS,GAAG;CAE5B,SAAS,OAAO,MAAqB;EACnC,QAAQ,KAAK;EACb,MAAM,QAAQ,eAAe,OAAO,MAAM,KAAK,GAAG;EAClD,IAAI,OAAO,OAAO,SAAS,mBAAmB,MAAM,MAAM,GAAG;CAC/D;CAEA,OACE,qBAAC,SAAD;EAAe;EAAM,cAAc;EAAnC,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GAAS;EAAyB,CAAA,GAClD,oBAAC,gBAAD;GACE,MAAK;GACL,OAAM;GACN,YAAY;GACZ,WAAU;GACV,mBAAkB,UAAS,MAAM,eAAe;GAEhD,UAAA,qBAAC,OAAD;IAAK,MAAK;IAAO,cAAY,EAAE,yBAAyB;IAAxD,UAAA,CACG,mBAAmB,MAAM,CAAC,CAAC,KAAI,cAC9B,qBAAC,UAAD;KAEE,MAAK;KACL,MAAK;KACL,gBAAc,YAAY,UAAU;KACpC,WAAW;KACX,eAAe,OAAO,UAAU,EAAE;KANpC,UAAA;MAQE,oBAAC,QAAD;OAAM,WAAU;OAAiC,OAAO,EAAE,iBAAiB,UAAU,MAAM;MAAI,CAAA;MAC/F,oBAAC,QAAD;OAAM,WAAU;OAAY,UAAA,UAAU;MAAY,CAAA;MACjD,YAAY,UAAU,MAAM,oBAAC,MAAD;OAAM,MAAK;OAAiB,WAAU;MAA6B,CAAA;KAC1F;IAVD,GAAA,UAAU,EAUT,CACT,GACD,qBAAC,UAAD;KAAQ,MAAK;KAAS,MAAK;KAAgB,gBAAc,YAAY;KAAM,WAAW;KAAQ,eAAe,OAAO,IAAI;KAAxH,UAAA;MACE,oBAAC,MAAD;OAAM,MAAK;OAAyB,WAAU;MAAyC,CAAA;MACvF,oBAAC,QAAD;OAAM,WAAU;OAAY,UAAA,EAAE,wBAAwB;MAAQ,CAAA;MAC7D,YAAY,QAAQ,oBAAC,MAAD;OAAM,MAAK;OAAiB,WAAU;MAA6B,CAAA;KAClF;IACL,CAAA,CAAA;;EACS,CAAA,CACT;;AAEb"}
1
+ {"version":3,"file":"CompositeBasketMenu.js","names":[],"sources":["../../../../src/features/composites/react/CompositeBasketMenu.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { type ReactNode, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../../react/ui/popover'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { basketOf } from '../baskets'\nimport { compositeBasketsOf } from '../nodes'\nimport { compositeOfRow, type CompositeRow } from '../rows'\n\nconst OPTION = 'flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm text-foreground transition-colors duration-150 hover:bg-muted focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary'\n\n/**\n * Basket choice of a Typed block: the child (a button) opens a list of the editor's baskets (a dot in the basket's colour\n * and its label) and a „none“ entry. The menu is a popover, not a dropdown menu: a dropdown item cannot show a dot in an\n * arbitrary CSS colour.\n */\nexport function CompositeBasketMenu({ editor, row, children }: { editor: Editor, row: CompositeRow, children: ReactNode }) {\n const { t } = useEditorI18n()\n const [open, setOpen] = useState(false)\n\n const current = basketOf(row)\n\n function choose(next: string | null) {\n setOpen(false)\n const found = compositeOfRow(editor.state.doc, row)\n if (found) editor.commands.setCompositeBasket(next, found.pos)\n }\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>{children}</PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n className=\"w-40 gap-0 p-1\"\n onCloseAutoFocus={event => event.preventDefault()}\n >\n <div role=\"menu\" aria-label={t('composites.basket.label')}>\n {compositeBasketsOf(editor).map(candidate => (\n <button\n key={candidate.id}\n type=\"button\"\n role=\"menuitemradio\"\n aria-checked={current === candidate.id}\n className={OPTION}\n onClick={() => choose(candidate.id)}\n >\n <span className=\"size-2.5 shrink-0 rounded-full\" style={{ backgroundColor: candidate.color }} />\n <span className=\"truncate\">{candidate.label}</span>\n {current === candidate.id && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n ))}\n <button type=\"button\" role=\"menuitemradio\" aria-checked={current === null} className={OPTION} onClick={() => choose(null)}>\n <Icon name=\"i-lucide-circle-dashed\" className=\"size-3 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{t('composites.basket.none')}</span>\n {current === null && <Icon name=\"i-lucide-check\" className=\"ml-auto size-3.5 shrink-0\" />}\n </button>\n </div>\n </PopoverContent>\n </Popover>\n )\n}\n"],"mappings":";;;;;;;;;AASA,MAAM,SAAS;;;;;;AAOf,SAAgB,oBAAoB,EAAE,QAAQ,KAAK,YAAwE;CACzH,MAAM,EAAE,MAAM,cAAc;CAC5B,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK;CAEtC,MAAM,UAAU,SAAS,GAAG;CAE5B,SAAS,OAAO,MAAqB;EACnC,QAAQ,KAAK;EACb,MAAM,QAAQ,eAAe,OAAO,MAAM,KAAK,GAAG;EAClD,IAAI,OAAO,OAAO,SAAS,mBAAmB,MAAM,MAAM,GAAG;CAC/D;CAEA,OACE,qBAAC,SAAD;EAAe;EAAM,cAAc;EAAnC,UAAA,CACE,oBAAC,gBAAD;GAAgB,SAAA;GAAS;EAAyB,CAAA,GAClD,oBAAC,gBAAD;GACE,MAAK;GACL,OAAM;GACN,YAAY;GACZ,WAAU;GACV,mBAAkB,UAAS,MAAM,eAAe;GAEhD,UAAA,qBAAC,OAAD;IAAK,MAAK;IAAO,cAAY,EAAE,yBAAyB;IAAxD,UAAA,CACG,mBAAmB,MAAM,CAAC,CAAC,KAAI,cAC9B,qBAAC,UAAD;KAEE,MAAK;KACL,MAAK;KACL,gBAAc,YAAY,UAAU;KACpC,WAAW;KACX,eAAe,OAAO,UAAU,EAAE;KANpC,UAAA;MAQE,oBAAC,QAAD;OAAM,WAAU;OAAiC,OAAO,EAAE,iBAAiB,UAAU,MAAM;MAAI,CAAA;MAC/F,oBAAC,QAAD;OAAM,WAAU;OAAY,UAAA,UAAU;MAAY,CAAA;MACjD,YAAY,UAAU,MAAM,oBAAC,MAAD;OAAM,MAAK;OAAiB,WAAU;MAA6B,CAAA;KAC1F;IAVD,GAAA,UAAU,EAUT,CACT,GACD,qBAAC,UAAD;KAAQ,MAAK;KAAS,MAAK;KAAgB,gBAAc,YAAY;KAAM,WAAW;KAAQ,eAAe,OAAO,IAAI;KAAxH,UAAA;MACE,oBAAC,MAAD;OAAM,MAAK;OAAyB,WAAU;MAAyC,CAAA;MACvF,oBAAC,QAAD;OAAM,WAAU;OAAY,UAAA,EAAE,wBAAwB;MAAQ,CAAA;MAC7D,YAAY,QAAQ,oBAAC,MAAD;OAAM,MAAK;OAAiB,WAAU;MAA6B,CAAA;KAClF;IACL,CAAA,CAAA;;EACS,CAAA,CACT;;AAEb"}
@@ -5,7 +5,7 @@ import { Editor } from "@tiptap/core";
5
5
  * chip and one chip per tag (with a `+` chip to add tags), and on the front the kind icon. The icon is a button that
6
6
  * opens the details popover (kind with a confirmation before it changes, the kind's fields and the summary;
7
7
  * `CompositeDetails`) and, in an editable editor, the composite's drag handle: dragging it moves the composite
8
- * (`startBlockDrag`). With `blocks.kindIcon: 'hover'` it shows only while the composite is hovered, its popover is
8
+ * (`startBlockDrag`). With `blocks.blockTypeIcon: 'hover'` it shows only while the composite is hovered, its popover is
9
9
  * open or the icon has keyboard focus. Chips and popover also render in read-only editors, without edit affordances.
10
10
  * The node view's own description and tags rows are hidden by CSS; this overlay shows and edits them.
11
11
  */
@@ -26,7 +26,7 @@ import { createPortal } from "react-dom";
26
26
  * chip and one chip per tag (with a `+` chip to add tags), and on the front the kind icon. The icon is a button that
27
27
  * opens the details popover (kind with a confirmation before it changes, the kind's fields and the summary;
28
28
  * `CompositeDetails`) and, in an editable editor, the composite's drag handle: dragging it moves the composite
29
- * (`startBlockDrag`). With `blocks.kindIcon: 'hover'` it shows only while the composite is hovered, its popover is
29
+ * (`startBlockDrag`). With `blocks.blockTypeIcon: 'hover'` it shows only while the composite is hovered, its popover is
30
30
  * open or the icon has keyboard focus. Chips and popover also render in read-only editors, without edit affordances.
31
31
  * The node view's own description and tags rows are hidden by CSS; this overlay shows and edits them.
32
32
  */
@@ -44,7 +44,7 @@ function CompositeChrome({ editor }) {
44
44
  }, [editor]);
45
45
  const { settings } = useEditorSettings();
46
46
  const { t } = useEditorI18n();
47
- const iconOnHover = settings.blocks.kindIcon === "hover";
47
+ const iconOnHover = settings.blocks.blockTypeIcon === "hover";
48
48
  const [hoveredKeys, setHoveredKeys] = useState(NO_KEYS);
49
49
  const [chipsHoveredKey, setChipsHoveredKey] = useState(null);
50
50
  const latestRows = useRef(rows);
@@ -83,8 +83,8 @@ function CompositeChrome({ editor }) {
83
83
  const found = compositeOfRow(editor.state.doc, row);
84
84
  if (!found || !startBlockDrag(editor, event, found.pos)) event.preventDefault();
85
85
  }
86
- const expanded = useStore(editor.storage.composite.expanded);
87
- const revealedTitles = useStore(editor.storage.composite.revealedTitles);
86
+ const expanded = useStore(editor.storage.typedBlock.expanded);
87
+ const revealedTitles = useStore(editor.storage.typedBlock.revealedTitles);
88
88
  const placed = useMemo(() => {
89
89
  const baskets = compositeBasketsOf(editor);
90
90
  let hiddenUntil = -1;
@@ -108,10 +108,12 @@ function CompositeChrome({ editor }) {
108
108
  status: rowStatus(row, t),
109
109
  derived: derived && {
110
110
  stale: derived.stale,
111
+ sourceMissing: derived.sourceMissing,
111
112
  open,
112
113
  toggleable: !!row.id
113
114
  },
114
- basket: basketById(baskets, basketOf(row)) ?? null,
115
+ hasBasket: row.capabilities.has("basket"),
116
+ basket: row.capabilities.has("basket") ? basketById(baskets, basketOf(row)) ?? null : null,
115
117
  titleHidden
116
118
  }];
117
119
  });
@@ -185,7 +187,7 @@ function CompositeChrome({ editor }) {
185
187
  onMouseEnter: () => setChipsHoveredKey(item.row.key),
186
188
  onMouseLeave: () => setChipsHoveredKey(null),
187
189
  children: [
188
- item.editable ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CompositeBasketMenu, {
190
+ item.editable ? /* @__PURE__ */ jsxs(Fragment$1, { children: [item.hasBasket && /* @__PURE__ */ jsx(CompositeBasketMenu, {
189
191
  editor,
190
192
  row: item.row,
191
193
  children: /* @__PURE__ */ jsx("button", {
@@ -245,6 +247,13 @@ function CompositeChrome({ editor }) {
245
247
  name: "i-lucide-triangle-alert",
246
248
  className: "size-3.5"
247
249
  }), t("composites.derivation.stale")]
250
+ }),
251
+ item.derived.sourceMissing && /* @__PURE__ */ jsxs("span", {
252
+ className: cn(CHIP, "text-(--sk-warning)"),
253
+ children: [/* @__PURE__ */ jsx(Icon, {
254
+ name: "i-lucide-unlink",
255
+ className: "size-3.5"
256
+ }), t("composites.derivation.sourceMissing")]
248
257
  })
249
258
  ] }),
250
259
  item.status && (item.editable ? /* @__PURE__ */ jsx(CompositeStatusMenu, {
@@ -1 +1 @@
1
- {"version":3,"file":"CompositeChrome.js","names":[],"sources":["../../../../src/features/composites/react/CompositeChrome.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { Fragment, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { startBlockDrag } from '../../../core'\nimport { Icon } from '../../../react/Icon'\nimport { useStore } from '../../../react/use-store'\nimport { useEditorSettings } from '../../../react/settings'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../../react/ui/popover'\nimport { cn } from '../../../react/ui/utils'\nimport { compositeSectionOf } from '../anchors'\nimport { derivedChromeOf } from '../derived-chrome'\nimport { rowStatus } from '../meta-display'\nimport { basketById, basketOf, titleHiddenOf } from '../baskets'\nimport { compositeBasketsOf } from '../nodes'\nimport { compositeOfRow, type CompositeRow, setCompositeTags } from '../rows'\nimport { CompositeBasketMenu } from './CompositeBasketMenu'\nimport { CompositeDetails } from './CompositeDetails'\nimport { CompositeStatusMenu } from './CompositeStatusMenu'\nimport { CompositeTagsEditor } from './CompositeTagsEditor'\nimport { useCompositeAnchors } from './use-composite-anchors'\nimport { useCompositeRows } from './use-composite-rows'\n\n/**\n * Chrome of every composite, laid over the editor (mounted by the composites feature): on the title line the status\n * chip and one chip per tag (with a `+` chip to add tags), and on the front the kind icon. The icon is a button that\n * opens the details popover (kind with a confirmation before it changes, the kind's fields and the summary;\n * `CompositeDetails`) and, in an editable editor, the composite's drag handle: dragging it moves the composite\n * (`startBlockDrag`). With `blocks.kindIcon: 'hover'` it shows only while the composite is hovered, its popover is\n * open or the icon has keyboard focus. Chips and popover also render in read-only editors, without edit affordances.\n * The node view's own description and tags rows are hidden by CSS; this overlay shows and edits them.\n */\nexport function CompositeChrome({ editor }: { editor: Editor }) {\n const { rows } = useCompositeRows(editor)\n const { host, anchors, frame } = useCompositeAnchors(editor, rows)\n\n // `isEditable` is not reactive: follow it on every transaction (`EditorSurface` dispatches one after `setEditable`).\n const [editable, setEditable] = useState(() => !editor.isDestroyed && editor.isEditable)\n useEffect(() => {\n const sync = () => setEditable(!editor.isDestroyed && editor.isEditable)\n sync()\n editor.on('transaction', sync)\n return () => {\n editor.off('transaction', sync)\n }\n }, [editor])\n\n const { settings } = useEditorSettings()\n const { t } = useEditorI18n()\n const iconOnHover = settings.blocks.kindIcon === 'hover'\n\n // Hover state of `kindIcon: 'hover'`: the keys of the rows whose composite is under the pointer (that one and every\n // composite around it), plus the row whose chips the pointer is on (they sit outside the editor's DOM).\n const [hoveredKeys, setHoveredKeys] = useState<ReadonlySet<string>>(NO_KEYS)\n const [chipsHoveredKey, setChipsHoveredKey] = useState<string | null>(null)\n const latestRows = useRef(rows)\n latestRows.current = rows\n\n useEffect(() => {\n let hoveredSection: Element | null = null\n const onMouseleave = () => {\n hoveredSection = null\n setHoveredKeys(NO_KEYS)\n }\n const onMouseover = (event: MouseEvent) => {\n const section = event.target instanceof Element ? event.target.closest('.composite') : null\n if (section === hoveredSection) return\n hoveredSection = section\n const chain = new Set<Element>()\n for (let el = section; el; el = el.parentElement?.closest('.composite') ?? null) chain.add(el)\n const { view, state } = editor\n setHoveredKeys(new Set(latestRows.current.filter((row) => {\n const found = compositeOfRow(state.doc, row)\n const dom = found ? view.nodeDOM(found.pos) : null\n const section = dom instanceof Element ? compositeSectionOf(dom) : null\n return section !== null && chain.has(section)\n }).map(row => row.key)))\n }\n\n onMouseleave()\n if (!iconOnHover || editor.isDestroyed) return\n const { dom } = editor.view\n dom.addEventListener('mouseover', onMouseover)\n dom.addEventListener('mouseleave', onMouseleave)\n return () => {\n dom.removeEventListener('mouseover', onMouseover)\n dom.removeEventListener('mouseleave', onMouseleave)\n }\n }, [editor, iconOnHover])\n\n function onIconDragStart(event: DragEvent, row: CompositeRow) {\n const found = compositeOfRow(editor.state.doc, row)\n if (!found || !startBlockDrag(editor, event, found.pos)) event.preventDefault()\n }\n\n const expanded = useStore(editor.storage.composite.expanded)\n const revealedTitles = useStore(editor.storage.composite.revealedTitles)\n\n const placed = useMemo(() => {\n const baskets = compositeBasketsOf(editor)\n // End of the collapsed derived Baustein the rows being walked sit in: its clipped content shows no chrome.\n let hiddenUntil = -1\n return rows.flatMap((row) => {\n if (row.pos < hiddenUntil) return []\n const derived = derivedChromeOf(editor, row)\n const open = !derived || !row.id || expanded.has(row.id)\n if (!open) hiddenUntil = row.end\n const anchor = anchors.get(row.key)\n if (!anchor) return []\n const titleHidden = titleHiddenOf(row)\n // A hidden title leaves nothing to measure: the chips sit in the strip beside the kind icon (`composites.css`).\n const inStrip = titleHidden && !(row.id && revealedTitles.has(row.id)) && anchor.toggleSize > 0\n // An empty title shows a placeholder the anchor cannot measure: keep clear of it.\n const left = inStrip ? anchor.toggleLeft + anchor.toggleSize + 6 : anchor.lineEnd + (anchor.titleEmpty ? 116 : 12)\n return [{\n row,\n anchor,\n // A kind without `chrome.controls` renders as in a read-only editor.\n editable: editable && row.controls,\n left,\n top: (inStrip ? anchor.toggleTop + anchor.toggleSize / 2 : anchor.lastCenter) - ROW_HEIGHT / 2,\n width: Math.max((frame?.right ?? anchor.right) - left, 120),\n status: rowStatus(row, t),\n derived: derived && { stale: derived.stale, open, toggleable: !!row.id },\n basket: basketById(baskets, basketOf(row)) ?? null,\n titleHidden,\n }]\n })\n }, [editor, rows, anchors, frame, expanded, revealedTitles, editable, t])\n\n function toggleExpanded(row: CompositeRow) {\n if (row.id) editor.commands.toggleCompositeExpanded(row.id)\n }\n\n function removeTag(row: CompositeRow, tag: string) {\n setCompositeTags(editor, row, row.tags.filter(candidate => candidate !== tag))\n }\n\n function toggleTitleHidden(row: CompositeRow) {\n const found = compositeOfRow(editor.state.doc, row)\n if (found) editor.commands.setCompositeTitleHidden(!titleHiddenOf(row), found.pos)\n }\n\n if (!host) return null\n\n return createPortal(\n <div className=\"absolute top-0 left-0 h-0 w-0\">\n {placed.map(item => (\n <Fragment key={item.row.key}>\n {item.anchor.toggleSize > 0 && (\n <Popover>\n <PopoverTrigger asChild>\n {/* A span, not a `button`: Firefox does not start drags from buttons. */}\n <span\n role=\"button\"\n tabIndex={0}\n draggable={item.editable}\n className={cn(\n 'absolute z-10 flex items-center justify-center rounded-sm bg-background text-muted-foreground transition-[color,background-color,opacity] duration-120 motion-reduce:transition-none hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n item.editable ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer',\n iconOnHover && !hoveredKeys.has(item.row.key) && chipsHoveredKey !== item.row.key && 'opacity-0 hover:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100',\n )}\n style={{ top: `${item.anchor.toggleTop}px`, left: `${item.anchor.toggleLeft}px`, width: `${item.anchor.toggleSize}px`, height: `${item.anchor.toggleSize}px` }}\n aria-label={t('composites.chrome.details', { kind: item.row.kindLabel })}\n title={item.editable ? t('composites.chrome.detailsDrag', { kind: item.row.kindLabel }) : t('composites.chrome.details', { kind: item.row.kindLabel })}\n onKeyDown={(event: KeyboardEvent<HTMLElement>) => {\n if (event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n event.currentTarget.click()\n }}\n onDragStart={event => onIconDragStart(event.nativeEvent, item.row)}\n >\n <Icon key={item.row.icon} name={item.row.icon} className=\"size-3.5\" />\n </span>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n className={DETAILS_POPOVER}\n >\n <CompositeDetails editor={editor} row={item.row} editable={item.editable} />\n </PopoverContent>\n </Popover>\n )}\n\n {(item.editable || item.basket || item.status || item.derived || (item.row.tagsVisible && item.row.tags.length > 0)) && (\n <div\n className=\"absolute z-10 flex items-center gap-px overflow-hidden rounded-md bg-background\"\n style={{ top: `${item.top}px`, left: `${item.left}px`, maxWidth: `${item.width}px`, height: `${ROW_HEIGHT}px` }}\n onMouseEnter={() => setChipsHoveredKey(item.row.key)}\n onMouseLeave={() => setChipsHoveredKey(null)}\n >\n {item.editable\n ? (\n <>\n <CompositeBasketMenu editor={editor} row={item.row}>\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-label={t('composites.basket.label')}\n title={item.basket ? `${t('composites.basket.label')}: ${item.basket.label}` : t('composites.basket.label')}\n >\n {item.basket\n ? <span className=\"size-2.5 rounded-full\" style={{ backgroundColor: item.basket.color }} />\n : <Icon name=\"i-lucide-circle-dashed\" className=\"size-3.5\" />}\n </button>\n </CompositeBasketMenu>\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-label={t(item.titleHidden ? 'composites.titleHidden.show' : 'composites.titleHidden.hide')}\n title={t(item.titleHidden ? 'composites.titleHidden.show' : 'composites.titleHidden.hide')}\n onClick={() => toggleTitleHidden(item.row)}\n >\n <Icon name={item.titleHidden ? 'i-lucide-eye' : 'i-lucide-eye-off'} className=\"size-3.5\" />\n </button>\n </>\n )\n : item.basket && (\n <span className={CHIP} title={item.basket.label}>\n <span className=\"size-2.5 rounded-full\" style={{ backgroundColor: item.basket.color }} />\n </span>\n )}\n\n {item.derived && (\n <>\n {item.derived.toggleable && (\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-expanded={item.derived.open}\n aria-label={t(item.derived.open ? 'composites.derivation.collapse' : 'composites.derivation.expand')}\n title={t(item.derived.open ? 'composites.derivation.collapse' : 'composites.derivation.expand')}\n onClick={() => toggleExpanded(item.row)}\n >\n <Icon name={item.derived.open ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'} className=\"size-3.5\" />\n </button>\n )}\n <span className={CHIP}>\n <Icon name=\"i-lucide-git-branch\" className=\"size-3.5\" />{t('composites.derivation.badge')}\n </span>\n {item.derived.stale && (\n <span className={cn(CHIP, 'text-(--sk-warning)')}>\n <Icon name=\"i-lucide-triangle-alert\" className=\"size-3.5\" />{t('composites.derivation.stale')}\n </span>\n )}\n </>\n )}\n\n {item.status && (item.editable\n ? (\n <CompositeStatusMenu editor={editor} row={item.row}>\n <button type=\"button\" className={CHIP_BUTTON} aria-label={t('composites.status.label', { status: item.status.label })}>\n <Icon name={item.status.icon} className={cn('size-3.5', STATUS_COLOR[item.status.color] ?? item.status.color)} />{item.status.label}\n </button>\n </CompositeStatusMenu>\n )\n : (\n <span className={CHIP}>\n <Icon name={item.status.icon} className={cn('size-3.5', STATUS_COLOR[item.status.color] ?? item.status.color)} />{item.status.label}\n </span>\n ))}\n\n {(item.row.tagsVisible ? item.row.tags : []).map(tag => (\n <span key={tag} className={cn(CHIP, 'group max-w-40 gap-0')}>\n <span className=\"truncate\">#{tag}</span>\n {item.editable && (\n <button\n type=\"button\"\n className=\"flex h-4 w-0 shrink-0 items-center justify-center overflow-hidden rounded-sm opacity-0 transition-all duration-150 group-hover:ml-1 group-hover:w-4 group-hover:opacity-100 hover:bg-muted hover:text-foreground focus-visible:ml-1 focus-visible:w-4 focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-primary\"\n aria-label={t('composites.tag.remove', { tag })}\n onClick={() => removeTag(item.row, tag)}\n >\n <Icon name=\"i-lucide-x\" className=\"size-3\" />\n </button>\n )}\n </span>\n ))}\n\n {item.editable && item.row.tagsVisible && (\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={CHIP_BUTTON} aria-label={t('composites.tag.add')} title={t('composites.tag.add')}>\n <Icon name=\"i-lucide-plus\" className=\"size-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n className=\"w-auto gap-0 p-0\"\n onCloseAutoFocus={event => event.preventDefault()}\n >\n <div className=\"w-64 p-3\">\n <CompositeTagsEditor editor={editor} row={item.row} />\n </div>\n </PopoverContent>\n </Popover>\n )}\n </div>\n )}\n </Fragment>\n ))}\n </div>,\n host,\n )\n}\n\nconst NO_KEYS: ReadonlySet<string> = new Set()\n\n/** Chips start right after the title's last character and run on to the editor's right edge. */\nconst ROW_HEIGHT = 24\n\nconst CHIP = 'inline-flex h-5 shrink-0 items-center gap-1 rounded-sm px-1.5 text-xs leading-none whitespace-nowrap text-muted-foreground'\nconst CHIP_BUTTON = `${CHIP} transition-colors duration-150 hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary`\n\n/** `statusStyle` names Nuxt UI text colors: the shadcn counterparts (`--sk-info` and `--sk-success` come from the token stylesheets). */\nconst STATUS_COLOR: Record<string, string> = {\n 'text-muted': 'text-muted-foreground',\n 'text-info': 'text-(--sk-info)',\n 'text-success': 'text-(--sk-success)',\n 'text-dimmed': 'text-muted-foreground/70',\n}\n\n/** Scale and fade in from the icon (`transform-origin` is Radix's), a bit longer than the default; `composites.css` defines the keyframes and the reduced-motion override. */\nconst DETAILS_POPOVER = 'w-auto gap-0 p-0 composite-popover data-[state=open]:animate-[composite-pop-in_160ms_var(--ease-out)] data-[state=closed]:animate-[composite-pop-out_120ms_var(--ease-out)]'\n"],"mappings":"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"}
1
+ {"version":3,"file":"CompositeChrome.js","names":[],"sources":["../../../../src/features/composites/react/CompositeChrome.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { Fragment, type KeyboardEvent, useEffect, useMemo, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { startBlockDrag } from '../../../core'\nimport { Icon } from '../../../react/Icon'\nimport { useStore } from '../../../react/use-store'\nimport { useEditorSettings } from '../../../react/settings'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { Popover, PopoverContent, PopoverTrigger } from '../../../react/ui/popover'\nimport { cn } from '../../../react/ui/utils'\nimport { compositeSectionOf } from '../anchors'\nimport { derivedChromeOf } from '../derived-chrome'\nimport { rowStatus } from '../meta-display'\nimport { basketById, basketOf, titleHiddenOf } from '../baskets'\nimport { compositeBasketsOf } from '../nodes'\nimport { compositeOfRow, type CompositeRow, setCompositeTags } from '../rows'\nimport { CompositeBasketMenu } from './CompositeBasketMenu'\nimport { CompositeDetails } from './CompositeDetails'\nimport { CompositeStatusMenu } from './CompositeStatusMenu'\nimport { CompositeTagsEditor } from './CompositeTagsEditor'\nimport { useCompositeAnchors } from './use-composite-anchors'\nimport { useCompositeRows } from './use-composite-rows'\n\n/**\n * Chrome of every composite, laid over the editor (mounted by the composites feature): on the title line the status\n * chip and one chip per tag (with a `+` chip to add tags), and on the front the kind icon. The icon is a button that\n * opens the details popover (kind with a confirmation before it changes, the kind's fields and the summary;\n * `CompositeDetails`) and, in an editable editor, the composite's drag handle: dragging it moves the composite\n * (`startBlockDrag`). With `blocks.blockTypeIcon: 'hover'` it shows only while the composite is hovered, its popover is\n * open or the icon has keyboard focus. Chips and popover also render in read-only editors, without edit affordances.\n * The node view's own description and tags rows are hidden by CSS; this overlay shows and edits them.\n */\nexport function CompositeChrome({ editor }: { editor: Editor }) {\n const { rows } = useCompositeRows(editor)\n const { host, anchors, frame } = useCompositeAnchors(editor, rows)\n\n // `isEditable` is not reactive: follow it on every transaction (`EditorSurface` dispatches one after `setEditable`).\n const [editable, setEditable] = useState(() => !editor.isDestroyed && editor.isEditable)\n useEffect(() => {\n const sync = () => setEditable(!editor.isDestroyed && editor.isEditable)\n sync()\n editor.on('transaction', sync)\n return () => {\n editor.off('transaction', sync)\n }\n }, [editor])\n\n const { settings } = useEditorSettings()\n const { t } = useEditorI18n()\n const iconOnHover = settings.blocks.blockTypeIcon === 'hover'\n\n // Hover state of `blockTypeIcon: 'hover'`: the keys of the rows whose composite is under the pointer (that one and every\n // composite around it), plus the row whose chips the pointer is on (they sit outside the editor's DOM).\n const [hoveredKeys, setHoveredKeys] = useState<ReadonlySet<string>>(NO_KEYS)\n const [chipsHoveredKey, setChipsHoveredKey] = useState<string | null>(null)\n const latestRows = useRef(rows)\n latestRows.current = rows\n\n useEffect(() => {\n let hoveredSection: Element | null = null\n const onMouseleave = () => {\n hoveredSection = null\n setHoveredKeys(NO_KEYS)\n }\n const onMouseover = (event: MouseEvent) => {\n const section = event.target instanceof Element ? event.target.closest('.composite') : null\n if (section === hoveredSection) return\n hoveredSection = section\n const chain = new Set<Element>()\n for (let el = section; el; el = el.parentElement?.closest('.composite') ?? null) chain.add(el)\n const { view, state } = editor\n setHoveredKeys(new Set(latestRows.current.filter((row) => {\n const found = compositeOfRow(state.doc, row)\n const dom = found ? view.nodeDOM(found.pos) : null\n const section = dom instanceof Element ? compositeSectionOf(dom) : null\n return section !== null && chain.has(section)\n }).map(row => row.key)))\n }\n\n onMouseleave()\n if (!iconOnHover || editor.isDestroyed) return\n const { dom } = editor.view\n dom.addEventListener('mouseover', onMouseover)\n dom.addEventListener('mouseleave', onMouseleave)\n return () => {\n dom.removeEventListener('mouseover', onMouseover)\n dom.removeEventListener('mouseleave', onMouseleave)\n }\n }, [editor, iconOnHover])\n\n function onIconDragStart(event: DragEvent, row: CompositeRow) {\n const found = compositeOfRow(editor.state.doc, row)\n if (!found || !startBlockDrag(editor, event, found.pos)) event.preventDefault()\n }\n\n const expanded = useStore(editor.storage.typedBlock.expanded)\n const revealedTitles = useStore(editor.storage.typedBlock.revealedTitles)\n\n const placed = useMemo(() => {\n const baskets = compositeBasketsOf(editor)\n // End of the collapsed derived Typed block the rows being walked sit in: its clipped content shows no chrome.\n let hiddenUntil = -1\n return rows.flatMap((row) => {\n if (row.pos < hiddenUntil) return []\n const derived = derivedChromeOf(editor, row)\n const open = !derived || !row.id || expanded.has(row.id)\n if (!open) hiddenUntil = row.end\n const anchor = anchors.get(row.key)\n if (!anchor) return []\n const titleHidden = titleHiddenOf(row)\n // A hidden title leaves nothing to measure: the chips sit in the strip beside the kind icon (`composites.css`).\n const inStrip = titleHidden && !(row.id && revealedTitles.has(row.id)) && anchor.toggleSize > 0\n // An empty title shows a placeholder the anchor cannot measure: keep clear of it.\n const left = inStrip ? anchor.toggleLeft + anchor.toggleSize + 6 : anchor.lineEnd + (anchor.titleEmpty ? 116 : 12)\n return [{\n row,\n anchor,\n // A kind without `chrome.controls` renders as in a read-only editor.\n editable: editable && row.controls,\n left,\n top: (inStrip ? anchor.toggleTop + anchor.toggleSize / 2 : anchor.lastCenter) - ROW_HEIGHT / 2,\n width: Math.max((frame?.right ?? anchor.right) - left, 120),\n status: rowStatus(row, t),\n derived: derived && { stale: derived.stale, sourceMissing: derived.sourceMissing, open, toggleable: !!row.id },\n // The basket menu and chip belong to the `basket` capability: a Block type without it has neither.\n hasBasket: row.capabilities.has('basket'),\n basket: row.capabilities.has('basket') ? basketById(baskets, basketOf(row)) ?? null : null,\n titleHidden,\n }]\n })\n }, [editor, rows, anchors, frame, expanded, revealedTitles, editable, t])\n\n function toggleExpanded(row: CompositeRow) {\n if (row.id) editor.commands.toggleCompositeExpanded(row.id)\n }\n\n function removeTag(row: CompositeRow, tag: string) {\n setCompositeTags(editor, row, row.tags.filter(candidate => candidate !== tag))\n }\n\n function toggleTitleHidden(row: CompositeRow) {\n const found = compositeOfRow(editor.state.doc, row)\n if (found) editor.commands.setCompositeTitleHidden(!titleHiddenOf(row), found.pos)\n }\n\n if (!host) return null\n\n return createPortal(\n <div className=\"absolute top-0 left-0 h-0 w-0\">\n {placed.map(item => (\n <Fragment key={item.row.key}>\n {item.anchor.toggleSize > 0 && (\n <Popover>\n <PopoverTrigger asChild>\n {/* A span, not a `button`: Firefox does not start drags from buttons. */}\n <span\n role=\"button\"\n tabIndex={0}\n draggable={item.editable}\n className={cn(\n 'absolute z-10 flex items-center justify-center rounded-sm bg-background text-muted-foreground transition-[color,background-color,opacity] duration-120 motion-reduce:transition-none hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary',\n item.editable ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer',\n iconOnHover && !hoveredKeys.has(item.row.key) && chipsHoveredKey !== item.row.key && 'opacity-0 hover:opacity-100 focus-visible:opacity-100 data-[state=open]:opacity-100',\n )}\n style={{ top: `${item.anchor.toggleTop}px`, left: `${item.anchor.toggleLeft}px`, width: `${item.anchor.toggleSize}px`, height: `${item.anchor.toggleSize}px` }}\n aria-label={t('composites.chrome.details', { kind: item.row.kindLabel })}\n title={item.editable ? t('composites.chrome.detailsDrag', { kind: item.row.kindLabel }) : t('composites.chrome.details', { kind: item.row.kindLabel })}\n onKeyDown={(event: KeyboardEvent<HTMLElement>) => {\n if (event.key !== 'Enter' && event.key !== ' ') return\n event.preventDefault()\n event.currentTarget.click()\n }}\n onDragStart={event => onIconDragStart(event.nativeEvent, item.row)}\n >\n <Icon key={item.row.icon} name={item.row.icon} className=\"size-3.5\" />\n </span>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={4}\n className={DETAILS_POPOVER}\n >\n <CompositeDetails editor={editor} row={item.row} editable={item.editable} />\n </PopoverContent>\n </Popover>\n )}\n\n {(item.editable || item.basket || item.status || item.derived || (item.row.tagsVisible && item.row.tags.length > 0)) && (\n <div\n className=\"absolute z-10 flex items-center gap-px overflow-hidden rounded-md bg-background\"\n style={{ top: `${item.top}px`, left: `${item.left}px`, maxWidth: `${item.width}px`, height: `${ROW_HEIGHT}px` }}\n onMouseEnter={() => setChipsHoveredKey(item.row.key)}\n onMouseLeave={() => setChipsHoveredKey(null)}\n >\n {item.editable\n ? (\n <>\n {item.hasBasket && (\n <CompositeBasketMenu editor={editor} row={item.row}>\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-label={t('composites.basket.label')}\n title={item.basket ? `${t('composites.basket.label')}: ${item.basket.label}` : t('composites.basket.label')}\n >\n {item.basket\n ? <span className=\"size-2.5 rounded-full\" style={{ backgroundColor: item.basket.color }} />\n : <Icon name=\"i-lucide-circle-dashed\" className=\"size-3.5\" />}\n </button>\n </CompositeBasketMenu>\n )}\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-label={t(item.titleHidden ? 'composites.titleHidden.show' : 'composites.titleHidden.hide')}\n title={t(item.titleHidden ? 'composites.titleHidden.show' : 'composites.titleHidden.hide')}\n onClick={() => toggleTitleHidden(item.row)}\n >\n <Icon name={item.titleHidden ? 'i-lucide-eye' : 'i-lucide-eye-off'} className=\"size-3.5\" />\n </button>\n </>\n )\n : item.basket && (\n <span className={CHIP} title={item.basket.label}>\n <span className=\"size-2.5 rounded-full\" style={{ backgroundColor: item.basket.color }} />\n </span>\n )}\n\n {item.derived && (\n <>\n {item.derived.toggleable && (\n <button\n type=\"button\"\n className={CHIP_BUTTON}\n aria-expanded={item.derived.open}\n aria-label={t(item.derived.open ? 'composites.derivation.collapse' : 'composites.derivation.expand')}\n title={t(item.derived.open ? 'composites.derivation.collapse' : 'composites.derivation.expand')}\n onClick={() => toggleExpanded(item.row)}\n >\n <Icon name={item.derived.open ? 'i-lucide-chevron-down' : 'i-lucide-chevron-right'} className=\"size-3.5\" />\n </button>\n )}\n <span className={CHIP}>\n <Icon name=\"i-lucide-git-branch\" className=\"size-3.5\" />{t('composites.derivation.badge')}\n </span>\n {item.derived.stale && (\n <span className={cn(CHIP, 'text-(--sk-warning)')}>\n <Icon name=\"i-lucide-triangle-alert\" className=\"size-3.5\" />{t('composites.derivation.stale')}\n </span>\n )}\n {item.derived.sourceMissing && (\n <span className={cn(CHIP, 'text-(--sk-warning)')}>\n <Icon name=\"i-lucide-unlink\" className=\"size-3.5\" />{t('composites.derivation.sourceMissing')}\n </span>\n )}\n </>\n )}\n\n {item.status && (item.editable\n ? (\n <CompositeStatusMenu editor={editor} row={item.row}>\n <button type=\"button\" className={CHIP_BUTTON} aria-label={t('composites.status.label', { status: item.status.label })}>\n <Icon name={item.status.icon} className={cn('size-3.5', STATUS_COLOR[item.status.color] ?? item.status.color)} />{item.status.label}\n </button>\n </CompositeStatusMenu>\n )\n : (\n <span className={CHIP}>\n <Icon name={item.status.icon} className={cn('size-3.5', STATUS_COLOR[item.status.color] ?? item.status.color)} />{item.status.label}\n </span>\n ))}\n\n {(item.row.tagsVisible ? item.row.tags : []).map(tag => (\n <span key={tag} className={cn(CHIP, 'group max-w-40 gap-0')}>\n <span className=\"truncate\">#{tag}</span>\n {item.editable && (\n <button\n type=\"button\"\n className=\"flex h-4 w-0 shrink-0 items-center justify-center overflow-hidden rounded-sm opacity-0 transition-all duration-150 group-hover:ml-1 group-hover:w-4 group-hover:opacity-100 hover:bg-muted hover:text-foreground focus-visible:ml-1 focus-visible:w-4 focus-visible:opacity-100 focus-visible:outline-2 focus-visible:outline-primary\"\n aria-label={t('composites.tag.remove', { tag })}\n onClick={() => removeTag(item.row, tag)}\n >\n <Icon name=\"i-lucide-x\" className=\"size-3\" />\n </button>\n )}\n </span>\n ))}\n\n {item.editable && item.row.tagsVisible && (\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={CHIP_BUTTON} aria-label={t('composites.tag.add')} title={t('composites.tag.add')}>\n <Icon name=\"i-lucide-plus\" className=\"size-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent\n side=\"bottom\"\n align=\"start\"\n sideOffset={6}\n className=\"w-auto gap-0 p-0\"\n onCloseAutoFocus={event => event.preventDefault()}\n >\n <div className=\"w-64 p-3\">\n <CompositeTagsEditor editor={editor} row={item.row} />\n </div>\n </PopoverContent>\n </Popover>\n )}\n </div>\n )}\n </Fragment>\n ))}\n </div>,\n host,\n )\n}\n\nconst NO_KEYS: ReadonlySet<string> = new Set()\n\n/** Chips start right after the title's last character and run on to the editor's right edge. */\nconst ROW_HEIGHT = 24\n\nconst CHIP = 'inline-flex h-5 shrink-0 items-center gap-1 rounded-sm px-1.5 text-xs leading-none whitespace-nowrap text-muted-foreground'\nconst CHIP_BUTTON = `${CHIP} transition-colors duration-150 hover:bg-muted hover:text-foreground focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary`\n\n/** `statusStyle` names Nuxt UI text colors: the shadcn counterparts (`--sk-info` and `--sk-success` come from the token stylesheets). */\nconst STATUS_COLOR: Record<string, string> = {\n 'text-muted': 'text-muted-foreground',\n 'text-info': 'text-(--sk-info)',\n 'text-success': 'text-(--sk-success)',\n 'text-dimmed': 'text-muted-foreground/70',\n}\n\n/** Scale and fade in from the icon (`transform-origin` is Radix's), a bit longer than the default; `composites.css` defines the keyframes and the reduced-motion override. */\nconst DETAILS_POPOVER = 'w-auto gap-0 p-0 composite-popover data-[state=open]:animate-[composite-pop-in_160ms_var(--ease-out)] data-[state=closed]:animate-[composite-pop-out_120ms_var(--ease-out)]'\n"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { Editor } from "@tiptap/core";
4
4
  /**
5
5
  * Content of the popover on a composite's front icon: the kind (a select, plain text while read-only), every field of
6
6
  * the kind except the status (its chip edits it) and the summary. Choosing another kind first shows an inline warning
7
- * that names the field values the switch drops (`setCompositeKind` keeps the meta keys the new kind declares, plus
7
+ * that names the field values the switch drops (`changeBlockType` keeps the meta keys the new kind declares, plus
8
8
  * `derivation` and `bib`, see `keepsMetaKey`) and
9
9
  * applies the change on „Ändern“.
10
10
  */
@@ -1,6 +1,7 @@
1
+ import { derivationOf } from "../../../core/derivation.js";
1
2
  import { keepsMetaKey } from "../meta-keys.js";
2
- import { derivationOf } from "../derivation.js";
3
- import { compositeKindsOf } from "../nodes.js";
3
+ import { blockTypesOf } from "../nodes.js";
4
+ import { propertyHostOf } from "../properties.js";
4
5
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
5
6
  import { Icon } from "../../../react/Icon.js";
6
7
  import { Button } from "../../../react/ui/button.js";
@@ -15,19 +16,19 @@ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
15
16
  /**
16
17
  * Content of the popover on a composite's front icon: the kind (a select, plain text while read-only), every field of
17
18
  * the kind except the status (its chip edits it) and the summary. Choosing another kind first shows an inline warning
18
- * that names the field values the switch drops (`setCompositeKind` keeps the meta keys the new kind declares, plus
19
+ * that names the field values the switch drops (`changeBlockType` keeps the meta keys the new kind declares, plus
19
20
  * `derivation` and `bib`, see `keepsMetaKey`) and
20
21
  * applies the change on „Ändern“.
21
22
  */
22
23
  function CompositeDetails({ editor, row, editable }) {
23
24
  const { t } = useEditorI18n();
24
- const kinds = useMemo(() => compositeKindsOf(editor), [editor]);
25
- const fields = row.fields.filter((field) => field.key !== "status" && field.type !== "derivation");
25
+ const kinds = useMemo(() => blockTypesOf(editor), [editor]);
26
+ const fields = row.definitions.filter((field) => field.key !== "status" && field.type !== "derivation");
26
27
  const derivedNode = useMemo(() => {
27
- const found = compositeOfRow(editor.state.doc, row);
28
+ const found = propertyHostOf(editor.state.doc, row);
28
29
  return found && derivationOf(found.node) ? found.node : null;
29
30
  }, [editor, row]);
30
- /** The places that refer to the row's Baustein (chips in other blocks, `reference` fields), for the „Verweise“ list. */
31
+ /** The places that refer to the row's Typed block (chips in other blocks, `reference` fields), for the „Verweise“ list. */
31
32
  const backlinks = useMemo(() => row.id ? compositeBacklinks(editor.state.doc, kinds, row.id) : [], [
32
33
  editor,
33
34
  kinds,
@@ -44,7 +45,7 @@ function CompositeDetails({ editor, row, editable }) {
44
45
  const target = kinds.find((kind) => kind.id === pending);
45
46
  if (!target) return [];
46
47
  return Object.entries(row.meta).filter(([key, value]) => !keepsMetaKey(target, key) && value != null && value !== "").map(([key, value]) => {
47
- const field = row.fields.find((candidate) => candidate.key === key);
48
+ const field = row.definitions.find((candidate) => candidate.key === key);
48
49
  const text = typeof value === "object" ? JSON.stringify(value) : String(value);
49
50
  return {
50
51
  key,
@@ -56,7 +57,7 @@ function CompositeDetails({ editor, row, editable }) {
56
57
  kinds,
57
58
  pending,
58
59
  row.meta,
59
- row.fields
60
+ row.definitions
60
61
  ]);
61
62
  function onKind(kind) {
62
63
  setPending(kind !== row.kind ? kind : null);
@@ -65,7 +66,7 @@ function CompositeDetails({ editor, row, editable }) {
65
66
  const kind = pending;
66
67
  setPending(null);
67
68
  const found = compositeOfRow(editor.state.doc, row);
68
- if (kind && found) editor.commands.setCompositeKind(kind, found.pos);
69
+ if (kind && found) editor.commands.changeBlockType(kind, found.pos);
69
70
  }
70
71
  return /* @__PURE__ */ jsxs("div", {
71
72
  className: "flex w-72 flex-col gap-2.5 p-3 text-sm",
@@ -1 +1 @@
1
- {"version":3,"file":"CompositeDetails.js","names":[],"sources":["../../../../src/features/composites/react/CompositeDetails.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { useEffect, useMemo, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Button } from '../../../react/ui/button'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { derivationOf } from '../derivation'\nimport { keepsMetaKey } from '../meta-keys'\nimport { compositeKindsOf } from '../nodes'\nimport { compositeBacklinks, compositeOfRow, type CompositeRow } from '../rows'\nimport { CompositeFieldEditor } from './CompositeFieldEditor'\nimport { DerivationBadge } from './DerivationBadge'\nimport { CompositeSummaryEditor } from './CompositeSummaryEditor'\n\n/**\n * Content of the popover on a composite's front icon: the kind (a select, plain text while read-only), every field of\n * the kind except the status (its chip edits it) and the summary. Choosing another kind first shows an inline warning\n * that names the field values the switch drops (`setCompositeKind` keeps the meta keys the new kind declares, plus\n * `derivation` and `bib`, see `keepsMetaKey`) and\n * applies the change on „Ändern“.\n */\nexport function CompositeDetails({ editor, row, editable }: { editor: Editor, row: CompositeRow, editable: boolean }) {\n const { t } = useEditorI18n()\n const kinds = useMemo(() => compositeKindsOf(editor), [editor])\n // The `derivation` field is shown by the details badge below, with the checks a field display cannot do.\n const fields = row.fields.filter(field => field.key !== 'status' && field.type !== 'derivation')\n const derivedNode = useMemo(() => {\n const found = compositeOfRow(editor.state.doc, row)\n return found && derivationOf(found.node) ? found.node : null\n }, [editor, row])\n /** The places that refer to the row's Baustein (chips in other blocks, `reference` fields), for the „Verweise“ list. */\n const backlinks = useMemo(() => row.id ? compositeBacklinks(editor.state.doc, kinds, row.id) : [], [editor, kinds, row])\n\n /** The kind chosen in the select, waiting for the confirmation. */\n const [pending, setPending] = useState<string | null>(null)\n // The kind changed some other way (undo, inspector, another select): a stale confirmation would be misleading.\n useEffect(() => {\n setPending(null)\n }, [row.kind])\n\n const pendingLabel = kinds.find(kind => kind.id === pending)?.label ?? ''\n\n /** Field values of the row that the pending kind does not keep (`keepsMetaKey`), as „Label: value“. */\n const lost = useMemo(() => {\n const target = kinds.find(kind => kind.id === pending)\n if (!target) return []\n return Object.entries(row.meta)\n .filter(([key, value]) => !keepsMetaKey(target, key) && value != null && value !== '')\n .map(([key, value]) => {\n const field = row.fields.find(candidate => candidate.key === key)\n const text = typeof value === 'object' ? JSON.stringify(value) : String(value)\n return { key, label: field?.label ?? key, text: field?.options?.find(option => option.value === text)?.label ?? text }\n })\n }, [kinds, pending, row.meta, row.fields])\n\n function onKind(kind: string) {\n setPending(kind !== row.kind ? kind : null)\n }\n\n function apply() {\n const kind = pending\n setPending(null)\n const found = compositeOfRow(editor.state.doc, row)\n if (kind && found) editor.commands.setCompositeKind(kind, found.pos)\n }\n\n return (\n <div className=\"flex w-72 flex-col gap-2.5 p-3 text-sm\">\n {editable\n ? (\n <Select value={row.kind} onValueChange={onKind}>\n <SelectTrigger size=\"sm\" className=\"w-full text-xs data-[size=sm]:h-6\" aria-label={t('composites.kind.select')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {kinds.map(kind => (\n <SelectItem key={kind.id} value={kind.id}>\n <Icon name={kind.icon} />\n {kind.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n : (\n <p className=\"flex min-w-0 items-center gap-1.5 text-foreground\">\n <Icon key={row.icon} name={row.icon} className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{row.kindLabel}</span>\n </p>\n )}\n\n {pending && (\n <div role=\"alert\" className=\"flex flex-col gap-2 rounded-md bg-(--sk-warning)/10 p-2 text-xs text-foreground ring-1 ring-(--sk-warning)/40\">\n {lost.length > 0\n ? (\n <>\n <p className=\"font-medium\">\n {t('composites.details.confirmLost', { kind: pendingLabel })}\n </p>\n <ul className=\"flex flex-col gap-0.5\">\n {lost.map(item => (\n <li key={item.key} className=\"flex min-w-0 gap-1\">\n <span className=\"shrink-0 text-muted-foreground\">{item.label}:</span>\n <span className=\"truncate\" title={item.text}>{item.text}</span>\n </li>\n ))}\n </ul>\n </>\n )\n : (\n <p className=\"font-medium\">\n {t('composites.details.confirm')}\n </p>\n )}\n <div className=\"flex justify-end gap-1.5\">\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setPending(null)}>{t('composites.details.cancel')}</Button>\n <Button size=\"xs\" className=\"bg-(--sk-warning) text-background hover:bg-(--sk-warning)/80\" onClick={apply}>{t('composites.details.change')}</Button>\n </div>\n </div>\n )}\n\n {derivedNode && <DerivationBadge editor={editor} node={derivedNode} detailed />}\n\n {fields.map(field => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{field.label}</span>\n <CompositeFieldEditor editor={editor} row={row} field={field} disabled={!editable} size=\"xs\" />\n </div>\n ))}\n\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{t('composites.details.summary')}</span>\n <CompositeSummaryEditor editor={editor} row={row} readonly={!editable} />\n </div>\n\n {backlinks.length > 0 && (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{t('composites.reference.backlinks')}</span>\n <ul className=\"flex flex-col gap-0.5\">\n {backlinks.map((link, index) => (\n <li key={`${link.from}:${index}`}>\n <button\n type=\"button\"\n className=\"flex w-full min-w-0 items-baseline gap-1 rounded-sm text-left text-xs text-foreground hover:text-primary focus-visible:outline-2 focus-visible:outline-primary\"\n onClick={() => editor.commands.revealBlock(link.from)}\n >\n <span className=\"truncate\">{link.excerpt || '…'}</span>\n {link.locator && <span className=\"shrink-0 text-muted-foreground\">{link.locator}</span>}\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CompositeDetails.js","names":[],"sources":["../../../../src/features/composites/react/CompositeDetails.tsx"],"sourcesContent":["import type { Editor } from '@tiptap/core'\nimport { useEffect, useMemo, useState } from 'react'\nimport { Icon } from '../../../react/Icon'\nimport { Button } from '../../../react/ui/button'\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../../react/ui/select'\nimport { useEditorI18n } from '../../../react/use-editor-i18n'\nimport { derivationOf } from '../../../core/derivation'\nimport { keepsMetaKey } from '../meta-keys'\nimport { blockTypesOf } from '../nodes'\nimport { propertyHostOf } from '../properties'\nimport { compositeBacklinks, compositeOfRow, type CompositeRow } from '../rows'\nimport { CompositeFieldEditor } from './CompositeFieldEditor'\nimport { DerivationBadge } from './DerivationBadge'\nimport { CompositeSummaryEditor } from './CompositeSummaryEditor'\n\n/**\n * Content of the popover on a composite's front icon: the kind (a select, plain text while read-only), every field of\n * the kind except the status (its chip edits it) and the summary. Choosing another kind first shows an inline warning\n * that names the field values the switch drops (`changeBlockType` keeps the meta keys the new kind declares, plus\n * `derivation` and `bib`, see `keepsMetaKey`) and\n * applies the change on „Ändern“.\n */\nexport function CompositeDetails({ editor, row, editable }: { editor: Editor, row: CompositeRow, editable: boolean }) {\n const { t } = useEditorI18n()\n const kinds = useMemo(() => blockTypesOf(editor), [editor])\n // The `derivation` field is shown by the details badge below, with the checks a field display cannot do.\n const fields = row.definitions.filter(field => field.key !== 'status' && field.type !== 'derivation')\n const derivedNode = useMemo(() => {\n const found = propertyHostOf(editor.state.doc, row)\n return found && derivationOf(found.node) ? found.node : null\n }, [editor, row])\n /** The places that refer to the row's Typed block (chips in other blocks, `reference` fields), for the „Verweise“ list. */\n const backlinks = useMemo(() => row.id ? compositeBacklinks(editor.state.doc, kinds, row.id) : [], [editor, kinds, row])\n\n /** The kind chosen in the select, waiting for the confirmation. */\n const [pending, setPending] = useState<string | null>(null)\n // The kind changed some other way (undo, inspector, another select): a stale confirmation would be misleading.\n useEffect(() => {\n setPending(null)\n }, [row.kind])\n\n const pendingLabel = kinds.find(kind => kind.id === pending)?.label ?? ''\n\n /** Field values of the row that the pending kind does not keep (`keepsMetaKey`), as „Label: value“. */\n const lost = useMemo(() => {\n const target = kinds.find(kind => kind.id === pending)\n if (!target) return []\n return Object.entries(row.meta)\n .filter(([key, value]) => !keepsMetaKey(target, key) && value != null && value !== '')\n .map(([key, value]) => {\n const field = row.definitions.find(candidate => candidate.key === key)\n const text = typeof value === 'object' ? JSON.stringify(value) : String(value)\n return { key, label: field?.label ?? key, text: field?.options?.find(option => option.value === text)?.label ?? text }\n })\n }, [kinds, pending, row.meta, row.definitions])\n\n function onKind(kind: string) {\n setPending(kind !== row.kind ? kind : null)\n }\n\n function apply() {\n const kind = pending\n setPending(null)\n const found = compositeOfRow(editor.state.doc, row)\n if (kind && found) editor.commands.changeBlockType(kind, found.pos)\n }\n\n return (\n <div className=\"flex w-72 flex-col gap-2.5 p-3 text-sm\">\n {editable\n ? (\n <Select value={row.kind} onValueChange={onKind}>\n <SelectTrigger size=\"sm\" className=\"w-full text-xs data-[size=sm]:h-6\" aria-label={t('composites.kind.select')}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {kinds.map(kind => (\n <SelectItem key={kind.id} value={kind.id}>\n <Icon name={kind.icon} />\n {kind.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )\n : (\n <p className=\"flex min-w-0 items-center gap-1.5 text-foreground\">\n <Icon key={row.icon} name={row.icon} className=\"size-4 shrink-0 text-muted-foreground\" />\n <span className=\"truncate\">{row.kindLabel}</span>\n </p>\n )}\n\n {pending && (\n <div role=\"alert\" className=\"flex flex-col gap-2 rounded-md bg-(--sk-warning)/10 p-2 text-xs text-foreground ring-1 ring-(--sk-warning)/40\">\n {lost.length > 0\n ? (\n <>\n <p className=\"font-medium\">\n {t('composites.details.confirmLost', { kind: pendingLabel })}\n </p>\n <ul className=\"flex flex-col gap-0.5\">\n {lost.map(item => (\n <li key={item.key} className=\"flex min-w-0 gap-1\">\n <span className=\"shrink-0 text-muted-foreground\">{item.label}:</span>\n <span className=\"truncate\" title={item.text}>{item.text}</span>\n </li>\n ))}\n </ul>\n </>\n )\n : (\n <p className=\"font-medium\">\n {t('composites.details.confirm')}\n </p>\n )}\n <div className=\"flex justify-end gap-1.5\">\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setPending(null)}>{t('composites.details.cancel')}</Button>\n <Button size=\"xs\" className=\"bg-(--sk-warning) text-background hover:bg-(--sk-warning)/80\" onClick={apply}>{t('composites.details.change')}</Button>\n </div>\n </div>\n )}\n\n {derivedNode && <DerivationBadge editor={editor} node={derivedNode} detailed />}\n\n {fields.map(field => (\n <div key={field.key} className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{field.label}</span>\n <CompositeFieldEditor editor={editor} row={row} field={field} disabled={!editable} size=\"xs\" />\n </div>\n ))}\n\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{t('composites.details.summary')}</span>\n <CompositeSummaryEditor editor={editor} row={row} readonly={!editable} />\n </div>\n\n {backlinks.length > 0 && (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-xs text-muted-foreground\">{t('composites.reference.backlinks')}</span>\n <ul className=\"flex flex-col gap-0.5\">\n {backlinks.map((link, index) => (\n <li key={`${link.from}:${index}`}>\n <button\n type=\"button\"\n className=\"flex w-full min-w-0 items-baseline gap-1 rounded-sm text-left text-xs text-foreground hover:text-primary focus-visible:outline-2 focus-visible:outline-primary\"\n onClick={() => editor.commands.revealBlock(link.from)}\n >\n <span className=\"truncate\">{link.excerpt || '…'}</span>\n {link.locator && <span className=\"shrink-0 text-muted-foreground\">{link.locator}</span>}\n </button>\n </li>\n ))}\n </ul>\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,16 +1,16 @@
1
- import { CompositeMetaField } from "../kinds.js";
2
- import { CompositeRow } from "../rows.js";
1
+ import { PropertyDefinition } from "../../../core/properties.js";
2
+ import { BlockProperties } from "../properties.js";
3
3
  import { Editor } from "@tiptap/core";
4
4
  //#region src/features/composites/react/CompositeFieldEditor.d.ts
5
5
  /**
6
- * One meta field of a Baustein as an input that writes through `setCompositeMetaField`. Text-like inputs keep a local
6
+ * One Block property of a block as an input that writes through `setBlockProperty`. Text-like inputs keep a local
7
7
  * draft and commit after typing pauses, on blur and on unmount, so the one-frame-late re-read of the rows never
8
8
  * overwrites what is being typed.
9
9
  */
10
10
  export declare function CompositeFieldEditor({ editor, row, field, disabled, size }: {
11
11
  editor: Editor;
12
- row: CompositeRow;
13
- field: CompositeMetaField;
12
+ row: BlockProperties;
13
+ field: PropertyDefinition;
14
14
  disabled?: boolean;
15
15
  size?: 'xs' | 'sm' | 'md';
16
16
  }): import("react").JSX.Element | null;
@@ -1,9 +1,9 @@
1
+ import { propertyHostOf, setBlockProperty } from "../properties.js";
1
2
  import { useEditorI18n } from "../../../react/use-editor-i18n.js";
2
3
  import { cn } from "../../../react/ui/utils.js";
3
4
  import { Input } from "../../../react/ui/input.js";
4
5
  import { Textarea } from "../../../react/ui/textarea.js";
5
6
  import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../react/ui/select.js";
6
- import { compositeOfRow, setCompositeMetaField } from "../rows.js";
7
7
  import { metaText } from "../meta-display.js";
8
8
  import { BibliographyEditor } from "./BibliographyEditor.js";
9
9
  import { DerivationBadge } from "./DerivationBadge.js";
@@ -29,7 +29,7 @@ const SELECT_SIZE = {
29
29
  md: ""
30
30
  };
31
31
  /**
32
- * One meta field of a Baustein as an input that writes through `setCompositeMetaField`. Text-like inputs keep a local
32
+ * One Block property of a block as an input that writes through `setBlockProperty`. Text-like inputs keep a local
33
33
  * draft and commit after typing pauses, on blur and on unmount, so the one-frame-late re-read of the rows never
34
34
  * overwrites what is being typed.
35
35
  */
@@ -64,7 +64,7 @@ function CompositeFieldEditor({ editor, row, field, disabled, size = "sm" }) {
64
64
  if (!dirty.current) return;
65
65
  dirty.current = false;
66
66
  const current = target.current;
67
- if (!current.editor.isDestroyed) setCompositeMetaField(current.editor, current.row, current.field.key, draftRef.current);
67
+ if (!current.editor.isDestroyed) setBlockProperty(current.editor, current.row, current.field.key, draftRef.current);
68
68
  }, []);
69
69
  useEffect(() => commit, [
70
70
  commit,
@@ -84,7 +84,7 @@ function CompositeFieldEditor({ editor, row, field, disabled, size = "sm" }) {
84
84
  commit();
85
85
  }
86
86
  function onChoice(value) {
87
- setCompositeMetaField(editor, row, field.key, value === EMPTY ? "" : value);
87
+ setBlockProperty(editor, row, field.key, value === EMPTY ? "" : value);
88
88
  }
89
89
  if (field.type === "select") return /* @__PURE__ */ jsxs(Select, {
90
90
  value: stored,
@@ -114,7 +114,7 @@ function CompositeFieldEditor({ editor, row, field, disabled, size = "sm" }) {
114
114
  className: "size-3.5 shrink-0 accent-(--sk-primary)",
115
115
  checked: chosen.includes(option.value),
116
116
  disabled,
117
- onChange: (event) => setCompositeMetaField(editor, row, field.key, event.target.checked ? [...chosen, option.value] : chosen.filter((item) => item !== option.value))
117
+ onChange: (event) => setBlockProperty(editor, row, field.key, event.target.checked ? [...chosen, option.value] : chosen.filter((item) => item !== option.value))
118
118
  }), option.label]
119
119
  }, option.value))
120
120
  });
@@ -133,7 +133,7 @@ function CompositeFieldEditor({ editor, row, field, disabled, size = "sm" }) {
133
133
  disabled
134
134
  });
135
135
  if (field.type === "derivation") {
136
- const derived = compositeOfRow(editor.state.doc, row)?.node;
136
+ const derived = propertyHostOf(editor.state.doc, row)?.node;
137
137
  return derived ? /* @__PURE__ */ jsx(DerivationBadge, {
138
138
  editor,
139
139
  node: derived