@bettercms-ai/kit 1.0.0 → 2.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 (587) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +90 -31
  8. package/dist/adapters/lossy.js +414 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
  11. package/{adapters → dist/adapters}/prod-types.js +71 -3
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +996 -179
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +92 -2
  22. package/{context.js → dist/context.js} +5 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/{controls → dist/controls}/form-picker-register.js +1 -1
  50. package/dist/controls/form-picker-register.js.map +1 -0
  51. package/{controls → dist/controls}/form-picker.js +11 -9
  52. package/dist/controls/form-picker.js.map +1 -0
  53. package/{controls → dist/controls}/icon-register.js +1 -1
  54. package/dist/controls/icon-register.js.map +1 -0
  55. package/{controls → dist/controls}/icon.d.ts +4 -2
  56. package/{controls → dist/controls}/icon.js +32 -27
  57. package/dist/controls/icon.js.map +1 -0
  58. package/{controls → dist/controls}/index.d.ts +1 -1
  59. package/{controls → dist/controls}/index.js +4 -3
  60. package/dist/controls/index.js.map +1 -0
  61. package/{controls → dist/controls}/json-register.js +1 -1
  62. package/dist/controls/json-register.js.map +1 -0
  63. package/{controls → dist/controls}/json.js +13 -3
  64. package/dist/controls/json.js.map +1 -0
  65. package/{controls → dist/controls}/link.js +6 -6
  66. package/dist/controls/link.js.map +1 -0
  67. package/{controls → dist/controls}/location-register.js +1 -1
  68. package/dist/controls/location-register.js.map +1 -0
  69. package/{controls → dist/controls}/location.js +64 -40
  70. package/dist/controls/location.js.map +1 -0
  71. package/{controls → dist/controls}/media-register.js +1 -1
  72. package/dist/controls/media-register.js.map +1 -0
  73. package/{controls → dist/controls}/media-services.d.ts +6 -0
  74. package/dist/controls/media-services.js +0 -0
  75. package/{controls → dist/controls}/media.d.ts +35 -4
  76. package/{controls → dist/controls}/media.js +491 -171
  77. package/dist/controls/media.js.map +1 -0
  78. package/{controls → dist/controls}/number.js +10 -9
  79. package/dist/controls/number.js.map +1 -0
  80. package/{controls → dist/controls}/reference-register.js +1 -1
  81. package/dist/controls/reference-register.js.map +1 -0
  82. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  83. package/dist/controls/reference-services.js +0 -0
  84. package/{controls → dist/controls}/reference.d.ts +1 -1
  85. package/{controls → dist/controls}/reference.js +93 -77
  86. package/dist/controls/reference.js.map +1 -0
  87. package/dist/controls/rich-text/blocks.d.ts +49 -0
  88. package/{controls → dist/controls}/rich-text/blocks.js +471 -144
  89. package/dist/controls/rich-text/blocks.js.map +1 -0
  90. package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
  91. package/{controls → dist/controls}/rich-text/catalog.js +75 -65
  92. package/dist/controls/rich-text/catalog.js.map +1 -0
  93. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  94. package/{controls → dist/controls}/rich-text/codec.js +3 -1
  95. package/dist/controls/rich-text/codec.js.map +1 -0
  96. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  97. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  98. package/dist/controls/rich-text/component-card.js.map +1 -0
  99. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  100. package/dist/controls/rich-text/component-panel.js +141 -0
  101. package/dist/controls/rich-text/component-panel.js.map +1 -0
  102. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  103. package/{controls → dist/controls}/rich-text/control.js +84 -42
  104. package/dist/controls/rich-text/control.js.map +1 -0
  105. package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
  106. package/{controls → dist/controls}/rich-text/dom.js +379 -50
  107. package/dist/controls/rich-text/dom.js.map +1 -0
  108. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  109. package/{controls → dist/controls}/rich-text/editor.js +148 -48
  110. package/dist/controls/rich-text/editor.js.map +1 -0
  111. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  112. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  113. package/dist/controls/rich-text/floating.js.map +1 -0
  114. package/{controls → dist/controls}/rich-text/index.js +1 -1
  115. package/dist/controls/rich-text/index.js.map +1 -0
  116. package/dist/controls/rich-text/link-form.js +147 -0
  117. package/dist/controls/rich-text/link-form.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  119. package/dist/controls/rich-text/markdown.js.map +1 -0
  120. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  121. package/dist/controls/rich-text/ops.js.map +1 -0
  122. package/dist/controls/rich-text/plain.d.ts +17 -0
  123. package/dist/controls/rich-text/plain.js +44 -0
  124. package/dist/controls/rich-text/plain.js.map +1 -0
  125. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  126. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  127. package/dist/controls/rich-text/toolbar.js.map +1 -0
  128. package/{controls → dist/controls}/scale.js +5 -5
  129. package/dist/controls/scale.js.map +1 -0
  130. package/{controls → dist/controls}/slot-register.js +1 -1
  131. package/dist/controls/slot-register.js.map +1 -0
  132. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  133. package/dist/controls/slot-services.js +155 -0
  134. package/dist/controls/slot-services.js.map +1 -0
  135. package/{controls → dist/controls}/slot.js +42 -24
  136. package/dist/controls/slot.js.map +1 -0
  137. package/{controls → dist/controls}/table/index.js +1 -1
  138. package/dist/controls/table/index.js.map +1 -0
  139. package/{controls → dist/controls}/table/prod.js +3 -3
  140. package/dist/controls/table/prod.js.map +1 -0
  141. package/{controls → dist/controls}/table/refs.js +13 -2
  142. package/dist/controls/table/refs.js.map +1 -0
  143. package/{controls → dist/controls}/table/stored.js +1 -1
  144. package/dist/controls/table/stored.js.map +1 -0
  145. package/{controls → dist/controls}/table/table-editor.js +51 -48
  146. package/dist/controls/table/table-editor.js.map +1 -0
  147. package/{controls → dist/controls}/table/table-link.js +3 -3
  148. package/dist/controls/table/table-link.js.map +1 -0
  149. package/{controls → dist/controls}/table/table.js +3 -3
  150. package/dist/controls/table/table.js.map +1 -0
  151. package/{controls → dist/controls}/text.d.ts +2 -2
  152. package/{controls → dist/controls}/text.js +78 -43
  153. package/dist/controls/text.js.map +1 -0
  154. package/dist/controls/unknown-value.d.ts +17 -0
  155. package/dist/controls/unknown-value.js +66 -0
  156. package/dist/controls/unknown-value.js.map +1 -0
  157. package/dist/core/core.d.ts +63 -0
  158. package/dist/core/core.js +171 -0
  159. package/dist/core/core.js.map +1 -0
  160. package/dist/core/facets.d.ts +347 -0
  161. package/dist/core/facets.js +334 -0
  162. package/dist/core/facets.js.map +1 -0
  163. package/dist/core/index.d.ts +3 -0
  164. package/dist/core/index.js +3 -0
  165. package/{engine → dist/engine}/array.js +34 -21
  166. package/dist/engine/array.js.map +1 -0
  167. package/{engine → dist/engine}/bits.js +1 -1
  168. package/dist/engine/bits.js.map +1 -0
  169. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  170. package/{engine → dist/engine}/breadcrumb.js +12 -36
  171. package/dist/engine/breadcrumb.js.map +1 -0
  172. package/{engine → dist/engine}/expand.d.ts +2 -4
  173. package/{engine → dist/engine}/expand.js +5 -22
  174. package/dist/engine/expand.js.map +1 -0
  175. package/{engine → dist/engine}/field-list.js +1 -1
  176. package/dist/engine/field-list.js.map +1 -0
  177. package/{engine → dist/engine}/field-shell.js +249 -121
  178. package/dist/engine/field-shell.js.map +1 -0
  179. package/{engine → dist/engine}/frame.d.ts +3 -1
  180. package/{engine → dist/engine}/frame.js +16 -14
  181. package/dist/engine/frame.js.map +1 -0
  182. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  183. package/{engine → dist/engine}/group-summary.js +7 -3
  184. package/dist/engine/group-summary.js.map +1 -0
  185. package/{engine → dist/engine}/grouping.d.ts +19 -5
  186. package/{engine → dist/engine}/grouping.js +193 -21
  187. package/dist/engine/grouping.js.map +1 -0
  188. package/{engine → dist/engine}/item-list.d.ts +11 -1
  189. package/{engine → dist/engine}/item-list.js +35 -13
  190. package/dist/engine/item-list.js.map +1 -0
  191. package/{engine → dist/engine}/kit-field.js +45 -10
  192. package/dist/engine/kit-field.js.map +1 -0
  193. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  194. package/{engine → dist/engine}/schema-form.js +182 -40
  195. package/dist/engine/schema-form.js.map +1 -0
  196. package/{engine → dist/engine}/slot.js +5 -15
  197. package/dist/engine/slot.js.map +1 -0
  198. package/dist/index.js +47 -0
  199. package/dist/index.js.map +1 -0
  200. package/{kit.css → dist/kit.css} +19 -0
  201. package/{lib → dist/lib}/cn.js +7 -4
  202. package/dist/lib/cn.js.map +1 -0
  203. package/{lib → dist/lib}/columns.js +4 -1
  204. package/dist/lib/columns.js.map +1 -0
  205. package/{lib → dist/lib}/frames.js +2 -2
  206. package/dist/lib/frames.js.map +1 -0
  207. package/dist/lib/icon-image.d.ts +10 -0
  208. package/dist/lib/icon-image.js +8 -0
  209. package/dist/lib/icon-image.js.map +1 -0
  210. package/{lib → dist/lib}/icons.js +4 -3
  211. package/dist/lib/icons.js.map +1 -0
  212. package/dist/lib/input-modality.d.ts +11 -0
  213. package/dist/lib/input-modality.js +47 -0
  214. package/dist/lib/input-modality.js.map +1 -0
  215. package/dist/lib/key-event.d.ts +11 -0
  216. package/dist/lib/key-event.js +16 -0
  217. package/dist/lib/key-event.js.map +1 -0
  218. package/{lib → dist/lib}/path.js +4 -2
  219. package/dist/lib/path.js.map +1 -0
  220. package/{lib → dist/lib}/schema.d.ts +34 -3
  221. package/{lib → dist/lib}/schema.js +110 -13
  222. package/dist/lib/schema.js.map +1 -0
  223. package/{lib → dist/lib}/utils.js +1 -1
  224. package/dist/lib/utils.js.map +1 -0
  225. package/{lib → dist/lib}/validate.d.ts +11 -1
  226. package/{lib → dist/lib}/validate.js +85 -11
  227. package/dist/lib/validate.js.map +1 -0
  228. package/dist/library/analysis.d.ts +23 -0
  229. package/dist/library/analysis.js +160 -0
  230. package/dist/library/analysis.js.map +1 -0
  231. package/dist/library/catalog.d.ts +57 -0
  232. package/dist/library/catalog.js +307 -0
  233. package/dist/library/catalog.js.map +1 -0
  234. package/dist/library/coreNotes.d.ts +8 -0
  235. package/dist/library/coreNotes.js +111 -0
  236. package/dist/library/coreNotes.js.map +1 -0
  237. package/dist/library/coverage.d.ts +40 -0
  238. package/dist/library/coverage.js +59 -0
  239. package/dist/library/coverage.js.map +1 -0
  240. package/dist/library/entries/advanced.entries.d.ts +2 -0
  241. package/dist/library/entries/advanced.entries.js +6579 -0
  242. package/dist/library/entries/advanced.entries.js.map +1 -0
  243. package/dist/library/entries/commerce.entries.d.ts +2 -0
  244. package/dist/library/entries/commerce.entries.js +4140 -0
  245. package/dist/library/entries/commerce.entries.js.map +1 -0
  246. package/dist/library/entries/company.entries.d.ts +2 -0
  247. package/dist/library/entries/company.entries.js +2731 -0
  248. package/dist/library/entries/company.entries.js.map +1 -0
  249. package/dist/library/entries/conversion.entries.d.ts +2 -0
  250. package/dist/library/entries/conversion.entries.js +3707 -0
  251. package/dist/library/entries/conversion.entries.js.map +1 -0
  252. package/dist/library/entries/data.entries.d.ts +7 -0
  253. package/dist/library/entries/data.entries.js +4613 -0
  254. package/dist/library/entries/data.entries.js.map +1 -0
  255. package/dist/library/entries/events.entries.d.ts +2 -0
  256. package/dist/library/entries/events.entries.js +3428 -0
  257. package/dist/library/entries/events.entries.js.map +1 -0
  258. package/dist/library/entries/features.entries.d.ts +2 -0
  259. package/dist/library/entries/features.entries.js +3157 -0
  260. package/dist/library/entries/features.entries.js.map +1 -0
  261. package/dist/library/entries/heroes.entries.d.ts +2 -0
  262. package/dist/library/entries/heroes.entries.js +3401 -0
  263. package/dist/library/entries/heroes.entries.js.map +1 -0
  264. package/dist/library/entries/index.d.ts +3 -0
  265. package/dist/library/entries/index.js +35 -0
  266. package/dist/library/entries/index.js.map +1 -0
  267. package/dist/library/entries/listings.entries.d.ts +2 -0
  268. package/dist/library/entries/listings.entries.js +2976 -0
  269. package/dist/library/entries/listings.entries.js.map +1 -0
  270. package/dist/library/entries/longform.entries.d.ts +2 -0
  271. package/dist/library/entries/longform.entries.js +4227 -0
  272. package/dist/library/entries/longform.entries.js.map +1 -0
  273. package/dist/library/entries/media.entries.d.ts +2 -0
  274. package/dist/library/entries/media.entries.js +2781 -0
  275. package/dist/library/entries/media.entries.js.map +1 -0
  276. package/dist/library/entries/navigation.entries.d.ts +2 -0
  277. package/dist/library/entries/navigation.entries.js +4011 -0
  278. package/dist/library/entries/navigation.entries.js.map +1 -0
  279. package/dist/library/entries/pricing.entries.d.ts +2 -0
  280. package/dist/library/entries/pricing.entries.js +2383 -0
  281. package/dist/library/entries/pricing.entries.js.map +1 -0
  282. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  283. package/dist/library/entries/social-proof.entries.js +2297 -0
  284. package/dist/library/entries/social-proof.entries.js.map +1 -0
  285. package/dist/library/examples/bento.d.ts +92 -0
  286. package/dist/library/examples/bento.js +201 -0
  287. package/dist/library/examples/bento.js.map +1 -0
  288. package/dist/library/examples/blocks.d.ts +14 -0
  289. package/dist/library/examples/blocks.js +313 -0
  290. package/dist/library/examples/blocks.js.map +1 -0
  291. package/dist/library/examples/faq.d.ts +28 -0
  292. package/dist/library/examples/faq.js +230 -0
  293. package/dist/library/examples/faq.js.map +1 -0
  294. package/dist/library/examples/hero.d.ts +43 -0
  295. package/dist/library/examples/hero.js +222 -0
  296. package/dist/library/examples/hero.js.map +1 -0
  297. package/dist/library/examples/index.d.ts +36 -0
  298. package/dist/library/examples/index.js +109 -0
  299. package/dist/library/examples/index.js.map +1 -0
  300. package/dist/library/examples/journalStory.d.ts +93 -0
  301. package/dist/library/examples/journalStory.js +338 -0
  302. package/dist/library/examples/journalStory.js.map +1 -0
  303. package/dist/library/examples/megaMenu.d.ts +134 -0
  304. package/dist/library/examples/megaMenu.js +442 -0
  305. package/dist/library/examples/megaMenu.js.map +1 -0
  306. package/dist/library/examples/pricing.d.ts +103 -0
  307. package/dist/library/examples/pricing.js +479 -0
  308. package/dist/library/examples/pricing.js.map +1 -0
  309. package/dist/library/examples/tabs.d.ts +87 -0
  310. package/dist/library/examples/tabs.js +180 -0
  311. package/dist/library/examples/tabs.js.map +1 -0
  312. package/dist/library/export.d.ts +42 -0
  313. package/dist/library/export.js +80 -0
  314. package/dist/library/export.js.map +1 -0
  315. package/dist/library/index.d.ts +13 -0
  316. package/dist/library/index.js +6 -0
  317. package/dist/library/kit-catalog.json +1510 -0
  318. package/dist/library/types.d.ts +42 -0
  319. package/dist/library/types.js +0 -0
  320. package/{schema → dist/schema}/adapters.js +1 -2
  321. package/dist/schema/adapters.js.map +1 -0
  322. package/{schema → dist/schema}/help.d.ts +2 -0
  323. package/{schema → dist/schema}/help.js +6 -4
  324. package/dist/schema/help.js.map +1 -0
  325. package/{schema → dist/schema}/scale.js +1 -1
  326. package/dist/schema/scale.js.map +1 -0
  327. package/{schema → dist/schema}/sources.js +1 -1
  328. package/dist/schema/sources.js.map +1 -0
  329. package/{schema → dist/schema}/table.js +11 -10
  330. package/dist/schema/table.js.map +1 -0
  331. package/{schema → dist/schema}/types.d.ts +29 -1
  332. package/{schema → dist/schema}/types.js +1 -1
  333. package/dist/schema/types.js.map +1 -0
  334. package/dist/styles.css +2 -0
  335. package/dist/table/table-view.d.ts +14 -0
  336. package/dist/table/table-view.js +140 -0
  337. package/dist/table/table-view.js.map +1 -0
  338. package/dist/table/table.css +73 -0
  339. package/dist/testing/corpus.d.ts +63 -0
  340. package/dist/testing/corpus.js +129 -0
  341. package/dist/testing/corpus.js.map +1 -0
  342. package/dist/testing/test-form.d.ts +11 -0
  343. package/dist/testing/test-form.js +38 -0
  344. package/dist/testing/test-form.js.map +1 -0
  345. package/dist/theme.css +345 -0
  346. package/dist/theme.d.ts +22 -0
  347. package/dist/theme.js +43 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens.css +542 -0
  350. package/dist/types.js +0 -0
  351. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  352. package/{ui → dist/ui}/action-tray.js +20 -19
  353. package/dist/ui/action-tray.js.map +1 -0
  354. package/dist/ui/autocomplete.d.ts +30 -0
  355. package/dist/ui/autocomplete.js +139 -0
  356. package/dist/ui/autocomplete.js.map +1 -0
  357. package/{ui → dist/ui}/button.d.ts +3 -3
  358. package/{ui → dist/ui}/button.js +6 -7
  359. package/dist/ui/button.js.map +1 -0
  360. package/{ui → dist/ui}/choice-switch.js +1 -1
  361. package/dist/ui/choice-switch.js.map +1 -0
  362. package/{ui → dist/ui}/controls.js +51 -39
  363. package/dist/ui/controls.js.map +1 -0
  364. package/{ui → dist/ui}/display.d.ts +10 -3
  365. package/{ui → dist/ui}/display.js +57 -46
  366. package/dist/ui/display.js.map +1 -0
  367. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  368. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  369. package/dist/ui/expanded-editor-modal.js.map +1 -0
  370. package/{ui → dist/ui}/field-context.js +1 -1
  371. package/dist/ui/field-context.js.map +1 -0
  372. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  373. package/{ui → dist/ui}/floating-panel.js +28 -12
  374. package/dist/ui/floating-panel.js.map +1 -0
  375. package/{ui → dist/ui}/index.d.ts +4 -0
  376. package/dist/ui/index.js +18 -0
  377. package/{ui → dist/ui}/input.d.ts +1 -1
  378. package/{ui → dist/ui}/input.js +9 -9
  379. package/dist/ui/input.js.map +1 -0
  380. package/{ui → dist/ui}/mode-bar.js +3 -3
  381. package/dist/ui/mode-bar.js.map +1 -0
  382. package/{ui → dist/ui}/overlay.d.ts +77 -5
  383. package/dist/ui/overlay.js +697 -0
  384. package/dist/ui/overlay.js.map +1 -0
  385. package/{ui → dist/ui}/path-crumbs.js +37 -3
  386. package/dist/ui/path-crumbs.js.map +1 -0
  387. package/{ui → dist/ui}/presence.js +2 -2
  388. package/dist/ui/presence.js.map +1 -0
  389. package/{ui → dist/ui}/select.js +89 -87
  390. package/dist/ui/select.js.map +1 -0
  391. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  392. package/dist/ui/shortcut-hint.js.map +1 -0
  393. package/dist/ui/spinner.d.ts +24 -0
  394. package/dist/ui/spinner.js +42 -0
  395. package/dist/ui/spinner.js.map +1 -0
  396. package/dist/ui/split-button.d.ts +32 -0
  397. package/dist/ui/split-button.js +60 -0
  398. package/dist/ui/split-button.js.map +1 -0
  399. package/{ui → dist/ui}/surfaces.js +1 -1
  400. package/dist/ui/surfaces.js.map +1 -0
  401. package/dist/ui/tab.d.ts +38 -0
  402. package/dist/ui/tab.js +87 -0
  403. package/dist/ui/tab.js.map +1 -0
  404. package/dist/ui/toast.d.ts +20 -0
  405. package/dist/ui/toast.js +115 -0
  406. package/dist/ui/toast.js.map +1 -0
  407. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  408. package/{ui → dist/ui}/tooltip-root.js +9 -8
  409. package/dist/ui/tooltip-root.js.map +1 -0
  410. package/{ui → dist/ui}/variants.js +1 -1
  411. package/dist/ui/variants.js.map +1 -0
  412. package/package.json +77 -23
  413. package/adapters/icons.js.map +0 -1
  414. package/adapters/lossy.js +0 -233
  415. package/adapters/lossy.js.map +0 -1
  416. package/adapters/prod-types.js.map +0 -1
  417. package/adapters/schema.js.map +0 -1
  418. package/adapters/values.js.map +0 -1
  419. package/brand/logo.js +0 -9
  420. package/brand/logo.js.map +0 -1
  421. package/context.js.map +0 -1
  422. package/controls/button.js.map +0 -1
  423. package/controls/c1.js.map +0 -1
  424. package/controls/c2.js.map +0 -1
  425. package/controls/choice.js.map +0 -1
  426. package/controls/code-register.js.map +0 -1
  427. package/controls/code.js.map +0 -1
  428. package/controls/color.js.map +0 -1
  429. package/controls/date-register.js.map +0 -1
  430. package/controls/date-zone.js.map +0 -1
  431. package/controls/date.js.map +0 -1
  432. package/controls/form-picker-register.js.map +0 -1
  433. package/controls/form-picker.js.map +0 -1
  434. package/controls/icon-register.js.map +0 -1
  435. package/controls/icon.js.map +0 -1
  436. package/controls/index.js.map +0 -1
  437. package/controls/json-register.js.map +0 -1
  438. package/controls/json.js.map +0 -1
  439. package/controls/link.js.map +0 -1
  440. package/controls/location-register.js.map +0 -1
  441. package/controls/location.js.map +0 -1
  442. package/controls/media-register.js.map +0 -1
  443. package/controls/media.js.map +0 -1
  444. package/controls/number.js.map +0 -1
  445. package/controls/reference-register.js.map +0 -1
  446. package/controls/reference.js.map +0 -1
  447. package/controls/rich-text/blocks.d.ts +0 -28
  448. package/controls/rich-text/blocks.js.map +0 -1
  449. package/controls/rich-text/catalog.js.map +0 -1
  450. package/controls/rich-text/codec.js.map +0 -1
  451. package/controls/rich-text/component-card.js.map +0 -1
  452. package/controls/rich-text/control.js.map +0 -1
  453. package/controls/rich-text/dom.js.map +0 -1
  454. package/controls/rich-text/editor.js.map +0 -1
  455. package/controls/rich-text/floating.js.map +0 -1
  456. package/controls/rich-text/index.js.map +0 -1
  457. package/controls/rich-text/link-form.js +0 -111
  458. package/controls/rich-text/link-form.js.map +0 -1
  459. package/controls/rich-text/markdown.js.map +0 -1
  460. package/controls/rich-text/ops.js.map +0 -1
  461. package/controls/rich-text/toolbar.js.map +0 -1
  462. package/controls/scale.js.map +0 -1
  463. package/controls/slot-register.js.map +0 -1
  464. package/controls/slot-services.js +0 -38
  465. package/controls/slot-services.js.map +0 -1
  466. package/controls/slot.js.map +0 -1
  467. package/controls/table/index.js.map +0 -1
  468. package/controls/table/prod.js.map +0 -1
  469. package/controls/table/refs.js.map +0 -1
  470. package/controls/table/stored.js.map +0 -1
  471. package/controls/table/table-editor.js.map +0 -1
  472. package/controls/table/table-link.js.map +0 -1
  473. package/controls/table/table.js.map +0 -1
  474. package/controls/text.js.map +0 -1
  475. package/engine/array.js.map +0 -1
  476. package/engine/bits.js.map +0 -1
  477. package/engine/breadcrumb.js.map +0 -1
  478. package/engine/expand.js.map +0 -1
  479. package/engine/field-list.js.map +0 -1
  480. package/engine/field-shell.js.map +0 -1
  481. package/engine/frame.js.map +0 -1
  482. package/engine/group-summary.js.map +0 -1
  483. package/engine/grouping.js.map +0 -1
  484. package/engine/item-list.js.map +0 -1
  485. package/engine/kit-field.js.map +0 -1
  486. package/engine/schema-form.js.map +0 -1
  487. package/engine/slot.js.map +0 -1
  488. package/index.js +0 -55
  489. package/index.js.map +0 -1
  490. package/lib/cn.js.map +0 -1
  491. package/lib/columns.js.map +0 -1
  492. package/lib/frames.js.map +0 -1
  493. package/lib/icons.js.map +0 -1
  494. package/lib/path.js.map +0 -1
  495. package/lib/schema.js.map +0 -1
  496. package/lib/utils.js.map +0 -1
  497. package/lib/validate.js.map +0 -1
  498. package/schema/adapters.js.map +0 -1
  499. package/schema/help.js.map +0 -1
  500. package/schema/scale.js.map +0 -1
  501. package/schema/sources.js.map +0 -1
  502. package/schema/table.js.map +0 -1
  503. package/schema/types.js.map +0 -1
  504. package/ui/action-tray.js.map +0 -1
  505. package/ui/button.js.map +0 -1
  506. package/ui/choice-switch.js.map +0 -1
  507. package/ui/controls.js.map +0 -1
  508. package/ui/display.js.map +0 -1
  509. package/ui/expanded-editor-modal.js.map +0 -1
  510. package/ui/field-context.js.map +0 -1
  511. package/ui/floating-panel.js.map +0 -1
  512. package/ui/index.js +0 -13
  513. package/ui/input.js.map +0 -1
  514. package/ui/mode-bar.js.map +0 -1
  515. package/ui/overlay.js +0 -378
  516. package/ui/overlay.js.map +0 -1
  517. package/ui/path-crumbs.js.map +0 -1
  518. package/ui/presence.js.map +0 -1
  519. package/ui/select.js.map +0 -1
  520. package/ui/shortcut-hint.js.map +0 -1
  521. package/ui/surfaces.js.map +0 -1
  522. package/ui/tooltip-root.js.map +0 -1
  523. package/ui/variants.js.map +0 -1
  524. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  525. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  526. /package/{brand → dist/brand}/logo.d.ts +0 -0
  527. /package/{controls → dist/controls}/c1.d.ts +0 -0
  528. /package/{controls → dist/controls}/c2.d.ts +0 -0
  529. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  530. /package/{controls → dist/controls}/code.d.ts +0 -0
  531. /package/{controls → dist/controls}/color.d.ts +0 -0
  532. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  533. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  534. /package/{controls → dist/controls}/date.d.ts +0 -0
  535. /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
  536. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  537. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  538. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  539. /package/{controls → dist/controls}/json.d.ts +0 -0
  540. /package/{controls → dist/controls}/link.d.ts +0 -0
  541. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  542. /package/{controls → dist/controls}/location.d.ts +0 -0
  543. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  544. /package/{controls → dist/controls}/number.d.ts +0 -0
  545. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  546. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  547. /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
  548. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  549. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  550. /package/{controls → dist/controls}/scale.d.ts +0 -0
  551. /package/{controls → dist/controls}/slot-register.d.ts +0 -0
  552. /package/{controls → dist/controls}/slot.d.ts +0 -0
  553. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  554. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  555. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  556. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  557. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  558. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  559. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  560. /package/{engine → dist/engine}/array.d.ts +0 -0
  561. /package/{engine → dist/engine}/bits.d.ts +0 -0
  562. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  563. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  564. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  565. /package/{engine → dist/engine}/slot.d.ts +0 -0
  566. /package/{index.d.ts → dist/index.d.ts} +0 -0
  567. /package/{lib → dist/lib}/cn.d.ts +0 -0
  568. /package/{lib → dist/lib}/columns.d.ts +0 -0
  569. /package/{lib → dist/lib}/frames.d.ts +0 -0
  570. /package/{lib → dist/lib}/icons.d.ts +0 -0
  571. /package/{lib → dist/lib}/path.d.ts +0 -0
  572. /package/{lib → dist/lib}/utils.d.ts +0 -0
  573. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  574. /package/{schema → dist/schema}/scale.d.ts +0 -0
  575. /package/{schema → dist/schema}/sources.d.ts +0 -0
  576. /package/{schema → dist/schema}/table.d.ts +0 -0
  577. /package/{types.d.ts → dist/types.d.ts} +0 -0
  578. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  579. /package/{ui → dist/ui}/controls.d.ts +0 -0
  580. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  581. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  582. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  583. /package/{ui → dist/ui}/presence.d.ts +0 -0
  584. /package/{ui → dist/ui}/select.d.ts +0 -0
  585. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  586. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  587. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"dom.js","names":[],"sources":["../../../src/kit/controls/rich-text/dom.ts"],"sourcesContent":["/**\n * RICH TEXT · DOM layer (V2 HEAD controls/rich-text/dom.ts). The field value is clean, semantic HTML; rich blocks are\n * \"islands\" while editing.\n *\n * Live DOM = the HTML, with every rich block swapped for a `div[data-rt-island=\"kind\"]` (contenteditable=false) that\n * React renders into through a portal. The island's model lives on the element (`el.__rt`).\n * Stored = `serialize()` swaps each island back for its static HTML (`renderStatic`). The static form is the markup\n * production's own renderer writes for the same block, so the host's ingest reads it back as that block.\n * Loading = `hydrate()` turns that markup back into islands, so a re-mount restores them.\n *\n * Only the blocks production stores are islands here. Each one's markup is what the host's codec renders the stored\n * block as and reads back (features/dock-v2/richTextCodec.ts); `data-extra` carries, opaque, whatever of the stored block\n * the editor does not edit, so nothing it holds is dropped by an edit elsewhere.\n * image `bcmsBlock` builtin:image: address, alt text, caption, alignment, size, link\n * (`<figure data-rt=\"image\" data-align data-size><a href><img src alt></a><figcaption>`)\n * table production's Portable Text table (rows of cells, a header row, header cells, and the V2 table's caption,\n * note, row groups and column groups), drawn with the kit's table editor (V2 TableBlock), stored as the markup\n * production's renderer writes (`<caption>`, `th[scope=colgroup data-group]`, a `<tbody data-key>` per row\n * group under a `th[scope=rowgroup]` row, `<figure data-rt=\"table\">…<p data-notes>` for the note; footnotes\n * fold into the note as `[1] …`, as production's ingest folds V2's). A cell's closing\n * footnote markers (`<sup data-footnote>`) ride the cell as written (`marks`). A table whose cells hold\n * other inline formatting the table value has no place for (a term, bold) is not an island: it stays\n * markup in the body, edited in place, so the formatting survives.\n * pullquote V2 article block (CPO D55), `<figure data-rt=\"pullquote\">` → a `pullQuote` block.\n * takeaways V2 article block (CPO D55), `<aside data-rt=\"takeaways\"><p data-title>…<ul><li>…` → a `keyTakeaways` block\n * {title?, points} (written in the text itself, V2 TakeawaysEditor).\n * callout `bcmsBlock` builtin:callout {tone, title, message}: `<div data-rt=\"callout\" data-callout><p data-title>…\n * <div data-body><p>…` (the message is plain text: paragraphs and line breaks)\n * toggle `bcmsBlock` builtin:toggle {title, body}: `<details data-rt=\"toggle\"><summary>…<div data-body><p>…`\n * video the `video` block {src, title}: `<div data-rt=\"video\" data-url data-title>`\n * file the `file` block {src, name, size}: `<div data-rt=\"file\" data-url data-name data-size>`\n * component `bcmsBlock` \"component\" {componentId, overrides, variant} (CPO D28): `<div data-rt=\"component\" data-ref\n * data-id data-name data-overrides data-variant>` — a linked instance of a project component, shown as a card.\n * A separate copy (V2 instances.ts `detach`) adds {detached, props, blocks, sourcePublishedAt}:\n * `data-detached=\"true\" data-props data-blocks data-source-published-at`, and carries no overrides.\n * A key the stored block holds is an attribute or element that is present; a key it lacks is absent, so an untouched\n * block reads back exactly as stored.\n * V2's gallery, embed, columns, footnotes, contents, related posts and author bio have no stored form in\n * production and are not offered.\n */\n\nimport { cellText, cellValue, emptyTable, isCellObject, isObjLike, normalizeTable, parseTableElement, tkey, type TableColumn, type TableGroup, type TableLink, type TableRow, type TableValue } from \"../../schema/table\";\n\nexport const esc = (s: string) => s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\nexport const escAttr = (s: string) => esc(s).replace(/\"/g, \"&quot;\");\nlet seq = 0;\nexport const rid = (p = \"r\") => `${p}${Date.now().toString(36)}${(seq++).toString(36)}`;\n\n/* ── Island models ─────────────────────────────────────────────────── */\nexport type ImageAlign = \"full\" | \"center\" | \"left\" | \"right\";\nexport type ImageSize = \"s\" | \"m\" | \"l\" | \"full\";\nexport const IMAGE_ALIGNS: readonly ImageAlign[] = [\"full\", \"center\", \"left\", \"right\"];\nexport const IMAGE_SIZES: readonly ImageSize[] = [\"s\", \"m\", \"l\", \"full\"];\n/** Every optional key is absent when the stored block lacks it (see the header). */\nexport interface ImageModel {\n src: string;\n /** absent only on a stored block that never had one (every new image has alt text, empty or not) */\n alt?: string;\n caption?: string;\n align?: ImageAlign;\n size?: ImageSize;\n href?: string;\n /** the stored block's other keys, opaque to the editor */\n extra?: string;\n}\n/** A table island IS the kit's table value (V2 TableModel); only what production's table keeps is stored (see above). */\nexport type TableModel = TableValue;\n/** V2 PullQuoteModel (article.ts). */\nexport interface PullQuoteModel {\n quote: string;\n name: string;\n role: string;\n link: string;\n}\n/** V2 TakeawaysModel (article.ts): the title over the list and one plain string per point. */\nexport interface TakeawaysModel {\n title: string;\n points: string[];\n}\nexport type CalloutTone = \"info\" | \"tip\" | \"warning\";\nexport const CALLOUT_TONES: readonly CalloutTone[] = [\"info\", \"tip\", \"warning\"];\nexport interface CalloutModel {\n /** the stored tone, as written (the editor offers info, tip and warning) */\n tone?: string;\n title?: string;\n /** plain text: paragraphs split by a blank line, line breaks kept */\n body?: string;\n extra?: string;\n}\nexport interface ToggleModel {\n title?: string;\n body?: string;\n extra?: string;\n}\nexport interface VideoModel {\n url?: string;\n title?: string;\n extra?: string;\n}\nexport interface FileModel {\n url?: string;\n name?: string;\n size?: number;\n extra?: string;\n}\n/** A linked instance of a project component (CPO D28): its library id, its own id, its name and its overrides. */\nexport interface ComponentModel {\n /** the component it links to (`fields.componentId`) */\n ref?: string;\n /** this instance (the block's key) */\n id: string;\n /** the component's name when it was placed (`schemaLabel`) */\n name?: string;\n /** the fields this instance overrides, as stored JSON */\n overrides?: string;\n /** the layout this instance draws the component in (V2's per-instance variant, `fields.variant`) */\n variant?: string;\n /** V2 `detached`: a separate copy that no longer follows the component (`fields.detached`) */\n detached?: boolean;\n /** a separate copy's values as readers see them, as stored JSON (V2 `props`, `fields.props`) */\n props?: string;\n /** a separate copy's frozen block tree, as stored JSON (`fields.blocks`); the editor never edits it */\n blocks?: string;\n /** the version of the component the copy was taken from (`fields.sourcePublishedAt`) */\n sourcePublishedAt?: string;\n extra?: string;\n}\nexport interface IslandModels {\n image: ImageModel;\n table: TableModel;\n pullquote: PullQuoteModel;\n takeaways: TakeawaysModel;\n callout: CalloutModel;\n toggle: ToggleModel;\n video: VideoModel;\n file: FileModel;\n component: ComponentModel;\n}\nexport type IslandKind = keyof IslandModels;\nexport const ISLAND_KINDS: IslandKind[] = [\"image\", \"table\", \"pullquote\", \"takeaways\", \"callout\", \"toggle\", \"video\", \"file\", \"component\"];\nexport type IslandEl = HTMLElement & {\n __rt?: IslandModels[IslandKind];\n __rtFocus?: boolean;\n /** the mounted island's own setter: restores a model from the editor's history (undo / redo) */\n __rtSet?: (m: IslandModels[IslandKind]) => void;\n};\n\nexport function defaultModel<K extends IslandKind>(kind: K, extra?: Partial<IslandModels[K]>): IslandModels[K] {\n const base: { [P in IslandKind]: () => IslandModels[P] } = {\n image: () => ({ src: \"\", alt: \"\" }),\n table: () => emptyTable(3, 2),\n pullquote: () => ({ quote: \"\", name: \"\", role: \"\", link: \"\" }),\n takeaways: () => ({ title: \"Key takeaways\", points: [\"\"] }),\n callout: () => ({ tone: \"info\", title: \"\", body: \"\" }),\n toggle: () => ({ title: \"\", body: \"\" }),\n video: () => ({ url: \"\" }),\n file: () => ({ url: \"\", name: \"\" }),\n component: () => ({ id: rid(\"ci\"), overrides: \"{}\" }),\n };\n if (kind === \"table\") return { ...base.table(), ...(extra ?? {}), id: tkey(\"tbl\") } as IslandModels[K];\n return { ...base[kind](), ...(extra ?? {}) } as IslandModels[K];\n}\n\n/** Deep copy (Duplicate). A copied table or component instance gets its own id. */\nexport const cloneModel = <K extends IslandKind>(kind: K, m: IslandModels[K]): IslandModels[K] => {\n const c = JSON.parse(JSON.stringify(m)) as IslandModels[K];\n if (kind === \"table\") (c as TableModel).id = tkey(\"tbl\");\n if (kind === \"component\") (c as ComponentModel).id = rid(\"ci\");\n return c;\n};\n\n/* ── plain text ⇄ paragraphs (a callout's message, a toggle's body) ── */\n/** \"a\\nb\\n\\nc\" → `<p>a<br>b</p><p>c</p>`. Split on exactly one blank line, so any text reads back as written. */\nexport const textToParas = (s: string) =>\n s\n .split(\"\\n\\n\")\n .map((p) => `<p>${esc(p).replace(/\\n/g, \"<br>\")}</p>`)\n .join(\"\");\n/** The inverse of textToParas: each paragraph's text, its line breaks kept. */\nexport function parasToText(el: Element): string {\n const ps = Array.from(el.children).filter((c) => c.tagName === \"P\");\n const text = (n: Element) => {\n const c = n.cloneNode(true) as Element;\n c.querySelectorAll(\"br\").forEach((br) => br.replaceWith(\"\\n\"));\n return (c.textContent ?? \"\").replace(/\\u200b/g, \"\");\n };\n return ps.length ? ps.map(text).join(\"\\n\\n\") : text(el);\n}\n\n/* ── Static HTML (stored) ──────────────────────────────────────────── */\n/** An image is `<figure><img src alt></figure>`: production's renderer writes exactly this, and its ingest reads it. */\nconst xAttr = (extra?: string) => (extra ? ` data-extra=\"${escAttr(extra)}\"` : \"\");\nconst attr = (name: string, v: string | number | undefined) => (v === undefined ? \"\" : ` ${name}=\"${escAttr(String(v))}\"`);\n\nexport function renderStatic(kind: IslandKind, model: unknown): string {\n switch (kind) {\n case \"image\": {\n const m = model as ImageModel;\n const img = m.src ? `<img src=\"${escAttr(m.src)}\"${attr(\"alt\", m.alt)}>` : \"\";\n const linked = img && m.href !== undefined ? `<a href=\"${escAttr(m.href)}\">${img}</a>` : img;\n const cap = m.caption !== undefined ? `<figcaption>${esc(m.caption)}</figcaption>` : \"\";\n return `<figure data-rt=\"image\"${attr(\"data-align\", m.align)}${attr(\"data-size\", m.size)}${xAttr(m.extra)}>${linked}${cap}</figure>`;\n }\n case \"table\":\n return renderStoredTable(model as TableModel);\n case \"pullquote\": {\n // V2 article.ts renderArticle(\"pullquote\")\n const m = model as PullQuoteModel;\n const name = m.name ? (m.link ? `<a href=\"${escAttr(m.link)}\" data-name>${esc(m.name)}</a>` : `<span data-name>${esc(m.name)}</span>`) : \"\";\n const role = m.role ? `<span data-role>${esc(m.role)}</span>` : \"\";\n const cap = name || role ? `<figcaption>${name}${name && role ? \", \" : \"\"}${role}</figcaption>` : \"\";\n return `<figure data-rt=\"pullquote\"><blockquote${m.link ? ` cite=\"${escAttr(m.link)}\"` : \"\"}><p>${esc(m.quote)}</p></blockquote>${cap}</figure>`;\n }\n case \"takeaways\": {\n // V2 article.ts renderArticle(\"takeaways\")\n const m = model as TakeawaysModel;\n const pts = m.points.map((p) => p.trim()).filter(Boolean);\n return `<aside data-rt=\"takeaways\">${m.title ? `<p data-title>${esc(m.title)}</p>` : \"\"}<ul>${pts.map((p) => `<li>${esc(p)}</li>`).join(\"\")}</ul></aside>`;\n }\n case \"callout\": {\n const m = model as CalloutModel;\n const title = m.title !== undefined ? `<p data-title=\"true\">${esc(m.title)}</p>` : \"\";\n const body = m.body !== undefined ? `<div data-body=\"true\">${textToParas(m.body)}</div>` : \"\";\n return `<div data-rt=\"callout\"${attr(\"data-callout\", m.tone)}${xAttr(m.extra)}>${title}${body}</div>`;\n }\n case \"toggle\": {\n const m = model as ToggleModel;\n const title = m.title !== undefined ? `<summary>${esc(m.title)}</summary>` : \"\";\n const body = m.body !== undefined ? `<div data-body=\"true\">${textToParas(m.body)}</div>` : \"\";\n return `<details data-rt=\"toggle\"${xAttr(m.extra)}>${title}${body}</details>`;\n }\n case \"video\": {\n const m = model as VideoModel;\n return `<div data-rt=\"video\"${attr(\"data-url\", m.url)}${attr(\"data-title\", m.title)}${xAttr(m.extra)}>${m.url ? `<a href=\"${escAttr(m.url)}\">${esc(m.title || m.url)}</a>` : \"\"}</div>`;\n }\n case \"file\": {\n const m = model as FileModel;\n const link = m.url && m.name ? `<a href=\"${escAttr(m.url)}\" download>${esc(m.name)}</a>` : \"\";\n return `<div data-rt=\"file\"${attr(\"data-url\", m.url)}${attr(\"data-name\", m.name)}${attr(\"data-size\", m.size)}${xAttr(m.extra)}>${link}</div>`;\n }\n case \"component\": {\n const m = model as ComponentModel;\n const label = m.name || \"Component\";\n const copy = m.detached ? ` data-detached=\"true\"${attr(\"data-props\", m.props)}${attr(\"data-blocks\", m.blocks)}${attr(\"data-source-published-at\", m.sourcePublishedAt)}` : \"\";\n return `<div data-rt=\"component\"${attr(\"data-ref\", m.ref)} data-id=\"${escAttr(m.id)}\"${attr(\"data-name\", m.name)}${attr(\"data-overrides\", m.overrides)}${attr(\"data-variant\", m.variant)}${copy}${xAttr(m.extra)}>⧉&nbsp;${esc(label)} · ${m.detached ? \"detached copy\" : \"component\"}</div>`;\n }\n }\n}\n\n/* The V2 table's group rows, read as production's ingest reads them (@bettercms-ai/richtext ingest.ts). */\nconst words = (el: Element | null | undefined) => (el?.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\nconst scopeIs = (c: Element, scope: string) => c.tagName === \"TH\" && (c.getAttribute(\"scope\") ?? \"\").toLowerCase() === scope;\n/** In `<thead>`: a `th[scope=colgroup]`, every other cell an empty `<td>`. A site's own two-row header stays rows. */\nconst isColumnGroupRow = (tr: HTMLTableRowElement) =>\n tr.parentElement?.tagName === \"THEAD\" &&\n Array.from(tr.cells).some((c) => scopeIs(c, \"colgroup\")) &&\n Array.from(tr.cells).every((c) => scopeIs(c, \"colgroup\") || (c.tagName === \"TD\" && !words(c)));\n/**\n * One `th[scope=rowgroup]` and nothing else, OPENING its own `<tbody>` with a body row after it (what production and\n * V2 write). A site's own `scope=rowgroup` row anywhere else stays a row, as production's ingest keeps it.\n */\nconst isRowGroupRow = (tr: HTMLTableRowElement) => {\n const body = tr.parentElement;\n if (tr.cells.length !== 1 || !scopeIs(tr.cells[0], \"rowgroup\") || body?.tagName !== \"TBODY\") return false;\n const rows = Array.from(body.children).filter((r) => r.tagName === \"TR\");\n return rows[0] === tr && rows.length > 1;\n};\nconst KEY = /^[A-Za-z0-9-]{1,32}$/;\n\n/**\n * Production's table markup → the table value, cell for cell (renderStoredTable's inverse): the plain `<table>`, or\n * the `<figure data-rt=\"table\">` around one with its note. The V2 reader (parseTableElement) is not used here: it reads\n * a one-column row as a row-group heading and a caption-less grid by guesses that a stored table never meant.\n */\nexport function parseStoredTable(src: Element): TableModel {\n const fig = src.tagName === \"FIGURE\" ? src : null;\n const table = fig ? fig.querySelector(\":scope > table\")! : src;\n const t = emptyTable(0, 0);\n const trs = Array.from(table.querySelectorAll<HTMLTableRowElement>(\":scope > thead > tr, :scope > tbody > tr, :scope > tfoot > tr, :scope > tr\"));\n const groupRow = trs.find(isColumnGroupRow);\n const grid = trs.filter((tr) => tr !== groupRow && !isRowGroupRow(tr));\n const head = grid.filter((tr) => tr.parentElement?.tagName === \"THEAD\");\n const body = grid.filter((tr) => tr.parentElement?.tagName !== \"THEAD\");\n const width = Math.max(1, ...grid.map((tr) => tr.cells.length));\n const headCells = head.length ? Array.from(head[head.length - 1].cells) : [];\n t.headerRow = head.length > 0;\n t.headerColumn = body.length > 0 && body.every((tr) => tr.cells[0]?.tagName === \"TH\");\n t.caption = words(table.querySelector(\":scope > caption\"));\n t.columns = Array.from({ length: width }, (_, i) => ({ _key: tkey(\"c\"), label: words(headCells[i]), type: \"text\" as const }));\n const cellOf = (cell: HTMLTableCellElement | undefined): TableRow[\"cells\"][string] => {\n if (!cell) return \"\";\n const { rest: c, marks } = splitMarks(cell);\n const text = words(c);\n const a = c.children.length === 1 && c.firstElementChild?.tagName === \"A\" && c.firstElementChild.textContent?.trim() === text ? c.firstElementChild : null;\n const value = a ? { label: text, href: a.getAttribute(\"href\") ?? \"\" } : text;\n return marks ? { value, marks } : value;\n };\n // A group's key rides the markup (`th[data-group]`, `<tbody data-key>`), so a save keeps it; the same key met again\n // (a group split by a loose row or column) is the same group.\n const groupOf = (list: TableGroup[], own: string | null, prefix: string, label: string): TableGroup => {\n const k = (own ?? \"\").trim();\n const found = k ? list.find((g) => g._key === k) : undefined;\n if (found) return found;\n const g = { _key: k && k.length <= 64 && !list.some((x) => x._key === k) ? k : tkey(prefix), label };\n list.push(g);\n return g;\n };\n // column groups: the columns each `th[scope=colgroup]` spans\n if (groupRow) {\n const groups: TableGroup[] = [];\n let at = 0;\n for (const c of Array.from(groupRow.cells)) {\n const span = Math.max(1, c.colSpan || 1);\n if (c.tagName === \"TH\") {\n const g = groupOf(groups, c.getAttribute(\"data-group\"), \"g\", words(c));\n for (let i = at; i < at + span && i < width; i++) t.columns[i].group = g._key;\n }\n at += span;\n }\n t.columnGroups = groups;\n }\n // row groups: a label row opens a group for the rows after it in its own <tbody>\n const rowGroups: TableGroup[] = [];\n let current: { key: string; body: Element | null } | undefined;\n t.rows = [];\n for (const tr of trs) {\n if (tr === groupRow || tr.parentElement?.tagName === \"THEAD\") continue;\n if (isRowGroupRow(tr)) {\n const g = groupOf(rowGroups, tr.parentElement?.getAttribute(\"data-key\") ?? null, \"rg\", words(tr.cells[0]));\n current = { key: g._key, body: tr.parentElement };\n continue;\n }\n if (current && current.body !== tr.parentElement) current = undefined;\n t.rows.push({ _key: tkey(\"r\"), cells: Object.fromEntries(t.columns.map((col, i) => [col._key, cellOf(tr.cells[i])])), ...(current ? { group: current.key } : {}) });\n }\n if (rowGroups.length) t.rowGroups = rowGroups;\n const note = fig?.querySelector(\":scope > [data-notes]\");\n // whitespace collapsed, as production's ingest reads it: the note renders as one paragraph\n const notes = words(note);\n if (notes) t.notes = notes;\n // the stored table's key rides the note's id (`<key>-notes`), so a save keeps it\n const own = (note?.getAttribute(\"id\") ?? table.getAttribute(\"aria-describedby\") ?? \"\").replace(/-notes$/, \"\");\n if (KEY.test(own)) t.id = own;\n // a link cell's column is a link column, so the editor draws (and the renderer writes) the link\n t.columns.forEach((col) => {\n const vals = t.rows.map((r) => r.cells[col._key]).filter((v) => v !== \"\");\n if (vals.length && vals.every((v) => isObjLike(v))) col.type = \"link\";\n });\n return t;\n}\n\n/**\n * The table as production's renderer writes a Portable Text table (@bettercms-ai/richtext html.ts tableHtml): a header\n * row in <thead>, header cells of the first column as <th>, every cell its text (a link cell its link). A caption, a\n * note or a group adds what that renderer writes for it, in the order the rows are held (an unedited stored table\n * comes back as it was; the editor's row list writes V2's order, loose rows first). An empty group has no row to label\n * and is not written, as production's renderer writes none.\n */\nexport function renderStoredTable(input: TableModel): string {\n const t = normalizeTable(input);\n const cols = t.columns;\n const cell = (row: TableRow, c: TableColumn) => {\n const raw = row.cells[c._key];\n const v = cellValue(raw);\n const text = esc(cellText(c, row, raw));\n const marks = isCellObject(raw) && typeof raw.marks === \"string\" ? raw.marks : \"\";\n return (isObjLike(v) && typeof (v as TableLink).href === \"string\" && (v as TableLink).href ? `<a href=\"${escAttr((v as TableLink).href)}\">${text}</a>` : text) + marks;\n };\n const rowHtml = (row: TableRow) => `<tr>${cols.map((c, i) => (i === 0 && t.headerColumn ? `<th>${cell(row, c)}</th>` : `<td>${cell(row, c)}</td>`)).join(\"\")}</tr>`;\n const span = (name: string, n: number) => (n > 1 ? ` ${name}=\"${n}\"` : \"\");\n const colLabels = new Map((t.columnGroups ?? []).map((g) => [g._key, String(g.label ?? \"\")]));\n const rowLabels = new Map((t.rowGroups ?? []).map((g) => [g._key, String(g.label ?? \"\")]));\n const runs = <T,>(items: T[], keyOf: (x: T) => string | undefined) => {\n const out: { key?: string; items: T[] }[] = [];\n for (const x of items) {\n const key = keyOf(x);\n const last = out[out.length - 1];\n if (last && last.key === key) last.items.push(x);\n else out.push({ key, items: [x] });\n }\n return out.some((r) => r.key !== undefined) ? out : [];\n };\n const colRuns = runs(cols, (c) => (c.group && colLabels.has(c.group) ? c.group : undefined));\n const rowRuns = runs(t.rows, (r) => (r.group && rowLabels.has(r.group) ? r.group : undefined));\n const caption = t.caption.trim();\n const notes = [(t.notes ?? \"\").trim(), ...(t.footnotes ?? []).map((f, i) => (f.text.trim() ? `[${i + 1}] ${f.text.trim()}` : \"\"))].filter(Boolean).join(\" \");\n if (!caption && !notes && !colRuns.length && !rowRuns.length) {\n const out: string[] = [\"<table>\"];\n if (t.headerRow) out.push(`<thead><tr>${cols.map((c) => `<th>${esc(c.label)}</th>`).join(\"\")}</tr></thead>`);\n out.push(`<tbody>${t.rows.map(rowHtml).join(\"\")}</tbody></table>`);\n return out.join(\"\");\n }\n const notesId = notes ? `${t.id}-notes` : \"\";\n const out: string[] = [`<table${notesId ? ` aria-describedby=\"${escAttr(notesId)}\"` : \"\"}>`];\n if (caption) out.push(`<caption>${esc(caption)}</caption>`);\n out.push(colRuns.map((r) => `<colgroup${span(\"span\", r.items.length)}></colgroup>`).join(\"\"));\n const groupRow = colRuns.length\n ? `<tr>${colRuns.map((r) => (r.key === undefined ? \"<td></td>\".repeat(r.items.length) : `<th scope=\"colgroup\"${span(\"colspan\", r.items.length)} data-group=\"${escAttr(r.key)}\">${esc(colLabels.get(r.key)!)}</th>`)).join(\"\")}</tr>`\n : \"\";\n if (groupRow || t.headerRow) out.push(`<thead>${groupRow}${t.headerRow ? `<tr>${cols.map((c) => `<th>${esc(c.label)}</th>`).join(\"\")}</tr>` : \"\"}</thead>`);\n if (rowRuns.length)\n for (const r of rowRuns)\n out.push(`<tbody${r.key === undefined ? \"\" : ` data-key=\"${escAttr(r.key)}\"`}>${r.key === undefined ? \"\" : `<tr><th scope=\"rowgroup\"${span(\"colspan\", cols.length)}>${esc(rowLabels.get(r.key)!)}</th></tr>`}${r.items.map(rowHtml).join(\"\")}</tbody>`);\n else if (t.rows.length) out.push(`<tbody>${t.rows.map(rowHtml).join(\"\")}</tbody>`);\n out.push(\"</table>\");\n const html = out.join(\"\");\n return notes ? `<figure data-rt=\"table\">${html}<p data-notes id=\"${escAttr(notesId)}\">${esc(notes)}</p></figure>` : html;\n}\n\n/* ── Detect + parse (static HTML → model) ──────────────────────────── */\n/** The footnote markers closing a cell (`<sup data-footnote>` holding only text), and the cell without them. */\nfunction splitMarks(c: Element): { rest: Element; marks: string } {\n const rest = c.cloneNode(true) as Element;\n const marks: string[] = [];\n for (let n = rest.lastChild; n; n = rest.lastChild) {\n if (n.nodeType === 3 && !(n.textContent ?? \"\").trim() && marks.length) n.remove();\n else if (n.nodeType === 1 && (n as Element).tagName === \"SUP\" && (n as Element).hasAttribute(\"data-footnote\") && !(n as Element).children.length) {\n marks.unshift((n as Element).outerHTML);\n n.remove();\n } else break;\n }\n return { rest, marks: marks.join(\"\") };\n}\n/** A cell the table value can hold: text, line breaks, or one link around its text, then any footnote markers. */\nconst plainCell = (cell: Element) => {\n const c = splitMarks(cell).rest;\n return (\n Array.from(c.childNodes).every((n) => n.nodeType === 3 || (n.nodeType === 1 && (n as Element).tagName === \"BR\")) ||\n (c.children.length === 1 && c.firstElementChild!.tagName === \"A\" && c.firstElementChild!.children.length === 0 && (c.textContent ?? \"\").trim() === (c.firstElementChild!.textContent ?? \"\").trim())\n );\n};\n\nexport function detectKind(el: Element): IslandKind | null {\n const rt = el.getAttribute(\"data-rt\");\n if (rt === \"table\") return el.tagName === \"TABLE\" && !Array.from(el.querySelectorAll(\"td,th\")).every(plainCell) ? null : \"table\";\n if (rt && (ISLAND_KINDS as string[]).includes(rt)) return rt as IslandKind;\n // a quote with an attribution is a pull quote (V2 detectArticle; legacy: <blockquote><p>…</p><cite>…</cite></blockquote>)\n if (el.tagName === \"BLOCKQUOTE\" && el.querySelector(\":scope > cite\")) return \"pullquote\";\n if (el.tagName === \"TABLE\") return Array.from(el.querySelectorAll(\"td,th\")).every(plainCell) ? \"table\" : null;\n if (el.tagName === \"FIGURE\" && el.querySelector(\":scope > table, :scope > .bt-scroll > table\")) return \"table\";\n // a figure that is only an image (optionally linked, optionally captioned)\n if (el.tagName === \"FIGURE\") {\n const kids = Array.from(el.children);\n const media = kids.filter((k) => k.tagName !== \"FIGCAPTION\");\n const m = media[0];\n if (media.length === 1 && kids.length - media.length <= 1 && (m.tagName === \"IMG\" || (m.tagName === \"A\" && m.children.length === 1 && m.firstElementChild!.tagName === \"IMG\"))) return \"image\";\n }\n return null;\n}\n\nconst attrOf = (el: Element, name: string) => (el.hasAttribute(name) ? el.getAttribute(name)! : undefined);\nconst oneOf = <T extends string>(list: readonly T[], v: string | undefined): T | undefined => (v !== undefined && (list as readonly string[]).includes(v) ? (v as T) : undefined);\n\nexport function parseIsland(kind: IslandKind, el: HTMLElement): IslandModels[IslandKind] {\n switch (kind) {\n case \"image\": {\n const img = el.querySelector(\"img\");\n const a = img?.parentElement?.tagName === \"A\" ? img.parentElement : null;\n const cap = el.querySelector(\":scope > figcaption\");\n const m: ImageModel = { src: img?.getAttribute(\"src\") ?? \"\" };\n if (img?.hasAttribute(\"alt\")) m.alt = img.getAttribute(\"alt\")!;\n if (cap) m.caption = (cap.textContent ?? \"\").replace(/\\u200b/g, \"\");\n const align = oneOf(IMAGE_ALIGNS, attrOf(el, \"data-align\"));\n const size = oneOf(IMAGE_SIZES, attrOf(el, \"data-size\"));\n if (align) m.align = align;\n if (size) m.size = size;\n if (a) m.href = a.getAttribute(\"href\") ?? \"\";\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n case \"table\":\n // production's own figure holds its <table> directly; V2's (pasted) wraps it in a scroll region\n if (el.matches(\"figure[data-rt=table]\")) return el.querySelector(\":scope > table\") ? parseStoredTable(el) : parseTableElement(el);\n return parseStoredTable(el.matches(\"table\") ? el : el.querySelector(\"table\")!);\n case \"pullquote\": {\n // V2 article.ts parseArticle(\"pullquote\"): a legacy pull quote IS the <blockquote> (no <figure> around it)\n const text = (n: Element | null) => (n?.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n const bq = el.matches(\"blockquote\") ? el : el.querySelector(\"blockquote\");\n const cap = el.querySelector(\"figcaption\");\n const nameEl = cap?.querySelector(\"[data-name]\") ?? el.querySelector(\"blockquote > cite, cite\");\n let role = text(cap?.querySelector(\"[data-role]\") ?? null);\n // legacy <cite>Name, role</cite>\n let name = text(nameEl);\n if (!cap && name.includes(\",\")) [name, role] = [name.slice(0, name.indexOf(\",\")).trim(), name.slice(name.indexOf(\",\") + 1).trim()];\n const quoteEl = bq?.cloneNode(true) as HTMLElement | undefined;\n quoteEl?.querySelectorAll(\"cite\").forEach((c) => c.remove());\n return { quote: text(quoteEl ?? null), name, role, link: bq?.getAttribute(\"cite\") ?? nameEl?.getAttribute(\"href\") ?? \"\" };\n }\n case \"takeaways\": {\n // V2 article.ts parseArticle(\"takeaways\"): an empty list still holds a line to type in\n const text = (n: Element | null) => (n?.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n const pts = Array.from(el.querySelectorAll(\"li\")).map((li) => text(li));\n return { title: text(el.querySelector(\"[data-title]\")), points: pts.length ? pts : [\"\"] };\n }\n case \"callout\": {\n const title = el.querySelector(\":scope > [data-title]\");\n const body = el.querySelector(\":scope > [data-body]\");\n const m: CalloutModel = {};\n const tone = attrOf(el, \"data-callout\");\n if (tone !== undefined) m.tone = tone;\n if (title) m.title = (title.textContent ?? \"\").replace(/\\u200b/g, \"\");\n if (body) m.body = parasToText(body);\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n case \"toggle\": {\n const title = el.querySelector(\":scope > summary\");\n const body = el.querySelector(\":scope > [data-body]\");\n const m: ToggleModel = {};\n if (title) m.title = (title.textContent ?? \"\").replace(/\\u200b/g, \"\");\n if (body) m.body = parasToText(body);\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n case \"video\": {\n const m: VideoModel = {};\n const url = attrOf(el, \"data-url\");\n const title = attrOf(el, \"data-title\");\n if (url !== undefined) m.url = url;\n if (title !== undefined) m.title = title;\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n case \"file\": {\n const m: FileModel = {};\n const url = attrOf(el, \"data-url\");\n const name = attrOf(el, \"data-name\");\n const size = attrOf(el, \"data-size\");\n if (url !== undefined) m.url = url;\n if (name !== undefined) m.name = name;\n if (size !== undefined && Number.isFinite(Number(size))) m.size = Number(size);\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n case \"component\": {\n // V2 markup: data-ref is the library component, data-id this instance; a legacy one names only data-block\n const m: ComponentModel = { id: attrOf(el, \"data-id\") || rid(\"ci\") };\n const ref = attrOf(el, \"data-ref\") ?? attrOf(el, \"data-block\");\n const name = attrOf(el, \"data-name\");\n const overrides = attrOf(el, \"data-overrides\");\n if (ref !== undefined) m.ref = ref;\n if (name !== undefined) m.name = name;\n if (overrides !== undefined) m.overrides = overrides;\n const variant = attrOf(el, \"data-variant\");\n if (variant !== undefined) m.variant = variant;\n if (el.getAttribute(\"data-detached\") === \"true\") {\n m.detached = true;\n const props = attrOf(el, \"data-props\");\n const blocks = attrOf(el, \"data-blocks\");\n const at = attrOf(el, \"data-source-published-at\");\n if (props !== undefined) m.props = props;\n if (blocks !== undefined) m.blocks = blocks;\n if (at !== undefined) m.sourcePublishedAt = at;\n }\n const extra = attrOf(el, \"data-extra\");\n if (extra) m.extra = extra;\n return m;\n }\n }\n}\n\nexport function createIsland<K extends IslandKind>(kind: K, model: IslandModels[K]): IslandEl {\n const el = document.createElement(\"div\") as IslandEl;\n el.setAttribute(\"data-rt-island\", kind);\n el.setAttribute(\"contenteditable\", \"false\");\n el.__rt = model;\n return el;\n}\n\n/** Static block HTML → islands (top level only). Keeps a writable line after a trailing island or rule. */\nexport function hydrate(root: HTMLElement) {\n for (const ch of Array.from(root.children)) {\n if (ch.hasAttribute(\"data-rt-island\")) continue;\n const k = detectKind(ch);\n if (!k) continue;\n ch.replaceWith(createIsland(k, parseIsland(k, ch as HTMLElement)));\n }\n // loose top-level inline content → a paragraph (a single-paragraph field stores its text inline, with no <p>)\n let run: Node[] = [];\n const flush = (before: Node | null) => {\n if (run.some((n) => (n.textContent ?? \"\").trim() || (n.nodeType === 1 && (n as Element).tagName !== \"BR\"))) {\n const p = document.createElement(\"p\");\n root.insertBefore(p, before);\n run.forEach((n) => p.append(n));\n } else run.forEach((n) => n.parentNode === root && n.nodeType === 3 && root.removeChild(n));\n run = [];\n };\n for (const n of Array.from(root.childNodes)) {\n const block = n.nodeType === 1 && (BLOCK_TAGS.has((n as Element).tagName) || (n as Element).hasAttribute(\"data-rt-island\"));\n if (block) flush(n);\n else if (n.nodeType === 1 || n.nodeType === 3) run.push(n);\n }\n flush(null);\n if (!root.firstElementChild) root.innerHTML = \"<p><br></p>\";\n const last = root.lastElementChild;\n if (last && (last.hasAttribute(\"data-rt-island\") || last.tagName === \"HR\")) {\n const p = document.createElement(\"p\");\n p.innerHTML = \"<br>\";\n root.append(p);\n }\n}\n\nconst BLOCK_TAGS = new Set([\"P\", \"H1\", \"H2\", \"H3\", \"H4\", \"H5\", \"H6\", \"BLOCKQUOTE\", \"PRE\", \"UL\", \"OL\", \"HR\", \"FIGURE\", \"TABLE\", \"DIV\", \"DETAILS\", \"SECTION\", \"ASIDE\", \"NAV\"]);\nconst isEmptyP = (el: Element) => el.tagName === \"P\" && (el.innerHTML === \"\" || el.innerHTML === \"<br>\");\n\n/** Live DOM → stored HTML. */\nexport function serialize(root: HTMLElement): string {\n const clone = root.cloneNode(true) as HTMLElement;\n const live = Array.from(root.children);\n Array.from(clone.children).forEach((c, i) => {\n if (!c.hasAttribute(\"data-rt-island\")) return;\n const l = live[i] as IslandEl;\n const kind = c.getAttribute(\"data-rt-island\") as IslandKind;\n const model = l.__rt;\n if (!model) return c.remove();\n const tpl = document.createElement(\"template\");\n tpl.innerHTML = renderStatic(kind, model);\n c.replaceWith(tpl.content);\n });\n clone.querySelectorAll(\"[data-hint]\").forEach((n) => n.removeAttribute(\"data-hint\"));\n while (clone.children.length > 1 && clone.lastElementChild && isEmptyP(clone.lastElementChild)) clone.lastElementChild.remove();\n const html = clone.innerHTML.replace(/​/g, \"\");\n return html === \"<p><br></p>\" || html === \"<p></p>\" ? \"\" : html;\n}\n\n/** The HTML exactly as the editor would store it after opening `html` (load → hydrate → serialize), with no edit. */\nexport function editorRoundTrip(html: string): string {\n const el = document.createElement(\"div\");\n el.innerHTML = sanitize(html || \"\") || \"<p><br></p>\";\n hydrate(el);\n return serialize(el);\n}\n\n/** Strip scripts, event handlers and script URLs from HTML we did not author (paste, Markdown, loaded values). */\nexport function sanitize(html: string): string {\n if (!/[<&]/.test(html)) return html;\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n doc.body.querySelectorAll(\"script,style,iframe,object,embed,link,meta,form,input,button,textarea,select,noscript\").forEach((n) => n.remove());\n doc.body.querySelectorAll(\"*\").forEach((el) => {\n for (const a of Array.from(el.attributes)) {\n const n = a.name.toLowerCase();\n if (n.startsWith(\"on\")) el.removeAttribute(a.name);\n else if ((n === \"href\" || n === \"src\" || n === \"xlink:href\") && /^\\s*(javascript|vbscript|data:text)/i.test(a.value)) el.removeAttribute(a.name);\n }\n });\n return doc.body.innerHTML;\n}\n\n/* ── Selection helpers ─────────────────────────────────────────────── */\nexport const TEXT_BLOCKS = new Set([\"P\", \"H1\", \"H2\", \"H3\", \"H4\", \"H5\", \"H6\", \"BLOCKQUOTE\", \"PRE\", \"LI\", \"DIV\"]);\n\nexport function topBlock(root: HTMLElement | null, node: Node | null): HTMLElement | null {\n if (!root) return null;\n let n: Node | null = node;\n while (n && n.parentNode !== root) n = n.parentNode;\n return n && n.nodeType === 1 ? (n as HTMLElement) : null;\n}\n\n/** Nearest text-ish block element around a node, inside root. */\nexport function closestBlock(root: HTMLElement, node: Node | null): HTMLElement | null {\n let n: Node | null = node;\n while (n && n !== root) {\n if (n.nodeType === 1 && TEXT_BLOCKS.has((n as HTMLElement).tagName) && (n as HTMLElement).closest(\"[data-rt-island]\") === null) return n as HTMLElement;\n n = n.parentNode;\n }\n return null;\n}\n\nexport function placeCaret(el: Node, atEnd = true) {\n const s = window.getSelection();\n if (!s) return;\n const r = document.createRange();\n r.selectNodeContents(el);\n r.collapse(!atEnd);\n s.removeAllRanges();\n s.addRange(r);\n}\n\nexport function textBeforeCaret(block: HTMLElement): string | null {\n const s = window.getSelection();\n if (!s || !s.rangeCount) return null;\n const r = s.getRangeAt(0);\n if (!block.contains(r.startContainer)) return null;\n const pre = document.createRange();\n pre.selectNodeContents(block);\n pre.setEnd(r.startContainer, r.startOffset);\n return pre.toString();\n}\n\nexport function editingHost(n: Node | null): HTMLElement | null {\n const el = n ? (n.nodeType === 1 ? (n as HTMLElement) : n.parentElement) : null;\n return el?.closest<HTMLElement>('[contenteditable=\"true\"],[contenteditable=\"plaintext-only\"]') ?? null;\n}\n\n/** A range's box. Browsers measure a collapsed caret as an empty rect, and some engines cannot measure ranges at all: then\n * the box of the element the range sits in. */\nexport function rangeRect(r: Range, fallback: Element | null): DOMRect {\n let rect: DOMRect | null = null;\n try {\n rect = r.getBoundingClientRect();\n } catch {\n rect = null;\n }\n if (rect && (rect.width || rect.height)) return rect;\n const host = r.startContainer.nodeType === 1 ? (r.startContainer as Element) : r.startContainer.parentElement;\n return (host ?? fallback ?? document.body).getBoundingClientRect();\n}\n\n/* ── Word count (V2 article.ts, CPO D55) ─────────────────────────────\n * Words = what the writer wrote once, in the flow a reader follows: text, headings, lists, quotes, callouts, toggles,\n * table cells and image captions. Not counted: components (counted apart), a pull quote (it repeats a line of the\n * story), key takeaways (they restate it), video and file links. */\nconst NOT_COUNTED = \"[data-rt=component],[data-rt=pullquote],[data-rt=takeaways],[data-rt=video],[data-rt=file]\";\nconst WORDS = (s: string) => s.replace(/\\u200b/g, \"\").trim().split(/\\s+/).filter(Boolean).length;\nexport function countWords(html: string): number {\n if (!html) return 0;\n if (!/data-rt=\"(?:component|pullquote|takeaways|video|file)\"/.test(html) || typeof DOMParser === \"undefined\")\n return WORDS(html.replace(/<\\/(p|li|h[1-6]|blockquote|pre|figcaption|td|th|summary)>/g, \" \").replace(/<[^>]+>/g, \" \").replace(/&nbsp;|&[a-z]+;/g, \" \"));\n const doc = new DOMParser().parseFromString(`<body>${html}</body>`, \"text/html\");\n doc.body.querySelectorAll(NOT_COUNTED).forEach((n) => n.remove());\n doc.body.querySelectorAll(\"p,li,h1,h2,h3,h4,h5,h6,td,th,figcaption,summary,pre,blockquote,div\").forEach((n) => n.append(\" \"));\n return WORDS(doc.body.textContent ?? \"\");\n}\n/** Linked component instances in the body. */\nexport const countComponents = (html: string) => (html.match(/data-rt=\"component\"/g) ?? []).length;\n/** \"1,840 words · 3 components\" */\nexport const bodyCountLabel = (html: string) => {\n const w = countWords(html);\n const c = countComponents(html);\n return `${w.toLocaleString(\"en-US\")} ${w === 1 ? \"word\" : \"words\"}${c ? ` · ${c} ${c === 1 ? \"component\" : \"components\"}` : \"\"}`;\n};\nexport const isEmptyHtml = (html: string) => !html.replace(/<(?!img|hr|figure|table|details|div data-rt)[^>]*>/g, \"\").replace(/&nbsp;/g, \"\").trim();\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"editor.js","names":[],"sources":["../../../src/kit/controls/rich-text/editor.tsx"],"sourcesContent":["/**\n * RICH TEXT — the boxed rich-text editor (V2 HEAD controls/rich-text-editor.tsx, Figma 60995-5431, CPO D49 / D54 / D55).\n *\n * contentEditable + execCommand keeps it dependency-free; the value is clean HTML, which the field's control turns into\n * the stored value through the host's codec (./codec.ts). Rich blocks (an image) are React \"islands\" rendered into\n * contenteditable=false nodes and written back as static HTML, so a re-mount restores them (./dom.ts).\n *\n * ./toolbar.tsx the field toolbar (no room at rest, folds into the chevron by width)\n * ./catalog.tsx Insert menu, slash menu and the shared block catalogue\n * ./blocks.tsx the rich blocks (an image)\n * ./markdown.ts HTML ⇄ Markdown for the Markdown toggle and pasting\n * ./ops.ts pure DOM block operations (insert, turn into, move, duplicate, live Markdown, field rules)\n * ./floating.tsx the selection bubble\n * ./dom.ts hydrate / serialize / sanitize and selection helpers\n *\n * Everything the editor offers is limited to what the field accepts (`features`): a toolbar button, a slash command, a\n * Markdown shortcut or pasted markup the field cannot hold is not offered, or is turned into what it can hold and said so.\n */\nimport * as React from \"react\";\nimport { createPortal, flushSync } from \"react-dom\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { IconArrowBarToDown, IconArrowBarToUp, IconCopy, IconGripVertical, IconPlus, IconTransform, IconTrash } from \"@tabler/icons-react\";\nimport { cn } from \"../../lib/cn\";\nimport { useKitEnv, useKitServices, type AiPreset } from \"../../context\";\nimport { Button } from \"../../ui/button\";\nimport { Textarea } from \"../../ui/input\";\nimport { ExpandedEditorModal } from \"../../ui/expanded-editor-modal\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from \"../../ui/overlay\";\nimport { shortcutHintsOn } from \"../../ui/shortcut-hint\";\nimport { ALL_FEATURES, type RichTextFeature } from \"./codec\";\nimport type { KitHistoryStep } from \"../component-services\";\nimport { Island, type IslandCtx } from \"./blocks\";\nimport { CatalogComponentsProvider, InsertMenuContent, SlashMenuPanel, blockAllowed, catalogKey, noteRecent, useCatalog, type CatalogComponents, type CatalogItem } from \"./catalog\";\nimport {\n bodyCountLabel, closestBlock, countComponents, countWords, createIsland, defaultModel, editingHost, esc, hydrate, isEmptyHtml, placeCaret, rangeRect, rid, sanitize,\n serialize, textBeforeCaret, topBlock, type IslandEl, type IslandModels, type IslandKind,\n} from \"./dom\";\nimport { htmlToMarkdown, looksLikeMarkdown, markdownToHtml } from \"./markdown\";\nimport * as ops from \"./ops\";\nimport { SelectionBubble } from \"./floating\";\nimport { LinkForm, type TextLink } from \"./link-form\";\nimport { EMPTY_FMT, FormatToolbar, MARK_FEATURE, stylesFor, type Fmt, type MarkCmd } from \"./toolbar\";\n\n/* ── Prose styles for the editable surface (kit tokens only) ── */\nexport const RT_PROSE =\n \"text-kit-base leading-[1.6] text-kit-fg [&>*+*]:mt-3 \" +\n \"[&_h1]:text-[28px] [&_h1]:font-semibold [&_h1]:leading-9 [&_h1]:tracking-[-0.01em] [&_h2]:text-[22px] [&_h2]:font-semibold [&_h2]:leading-8 [&_h2]:tracking-[-0.01em] \" +\n \"[&_h3]:text-kit-lg [&_h3]:font-semibold [&_h4]:text-kit-md [&_h4]:font-semibold [&_h5]:text-kit-base [&_h5]:font-semibold [&_h6]:text-kit-sm [&_h6]:font-semibold [&_h6]:uppercase [&_h6]:tracking-wide [&_h6]:text-kit-fg-2 [&>h1]:mt-6 [&>h2]:mt-6 [&>h3]:mt-5 [&>*:first-child]:mt-0 \" +\n // a block's own list (key takeaways, V2 data-rt-isolate) is app UI, not body prose: V2 rich-text-editor.tsx skips it\n \"[&_ul:not([data-rt-isolate]_*)]:list-disc [&_ul:not([data-rt-isolate]_*)]:pl-5 [&_ol:not([data-rt-isolate]_*)]:list-decimal [&_ol:not([data-rt-isolate]_*)]:pl-5 [&_li:not([data-rt-isolate]_*)]:pl-1 [&_li+li:not([data-rt-isolate]_*)]:mt-1 [&_li:not([data-rt-isolate]_*)]:marker:text-kit-fg-3 \" +\n \"[&_blockquote]:border-l-2 [&_blockquote]:border-kit-line-strong [&_blockquote]:pl-4 [&_blockquote]:text-kit-fg-2 [&_blockquote]:italic \" +\n \"[&_a]:text-kit-accent-fg [&_a]:underline [&_a]:decoration-kit-accent-line [&_a]:underline-offset-2 \" +\n // a glossary term (`<abbr data-term title>`) reads as a dotted underline; a footnote marker as a small superscript\n \"[&_abbr]:cursor-help [&_abbr]:underline [&_abbr]:decoration-dotted [&_abbr]:underline-offset-2 [&_sup]:text-[0.7em] [&_sup]:leading-none \" +\n \"[&_code]:rounded-kit-md [&_code]:bg-kit-muted [&_code]:px-1 [&_code]:py-px [&_code]:font-kit-mono [&_code]:text-[0.9em] \" +\n \"[&_pre]:overflow-x-auto [&_pre]:whitespace-pre-wrap [&_pre]:rounded-kit-lg [&_pre]:border [&_pre]:border-kit-line [&_pre]:bg-kit-code [&_pre]:p-3 [&_pre]:font-kit-mono [&_pre]:text-kit-sm \" +\n \"[&_pre_code]:rounded-none [&_pre_code]:bg-transparent [&_pre_code]:p-0 [&_pre_code]:text-[1em] \" +\n \"[&_hr]:my-6 [&_hr]:border-kit-line \" +\n \"[&_table]:w-full [&_table]:border-collapse [&_table]:text-kit-sm [&_td]:border [&_td]:border-kit-line [&_td]:px-2.5 [&_td]:py-1.5 [&_td]:align-top [&_th]:border [&_th]:border-kit-line [&_th]:bg-kit-subtle [&_th]:px-2.5 [&_th]:py-1.5 [&_th]:text-left [&_th]:align-top [&_th]:font-medium\";\n\n/** Panel density (≈340px inspector): 13px text, smaller headings. */\nconst RT_PANEL = \"text-kit-sm leading-[1.6] [&_h1]:text-kit-xl [&_h1]:leading-7 [&_h2]:text-kit-lg [&_h2]:leading-7 [&_h3]:text-kit-md [&_h4]:text-kit-base [&_h5]:text-kit-sm [&_h6]:text-kit-xs\";\n\n/** execCommand, where the engine has it (it returns false where it does not). */\nconst exec = (cmd: string, arg?: string): boolean => {\n try {\n return typeof document.execCommand === \"function\" && document.execCommand(cmd, false, arg);\n } catch {\n return false;\n }\n};\nconst queryState = (c: string) => {\n try {\n return typeof document.queryCommandState === \"function\" && document.queryCommandState(c);\n } catch {\n return false;\n }\n};\n/** Insert HTML at the caret: the browser's own insert (undoable), else by hand. */\nfunction insertHtmlAtCaret(html: string) {\n if (exec(\"insertHTML\", html)) return;\n const s = window.getSelection();\n if (!s || !s.rangeCount) return;\n const r = s.getRangeAt(0);\n r.deleteContents();\n const tpl = document.createElement(\"template\");\n tpl.innerHTML = sanitize(html);\n const last = tpl.content.lastChild;\n r.insertNode(tpl.content);\n if (last) {\n r.setStartAfter(last);\n r.collapse(true);\n s.removeAllRanges();\n s.addRange(r);\n }\n}\nfunction insertTextAtCaret(text: string) {\n if (exec(\"insertText\", text)) return;\n const s = window.getSelection();\n if (!s || !s.rangeCount) return;\n const r = s.getRangeAt(0);\n r.deleteContents();\n const t = document.createTextNode(text);\n r.insertNode(t);\n r.setStartAfter(t);\n r.collapse(true);\n s.removeAllRanges();\n s.addRange(r);\n}\n\n/** The slash menu at full height (header 32, list 300, footer 28, borders), the least it shrinks to, and the gap it keeps from the window's edge. */\nconst SLASH_MENU_H = 362;\nconst SLASH_MIN_H = 160;\nconst SLASH_EDGE = 8;\n\n/**\n * Where the slash menu goes, collision-aware: below the caret when the whole menu fits there, else on the side with\n * more room, and never taller than that room (its list scrolls), so the last row (More components) stays reachable in\n * a short window.\n */\nexport function slashPlacement(caret: { top: number; bottom: number }, viewportH: number): { flipUp: boolean; maxHeight: number } {\n const below = viewportH - caret.bottom - 6 - SLASH_EDGE;\n const above = caret.top - 6 - SLASH_EDGE;\n const flipUp = below < SLASH_MENU_H && above > below;\n return { flipUp, maxHeight: Math.max(SLASH_MIN_H, Math.min(SLASH_MENU_H, flipUp ? above : below)) };\n}\n\ntype IslandStep = { el: IslandEl; before: IslandModels[IslandKind]; label: string; at: number };\n/** A step the host's history holds (KitServices.historyStep); its undo and redo are the host's, while it is next. */\ntype HostStep = { label: string; step: KitHistoryStep };\ntype GutterState = { el: HTMLElement; top: number; height: number };\ntype SlashState = { rect: DOMRect; node: Text; offset: number; query: string; folder: boolean; active: number };\ntype LinkState = { rect: DOMRect; initial: TextLink; existing: HTMLAnchorElement | null };\ntype Notice = { message: string; description?: string; action?: { label: string; onClick: () => void } };\n\nexport interface RichTextEditorProps {\n value: string;\n onChange: (html: string) => void;\n readOnly?: boolean;\n placeholder?: string;\n docKey: string;\n /** what the field accepts; the editor offers nothing else (default: everything) */\n features?: readonly RichTextFeature[];\n /** a one-paragraph field: Enter starts no new block */\n single?: boolean;\n /** links may open in a new tab */\n allowNewTab?: boolean;\n /** the writing surface's id (the field label's `for`; its label is `${id}-label`) */\n id?: string;\n invalid?: boolean;\n /** panel = narrow (~340px) inspector, document = the full editor column. */\n variant?: \"panel\" | \"document\";\n /** CPO D49: the expanded editor's breadcrumb, root → this field (\"Alternating feature rows\", \"Thin walls\", \"Body\"). */\n expandCrumbs?: string[];\n /** Controlled expanded modal (a host's label-row action opens it too). */\n expandedOpen?: boolean;\n onExpandedOpenChange?: (open: boolean) => void;\n /** This editor IS the body of the expanded modal: toolbar always shown, tall writing surface. */\n inModal?: boolean;\n /** Already the full editor: no Expand button. */\n hideFullscreen?: boolean;\n /** Scroll the writing surface beyond this height (px). */\n maxHeight?: number;\n autoFocus?: boolean;\n /** Shows the toolbar Comment button. */\n onComment?: (quote: string) => void;\n /** the components this field may embed (the insert menus' More components); absent → none offered */\n components?: CatalogComponents;\n}\n\n/* ── Editor ────────────────────────────────────────────────────────── */\nexport function RichTextEditor({\n value,\n onChange,\n readOnly,\n placeholder,\n docKey,\n features = ALL_FEATURES,\n single,\n allowNewTab = true,\n id,\n invalid,\n variant = \"document\",\n expandCrumbs,\n expandedOpen,\n onExpandedOpenChange,\n inModal,\n hideFullscreen,\n maxHeight,\n autoFocus,\n onComment,\n components,\n}: RichTextEditorProps) {\n const hints = shortcutHintsOn();\n const ph = placeholder ?? (hints ? \"Type '/' for commands\" : \"Write something…\");\n const dense = variant === \"panel\";\n const ref = React.useRef<HTMLDivElement>(null);\n const wrap = React.useRef<HTMLDivElement>(null);\n const scroller = React.useRef<HTMLDivElement>(null);\n const saved = React.useRef<Range | null>(null);\n const known = React.useRef<string | null>(null);\n const pending = React.useRef<string | null>(null);\n /** a host undo just ran: its value is loaded even while the editor has focus (⌘Z here) */\n const forceLoad = React.useRef(false);\n const prevDoc = React.useRef<string | null>(null);\n const onChangeRef = React.useRef(onChange);\n onChangeRef.current = onChange;\n const valueRef = React.useRef(value);\n valueRef.current = value;\n const services = useKitServices();\n const env = useKitEnv();\n const featureKey = features.join(\",\");\n // eslint-disable-next-line react-hooks/exhaustive-deps\n const allows = React.useCallback((f: RichTextFeature) => features.includes(f), [featureKey]);\n\n const [empty, setEmpty] = React.useState(isEmptyHtml(value));\n const [words, setWords] = React.useState(() => countWords(value));\n const [comps, setComps] = React.useState(() => countComponents(value));\n const [fmt, setFmt] = React.useState<Fmt>(EMPTY_FMT);\n const [modalOwn, setModalOwn] = React.useState(false);\n const modalOpen = expandedOpen ?? modalOwn;\n const setModalOpen = (o: boolean) => (onExpandedOpenChange ? onExpandedOpenChange(o) : setModalOwn(o));\n const [md, setMd] = React.useState<{ text: string; original: string } | null>(null);\n const [mdConfirm, setMdConfirm] = React.useState(false);\n const [bubble, setBubble] = React.useState<DOMRect | null>(null);\n const [slash, setSlash] = React.useState<SlashState | null>(null);\n const [gutter, setGutter] = React.useState<GutterState | null>(null);\n const [blockMenu, setBlockMenu] = React.useState(false);\n const [gutterInsert, setGutterInsert] = React.useState(false);\n const gutterTarget = React.useRef<HTMLElement | null>(null);\n // D58: AI writing help follows ai.use and needs the host's AI service; without both no AI entry point is drawn.\n const canAI = env.can(\"ai.use\") && !!services.aiRewrite;\n const aiAttempt = React.useRef(0);\n const [link, setLink] = React.useState<LinkState | null>(null);\n const [drag, setDrag] = React.useState<{ from: HTMLElement; line: number | null; target: Element | null } | null>(null);\n const [focused, setFocused] = React.useState(false);\n const [menus, setMenus] = React.useState({ style: false, more: false });\n const [insertOpen, setInsertOpen] = React.useState(false);\n const inserted = React.useRef(false);\n const [islands, setIslands] = React.useState<{ id: string; el: IslandEl }[]>([]);\n const hist = React.useRef<{ past: IslandStep[]; future: IslandStep[]; textAt: number; hosts: HostStep[] }>({ past: [], future: [], textAt: 0, hosts: [] });\n const [width, setWidth] = React.useState(720);\n /* The block gutter (+ / grip) never reserves room inside the field: it floats in the space LEFT of the box when the\n host leaves ≥ 48px there (document columns), and sits in the box's padding otherwise. */\n const [gutterRoom, setGutterRoom] = React.useState(false);\n const blurTimer = React.useRef<number | undefined>(undefined);\n const [notice, setNotice] = React.useState<Notice | null>(null);\n\n const expanded = !!inModal;\n const toolbarOpen = !readOnly && (focused || menus.style || menus.more || insertOpen || expanded || !!md || !!link);\n const scrollable = !!maxHeight && !expanded;\n\n /** A refusal or a result the author must see: the host's toaster, else a line under the editor. Never silent. */\n const notify = React.useCallback(\n (message: string, opts: { description?: string; action?: Notice[\"action\"] } = {}) => {\n if (services.toast) services.toast(message, opts);\n else setNotice({ message, ...opts });\n },\n [services],\n );\n React.useEffect(() => {\n if (!notice) return;\n const t = window.setTimeout(() => setNotice(null), 8000);\n return () => window.clearTimeout(t);\n }, [notice]);\n\n /* ── islands ─────────────────────────────────────────────────────── */\n const syncIslands = React.useCallback(() => {\n const el = ref.current;\n if (!el) return setIslands((p) => (p.length ? [] : p));\n const list = Array.from(el.querySelectorAll<IslandEl>(\":scope > [data-rt-island]\"));\n const seen = new Set<string>();\n for (const x of list) {\n if (!x.__rt) {\n // a copy the browser made (drag/drop, native undo of a clone): start it fresh\n x.innerHTML = \"\";\n x.__rt = defaultModel(x.getAttribute(\"data-rt-island\") as IslandKind);\n delete x.dataset.rtId;\n }\n if (!x.dataset.rtId || seen.has(x.dataset.rtId)) x.dataset.rtId = rid(\"i\");\n seen.add(x.dataset.rtId);\n }\n setIslands((prev) => (prev.length === list.length && prev.every((p, i) => p.el === list[i]) ? prev : list.map((x) => ({ id: x.dataset.rtId!, el: x }))));\n }, []);\n\n /* ── value in / out ──────────────────────────────────────────────── */\n const load = React.useCallback(\n (html: string) => {\n const el = ref.current;\n if (!el) return;\n el.innerHTML = sanitize(html || \"\") || \"<p><br></p>\";\n hydrate(el);\n known.current = html;\n setEmpty(isEmptyHtml(html));\n setWords(countWords(html));\n setComps(countComponents(html));\n syncIslands();\n },\n [syncIslands],\n );\n\n const emit = React.useCallback(() => {\n const el = ref.current;\n if (!el) return;\n syncIslands();\n const html = serialize(el);\n setEmpty(isEmptyHtml(html) && !el.querySelector(\":scope > [data-rt-island], :scope > hr\"));\n setWords(countWords(html));\n setComps(countComponents(html));\n if (html === known.current) return;\n forceLoad.current = false;\n known.current = html;\n onChangeRef.current(html);\n }, [syncIslands]);\n\n React.useLayoutEffect(() => {\n const el = ref.current;\n if (!el) return;\n const docChanged = prevDoc.current !== null && prevDoc.current !== docKey;\n prevDoc.current = docKey;\n if (pending.current !== null) {\n const h = pending.current;\n pending.current = null;\n load(h);\n return;\n }\n if (forceLoad.current && value !== known.current) {\n forceLoad.current = false;\n load(value);\n return;\n }\n if (docChanged || !el.firstChild || (value !== known.current && !wrap.current?.contains(document.activeElement))) load(value);\n }, [value, docKey, md, load]);\n\n React.useEffect(() => {\n setMd(null);\n setMdConfirm(false);\n setSlash(null);\n setLink(null);\n setGutter(null);\n }, [docKey]);\n\n React.useEffect(() => {\n exec(\"defaultParagraphSeparator\", \"p\");\n if (autoFocus && ref.current && !readOnly) {\n ref.current.focus({ preventScroll: true });\n placeCaret(ref.current.lastElementChild ?? ref.current);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n React.useEffect(() => {\n const w = wrap.current;\n if (!w || typeof ResizeObserver === \"undefined\") return;\n const measureRoom = () => {\n let a = w.parentElement;\n while (a && a !== document.body) {\n const cs = getComputedStyle(a);\n if (cs.overflowX !== \"visible\" || cs.overflowY !== \"visible\") break;\n a = a.parentElement;\n }\n const left = w.getBoundingClientRect().left - (a ? a.getBoundingClientRect().left : 0);\n setGutterRoom(left >= 48);\n };\n const ro = new ResizeObserver(([e]) => {\n setWidth(Math.round(e.contentRect.width));\n measureRoom();\n });\n ro.observe(w);\n return () => ro.disconnect();\n }, []);\n\n /* the toolbar sticks below any sticky header (e.g. field tabs) in the same scroll area */\n const [stickyTop, setStickyTop] = React.useState(0);\n React.useEffect(() => {\n const w = wrap.current;\n if (!toolbarOpen || dense || !w) return;\n let sp = w.parentElement;\n while (sp && !/(auto|scroll)/.test(getComputedStyle(sp).overflowY)) sp = sp.parentElement;\n if (!sp) return setStickyTop(0);\n let top = 0;\n sp.querySelectorAll<HTMLElement>(\".sticky\").forEach((h) => {\n if (h.contains(w) || w.contains(h) || !(h.compareDocumentPosition(w) & Node.DOCUMENT_POSITION_FOLLOWING)) return;\n const cs = getComputedStyle(h);\n if (cs.position !== \"sticky\") return;\n top = Math.max(top, (parseFloat(cs.top) || 0) + h.offsetHeight);\n });\n setStickyTop(top);\n }, [toolbarOpen, dense]);\n\n // the slash menu follows the caret when anything scrolls; it closes only when the caret has left the \"/\" it was opened for\n const hasSlash = !!slash;\n React.useEffect(() => {\n if (!hasSlash) return;\n let raf = 0;\n const on = (e: Event) => {\n if (e.target instanceof Element && e.target.closest(\"[role=listbox]\")) return;\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() =>\n setSlash((sl) => {\n const s = window.getSelection();\n if (!sl || !s || !s.rangeCount || s.getRangeAt(0).startContainer !== sl.node) return null;\n const rect = rangeRect(s.getRangeAt(0), sl.node.parentElement ?? ref.current);\n return rect.top === sl.rect.top && rect.left === sl.rect.left ? sl : { ...sl, rect };\n }),\n );\n };\n window.addEventListener(\"scroll\", on, true);\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener(\"scroll\", on, true);\n };\n }, [hasSlash]);\n\n // keep the bubble on the selection while anything scrolls (incl. the toolbar sliding open)\n const hasBubble = !!bubble;\n React.useEffect(() => {\n if (!hasBubble) return;\n let raf = 0;\n const on = () => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(() => {\n const s = window.getSelection();\n const ok = s && s.rangeCount && !s.isCollapsed && ref.current?.contains(s.anchorNode);\n setBubble(ok ? rangeRect(s!.getRangeAt(0), ref.current) : null);\n });\n };\n window.addEventListener(\"scroll\", on, true);\n window.addEventListener(\"resize\", on);\n return () => {\n cancelAnimationFrame(raf);\n window.removeEventListener(\"scroll\", on, true);\n window.removeEventListener(\"resize\", on);\n };\n }, [hasBubble]);\n\n /* ── selection ───────────────────────────────────────────────────── */\n const saveSel = () => {\n const s = window.getSelection();\n if (s && s.rangeCount && ref.current?.contains(s.anchorNode)) saved.current = s.getRangeAt(0).cloneRange();\n };\n const restoreSel = () => {\n const el = ref.current;\n if (!el) return;\n const r = saved.current;\n const s = window.getSelection();\n if (r && el.contains(r.startContainer) && s) {\n (editingHost(r.startContainer) ?? el).focus({ preventScroll: true });\n s.removeAllRanges();\n s.addRange(r);\n } else {\n el.focus({ preventScroll: true });\n placeCaret(el.lastElementChild ?? el);\n }\n };\n\n const refresh = React.useCallback(() => {\n const el = ref.current;\n const s = window.getSelection();\n if (!el || !s || !s.rangeCount || !el.contains(s.anchorNode)) return;\n saved.current = s.getRangeAt(0).cloneRange();\n const anchorEl = s.anchorNode?.nodeType === 1 ? (s.anchorNode as HTMLElement) : s.anchorNode?.parentElement;\n const inIsland = !!anchorEl?.closest(\"[data-rt-island]\");\n const tb = topBlock(el, s.anchorNode);\n const r = s.getRangeAt(0);\n const hasSel = !s.isCollapsed && !!r.toString().trim();\n const next: Fmt = {\n bold: queryState(\"bold\") && !/^H[1-6]$/.test(tb?.tagName ?? \"\"),\n italic: queryState(\"italic\"),\n underline: queryState(\"underline\"),\n strike: queryState(\"strikeThrough\"),\n ul: !inIsland && tb?.tagName === \"UL\",\n ol: !inIsland && tb?.tagName === \"OL\",\n block: inIsland ? \"island\" : (tb?.tagName.toLowerCase() ?? \"p\"),\n hasSel,\n onLink: !!anchorEl?.closest(\"a\"),\n };\n setFmt((p) => (JSON.stringify(p) === JSON.stringify(next) ? p : next));\n setBubble(hasSel ? rangeRect(r, el) : null);\n el.querySelectorAll(\":scope > [data-hint]\").forEach((n) => (n !== tb || n.textContent) && n.removeAttribute(\"data-hint\"));\n if (tb && tb.tagName === \"P\" && s.isCollapsed && !tb.textContent && !tb.querySelector(\"img\") && document.activeElement === el && shortcutHintsOn()) tb.setAttribute(\"data-hint\", \"Type '/' for commands\");\n }, []);\n\n React.useEffect(() => {\n const on = () => refresh();\n document.addEventListener(\"selectionchange\", on);\n return () => document.removeEventListener(\"selectionchange\", on);\n }, [refresh]);\n\n const run = (fn: () => void) => {\n restoreSel();\n fn();\n emit();\n refresh();\n };\n\n /* ── gutter ──────────────────────────────────────────────────────── */\n const placeGutter = (b: HTMLElement | null) => {\n const sc = scroller.current;\n if (!b || !sc) return setGutter(null);\n const sr = sc.getBoundingClientRect();\n const br = b.getBoundingClientRect();\n setGutter((g) => {\n const top = br.top - sr.top + sc.scrollTop;\n return g && g.el === b && g.top === top ? g : { el: b, top, height: br.height };\n });\n };\n const currentBlock = (): HTMLElement | null => {\n const el = ref.current;\n if (!el) return null;\n const s = window.getSelection();\n return topBlock(el, s && s.rangeCount && el.contains(s.anchorNode) ? s.anchorNode : document.activeElement);\n };\n\n /* ── block operations (DOM work lives in ./ops) ─────────── */\n const deleteBlock = (b: HTMLElement) => {\n const el = ref.current;\n if (!el || !el.contains(b)) return;\n const next = b.nextSibling;\n b.remove();\n let filler: HTMLElement | null = null;\n if (!el.firstElementChild) {\n filler = document.createElement(\"p\");\n filler.innerHTML = \"<br>\";\n el.append(filler);\n }\n setGutter(null);\n setBlockMenu(false);\n emit();\n notify(\"Block deleted\", {\n action: {\n label: \"Undo\",\n onClick: () => {\n const root = ref.current;\n if (!root) return;\n if (filler?.isConnected && !filler.textContent) filler.remove();\n if (next && next.parentNode === root) root.insertBefore(b, next);\n else root.append(b);\n emit();\n },\n },\n });\n };\n\n const duplicateBlock = (b: HTMLElement) => {\n const c = ops.duplicateBlock(b);\n emit();\n if (gutter) placeGutter(c);\n };\n\n const moveBlock = (b: HTMLElement, dir: -1 | 1) => {\n if (!ops.moveBlock(b, dir)) return;\n emit();\n if (gutter) requestAnimationFrame(() => placeGutter(b));\n };\n\n const turnInto = (b: HTMLElement | null, tag: string) => {\n const el = ref.current;\n if (el && ops.turnInto(el, b, tag)) emit();\n };\n\n const exitIsland = (x: HTMLElement) => {\n const el = ref.current;\n if (!el || !el.contains(x)) return;\n const next = ops.ensureLineAfter(x);\n el.focus({ preventScroll: true });\n placeCaret(next, false);\n emit();\n };\n\n const insertBlock = (it: CatalogItem) => {\n const el = ref.current;\n if (!el || readOnly) return;\n if (it.kind === \"component\" && it.component) {\n // V2 insert: a fresh linked instance, ONE undo step\n const c = it.component;\n noteRecent(it);\n oneStep(`Insert ${c.name}`, () => {\n const isl = ops.insertIsland(el, \"component\", { ...defaultModel(\"component\"), ref: c.id, name: c.name });\n emit();\n return isl;\n });\n refresh();\n return;\n }\n if (!it.id || !blockAllowed(it.id, allows)) return;\n noteRecent(it);\n ops.insertBasic(el, it.id);\n emit();\n refresh();\n };\n\n /* ── slash menu ──────────────────────────────────────────────────── */\n const slashCat = useCatalog(slash?.query ?? \"\", allows, slash?.folder ?? false, components ?? null);\n const caretRect = () => {\n const s = window.getSelection();\n if (!s || !s.rangeCount) return null;\n return rangeRect(s.getRangeAt(0), topBlock(ref.current, s.anchorNode) ?? ref.current);\n };\n const pickSlash = (it: CatalogItem) => {\n if (it.kind === \"folder\") return setSlash((s) => s && { ...s, folder: true, active: 1 });\n if (it.kind === \"back\") return setSlash((s) => s && { ...s, folder: false, active: 0 });\n const sl = slash;\n setSlash(null);\n if (sl) {\n try {\n const r = document.createRange();\n r.setStart(sl.node, sl.offset);\n r.setEnd(sl.node, Math.min(sl.node.length, sl.offset + 1 + sl.query.length));\n r.deleteContents();\n const c = document.createRange();\n c.setStart(sl.node, Math.min(sl.offset, sl.node.length));\n c.collapse(true);\n const s = window.getSelection();\n s?.removeAllRanges();\n s?.addRange(c);\n } catch {\n /* the text moved */\n }\n // A component is ONE step of the host's history, recorded from the body as it stands when the step starts: the\n // typed \"/query\" goes first, flushed, so an undo of the insert never brings it back as a paragraph.\n if (it.kind === \"component\") flushSync(() => emit());\n }\n insertBlock(it);\n };\n\n const toggleInlineCode = () => {\n const el = ref.current;\n const s = window.getSelection();\n if (!el || !s || !s.rangeCount || !allows(\"code\")) return;\n const anchorEl = s.anchorNode?.nodeType === 1 ? (s.anchorNode as HTMLElement) : s.anchorNode?.parentElement;\n const code = anchorEl?.closest(\"code\");\n if (code && el.contains(code) && !code.closest(\"pre\")) {\n code.replaceWith(...Array.from(code.childNodes));\n emit();\n return;\n }\n const text = s.toString();\n if (!text) return void notify(\"Select some text first\", { description: \"Or wrap words in backticks to format them as code.\" });\n insertHtmlAtCaret(`<code>${esc(text)}</code>`);\n emit();\n };\n\n /* ── keyboard ────────────────────────────────────────────────────── */\n const onKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (slash) {\n if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n setSlash(slash.folder ? { ...slash, folder: false, active: 0 } : null);\n return;\n }\n if (catalogKey(e, slashCat.flat, slash.active, (a) => setSlash((s) => s && { ...s, active: a }), pickSlash, false)) {\n e.preventDefault();\n return;\n }\n }\n const mod = e.metaKey || e.ctrlKey;\n const k = e.key.toLowerCase();\n if (mod && !e.altKey && k === \"k\") {\n e.preventDefault();\n saveSel();\n openLink();\n return;\n }\n if (mod && !e.altKey && !e.shiftKey && k === \"e\") {\n e.preventDefault();\n toggleInlineCode();\n return;\n }\n // the browser's own mark shortcuts, only for the marks the field keeps\n if (mod && !e.altKey && !e.shiftKey && ((k === \"b\" && !allows(\"bold\")) || (k === \"i\" && !allows(\"italic\")) || (k === \"u\" && !allows(\"underline\")))) {\n e.preventDefault();\n return;\n }\n if (mod && e.altKey && /^Digit[0-6]$/.test(e.code)) {\n e.preventDefault();\n const n = Number(e.code.slice(5));\n const tag = n === 0 ? \"p\" : `h${n}`;\n if (tag === \"p\" || allows(tag as RichTextFeature)) turnInto(currentBlock(), tag);\n return;\n }\n if (e.key === \"Enter\" && !mod && !e.shiftKey) {\n // a one-paragraph field has no second block to start\n if (single) {\n e.preventDefault();\n return;\n }\n // Enter on an empty quote or heading line leaves it for a paragraph\n const cb = currentBlock();\n if (cb && /^(BLOCKQUOTE|H[1-6])$/.test(cb.tagName) && !cb.textContent?.replace(/​/g, \"\").trim()) {\n e.preventDefault();\n turnInto(cb, \"p\");\n return;\n }\n // Enter at the end of a quote starts a paragraph (not another quote)\n const sel = window.getSelection();\n if (cb?.tagName === \"BLOCKQUOTE\" && sel?.isCollapsed && sel.rangeCount && !cb.querySelector(\"p\")) {\n const rest = document.createRange();\n rest.selectNodeContents(cb);\n rest.setStart(sel.anchorNode!, sel.anchorOffset);\n if (!rest.toString().trim()) {\n e.preventDefault();\n const p = document.createElement(\"p\");\n p.innerHTML = \"<br>\";\n cb.after(p);\n placeCaret(p);\n emit();\n return;\n }\n }\n const s = window.getSelection();\n const pre = s?.anchorNode && (s.anchorNode.nodeType === 1 ? (s.anchorNode as HTMLElement) : s.anchorNode.parentElement)?.closest(\"pre\");\n if (pre && ref.current?.contains(pre)) {\n e.preventDefault();\n exec(\"insertLineBreak\");\n return;\n }\n }\n if (e.key === \"ArrowDown\" && !mod && !e.shiftKey && !single) {\n // leave a trailing heading / quote / code block / list\n const b = currentBlock();\n const s = window.getSelection();\n if (b && !b.nextElementSibling && b.tagName !== \"P\" && !b.hasAttribute(\"data-rt-island\") && s?.isCollapsed && s.rangeCount) {\n const rest = document.createRange();\n rest.selectNodeContents(b);\n rest.setStart(s.anchorNode!, s.anchorOffset);\n if (!rest.toString().trim()) {\n e.preventDefault();\n const p = ops.ensureLineAfter(b);\n placeCaret(p, false);\n emit();\n }\n }\n }\n };\n\n /** Block-level shortcuts; runs for the surface and for text inside rich blocks. */\n const onWrapKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (e.defaultPrevented) return;\n const mod = e.metaKey || e.ctrlKey;\n if (mod && e.key === \"Enter\" && !hideFullscreen) {\n e.preventDefault();\n setModalOpen(true);\n return;\n }\n if (md || readOnly) return;\n const t = e.target as HTMLElement;\n if (!ref.current?.contains(t) || t.tagName === \"INPUT\" || t.tagName === \"TEXTAREA\") return;\n if (undoKey(e)) return;\n if (single) return;\n if (mod && !e.shiftKey && !e.altKey && e.key.toLowerCase() === \"d\") {\n e.preventDefault();\n const b = currentBlock();\n if (b) duplicateBlock(b);\n return;\n }\n if (mod && e.shiftKey && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n e.preventDefault();\n const b = currentBlock();\n if (b) moveBlock(b, e.key === \"ArrowUp\" ? -1 : 1);\n }\n };\n\n const onInput = (e: React.FormEvent<HTMLDivElement>) => {\n if (e.target !== ref.current) return;\n const ne = e.nativeEvent as InputEvent;\n if (ne.inputType !== \"historyUndo\" && ne.inputType !== \"historyRedo\") {\n hist.current.textAt = Date.now();\n hist.current.future = [];\n }\n if (!single && ne.inputType === \"insertText\" && (ne.data === \" \" || ne.data === \"-\") && ops.liveMarkdown(ref.current!, ne.data, allows)) {\n setSlash(null);\n emit();\n return;\n }\n if (ne.inputType === \"insertText\" && ne.data === \"`\" && allows(\"code\")) ops.liveInlineCode();\n emit();\n const s = window.getSelection();\n if (!s || !s.rangeCount) return setSlash(null);\n const r = s.getRangeAt(0);\n if (!slash) {\n // \"/\" opens the menu only at the very start of a block, and only in a field that takes more than one block\n if (single || ne.inputType !== \"insertText\" || ne.data !== \"/\" || r.startContainer.nodeType !== 3) return;\n const blk = closestBlock(ref.current!, r.startContainer);\n if (!blk || textBeforeCaret(blk) !== \"/\") return;\n const rect = caretRect();\n if (rect) setSlash({ rect, node: r.startContainer as Text, offset: r.startOffset - 1, query: \"\", folder: false, active: 0 });\n return;\n }\n if (r.startContainer !== slash.node || r.startOffset <= slash.offset || slash.node.data[slash.offset] !== \"/\") return setSlash(null);\n const q = slash.node.data.slice(slash.offset + 1, r.startOffset);\n if (/\\s/.test(q) || q.length > 24) return setSlash(null);\n setSlash({ ...slash, query: q, active: slash.folder ? 1 : 0 });\n };\n\n /* ── links ───────────────────────────────────────────────────────── */\n const openLink = () => {\n if (!allows(\"link\")) return;\n restoreSel();\n const s = window.getSelection();\n const anchorEl = s?.anchorNode?.nodeType === 1 ? (s.anchorNode as HTMLElement) : s?.anchorNode?.parentElement;\n const anchor = (anchorEl?.closest(\"a\") as HTMLAnchorElement | null) ?? null;\n if (!anchor && (!s || s.isCollapsed || !s.toString().trim())) {\n notify(\"Select some text first\", { description: hints ? \"Then press ⌘K to link it.\" : \"Then link it.\" });\n return;\n }\n const rect = s && s.rangeCount ? rangeRect(s.getRangeAt(0), ref.current) : ref.current!.getBoundingClientRect();\n setBubble(null);\n setLink({ rect, existing: anchor, initial: anchor ? { href: anchor.getAttribute(\"href\") ?? \"\", newTab: anchor.getAttribute(\"target\") === \"_blank\" } : { href: \"\" } });\n };\n const saveLink = (v: TextLink) => {\n const l = link;\n setLink(null);\n if (!l) return;\n if (l.existing) {\n l.existing.setAttribute(\"href\", v.href);\n if (v.newTab) l.existing.setAttribute(\"target\", \"_blank\");\n else l.existing.removeAttribute(\"target\");\n emit();\n return;\n }\n run(() => {\n const text = window.getSelection()?.toString() || v.href;\n insertHtmlAtCaret(`<a href=\"${esc(v.href).replace(/\"/g, \"&quot;\")}\"${v.newTab ? ` target=\"_blank\"` : \"\"}>${esc(text)}</a>`);\n });\n };\n\n /* ── AI rewrite of the selection (the host's service) ────────────── */\n const aiRewrite = (preset: AiPreset) => {\n const rewrite = services.aiRewrite;\n restoreSel();\n const range = saved.current?.cloneRange();\n const text = range?.toString() ?? \"\";\n if (!rewrite || !range || !text.trim()) return;\n setBubble(null);\n Promise.resolve()\n .then(() => rewrite(text, preset, aiAttempt.current++))\n .then(\n (out) => {\n const el = ref.current;\n if (!el || !el.contains(range.startContainer) || range.toString() !== text) {\n notify(\"The text changed before the rewrite came back\", { description: \"Nothing was replaced. Select it again to retry.\" });\n return;\n }\n el.focus({ preventScroll: true });\n const s = window.getSelection();\n s?.removeAllRanges();\n s?.addRange(range);\n insertTextAtCaret(out);\n emit();\n notify(\"Rewritten with AI\", { description: hints ? \"Press ⌘Z to undo\" : undefined });\n },\n (err: unknown) => notify(\"Could not rewrite the selection\", { description: err instanceof Error ? err.message : String(err) }),\n );\n };\n\n /* ── drag to reorder via the grip ────────────────────────────────── */\n const onGripDown = (e: React.PointerEvent) => {\n if (!gutter) return;\n startDrag(gutter.el, e, () => setBlockMenu(true));\n };\n /** Drag a top-level block (the gutter grip) to a new position; a tap calls `onTap`. */\n const startDrag = (from: HTMLElement, e: React.PointerEvent, onTap?: () => void) => {\n if (readOnly || e.button !== 0) return;\n e.preventDefault();\n const start = e.clientY;\n let moved = false;\n const kids = () => Array.from(ref.current?.children ?? []);\n const move = (ev: PointerEvent) => {\n if (!moved && Math.abs(ev.clientY - start) < 4) return;\n moved = true;\n const sc = scroller.current!;\n const sr = sc.getBoundingClientRect();\n let target: Element | null = null;\n let line = 0;\n for (const k of kids()) {\n const r = k.getBoundingClientRect();\n if (ev.clientY < r.top + r.height / 2) {\n target = k;\n line = r.top - sr.top + sc.scrollTop - 4;\n break;\n }\n line = r.bottom - sr.top + sc.scrollTop + 4;\n }\n setDrag({ from, line, target });\n };\n const up = () => {\n window.removeEventListener(\"pointermove\", move);\n window.removeEventListener(\"pointerup\", up);\n if (!moved) {\n onTap?.();\n return;\n }\n setDrag((d) => {\n if (d && d.target !== d.from) {\n if (d.target) d.target.before(d.from);\n else ref.current?.append(d.from);\n setTimeout(emit, 0);\n }\n return null;\n });\n };\n window.addEventListener(\"pointermove\", move);\n window.addEventListener(\"pointerup\", up);\n };\n\n /* ── pasted and converted markup keeps to the field's rules ──────── */\n const conform = (html: string): string => {\n const r = ops.restrictHtml(html, allows);\n if (r.dropped.length) notify(`This field keeps no ${r.dropped.join(\" or \")}`, { description: \"They were left out; the text around them was kept.\" });\n return r.html;\n };\n\n /* ── Markdown mode ───────────────────────────────────────────────── */\n const toggleMarkdown = () => {\n if (!md) {\n const html = ref.current ? serialize(ref.current) : value;\n const text = htmlToMarkdown(html);\n setMd({ text, original: text });\n setSlash(null);\n setGutter(null);\n setBubble(null);\n setLink(null);\n return;\n }\n if (md.text === md.original) {\n setMd(null);\n setMdConfirm(false);\n return;\n }\n setMdConfirm(true);\n };\n const convertMarkdown = () => {\n if (!md) return;\n let html: string;\n try {\n html = conform(markdownToHtml(md.text));\n } catch (err) {\n notify(\"Could not convert this Markdown\", { description: `${err instanceof Error ? err.message : String(err)}. Your rich text is unchanged.` });\n return;\n }\n pending.current = html;\n known.current = html;\n onChangeRef.current(html);\n setMd(null);\n setMdConfirm(false);\n };\n\n /* ── One undo history (CPO D54): typing is the browser's own undo; an island write (an image's address or alt text)\n is a step on this stack. ⌘Z takes whichever happened last. ── */\n /** A host step's undo or redo; its value then loads even here, with the caret in the editor. */\n const runHost = (run: () => true | string): true | string => {\n forceLoad.current = true;\n const r = run();\n if (r !== true) forceLoad.current = false;\n return r;\n };\n /**\n * This body's host step that is the host's next undo (or redo) NOW. The host's toolbar moves these steps too: after\n * its Undo then Redo, the step is the latest change again, so ⌘Z here undoes it. Any later change in this body is a\n * host step of its own (the body's value is the host's), so a host step that is next is the latest change here.\n */\n const hostNext = (way: \"undo\" | \"redo\"): HostStep | null => {\n const hs = hist.current.hosts;\n for (let i = hs.length - 1; i >= 0; i--) if (hs[i].step.next() === way) return hs[i];\n return null;\n };\n const islandUndo = (): boolean => {\n const host = hostNext(\"undo\");\n if (host) {\n const r = runHost(host.step.undo);\n if (r !== true) notify(\"Nothing was undone\", { description: r });\n return true;\n }\n const h = hist.current;\n // a step whose island is gone has nothing to undo\n while (h.past.length && !h.past[h.past.length - 1].el.isConnected) h.past.pop();\n const step = h.past[h.past.length - 1];\n if (!step || step.at < h.textAt) return false;\n if (!step.el.__rtSet) return false;\n h.past.pop();\n h.future.push({ ...step, before: step.el.__rt!, at: Date.now() });\n step.el.__rtSet(step.before);\n return true;\n };\n const islandRedo = (): boolean => {\n const host = hostNext(\"redo\");\n if (host) {\n const r = runHost(host.step.redo);\n if (r !== true) notify(\"Nothing was redone\", { description: r });\n return true;\n }\n const h = hist.current;\n const step = h.future.pop();\n if (!step || !step.el.isConnected || !step.el.__rtSet) return false;\n h.past.push({ ...step, before: step.el.__rt!, at: Date.now() });\n step.el.__rtSet(step.before);\n return true;\n };\n /**\n * One action as ONE undo step (a separate copy, \"use shared version again\", a component inserted): in the host's\n * history when it keeps one (KitServices.historyStep: its toolbar Undo, an Undo toast and ⌘Z here are the same\n * undo), else in this editor's own (`before`: the model the island had; an insert has none, and stays as undoable\n * as any block inserted here). `write` makes the change and answers the island it changed. Answers its undo.\n */\n const oneStep = (label: string, write: () => IslandEl | null, before?: IslandModels[IslandKind]): (() => true | string) => {\n const h = hist.current;\n const made: { el: IslandEl | null } = { el: null };\n const historyStep = services.historyStep;\n const step = historyStep\n ? historyStep(() => {\n made.el = write();\n })\n : ((made.el = write()), null);\n const el = made.el;\n if (step) {\n h.hosts = [...h.hosts, { label, step }].slice(-100);\n return () => runHost(step.undo);\n }\n if (!el || !before) return () => \"This change has no undo step here.\";\n const s: IslandStep = { el, before, label, at: Date.now() };\n h.past = [...h.past, s].slice(-100);\n h.future = [];\n return () => {\n if (!h.past.includes(s)) return \"It was undone already.\";\n if (h.past[h.past.length - 1] !== s || s.at < h.textAt) return \"Changes made after it come first. Press ⌘Z to undo them.\";\n return islandUndo() ? true : \"The block was removed, so there is nothing to undo.\";\n };\n };\n const record = (el: IslandEl, before: IslandModels[IslandKind], label: string, coalesce?: boolean) => {\n const h = hist.current;\n const now = Date.now();\n const top = h.past[h.past.length - 1];\n // typing in one field coalesces (~500ms), unless the text was edited in between\n if (coalesce && top && top.el === el && top.label === label && now - top.at < 500 && top.at > h.textAt) top.at = now;\n else h.past = [...h.past, { el, before, label, at: now }].slice(-100);\n h.future = [];\n };\n const undoKey = (e: React.KeyboardEvent): boolean => {\n const mod = e.metaKey || e.ctrlKey;\n if (!mod || e.altKey || e.key.toLowerCase() !== \"z\") return false;\n if (e.shiftKey) {\n if (!islandRedo()) return false;\n e.preventDefault();\n return true;\n }\n if (islandUndo()) {\n e.preventDefault();\n return true;\n }\n if (!hist.current.past.length || !ref.current) return false;\n e.preventDefault();\n const before = ref.current.innerHTML;\n exec(\"undo\");\n if (ref.current.innerHTML === before) {\n hist.current.textAt = 0;\n islandUndo();\n }\n return true;\n };\n\n /* ── API for islands (stable) ────────────────────────────────────── */\n const api = React.useRef({ emit, deleteBlock, exitIsland, record, oneStep, notify, duplicateBlock, moveBlock, islandUndo, islandRedo });\n api.current = { emit, deleteBlock, exitIsland, record, oneStep, notify, duplicateBlock, moveBlock, islandUndo, islandRedo };\n const islandCtx = React.useMemo<IslandCtx>(\n () => ({\n readOnly,\n dense,\n emit: () => api.current.emit(),\n remove: (x) => api.current.deleteBlock(x),\n exit: (x) => api.current.exitIsland(x),\n record: (x, before, label, coalesce) => api.current.record(x, before, label, coalesce),\n step: (label, write, before) => api.current.oneStep(label, write, before),\n notify: (message, description) => api.current.notify(message, { description }),\n duplicate: (x) => api.current.duplicateBlock(x),\n move: (x, dir) => api.current.moveBlock(x, dir),\n undo: () => api.current.islandUndo(),\n redo: () => api.current.islandRedo(),\n }),\n [readOnly, dense],\n );\n\n const commentSel = onComment\n ? () => {\n restoreSel();\n const q = window.getSelection()?.toString().trim();\n if (q) onComment(q);\n }\n : undefined;\n const onMark = (cmd: MarkCmd) => allows(MARK_FEATURE[cmd]) && run(() => exec(cmd));\n const onStyle = (tag: string) => {\n restoreSel();\n turnInto(currentBlock(), tag);\n refresh();\n };\n\n /* ── render ──────────────────────────────────────────────────────── */\n const { flipUp, maxHeight: slashMaxH } = slash ? slashPlacement(slash.rect, window.innerHeight) : { flipUp: false, maxHeight: SLASH_MENU_H };\n const gBlock = gutter?.el;\n const gIsText = !!gBlock && !gBlock.hasAttribute(\"data-rt-island\") && gBlock.tagName !== \"HR\";\n const btn = dense ? \"size-5 [&_svg]:size-3.5\" : \"size-[22px] [&_svg]:size-3.5\";\n /* outside: + and grip float left of the box · inset: a slim grip sits in the 16px padding (insert via / or the\n toolbar) · none: compact inspector fields and one-paragraph fields */\n const gutterMode: \"outside\" | \"inset\" | \"none\" = readOnly || dense || single ? \"none\" : gutterRoom ? \"outside\" : \"inset\";\n const showGutter = gutterMode !== \"none\";\n const minH = expanded ? \"min-h-[60vh]\" : single ? \"min-h-9\" : dense ? \"min-h-[120px]\" : \"min-h-[190px]\";\n const turnStyles = stylesFor(allows).filter((s) => [\"p\", \"h1\", \"h2\", \"h3\", \"blockquote\"].includes(s.tag));\n\n return (\n <CatalogComponentsProvider value={components ?? null}>\n <div\n ref={wrap}\n data-rt-editor=\"\"\n className={cn(\n \"relative rounded-kit-lg border transition-colors duration-150 [--rt-toolbar-h:2rem] pointer-coarse:[--rt-toolbar-h:2.75rem]\",\n /* the expanded modal is raised: the editor sits level with it, never below (D56) */\n expanded ? \"bg-[var(--kit-surface-raised)]\" : \"bg-kit-surface\",\n invalid ? \"border-[var(--kit-field-invalid)]\" : toolbarOpen ? \"border-kit-line-strong\" : \"border-kit-line\",\n )}\n /* what the sticky toolbar covers at the top of the scroll area */\n style={{ \"--rt-sticky-top\": toolbarOpen && !dense ? `calc(${stickyTop}px + var(--rt-toolbar-h))` : \"var(--kit-sticky-top, 0px)\" } as React.CSSProperties}\n onMouseLeave={() => !blockMenu && !gutterInsert && !drag && setGutter(null)}\n onKeyDown={onWrapKeyDown}\n onFocus={() => {\n window.clearTimeout(blurTimer.current);\n setFocused(true);\n }}\n onBlur={() => {\n window.clearTimeout(blurTimer.current);\n blurTimer.current = window.setTimeout(() => {\n const a = document.activeElement;\n if (wrap.current?.contains(a) || a?.closest(\"[role=menu],[role=dialog],[role=listbox],[data-floating-layer]\")) return;\n setFocused(false);\n setBubble(null);\n ref.current?.querySelectorAll(\"[data-hint]\").forEach((n) => n.removeAttribute(\"data-hint\"));\n if (valueRef.current !== known.current && !md) load(valueRef.current);\n }, 400);\n }}\n >\n {readOnly ? null : (\n <FormatToolbar\n open={toolbarOpen}\n sticky={!dense}\n stickyTop={stickyTop}\n width={width}\n dense={dense}\n fmt={fmt}\n md={!!md}\n allows={allows}\n hideFullscreen={hideFullscreen}\n insertOpen={insertOpen}\n setInsertOpen={(o) => {\n if (o) inserted.current = false;\n setInsertOpen(o);\n }}\n onMenuOpen={(name, o) => setMenus((m) => ({ ...m, [name]: o }))}\n onStyle={onStyle}\n onMark={onMark}\n onList={(kind) =>\n allows(kind) &&\n run(() => {\n // Chrome nests the list inside a heading/quote (<h2><ul>…) — turn the line into a paragraph first.\n const b = currentBlock();\n if (b && /^(H[1-6]|BLOCKQUOTE)$/.test(b.tagName)) turnInto(b, \"p\");\n exec(kind === \"ul\" ? \"insertUnorderedList\" : \"insertOrderedList\");\n // …and it can still leave <p><ul>…</ul></p>; lift the list out of any text block.\n ref.current?.querySelectorAll(\":is(p,h1,h2,h3,h4,h5,h6,blockquote) > :is(ul,ol)\").forEach((list) => {\n const host = list.parentElement!;\n host.replaceWith(...Array.from(host.childNodes).filter((n) => n.nodeType === 1 || n.textContent?.trim()));\n });\n })\n }\n onLink={openLink}\n onClear={() =>\n run(() => {\n exec(\"removeFormat\");\n exec(\"unlink\");\n })\n }\n onComment={commentSel}\n onInlineCode={() => {\n restoreSel();\n toggleInlineCode();\n }}\n onCodeBlock={() => {\n restoreSel();\n if (allows(\"pre\")) turnInto(currentBlock(), \"pre\");\n }}\n onInsert={(it) => {\n inserted.current = true;\n restoreSel();\n insertBlock(it);\n setInsertOpen(false);\n }}\n keepFocusOnInsertClose={() => inserted.current}\n onFullscreen={() => setModalOpen(true)}\n onMarkdown={toggleMarkdown}\n saveSel={saveSel}\n />\n )}\n\n {md ? (\n <div className=\"px-3 pb-2.5 pt-2.5\">\n <Textarea\n aria-label=\"Field content as Markdown\"\n spellCheck={false}\n value={md.text}\n readOnly={readOnly}\n onChange={(e) => {\n setMd({ ...md, text: e.target.value });\n setMdConfirm(false);\n }}\n className={cn(\"font-kit-mono text-kit-xs leading-5\", expanded ? \"min-h-[60vh]\" : dense ? \"min-h-[120px]\" : \"min-h-[190px]\")}\n style={scrollable ? { maxHeight } : undefined}\n />\n <p className=\"mt-1.5 text-kit-2xs text-kit-fg-3\">Markdown. Switching back converts it to blocks.</p>\n <AnimatePresence initial={false}>\n {mdConfirm ? (\n <motion.div\n key=\"confirm\"\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 4 }}\n transition={{ duration: 0.15 }}\n role=\"alertdialog\"\n aria-label=\"Convert edited Markdown?\"\n className=\"mt-2 flex flex-wrap items-center gap-2 rounded-kit-lg border border-kit-line bg-kit-subtle px-3 py-2\"\n >\n <span className=\"flex-1 text-kit-sm font-medium text-kit-fg\">Convert edited Markdown?</span>\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setMdConfirm(false)}>\n Keep editing Markdown\n </Button>\n <Button size=\"xs\" variant=\"primary\" autoFocus onClick={convertMarkdown}>\n Convert to rich text\n </Button>\n </motion.div>\n ) : null}\n </AnimatePresence>\n </div>\n ) : (\n <div\n ref={scroller}\n className={cn(\"relative\", scrollable && \"overflow-y-auto\")}\n style={scrollable ? { maxHeight } : undefined}\n onMouseMove={(e) => {\n if (drag || blockMenu || gutterInsert || !showGutter) return;\n const t = e.target as HTMLElement;\n if (t.closest(\"[data-rt-gutter]\")) return;\n placeGutter(topBlock(ref.current, t));\n }}\n >\n <div\n ref={ref}\n id={inModal ? undefined : id}\n role=\"textbox\"\n aria-multiline={!single}\n aria-labelledby={!inModal && id ? `${id}-label` : undefined}\n aria-label={inModal || !id ? (expandCrumbs?.[expandCrumbs.length - 1] ?? \"Rich text\") : undefined}\n aria-placeholder={ph}\n aria-readonly={readOnly || undefined}\n aria-invalid={invalid || undefined}\n contentEditable={!readOnly}\n suppressContentEditableWarning\n spellCheck\n tabIndex={readOnly ? 0 : undefined}\n onInput={onInput}\n onKeyDown={onKeyDown}\n onKeyUp={refresh}\n onMouseUp={refresh}\n onPaste={(e) => {\n if (readOnly) return;\n const files = Array.from(e.clipboardData.files).filter((f) => f.type.startsWith(\"image/\"));\n if (files.length) {\n e.preventDefault();\n notify(allows(\"image\") ? \"Add images from the media library\" : \"This field keeps no images\", {\n description: allows(\"image\") ? \"A pasted file has no address the page can show it from. Use Insert › Image.\" : undefined,\n });\n return;\n }\n const text = e.clipboardData.getData(\"text/plain\");\n e.preventDefault();\n if (!text) return;\n if (single || (!/\\n/.test(text.trim()) && !looksLikeMarkdown(text))) {\n insertTextAtCaret(single ? text.replace(/\\s*\\n\\s*/g, \" \") : text);\n emit();\n return;\n }\n let html: string;\n try {\n html = markdownToHtml(text);\n } catch {\n html = text.split(/\\n{2,}/).map((p) => `<p>${esc(p.trim()).replace(/\\n/g, \"<br>\")}</p>`).join(\"\");\n }\n insertHtmlAtCaret(conform(html));\n if (ref.current) hydrate(ref.current);\n emit();\n }}\n onDragOver={(e) => {\n if (e.dataTransfer.types.includes(\"application/x-bcms-asset\") && allows(\"image\")) e.preventDefault();\n }}\n onDrop={(e) => {\n const asset = e.dataTransfer.getData(\"application/x-bcms-asset\");\n if (!asset || readOnly || !allows(\"image\")) return;\n e.preventDefault();\n try {\n const a = JSON.parse(asset) as { url: string; alt?: string; name: string };\n const b = topBlock(ref.current, e.target as Node);\n const isl = createIsland(\"image\", defaultModel(\"image\", { src: a.url, alt: a.alt ?? \"\" }));\n if (b) b.after(isl);\n else ref.current?.append(isl);\n ops.ensureLineAfter(isl);\n emit();\n } catch {\n notify(\"That drop is not an image from the media library\");\n }\n }}\n className={cn(\n RT_PROSE,\n dense && RT_PANEL,\n \"peer relative outline-none [&_*]:outline-none\",\n \"[&>p[data-hint]]:before:pointer-events-none [&>p[data-hint]]:before:float-left [&>p[data-hint]]:before:h-0 [&>p[data-hint]]:before:text-kit-fg-4 [&>p[data-hint]]:before:content-[attr(data-hint)]\",\n dense ? \"px-2.5 py-2\" : \"px-4 py-3.5\",\n minH,\n )}\n />\n {empty ? (\n <div aria-hidden className={cn(\"pointer-events-none absolute text-kit-fg-4 peer-focus:hidden\", dense ? \"left-2.5 top-2 text-kit-sm\" : \"left-4 top-3.5 text-kit-base\")}>\n {ph}\n </div>\n ) : null}\n\n {/* Block gutter (+ / grip) */}\n {gutter && showGutter ? (\n <div\n data-rt-gutter=\"\"\n /* z-3: under the sticky toolbar (z-4), so a tall block's grip never paints over it */\n className={cn(\"absolute z-[3] flex items-start\", gutterMode === \"outside\" ? \"-left-12 pr-1\" : \"left-0\")}\n style={{ top: gutter.top + Math.max(-2, Math.min(4, gutter.height / 2 - 12)) }}\n >\n {gutterMode === \"outside\" ? (\n <Popover\n open={gutterInsert}\n onOpenChange={(o) => {\n if (o) {\n gutterTarget.current = gutter.el;\n inserted.current = false;\n }\n setGutterInsert(o);\n }}\n >\n <Tooltip content=\"Add a block below\" disabled={gutterInsert}>\n <PopoverTrigger\n aria-label=\"Add a block below\"\n className={cn(\"flex items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover data-[popup-open]:text-kit-fg\", btn)}\n >\n <IconPlus stroke={1.5} aria-hidden />\n </PopoverTrigger>\n </Tooltip>\n {gutterInsert ? (\n <InsertMenuContent\n side=\"bottom\"\n align=\"start\"\n allows={allows}\n keepFocusOnClose={() => inserted.current}\n onInsert={(it) => {\n const b = gutterTarget.current;\n const el = ref.current;\n inserted.current = true;\n setGutterInsert(false);\n if (!b || !el || !el.contains(b)) return;\n const p = document.createElement(\"p\");\n p.innerHTML = \"<br>\";\n b.after(p);\n el.focus({ preventScroll: true });\n placeCaret(p);\n insertBlock(it);\n }}\n />\n ) : null}\n </Popover>\n ) : null}\n <Menu open={blockMenu} onOpenChange={setBlockMenu}>\n <Tooltip content=\"Drag to move, click for options\" disabled={blockMenu || !!drag}>\n <MenuTrigger\n aria-label=\"Block options\"\n onPointerDown={onGripDown}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n setBlockMenu(true);\n }\n }}\n className={cn(\n \"flex cursor-grab items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg active:cursor-grabbing\",\n gutterMode === \"inset\" ? \"h-[22px] w-4 rounded-kit-sm [&_svg]:size-3.5\" : btn,\n (blockMenu || drag) && \"bg-kit-hover text-kit-fg\",\n )}\n >\n <IconGripVertical stroke={1.5} aria-hidden />\n </MenuTrigger>\n </Tooltip>\n <MenuContent className=\"w-56\" align=\"start\" finalFocus={false}>\n {turnStyles.length > 1 ? (\n <MenuSub>\n <MenuSubTrigger icon={<IconTransform stroke={1.5} />} disabled={!gIsText}>\n Turn into\n </MenuSubTrigger>\n <MenuSubContent className=\"w-48\">\n {turnStyles.map((t) => (\n <MenuItem key={t.tag} icon={t.icon} onClick={() => turnInto(gBlock ?? null, t.tag)}>\n {t.label}\n </MenuItem>\n ))}\n </MenuSubContent>\n </MenuSub>\n ) : null}\n <MenuItem icon={<IconCopy stroke={1.5} />} shortcut=\"⌘D\" onClick={() => gBlock && duplicateBlock(gBlock)}>\n Duplicate\n </MenuItem>\n <MenuItem icon={<IconArrowBarToUp stroke={1.5} />} shortcut=\"⌘⇧↑\" disabled={!gBlock?.previousElementSibling} onClick={() => gBlock && moveBlock(gBlock, -1)}>\n Move up\n </MenuItem>\n <MenuItem icon={<IconArrowBarToDown stroke={1.5} />} shortcut=\"⌘⇧↓\" disabled={!gBlock?.nextElementSibling} onClick={() => gBlock && moveBlock(gBlock, 1)}>\n Move down\n </MenuItem>\n <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => gBlock && deleteBlock(gBlock)}>\n Delete\n </MenuItem>\n </MenuContent>\n </Menu>\n </div>\n ) : null}\n {drag?.line != null ? <div className=\"pointer-events-none absolute inset-x-3 z-[6] h-0.5 rounded-full bg-kit-info\" style={{ top: drag.line }} /> : null}\n\n {/* Rich blocks render into their contenteditable=false hosts */}\n {islands.map(({ id: key, el }) => createPortal(<Island el={el} ctx={islandCtx} />, el, key))}\n </div>\n )}\n\n {/* Footer meta, and any refusal said in place when the host has no toaster */}\n <div className=\"flex min-h-7 items-center justify-end gap-3 rounded-b-kit-lg border-t border-kit-line-subtle px-3 text-kit-2xs text-kit-fg-3\">\n {/* V2 says these in a toast; with no toaster the refusal is said here, and the region exists only while it has one */}\n {notice ? (\n <span role=\"status\" aria-live=\"polite\" className=\"mr-auto min-w-0 truncate text-kit-fg-2\">\n {notice.message}\n {notice.description ? ` ${notice.description}` : \"\"}\n {notice.action ? (\n <button\n type=\"button\"\n className=\"ml-1.5 font-medium text-kit-fg underline underline-offset-2\"\n onClick={() => {\n notice.action!.onClick();\n setNotice(null);\n }}\n >\n {notice.action.label}\n </button>\n ) : null}\n </span>\n ) : null}\n <span className=\"shrink-0 tabular-nums\">\n {words.toLocaleString(\"en-US\")} {words === 1 ? \"word\" : \"words\"}\n {comps ? ` · ${comps} ${comps === 1 ? \"component\" : \"components\"}` : \"\"} · {Math.max(1, Math.round(words / 220))} min read\n </span>\n </div>\n\n {/* Bubble toolbar on selection: a toolbar menu owns the moment, so the bubble steps aside while one is open */}\n {bubble && !readOnly && !slash && !link && !md && !menus.style && !menus.more && !insertOpen ? (\n <SelectionBubble\n rect={bubble}\n avoid={toolbarOpen ? wrap.current?.querySelector<HTMLElement>('[role=\"toolbar\"][aria-label=\"Text formatting\"]')?.getBoundingClientRect() : null}\n fmt={fmt}\n allows={allows}\n saveSel={saveSel}\n onAi={canAI ? aiRewrite : undefined}\n onStyle={onStyle}\n onMark={onMark}\n onInlineCode={() => {\n restoreSel();\n toggleInlineCode();\n }}\n onLink={openLink}\n onComment={commentSel}\n />\n ) : null}\n\n {/* Slash menu (opens only at the start of a block; never takes focus) */}\n {slash && !md\n ? createPortal(\n <>\n <div data-floating-layer=\"\" className=\"pointer-events-auto fixed inset-0 z-[84]\" onMouseDown={() => setSlash(null)} />\n <motion.div\n initial={{ opacity: 0, y: flipUp ? -4 : 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.14 }}\n style={{\n left: Math.min(window.innerWidth - 330, Math.max(8, slash.rect.left)),\n ...(flipUp ? { bottom: window.innerHeight - slash.rect.top + 6 } : { top: slash.rect.bottom + 6 }),\n }}\n data-floating-layer=\"\"\n className=\"pointer-events-auto fixed z-[85]\"\n >\n <SlashMenuPanel query={slash.query} folder={slash.folder} active={slash.active} allows={allows} setActive={(a) => setSlash((s) => s && { ...s, active: a })} onPick={pickSlash} maxHeight={slashMaxH} />\n </motion.div>\n </>,\n document.body,\n )\n : null}\n\n {/* Link popover anchored to the selection */}\n <Popover open={!!link} onOpenChange={(o) => !o && setLink(null)}>\n <PopoverAnchor\n render={<span className=\"pointer-events-none fixed\" style={link ? { top: link.rect.bottom, left: link.rect.left, width: Math.max(1, link.rect.width), height: 1 } : { top: 0, left: 0 }} />}\n />\n <PopoverContent className=\"w-[340px] rounded-kit-lg p-3\" finalFocus={false}>\n {link ? (\n <LinkForm\n initial={link.initial}\n allowNewTab={allowNewTab}\n onSave={saveLink}\n onCancel={() => setLink(null)}\n onDetach={\n link.existing\n ? () => {\n const a = link.existing!;\n a.replaceWith(...Array.from(a.childNodes));\n setLink(null);\n emit();\n }\n : undefined\n }\n />\n ) : null}\n </PopoverContent>\n </Popover>\n {!hideFullscreen ? (\n <ExpandedEditorModal open={modalOpen} onOpenChange={setModalOpen} crumbs={expandCrumbs?.length ? expandCrumbs : [\"Text\"]} returnFocus={() => ref.current} meta={bodyCountLabel(value)}>\n {modalOpen ? (\n <RichTextEditor\n value={value}\n onChange={onChange}\n readOnly={readOnly}\n placeholder={placeholder}\n docKey={`${docKey}:expanded`}\n features={features}\n single={single}\n allowNewTab={allowNewTab}\n expandCrumbs={expandCrumbs}\n variant=\"document\"\n hideFullscreen\n inModal\n autoFocus\n onComment={onComment}\n components={components}\n />\n ) : null}\n </ExpandedEditorModal>\n ) : null}\n </div>\n </CatalogComponentsProvider>\n );\n}\n\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"floating.js","names":[],"sources":["../../../src/kit/controls/rich-text/floating.tsx"],"sourcesContent":["/**\n * RICH TEXT · the selection bubble: AI rewrite, style, marks, link (V2 HEAD controls/rich-text/floating.tsx).\n * V2's inline \"Ask AI\" prompt took free text; the host's AI service rewrites by preset only, so it is not drawn.\n */\nimport { createPortal } from \"react-dom\";\nimport { motion } from \"framer-motion\";\nimport { IconBold, IconCode, IconItalic, IconLink, IconMessage, IconStrikethrough, IconUnderline } from \"@tabler/icons-react\";\nimport { Sparkle } from \"../../ui/button\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger } from \"../../ui/overlay\";\nimport type { AiPreset } from \"../../context\";\nimport type { RichTextFeature } from \"./codec\";\nimport { StyleMenu, ToolButton, stylesFor, type Fmt, type MarkCmd } from \"./toolbar\";\n\n/** The bubble's rewrite directions (V2: improve, shorter, punchier, grammar), as the host service's presets. */\nexport const BUBBLE_AI: { id: AiPreset; label: string }[] = [\n { id: \"improve\", label: \"Improve writing\" },\n { id: \"shorter\", label: \"Make shorter\" },\n { id: \"simplify\", label: \"Simplify\" },\n { id: \"grammar\", label: \"Fix spelling and grammar\" },\n];\n\nexport function SelectionBubble({\n rect,\n fmt,\n allows,\n saveSel,\n onAi,\n onStyle,\n onMark,\n onInlineCode,\n onLink,\n onComment,\n avoid,\n}: {\n rect: DOMRect;\n /** The editor's own toolbar row (when it is open): the bubble never sits on top of it. */\n avoid?: DOMRect | null;\n fmt: Fmt;\n allows: (f: RichTextFeature) => boolean;\n saveSel: () => void;\n /** Absent when the person has no AI (D58: ai.use) or the host has no AI service: the AI menu and its divider are not drawn. */\n onAi?: (preset: AiPreset) => void;\n onStyle: (tag: string) => void;\n onMark: (cmd: MarkCmd) => void;\n onInlineCode: () => void;\n onLink: () => void;\n onComment?: () => void;\n}) {\n // Above the selection by default; flips below it when above would cover the editor's toolbar or leave the viewport.\n const above = rect.top - 44;\n const blocked = above < 8 || (!!avoid && above < avoid.bottom + 4 && above + 36 > avoid.top);\n const top = blocked ? rect.bottom + 8 : above;\n const styles = stylesFor(allows);\n return createPortal(\n <motion.div\n initial={{ opacity: 0, y: 4 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.14 }}\n onMouseDown={(e) => {\n if (!(e.target as HTMLElement).closest(\"button\")) e.preventDefault();\n }}\n style={{ top, left: Math.min(window.innerWidth - 400, Math.max(8, rect.left + rect.width / 2 - 190)) }}\n data-floating-layer=\"\"\n data-kit-scope=\"\"\n className=\"pointer-events-auto fixed z-[85] flex h-9 items-center gap-0.5 rounded-kit-lg border border-kit-line bg-kit-surface px-1 text-kit-fg shadow-kit-sm [.dark_&]:border-kit-line-strong [.dark_&]:bg-[#252528]\"\n role=\"toolbar\"\n aria-label=\"Selection formatting\"\n >\n {onAi ? (\n <>\n <Menu>\n <MenuTrigger\n onMouseDown={(e) => {\n e.preventDefault();\n saveSel();\n }}\n className=\"flex h-7 items-center gap-1.5 rounded-kit-md px-2 text-kit-sm text-kit-fg hover:bg-kit-hover data-[popup-open]:bg-kit-hover\"\n >\n <Sparkle size={14} /> Improve writing\n </MenuTrigger>\n <MenuContent className=\"w-52\" finalFocus={false}>\n {BUBBLE_AI.map((p) => (\n <MenuItem key={p.id} icon={<Sparkle size={16} />} onClick={() => onAi(p.id)}>\n {p.label}\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n <span aria-hidden className=\"mx-0.5 h-4 w-px bg-kit-line\" />\n </>\n ) : null}\n {fmt.block !== \"island\" && styles.length > 1 ? (\n <>\n <StyleMenu block={fmt.block} styles={styles} onPick={onStyle} />\n <span aria-hidden className=\"mx-0.5 h-4 w-px bg-kit-line\" />\n </>\n ) : null}\n {allows(\"bold\") ? <ToolButton label=\"Bold\" icon={<IconBold stroke={1.5} />} shortcut=\"⌘B\" active={fmt.bold} onClick={() => onMark(\"bold\")} /> : null}\n {allows(\"italic\") ? <ToolButton label=\"Italic\" icon={<IconItalic stroke={1.5} />} shortcut=\"⌘I\" active={fmt.italic} onClick={() => onMark(\"italic\")} /> : null}\n {allows(\"underline\") ? <ToolButton label=\"Underline\" icon={<IconUnderline stroke={1.5} />} shortcut=\"⌘U\" active={fmt.underline} onClick={() => onMark(\"underline\")} /> : null}\n {allows(\"strike\") ? <ToolButton label=\"Strikethrough\" icon={<IconStrikethrough stroke={1.5} />} active={fmt.strike} onClick={() => onMark(\"strikeThrough\")} /> : null}\n {allows(\"code\") ? <ToolButton label=\"Inline code\" icon={<IconCode stroke={1.5} />} shortcut=\"⌘E\" onClick={onInlineCode} /> : null}\n {allows(\"link\") ? <ToolButton label=\"Link\" icon={<IconLink stroke={1.5} />} shortcut=\"⌘K\" active={fmt.onLink} onClick={onLink} /> : null}\n {onComment ? <ToolButton label=\"Comment\" icon={<IconMessage stroke={1.5} />} onClick={onComment} /> : null}\n </motion.div>,\n document.body,\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/kit/controls/rich-text/index.ts"],"sourcesContent":["/**\n * Rich text: registers the control and its label-row action (one line each, so lanes merge cleanly).\n * Imported for its side effect by whatever loads the kit's controls; import the parts themselves by path.\n */\nimport { ACTIONS, CONTROLS } from \"../../engine/kit-field\";\nimport { RichTextControl, RichTextExpandAction } from \"./control\";\n\nCONTROLS.richtext = RichTextControl;\nACTIONS.richtext = RichTextExpandAction;\n"],"mappings":";;;;;;;AAOA,SAAS,WAAW;AACpB,QAAQ,WAAW"}
