@threadlabs/looma 0.2.5 → 0.2.7

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 (427) hide show
  1. package/dist/chunk-3HMMDK27.js +2914 -0
  2. package/dist/chunk-3K45IWIJ.js +4733 -0
  3. package/dist/chunk-MLKGABMK.js +9 -0
  4. package/dist/declarative-generated.cjs +135 -0
  5. package/dist/declarative-generated.d.cts +10 -0
  6. package/dist/declarative-generated.d.ts +10 -0
  7. package/dist/declarative-generated.js +111 -0
  8. package/dist/declarative.cjs +2942 -0
  9. package/dist/declarative.d.cts +27 -0
  10. package/dist/declarative.d.ts +27 -0
  11. package/dist/declarative.js +13 -0
  12. package/dist/index.cjs +7478 -6457
  13. package/dist/index.d.cts +4 -58
  14. package/dist/index.d.ts +4 -58
  15. package/dist/index.js +15 -27
  16. package/dist/loader.cjs +7652 -0
  17. package/dist/loader.d.cts +4 -0
  18. package/dist/loader.d.ts +4 -0
  19. package/dist/loader.js +16 -0
  20. package/dist/valibot.cjs +31 -0
  21. package/dist/valibot.d.cts +10 -0
  22. package/dist/valibot.d.ts +1 -43
  23. package/dist/valibot.js +2 -0
  24. package/dist/{types/field/validation.d.ts → validation-bxcou-l-.d.cts} +13 -11
  25. package/dist/validation-bxcou-l-.d.ts +58 -0
  26. package/editor/{chunk-B5WVJOPV.js → chunk-BXICJBWS.js} +118 -8
  27. package/editor/{chunk-ZOUKEZ77.js → chunk-JK53ENSG.js} +8 -21
  28. package/editor/chunk-WI7ZA44X.js +2558 -0
  29. package/editor/extensions/index.d.ts +11 -2
  30. package/editor/extensions/index.js +9 -7
  31. package/editor/index.d.ts +1 -1
  32. package/editor/index.js +10 -8
  33. package/editor/ui.js +2 -2
  34. package/editor.css +32 -0
  35. package/layout/index.cjs +466 -400
  36. package/layout/index.d.cts +1 -2
  37. package/layout/index.d.ts +1 -2
  38. package/layout/index.js +471 -395
  39. package/package.json +14 -5
  40. package/vue/chunk-4DPYH3IT.js +3538 -0
  41. package/vue/editor/index.d.ts +17 -7
  42. package/vue/editor/index.js +53 -35
  43. package/vue/index.d.ts +48 -31
  44. package/vue/index.js +1 -1
  45. package/dist/chunk-24OTMNIU.js +0 -1617
  46. package/dist/chunk-D5WRORG6.js +0 -366
  47. package/dist/chunk-HNFCGIBP.js +0 -8
  48. package/dist/chunk-NB6DBRXQ.js +0 -323
  49. package/dist/chunk-OF57X5AR.js +0 -10
  50. package/dist/chunk-TL4FIE7X.js +0 -93
  51. package/dist/chunk-UL7UIUJZ.js +0 -20
  52. package/dist/cjs/app-globals-V2Kpy_OQ.js +0 -5
  53. package/dist/cjs/controlled-state-BFya8rAX.js +0 -9
  54. package/dist/cjs/events-TcQIzpNv.js +0 -19
  55. package/dist/cjs/icons-BAdjrnhS.js +0 -680
  56. package/dist/cjs/id-CYbKpaYr.js +0 -9
  57. package/dist/cjs/index-BHG9Rpil.js +0 -1602
  58. package/dist/cjs/index.cjs.js +0 -2
  59. package/dist/cjs/loader.cjs.js +0 -13
  60. package/dist/cjs/looma.cjs.js +0 -25
  61. package/dist/cjs/manager-Ce25WRtl.js +0 -95
  62. package/dist/cjs/positioning-CCR6ifPj.js +0 -426
  63. package/dist/cjs/ui-affordance-scope.cjs.entry.js +0 -43
  64. package/dist/cjs/ui-avatar-group.cjs.entry.js +0 -43
  65. package/dist/cjs/ui-avatar.cjs.entry.js +0 -50
  66. package/dist/cjs/ui-badge.cjs.entry.js +0 -19
  67. package/dist/cjs/ui-button.cjs.entry.js +0 -75
  68. package/dist/cjs/ui-callout.cjs.entry.js +0 -27
  69. package/dist/cjs/ui-checkbox.cjs.entry.js +0 -97
  70. package/dist/cjs/ui-chip_2.cjs.entry.js +0 -258
  71. package/dist/cjs/ui-combobox.cjs.entry.js +0 -708
  72. package/dist/cjs/ui-context-menu.cjs.entry.js +0 -239
  73. package/dist/cjs/ui-dialog.cjs.entry.js +0 -131
  74. package/dist/cjs/ui-disclosure.cjs.entry.js +0 -112
  75. package/dist/cjs/ui-editable.cjs.entry.js +0 -100
  76. package/dist/cjs/ui-floating-action-button.cjs.entry.js +0 -20
  77. package/dist/cjs/ui-form-field.cjs.entry.js +0 -114
  78. package/dist/cjs/ui-icon-button.cjs.entry.js +0 -23
  79. package/dist/cjs/ui-input.cjs.entry.js +0 -106
  80. package/dist/cjs/ui-menu-item.cjs.entry.js +0 -19
  81. package/dist/cjs/ui-menu.cjs.entry.js +0 -182
  82. package/dist/cjs/ui-popover.cjs.entry.js +0 -135
  83. package/dist/cjs/ui-radio-group.cjs.entry.js +0 -134
  84. package/dist/cjs/ui-radio.cjs.entry.js +0 -94
  85. package/dist/cjs/ui-search-result-row.cjs.entry.js +0 -47
  86. package/dist/cjs/ui-search-shell.cjs.entry.js +0 -39
  87. package/dist/cjs/ui-select.cjs.entry.js +0 -108
  88. package/dist/cjs/ui-switch.cjs.entry.js +0 -74
  89. package/dist/cjs/ui-tabs.cjs.entry.js +0 -118
  90. package/dist/cjs/ui-textarea.cjs.entry.js +0 -110
  91. package/dist/cjs/ui-toast-region.cjs.entry.js +0 -93
  92. package/dist/cjs/ui-top-bar.cjs.entry.js +0 -43
  93. package/dist/cjs/ui-tree-item.cjs.entry.js +0 -135
  94. package/dist/cjs/ui-tree.cjs.entry.js +0 -500
  95. package/dist/collection/collection-manifest.json +0 -45
  96. package/dist/collection/components/ui-affordance-scope/ui-affordance-scope.css +0 -8
  97. package/dist/collection/components/ui-affordance-scope/ui-affordance-scope.js +0 -70
  98. package/dist/collection/components/ui-avatar/ui-avatar.css +0 -35
  99. package/dist/collection/components/ui-avatar/ui-avatar.js +0 -130
  100. package/dist/collection/components/ui-avatar-group/ui-avatar-group.css +0 -32
  101. package/dist/collection/components/ui-avatar-group/ui-avatar-group.js +0 -95
  102. package/dist/collection/components/ui-badge/ui-badge.css +0 -90
  103. package/dist/collection/components/ui-badge/ui-badge.js +0 -62
  104. package/dist/collection/components/ui-button/ui-button.css +0 -121
  105. package/dist/collection/components/ui-button/ui-button.js +0 -141
  106. package/dist/collection/components/ui-callout/ui-callout.css +0 -74
  107. package/dist/collection/components/ui-callout/ui-callout.js +0 -59
  108. package/dist/collection/components/ui-checkbox/ui-checkbox.css +0 -24
  109. package/dist/collection/components/ui-checkbox/ui-checkbox.js +0 -228
  110. package/dist/collection/components/ui-chip/ui-chip.css +0 -57
  111. package/dist/collection/components/ui-chip/ui-chip.js +0 -67
  112. package/dist/collection/components/ui-combobox/ui-combobox.css +0 -47
  113. package/dist/collection/components/ui-combobox/ui-combobox.js +0 -1295
  114. package/dist/collection/components/ui-context-menu/ui-context-menu.css +0 -34
  115. package/dist/collection/components/ui-context-menu/ui-context-menu.js +0 -311
  116. package/dist/collection/components/ui-dialog/ui-dialog.css +0 -72
  117. package/dist/collection/components/ui-dialog/ui-dialog.js +0 -242
  118. package/dist/collection/components/ui-disclosure/ui-disclosure.css +0 -7
  119. package/dist/collection/components/ui-disclosure/ui-disclosure.js +0 -184
  120. package/dist/collection/components/ui-editable/ui-editable.css +0 -2
  121. package/dist/collection/components/ui-editable/ui-editable.js +0 -196
  122. package/dist/collection/components/ui-floating-action-button/ui-floating-action-button.css +0 -73
  123. package/dist/collection/components/ui-floating-action-button/ui-floating-action-button.js +0 -85
  124. package/dist/collection/components/ui-form-field/ui-form-field.css +0 -25
  125. package/dist/collection/components/ui-form-field/ui-form-field.js +0 -180
  126. package/dist/collection/components/ui-icon-button/ui-icon-button.css +0 -145
  127. package/dist/collection/components/ui-icon-button/ui-icon-button.js +0 -128
  128. package/dist/collection/components/ui-input/ui-input.css +0 -48
  129. package/dist/collection/components/ui-input/ui-input.js +0 -217
  130. package/dist/collection/components/ui-menu/ui-menu.css +0 -73
  131. package/dist/collection/components/ui-menu/ui-menu.js +0 -280
  132. package/dist/collection/components/ui-menu-item/ui-menu-item.css +0 -32
  133. package/dist/collection/components/ui-menu-item/ui-menu-item.js +0 -64
  134. package/dist/collection/components/ui-popover/ui-popover.css +0 -58
  135. package/dist/collection/components/ui-popover/ui-popover.js +0 -232
  136. package/dist/collection/components/ui-radio/ui-radio.css +0 -22
  137. package/dist/collection/components/ui-radio/ui-radio.js +0 -226
  138. package/dist/collection/components/ui-radio-group/ui-radio-group.css +0 -10
  139. package/dist/collection/components/ui-radio-group/ui-radio-group.js +0 -247
  140. package/dist/collection/components/ui-search-result-row/ui-search-result-row.css +0 -80
  141. package/dist/collection/components/ui-search-result-row/ui-search-result-row.js +0 -100
  142. package/dist/collection/components/ui-search-shell/ui-search-shell.css +0 -63
  143. package/dist/collection/components/ui-search-shell/ui-search-shell.js +0 -46
  144. package/dist/collection/components/ui-select/ui-select.css +0 -64
  145. package/dist/collection/components/ui-select/ui-select.js +0 -218
  146. package/dist/collection/components/ui-switch/ui-switch.css +0 -63
  147. package/dist/collection/components/ui-switch/ui-switch.js +0 -185
  148. package/dist/collection/components/ui-tabs/ui-tabs.css +0 -68
  149. package/dist/collection/components/ui-tabs/ui-tabs.js +0 -190
  150. package/dist/collection/components/ui-textarea/ui-textarea.css +0 -49
  151. package/dist/collection/components/ui-textarea/ui-textarea.js +0 -241
  152. package/dist/collection/components/ui-toast-region/ui-toast-region.css +0 -59
  153. package/dist/collection/components/ui-toast-region/ui-toast-region.js +0 -126
  154. package/dist/collection/components/ui-tooltip/ui-tooltip.css +0 -43
  155. package/dist/collection/components/ui-tooltip/ui-tooltip.js +0 -430
  156. package/dist/collection/components/ui-top-bar/ui-top-bar.css +0 -51
  157. package/dist/collection/components/ui-top-bar/ui-top-bar.js +0 -52
  158. package/dist/collection/components/ui-tree/ui-tree.css +0 -12
  159. package/dist/collection/components/ui-tree/ui-tree.js +0 -515
  160. package/dist/collection/components/ui-tree-item/ui-tree-item.css +0 -217
  161. package/dist/collection/components/ui-tree-item/ui-tree-item.js +0 -406
  162. package/dist/collection/field/combobox.js +0 -4
  163. package/dist/collection/field/editable.js +0 -1
  164. package/dist/collection/field/multi-combobox.js +0 -1
  165. package/dist/collection/field/valibot.js +0 -5
  166. package/dist/collection/field/validation.js +0 -62
  167. package/dist/collection/icons.js +0 -71
  168. package/dist/collection/input-modality.js +0 -24
  169. package/dist/collection/overlay/manager.js +0 -92
  170. package/dist/collection/overlay/positioning.js +0 -424
  171. package/dist/collection/utils/controlled-state.js +0 -4
  172. package/dist/collection/utils/drag-drop.js +0 -51
  173. package/dist/collection/utils/events.js +0 -13
  174. package/dist/collection/utils/id.js +0 -5
  175. package/dist/collection/utils/initials.js +0 -11
  176. package/dist/components/index.d.ts +0 -102
  177. package/dist/components/index.js +0 -1
  178. package/dist/components/p-6SWSrfmW.js +0 -1
  179. package/dist/components/p-B_DaIVEY.js +0 -1
  180. package/dist/components/p-Bh_1GxOD.js +0 -1
  181. package/dist/components/p-BnGhGgTH.js +0 -1
  182. package/dist/components/p-BzaB_bXo.js +0 -1
  183. package/dist/components/p-C-0syqXZ.js +0 -1
  184. package/dist/components/p-CoFximGM.js +0 -13
  185. package/dist/components/p-JwSoedEO.js +0 -1
  186. package/dist/components/p-Vc4ExHFc.js +0 -1
  187. package/dist/components/p-hgBUJRDa.js +0 -1
  188. package/dist/components/ui-affordance-scope.d.ts +0 -11
  189. package/dist/components/ui-affordance-scope.js +0 -1
  190. package/dist/components/ui-avatar-group.d.ts +0 -11
  191. package/dist/components/ui-avatar-group.js +0 -1
  192. package/dist/components/ui-avatar.d.ts +0 -11
  193. package/dist/components/ui-avatar.js +0 -1
  194. package/dist/components/ui-badge.d.ts +0 -11
  195. package/dist/components/ui-badge.js +0 -1
  196. package/dist/components/ui-button.d.ts +0 -11
  197. package/dist/components/ui-button.js +0 -1
  198. package/dist/components/ui-callout.d.ts +0 -11
  199. package/dist/components/ui-callout.js +0 -1
  200. package/dist/components/ui-checkbox.d.ts +0 -11
  201. package/dist/components/ui-checkbox.js +0 -1
  202. package/dist/components/ui-chip.d.ts +0 -11
  203. package/dist/components/ui-chip.js +0 -1
  204. package/dist/components/ui-combobox.d.ts +0 -11
  205. package/dist/components/ui-combobox.js +0 -1
  206. package/dist/components/ui-context-menu.d.ts +0 -11
  207. package/dist/components/ui-context-menu.js +0 -1
  208. package/dist/components/ui-dialog.d.ts +0 -11
  209. package/dist/components/ui-dialog.js +0 -1
  210. package/dist/components/ui-disclosure.d.ts +0 -11
  211. package/dist/components/ui-disclosure.js +0 -1
  212. package/dist/components/ui-editable.d.ts +0 -11
  213. package/dist/components/ui-editable.js +0 -1
  214. package/dist/components/ui-floating-action-button.d.ts +0 -11
  215. package/dist/components/ui-floating-action-button.js +0 -1
  216. package/dist/components/ui-form-field.d.ts +0 -11
  217. package/dist/components/ui-form-field.js +0 -1
  218. package/dist/components/ui-icon-button.d.ts +0 -11
  219. package/dist/components/ui-icon-button.js +0 -1
  220. package/dist/components/ui-input.d.ts +0 -11
  221. package/dist/components/ui-input.js +0 -1
  222. package/dist/components/ui-menu-item.d.ts +0 -11
  223. package/dist/components/ui-menu-item.js +0 -1
  224. package/dist/components/ui-menu.d.ts +0 -11
  225. package/dist/components/ui-menu.js +0 -1
  226. package/dist/components/ui-popover.d.ts +0 -11
  227. package/dist/components/ui-popover.js +0 -1
  228. package/dist/components/ui-radio-group.d.ts +0 -11
  229. package/dist/components/ui-radio-group.js +0 -1
  230. package/dist/components/ui-radio.d.ts +0 -11
  231. package/dist/components/ui-radio.js +0 -1
  232. package/dist/components/ui-search-result-row.d.ts +0 -11
  233. package/dist/components/ui-search-result-row.js +0 -1
  234. package/dist/components/ui-search-shell.d.ts +0 -11
  235. package/dist/components/ui-search-shell.js +0 -1
  236. package/dist/components/ui-select.d.ts +0 -11
  237. package/dist/components/ui-select.js +0 -1
  238. package/dist/components/ui-switch.d.ts +0 -11
  239. package/dist/components/ui-switch.js +0 -1
  240. package/dist/components/ui-tabs.d.ts +0 -11
  241. package/dist/components/ui-tabs.js +0 -1
  242. package/dist/components/ui-textarea.d.ts +0 -11
  243. package/dist/components/ui-textarea.js +0 -1
  244. package/dist/components/ui-toast-region.d.ts +0 -11
  245. package/dist/components/ui-toast-region.js +0 -1
  246. package/dist/components/ui-tooltip.d.ts +0 -11
  247. package/dist/components/ui-tooltip.js +0 -1
  248. package/dist/components/ui-top-bar.d.ts +0 -11
  249. package/dist/components/ui-top-bar.js +0 -1
  250. package/dist/components/ui-tree-item.d.ts +0 -11
  251. package/dist/components/ui-tree-item.js +0 -1
  252. package/dist/components/ui-tree.d.ts +0 -11
  253. package/dist/components/ui-tree.js +0 -1
  254. package/dist/esm/app-globals-DQuL1Twl.js +0 -3
  255. package/dist/esm/controlled-state-BnGhGgTH.js +0 -6
  256. package/dist/esm/events-JwSoedEO.js +0 -15
  257. package/dist/esm/icons-CoFximGM.js +0 -678
  258. package/dist/esm/id-hgBUJRDa.js +0 -7
  259. package/dist/esm/index-8BGiMGQ0.js +0 -1593
  260. package/dist/esm/index.js +0 -1
  261. package/dist/esm/loader.js +0 -11
  262. package/dist/esm/looma.js +0 -21
  263. package/dist/esm/manager-C-0syqXZ.js +0 -91
  264. package/dist/esm/positioning-ZOr-2PSe.js +0 -421
  265. package/dist/esm/ui-affordance-scope.entry.js +0 -41
  266. package/dist/esm/ui-avatar-group.entry.js +0 -41
  267. package/dist/esm/ui-avatar.entry.js +0 -48
  268. package/dist/esm/ui-badge.entry.js +0 -17
  269. package/dist/esm/ui-button.entry.js +0 -73
  270. package/dist/esm/ui-callout.entry.js +0 -25
  271. package/dist/esm/ui-checkbox.entry.js +0 -95
  272. package/dist/esm/ui-chip_2.entry.js +0 -255
  273. package/dist/esm/ui-combobox.entry.js +0 -706
  274. package/dist/esm/ui-context-menu.entry.js +0 -237
  275. package/dist/esm/ui-dialog.entry.js +0 -129
  276. package/dist/esm/ui-disclosure.entry.js +0 -110
  277. package/dist/esm/ui-editable.entry.js +0 -98
  278. package/dist/esm/ui-floating-action-button.entry.js +0 -18
  279. package/dist/esm/ui-form-field.entry.js +0 -112
  280. package/dist/esm/ui-icon-button.entry.js +0 -21
  281. package/dist/esm/ui-input.entry.js +0 -104
  282. package/dist/esm/ui-menu-item.entry.js +0 -17
  283. package/dist/esm/ui-menu.entry.js +0 -180
  284. package/dist/esm/ui-popover.entry.js +0 -133
  285. package/dist/esm/ui-radio-group.entry.js +0 -132
  286. package/dist/esm/ui-radio.entry.js +0 -92
  287. package/dist/esm/ui-search-result-row.entry.js +0 -45
  288. package/dist/esm/ui-search-shell.entry.js +0 -37
  289. package/dist/esm/ui-select.entry.js +0 -106
  290. package/dist/esm/ui-switch.entry.js +0 -72
  291. package/dist/esm/ui-tabs.entry.js +0 -116
  292. package/dist/esm/ui-textarea.entry.js +0 -108
  293. package/dist/esm/ui-toast-region.entry.js +0 -91
  294. package/dist/esm/ui-top-bar.entry.js +0 -41
  295. package/dist/esm/ui-tree-item.entry.js +0 -133
  296. package/dist/esm/ui-tree.entry.js +0 -498
  297. package/dist/index.cjs.js +0 -1
  298. package/dist/looma/index.esm.js +0 -0
  299. package/dist/looma/looma.esm.js +0 -1
  300. package/dist/looma/p-08f80207.entry.js +0 -1
  301. package/dist/looma/p-0b5b8d9e.entry.js +0 -1
  302. package/dist/looma/p-1249a806.entry.js +0 -1
  303. package/dist/looma/p-16e0669d.entry.js +0 -1
  304. package/dist/looma/p-1c00670f.entry.js +0 -1
  305. package/dist/looma/p-1c5a7522.entry.js +0 -1
  306. package/dist/looma/p-22842f8c.entry.js +0 -1
  307. package/dist/looma/p-2915d5c0.entry.js +0 -1
  308. package/dist/looma/p-3b2961a6.entry.js +0 -1
  309. package/dist/looma/p-3f60f4c8.entry.js +0 -1
  310. package/dist/looma/p-424d6719.entry.js +0 -1
  311. package/dist/looma/p-4caccfce.entry.js +0 -1
  312. package/dist/looma/p-5fdcee1d.entry.js +0 -1
  313. package/dist/looma/p-6d8b99ee.entry.js +0 -1
  314. package/dist/looma/p-6f20d470.entry.js +0 -1
  315. package/dist/looma/p-7c0b5364.entry.js +0 -1
  316. package/dist/looma/p-8BGiMGQ0.js +0 -2
  317. package/dist/looma/p-8bdd9495.entry.js +0 -1
  318. package/dist/looma/p-99116a72.entry.js +0 -1
  319. package/dist/looma/p-9cfbf722.entry.js +0 -1
  320. package/dist/looma/p-9d2662ca.entry.js +0 -1
  321. package/dist/looma/p-9ff2fa19.entry.js +0 -1
  322. package/dist/looma/p-BnGhGgTH.js +0 -1
  323. package/dist/looma/p-C-0syqXZ.js +0 -1
  324. package/dist/looma/p-CoFximGM.js +0 -13
  325. package/dist/looma/p-DQuL1Twl.js +0 -1
  326. package/dist/looma/p-JwSoedEO.js +0 -1
  327. package/dist/looma/p-ZOr-2PSe.js +0 -1
  328. package/dist/looma/p-a2dd4c6c.entry.js +0 -1
  329. package/dist/looma/p-add67e4c.entry.js +0 -1
  330. package/dist/looma/p-b6ede6bb.entry.js +0 -1
  331. package/dist/looma/p-b76e2111.entry.js +0 -1
  332. package/dist/looma/p-ca2a54fd.entry.js +0 -1
  333. package/dist/looma/p-d372b0db.entry.js +0 -1
  334. package/dist/looma/p-d4825822.entry.js +0 -1
  335. package/dist/looma/p-d56571a2.entry.js +0 -1
  336. package/dist/looma/p-d5c3954f.entry.js +0 -1
  337. package/dist/looma/p-e604e906.entry.js +0 -1
  338. package/dist/looma/p-f1f7c5cb.entry.js +0 -1
  339. package/dist/looma/p-hgBUJRDa.js +0 -1
  340. package/dist/types/components/ui-affordance-scope/ui-affordance-scope.d.ts +0 -11
  341. package/dist/types/components/ui-avatar/ui-avatar.d.ts +0 -11
  342. package/dist/types/components/ui-avatar-group/ui-avatar-group.d.ts +0 -11
  343. package/dist/types/components/ui-badge/ui-badge.d.ts +0 -5
  344. package/dist/types/components/ui-button/ui-button.d.ts +0 -13
  345. package/dist/types/components/ui-callout/ui-callout.d.ts +0 -6
  346. package/dist/types/components/ui-checkbox/ui-checkbox.d.ts +0 -20
  347. package/dist/types/components/ui-chip/ui-chip.d.ts +0 -8
  348. package/dist/types/components/ui-combobox/ui-combobox.d.ts +0 -128
  349. package/dist/types/components/ui-context-menu/ui-context-menu.d.ts +0 -43
  350. package/dist/types/components/ui-dialog/ui-dialog.d.ts +0 -27
  351. package/dist/types/components/ui-disclosure/ui-disclosure.d.ts +0 -21
  352. package/dist/types/components/ui-editable/ui-editable.d.ts +0 -24
  353. package/dist/types/components/ui-floating-action-button/ui-floating-action-button.d.ts +0 -6
  354. package/dist/types/components/ui-form-field/ui-form-field.d.ts +0 -18
  355. package/dist/types/components/ui-icon-button/ui-icon-button.d.ts +0 -9
  356. package/dist/types/components/ui-input/ui-input.d.ts +0 -19
  357. package/dist/types/components/ui-menu/ui-menu.d.ts +0 -28
  358. package/dist/types/components/ui-menu-item/ui-menu-item.d.ts +0 -5
  359. package/dist/types/components/ui-popover/ui-popover.d.ts +0 -26
  360. package/dist/types/components/ui-radio/ui-radio.d.ts +0 -20
  361. package/dist/types/components/ui-radio-group/ui-radio-group.d.ts +0 -21
  362. package/dist/types/components/ui-search-result-row/ui-search-result-row.d.ts +0 -15
  363. package/dist/types/components/ui-search-shell/ui-search-shell.d.ts +0 -9
  364. package/dist/types/components/ui-select/ui-select.d.ts +0 -20
  365. package/dist/types/components/ui-switch/ui-switch.d.ts +0 -16
  366. package/dist/types/components/ui-tabs/ui-tabs.d.ts +0 -18
  367. package/dist/types/components/ui-textarea/ui-textarea.d.ts +0 -20
  368. package/dist/types/components/ui-toast-region/ui-toast-region.d.ts +0 -16
  369. package/dist/types/components/ui-tooltip/ui-tooltip.d.ts +0 -57
  370. package/dist/types/components/ui-top-bar/ui-top-bar.d.ts +0 -12
  371. package/dist/types/components/ui-tree/ui-tree.d.ts +0 -53
  372. package/dist/types/components/ui-tree-item/ui-tree-item.d.ts +0 -44
  373. package/dist/types/components.d.ts +0 -1889
  374. package/dist/types/field/combobox.d.ts +0 -46
  375. package/dist/types/field/editable.d.ts +0 -5
  376. package/dist/types/field/multi-combobox.d.ts +0 -11
  377. package/dist/types/field/valibot.d.ts +0 -7
  378. package/dist/types/icons.d.ts +0 -53
  379. package/dist/types/input-modality.d.ts +0 -6
  380. package/dist/types/overlay/manager.d.ts +0 -17
  381. package/dist/types/overlay/positioning.d.ts +0 -74
  382. package/dist/types/stencil-public-runtime.d.ts +0 -1860
  383. package/dist/types/utils/controlled-state.d.ts +0 -4
  384. package/dist/types/utils/drag-drop.d.ts +0 -15
  385. package/dist/types/utils/events.d.ts +0 -4
  386. package/dist/types/utils/id.d.ts +0 -1
  387. package/dist/types/utils/initials.d.ts +0 -1
  388. package/dist/ui-affordance-scope.entry-L6TIXYOP.js +0 -54
  389. package/dist/ui-avatar-group.entry-TCAA6P72.js +0 -51
  390. package/dist/ui-avatar.entry-52DQ7VXA.js +0 -51
  391. package/dist/ui-badge.entry-2XCAA6LL.js +0 -22
  392. package/dist/ui-button.entry-MNFBMNSX.js +0 -83
  393. package/dist/ui-callout.entry-SSHT5TH2.js +0 -32
  394. package/dist/ui-checkbox.entry-LOWIWIWI.js +0 -111
  395. package/dist/ui-chip_2.entry-BIMTSF6C.js +0 -272
  396. package/dist/ui-combobox.entry-25Z4MN7N.js +0 -717
  397. package/dist/ui-context-menu.entry-YZDL5Y4M.js +0 -248
  398. package/dist/ui-dialog.entry-HIXZX5AB.js +0 -146
  399. package/dist/ui-disclosure.entry-2JZHZNDQ.js +0 -126
  400. package/dist/ui-editable.entry-U3VR3XPT.js +0 -110
  401. package/dist/ui-floating-action-button.entry-6S3QN3KJ.js +0 -23
  402. package/dist/ui-form-field.entry-GQOSMLHT.js +0 -120
  403. package/dist/ui-icon-button.entry-QJXKVDM6.js +0 -26
  404. package/dist/ui-input.entry-UWMQ6JMP.js +0 -114
  405. package/dist/ui-menu-item.entry-NHNZKKJS.js +0 -22
  406. package/dist/ui-menu.entry-D53RUJND.js +0 -192
  407. package/dist/ui-popover.entry-7ZSIWCFQ.js +0 -152
  408. package/dist/ui-radio-group.entry-37MSYIH4.js +0 -142
  409. package/dist/ui-radio.entry-7YGCDHXT.js +0 -108
  410. package/dist/ui-search-result-row.entry-6FCCLGAS.js +0 -50
  411. package/dist/ui-search-shell.entry-HSBEXPER.js +0 -41
  412. package/dist/ui-select.entry-GIDIAYRD.js +0 -117
  413. package/dist/ui-switch.entry-MYAL6XPC.js +0 -87
  414. package/dist/ui-tabs.entry-R4TEXQSD.js +0 -128
  415. package/dist/ui-textarea.entry-FW32JNDV.js +0 -119
  416. package/dist/ui-toast-region.entry-BTMFPKZF.js +0 -104
  417. package/dist/ui-top-bar.entry-5DQGJF3B.js +0 -49
  418. package/dist/ui-tree-item.entry-ADT7DSOS.js +0 -145
  419. package/dist/ui-tree.entry-7PYQ5RIN.js +0 -470
  420. package/editor/chunk-64GLF274.js +0 -1271
  421. package/layout/index.css +0 -387
  422. package/loader/cdn.js +0 -1
  423. package/loader/index.cjs.js +0 -1
  424. package/loader/index.d.ts +0 -24
  425. package/loader/index.es2017.js +0 -1
  426. package/loader/index.js +0 -2
  427. package/vue/chunk-ROMBQS2L.js +0 -352
@@ -0,0 +1,2558 @@
1
+ import {
2
+ __export
3
+ } from "./chunk-JK53ENSG.js";
4
+
5
+ // src/ui.ts
6
+ import { registerLoomaPackage } from "@threadlabs/looma/core/declarative";
7
+
8
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-insert-table-grid.js
9
+ var ui_editor_insert_table_grid_exports = {};
10
+ __export(ui_editor_insert_table_grid_exports, {
11
+ default: () => controller
12
+ });
13
+ function bounded(value, fallback) {
14
+ const parsed = Number.parseInt(String(value ?? fallback), 10);
15
+ return Math.min(10, Math.max(1, Number.isFinite(parsed) ? parsed : fallback));
16
+ }
17
+ function controller(host) {
18
+ const element = host.element;
19
+ let selectedRows = 3;
20
+ let selectedCols = 3;
21
+ let previewRows = null;
22
+ let previewCols = null;
23
+ let withHeaderRow = true;
24
+ let selectionCommitted = false;
25
+ const updateSelection = () => {
26
+ const activeRows = previewRows ?? selectedRows;
27
+ const activeCols = previewCols ?? selectedCols;
28
+ const hint = element.querySelector(".ui-editor-insert-table-grid__hint");
29
+ if (hint) hint.textContent = previewRows !== null && previewCols !== null ? `${activeRows} \xD7 ${activeCols}` : `${selectedRows} \xD7 ${selectedCols}${selectionCommitted ? " selected" : ""}`;
30
+ for (const cell of element.querySelectorAll("[data-row][data-col]")) {
31
+ const selected = Number(cell.dataset.row) <= activeRows && Number(cell.dataset.col) <= activeCols;
32
+ cell.classList.toggle("ui-editor-insert-table-grid__cell--selected", selected);
33
+ cell.setAttribute("aria-pressed", String(selected));
34
+ }
35
+ };
36
+ const render = () => {
37
+ element.hidden = !host.state.open;
38
+ if (!host.state.open) return;
39
+ const maxRows = bounded(host.state.maxRows, 8);
40
+ const maxCols = bounded(host.state.maxCols, 8);
41
+ const cells = [];
42
+ for (let row = 1; row <= maxRows; row += 1) for (let col = 1; col <= maxCols; col += 1) {
43
+ const selected = row <= selectedRows && col <= selectedCols;
44
+ cells.push(`<button type="button" data-row="${row}" data-col="${col}" aria-label="${row} rows by ${col} columns" aria-pressed="${selected}" class="ui-editor-insert-table-grid__cell${selected ? " ui-editor-insert-table-grid__cell--selected" : ""}"></button>`);
45
+ }
46
+ element.innerHTML = `<div class="ui-editor-insert-table-grid"><p class="ui-editor-insert-table-grid__hint">${selectedRows} \xD7 ${selectedCols}</p><div class="ui-editor-insert-table-grid__grid" role="group" aria-label="Table dimensions" style="--ui-editor-table-grid-rows:${maxRows};--ui-editor-table-grid-cols:${maxCols}">${cells.join("")}</div><label class="ui-editor-insert-table-grid__header"><input type="checkbox" checked> Header row</label><button type="button" data-insert-table>Insert table</button></div>`;
47
+ const checkbox = element.querySelector('input[type="checkbox"]');
48
+ if (checkbox) {
49
+ checkbox.checked = withHeaderRow;
50
+ checkbox.addEventListener("change", () => {
51
+ withHeaderRow = checkbox.checked;
52
+ });
53
+ }
54
+ updateSelection();
55
+ };
56
+ const onClick = (event) => {
57
+ const cell = event.target.closest?.("[data-row][data-col]");
58
+ if (cell) {
59
+ selectedRows = Number(cell.dataset.row);
60
+ selectedCols = Number(cell.dataset.col);
61
+ previewRows = null;
62
+ previewCols = null;
63
+ selectionCommitted = true;
64
+ updateSelection();
65
+ return;
66
+ }
67
+ if (event.target.closest?.("[data-insert-table]")) {
68
+ host.dispatch("looma-editor-insert-table", { rows: selectedRows, cols: selectedCols, withHeaderRow });
69
+ }
70
+ };
71
+ const onMouseover = (event) => {
72
+ const cell = event.target.closest?.("[data-row][data-col]");
73
+ if (!cell) {
74
+ previewRows = null;
75
+ previewCols = null;
76
+ updateSelection();
77
+ return;
78
+ }
79
+ previewRows = Number(cell.dataset.row);
80
+ previewCols = Number(cell.dataset.col);
81
+ updateSelection();
82
+ };
83
+ const onMouseleave = () => {
84
+ previewRows = null;
85
+ previewCols = null;
86
+ updateSelection();
87
+ };
88
+ element.addEventListener("click", onClick);
89
+ element.addEventListener("mouseover", onMouseover);
90
+ element.addEventListener("mouseleave", onMouseleave);
91
+ const stop = host.effect(render);
92
+ render();
93
+ return () => {
94
+ stop();
95
+ element.removeEventListener("click", onClick);
96
+ element.removeEventListener("mouseover", onMouseover);
97
+ element.removeEventListener("mouseleave", onMouseleave);
98
+ };
99
+ }
100
+
101
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-mention-menu.js
102
+ var ui_editor_mention_menu_exports = {};
103
+ __export(ui_editor_mention_menu_exports, {
104
+ default: () => controller2
105
+ });
106
+
107
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/shared/editor.js
108
+ var backgrounds = [
109
+ ["background-none", "Default", ""],
110
+ ["background-gray", "Gray", "#f3f4f6"],
111
+ ["background-yellow", "Yellow", "#fef3c7"],
112
+ ["background-blue", "Blue", "#dbeafe"],
113
+ ["background-green", "Green", "#dcfce7"],
114
+ ["background-red", "Red", "#fee2e2"]
115
+ ];
116
+ function escapeHtml(value) {
117
+ return String(value).replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#39;");
118
+ }
119
+ var icons = {
120
+ "align-left": [["path", { d: "M21 5H3" }], ["path", { d: "M15 12H3" }], ["path", { d: "M17 19H3" }]],
121
+ "align-center": [["path", { d: "M21 5H3" }], ["path", { d: "M17 12H7" }], ["path", { d: "M19 19H5" }]],
122
+ "align-right": [["path", { d: "M21 5H3" }], ["path", { d: "M21 12H9" }], ["path", { d: "M21 19H7" }]],
123
+ rows: [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M21 9H3" }], ["path", { d: "M21 15H3" }]],
124
+ columns: [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M9 3v18" }], ["path", { d: "M15 3v18" }]],
125
+ table: [["path", { d: "M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18" }]],
126
+ "chevron-down": [["path", { d: "m6 9 6 6 6-6" }]],
127
+ "panel-top": [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M3 9h18" }]],
128
+ "panel-bottom": [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M3 15h18" }]],
129
+ "panel-left": [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M9 3v18" }]],
130
+ "panel-right": [["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2" }], ["path", { d: "M15 3v18" }]],
131
+ eraser: [["path", { d: "M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21" }], ["path", { d: "m5.082 11.09 8.828 8.828" }]],
132
+ merge: [["path", { d: "m8 6 4-4 4 4" }], ["path", { d: "M12 2v10.3a4 4 0 0 1-1.172 2.872L4 22" }], ["path", { d: "m20 22-5-5" }]],
133
+ split: [["path", { d: "M16 3h5v5" }], ["path", { d: "M8 3H3v5" }], ["path", { d: "M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3" }], ["path", { d: "m15 9 6-6" }]],
134
+ trash: [["path", { d: "M10 11v6" }], ["path", { d: "M14 11v6" }], ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" }], ["path", { d: "M3 6h18" }], ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" }]],
135
+ plus: [["path", { d: "M5 12h14" }], ["path", { d: "M12 5v14" }]],
136
+ "grip-vertical": [["circle", { cx: "9", cy: "12", r: "1" }], ["circle", { cx: "9", cy: "5", r: "1" }], ["circle", { cx: "9", cy: "19", r: "1" }], ["circle", { cx: "15", cy: "12", r: "1" }], ["circle", { cx: "15", cy: "5", r: "1" }], ["circle", { cx: "15", cy: "19", r: "1" }]],
137
+ "grip-horizontal": [["circle", { cx: "12", cy: "9", r: "1" }], ["circle", { cx: "19", cy: "9", r: "1" }], ["circle", { cx: "5", cy: "9", r: "1" }], ["circle", { cx: "12", cy: "15", r: "1" }], ["circle", { cx: "19", cy: "15", r: "1" }], ["circle", { cx: "5", cy: "15", r: "1" }]],
138
+ "heading-1": [["path", { d: "M4 12h8" }], ["path", { d: "M4 18V6" }], ["path", { d: "M12 18V6" }], ["path", { d: "m17 12 3-2v8" }]],
139
+ pilcrow: [["path", { d: "M13 4v16" }], ["path", { d: "M17 4v16" }], ["path", { d: "M19 4H9.5a4.5 4.5 0 0 0 0 9H13" }]],
140
+ quote: [["path", { d: "M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z" }], ["path", { d: "M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z" }]]
141
+ };
142
+ function icon(name, className = "looma-icon") {
143
+ const nodes = (icons[name] ?? []).map(([tag, attributes]) => {
144
+ const serialized = Object.entries(attributes).map(([key, value]) => ` ${key}="${value}"`).join("");
145
+ return `<${tag}${serialized}></${tag}>`;
146
+ }).join("");
147
+ return `<svg class="${className}" data-looma-icon="${name}" aria-hidden="true" focusable="false" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${nodes}</svg>`;
148
+ }
149
+ function normalizeAnchor(value) {
150
+ if (!value || typeof value !== "object") return null;
151
+ const finite = (candidate) => typeof candidate === "number" && Number.isFinite(candidate) ? candidate : null;
152
+ const x = finite(value.x);
153
+ const y = finite(value.y);
154
+ const width = finite(value.width);
155
+ const height = finite(value.height);
156
+ const left = finite(value.left) ?? x;
157
+ const top = finite(value.top) ?? y;
158
+ const right = finite(value.right) ?? (left !== null && width !== null ? left + width : null);
159
+ const bottom = finite(value.bottom) ?? (top !== null && height !== null ? top + height : null);
160
+ return left === null || top === null || right === null || bottom === null ? null : { left, top, right, bottom };
161
+ }
162
+ function viewport() {
163
+ const visual = window.visualViewport;
164
+ const left = visual?.offsetLeft ?? 0;
165
+ const top = visual?.offsetTop ?? 0;
166
+ const width = visual?.width ?? window.innerWidth;
167
+ const height = visual?.height ?? window.innerHeight;
168
+ return { left, top, width, height, right: left + width, bottom: top + height };
169
+ }
170
+
171
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-mention-menu.js
172
+ function controller2(host) {
173
+ const element = host.element;
174
+ let selectedIndex = Number(host.state.selectedIndex ?? 0);
175
+ const syncSelection = () => {
176
+ const prefix = element.id || "ui-editor-mention-menu";
177
+ for (const option of element.querySelectorAll("[data-index]")) {
178
+ const active = Number(option.dataset.index) === selectedIndex;
179
+ option.classList.toggle("ui-editor-mention-menu__item--active", active);
180
+ option.setAttribute("aria-selected", String(active));
181
+ }
182
+ if (element.querySelector("[data-index]")) element.setAttribute("aria-activedescendant", `${prefix}-option-${selectedIndex}`);
183
+ };
184
+ const position = () => {
185
+ const rect = normalizeAnchor(host.state.anchorRect);
186
+ if (!rect) {
187
+ element.style.display = "none";
188
+ return;
189
+ }
190
+ const view = viewport();
191
+ element.style.display = "block";
192
+ element.style.position = "fixed";
193
+ element.style.zIndex = "500";
194
+ if (window.innerWidth < 768) {
195
+ const height = Math.min(320, Math.max(0, view.height - 56));
196
+ Object.assign(element.style, { left: `${view.left}px`, top: `${view.top + view.height - height - 56}px`, right: "", bottom: "", width: `${view.width}px`, maxHeight: `${height}px` });
197
+ return;
198
+ }
199
+ const below = view.bottom - rect.bottom - 8;
200
+ const above = rect.top - view.top - 8;
201
+ const top = below >= 320 || below >= above ? rect.bottom + 8 : rect.top - 328;
202
+ const left = Math.max(view.left + 8, Math.min(rect.left, view.right - 328));
203
+ Object.assign(element.style, { top: `${Math.max(view.top + 8, top)}px`, left: `${left}px`, right: "", bottom: "", width: "320px", maxHeight: "" });
204
+ };
205
+ const render = () => {
206
+ const items = (Array.isArray(host.state.items) ? host.state.items : []).slice(0, 20);
207
+ selectedIndex = Math.min(Number(host.state.selectedIndex ?? selectedIndex), Math.max(0, items.length - 1));
208
+ const visible = host.state.open && (host.state.loading || items.length > 0) && normalizeAnchor(host.state.anchorRect);
209
+ element.hidden = !visible;
210
+ if (!visible) return;
211
+ position();
212
+ const prefix = element.id || "ui-editor-mention-menu";
213
+ const selectedId = `${prefix}-option-${selectedIndex}`;
214
+ element.setAttribute("aria-busy", String(Boolean(host.state.loading)));
215
+ if (items.length) element.setAttribute("aria-activedescendant", selectedId);
216
+ else element.removeAttribute("aria-activedescendant");
217
+ const rows = items.map((item, index) => `<li id="${prefix}-option-${index}" class="ui-editor-mention-menu__item${index === selectedIndex ? " ui-editor-mention-menu__item--active" : ""}" role="option" aria-selected="${index === selectedIndex}" data-index="${index}"><span class="ui-editor-mention-menu__avatar" aria-hidden="true">${escapeHtml(item.initials ?? String(item.label).slice(0, 2).toUpperCase())}</span><span class="ui-editor-mention-menu__body"><span class="ui-editor-mention-menu__label">${escapeHtml(item.label)}</span>${item.detail ? `<span class="ui-editor-mention-menu__detail">${escapeHtml(item.detail)}</span>` : ""}</span></li>`).join("");
218
+ element.innerHTML = `<div class="ui-editor-mention-menu"><div class="ui-editor-mention-menu__header"><span>People</span><span class="ui-editor-mention-menu__hint">Type after @ to search</span></div>${host.state.loading && !items.length ? '<div class="ui-editor-mention-menu__loading" role="status">Searching\u2026</div>' : `<ul class="ui-editor-mention-menu__list" role="presentation">${rows}</ul>`}</div>`;
219
+ };
220
+ const onMousedown = (event) => event.preventDefault();
221
+ const onClick = (event) => {
222
+ const option = event.target.closest?.("[data-index]");
223
+ if (option) host.dispatch("looma-editor-mention-menu-select", { index: Number(option.dataset.index) });
224
+ };
225
+ const onMouseover = (event) => {
226
+ const option = event.target.closest?.("[data-index]");
227
+ const index = Number(option?.dataset.index);
228
+ if (!Number.isFinite(index) || index === selectedIndex) return;
229
+ selectedIndex = index;
230
+ syncSelection();
231
+ host.dispatch("looma-editor-mention-menu-highlight", { index });
232
+ };
233
+ const onViewport = () => {
234
+ if (host.state.open) position();
235
+ };
236
+ element.setAttribute("role", "listbox");
237
+ element.setAttribute("aria-label", "Mention a person");
238
+ element.addEventListener("mousedown", onMousedown);
239
+ element.addEventListener("click", onClick);
240
+ element.addEventListener("mouseover", onMouseover);
241
+ window.addEventListener("resize", onViewport);
242
+ window.addEventListener("scroll", onViewport, true);
243
+ window.visualViewport?.addEventListener("resize", onViewport);
244
+ window.visualViewport?.addEventListener("scroll", onViewport);
245
+ const stop = host.effect(render);
246
+ render();
247
+ return () => {
248
+ stop();
249
+ element.removeEventListener("mousedown", onMousedown);
250
+ element.removeEventListener("click", onClick);
251
+ element.removeEventListener("mouseover", onMouseover);
252
+ window.removeEventListener("resize", onViewport);
253
+ window.removeEventListener("scroll", onViewport, true);
254
+ window.visualViewport?.removeEventListener("resize", onViewport);
255
+ window.visualViewport?.removeEventListener("scroll", onViewport);
256
+ };
257
+ }
258
+
259
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-slash-menu.js
260
+ var ui_editor_slash_menu_exports = {};
261
+ __export(ui_editor_slash_menu_exports, {
262
+ default: () => controller3
263
+ });
264
+ function controller3(host) {
265
+ const element = host.element;
266
+ let selectedIndex = Number(host.state.selectedIndex ?? 0);
267
+ const position = () => {
268
+ const rect = normalizeAnchor(host.state.anchorRect);
269
+ if (!rect) {
270
+ element.style.display = "none";
271
+ return;
272
+ }
273
+ const view = viewport();
274
+ element.style.display = "block";
275
+ element.style.position = "fixed";
276
+ element.style.zIndex = "500";
277
+ if (window.innerWidth < 768) {
278
+ const height = Math.min(320, Math.max(0, view.height - 56));
279
+ Object.assign(element.style, { left: `${view.left}px`, right: "", bottom: "", top: `${view.top + view.height - height - 56}px`, width: `${view.width}px`, maxHeight: `${height}px` });
280
+ return;
281
+ }
282
+ const below = view.bottom - rect.bottom - 8;
283
+ const above = rect.top - view.top - 8;
284
+ const top = below >= 320 || below >= above ? rect.bottom + 8 : rect.top - 328;
285
+ const left = Math.max(view.left + 8, Math.min(rect.left, view.right - 288));
286
+ Object.assign(element.style, { top: `${Math.max(view.top + 8, top)}px`, left: `${left}px`, right: "", bottom: "", width: "280px", maxHeight: "" });
287
+ };
288
+ const syncSelection = (ensureVisible = false) => {
289
+ let selected;
290
+ for (const option of element.querySelectorAll("[data-index]")) {
291
+ const active = Number(option.dataset.index) === selectedIndex;
292
+ option.classList.toggle("ui-editor-slash-menu__item--active", active);
293
+ option.setAttribute("aria-selected", String(active));
294
+ if (active) selected = option;
295
+ }
296
+ if (ensureVisible) selected?.scrollIntoView?.({ block: "nearest" });
297
+ };
298
+ const render = () => {
299
+ selectedIndex = Number(host.state.selectedIndex ?? selectedIndex);
300
+ const items = Array.isArray(host.state.items) ? host.state.items : [];
301
+ const visible = host.state.open && items.length > 0 && normalizeAnchor(host.state.anchorRect);
302
+ element.hidden = !visible;
303
+ if (!visible) return;
304
+ position();
305
+ const query = String(host.state.query ?? "").trim();
306
+ element.innerHTML = `<div class="ui-editor-slash-menu"><div class="ui-editor-slash-menu__header" aria-hidden="true"><span class="ui-editor-slash-menu__header-label">Insert</span>${query ? `<span class="ui-editor-slash-menu__header-query">${escapeHtml(query)}</span>` : ""}</div><ul class="ui-editor-slash-menu__list" role="presentation">${items.map((item, index) => `<li class="ui-editor-slash-menu__item${index === selectedIndex ? " ui-editor-slash-menu__item--active" : ""}" role="option" aria-selected="${index === selectedIndex}" data-index="${index}"><span class="ui-editor-slash-menu__icon" aria-hidden="true">${icon(item.icon)}</span><span class="ui-editor-slash-menu__body"><span class="ui-editor-slash-menu__title">${escapeHtml(item.title)}</span><span class="ui-editor-slash-menu__description">${escapeHtml(item.description)}</span></span></li>`).join("")}</ul><div class="ui-editor-slash-menu__footer" aria-hidden="true"><kbd>\u2191\u2193</kbd> navigate &nbsp;\xB7&nbsp; <kbd>\u21B5</kbd> insert &nbsp;\xB7&nbsp; <kbd>Esc</kbd> close</div></div>`;
307
+ };
308
+ const onMousedown = (event) => event.preventDefault();
309
+ const onClick = (event) => {
310
+ const option = event.target.closest?.("[data-index]");
311
+ if (option) host.dispatch("looma-editor-slash-menu-select", { index: Number(option.dataset.index) });
312
+ };
313
+ const onMouseover = (event) => {
314
+ const option = event.target.closest?.("[data-index]");
315
+ const index = Number(option?.dataset.index);
316
+ if (!Number.isFinite(index) || index === selectedIndex) return;
317
+ selectedIndex = index;
318
+ syncSelection();
319
+ host.dispatch("looma-editor-slash-menu-highlight", { index });
320
+ };
321
+ const onViewport = () => {
322
+ if (host.state.open) position();
323
+ };
324
+ element.setAttribute("role", "listbox");
325
+ element.setAttribute("aria-label", "Insert block");
326
+ element.addEventListener("mousedown", onMousedown);
327
+ element.addEventListener("click", onClick);
328
+ element.addEventListener("mouseover", onMouseover);
329
+ window.addEventListener("resize", onViewport);
330
+ window.addEventListener("scroll", onViewport, true);
331
+ window.visualViewport?.addEventListener("resize", onViewport);
332
+ window.visualViewport?.addEventListener("scroll", onViewport);
333
+ const stop = host.effect(render);
334
+ render();
335
+ return () => {
336
+ stop();
337
+ element.removeEventListener("mousedown", onMousedown);
338
+ element.removeEventListener("click", onClick);
339
+ element.removeEventListener("mouseover", onMouseover);
340
+ window.removeEventListener("resize", onViewport);
341
+ window.removeEventListener("scroll", onViewport, true);
342
+ window.visualViewport?.removeEventListener("resize", onViewport);
343
+ window.visualViewport?.removeEventListener("scroll", onViewport);
344
+ };
345
+ }
346
+
347
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-table-context-menu.js
348
+ var ui_editor_table_context_menu_exports = {};
349
+ __export(ui_editor_table_context_menu_exports, {
350
+ default: () => controller4
351
+ });
352
+ var sections = [
353
+ ["Structure", [
354
+ ["add-row-before", "Add row above", "panel-top", "canAddRowBefore"],
355
+ ["add-row-after", "Add row below", "panel-bottom", "canAddRowAfter"],
356
+ ["add-column-before", "Add column left", "panel-left", "canAddColumnBefore"],
357
+ ["add-column-after", "Add column right", "panel-right", "canAddColumnAfter"]
358
+ ]],
359
+ ["Cells", [
360
+ ["clear-cells", "Clear selected cells", "eraser"],
361
+ ["merge-cells", "Merge cells", "merge", "canMergeCells"],
362
+ ["split-cell", "Split cell", "split", "canSplitCell"]
363
+ ]],
364
+ ["Table", [
365
+ ["delete-row", "Delete row", "trash", "canDeleteRow", "danger"],
366
+ ["delete-column", "Delete column", "trash", "canDeleteColumn", "danger"],
367
+ ["delete-table", "Delete table", "trash", "canDeleteTable", "danger"]
368
+ ]]
369
+ ];
370
+ function controller4(host) {
371
+ const element = host.element;
372
+ let positionFrame;
373
+ const position = () => {
374
+ positionFrame = void 0;
375
+ const menu = element.querySelector(".ui-editor-table-context-menu");
376
+ if (!menu) return;
377
+ menu.style.translate = "";
378
+ const rect = menu.getBoundingClientRect();
379
+ const view = viewport();
380
+ const inset = 12;
381
+ let x = 0;
382
+ let y = 0;
383
+ if (rect.left < view.left + inset) x = view.left + inset - rect.left;
384
+ else if (rect.right > view.right - inset) x = view.right - inset - rect.right;
385
+ if (rect.top < view.top + inset) y = view.top + inset - rect.top;
386
+ else if (rect.bottom > view.bottom - inset) y = view.bottom - inset - rect.bottom;
387
+ if (x || y) menu.style.translate = `${x}px ${y}px`;
388
+ };
389
+ const schedule = () => {
390
+ if (positionFrame) cancelAnimationFrame(positionFrame);
391
+ positionFrame = requestAnimationFrame(position);
392
+ };
393
+ const render = () => {
394
+ element.hidden = !host.state.open;
395
+ if (!host.state.open) return;
396
+ const background = String(host.state.cellBackground ?? "");
397
+ const rendered = [];
398
+ const swatches = backgrounds.map(([action, label, swatch]) => {
399
+ const selected = swatch === background;
400
+ return `<button type="button" class="ui-editor-table-context-menu__swatch-button" role="menuitemradio" aria-checked="${selected}" data-action="${action}"${selected ? ' data-selected="true"' : ""}><span class="ui-editor-table-context-menu__swatch${swatch ? "" : " ui-editor-table-context-menu__swatch--default"}"${swatch ? ` style="--ui-editor-table-context-swatch:${swatch}"` : ""}></span><span class="ui-editor-table-context-menu__swatch-label">${label}</span></button>`;
401
+ }).join("");
402
+ rendered.push(`<div class="ui-editor-table-context-menu__section" role="none"><div class="ui-editor-table-context-menu__heading" role="presentation">Cell background</div><div class="ui-editor-table-context-menu__swatches" role="group" aria-label="Cell background">${swatches}</div></div>`);
403
+ for (const [heading, actions] of sections) {
404
+ const available = actions.filter(([, , , capability]) => !capability || host.state[capability]);
405
+ if (!available.length) continue;
406
+ rendered.push(`<div class="ui-editor-table-context-menu__sep"></div><div class="ui-editor-table-context-menu__section" role="none"><div class="ui-editor-table-context-menu__heading" role="presentation">${heading}</div>${available.map(([action, label, iconName, , tone]) => `<button type="button" role="menuitem" data-action="${action}"${tone ? ` data-tone="${tone}"` : ""}>${icon(iconName)}<span>${label}</span></button>`).join("")}</div>`);
407
+ }
408
+ element.innerHTML = `<div class="ui-editor-table-context-menu" role="menu">${rendered.join("")}</div>`;
409
+ schedule();
410
+ };
411
+ const onClick = (event) => {
412
+ const action = event.target.closest?.("[data-action]")?.dataset.action;
413
+ if (action) host.dispatch("looma-editor-table-action", { action });
414
+ };
415
+ element.addEventListener("click", onClick);
416
+ window.addEventListener("resize", schedule);
417
+ window.visualViewport?.addEventListener("resize", schedule);
418
+ window.visualViewport?.addEventListener("scroll", schedule);
419
+ const stop = host.effect(render);
420
+ render();
421
+ return () => {
422
+ stop();
423
+ element.removeEventListener("click", onClick);
424
+ window.removeEventListener("resize", schedule);
425
+ window.visualViewport?.removeEventListener("resize", schedule);
426
+ window.visualViewport?.removeEventListener("scroll", schedule);
427
+ if (positionFrame) cancelAnimationFrame(positionFrame);
428
+ };
429
+ }
430
+
431
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-table-overlay.js
432
+ var ui_editor_table_overlay_exports = {};
433
+ __export(ui_editor_table_overlay_exports, {
434
+ default: () => controller5
435
+ });
436
+ function bounded2(value, fallback) {
437
+ const parsed = Number.parseInt(String(value ?? fallback), 10);
438
+ return Number.isFinite(parsed) ? Math.min(100, Math.max(1, parsed)) : fallback;
439
+ }
440
+ function fallbackBoundaries(segments, length) {
441
+ return Array.from({ length: segments + 1 }, (_, index) => index * length / segments);
442
+ }
443
+ function numbers(value) {
444
+ const values = Array.isArray(value) ? value.map(Number) : typeof value === "string" ? value.split(/[\s,]+/).filter(Boolean).map(Number) : [];
445
+ return values.every(Number.isFinite) ? values : [];
446
+ }
447
+ function cellFrom(value) {
448
+ const values = numbers(value);
449
+ if (values.length !== 6) return null;
450
+ const [left, top, width, height, rowIndex, columnIndex] = values;
451
+ return { left, top, width, height, rowIndex, columnIndex };
452
+ }
453
+ function createProximity(scope, selector = ".ui-editor-table-overlay__handle[data-ui-affordance]", radius = 16) {
454
+ const owner = scope.ownerDocument.defaultView;
455
+ const pointerTarget = scope.ownerDocument;
456
+ let anchors = [];
457
+ let frame = null;
458
+ let point = null;
459
+ let dirty = false;
460
+ const distance = (position, rect) => Math.hypot(
461
+ Math.max(rect.left - position.x, 0, position.x - rect.right),
462
+ Math.max(rect.top - position.y, 0, position.y - rect.bottom)
463
+ );
464
+ const clear = () => {
465
+ for (const anchor of anchors) anchor.element.removeAttribute("data-ui-proximity");
466
+ scope.removeAttribute("data-ui-interaction");
467
+ };
468
+ const measure = () => {
469
+ anchors = Array.from(scope.querySelectorAll(selector)).filter((element) => !element.disabled && element.getAttribute("aria-disabled") !== "true").map((element) => ({ element, rect: element.getBoundingClientRect() }));
470
+ dirty = false;
471
+ };
472
+ const update = () => {
473
+ frame = null;
474
+ if (dirty) measure();
475
+ if (!point) {
476
+ clear();
477
+ return;
478
+ }
479
+ let engaged = false;
480
+ for (const anchor of anchors) {
481
+ const near = distance(point, anchor.rect) <= radius;
482
+ if (near) anchor.element.setAttribute("data-ui-proximity", "near");
483
+ else anchor.element.removeAttribute("data-ui-proximity");
484
+ engaged ||= near;
485
+ }
486
+ if (engaged) scope.setAttribute("data-ui-interaction", "engaged");
487
+ else scope.removeAttribute("data-ui-interaction");
488
+ };
489
+ const schedule = () => {
490
+ if (frame === null) frame = owner.requestAnimationFrame(update);
491
+ };
492
+ const refresh = () => {
493
+ dirty = true;
494
+ schedule();
495
+ };
496
+ const onPointermove = (event) => {
497
+ point = event.pointerType === "touch" ? null : { x: event.clientX, y: event.clientY };
498
+ schedule();
499
+ };
500
+ pointerTarget.addEventListener("pointermove", onPointermove, { passive: true });
501
+ owner.addEventListener("resize", refresh, { passive: true });
502
+ owner.addEventListener("scroll", refresh, { passive: true, capture: true });
503
+ owner.visualViewport?.addEventListener("resize", refresh, { passive: true });
504
+ owner.visualViewport?.addEventListener("scroll", refresh, { passive: true });
505
+ measure();
506
+ return { refresh, destroy() {
507
+ pointerTarget.removeEventListener("pointermove", onPointermove);
508
+ owner.removeEventListener("resize", refresh);
509
+ owner.removeEventListener("scroll", refresh, true);
510
+ owner.visualViewport?.removeEventListener("resize", refresh);
511
+ owner.visualViewport?.removeEventListener("scroll", refresh);
512
+ if (frame !== null) owner.cancelAnimationFrame(frame);
513
+ clear();
514
+ } };
515
+ }
516
+ function controller5(host) {
517
+ const element = host.element;
518
+ let activeControlKey = null;
519
+ const proximity = createProximity(element);
520
+ const boundaries = (axis, segments) => {
521
+ const geometry = host.state.geometry;
522
+ const values = geometry?.[axis === "row" ? "rowBoundaries" : "columnBoundaries"] ?? host.state[axis === "row" ? "rowBoundaries" : "columnBoundaries"];
523
+ const parsed = numbers(values);
524
+ if (parsed.length === segments + 1) return parsed;
525
+ const rect = element.getBoundingClientRect();
526
+ return fallbackBoundaries(segments, axis === "row" ? rect.height : rect.width);
527
+ };
528
+ const insertion = (axis, index, position) => {
529
+ const first = index === 0;
530
+ const noun = axis === "row" ? "row" : "column";
531
+ const action = axis === "row" ? first ? "add-row-before" : "add-row-after" : first ? "add-column-before" : "add-column-after";
532
+ const relation = first ? axis === "row" ? "above" : "left" : axis === "row" ? "below" : "right";
533
+ const label = `Insert ${noun} ${relation}`;
534
+ const key = `${axis}:${index}`;
535
+ return `<div class="ui-editor-table-overlay__control ui-editor-table-overlay__control--${axis}" style="${axis === "row" ? "top" : "left"}:${position}px" data-control-key="${key}" data-active="${activeControlKey === key}"><span class="ui-editor-table-overlay__line" aria-hidden="true"></span><span class="ui-editor-table-overlay__guide" data-ui-guide aria-hidden="true"></span><button type="button" class="ui-editor-table-overlay__handle" data-ui-affordance="insert-${noun}" data-action="${action}" data-boundary-index="${index}" aria-label="${label}">${icon("plus")}<span class="ui-editor-table-overlay__tooltip" role="tooltip">${label}</span></button></div>`;
536
+ };
537
+ const selectors = (cell) => {
538
+ const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
539
+ return `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--row" style="top:${cell.top + cell.height / 2}px" data-action="select-row" ${indexes} title="Select row" aria-label="Select row">${icon("grip-vertical")}</button><button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--column" style="left:${cell.left + cell.width / 2}px" data-action="select-column" ${indexes} title="Select column" aria-label="Select column">${icon("grip-horizontal")}</button>`;
540
+ };
541
+ const menu = (cell) => `<button type="button" class="ui-editor-table-overlay__cell-menu" style="left:${cell.left + cell.width - 30}px;top:${cell.top + 6}px" data-action="open-cell-menu" data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}" title="Cell actions" aria-label="Cell actions">${icon("chevron-down")}</button>`;
542
+ const render = () => {
543
+ element.hidden = !host.state.open;
544
+ if (!host.state.open) {
545
+ activeControlKey = null;
546
+ return;
547
+ }
548
+ const rows = bounded2(host.state.rows, 3);
549
+ const cols = bounded2(host.state.cols, 3);
550
+ const rowBoundaries = boundaries("row", rows);
551
+ const columnBoundaries = boundaries("column", cols);
552
+ const geometry = host.state.geometry;
553
+ const active = geometry?.activeCell ?? cellFrom(host.state.activeCell);
554
+ const hovered = geometry?.hoveredCell ?? cellFrom(host.state.hoveredCell);
555
+ element.innerHTML = `<div class="ui-editor-table-overlay" aria-label="Table controls"><div class="ui-editor-table-overlay__rows">${rowBoundaries.map((position, index) => insertion("row", index, position)).join("")}</div><div class="ui-editor-table-overlay__cols">${columnBoundaries.map((position, index) => insertion("col", index, position)).join("")}</div>${hovered ? selectors(hovered) : ""}${active ? menu(active) : ""}</div>`;
556
+ proximity.refresh();
557
+ };
558
+ const setActive = (key) => {
559
+ if (activeControlKey === key) return;
560
+ activeControlKey = key;
561
+ for (const control of element.querySelectorAll("[data-control-key]")) control.dataset.active = String(control.dataset.controlKey === key);
562
+ };
563
+ const onClick = (event) => {
564
+ const button = event.target.closest?.("button[data-action]");
565
+ if (!button) return;
566
+ const action = button.dataset.action;
567
+ if (action === "select-row" || action === "select-column") {
568
+ host.dispatch("looma-editor-table-overlay-action", { action, rowIndex: Number(button.dataset.rowIndex), columnIndex: Number(button.dataset.columnIndex) });
569
+ return;
570
+ }
571
+ if (action === "open-cell-menu") {
572
+ const rect = button.getBoundingClientRect();
573
+ host.dispatch("looma-editor-table-overlay-action", { action, rowIndex: Number(button.dataset.rowIndex), columnIndex: Number(button.dataset.columnIndex), anchor: { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom } });
574
+ return;
575
+ }
576
+ host.dispatch("looma-editor-table-overlay-action", { action, boundaryIndex: Number(button.dataset.boundaryIndex) });
577
+ };
578
+ const enter = (event) => setActive(event.target.closest?.("[data-control-key]")?.dataset.controlKey ?? null);
579
+ const leave = (event) => setActive(event.relatedTarget instanceof Element ? event.relatedTarget.closest?.("[data-control-key]")?.dataset.controlKey ?? null : null);
580
+ element.addEventListener("click", onClick);
581
+ element.addEventListener("pointerover", enter);
582
+ element.addEventListener("pointerout", leave);
583
+ element.addEventListener("focusin", enter);
584
+ element.addEventListener("focusout", leave);
585
+ const stop = host.effect(render);
586
+ render();
587
+ return () => {
588
+ stop();
589
+ proximity.destroy();
590
+ element.removeEventListener("click", onClick);
591
+ element.removeEventListener("pointerover", enter);
592
+ element.removeEventListener("pointerout", leave);
593
+ element.removeEventListener("focusin", enter);
594
+ element.removeEventListener("focusout", leave);
595
+ };
596
+ }
597
+
598
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-table-toolbar.js
599
+ var ui_editor_table_toolbar_exports = {};
600
+ __export(ui_editor_table_toolbar_exports, {
601
+ default: () => controller6
602
+ });
603
+ var overflowSections = [
604
+ ["Structure", [["add-row-before", "Add row above", "panel-top", "canAddRowBefore"], ["add-column-before", "Add column left", "panel-left", "canAddColumnBefore"]]],
605
+ ["Cells", [["clear-cells", "Clear selected cells", "eraser"], ["merge-cells", "Merge selected cells", "merge", "canMergeCells"], ["split-cell", "Split merged cell", "split", "canSplitCell"]]],
606
+ ["Table", [["delete-row", "Delete row", "trash", "canDeleteRow", "danger"], ["delete-column", "Delete column", "trash", "canDeleteColumn", "danger"], ["delete-table", "Delete table", "trash", "canDeleteTable", "danger"]]]
607
+ ];
608
+ function controller6(host) {
609
+ const element = host.element;
610
+ let overflowOpen = false;
611
+ const render = () => {
612
+ element.hidden = !host.state.open;
613
+ if (!host.state.open) {
614
+ overflowOpen = false;
615
+ return;
616
+ }
617
+ const active = `align-${host.state.cellAlignment === "center" || host.state.cellAlignment === "right" ? host.state.cellAlignment : "left"}`;
618
+ const alignments = [["align-left", "Align left"], ["align-center", "Align center"], ["align-right", "Align right"]];
619
+ const structure = [["add-row-after", "Add row", "rows", "canAddRowAfter"], ["add-column-after", "Add column", "columns", "canAddColumnAfter"]].filter(([, , , capability]) => host.state[capability]);
620
+ const background = String(host.state.cellBackground ?? "");
621
+ const menu = overflowOpen ? `<div class="ui-editor-table-toolbar__menu" role="menu" aria-label="More table actions"><div class="ui-editor-table-toolbar__menu-section" role="none"><div class="ui-editor-table-toolbar__menu-heading" role="presentation">Background</div><div class="ui-editor-table-toolbar__swatches" role="group" aria-label="Cell background">${backgrounds.map(([action, label, swatch]) => {
622
+ const selected = swatch === background;
623
+ return `<button type="button" class="ui-editor-table-toolbar__swatch-button" role="menuitemradio" aria-checked="${selected}" data-action="${action}"${selected ? ' data-selected="true"' : ""}><span class="ui-editor-table-toolbar__swatch${swatch ? "" : " ui-editor-table-toolbar__swatch--default"}"${swatch ? ` style="--ui-editor-table-toolbar-swatch:${swatch}"` : ""}></span><span>${label}</span></button>`;
624
+ }).join("")}</div></div>${overflowSections.map(([heading, actions]) => {
625
+ const available = actions.filter(([, , , capability]) => !capability || host.state[capability]);
626
+ return available.length ? `<div class="ui-editor-table-toolbar__menu-section ui-editor-table-toolbar__menu-section--divided" role="none"><div class="ui-editor-table-toolbar__menu-heading" role="presentation">${heading}</div>${available.map(([action, label, iconName, , tone]) => `<button type="button" role="menuitem" data-action="${action}"${tone ? ` data-tone="${tone}"` : ""}>${icon(iconName)}<span>${label}</span></button>`).join("")}</div>` : "";
627
+ }).join("")}</div>` : "";
628
+ element.innerHTML = `<div class="ui-editor-table-toolbar" role="toolbar" aria-label="Table actions"><div class="ui-editor-table-toolbar__group" role="group" aria-label="Cell alignment">${alignments.map(([action, label]) => `<button type="button" class="ui-editor-table-toolbar__icon-button" data-action="${action}" aria-label="${label}" title="${label}" aria-pressed="${action === active}" data-active="${action === active}">${icon(action)}</button>`).join("")}</div>${structure.length ? '<div class="ui-editor-table-toolbar__sep" aria-hidden="true"></div><div class="ui-editor-table-toolbar__group" role="group" aria-label="Table structure">' + structure.map(([action, label, iconName]) => `<button type="button" data-action="${action}">${icon(iconName)}<span>${label}</span></button>`).join("") + "</div>" : ""}<div class="ui-editor-table-toolbar__sep" aria-hidden="true"></div><div class="ui-editor-table-toolbar__overflow"><button type="button" class="ui-editor-table-toolbar__more" data-action="toggle-overflow" aria-haspopup="menu" aria-expanded="${overflowOpen}">${icon("table")}<span>Table options</span>${icon("chevron-down", "looma-icon looma-icon--chevron")}</button>${menu}</div></div>`;
629
+ };
630
+ const onClick = (event) => {
631
+ const action = event.target.closest?.("[data-action]")?.dataset.action;
632
+ if (!action) return;
633
+ if (action === "toggle-overflow") {
634
+ overflowOpen = !overflowOpen;
635
+ render();
636
+ return;
637
+ }
638
+ overflowOpen = false;
639
+ render();
640
+ host.dispatch("looma-editor-table-action", { action });
641
+ };
642
+ const onOutside = (event) => {
643
+ if (!overflowOpen || event.composedPath().includes(element)) return;
644
+ overflowOpen = false;
645
+ render();
646
+ };
647
+ element.addEventListener("click", onClick);
648
+ document.addEventListener("pointerdown", onOutside, true);
649
+ const stop = host.effect(render);
650
+ render();
651
+ return () => {
652
+ stop();
653
+ element.removeEventListener("click", onClick);
654
+ document.removeEventListener("pointerdown", onOutside, true);
655
+ };
656
+ }
657
+
658
+ // ../../tools/migrate-html-next/generated/editor/components/controllers/ui-editor-toolbar.js
659
+ var ui_editor_toolbar_exports = {};
660
+ __export(ui_editor_toolbar_exports, {
661
+ default: () => controller7
662
+ });
663
+ function controller7(host) {
664
+ const element = host.element;
665
+ if (!element.hasAttribute("role")) element.setAttribute("role", "toolbar");
666
+ if (!element.hasAttribute("aria-label")) element.setAttribute("aria-label", "Editor toolbar");
667
+ }
668
+
669
+ // ../../tools/migrate-html-next/generated/adoption/editor/registry.js
670
+ var records = [
671
+ { tag: "ui-editor-insert-table-grid", source: '<template component="ui-editor-insert-table-grid" status="early" summary="Looma ui-editor-insert-table-grid editor surface." controller="./controllers/ui-editor-insert-table-grid.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="maxRows" type="integer" default="8">maxRows value.</prop>\n <prop name="maxCols" type="integer" default="8">maxCols value.</prop>\n <event name="looma-editor-insert-table" type="object({ rows: integer, cols: integer, withHeaderRow: boolean })"></event>\n </defs>\n <div></div>\n</template>\n', controller: ui_editor_insert_table_grid_exports },
672
+ { tag: "ui-editor-mention-menu", source: '<template component="ui-editor-mention-menu" status="early" summary="Looma ui-editor-mention-menu editor surface." controller="./controllers/ui-editor-mention-menu.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="query" type="string" default="">query value.</prop>\n <prop name="items" type="list(object({ id: string, label: string, detail?: string, initials?: string }))">items value.</prop>\n <prop name="selectedIndex" type="integer" default="0">selectedIndex value.</prop>\n <prop name="loading" type="boolean" default="false">loading value.</prop>\n <prop name="anchorRect" type="object({ left?: number, top?: number, right?: number, bottom?: number, x?: number, y?: number, width?: number, height?: number }) | null">anchorRect value.</prop>\n <event name="looma-editor-mention-menu-highlight" type="object({ index: integer })"></event>\n <event name="looma-editor-mention-menu-select" type="object({ index: integer })"></event>\n </defs>\n <div .items="items" .anchorRect="anchorRect"></div>\n</template>\n', controller: ui_editor_mention_menu_exports },
673
+ { tag: "ui-editor-slash-menu", source: '<template component="ui-editor-slash-menu" status="early" summary="Looma ui-editor-slash-menu editor surface." controller="./controllers/ui-editor-slash-menu.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="query" type="string" default="">query value.</prop>\n <prop name="items" type="list(object({ title: string, description: string, icon: string }))">items value.</prop>\n <prop name="selectedIndex" type="integer" default="0">selectedIndex value.</prop>\n <prop name="anchorRect" type="object({ left?: number, top?: number, right?: number, bottom?: number, x?: number, y?: number, width?: number, height?: number }) | null">anchorRect value.</prop>\n <event name="looma-editor-slash-menu-highlight" type="object({ index: integer })"></event>\n <event name="looma-editor-slash-menu-select" type="object({ index: integer })"></event>\n </defs>\n <div .items="items" .anchorRect="anchorRect"></div>\n</template>\n', controller: ui_editor_slash_menu_exports },
674
+ { tag: "ui-editor-table-context-menu", source: '<template component="ui-editor-table-context-menu" status="early" summary="Looma ui-editor-table-context-menu editor surface." controller="./controllers/ui-editor-table-context-menu.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="cellBackground" type="string" default="">cellBackground value.</prop>\n <prop name="canAddRowBefore" type="boolean" default="false">canAddRowBefore value.</prop>\n <prop name="canAddRowAfter" type="boolean" default="false">canAddRowAfter value.</prop>\n <prop name="canAddColumnBefore" type="boolean" default="false">canAddColumnBefore value.</prop>\n <prop name="canAddColumnAfter" type="boolean" default="false">canAddColumnAfter value.</prop>\n <prop name="canDeleteRow" type="boolean" default="false">canDeleteRow value.</prop>\n <prop name="canDeleteColumn" type="boolean" default="false">canDeleteColumn value.</prop>\n <prop name="canDeleteTable" type="boolean" default="false">canDeleteTable value.</prop>\n <prop name="canMergeCells" type="boolean" default="false">canMergeCells value.</prop>\n <prop name="canSplitCell" type="boolean" default="false">canSplitCell value.</prop>\n <event name="looma-editor-table-action" type="object({ action: string })"></event>\n </defs>\n <div></div>\n</template>\n', controller: ui_editor_table_context_menu_exports },
675
+ { tag: "ui-editor-table-overlay", source: '<template component="ui-editor-table-overlay" status="early" summary="Looma ui-editor-table-overlay editor surface." controller="./controllers/ui-editor-table-overlay.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="rows" type="integer" default="3">rows value.</prop>\n <prop name="cols" type="integer" default="3">cols value.</prop>\n <prop name="rowBoundaries" type="string | list(number)">rowBoundaries value.</prop>\n <prop name="columnBoundaries" type="string | list(number)">columnBoundaries value.</prop>\n <prop name="activeCell" type="string | list(number)">activeCell value.</prop>\n <prop name="hoveredCell" type="string | list(number)">hoveredCell value.</prop>\n <prop name="geometry" type="object({ rowBoundaries: list(number), columnBoundaries: list(number), activeCell: object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer }) | null, hoveredCell?: object({ left: number, top: number, width: number, height: number, rowIndex: integer, columnIndex: integer }) | null }) | null">geometry value.</prop>\n <event name="looma-editor-table-overlay-action" type="object({ action: string, boundaryIndex?: integer, rowIndex?: integer, columnIndex?: integer, anchor?: object({ left: number, top: number, right: number, bottom: number }) })"></event>\n </defs>\n <div .geometry="geometry"></div>\n</template>\n', controller: ui_editor_table_overlay_exports },
676
+ { tag: "ui-editor-table-toolbar", source: '<template component="ui-editor-table-toolbar" status="early" summary="Looma ui-editor-table-toolbar editor surface." controller="./controllers/ui-editor-table-toolbar.js">\n <defs>\n <prop name="open" type="boolean" default="false">open value.</prop>\n <prop name="cellAlignment" type="left | center | right" default="left">cellAlignment value.</prop>\n <prop name="cellBackground" type="string" default="">cellBackground value.</prop>\n <prop name="canAddRowBefore" type="boolean" default="false">canAddRowBefore value.</prop>\n <prop name="canAddRowAfter" type="boolean" default="false">canAddRowAfter value.</prop>\n <prop name="canAddColumnBefore" type="boolean" default="false">canAddColumnBefore value.</prop>\n <prop name="canAddColumnAfter" type="boolean" default="false">canAddColumnAfter value.</prop>\n <prop name="canDeleteRow" type="boolean" default="false">canDeleteRow value.</prop>\n <prop name="canDeleteColumn" type="boolean" default="false">canDeleteColumn value.</prop>\n <prop name="canDeleteTable" type="boolean" default="false">canDeleteTable value.</prop>\n <prop name="canMergeCells" type="boolean" default="false">canMergeCells value.</prop>\n <prop name="canSplitCell" type="boolean" default="false">canSplitCell value.</prop>\n <event name="looma-editor-table-action" type="object({ action: string })"></event>\n </defs>\n <div></div>\n</template>\n', controller: ui_editor_table_toolbar_exports },
677
+ { tag: "ui-editor-toolbar", source: '<template component="ui-editor-toolbar" status="early" summary="Looma ui-editor-toolbar editor surface." controller="./controllers/ui-editor-toolbar.js">\n <defs>\n\n </defs>\n <div><slot></slot></div>\n</template>\n', controller: ui_editor_toolbar_exports }
678
+ ];
679
+ var styles = `/**
680
+ * Looma editor styles (tokens-based).
681
+ * Tables, context menu, insert-table grid, slash menu. Use with ProseMirror/Tiptap content.
682
+ */
683
+
684
+ /* Turnkey editor */
685
+ .looma-editor {
686
+ position: relative;
687
+ min-width: 0;
688
+ color: var(--ui-text-primary);
689
+ font-family: var(--ui-font-family-sans);
690
+ }
691
+
692
+ .looma-editor .ProseMirror {
693
+ min-height: var(--ui-editor-content-min-height, 300px);
694
+ padding:
695
+ var(--ui-editor-content-padding-block, var(--ui-space-4))
696
+ var(--ui-editor-content-padding-inline, var(--ui-space-6));
697
+ outline: none;
698
+ color: var(--ui-editor-content-color, var(--ui-text-primary));
699
+ caret-color: var(--ui-editor-caret-color, var(--ui-accent-solid));
700
+ font-family: var(--ui-editor-font-family, var(--ui-font-family-sans));
701
+ font-size: var(--ui-editor-font-size, var(--ui-font-size-md));
702
+ line-height: var(--ui-editor-line-height, var(--ui-line-height-relaxed));
703
+ }
704
+
705
+ @media (max-width: 767px) {
706
+ .looma-editor .ProseMirror {
707
+ padding-bottom: var(--ui-editor-mobile-bottom-space, 80px);
708
+ }
709
+ }
710
+
711
+ .looma-editor .ProseMirror p {
712
+ margin: 0 0 var(--ui-editor-paragraph-gap, var(--ui-space-3));
713
+ }
714
+
715
+ .looma-editor .ProseMirror h1,
716
+ .looma-editor .ProseMirror h2,
717
+ .looma-editor .ProseMirror h3 {
718
+ color: inherit;
719
+ line-height: var(--ui-line-height-tight);
720
+ }
721
+
722
+ .looma-editor .ProseMirror h1 {
723
+ margin: var(--ui-space-6) 0 var(--ui-space-3);
724
+ font-size: var(--ui-font-size-2xl);
725
+ font-weight: var(--ui-font-bold);
726
+ }
727
+
728
+ .looma-editor .ProseMirror h2 {
729
+ margin: var(--ui-space-5) 0 var(--ui-space-2);
730
+ font-size: var(--ui-font-size-xl);
731
+ font-weight: var(--ui-font-semibold);
732
+ }
733
+
734
+ .looma-editor .ProseMirror h3 {
735
+ margin: var(--ui-space-4) 0 var(--ui-space-2);
736
+ font-size: var(--ui-font-size-lg);
737
+ font-weight: var(--ui-font-semibold);
738
+ }
739
+
740
+ .looma-editor .ProseMirror ul,
741
+ .looma-editor .ProseMirror ol {
742
+ margin: 0 0 var(--ui-space-3);
743
+ /* Nested lists retain the browser's hierarchy; this is only the root inset. */
744
+ padding-inline-start: var(--ui-editor-list-inset, var(--ui-space-5));
745
+ }
746
+
747
+ .looma-editor .ProseMirror li {
748
+ margin-bottom: var(--ui-space-1);
749
+ }
750
+
751
+ .looma-editor .ProseMirror blockquote {
752
+ margin: var(--ui-space-4) 0;
753
+ padding-left: var(--ui-space-4);
754
+ border-left: 3px solid var(--ui-accent-solid);
755
+ color: var(--ui-text-secondary);
756
+ font-style: italic;
757
+ }
758
+
759
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone] {
760
+ --ui-callout-padding-block: var(--ui-space-2);
761
+ --ui-callout-padding-inline: var(--ui-space-3);
762
+ --ui-callout-icon-column: 1rem;
763
+ --ui-callout-gap: var(--ui-space-2);
764
+ --ui-callout-icon-size: 1rem;
765
+ --ui-callout-border-width: 1px;
766
+ --ui-callout-leading-border-width: 4px;
767
+ --ui-callout-surface: var(--ui-accent-soft);
768
+ --ui-callout-text: var(--ui-text-primary);
769
+ --ui-callout-border: var(--ui-accent-solid);
770
+ --ui-callout-icon: var(--ui-accent-solid);
771
+ --ui-editor-callout-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M13.4 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7.4'/%3E%3Cpath d='M2 6h4'/%3E%3Cpath d='M2 10h4'/%3E%3Cpath d='M2 14h4'/%3E%3Cpath d='M2 18h4'/%3E%3Cpath d='M21.378 5.626a1 1 0 1 0-3.004-3.004l-5.01 5.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z'/%3E%3C/svg%3E");
772
+
773
+ display: grid;
774
+ grid-template-columns: var(--ui-callout-icon-column) minmax(0, 1fr);
775
+ align-items: start;
776
+ column-gap: var(--ui-callout-gap);
777
+ margin: var(--ui-space-4) 0;
778
+ padding: var(--ui-callout-padding-block) var(--ui-callout-padding-inline);
779
+ border: var(--ui-callout-border-width) solid color-mix(in srgb, var(--ui-callout-border) 35%, transparent);
780
+ border-inline-start: var(--ui-callout-leading-border-width) solid var(--ui-callout-border);
781
+ border-radius: var(--ui-radius-2);
782
+ background: var(--ui-callout-surface);
783
+ color: var(--ui-callout-text);
784
+ }
785
+
786
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone]::before {
787
+ width: var(--ui-callout-icon-size);
788
+ height: var(--ui-callout-icon-size);
789
+ margin-top: 0.2em;
790
+ background: var(--ui-callout-icon);
791
+ content: "";
792
+ mask: var(--ui-editor-callout-icon) center / contain no-repeat;
793
+ -webkit-mask: var(--ui-editor-callout-icon) center / contain no-repeat;
794
+ }
795
+
796
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone] > * {
797
+ grid-column: 2;
798
+ }
799
+
800
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone] > :last-child {
801
+ margin-bottom: 0;
802
+ }
803
+
804
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone="info"] {
805
+ --ui-callout-surface: var(--ui-info-soft);
806
+ --ui-callout-border: var(--ui-info-solid);
807
+ --ui-callout-icon: var(--ui-info-solid);
808
+ --ui-editor-callout-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 16v-4'/%3E%3Cpath d='M12 8h.01'/%3E%3C/svg%3E");
809
+ }
810
+
811
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone="note"] {
812
+ --ui-callout-surface: var(--ui-accent-soft);
813
+ --ui-callout-border: var(--ui-accent-solid);
814
+ --ui-callout-icon: var(--ui-accent-solid);
815
+ }
816
+
817
+ .looma-editor .ProseMirror aside[data-looma-callout][data-tone="warning"] {
818
+ --ui-callout-surface: var(--ui-warning-soft);
819
+ --ui-callout-border: var(--ui-warning-solid);
820
+ --ui-callout-icon: var(--ui-warning-solid);
821
+ --ui-editor-callout-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E");
822
+ }
823
+
824
+ .looma-editor .ProseMirror pre {
825
+ margin: var(--ui-space-4) 0;
826
+ padding: var(--ui-space-4);
827
+ overflow-x: auto;
828
+ border: 1px solid var(--ui-border-default);
829
+ border-radius: var(--ui-radius-2);
830
+ background: var(--ui-surface-muted);
831
+ font-family: var(--ui-font-family-mono, ui-monospace, monospace);
832
+ font-size: var(--ui-font-size-sm);
833
+ }
834
+
835
+ .looma-editor .ProseMirror code {
836
+ padding: 0.1em 0.3em;
837
+ border-radius: var(--ui-radius-1);
838
+ background: var(--ui-surface-subtle);
839
+ font-family: var(--ui-font-family-mono, ui-monospace, monospace);
840
+ font-size: 0.9em;
841
+ }
842
+
843
+ .looma-editor .ProseMirror pre code {
844
+ padding: 0;
845
+ background: none;
846
+ }
847
+
848
+ .looma-editor .ProseMirror hr {
849
+ margin: var(--ui-space-6) 0;
850
+ border: 0;
851
+ border-top: 1px solid var(--ui-border-default);
852
+ }
853
+
854
+ .looma-editor .ProseMirror mark {
855
+ border-radius: var(--ui-radius-1);
856
+ background: var(--ui-editor-highlight-bg, var(--ui-warning-soft));
857
+ }
858
+
859
+ .looma-editor .ProseMirror a {
860
+ color: var(--ui-editor-link-color, var(--ui-accent-solid));
861
+ text-decoration: underline;
862
+ }
863
+
864
+ .looma-editor .ProseMirror ul[data-type="taskList"] {
865
+ padding-left: var(--ui-space-2);
866
+ list-style: none;
867
+ }
868
+
869
+ .looma-editor .ProseMirror ul[data-type="taskList"] li {
870
+ display: flex;
871
+ align-items: flex-start;
872
+ gap: var(--ui-space-2);
873
+ }
874
+
875
+ .looma-editor .ProseMirror ul[data-type="taskList"] li > label {
876
+ margin-top: 3px;
877
+ }
878
+
879
+ .looma-editor .ProseMirror ul[data-type="taskList"] input[type="checkbox"] {
880
+ width: 16px;
881
+ height: 16px;
882
+ accent-color: var(--ui-accent-solid);
883
+ cursor: pointer;
884
+ }
885
+
886
+ .looma-editor .ProseMirror .is-editor-empty:first-child::before {
887
+ float: left;
888
+ height: 0;
889
+ color: var(--ui-text-muted);
890
+ content: attr(data-placeholder);
891
+ pointer-events: none;
892
+ }
893
+
894
+ .looma-editor .ProseMirror img {
895
+ max-width: 100%;
896
+ height: auto;
897
+ margin: var(--ui-space-3) 0;
898
+ border-radius: var(--ui-radius-2);
899
+ }
900
+
901
+ .looma-editor .ProseMirror img[data-looma-image]:focus-visible {
902
+ outline: 2px solid var(--ui-focus-ring);
903
+ outline-offset: 3px;
904
+ }
905
+
906
+ .looma-editor__file-input {
907
+ position: absolute;
908
+ width: 0;
909
+ height: 0;
910
+ opacity: 0;
911
+ pointer-events: none;
912
+ }
913
+
914
+ .looma-editor__upload-error {
915
+ display: flex;
916
+ align-items: center;
917
+ justify-content: space-between;
918
+ gap: var(--ui-space-3);
919
+ margin-top: var(--ui-space-3);
920
+ padding: var(--ui-space-2) var(--ui-space-3);
921
+ border: 1px solid var(--ui-danger-solid);
922
+ border-radius: var(--ui-radius-2);
923
+ background: var(--ui-danger-soft);
924
+ color: var(--ui-text);
925
+ font-size: var(--ui-font-size-sm);
926
+ }
927
+
928
+ .looma-editor__upload-error button {
929
+ min-height: 2rem;
930
+ padding: 0 var(--ui-space-3);
931
+ border: 0;
932
+ border-radius: var(--ui-radius-1);
933
+ background: var(--ui-danger-solid);
934
+ color: var(--ui-text-on-accent);
935
+ cursor: pointer;
936
+ font: inherit;
937
+ font-weight: var(--ui-font-semibold);
938
+ }
939
+
940
+ .looma-editor__upload-error button:focus-visible {
941
+ outline: 2px solid var(--ui-focus-ring);
942
+ outline-offset: 2px;
943
+ }
944
+
945
+ .looma-editor__upload-error button:disabled {
946
+ cursor: wait;
947
+ opacity: 0.65;
948
+ }
949
+
950
+ .looma-editor__drop-overlay {
951
+ position: absolute;
952
+ z-index: var(--ui-editor-drop-overlay-z-index, 10);
953
+ inset: 0;
954
+ display: flex;
955
+ flex-direction: column;
956
+ align-items: center;
957
+ justify-content: center;
958
+ gap: var(--ui-space-3);
959
+ border: 2px dashed var(--ui-accent-solid);
960
+ border-radius: var(--ui-radius-2);
961
+ background: color-mix(in srgb, var(--ui-accent-soft) 92%, transparent);
962
+ color: var(--ui-accent-active);
963
+ font-size: var(--ui-font-size-sm);
964
+ font-weight: var(--ui-font-semibold);
965
+ pointer-events: none;
966
+ }
967
+
968
+ .looma-editor__drop-overlay > .looma-icon {
969
+ width: var(--ui-font-size-2xl);
970
+ height: var(--ui-font-size-2xl);
971
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
972
+ }
973
+
974
+ .looma-editor__toolbar-button {
975
+ --ui-icon-button-size-sm: var(--ui-editor-toolbar-button-size, 2rem);
976
+ --ui-icon-button-radius: var(--ui-editor-toolbar-button-radius, var(--ui-radius-1));
977
+ --ui-icon-button-icon-size: var(--ui-editor-toolbar-icon-size, 1rem);
978
+ }
979
+
980
+ .looma-editor__toolbar-button > .looma-icon {
981
+ width: var(--ui-editor-toolbar-icon-size, 1rem);
982
+ height: var(--ui-editor-toolbar-icon-size, 1rem);
983
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
984
+ }
985
+
986
+ .looma-editor__table-picker-popover,
987
+ .looma-editor__table-toolbar-shell,
988
+ .looma-editor__table-menu-shell {
989
+ z-index: var(--ui-editor-popover-z-index, 300);
990
+ }
991
+
992
+ .looma-editor__table-picker-popover {
993
+ min-width: 220px;
994
+ padding: 0;
995
+ border: 0;
996
+ background: transparent;
997
+ }
998
+
999
+ .looma-editor__table-toolbar-shell,
1000
+ .looma-editor__table-menu-shell,
1001
+ .looma-editor__table-overlay-shell {
1002
+ position: fixed;
1003
+ }
1004
+
1005
+ .looma-editor__mobile-toolbar-shell {
1006
+ position: fixed;
1007
+ z-index: var(--ui-editor-mobile-toolbar-z-index, var(--ui-editor-popover-z-index, 300));
1008
+ display: flex;
1009
+ align-items: stretch;
1010
+ min-height: var(--ui-editor-toolbar-mobile-min-height, 56px);
1011
+ padding:
1012
+ var(--ui-editor-mobile-toolbar-padding-block, 4px)
1013
+ max(var(--ui-editor-mobile-toolbar-padding-inline, 8px), env(safe-area-inset-left));
1014
+ overflow-x: auto;
1015
+ overflow-y: hidden;
1016
+ overscroll-behavior-inline: contain;
1017
+ -webkit-overflow-scrolling: touch;
1018
+ scroll-snap-type: x mandatory;
1019
+ scrollbar-width: none;
1020
+ background: var(--ui-editor-toolbar-bg, var(--ui-surface, #fff));
1021
+ border-top: 1px solid var(--ui-editor-toolbar-border, var(--ui-border, #e5e7eb));
1022
+ box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));
1023
+ }
1024
+
1025
+ .looma-editor__mobile-toolbar-shell::-webkit-scrollbar {
1026
+ display: none;
1027
+ }
1028
+
1029
+ .looma-editor__mobile-toolbar-shell > *,
1030
+ .looma-editor__mobile-toolbar-shell button,
1031
+ .looma-editor__mobile-toolbar-shell [data-component-root~="ui-icon-button"] {
1032
+ flex: 0 0 auto;
1033
+ scroll-snap-align: start;
1034
+ }
1035
+
1036
+ .looma-editor__mobile-toolbar-shell [data-component-root~="ui-editor-toolbar"][floating] {
1037
+ width: 100%;
1038
+ max-width: none;
1039
+ min-height: 100%;
1040
+ padding: 0;
1041
+ overflow-x: auto;
1042
+ overflow-y: hidden;
1043
+ overscroll-behavior-inline: contain;
1044
+ -webkit-overflow-scrolling: touch;
1045
+ scroll-snap-type: x mandatory;
1046
+ scrollbar-width: none;
1047
+ background: transparent;
1048
+ border: 0;
1049
+ border-radius: 0;
1050
+ box-shadow: none;
1051
+ backdrop-filter: none;
1052
+ }
1053
+
1054
+ .looma-editor__mobile-toolbar-shell [data-component-root~="ui-editor-toolbar"][floating]::-webkit-scrollbar {
1055
+ display: none;
1056
+ }
1057
+
1058
+ .looma-editor__mobile-toolbar-shell .looma-editor__toolbar-button {
1059
+ --ui-icon-button-size-sm: var(--ui-editor-toolbar-mobile-button-size, 44px);
1060
+ }
1061
+
1062
+ .looma-editor__mobile-toolbar-back {
1063
+ display: inline-flex;
1064
+ align-items: center;
1065
+ justify-content: center;
1066
+ gap: var(--ui-space-1-5, 6px);
1067
+ min-width: 44px;
1068
+ min-height: 44px;
1069
+ padding: 0 var(--ui-space-3, 12px);
1070
+ border: 0;
1071
+ border-radius: var(--ui-radius-md, 6px);
1072
+ background: transparent;
1073
+ color: var(--ui-text-secondary, #4b5563);
1074
+ cursor: pointer;
1075
+ font: inherit;
1076
+ white-space: nowrap;
1077
+ }
1078
+
1079
+ .looma-editor__mobile-toolbar-back .looma-icon {
1080
+ width: 1rem;
1081
+ height: 1rem;
1082
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
1083
+ }
1084
+
1085
+ .looma-editor__mobile-toolbar-back:is(:hover, :focus-visible) {
1086
+ background: var(--ui-surface-hover, #f3f4f6);
1087
+ color: var(--ui-text-primary, #111827);
1088
+ }
1089
+
1090
+ .looma-editor__mobile-toolbar-shell .ui-editor-table-toolbar {
1091
+ min-width: max-content;
1092
+ min-height: 100%;
1093
+ padding: 0;
1094
+ background: transparent;
1095
+ border: 0;
1096
+ border-radius: 0;
1097
+ box-shadow: none;
1098
+ backdrop-filter: none;
1099
+ }
1100
+
1101
+ .looma-editor__mobile-toolbar-shell .ui-editor-table-toolbar button {
1102
+ min-height: 44px;
1103
+ background: transparent;
1104
+ }
1105
+
1106
+ .looma-editor__mobile-toolbar-shell .ui-editor-table-toolbar button[data-active="true"],
1107
+ .looma-editor__mobile-toolbar-shell .ui-editor-table-toolbar button[data-selected="true"] {
1108
+ background: var(--ui-accent-soft, var(--ui-accent-subtle, #e8f0fb));
1109
+ }
1110
+
1111
+ .looma-editor__mobile-toolbar-shell .ui-editor-table-toolbar__menu {
1112
+ top: auto;
1113
+ right: 0;
1114
+ bottom: calc(100% + var(--ui-space-2, 8px));
1115
+ max-height: min(50dvh, 22rem);
1116
+ overflow-y: auto;
1117
+ overscroll-behavior: contain;
1118
+ }
1119
+
1120
+ .looma-editor__table-overlay-shell {
1121
+ z-index: var(--ui-editor-overlay-z-index, 299);
1122
+ overflow: visible;
1123
+ pointer-events: none;
1124
+ }
1125
+
1126
+ /* Slash menu */
1127
+ [data-component-root~="ui-editor-slash-menu"] {
1128
+ user-select: none;
1129
+ }
1130
+
1131
+ /* Mention menu */
1132
+ [data-component-root~="ui-editor-mention-menu"] {
1133
+ user-select: none;
1134
+ }
1135
+
1136
+ .ui-editor-mention-menu {
1137
+ display: flex;
1138
+ overflow: hidden;
1139
+ flex-direction: column;
1140
+ background: var(--ui-surface, #fff);
1141
+ border: 1px solid var(--ui-border, #e5e7eb);
1142
+ border-radius: var(--ui-radius-xl, 1rem);
1143
+ box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));
1144
+ }
1145
+
1146
+ .ui-editor-mention-menu__header {
1147
+ display: flex;
1148
+ align-items: center;
1149
+ justify-content: space-between;
1150
+ gap: var(--ui-space-3, 12px);
1151
+ padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
1152
+ color: var(--ui-text-secondary, #4b5563);
1153
+ border-bottom: 1px solid var(--ui-border, #e5e7eb);
1154
+ font-size: var(--ui-font-size-xs, 0.75rem);
1155
+ font-weight: var(--ui-font-semibold, 600);
1156
+ }
1157
+
1158
+ .ui-editor-mention-menu__hint {
1159
+ overflow: hidden;
1160
+ color: var(--ui-text-muted, #6b7280);
1161
+ font-weight: var(--ui-font-normal, 400);
1162
+ text-overflow: ellipsis;
1163
+ white-space: nowrap;
1164
+ }
1165
+
1166
+ .ui-editor-mention-menu__list {
1167
+ max-height: 280px;
1168
+ padding: var(--ui-space-1, 4px) 0;
1169
+ margin: 0;
1170
+ overflow-y: auto;
1171
+ overscroll-behavior: contain;
1172
+ list-style: none;
1173
+ }
1174
+
1175
+ .ui-editor-mention-menu__item {
1176
+ display: flex;
1177
+ align-items: center;
1178
+ min-height: 44px;
1179
+ padding: var(--ui-space-1-5, 6px) var(--ui-space-3, 12px);
1180
+ gap: var(--ui-space-3, 12px);
1181
+ cursor: pointer;
1182
+ }
1183
+
1184
+ .ui-editor-mention-menu__item--active {
1185
+ background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));
1186
+ }
1187
+
1188
+ .ui-editor-mention-menu__avatar {
1189
+ display: inline-flex;
1190
+ align-items: center;
1191
+ justify-content: center;
1192
+ width: 32px;
1193
+ height: 32px;
1194
+ flex: 0 0 auto;
1195
+ color: var(--ui-accent-active, var(--ui-accent-solid, #2563eb));
1196
+ background: var(--ui-accent-soft, var(--ui-accent-subtle, #eff6ff));
1197
+ border-radius: 999px;
1198
+ font-size: var(--ui-font-size-xs, 0.75rem);
1199
+ font-weight: var(--ui-font-semibold, 600);
1200
+ }
1201
+
1202
+ .ui-editor-mention-menu__body {
1203
+ display: flex;
1204
+ min-width: 0;
1205
+ flex-direction: column;
1206
+ }
1207
+
1208
+ .ui-editor-mention-menu__label,
1209
+ .ui-editor-mention-menu__detail {
1210
+ overflow: hidden;
1211
+ text-overflow: ellipsis;
1212
+ white-space: nowrap;
1213
+ }
1214
+
1215
+ .ui-editor-mention-menu__label {
1216
+ color: var(--ui-text-primary, #111827);
1217
+ font-size: var(--ui-font-size-sm, 0.875rem);
1218
+ font-weight: var(--ui-font-medium, 500);
1219
+ }
1220
+
1221
+ .ui-editor-mention-menu__detail,
1222
+ .ui-editor-mention-menu__loading {
1223
+ color: var(--ui-text-muted, #6b7280);
1224
+ font-size: var(--ui-font-size-xs, 0.75rem);
1225
+ }
1226
+
1227
+ .ui-editor-mention-menu__loading {
1228
+ min-height: 44px;
1229
+ padding: var(--ui-space-3, 12px);
1230
+ }
1231
+
1232
+ .looma-editor .ProseMirror .looma-mention {
1233
+ padding: 0.08em 0.28em;
1234
+ color: var(--ui-editor-mention-color, var(--ui-accent-active, var(--ui-accent-solid)));
1235
+ background: var(--ui-editor-mention-bg, var(--ui-accent-soft, var(--ui-accent-subtle)));
1236
+ border-radius: var(--ui-radius-sm, 4px);
1237
+ font-weight: var(--ui-font-medium, 500);
1238
+ white-space: nowrap;
1239
+ }
1240
+
1241
+ @media (max-width: 767px) {
1242
+ .ui-editor-mention-menu {
1243
+ border-bottom: 0;
1244
+ border-radius: var(--ui-radius-xl, 1rem) var(--ui-radius-xl, 1rem) 0 0;
1245
+ }
1246
+
1247
+ .ui-editor-mention-menu__list {
1248
+ max-height: calc(60dvh - 48px);
1249
+ }
1250
+ }
1251
+
1252
+ /* Toolbar shell */
1253
+ [data-component-root~="ui-editor-toolbar"] {
1254
+ position: sticky;
1255
+ top: 0;
1256
+ z-index: var(--ui-editor-toolbar-z-index, 10);
1257
+ display: flex;
1258
+ align-items: center;
1259
+ justify-content: flex-start;
1260
+ gap: var(--ui-editor-toolbar-gap, 2px);
1261
+ padding:
1262
+ var(--ui-editor-toolbar-padding-block, 6px)
1263
+ var(--ui-editor-toolbar-padding-inline, 12px);
1264
+ min-height: var(--ui-editor-toolbar-min-height, 48px);
1265
+ overflow-x: auto;
1266
+ -webkit-overflow-scrolling: touch;
1267
+ scrollbar-width: none;
1268
+ white-space: nowrap;
1269
+ background: var(--ui-editor-toolbar-bg, var(--ui-surface, #fff));
1270
+ border-bottom: 1px solid var(--ui-editor-toolbar-border, var(--ui-border, #e5e7eb));
1271
+ }
1272
+
1273
+ [data-component-root~="ui-editor-toolbar"] > * {
1274
+ flex: 0 0 auto;
1275
+ }
1276
+
1277
+ [data-component-root~="ui-editor-toolbar"]::-webkit-scrollbar {
1278
+ display: none;
1279
+ }
1280
+
1281
+ [data-component-root~="ui-editor-toolbar"][floating] {
1282
+ position: static;
1283
+ top: auto;
1284
+ width: max-content;
1285
+ max-width: min(calc(100vw - 24px), 100%);
1286
+ min-height: auto;
1287
+ padding: var(--ui-editor-toolbar-floating-padding, 4px);
1288
+ overflow-x: visible;
1289
+ background: color-mix(in srgb, var(--ui-editor-toolbar-bg, var(--ui-surface, #fff)) 96%, transparent);
1290
+ border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border, #e5e7eb));
1291
+ border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg, 10px));
1292
+ box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));
1293
+ backdrop-filter: blur(10px);
1294
+ }
1295
+
1296
+ @media (max-width: 767px) {
1297
+ [data-component-root~="ui-editor-toolbar"] {
1298
+ position: fixed;
1299
+ top: auto;
1300
+ bottom: env(safe-area-inset-bottom);
1301
+ left: 0;
1302
+ right: 0;
1303
+ min-height: var(--ui-editor-toolbar-mobile-min-height, 56px);
1304
+ border-top: 1px solid var(--ui-editor-toolbar-border, var(--ui-border, #e5e7eb));
1305
+ border-bottom: none;
1306
+ box-shadow: var(--ui-editor-toolbar-mobile-shadow, 0 -2px 8px rgb(0 0 0 / 0.06));
1307
+ }
1308
+
1309
+ [data-component-root~="ui-editor-toolbar"][floating] {
1310
+ position: static;
1311
+ inset: auto;
1312
+ min-height: auto;
1313
+ border: 1px solid var(--ui-editor-toolbar-border, var(--ui-border, #e5e7eb));
1314
+ border-radius: var(--ui-editor-toolbar-floating-radius, var(--ui-radius-lg, 10px));
1315
+ box-shadow: var(--ui-editor-toolbar-floating-shadow, var(--ui-shadow-lg, 0 10px 24px rgb(0 0 0 / 0.12)));
1316
+ }
1317
+ }
1318
+
1319
+ .ui-editor-toolbar__divider {
1320
+ width: 1px;
1321
+ height: 20px;
1322
+ background: var(--ui-editor-toolbar-divider, var(--ui-border, #e5e7eb));
1323
+ flex-shrink: 0;
1324
+ margin: 0 var(--ui-editor-toolbar-divider-margin, 4px);
1325
+ }
1326
+
1327
+ .ui-editor-slash-menu {
1328
+ background: var(--ui-surface, #fff);
1329
+ border: 1px solid var(--ui-border, #e5e7eb);
1330
+ border-radius: var(--ui-radius-xl, 1rem);
1331
+ box-shadow: var(--ui-shadow-lg, 0 8px 24px rgb(0 0 0 / 0.12));
1332
+ overflow: hidden;
1333
+ display: flex;
1334
+ flex-direction: column;
1335
+ }
1336
+
1337
+ @media (max-width: 767px) {
1338
+ .ui-editor-slash-menu {
1339
+ border-radius: var(--ui-radius-xl, 1rem) var(--ui-radius-xl, 1rem) 0 0;
1340
+ border-bottom: none;
1341
+ }
1342
+ }
1343
+
1344
+ .ui-editor-slash-menu__header {
1345
+ display: none;
1346
+ align-items: center;
1347
+ gap: var(--ui-space-2, 8px);
1348
+ padding: var(--ui-space-3, 12px) var(--ui-space-4, 16px);
1349
+ border-bottom: 1px solid var(--ui-border, #e5e7eb);
1350
+ font-size: var(--ui-font-size-xs, 0.75rem);
1351
+ color: var(--ui-text-muted, #6b7280);
1352
+ font-weight: var(--ui-font-semibold, 600);
1353
+ text-transform: uppercase;
1354
+ letter-spacing: 0.05em;
1355
+ }
1356
+
1357
+ @media (max-width: 767px) {
1358
+ .ui-editor-slash-menu__header {
1359
+ display: flex;
1360
+ }
1361
+ }
1362
+
1363
+ .ui-editor-slash-menu__header-query {
1364
+ background: var(--ui-surface-hover, #f3f4f6);
1365
+ border-radius: var(--ui-radius-sm, 4px);
1366
+ padding: 0.1em 0.4em;
1367
+ font-family: var(--ui-font-family-mono, ui-monospace, monospace);
1368
+ font-size: var(--ui-font-size-xs, 0.75rem);
1369
+ color: var(--ui-accent, #3b82f6);
1370
+ text-transform: none;
1371
+ letter-spacing: 0;
1372
+ }
1373
+
1374
+ .ui-editor-slash-menu__list {
1375
+ list-style: none;
1376
+ margin: 0;
1377
+ padding: var(--ui-space-1, 4px) 0;
1378
+ overflow-y: auto;
1379
+ max-height: 280px;
1380
+ overscroll-behavior: contain;
1381
+ }
1382
+
1383
+ @media (max-width: 767px) {
1384
+ .ui-editor-slash-menu__list {
1385
+ max-height: calc(60dvh - 80px);
1386
+ padding: var(--ui-space-1, 4px) 0 var(--ui-space-2, 8px);
1387
+ }
1388
+ }
1389
+
1390
+ .ui-editor-slash-menu__item {
1391
+ display: flex;
1392
+ align-items: center;
1393
+ gap: var(--ui-space-3, 12px);
1394
+ padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
1395
+ min-height: 44px;
1396
+ cursor: pointer;
1397
+ transition: background-color 120ms ease;
1398
+ }
1399
+
1400
+ .ui-editor-slash-menu__item--active {
1401
+ background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));
1402
+ }
1403
+
1404
+ .ui-editor-slash-menu__icon {
1405
+ display: flex;
1406
+ align-items: center;
1407
+ justify-content: center;
1408
+ width: 32px;
1409
+ height: 32px;
1410
+ background: var(--ui-surface-hover, #f3f4f6);
1411
+ border: 1px solid var(--ui-border, #e5e7eb);
1412
+ border-radius: var(--ui-radius-md, 6px);
1413
+ font-size: var(--ui-font-size-sm, 0.875rem);
1414
+ font-weight: var(--ui-font-bold, 700);
1415
+ color: var(--ui-text-secondary, #4b5563);
1416
+ font-family: var(--ui-font-family-mono, ui-monospace, monospace);
1417
+ flex-shrink: 0;
1418
+ line-height: 1;
1419
+ }
1420
+
1421
+ .ui-editor-slash-menu__item--active .ui-editor-slash-menu__icon {
1422
+ background: var(--ui-accent, #3b82f6);
1423
+ border-color: var(--ui-accent, #3b82f6);
1424
+ color: var(--ui-accent-contrast, #fff);
1425
+ }
1426
+
1427
+ .ui-editor-slash-menu__icon .looma-icon {
1428
+ width: 1rem;
1429
+ height: 1rem;
1430
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
1431
+ }
1432
+
1433
+ .ui-editor-slash-menu__body {
1434
+ display: flex;
1435
+ min-width: 0;
1436
+ flex-direction: column;
1437
+ gap: 1px;
1438
+ }
1439
+
1440
+ .ui-editor-slash-menu__title {
1441
+ font-size: var(--ui-font-size-sm, 0.875rem);
1442
+ font-weight: var(--ui-font-medium, 500);
1443
+ color: var(--ui-text, #111827);
1444
+ white-space: nowrap;
1445
+ overflow: hidden;
1446
+ text-overflow: ellipsis;
1447
+ }
1448
+
1449
+ .ui-editor-slash-menu__description {
1450
+ font-size: var(--ui-font-size-xs, 0.75rem);
1451
+ color: var(--ui-text-muted, #6b7280);
1452
+ white-space: nowrap;
1453
+ overflow: hidden;
1454
+ text-overflow: ellipsis;
1455
+ }
1456
+
1457
+ .ui-editor-slash-menu__footer {
1458
+ display: none;
1459
+ padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
1460
+ border-top: 1px solid var(--ui-border, #e5e7eb);
1461
+ font-size: var(--ui-font-size-xs, 0.75rem);
1462
+ color: var(--ui-text-muted, #6b7280);
1463
+ }
1464
+
1465
+ @media (min-width: 768px) {
1466
+ .ui-editor-slash-menu__footer {
1467
+ display: block;
1468
+ }
1469
+ }
1470
+
1471
+ .ui-editor-slash-menu kbd {
1472
+ display: inline-flex;
1473
+ align-items: center;
1474
+ justify-content: center;
1475
+ font-family: var(--ui-font-family-mono, ui-monospace, monospace);
1476
+ font-size: 10px;
1477
+ background: var(--ui-surface-hover, #f3f4f6);
1478
+ border: 1px solid var(--ui-border, #e5e7eb);
1479
+ border-radius: 3px;
1480
+ padding: 0 3px;
1481
+ color: var(--ui-text-secondary, #4b5563);
1482
+ }
1483
+
1484
+ /* Table context menu */
1485
+ .ui-editor-table-context-menu {
1486
+ min-width: 14rem;
1487
+ max-width: min(17rem, calc(100vw - 24px));
1488
+ max-height: min(28rem, calc(100vh - 24px));
1489
+ padding: var(--ui-space-1-5, 6px);
1490
+ background: var(--ui-surface, #fff);
1491
+ border: 1px solid var(--ui-border, #e5e7eb);
1492
+ border-radius: var(--ui-radius-lg, 10px);
1493
+ box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));
1494
+ display: flex;
1495
+ flex-direction: column;
1496
+ gap: 2px;
1497
+ overflow-y: auto;
1498
+ overscroll-behavior: contain;
1499
+ scrollbar-width: thin;
1500
+ }
1501
+
1502
+ .ui-editor-table-context-menu__section {
1503
+ display: flex;
1504
+ flex-direction: column;
1505
+ gap: 3px;
1506
+ }
1507
+
1508
+ .ui-editor-table-context-menu button {
1509
+ display: flex;
1510
+ align-items: center;
1511
+ gap: var(--ui-space-2, 8px);
1512
+ width: 100%;
1513
+ text-align: left;
1514
+ min-height: 32px;
1515
+ padding: var(--ui-space-1-5, 6px) var(--ui-space-2, 8px);
1516
+ border: none;
1517
+ border-radius: var(--ui-radius-sm, 4px);
1518
+ background: none;
1519
+ font-size: var(--ui-font-size-sm, 0.875rem);
1520
+ cursor: pointer;
1521
+ color: var(--ui-text, #111);
1522
+ }
1523
+
1524
+ .ui-editor-table-context-menu button > .looma-icon {
1525
+ width: 1rem;
1526
+ height: 1rem;
1527
+ flex: 0 0 auto;
1528
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
1529
+ }
1530
+
1531
+ .ui-editor-table-context-menu button:hover:not(:disabled) {
1532
+ background: var(--ui-surface-hover, #f3f4f6);
1533
+ }
1534
+
1535
+ .ui-editor-table-context-menu button[data-selected="true"] {
1536
+ background: var(--ui-accent-subtle, rgb(59 130 246 / 0.1));
1537
+ }
1538
+
1539
+ .ui-editor-table-context-menu button[data-tone="danger"] {
1540
+ color: var(--ui-danger, #dc2626);
1541
+ }
1542
+
1543
+ .ui-editor-table-context-menu__swatches {
1544
+ display: grid;
1545
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1546
+ gap: 3px;
1547
+ }
1548
+
1549
+ .ui-editor-table-context-menu__swatch-button {
1550
+ display: inline-flex;
1551
+ align-items: center;
1552
+ gap: var(--ui-space-2, 8px);
1553
+ }
1554
+
1555
+ .ui-editor-table-context-menu__swatch {
1556
+ display: inline-flex;
1557
+ width: 1rem;
1558
+ height: 1rem;
1559
+ border-radius: 999px;
1560
+ border: 1px solid var(--ui-border, #d1d5db);
1561
+ background: var(--ui-editor-table-context-swatch, #fff);
1562
+ box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.35);
1563
+ flex-shrink: 0;
1564
+ }
1565
+
1566
+ .ui-editor-table-context-menu__swatch--default {
1567
+ position: relative;
1568
+ background:
1569
+ linear-gradient(
1570
+ 135deg,
1571
+ transparent calc(50% - 1px),
1572
+ var(--ui-text-muted, #6b7280) calc(50% - 1px),
1573
+ var(--ui-text-muted, #6b7280) calc(50% + 1px),
1574
+ transparent calc(50% + 1px)
1575
+ ),
1576
+ var(--ui-surface, #fff);
1577
+ }
1578
+
1579
+ .ui-editor-table-context-menu__swatch-label {
1580
+ min-width: 0;
1581
+ white-space: nowrap;
1582
+ }
1583
+
1584
+ .ui-editor-table-context-menu__heading {
1585
+ padding: var(--ui-space-1, 4px) var(--ui-space-2, 8px);
1586
+ font-size: 0.6875rem;
1587
+ font-weight: 700;
1588
+ letter-spacing: 0.05em;
1589
+ text-transform: uppercase;
1590
+ color: var(--ui-text-muted, #6b7280);
1591
+ }
1592
+
1593
+ .ui-editor-table-context-menu__sep {
1594
+ height: 1px;
1595
+ background: var(--ui-border, #e5e7eb);
1596
+ margin: var(--ui-space-1, 4px) 0;
1597
+ }
1598
+
1599
+ /* Table toolbar */
1600
+ .ui-editor-table-toolbar {
1601
+ display: inline-flex;
1602
+ align-items: center;
1603
+ gap: var(--ui-space-1, 4px);
1604
+ padding: var(--ui-space-1, 4px);
1605
+ background: color-mix(in srgb, var(--ui-surface, #fff) 94%, transparent);
1606
+ border: 1px solid var(--ui-border, #e5e7eb);
1607
+ border-radius: calc(var(--ui-radius-md, 6px) + 2px);
1608
+ box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));
1609
+ backdrop-filter: blur(10px);
1610
+ }
1611
+
1612
+ .ui-editor-table-toolbar__group {
1613
+ display: inline-flex;
1614
+ align-items: center;
1615
+ gap: 2px;
1616
+ overflow: hidden;
1617
+ }
1618
+
1619
+ .ui-editor-table-toolbar__sep {
1620
+ width: 1px;
1621
+ align-self: stretch;
1622
+ background: var(--ui-border, #e5e7eb);
1623
+ }
1624
+
1625
+ .ui-editor-table-toolbar__overflow {
1626
+ position: relative;
1627
+ }
1628
+
1629
+ .ui-editor-table-toolbar button {
1630
+ display: inline-flex;
1631
+ align-items: center;
1632
+ justify-content: center;
1633
+ gap: var(--ui-space-1-5, 6px);
1634
+ min-height: 32px;
1635
+ border: 0;
1636
+ border-radius: var(--ui-radius-sm, 4px);
1637
+ background: transparent;
1638
+ color: var(--ui-text-primary, #111827);
1639
+ cursor: pointer;
1640
+ font-size: var(--ui-text-sm, 0.875rem);
1641
+ font-weight: 500;
1642
+ line-height: 1;
1643
+ padding: var(--ui-space-1-5, 6px) var(--ui-space-2, 8px);
1644
+ white-space: nowrap;
1645
+ }
1646
+
1647
+ .ui-editor-table-toolbar button:hover {
1648
+ background: var(--ui-surface-hover, #f3f4f6);
1649
+ }
1650
+
1651
+ .ui-editor-table-toolbar button[data-active="true"] {
1652
+ background: var(--ui-accent-soft, var(--ui-accent-subtle, #e8f0fb));
1653
+ color: var(--ui-accent-active, #003d7a);
1654
+ }
1655
+
1656
+ .ui-editor-table-toolbar__group button {
1657
+ border-radius: var(--ui-radius-sm, 4px);
1658
+ }
1659
+
1660
+ .ui-editor-table-toolbar__group button + button {
1661
+ border-left: 0;
1662
+ }
1663
+
1664
+ .ui-editor-table-toolbar__more {
1665
+ border: 0 !important;
1666
+ border-radius: var(--ui-radius-sm, 4px) !important;
1667
+ }
1668
+
1669
+ .ui-editor-table-toolbar button[data-tone="danger"] {
1670
+ color: var(--ui-danger, #dc2626);
1671
+ }
1672
+
1673
+ .ui-editor-table-toolbar .looma-icon {
1674
+ width: var(--ui-editor-toolbar-icon-size, 1rem);
1675
+ height: var(--ui-editor-toolbar-icon-size, 1rem);
1676
+ flex: 0 0 auto;
1677
+ stroke-width: var(--ui-editor-toolbar-icon-stroke-width, 1.75);
1678
+ }
1679
+
1680
+ .ui-editor-table-toolbar .looma-icon--chevron {
1681
+ width: 0.875rem;
1682
+ height: 0.875rem;
1683
+ }
1684
+
1685
+ .ui-editor-table-toolbar__icon-button {
1686
+ width: 32px;
1687
+ padding-inline: 0 !important;
1688
+ }
1689
+
1690
+ .ui-editor-table-toolbar__menu {
1691
+ position: absolute;
1692
+ top: calc(100% + var(--ui-space-2, 8px));
1693
+ right: 0;
1694
+ min-width: 12rem;
1695
+ padding: var(--ui-space-1, 4px);
1696
+ background: var(--ui-surface, #fff);
1697
+ border: 1px solid var(--ui-border, #e5e7eb);
1698
+ border-radius: var(--ui-radius-md, 6px);
1699
+ box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));
1700
+ display: flex;
1701
+ flex-direction: column;
1702
+ gap: 2px;
1703
+ z-index: 2;
1704
+ }
1705
+
1706
+ .ui-editor-table-toolbar__menu-section + .ui-editor-table-toolbar__menu-section {
1707
+ margin-top: var(--ui-space-1, 4px);
1708
+ padding-top: var(--ui-space-1, 4px);
1709
+ border-top: 1px solid color-mix(in srgb, var(--ui-border, #e5e7eb) 80%, transparent);
1710
+ }
1711
+
1712
+ .ui-editor-table-toolbar__menu-heading {
1713
+ padding: var(--ui-space-1, 4px) var(--ui-space-2, 8px);
1714
+ font-size: 0.6875rem;
1715
+ font-weight: 700;
1716
+ letter-spacing: 0.05em;
1717
+ text-transform: uppercase;
1718
+ color: var(--ui-text-muted, #6b7280);
1719
+ }
1720
+
1721
+ .ui-editor-table-toolbar__menu button {
1722
+ display: flex;
1723
+ justify-content: flex-start;
1724
+ width: 100%;
1725
+ text-align: left;
1726
+ }
1727
+
1728
+ .ui-editor-table-toolbar__swatches {
1729
+ display: grid;
1730
+ grid-template-columns: repeat(3, minmax(0, 1fr));
1731
+ gap: 2px;
1732
+ }
1733
+
1734
+ .ui-editor-table-toolbar__swatch-button {
1735
+ gap: var(--ui-space-1, 4px);
1736
+ justify-content: flex-start !important;
1737
+ }
1738
+
1739
+ .ui-editor-table-toolbar__swatch {
1740
+ width: 14px;
1741
+ height: 14px;
1742
+ flex: 0 0 14px;
1743
+ border: 1px solid color-mix(in srgb, var(--ui-border, #e5e7eb) 80%, #000);
1744
+ border-radius: 3px;
1745
+ background: var(--ui-editor-table-toolbar-swatch);
1746
+ }
1747
+
1748
+ .ui-editor-table-toolbar__swatch--default {
1749
+ background:
1750
+ linear-gradient(135deg, transparent 44%, var(--ui-danger, #dc2626) 46% 54%, transparent 56%),
1751
+ var(--ui-surface, #fff);
1752
+ }
1753
+
1754
+ .ui-editor-table-toolbar__swatch-button[data-selected="true"] {
1755
+ background: var(--ui-accent-soft, var(--ui-accent-subtle, #e8f0fb));
1756
+ }
1757
+
1758
+ /* Insert table grid */
1759
+ .ui-editor-insert-table-grid {
1760
+ padding: var(--ui-space-3, 12px);
1761
+ background: var(--ui-surface, #fff);
1762
+ border: 1px solid var(--ui-border, #e5e7eb);
1763
+ border-radius: var(--ui-radius-md, 6px);
1764
+ box-shadow: var(--ui-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));
1765
+ }
1766
+
1767
+ .ui-editor-insert-table-grid__hint {
1768
+ margin: 0 0 var(--ui-space-2, 8px);
1769
+ font-size: var(--ui-text-sm, 0.875rem);
1770
+ color: var(--ui-text-muted, #6b7280);
1771
+ }
1772
+
1773
+ .ui-editor-insert-table-grid__grid {
1774
+ display: grid;
1775
+ grid-template-columns: repeat(var(--ui-editor-table-grid-cols, 8), 1.25rem);
1776
+ grid-template-rows: repeat(var(--ui-editor-table-grid-rows, 8), 1.25rem);
1777
+ gap: 2px;
1778
+ margin-bottom: var(--ui-space-2, 8px);
1779
+ }
1780
+
1781
+ .ui-editor-insert-table-grid__cell {
1782
+ width: 1.25rem;
1783
+ height: 1.25rem;
1784
+ padding: 0;
1785
+ border: 1px solid var(--ui-border, #e5e7eb);
1786
+ border-radius: 2px;
1787
+ background: var(--ui-surface, #fff);
1788
+ cursor: pointer;
1789
+ }
1790
+
1791
+ .ui-editor-insert-table-grid__cell--selected {
1792
+ background: var(--ui-accent-solid, var(--ui-accent, #0066cc));
1793
+ border-color: var(--ui-accent-solid, var(--ui-accent, #0066cc));
1794
+ }
1795
+
1796
+ .ui-editor-insert-table-grid__header {
1797
+ display: block;
1798
+ margin-bottom: var(--ui-space-2, 8px);
1799
+ font-size: var(--ui-text-sm, 0.875rem);
1800
+ cursor: pointer;
1801
+ }
1802
+
1803
+ .ui-editor-insert-table-grid [data-insert-table] {
1804
+ width: 100%;
1805
+ padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
1806
+ border: 1px solid var(--ui-border, #e5e7eb);
1807
+ border-radius: var(--ui-radius-sm, 4px);
1808
+ background: var(--ui-accent-solid, var(--ui-accent, #0066cc));
1809
+ color: var(--ui-accent-contrast, #fff);
1810
+ font-size: var(--ui-text-sm, 0.875rem);
1811
+ cursor: pointer;
1812
+ }
1813
+
1814
+ .ui-editor-insert-table-grid [data-insert-table]:hover {
1815
+ filter: brightness(1.05);
1816
+ }
1817
+
1818
+ /* Table overlay controls */
1819
+ [data-component-root~="ui-editor-table-overlay"] {
1820
+ display: block;
1821
+ width: 100%;
1822
+ height: 100%;
1823
+ overflow: visible;
1824
+ pointer-events: none;
1825
+ }
1826
+
1827
+ .ui-editor-table-overlay {
1828
+ position: relative;
1829
+ width: 100%;
1830
+ height: 100%;
1831
+ overflow: visible;
1832
+ pointer-events: none;
1833
+ }
1834
+
1835
+ .ui-editor-table-overlay__rows,
1836
+ .ui-editor-table-overlay__cols {
1837
+ pointer-events: none;
1838
+ position: absolute;
1839
+ }
1840
+
1841
+ .ui-editor-table-overlay__rows {
1842
+ inset: 0;
1843
+ width: 100%;
1844
+ }
1845
+
1846
+ .ui-editor-table-overlay__cols {
1847
+ inset: 0;
1848
+ height: 100%;
1849
+ }
1850
+
1851
+ .ui-editor-table-overlay__control {
1852
+ position: absolute;
1853
+ z-index: 1;
1854
+ pointer-events: none;
1855
+ }
1856
+
1857
+ .ui-editor-table-overlay__handle {
1858
+ position: absolute;
1859
+ display: inline-flex;
1860
+ align-items: center;
1861
+ justify-content: center;
1862
+ width: 24px;
1863
+ height: 24px;
1864
+ padding: 0;
1865
+ border: 1px solid var(--ui-affordance-near-color, var(--ui-border-strong, #c8c8c4));
1866
+ border-radius: var(--ui-radius-round, 999px);
1867
+ background: color-mix(in srgb, var(--ui-surface-elevated, #fff) 96%, transparent);
1868
+ color: var(--ui-affordance-near-color, var(--ui-text-secondary, #5c5c5c));
1869
+ font: inherit;
1870
+ font-size: 16px;
1871
+ line-height: 1;
1872
+ box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));
1873
+ opacity: 0;
1874
+ scale: 0.72;
1875
+ transition:
1876
+ opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1877
+ scale var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1878
+ color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1879
+ background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
1880
+ border-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1881
+ pointer-events: auto;
1882
+ cursor: pointer;
1883
+ }
1884
+
1885
+ .ui-editor-table-overlay__handle > .looma-icon {
1886
+ width: 14px;
1887
+ height: 14px;
1888
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
1889
+ }
1890
+
1891
+ .ui-editor-table-overlay__handle[data-ui-proximity="near"],
1892
+ .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__handle,
1893
+ .ui-editor-table-overlay__handle:focus-visible {
1894
+ opacity: 1;
1895
+ scale: 1;
1896
+ }
1897
+
1898
+ .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__handle,
1899
+ .ui-editor-table-overlay__handle:focus-visible {
1900
+ border-color: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
1901
+ background: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
1902
+ color: var(--ui-text-on-accent, #fff);
1903
+ box-shadow: var(--ui-shadow-sm, 0 1px 3px rgb(0 0 0 / 0.1));
1904
+ }
1905
+
1906
+ .ui-editor-table-overlay__handle:focus-visible,
1907
+ .ui-editor-table-overlay__selector:focus-visible,
1908
+ .ui-editor-table-overlay__cell-menu:focus-visible {
1909
+ outline: 2px solid var(--ui-focus-ring, #5b55d6);
1910
+ outline-offset: 2px;
1911
+ }
1912
+
1913
+ .ui-editor-table-overlay__control--row {
1914
+ left: 0;
1915
+ width: 100%;
1916
+ height: 0;
1917
+ }
1918
+
1919
+ .ui-editor-table-overlay__control--row .ui-editor-table-overlay__handle {
1920
+ top: -12px;
1921
+ left: -30px;
1922
+ }
1923
+
1924
+ .ui-editor-table-overlay__control--col {
1925
+ top: 0;
1926
+ width: 0;
1927
+ height: 100%;
1928
+ }
1929
+
1930
+ .ui-editor-table-overlay__control--col .ui-editor-table-overlay__handle {
1931
+ top: -30px;
1932
+ left: -12px;
1933
+ }
1934
+
1935
+ .ui-editor-table-overlay__line {
1936
+ position: absolute;
1937
+ background: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
1938
+ opacity: 0;
1939
+ transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1940
+ }
1941
+
1942
+ .ui-editor-table-overlay__control--row .ui-editor-table-overlay__line {
1943
+ inset: -1px 0 auto;
1944
+ height: 2px;
1945
+ }
1946
+
1947
+ .ui-editor-table-overlay__control--col .ui-editor-table-overlay__line {
1948
+ inset: 0 auto 0 -1px;
1949
+ width: 2px;
1950
+ }
1951
+
1952
+ .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__line {
1953
+ opacity: 0.8;
1954
+ }
1955
+
1956
+ .ui-editor-table-overlay__guide {
1957
+ position: absolute;
1958
+ width: var(--ui-affordance-guide-size, 4px);
1959
+ height: var(--ui-affordance-guide-size, 4px);
1960
+ border-radius: var(--ui-radius-round, 999px);
1961
+ background: var(--ui-affordance-guide-color, var(--ui-border-strong, #c8c8c4));
1962
+ opacity: var(--ui-affordance-guide-opacity, 0.42);
1963
+ transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1964
+ }
1965
+
1966
+ .ui-editor-table-overlay__control--row .ui-editor-table-overlay__guide {
1967
+ left: -10px;
1968
+ top: -2px;
1969
+ }
1970
+
1971
+ .ui-editor-table-overlay__control--col .ui-editor-table-overlay__guide {
1972
+ left: -2px;
1973
+ top: -10px;
1974
+ }
1975
+
1976
+ .ui-editor-table-overlay__control:has(.ui-editor-table-overlay__handle[data-ui-proximity="near"]) .ui-editor-table-overlay__guide,
1977
+ .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__guide {
1978
+ opacity: 0;
1979
+ }
1980
+
1981
+ .ui-editor-table-overlay__tooltip {
1982
+ position: absolute;
1983
+ z-index: 2;
1984
+ top: calc(100% + 6px);
1985
+ left: 50%;
1986
+ width: max-content;
1987
+ max-width: 14rem;
1988
+ padding: var(--ui-space-1, 4px) var(--ui-space-2, 8px);
1989
+ border-radius: var(--ui-radius-1, 4px);
1990
+ background: var(--ui-text-primary, #1a1a1a);
1991
+ color: var(--ui-surface-elevated, #fff);
1992
+ font-size: var(--ui-font-size-xs, 0.75rem);
1993
+ font-weight: var(--ui-font-medium, 500);
1994
+ line-height: var(--ui-line-height-md, 1.4);
1995
+ opacity: 0;
1996
+ transform: translateX(-50%);
1997
+ transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
1998
+ pointer-events: none;
1999
+ }
2000
+
2001
+ .ui-editor-table-overlay__control--row .ui-editor-table-overlay__tooltip {
2002
+ top: 50%;
2003
+ left: auto;
2004
+ right: calc(100% + 8px);
2005
+ transform: translateY(-50%);
2006
+ }
2007
+
2008
+ .ui-editor-table-overlay__control[data-active="true"] .ui-editor-table-overlay__tooltip,
2009
+ .ui-editor-table-overlay__handle:focus-visible .ui-editor-table-overlay__tooltip {
2010
+ opacity: 1;
2011
+ }
2012
+
2013
+ .ui-editor-table-overlay__selector,
2014
+ .ui-editor-table-overlay__cell-menu {
2015
+ position: absolute;
2016
+ z-index: 2;
2017
+ display: inline-flex;
2018
+ align-items: center;
2019
+ justify-content: center;
2020
+ padding: 0;
2021
+ border: 1px solid transparent;
2022
+ background: transparent;
2023
+ color: var(--ui-text-secondary, #5c5c5c);
2024
+ box-shadow: none;
2025
+ pointer-events: auto;
2026
+ cursor: pointer;
2027
+ transition:
2028
+ color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
2029
+ background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
2030
+ border-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
2031
+ box-shadow var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
2032
+ }
2033
+
2034
+ .ui-editor-table-overlay__selector:hover,
2035
+ .ui-editor-table-overlay__cell-menu:hover {
2036
+ background: var(--ui-icon-button-hover-bg, var(--ui-surface-muted, #f3f4f6));
2037
+ color: var(--ui-icon-button-hover-color, var(--ui-text-primary, #1a1a1a));
2038
+ box-shadow: var(--ui-shadow-xs, 0 1px 2px rgb(0 0 0 / 0.05));
2039
+ }
2040
+
2041
+ .ui-editor-table-overlay__selector {
2042
+ border-radius: var(--ui-radius-round, 999px);
2043
+ }
2044
+
2045
+ .ui-editor-table-overlay__selector::before {
2046
+ content: "";
2047
+ position: absolute;
2048
+ inset: 50% auto auto 50%;
2049
+ border-radius: var(--ui-radius-round, 999px);
2050
+ background: var(--ui-affordance-guide-color, var(--ui-border-strong, #c8c8c4));
2051
+ opacity: var(--ui-affordance-guide-opacity, 0.42);
2052
+ transform: translate(-50%, -50%);
2053
+ transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
2054
+ pointer-events: none;
2055
+ }
2056
+
2057
+ .ui-editor-table-overlay__selector .looma-icon {
2058
+ display: block;
2059
+ width: 14px;
2060
+ height: 14px;
2061
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
2062
+ opacity: 0;
2063
+ transform: scale(0.72);
2064
+ transition:
2065
+ opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
2066
+ transform var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
2067
+ }
2068
+
2069
+ .ui-editor-table-overlay__selector:hover::before,
2070
+ .ui-editor-table-overlay__selector:focus-visible::before {
2071
+ opacity: 0;
2072
+ }
2073
+
2074
+ .ui-editor-table-overlay__selector:hover .looma-icon,
2075
+ .ui-editor-table-overlay__selector:focus-visible .looma-icon {
2076
+ opacity: 1;
2077
+ transform: scale(1);
2078
+ }
2079
+
2080
+ .ui-editor-table-overlay__selector--row {
2081
+ left: -9px;
2082
+ width: 18px;
2083
+ height: 32px;
2084
+ transform: translateY(-50%);
2085
+ }
2086
+
2087
+ .ui-editor-table-overlay__selector--row::before {
2088
+ width: 2px;
2089
+ height: 16px;
2090
+ }
2091
+
2092
+ .ui-editor-table-overlay__selector--column {
2093
+ top: -9px;
2094
+ width: 32px;
2095
+ height: 18px;
2096
+ transform: translateX(-50%);
2097
+ }
2098
+
2099
+ .ui-editor-table-overlay__selector--column::before {
2100
+ width: 16px;
2101
+ height: 2px;
2102
+ }
2103
+
2104
+ @media (hover: none), (pointer: coarse) {
2105
+ .ui-editor-table-overlay__selector::before {
2106
+ opacity: 0;
2107
+ }
2108
+
2109
+ .ui-editor-table-overlay__selector .looma-icon {
2110
+ opacity: 1;
2111
+ transform: none;
2112
+ }
2113
+ }
2114
+
2115
+ .ui-editor-table-overlay__cell-menu {
2116
+ width: 24px;
2117
+ height: 24px;
2118
+ border-radius: var(--ui-radius-1, 4px);
2119
+ background: color-mix(in srgb, var(--ui-surface-muted, #f3f4f6) 78%, transparent);
2120
+ }
2121
+
2122
+ .ui-editor-table-overlay__cell-menu .looma-icon {
2123
+ width: 15px;
2124
+ height: 15px;
2125
+ stroke-width: var(--ui-editor-table-affordance-icon-stroke-width, 2);
2126
+ }
2127
+
2128
+ .ProseMirror .tableWrapper {
2129
+ max-width: 100%;
2130
+ overflow-x: auto;
2131
+ overflow-y: visible;
2132
+ overscroll-behavior-inline: contain;
2133
+ -webkit-overflow-scrolling: touch;
2134
+ }
2135
+
2136
+ /* ProseMirror table (for when Looma editor content is rendered) */
2137
+ .ProseMirror:focus-visible {
2138
+ outline: none;
2139
+ box-shadow: none;
2140
+ }
2141
+
2142
+ .ProseMirror table {
2143
+ border-collapse: collapse;
2144
+ margin: 0;
2145
+ width: max-content !important;
2146
+ min-width: 100%;
2147
+ max-width: none !important;
2148
+ table-layout: fixed;
2149
+ }
2150
+
2151
+ .ProseMirror table.ProseMirror-selectednode,
2152
+ .ProseMirror .tableWrapper.ProseMirror-selectednode {
2153
+ outline: none;
2154
+ }
2155
+
2156
+ .ProseMirror th,
2157
+ .ProseMirror td {
2158
+ position: relative;
2159
+ border: 1px solid var(--ui-border, #e5e7eb);
2160
+ padding: var(--ui-space-2, 8px) var(--ui-space-3, 12px);
2161
+ vertical-align: top;
2162
+ min-width: var(--ui-editor-table-cell-min-width, 112px);
2163
+ text-align: left;
2164
+ overflow-wrap: anywhere;
2165
+ }
2166
+
2167
+ .ProseMirror :is(th, td) > p,
2168
+ .looma-editor .ProseMirror :is(th, td) > p {
2169
+ margin: 0;
2170
+ }
2171
+
2172
+ .ProseMirror :is(th, td) > p + p,
2173
+ .looma-editor .ProseMirror :is(th, td) > p + p {
2174
+ margin-top: var(--ui-editor-table-paragraph-gap, var(--ui-space-2, 8px));
2175
+ }
2176
+
2177
+ .ProseMirror th {
2178
+ font-weight: 600;
2179
+ background: var(--ui-surface-hover, #f3f4f6);
2180
+ }
2181
+
2182
+ .ProseMirror .selectedCell {
2183
+ background: var(--ui-accent-subtle, rgba(59, 130, 246, 0.1));
2184
+ }
2185
+
2186
+ .ProseMirror .column-resize-handle {
2187
+ position: absolute;
2188
+ z-index: 3;
2189
+ right: -5px;
2190
+ top: 0;
2191
+ bottom: 0;
2192
+ width: 10px;
2193
+ cursor: col-resize;
2194
+ background: transparent;
2195
+ touch-action: none;
2196
+ }
2197
+
2198
+ .ProseMirror .column-resize-handle::after {
2199
+ content: "";
2200
+ position: absolute;
2201
+ inset-block: 0;
2202
+ inset-inline-start: 4px;
2203
+ width: 2px;
2204
+ border-radius: var(--ui-radius-round, 999px);
2205
+ background: color-mix(in srgb, var(--ui-affordance-near-color, var(--ui-border-strong, #c8c8c4)) 72%, transparent);
2206
+ transition:
2207
+ width var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease),
2208
+ background-color var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
2209
+ }
2210
+
2211
+ .ProseMirror .column-resize-handle:hover::after,
2212
+ .ProseMirror.resize-cursor .column-resize-handle::after {
2213
+ width: 3px;
2214
+ background: var(--ui-affordance-direct-color, var(--ui-accent-solid, #5b55d6));
2215
+ }
2216
+
2217
+ .ProseMirror .column-resize-handle::before {
2218
+ content: "Drag to resize column";
2219
+ position: absolute;
2220
+ z-index: 4;
2221
+ top: 4px;
2222
+ left: calc(100% + 6px);
2223
+ width: max-content;
2224
+ padding: var(--ui-space-1, 4px) var(--ui-space-2, 8px);
2225
+ border-radius: var(--ui-radius-1, 4px);
2226
+ background: var(--ui-text-primary, #1a1a1a);
2227
+ color: var(--ui-surface-elevated, #fff);
2228
+ font-size: var(--ui-font-size-xs, 0.75rem);
2229
+ line-height: var(--ui-line-height-md, 1.4);
2230
+ opacity: 0;
2231
+ transform: none;
2232
+ transition: opacity var(--ui-affordance-motion, var(--ui-motion-fast, 120ms)) var(--ui-motion-ease, ease);
2233
+ pointer-events: none;
2234
+ }
2235
+
2236
+ .ProseMirror .column-resize-handle:hover::before {
2237
+ opacity: 1;
2238
+ }
2239
+ `;
2240
+
2241
+ // src/table-overlay.ts
2242
+ import {
2243
+ createProximityCoordinator,
2244
+ loomaIconMarkup
2245
+ } from "@threadlabs/looma/core";
2246
+ var DEFAULT_ROWS = 3;
2247
+ var DEFAULT_COLS = 3;
2248
+ function sameNumbers(left, right) {
2249
+ return left.length === right.length && left.every((value, index) => value === right[index]);
2250
+ }
2251
+ function sameActiveCell(left, right) {
2252
+ if (left === right) return true;
2253
+ if (!left || !right) return false;
2254
+ return left.left === right.left && left.top === right.top && left.width === right.width && left.height === right.height && left.rowIndex === right.rowIndex && left.columnIndex === right.columnIndex;
2255
+ }
2256
+ function sameGeometry(left, right) {
2257
+ if (left === right) return true;
2258
+ if (!left || !right) return false;
2259
+ return sameNumbers(left.rowBoundaries, right.rowBoundaries) && sameNumbers(left.columnBoundaries, right.columnBoundaries) && sameActiveCell(left.activeCell, right.activeCell) && sameActiveCell(left.hoveredCell ?? null, right.hoveredCell ?? null);
2260
+ }
2261
+ function mapTableCells(table) {
2262
+ const rows = Array.from(table.rows);
2263
+ const grid = [];
2264
+ const coordinates = /* @__PURE__ */ new Map();
2265
+ rows.forEach((row, rowIndex) => {
2266
+ grid[rowIndex] ??= [];
2267
+ let columnIndex = 0;
2268
+ for (const cell of Array.from(row.cells)) {
2269
+ while (grid[rowIndex]?.[columnIndex]) columnIndex += 1;
2270
+ coordinates.set(cell, { rowIndex, columnIndex });
2271
+ const rowSpan = cell.rowSpan === 0 ? rows.length - rowIndex : Math.max(1, cell.rowSpan);
2272
+ const columnSpan = Math.max(1, cell.colSpan);
2273
+ for (let rowOffset = 0; rowOffset < rowSpan; rowOffset += 1) {
2274
+ const gridRow = grid[rowIndex + rowOffset] ??= [];
2275
+ for (let columnOffset = 0; columnOffset < columnSpan; columnOffset += 1) {
2276
+ gridRow[columnIndex + columnOffset] = cell;
2277
+ }
2278
+ }
2279
+ columnIndex += columnSpan;
2280
+ }
2281
+ });
2282
+ return { grid, coordinates };
2283
+ }
2284
+ function resolveTableCellAt(table, rowIndex, columnIndex) {
2285
+ return mapTableCells(table).grid[rowIndex]?.[columnIndex] ?? null;
2286
+ }
2287
+ function uniqueSorted(values) {
2288
+ return values.sort((left, right) => left - right).filter((value, index, all) => index === 0 || Math.abs(value - (all[index - 1] ?? value)) >= 0.5).map((value) => Math.round(value * 100) / 100);
2289
+ }
2290
+ function measureTableOverlayGeometry(table, activeCell, hoveredCell = null) {
2291
+ const tableRect = table.getBoundingClientRect();
2292
+ const rows = Array.from(table.rows);
2293
+ const cells = rows.flatMap((row) => Array.from(row.cells));
2294
+ const { coordinates } = mapTableCells(table);
2295
+ const rowBoundaries = uniqueSorted(rows.flatMap((row) => {
2296
+ const rect = row.getBoundingClientRect();
2297
+ return [rect.top - tableRect.top, rect.bottom - tableRect.top];
2298
+ }));
2299
+ const columnBoundaries = uniqueSorted(cells.flatMap((cell) => {
2300
+ const rect = cell.getBoundingClientRect();
2301
+ return [rect.left - tableRect.left, rect.right - tableRect.left];
2302
+ }));
2303
+ if (!activeCell || !table.contains(activeCell)) {
2304
+ return {
2305
+ rowBoundaries,
2306
+ columnBoundaries,
2307
+ activeCell: null,
2308
+ hoveredCell: measureCellRect(table, hoveredCell, coordinates)
2309
+ };
2310
+ }
2311
+ return {
2312
+ rowBoundaries,
2313
+ columnBoundaries,
2314
+ activeCell: measureCellRect(table, activeCell, coordinates),
2315
+ hoveredCell: measureCellRect(table, hoveredCell, coordinates)
2316
+ };
2317
+ }
2318
+ function measureCellRect(table, cell, coordinates) {
2319
+ if (!cell || !table.contains(cell)) return null;
2320
+ const tableRect = table.getBoundingClientRect();
2321
+ const cellRect = cell.getBoundingClientRect();
2322
+ const coordinate = coordinates.get(cell);
2323
+ return {
2324
+ left: Math.round((cellRect.left - tableRect.left) * 100) / 100,
2325
+ top: Math.round((cellRect.top - tableRect.top) * 100) / 100,
2326
+ width: Math.round(cellRect.width * 100) / 100,
2327
+ height: Math.round(cellRect.height * 100) / 100,
2328
+ rowIndex: coordinate?.rowIndex ?? 0,
2329
+ columnIndex: coordinate?.columnIndex ?? 0
2330
+ };
2331
+ }
2332
+ function finiteNumbers(value) {
2333
+ if (!value) return [];
2334
+ const values = value.split(",").map((part) => Number(part.trim()));
2335
+ return values.every(Number.isFinite) ? values : [];
2336
+ }
2337
+ function fallbackBoundaries2(segments, length) {
2338
+ return Array.from({ length: segments + 1 }, (_, index) => index * length / segments);
2339
+ }
2340
+ if (typeof HTMLElement !== "undefined") {
2341
+ class UIEditorTableOverlayElement extends HTMLElement {
2342
+ static get observedAttributes() {
2343
+ return ["open", "rows", "cols", "row-boundaries", "column-boundaries", "active-cell", "hovered-cell"];
2344
+ }
2345
+ #rows = DEFAULT_ROWS;
2346
+ #cols = DEFAULT_COLS;
2347
+ #activeControlKey = null;
2348
+ #proximity = null;
2349
+ #geometry = null;
2350
+ #renderPending = false;
2351
+ get geometry() {
2352
+ return this.#geometry;
2353
+ }
2354
+ set geometry(value) {
2355
+ if (sameGeometry(this.#geometry, value)) return;
2356
+ this.#geometry = value;
2357
+ this.#scheduleRender();
2358
+ }
2359
+ connectedCallback() {
2360
+ this.#rows = this.#readBoundedNumber("rows", DEFAULT_ROWS);
2361
+ this.#cols = this.#readBoundedNumber("cols", DEFAULT_COLS);
2362
+ this.render();
2363
+ this.addEventListener("click", this.onClick);
2364
+ this.addEventListener("pointerover", this.onPointerOver);
2365
+ this.addEventListener("pointerout", this.onPointerOut);
2366
+ this.addEventListener("focusin", this.onFocusIn);
2367
+ this.addEventListener("focusout", this.onFocusOut);
2368
+ this.#proximity = createProximityCoordinator(this, {
2369
+ pointerTarget: this.ownerDocument,
2370
+ anchorSelector: ".ui-editor-table-overlay__handle[data-ui-affordance]"
2371
+ });
2372
+ }
2373
+ disconnectedCallback() {
2374
+ this.removeEventListener("click", this.onClick);
2375
+ this.removeEventListener("pointerover", this.onPointerOver);
2376
+ this.removeEventListener("pointerout", this.onPointerOut);
2377
+ this.removeEventListener("focusin", this.onFocusIn);
2378
+ this.removeEventListener("focusout", this.onFocusOut);
2379
+ this.#proximity?.destroy();
2380
+ this.#proximity = null;
2381
+ }
2382
+ attributeChangedCallback(name) {
2383
+ if (name === "rows") this.#rows = this.#readBoundedNumber("rows", DEFAULT_ROWS);
2384
+ if (name === "cols") this.#cols = this.#readBoundedNumber("cols", DEFAULT_COLS);
2385
+ this.#scheduleRender();
2386
+ }
2387
+ #scheduleRender() {
2388
+ if (!this.isConnected || this.#renderPending) return;
2389
+ this.#renderPending = true;
2390
+ queueMicrotask(() => {
2391
+ this.#renderPending = false;
2392
+ if (this.isConnected) this.render();
2393
+ });
2394
+ }
2395
+ #readBoundedNumber(name, fallback) {
2396
+ const parsed = Number.parseInt(this.getAttribute(name) ?? String(fallback), 10);
2397
+ return Number.isFinite(parsed) ? Math.min(100, Math.max(1, parsed)) : fallback;
2398
+ }
2399
+ #boundaries(name, segments) {
2400
+ if (this.#geometry) {
2401
+ return name === "row-boundaries" ? this.#geometry.rowBoundaries : this.#geometry.columnBoundaries;
2402
+ }
2403
+ const explicit = finiteNumbers(this.getAttribute(name));
2404
+ if (explicit.length === segments + 1) return explicit;
2405
+ const length = name === "row-boundaries" ? this.getBoundingClientRect().height : this.getBoundingClientRect().width;
2406
+ return fallbackBoundaries2(segments, length);
2407
+ }
2408
+ #activeCell() {
2409
+ if (this.#geometry) return this.#geometry.activeCell;
2410
+ const values = finiteNumbers(this.getAttribute("active-cell"));
2411
+ if (values.length !== 6) return null;
2412
+ const [left, top, width, height, rowIndex, columnIndex] = values;
2413
+ if (left === void 0 || top === void 0 || width === void 0 || height === void 0 || rowIndex === void 0 || columnIndex === void 0) return null;
2414
+ return { left, top, width, height, rowIndex, columnIndex };
2415
+ }
2416
+ #hoveredCell() {
2417
+ if (this.#geometry) return this.#geometry.hoveredCell ?? null;
2418
+ const values = finiteNumbers(this.getAttribute("hovered-cell"));
2419
+ if (values.length !== 6) return null;
2420
+ const [left, top, width, height, rowIndex, columnIndex] = values;
2421
+ if (left === void 0 || top === void 0 || width === void 0 || height === void 0 || rowIndex === void 0 || columnIndex === void 0) return null;
2422
+ return { left, top, width, height, rowIndex, columnIndex };
2423
+ }
2424
+ dispatch(detail) {
2425
+ this.dispatchEvent(new CustomEvent(
2426
+ "looma-editor-table-overlay-action",
2427
+ { detail, bubbles: true, composed: true }
2428
+ ));
2429
+ }
2430
+ onClick = (event) => {
2431
+ const target = event.target.closest("button[data-action]");
2432
+ if (!target) return;
2433
+ const action = target.dataset.action;
2434
+ if (!action) return;
2435
+ if (action === "select-row" || action === "select-column") {
2436
+ const rowIndex = Number.parseInt(target.dataset.rowIndex ?? "", 10);
2437
+ const columnIndex = Number.parseInt(target.dataset.columnIndex ?? "", 10);
2438
+ if (Number.isFinite(rowIndex) && Number.isFinite(columnIndex)) {
2439
+ this.dispatch({ action, rowIndex, columnIndex });
2440
+ }
2441
+ return;
2442
+ }
2443
+ if (action === "open-cell-menu") {
2444
+ const rowIndex = Number.parseInt(target.dataset.rowIndex ?? "", 10);
2445
+ const columnIndex = Number.parseInt(target.dataset.columnIndex ?? "", 10);
2446
+ if (!Number.isFinite(rowIndex) || !Number.isFinite(columnIndex)) return;
2447
+ const rect = target.getBoundingClientRect();
2448
+ this.dispatch({
2449
+ action,
2450
+ rowIndex,
2451
+ columnIndex,
2452
+ anchor: { left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom }
2453
+ });
2454
+ return;
2455
+ }
2456
+ const boundaryIndex = Number.parseInt(target.dataset.boundaryIndex ?? "", 10);
2457
+ if (!Number.isFinite(boundaryIndex) || boundaryIndex < 0) return;
2458
+ this.dispatch({ action, boundaryIndex });
2459
+ };
2460
+ onPointerOver = (event) => {
2461
+ const control = event.target.closest("[data-control-key]");
2462
+ this.#setActiveControl(control?.dataset.controlKey ?? null);
2463
+ };
2464
+ onPointerOut = (event) => {
2465
+ const related = event.relatedTarget;
2466
+ const next = related instanceof Element ? related.closest("[data-control-key]") : null;
2467
+ this.#setActiveControl(next?.dataset.controlKey ?? null);
2468
+ };
2469
+ onFocusIn = (event) => {
2470
+ const control = event.target.closest("[data-control-key]");
2471
+ this.#setActiveControl(control?.dataset.controlKey ?? null);
2472
+ };
2473
+ onFocusOut = (event) => {
2474
+ const related = event.relatedTarget;
2475
+ const next = related instanceof Element ? related.closest("[data-control-key]") : null;
2476
+ this.#setActiveControl(next?.dataset.controlKey ?? null);
2477
+ };
2478
+ #setActiveControl(controlKey) {
2479
+ if (this.#activeControlKey === controlKey) return;
2480
+ this.#activeControlKey = controlKey;
2481
+ this.#syncActiveControl();
2482
+ }
2483
+ #syncActiveControl() {
2484
+ this.querySelectorAll("[data-control-key]").forEach((control) => {
2485
+ control.dataset.active = this.#activeControlKey === control.dataset.controlKey ? "true" : "false";
2486
+ });
2487
+ }
2488
+ #insertionControl(axis, index, position) {
2489
+ const first = index === 0;
2490
+ const action = axis === "row" ? first ? "add-row-before" : "add-row-after" : first ? "add-column-before" : "add-column-after";
2491
+ const noun = axis === "row" ? "row" : "column";
2492
+ const relation = first ? axis === "row" ? "above" : "left" : axis === "row" ? "below" : "right";
2493
+ const label = `Insert ${noun} ${relation}`;
2494
+ const controlKey = `${axis}:${index}`;
2495
+ const positionStyle = axis === "row" ? `top:${position}px;` : `left:${position}px;`;
2496
+ return [
2497
+ `<div class="ui-editor-table-overlay__control ui-editor-table-overlay__control--${axis}"`,
2498
+ ` style="${positionStyle}" data-control-key="${controlKey}"`,
2499
+ ` data-active="${this.#activeControlKey === controlKey ? "true" : "false"}">`,
2500
+ '<span class="ui-editor-table-overlay__line" aria-hidden="true"></span>',
2501
+ '<span class="ui-editor-table-overlay__guide" data-ui-guide aria-hidden="true"></span>',
2502
+ `<button type="button" class="ui-editor-table-overlay__handle" data-ui-affordance="insert-${noun}"`,
2503
+ ` data-action="${action}" data-boundary-index="${index}" aria-label="${label}">`,
2504
+ loomaIconMarkup("plus"),
2505
+ `<span class="ui-editor-table-overlay__tooltip" role="tooltip">${label}</span>`,
2506
+ "</button>",
2507
+ "</div>"
2508
+ ].join("");
2509
+ }
2510
+ #cellSelectors(cell) {
2511
+ const centerX = cell.left + cell.width / 2;
2512
+ const centerY = cell.top + cell.height / 2;
2513
+ const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
2514
+ return [
2515
+ `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--row" style="top:${centerY}px" data-action="select-row" ${indexes} title="Select row" aria-label="Select row">${loomaIconMarkup("grip-vertical")}</button>`,
2516
+ `<button type="button" class="ui-editor-table-overlay__selector ui-editor-table-overlay__selector--column" style="left:${centerX}px" data-action="select-column" ${indexes} title="Select column" aria-label="Select column">${loomaIconMarkup("grip-horizontal")}</button>`
2517
+ ].join("");
2518
+ }
2519
+ #cellMenu(cell) {
2520
+ const indexes = `data-row-index="${cell.rowIndex}" data-column-index="${cell.columnIndex}"`;
2521
+ return `<button type="button" class="ui-editor-table-overlay__cell-menu" style="left:${cell.left + cell.width - 30}px;top:${cell.top + 6}px" data-action="open-cell-menu" ${indexes} title="Cell actions" aria-label="Cell actions">${loomaIconMarkup("chevron-down")}</button>`;
2522
+ }
2523
+ render() {
2524
+ const open = this.hasAttribute("open") && this.getAttribute("open") !== "false";
2525
+ this.hidden = !open;
2526
+ if (!open) {
2527
+ this.#setActiveControl(null);
2528
+ return;
2529
+ }
2530
+ const rows = this.#boundaries("row-boundaries", this.#rows);
2531
+ const columns = this.#boundaries("column-boundaries", this.#cols);
2532
+ const activeCell = this.#activeCell();
2533
+ const hoveredCell = this.#hoveredCell();
2534
+ this.innerHTML = [
2535
+ '<div class="ui-editor-table-overlay" aria-label="Table controls">',
2536
+ '<div class="ui-editor-table-overlay__rows">',
2537
+ rows.map((position, index) => this.#insertionControl("row", index, position)).join(""),
2538
+ "</div>",
2539
+ '<div class="ui-editor-table-overlay__cols">',
2540
+ columns.map((position, index) => this.#insertionControl("col", index, position)).join(""),
2541
+ "</div>",
2542
+ hoveredCell ? this.#cellSelectors(hoveredCell) : "",
2543
+ activeCell ? this.#cellMenu(activeCell) : "",
2544
+ "</div>"
2545
+ ].join("");
2546
+ this.#syncActiveControl();
2547
+ this.#proximity?.refresh();
2548
+ }
2549
+ }
2550
+ }
2551
+
2552
+ // src/ui.ts
2553
+ registerLoomaPackage("editor", records, styles);
2554
+
2555
+ export {
2556
+ resolveTableCellAt,
2557
+ measureTableOverlayGeometry
2558
+ };