@@ -1,111 +0,0 @@
1
- import { Button } from "../../ui/button.js";
2
- import { Switch } from "../../ui/controls.js";
3
- import { Input } from "../../ui/input.js";
4
- import * as React from "react";
5
- import { IconLink, IconUnlink } from "@tabler/icons-react";
6
- import { jsx, jsxs } from "react/jsx-runtime";
7
- //#region src/kit/controls/rich-text/link-form.tsx
8
- /**
9
- * RICH TEXT · the link popover's body for a link inside the text: the address, and "Open in a new tab" when the field
10
- * allows it. A text link stores its address and target only (production's link mark), so V2's link type tabs and rel
11
- * choice, which belong to the link FIELD, are not offered here.
12
- */
13
- /** An address a link may carry: http(s), mailto, tel, a site path or an in-page anchor. */
14
- function linkProblem(href) {
15
- const h = href.trim();
16
- if (!h) return "Add an address first.";
17
- if (/^(https?:\/\/[^\s]+|mailto:[^\s]+|tel:[+\d][\d\s()-]*|\/(?!\/)[^\s]*|#[^\s]+)$/i.test(h)) return null;
18
- if (/^[a-z][a-z0-9+.-]*:/i.test(h)) return "Use an address that starts with https://, mailto: or tel:.";
19
- if (/^[^\s/]+\.[^\s]+$/.test(h)) return `Add https:// in front: https://${h}`;
20
- return "Use a full address (https://…), a page path (/about) or an anchor (#section).";
21
- }
22
- function LinkForm({ initial, allowNewTab, onSave, onCancel, onDetach }) {
23
- const [href, setHref] = React.useState(initial.href);
24
- const [newTab, setNewTab] = React.useState(!!initial.newTab);
25
- const [problem, setProblem] = React.useState(null);
26
- const urlId = React.useId();
27
- const tabId = React.useId();
28
- const errId = React.useId();
29
- return /* @__PURE__ */ jsxs("form", {
30
- className: "flex flex-col gap-2",
31
- onSubmit: (e) => {
32
- e.preventDefault();
33
- const p = linkProblem(href);
34
- setProblem(p);
35
- if (!p) onSave({
36
- href: href.trim(),
37
- newTab: allowNewTab && newTab
38
- });
39
- },
40
- children: [
41
- /* @__PURE__ */ jsx("label", {
42
- htmlFor: urlId,
43
- className: "text-kit-xs font-medium text-kit-fg-2",
44
- children: "Link to"
45
- }),
46
- /* @__PURE__ */ jsx(Input, {
47
- id: urlId,
48
- autoFocus: true,
49
- size: "sm",
50
- value: href,
51
- onChange: (e) => {
52
- setHref(e.target.value);
53
- if (problem) setProblem(null);
54
- },
55
- placeholder: "https://… or /page",
56
- leading: /* @__PURE__ */ jsx(IconLink, { stroke: 1.5 }),
57
- "aria-invalid": problem ? true : void 0,
58
- "aria-describedby": problem ? errId : void 0
59
- }),
60
- problem ? /* @__PURE__ */ jsx("p", {
61
- id: errId,
62
- role: "alert",
63
- className: "text-kit-xs text-kit-danger-fg",
64
- children: problem
65
- }) : null,
66
- allowNewTab ? /* @__PURE__ */ jsxs("div", {
67
- className: "flex items-center justify-between gap-2",
68
- children: [/* @__PURE__ */ jsx("label", {
69
- htmlFor: tabId,
70
- className: "text-kit-sm text-kit-fg",
71
- children: "Open in a new tab"
72
- }), /* @__PURE__ */ jsx(Switch, {
73
- id: tabId,
74
- size: "sm",
75
- checked: newTab,
76
- onCheckedChange: setNewTab,
77
- "aria-label": "Open in a new tab"
78
- })]
79
- }) : null,
80
- /* @__PURE__ */ jsxs("div", {
81
- className: "mt-1 flex items-center gap-2",
82
- children: [
83
- onDetach ? /* @__PURE__ */ jsx(Button, {
84
- size: "xs",
85
- variant: "ghost",
86
- leftIcon: /* @__PURE__ */ jsx(IconUnlink, { stroke: 1.5 }),
87
- onClick: onDetach,
88
- children: "Remove link"
89
- }) : null,
90
- /* @__PURE__ */ jsx("span", { className: "flex-1" }),
91
- /* @__PURE__ */ jsx(Button, {
92
- size: "xs",
93
- variant: "ghost",
94
- onClick: onCancel,
95
- children: "Cancel"
96
- }),
97
- /* @__PURE__ */ jsx(Button, {
98
- size: "xs",
99
- variant: "primary",
100
- type: "submit",
101
- children: "Save"
102
- })
103
- ]
104
- })
105
- ]
106
- });
107
- }
108
- //#endregion
109
- export { LinkForm };
110
-
111
- //# sourceMappingURL=link-form.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"link-form.js","names":[],"sources":["../../../src/kit/controls/rich-text/link-form.tsx"],"sourcesContent":["/**\n * RICH TEXT · the link popover's body for a link inside the text: the address, and \"Open in a new tab\" when the field\n * allows it. A text link stores its address and target only (production's link mark), so V2's link type tabs and rel\n * choice, which belong to the link FIELD, are not offered here.\n */\nimport * as React from \"react\";\nimport { IconLink, IconUnlink } from \"@tabler/icons-react\";\nimport { Button } from \"../../ui/button\";\nimport { Switch } from \"../../ui/controls\";\nimport { Input } from \"../../ui/input\";\n\nexport interface TextLink {\n href: string;\n newTab?: boolean;\n}\n\n/** An address a link may carry: http(s), mailto, tel, a site path or an in-page anchor. */\nexport function linkProblem(href: string): string | null {\n const h = href.trim();\n if (!h) return \"Add an address first.\";\n if (/^(https?:\\/\\/[^\\s]+|mailto:[^\\s]+|tel:[+\\d][\\d\\s()-]*|\\/(?!\\/)[^\\s]*|#[^\\s]+)$/i.test(h)) return null;\n if (/^[a-z][a-z0-9+.-]*:/i.test(h)) return \"Use an address that starts with https://, mailto: or tel:.\";\n if (/^[^\\s/]+\\.[^\\s]+$/.test(h)) return `Add https:// in front: https://${h}`;\n return \"Use a full address (https://…), a page path (/about) or an anchor (#section).\";\n}\n\nexport function LinkForm({\n initial,\n allowNewTab,\n onSave,\n onCancel,\n onDetach,\n}: {\n initial: TextLink;\n allowNewTab: boolean;\n onSave: (v: TextLink) => void;\n onCancel: () => void;\n onDetach?: () => void;\n}) {\n const [href, setHref] = React.useState(initial.href);\n const [newTab, setNewTab] = React.useState(!!initial.newTab);\n const [problem, setProblem] = React.useState<string | null>(null);\n const urlId = React.useId();\n const tabId = React.useId();\n const errId = React.useId();\n return (\n <form\n className=\"flex flex-col gap-2\"\n onSubmit={(e) => {\n e.preventDefault();\n const p = linkProblem(href);\n setProblem(p);\n if (!p) onSave({ href: href.trim(), newTab: allowNewTab && newTab });\n }}\n >\n <label htmlFor={urlId} className=\"text-kit-xs font-medium text-kit-fg-2\">\n Link to\n </label>\n <Input\n id={urlId}\n autoFocus\n size=\"sm\"\n value={href}\n onChange={(e) => {\n setHref(e.target.value);\n if (problem) setProblem(null);\n }}\n placeholder=\"https://… or /page\"\n leading={<IconLink stroke={1.5} />}\n aria-invalid={problem ? true : undefined}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n {allowNewTab ? (\n <div className=\"flex items-center justify-between gap-2\">\n <label htmlFor={tabId} className=\"text-kit-sm text-kit-fg\">\n Open in a new tab\n </label>\n <Switch id={tabId} size=\"sm\" checked={newTab} onCheckedChange={setNewTab} aria-label=\"Open in a new tab\" />\n </div>\n ) : null}\n <div className=\"mt-1 flex items-center gap-2\">\n {onDetach ? (\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconUnlink stroke={1.5} />} onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n <Button size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n <Button size=\"xs\" variant=\"primary\" type=\"submit\">\n Save\n </Button>\n </div>\n </form>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,YAAY,MAA6B;CACvD,MAAM,IAAI,KAAK,MAAM;AACrB,KAAI,CAAC,EAAG,QAAO;AACf,KAAI,kFAAkF,KAAK,EAAE,CAAE,QAAO;AACtG,KAAI,uBAAuB,KAAK,EAAE,CAAE,QAAO;AAC3C,KAAI,oBAAoB,KAAK,EAAE,CAAE,QAAO,kCAAkC;AAC1E,QAAO;;AAGT,SAAgB,SAAS,EACvB,SACA,aACA,QACA,UACA,YAOC;CACD,MAAM,CAAC,MAAM,WAAW,MAAM,SAAS,QAAQ,KAAK;CACpD,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,CAAC,CAAC,QAAQ,OAAO;CAC5D,MAAM,CAAC,SAAS,cAAc,MAAM,SAAwB,KAAK;CACjE,MAAM,QAAQ,MAAM,OAAO;CAC3B,MAAM,QAAQ,MAAM,OAAO;CAC3B,MAAM,QAAQ,MAAM,OAAO;AAC3B,QACE,qBAAC,QAAD;EACE,WAAU;EACV,WAAW,MAAM;AACf,KAAE,gBAAgB;GAClB,MAAM,IAAI,YAAY,KAAK;AAC3B,cAAW,EAAE;AACb,OAAI,CAAC,EAAG,QAAO;IAAE,MAAM,KAAK,MAAM;IAAE,QAAQ,eAAe;IAAQ,CAAC;;YANxE;GASE,oBAAC,SAAD;IAAO,SAAS;IAAO,WAAU;cAAwC;IAEjE,CAAA;GACR,oBAAC,OAAD;IACE,IAAI;IACJ,WAAA;IACA,MAAK;IACL,OAAO;IACP,WAAW,MAAM;AACf,aAAQ,EAAE,OAAO,MAAM;AACvB,SAAI,QAAS,YAAW,KAAK;;IAE/B,aAAY;IACZ,SAAS,oBAAC,UAAD,EAAU,QAAQ,KAAO,CAAA;IAClC,gBAAc,UAAU,OAAO,KAAA;IAC/B,oBAAkB,UAAU,QAAQ,KAAA;IACpC,CAAA;GACD,UACC,oBAAC,KAAD;IAAG,IAAI;IAAO,MAAK;IAAQ,WAAU;cAClC;IACC,CAAA,GACF;GACH,cACC,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,SAAD;KAAO,SAAS;KAAO,WAAU;eAA0B;KAEnD,CAAA,EACR,oBAAC,QAAD;KAAQ,IAAI;KAAO,MAAK;KAAK,SAAS;KAAQ,iBAAiB;KAAW,cAAW;KAAsB,CAAA,CACvG;QACJ;GACJ,qBAAC,OAAD;IAAK,WAAU;cAAf;KACG,WACC,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAQ,UAAU,oBAAC,YAAD,EAAY,QAAQ,KAAO,CAAA;MAAE,SAAS;gBAAU;MAEnF,CAAA,GACP;KACJ,oBAAC,QAAD,EAAM,WAAU,UAAW,CAAA;KAC3B,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAQ,SAAS;gBAAU;MAE5C,CAAA;KACT,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAU,MAAK;gBAAS;MAEzC,CAAA;KACL;;GACD"}