@bettercms-ai/kit 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (947) hide show
  1. package/_virtual/_rolldown/runtime.js +13 -0
  2. package/adapters/icons.d.ts +15 -0
  3. package/adapters/icons.js +27 -0
  4. package/adapters/icons.js.map +1 -0
  5. package/adapters/lossy.d.ts +267 -0
  6. package/adapters/lossy.js +233 -0
  7. package/adapters/lossy.js.map +1 -0
  8. package/adapters/prod-types.d.ts +468 -0
  9. package/adapters/prod-types.js +646 -0
  10. package/adapters/prod-types.js.map +1 -0
  11. package/adapters/schema.d.ts +115 -0
  12. package/adapters/schema.js +2203 -0
  13. package/adapters/schema.js.map +1 -0
  14. package/adapters/values.d.ts +200 -0
  15. package/adapters/values.js +553 -0
  16. package/adapters/values.js.map +1 -0
  17. package/brand/logo.d.ts +17 -0
  18. package/brand/logo.js +9 -0
  19. package/brand/logo.js.map +1 -0
  20. package/context.d.ts +269 -0
  21. package/context.js +214 -0
  22. package/context.js.map +1 -0
  23. package/controls/button.d.ts +58 -0
  24. package/controls/button.js +507 -0
  25. package/controls/button.js.map +1 -0
  26. package/controls/c1.d.ts +11 -0
  27. package/controls/c1.js +24 -0
  28. package/controls/c1.js.map +1 -0
  29. package/controls/c2.d.ts +10 -0
  30. package/controls/c2.js +19 -0
  31. package/controls/c2.js.map +1 -0
  32. package/controls/choice.d.ts +39 -0
  33. package/controls/choice.js +410 -0
  34. package/controls/choice.js.map +1 -0
  35. package/controls/code-register.d.ts +1 -0
  36. package/controls/code-register.js +8 -0
  37. package/controls/code-register.js.map +1 -0
  38. package/controls/code.d.ts +42 -0
  39. package/controls/code.js +396 -0
  40. package/controls/code.js.map +1 -0
  41. package/controls/color.d.ts +5 -0
  42. package/controls/color.js +130 -0
  43. package/controls/color.js.map +1 -0
  44. package/controls/component-services.d.ts +114 -0
  45. package/controls/date-register.d.ts +1 -0
  46. package/controls/date-register.js +9 -0
  47. package/controls/date-register.js.map +1 -0
  48. package/controls/date-zone.d.ts +104 -0
  49. package/controls/date-zone.js +272 -0
  50. package/controls/date-zone.js.map +1 -0
  51. package/controls/date.d.ts +7 -0
  52. package/controls/date.js +458 -0
  53. package/controls/date.js.map +1 -0
  54. package/controls/form-picker-register.d.ts +1 -0
  55. package/controls/form-picker-register.js +19 -0
  56. package/controls/form-picker-register.js.map +1 -0
  57. package/controls/form-picker.d.ts +43 -0
  58. package/controls/form-picker.js +83 -0
  59. package/controls/form-picker.js.map +1 -0
  60. package/controls/icon-register.d.ts +1 -0
  61. package/controls/icon-register.js +8 -0
  62. package/controls/icon-register.js.map +1 -0
  63. package/controls/icon.d.ts +38 -0
  64. package/controls/icon.js +355 -0
  65. package/controls/icon.js.map +1 -0
  66. package/controls/index.d.ts +5 -0
  67. package/controls/index.js +37 -0
  68. package/controls/index.js.map +1 -0
  69. package/controls/json-register.d.ts +1 -0
  70. package/controls/json-register.js +8 -0
  71. package/controls/json-register.js.map +1 -0
  72. package/controls/json.d.ts +2 -0
  73. package/controls/json.js +72 -0
  74. package/controls/json.js.map +1 -0
  75. package/controls/link.d.ts +260 -0
  76. package/controls/link.js +1186 -0
  77. package/controls/link.js.map +1 -0
  78. package/controls/location-register.d.ts +1 -0
  79. package/controls/location-register.js +8 -0
  80. package/controls/location-register.js.map +1 -0
  81. package/controls/location.d.ts +16 -0
  82. package/controls/location.js +197 -0
  83. package/controls/location.js.map +1 -0
  84. package/controls/media-register.d.ts +1 -0
  85. package/controls/media-register.js +12 -0
  86. package/controls/media-register.js.map +1 -0
  87. package/controls/media-services.d.ts +40 -0
  88. package/controls/media.d.ts +73 -0
  89. package/controls/media.js +1076 -0
  90. package/controls/media.js.map +1 -0
  91. package/controls/number.d.ts +22 -0
  92. package/controls/number.js +195 -0
  93. package/controls/number.js.map +1 -0
  94. package/controls/reference-register.d.ts +1 -0
  95. package/controls/reference-register.js +10 -0
  96. package/controls/reference-register.js.map +1 -0
  97. package/controls/reference-services.d.ts +54 -0
  98. package/controls/reference.d.ts +23 -0
  99. package/controls/reference.js +761 -0
  100. package/controls/reference.js.map +1 -0
  101. package/controls/rich-text/blocks.d.ts +28 -0
  102. package/controls/rich-text/blocks.js +1532 -0
  103. package/controls/rich-text/blocks.js.map +1 -0
  104. package/controls/rich-text/catalog.d.ts +98 -0
  105. package/controls/rich-text/catalog.js +613 -0
  106. package/controls/rich-text/catalog.js.map +1 -0
  107. package/controls/rich-text/codec.d.ts +56 -0
  108. package/controls/rich-text/codec.js +32 -0
  109. package/controls/rich-text/codec.js.map +1 -0
  110. package/controls/rich-text/component-card.d.ts +14 -0
  111. package/controls/rich-text/component-card.js +706 -0
  112. package/controls/rich-text/component-card.js.map +1 -0
  113. package/controls/rich-text/control.d.ts +21 -0
  114. package/controls/rich-text/control.js +254 -0
  115. package/controls/rich-text/control.js.map +1 -0
  116. package/controls/rich-text/dom.d.ts +190 -0
  117. package/controls/rich-text/dom.js +690 -0
  118. package/controls/rich-text/dom.js.map +1 -0
  119. package/controls/rich-text/editor.d.ts +50 -0
  120. package/controls/rich-text/editor.js +1530 -0
  121. package/controls/rich-text/editor.js.map +1 -0
  122. package/controls/rich-text/floating.d.ts +23 -0
  123. package/controls/rich-text/floating.js +137 -0
  124. package/controls/rich-text/floating.js.map +1 -0
  125. package/controls/rich-text/index.d.ts +1 -0
  126. package/controls/rich-text/index.js +12 -0
  127. package/controls/rich-text/index.js.map +1 -0
  128. package/controls/rich-text/link-form.d.ts +13 -0
  129. package/controls/rich-text/link-form.js +111 -0
  130. package/controls/rich-text/link-form.js.map +1 -0
  131. package/controls/rich-text/markdown.d.ts +6 -0
  132. package/controls/rich-text/markdown.js +179 -0
  133. package/controls/rich-text/markdown.js.map +1 -0
  134. package/controls/rich-text/ops.d.ts +35 -0
  135. package/controls/rich-text/ops.js +314 -0
  136. package/controls/rich-text/ops.js.map +1 -0
  137. package/controls/rich-text/toolbar.d.ts +85 -0
  138. package/controls/rich-text/toolbar.js +338 -0
  139. package/controls/rich-text/toolbar.js.map +1 -0
  140. package/controls/scale.d.ts +56 -0
  141. package/controls/scale.js +563 -0
  142. package/controls/scale.js.map +1 -0
  143. package/controls/slot-register.d.ts +1 -0
  144. package/controls/slot-register.js +16 -0
  145. package/controls/slot-register.js.map +1 -0
  146. package/controls/slot-services.d.ts +97 -0
  147. package/controls/slot-services.js +38 -0
  148. package/controls/slot-services.js.map +1 -0
  149. package/controls/slot.d.ts +33 -0
  150. package/controls/slot.js +348 -0
  151. package/controls/slot.js.map +1 -0
  152. package/controls/table/index.d.ts +1 -0
  153. package/controls/table/index.js +12 -0
  154. package/controls/table/index.js.map +1 -0
  155. package/controls/table/prod.d.ts +21 -0
  156. package/controls/table/prod.js +79 -0
  157. package/controls/table/prod.js.map +1 -0
  158. package/controls/table/refs.d.ts +50 -0
  159. package/controls/table/refs.js +68 -0
  160. package/controls/table/refs.js.map +1 -0
  161. package/controls/table/stored.d.ts +15 -0
  162. package/controls/table/stored.js +44 -0
  163. package/controls/table/stored.js.map +1 -0
  164. package/controls/table/table-editor.d.ts +103 -0
  165. package/controls/table/table-editor.js +2722 -0
  166. package/controls/table/table-editor.js.map +1 -0
  167. package/controls/table/table-link.d.ts +24 -0
  168. package/controls/table/table-link.js +180 -0
  169. package/controls/table/table-link.js.map +1 -0
  170. package/controls/table/table.d.ts +9 -0
  171. package/controls/table/table.js +103 -0
  172. package/controls/table/table.js.map +1 -0
  173. package/controls/text.d.ts +17 -0
  174. package/controls/text.js +287 -0
  175. package/controls/text.js.map +1 -0
  176. package/engine/array.d.ts +101 -0
  177. package/engine/array.js +893 -0
  178. package/engine/array.js.map +1 -0
  179. package/engine/bits.d.ts +24 -0
  180. package/engine/bits.js +60 -0
  181. package/engine/bits.js.map +1 -0
  182. package/engine/breadcrumb.d.ts +45 -0
  183. package/engine/breadcrumb.js +87 -0
  184. package/engine/breadcrumb.js.map +1 -0
  185. package/engine/expand.d.ts +68 -0
  186. package/engine/expand.js +170 -0
  187. package/engine/expand.js.map +1 -0
  188. package/engine/field-list.d.ts +20 -0
  189. package/engine/field-list.js +19 -0
  190. package/engine/field-list.js.map +1 -0
  191. package/engine/field-shell.d.ts +49 -0
  192. package/engine/field-shell.js +860 -0
  193. package/engine/field-shell.js.map +1 -0
  194. package/engine/frame.d.ts +120 -0
  195. package/engine/frame.js +599 -0
  196. package/engine/frame.js.map +1 -0
  197. package/engine/group-summary.d.ts +4 -0
  198. package/engine/group-summary.js +66 -0
  199. package/engine/group-summary.js.map +1 -0
  200. package/engine/grouping.d.ts +224 -0
  201. package/engine/grouping.js +824 -0
  202. package/engine/grouping.js.map +1 -0
  203. package/engine/item-list.d.ts +89 -0
  204. package/engine/item-list.js +703 -0
  205. package/engine/item-list.js.map +1 -0
  206. package/engine/kit-field.d.ts +72 -0
  207. package/engine/kit-field.js +523 -0
  208. package/engine/kit-field.js.map +1 -0
  209. package/engine/schema-form.d.ts +91 -0
  210. package/engine/schema-form.js +320 -0
  211. package/engine/schema-form.js.map +1 -0
  212. package/engine/slot.d.ts +13 -0
  213. package/engine/slot.js +226 -0
  214. package/engine/slot.js.map +1 -0
  215. package/index.d.ts +46 -0
  216. package/index.js +55 -0
  217. package/index.js.map +1 -0
  218. package/kit.css +56 -0
  219. package/lib/cn.d.ts +4 -0
  220. package/lib/cn.js +53 -0
  221. package/lib/cn.js.map +1 -0
  222. package/lib/columns.d.ts +14 -0
  223. package/lib/columns.js +27 -0
  224. package/lib/columns.js.map +1 -0
  225. package/lib/frames.d.ts +36 -0
  226. package/lib/frames.js +214 -0
  227. package/lib/frames.js.map +1 -0
  228. package/lib/icons.d.ts +16 -0
  229. package/lib/icons.js +172 -0
  230. package/lib/icons.js.map +1 -0
  231. package/lib/path.d.ts +29 -0
  232. package/lib/path.js +64 -0
  233. package/lib/path.js.map +1 -0
  234. package/lib/schema.d.ts +49 -0
  235. package/lib/schema.js +287 -0
  236. package/lib/schema.js.map +1 -0
  237. package/lib/utils.d.ts +7 -0
  238. package/lib/utils.js +37 -0
  239. package/lib/utils.js.map +1 -0
  240. package/lib/validate.d.ts +20 -0
  241. package/lib/validate.js +150 -0
  242. package/lib/validate.js.map +1 -0
  243. package/package.json +31 -59
  244. package/schema/adapters.d.ts +28 -0
  245. package/schema/adapters.js +493 -0
  246. package/schema/adapters.js.map +1 -0
  247. package/schema/help.d.ts +25 -0
  248. package/schema/help.js +54 -0
  249. package/schema/help.js.map +1 -0
  250. package/schema/scale.d.ts +69 -0
  251. package/schema/scale.js +250 -0
  252. package/schema/scale.js.map +1 -0
  253. package/schema/sources.d.ts +103 -0
  254. package/schema/sources.js +65 -0
  255. package/schema/sources.js.map +1 -0
  256. package/schema/table.d.ts +319 -0
  257. package/schema/table.js +1198 -0
  258. package/schema/table.js.map +1 -0
  259. package/schema/types.d.ts +269 -0
  260. package/schema/types.js +14 -0
  261. package/schema/types.js.map +1 -0
  262. package/types.d.ts +17 -0
  263. package/ui/action-tray.d.ts +54 -0
  264. package/ui/action-tray.js +153 -0
  265. package/ui/action-tray.js.map +1 -0
  266. package/ui/button.d.ts +57 -0
  267. package/ui/button.js +202 -0
  268. package/ui/button.js.map +1 -0
  269. package/ui/choice-switch.d.ts +36 -0
  270. package/ui/choice-switch.js +57 -0
  271. package/ui/choice-switch.js.map +1 -0
  272. package/ui/controls.d.ts +83 -0
  273. package/ui/controls.js +319 -0
  274. package/ui/controls.js.map +1 -0
  275. package/ui/display.d.ts +156 -0
  276. package/ui/display.js +444 -0
  277. package/ui/display.js.map +1 -0
  278. package/ui/expanded-editor-modal.d.ts +26 -0
  279. package/ui/expanded-editor-modal.js +140 -0
  280. package/ui/expanded-editor-modal.js.map +1 -0
  281. package/ui/field-context.d.ts +12 -0
  282. package/ui/field-context.js +23 -0
  283. package/ui/field-context.js.map +1 -0
  284. package/ui/floating-panel.d.ts +152 -0
  285. package/ui/floating-panel.js +912 -0
  286. package/ui/floating-panel.js.map +1 -0
  287. package/ui/index.d.ts +12 -0
  288. package/ui/index.js +13 -0
  289. package/ui/input.d.ts +78 -0
  290. package/ui/input.js +250 -0
  291. package/ui/input.js.map +1 -0
  292. package/ui/mode-bar.d.ts +31 -0
  293. package/ui/mode-bar.js +65 -0
  294. package/ui/mode-bar.js.map +1 -0
  295. package/ui/overlay.d.ts +123 -0
  296. package/ui/overlay.js +378 -0
  297. package/ui/overlay.js.map +1 -0
  298. package/ui/path-crumbs.d.ts +90 -0
  299. package/ui/path-crumbs.js +532 -0
  300. package/ui/path-crumbs.js.map +1 -0
  301. package/ui/presence.d.ts +16 -0
  302. package/ui/presence.js +65 -0
  303. package/ui/presence.js.map +1 -0
  304. package/ui/select.d.ts +66 -0
  305. package/ui/select.js +405 -0
  306. package/ui/select.js.map +1 -0
  307. package/ui/shortcut-hint.d.ts +14 -0
  308. package/ui/shortcut-hint.js +35 -0
  309. package/ui/shortcut-hint.js.map +1 -0
  310. package/ui/surfaces.d.ts +23 -0
  311. package/ui/surfaces.js +26 -0
  312. package/ui/surfaces.js.map +1 -0
  313. package/ui/tooltip-root.d.ts +12 -0
  314. package/ui/tooltip-root.js +76 -0
  315. package/ui/tooltip-root.js.map +1 -0
  316. package/ui/variants.d.ts +15 -0
  317. package/ui/variants.js +14 -0
  318. package/ui/variants.js.map +1 -0
  319. package/LICENSE +0 -21
  320. package/README.md +0 -27
  321. package/dist/_chunks-cjs/_visual-editing.js +0 -5898
  322. package/dist/_chunks-cjs/refractor.js +0 -22
  323. package/dist/_chunks-es/_visual-editing.mjs +0 -5904
  324. package/dist/_chunks-es/refractor.mjs +0 -25
  325. package/dist/_color.d.mts +0 -119
  326. package/dist/_color.d.ts +0 -119
  327. package/dist/_color.js +0 -1412
  328. package/dist/_color.mjs +0 -1411
  329. package/dist/_visual-editing.d.mts +0 -1126
  330. package/dist/_visual-editing.d.ts +0 -1126
  331. package/dist/_visual-editing.js +0 -30
  332. package/dist/_visual-editing.mjs +0 -30
  333. package/dist/index.d.mts +0 -3140
  334. package/dist/index.d.ts +0 -3140
  335. package/dist/index.js +0 -2036
  336. package/dist/index.mjs +0 -2044
  337. package/dist/theme.d.mts +0 -1506
  338. package/dist/theme.d.ts +0 -1506
  339. package/dist/theme.js +0 -4126
  340. package/dist/theme.mjs +0 -4126
  341. package/exports/_visual-editing.ts +0 -31
  342. package/exports/index.ts +0 -1
  343. package/exports/theme.ts +0 -1
  344. package/src/color/index.d.mts +0 -119
  345. package/src/color/index.mjs +0 -1411
  346. package/src/core/__workshop__/constants.ts +0 -293
  347. package/src/core/_compat.ts +0 -264
  348. package/src/core/components/autocomplete/__mocks__/apiStore.ts +0 -49
  349. package/src/core/components/autocomplete/__mocks__/countries.ts +0 -245
  350. package/src/core/components/autocomplete/__workshop__/async.tsx +0 -156
  351. package/src/core/components/autocomplete/__workshop__/constrainedHeight.tsx +0 -137
  352. package/src/core/components/autocomplete/__workshop__/custom.tsx +0 -89
  353. package/src/core/components/autocomplete/__workshop__/example.tsx +0 -79
  354. package/src/core/components/autocomplete/__workshop__/focusAndBlur.tsx +0 -36
  355. package/src/core/components/autocomplete/__workshop__/fullscreen.tsx +0 -294
  356. package/src/core/components/autocomplete/__workshop__/index.ts +0 -39
  357. package/src/core/components/autocomplete/__workshop__/types.ts +0 -4
  358. package/src/core/components/autocomplete/autocomplete.styles.tsx +0 -39
  359. package/src/core/components/autocomplete/autocomplete.tsx +0 -767
  360. package/src/core/components/autocomplete/autocompleteOption.tsx +0 -45
  361. package/src/core/components/autocomplete/autocompleteReducer.ts +0 -47
  362. package/src/core/components/autocomplete/constants.ts +0 -28
  363. package/src/core/components/autocomplete/index.ts +0 -2
  364. package/src/core/components/autocomplete/types.ts +0 -108
  365. package/src/core/components/breadcrumbs/__workshop__/example.tsx +0 -62
  366. package/src/core/components/breadcrumbs/__workshop__/index.ts +0 -14
  367. package/src/core/components/breadcrumbs/breadcrumbs.styles.ts +0 -18
  368. package/src/core/components/breadcrumbs/breadcrumbs.test.tsx +0 -51
  369. package/src/core/components/breadcrumbs/breadcrumbs.tsx +0 -133
  370. package/src/core/components/breadcrumbs/index.ts +0 -1
  371. package/src/core/components/dialog/__workshop__/activate.tsx +0 -134
  372. package/src/core/components/dialog/__workshop__/autoFocus.tsx +0 -29
  373. package/src/core/components/dialog/__workshop__/index.ts +0 -19
  374. package/src/core/components/dialog/__workshop__/layering.tsx +0 -41
  375. package/src/core/components/dialog/__workshop__/nested.tsx +0 -72
  376. package/src/core/components/dialog/__workshop__/onScroll.tsx +0 -39
  377. package/src/core/components/dialog/__workshop__/panes.tsx +0 -82
  378. package/src/core/components/dialog/__workshop__/position.tsx +0 -30
  379. package/src/core/components/dialog/__workshop__/props.tsx +0 -75
  380. package/src/core/components/dialog/__workshop__/provider.tsx +0 -11
  381. package/src/core/components/dialog/__workshop__/wrapped.tsx +0 -76
  382. package/src/core/components/dialog/dialog.tsx +0 -430
  383. package/src/core/components/dialog/dialogContext.ts +0 -20
  384. package/src/core/components/dialog/dialogProvider.tsx +0 -35
  385. package/src/core/components/dialog/index.ts +0 -4
  386. package/src/core/components/dialog/styles.ts +0 -77
  387. package/src/core/components/dialog/useDialog.ts +0 -11
  388. package/src/core/components/hotkeys/__workshop__/index.ts +0 -14
  389. package/src/core/components/hotkeys/__workshop__/plain.tsx +0 -9
  390. package/src/core/components/hotkeys/hotkeys.test.tsx +0 -42
  391. package/src/core/components/hotkeys/hotkeys.tsx +0 -66
  392. package/src/core/components/hotkeys/index.ts +0 -1
  393. package/src/core/components/index.ts +0 -9
  394. package/src/core/components/menu/__workshop__/asComponent.tsx +0 -45
  395. package/src/core/components/menu/__workshop__/avatarMenu.tsx +0 -51
  396. package/src/core/components/menu/__workshop__/closableMenuButton.tsx +0 -46
  397. package/src/core/components/menu/__workshop__/constrainedInBoundary.tsx +0 -134
  398. package/src/core/components/menu/__workshop__/customMenuItem.tsx +0 -45
  399. package/src/core/components/menu/__workshop__/customSelectedState.tsx +0 -39
  400. package/src/core/components/menu/__workshop__/disableFocusOnClose.tsx +0 -40
  401. package/src/core/components/menu/__workshop__/groups.tsx +0 -156
  402. package/src/core/components/menu/__workshop__/index.ts +0 -89
  403. package/src/core/components/menu/__workshop__/menuButton.tsx +0 -80
  404. package/src/core/components/menu/__workshop__/menuGroupRight.tsx +0 -58
  405. package/src/core/components/menu/__workshop__/nestedMenu.tsx +0 -22
  406. package/src/core/components/menu/__workshop__/onCloseMenuButton.tsx +0 -41
  407. package/src/core/components/menu/__workshop__/selectedItem.tsx +0 -69
  408. package/src/core/components/menu/__workshop__/shouldFocus.tsx +0 -47
  409. package/src/core/components/menu/__workshop__/tones.tsx +0 -25
  410. package/src/core/components/menu/__workshop__/withoutArrow.tsx +0 -32
  411. package/src/core/components/menu/helpers.ts +0 -82
  412. package/src/core/components/menu/index.ts +0 -5
  413. package/src/core/components/menu/menu.spacing.test.tsx +0 -63
  414. package/src/core/components/menu/menu.test.tsx +0 -125
  415. package/src/core/components/menu/menu.tsx +0 -178
  416. package/src/core/components/menu/menuButton.tsx +0 -268
  417. package/src/core/components/menu/menuContext.ts +0 -18
  418. package/src/core/components/menu/menuDivider.ts +0 -23
  419. package/src/core/components/menu/menuGroup.spacing.test.tsx +0 -63
  420. package/src/core/components/menu/menuGroup.tsx +0 -233
  421. package/src/core/components/menu/menuItem.spacing.test.tsx +0 -59
  422. package/src/core/components/menu/menuItem.tsx +0 -197
  423. package/src/core/components/menu/useMenu.ts +0 -21
  424. package/src/core/components/menu/useMenuController.ts +0 -231
  425. package/src/core/components/skeleton/__workshop__/delay.tsx +0 -70
  426. package/src/core/components/skeleton/__workshop__/index.ts +0 -11
  427. package/src/core/components/skeleton/__workshop__/skeleton.tsx +0 -64
  428. package/src/core/components/skeleton/index.ts +0 -2
  429. package/src/core/components/skeleton/skeleton.tsx +0 -57
  430. package/src/core/components/skeleton/styles.ts +0 -50
  431. package/src/core/components/skeleton/textSkeleton.tsx +0 -122
  432. package/src/core/components/tab/__workshop__/example.tsx +0 -79
  433. package/src/core/components/tab/__workshop__/index.ts +0 -14
  434. package/src/core/components/tab/index.ts +0 -3
  435. package/src/core/components/tab/tab.tsx +0 -101
  436. package/src/core/components/tab/tabList.test.tsx +0 -48
  437. package/src/core/components/tab/tabList.tsx +0 -70
  438. package/src/core/components/tab/tabPanel.tsx +0 -39
  439. package/src/core/components/toast/__workshop__/hook.tsx +0 -71
  440. package/src/core/components/toast/__workshop__/index.ts +0 -19
  441. package/src/core/components/toast/__workshop__/toast.tsx +0 -26
  442. package/src/core/components/toast/index.ts +0 -4
  443. package/src/core/components/toast/styles.ts +0 -77
  444. package/src/core/components/toast/toast.test.tsx +0 -101
  445. package/src/core/components/toast/toast.tsx +0 -198
  446. package/src/core/components/toast/toastContext.ts +0 -7
  447. package/src/core/components/toast/toastLayer.tsx +0 -51
  448. package/src/core/components/toast/toastProvider.tsx +0 -113
  449. package/src/core/components/toast/toastState.ts +0 -6
  450. package/src/core/components/toast/types.ts +0 -26
  451. package/src/core/components/toast/useToast.ts +0 -25
  452. package/src/core/components/tree/__workshop__/basic.perf.ts +0 -19
  453. package/src/core/components/tree/__workshop__/basic.tsx +0 -105
  454. package/src/core/components/tree/__workshop__/index.ts +0 -21
  455. package/src/core/components/tree/__workshop__/tabFromElement.tsx +0 -84
  456. package/src/core/components/tree/helpers.ts +0 -105
  457. package/src/core/components/tree/index.ts +0 -4
  458. package/src/core/components/tree/style.ts +0 -105
  459. package/src/core/components/tree/tree.test.tsx +0 -55
  460. package/src/core/components/tree/tree.tsx +0 -240
  461. package/src/core/components/tree/treeContext.ts +0 -10
  462. package/src/core/components/tree/treeGroup.tsx +0 -28
  463. package/src/core/components/tree/treeItem.test.tsx +0 -65
  464. package/src/core/components/tree/treeItem.tsx +0 -224
  465. package/src/core/components/tree/types.ts +0 -25
  466. package/src/core/components/tree/useTree.ts +0 -17
  467. package/src/core/constants.ts +0 -79
  468. package/src/core/helpers/animation.ts +0 -27
  469. package/src/core/helpers/element.ts +0 -55
  470. package/src/core/helpers/focus.ts +0 -100
  471. package/src/core/helpers/index.ts +0 -4
  472. package/src/core/helpers/scroll.ts +0 -15
  473. package/src/core/hooks/index.ts +0 -12
  474. package/src/core/hooks/useArrayProp.ts +0 -17
  475. package/src/core/hooks/useClickOutside.test.tsx +0 -482
  476. package/src/core/hooks/useClickOutside.ts +0 -118
  477. package/src/core/hooks/useClickOutsideEvent.test.tsx +0 -115
  478. package/src/core/hooks/useClickOutsideEvent.ts +0 -73
  479. package/src/core/hooks/useCustomValidity.ts +0 -13
  480. package/src/core/hooks/useDelayed.test.ts +0 -88
  481. package/src/core/hooks/useDelayedState.ts +0 -36
  482. package/src/core/hooks/useElementRect/__workshop__/example.tsx +0 -32
  483. package/src/core/hooks/useElementRect/__workshop__/index.ts +0 -14
  484. package/src/core/hooks/useElementRect/index.ts +0 -1
  485. package/src/core/hooks/useElementRect/useElementRect.ts +0 -13
  486. package/src/core/hooks/useElementSize.ts +0 -19
  487. package/src/core/hooks/useForwardedRef.ts +0 -19
  488. package/src/core/hooks/useGlobalKeyDown.ts +0 -24
  489. package/src/core/hooks/useIsomorphicEffect.ts +0 -7
  490. package/src/core/hooks/useMatchMedia.ts +0 -28
  491. package/src/core/hooks/useMediaIndex/__workshop__/index.ts +0 -14
  492. package/src/core/hooks/useMediaIndex/__workshop__/test.tsx +0 -14
  493. package/src/core/hooks/useMediaIndex/index.ts +0 -1
  494. package/src/core/hooks/useMediaIndex/useMediaIndex.test.tsx +0 -36
  495. package/src/core/hooks/useMediaIndex/useMediaIndex.ts +0 -102
  496. package/src/core/hooks/useMounted.ts +0 -15
  497. package/src/core/hooks/usePrefersDark.hydration.test.tsx +0 -56
  498. package/src/core/hooks/usePrefersDark.test.tsx +0 -19
  499. package/src/core/hooks/usePrefersDark.ts +0 -16
  500. package/src/core/hooks/usePrefersReducedMotion.hydration.test.tsx +0 -56
  501. package/src/core/hooks/usePrefersReducedMotion.test.tsx +0 -19
  502. package/src/core/hooks/usePrefersReducedMotion.ts +0 -16
  503. package/src/core/index.ts +0 -10
  504. package/src/core/lib/createGlobalScopedContext.ts +0 -36
  505. package/src/core/lib/globalScope.ts +0 -19
  506. package/src/core/lib/isRecord.ts +0 -3
  507. package/src/core/middleware/origin.ts +0 -47
  508. package/src/core/observers/elementSizeObserver.ts +0 -116
  509. package/src/core/observers/index.ts +0 -2
  510. package/src/core/observers/resizeObserver.ts +0 -9
  511. package/src/core/primitives/_selectable/index.ts +0 -1
  512. package/src/core/primitives/_selectable/selectable.tsx +0 -15
  513. package/src/core/primitives/_selectable/style.ts +0 -115
  514. package/src/core/primitives/avatar/__workshop__/asButton.tsx +0 -14
  515. package/src/core/primitives/avatar/__workshop__/index.ts +0 -29
  516. package/src/core/primitives/avatar/__workshop__/stack.tsx +0 -25
  517. package/src/core/primitives/avatar/__workshop__/withinButton.tsx +0 -63
  518. package/src/core/primitives/avatar/__workshop__/withinMenuItem.tsx +0 -70
  519. package/src/core/primitives/avatar/avatar.tsx +0 -200
  520. package/src/core/primitives/avatar/avatarCounter.tsx +0 -91
  521. package/src/core/primitives/avatar/avatarStack.tsx +0 -100
  522. package/src/core/primitives/avatar/index.ts +0 -4
  523. package/src/core/primitives/avatar/styles.ts +0 -167
  524. package/src/core/primitives/avatar/types.ts +0 -17
  525. package/src/core/primitives/badge/__workshop__/index.ts +0 -19
  526. package/src/core/primitives/badge/__workshop__/props.tsx +0 -30
  527. package/src/core/primitives/badge/__workshop__/tones.tsx +0 -21
  528. package/src/core/primitives/badge/badge.test.tsx +0 -16
  529. package/src/core/primitives/badge/badge.tsx +0 -70
  530. package/src/core/primitives/badge/index.ts +0 -1
  531. package/src/core/primitives/badge/styles.ts +0 -20
  532. package/src/core/primitives/badge/types.ts +0 -8
  533. package/src/core/primitives/box/__workshop__/asComponent.tsx +0 -31
  534. package/src/core/primitives/box/__workshop__/index.ts +0 -24
  535. package/src/core/primitives/box/__workshop__/props.tsx +0 -20
  536. package/src/core/primitives/box/__workshop__/responsive.tsx +0 -20
  537. package/src/core/primitives/box/box.test.tsx +0 -142
  538. package/src/core/primitives/box/box.tsx +0 -154
  539. package/src/core/primitives/box/index.ts +0 -1
  540. package/src/core/primitives/button/__workshop__/custom.tsx +0 -51
  541. package/src/core/primitives/button/__workshop__/customIcons.tsx +0 -30
  542. package/src/core/primitives/button/__workshop__/disabled.tsx +0 -74
  543. package/src/core/primitives/button/__workshop__/index.ts +0 -59
  544. package/src/core/primitives/button/__workshop__/labelUploadButton.tsx +0 -36
  545. package/src/core/primitives/button/__workshop__/mixedChildren.tsx +0 -12
  546. package/src/core/primitives/button/__workshop__/props.tsx +0 -55
  547. package/src/core/primitives/button/__workshop__/stacked.tsx +0 -58
  548. package/src/core/primitives/button/__workshop__/styled1.tsx +0 -17
  549. package/src/core/primitives/button/__workshop__/styled2.tsx +0 -19
  550. package/src/core/primitives/button/__workshop__/uploadButton.tsx +0 -28
  551. package/src/core/primitives/button/button.test.tsx +0 -82
  552. package/src/core/primitives/button/button.tsx +0 -210
  553. package/src/core/primitives/button/index.ts +0 -1
  554. package/src/core/primitives/button/styles.ts +0 -117
  555. package/src/core/primitives/card/__workshop__/allTones.tsx +0 -25
  556. package/src/core/primitives/card/__workshop__/asButton.tsx +0 -107
  557. package/src/core/primitives/card/__workshop__/asComponent.tsx +0 -27
  558. package/src/core/primitives/card/__workshop__/checkered.tsx +0 -26
  559. package/src/core/primitives/card/__workshop__/index.ts +0 -18
  560. package/src/core/primitives/card/__workshop__/interactive.tsx +0 -30
  561. package/src/core/primitives/card/__workshop__/listNavigation.tsx +0 -80
  562. package/src/core/primitives/card/__workshop__/props.tsx +0 -53
  563. package/src/core/primitives/card/__workshop__/selected.tsx +0 -94
  564. package/src/core/primitives/card/__workshop__/styled.tsx +0 -14
  565. package/src/core/primitives/card/card.tsx +0 -128
  566. package/src/core/primitives/card/index.ts +0 -2
  567. package/src/core/primitives/card/styles.ts +0 -147
  568. package/src/core/primitives/card/types.ts +0 -11
  569. package/src/core/primitives/checkbox/__workshop__/example.tsx +0 -25
  570. package/src/core/primitives/checkbox/__workshop__/index.ts +0 -13
  571. package/src/core/primitives/checkbox/__workshop__/props.tsx +0 -33
  572. package/src/core/primitives/checkbox/__workshop__/readOnly.tsx +0 -16
  573. package/src/core/primitives/checkbox/__workshop__/tones.tsx +0 -28
  574. package/src/core/primitives/checkbox/checkbox.tsx +0 -73
  575. package/src/core/primitives/checkbox/index.ts +0 -1
  576. package/src/core/primitives/checkbox/styles.ts +0 -128
  577. package/src/core/primitives/code/__workshop__/index.ts +0 -19
  578. package/src/core/primitives/code/__workshop__/opticalAlignment.tsx +0 -48
  579. package/src/core/primitives/code/__workshop__/props.tsx +0 -21
  580. package/src/core/primitives/code/code.tsx +0 -55
  581. package/src/core/primitives/code/index.ts +0 -1
  582. package/src/core/primitives/code/refractor.tsx +0 -20
  583. package/src/core/primitives/code/styles.ts +0 -77
  584. package/src/core/primitives/container/__workshop__/example.tsx +0 -20
  585. package/src/core/primitives/container/__workshop__/index.ts +0 -8
  586. package/src/core/primitives/container/container.tsx +0 -54
  587. package/src/core/primitives/container/index.ts +0 -2
  588. package/src/core/primitives/container/styles.ts +0 -23
  589. package/src/core/primitives/container/types.ts +0 -6
  590. package/src/core/primitives/flex/__workshop__/example.tsx +0 -34
  591. package/src/core/primitives/flex/__workshop__/gap.tsx +0 -25
  592. package/src/core/primitives/flex/__workshop__/index.ts +0 -11
  593. package/src/core/primitives/flex/flex.tsx +0 -64
  594. package/src/core/primitives/flex/index.ts +0 -1
  595. package/src/core/primitives/grid/__workshop__/index.ts +0 -10
  596. package/src/core/primitives/grid/__workshop__/responsive.tsx +0 -54
  597. package/src/core/primitives/grid/grid.test.tsx +0 -80
  598. package/src/core/primitives/grid/grid.tsx +0 -74
  599. package/src/core/primitives/grid/index.ts +0 -1
  600. package/src/core/primitives/heading/__workshop__/index.ts +0 -19
  601. package/src/core/primitives/heading/__workshop__/opticalAlignment.tsx +0 -54
  602. package/src/core/primitives/heading/__workshop__/plain.tsx +0 -32
  603. package/src/core/primitives/heading/heading.tsx +0 -88
  604. package/src/core/primitives/heading/index.ts +0 -1
  605. package/src/core/primitives/heading/styles.ts +0 -64
  606. package/src/core/primitives/heading/types.ts +0 -7
  607. package/src/core/primitives/index.ts +0 -27
  608. package/src/core/primitives/inline/__workshop__/index.ts +0 -8
  609. package/src/core/primitives/inline/__workshop__/plain.tsx +0 -27
  610. package/src/core/primitives/inline/index.ts +0 -1
  611. package/src/core/primitives/inline/inline.test.tsx +0 -51
  612. package/src/core/primitives/inline/inline.tsx +0 -63
  613. package/src/core/primitives/inline/styles.ts +0 -32
  614. package/src/core/primitives/inline/types.ts +0 -6
  615. package/src/core/primitives/kbd/__workshop__/index.ts +0 -8
  616. package/src/core/primitives/kbd/__workshop__/plain.tsx +0 -9
  617. package/src/core/primitives/kbd/index.ts +0 -1
  618. package/src/core/primitives/kbd/kbd.tsx +0 -69
  619. package/src/core/primitives/label/__workshop__/index.ts +0 -19
  620. package/src/core/primitives/label/__workshop__/opticalAlignment.tsx +0 -48
  621. package/src/core/primitives/label/__workshop__/plain.tsx +0 -24
  622. package/src/core/primitives/label/index.ts +0 -1
  623. package/src/core/primitives/label/label.tsx +0 -87
  624. package/src/core/primitives/label/styles.ts +0 -45
  625. package/src/core/primitives/popover/__workshop__/AlignedStory.tsx +0 -77
  626. package/src/core/primitives/popover/__workshop__/MarginsStory.tsx +0 -31
  627. package/src/core/primitives/popover/__workshop__/MatchReferenceWidthStory.tsx +0 -32
  628. package/src/core/primitives/popover/__workshop__/OpenOnMountStory.tsx +0 -11
  629. package/src/core/primitives/popover/__workshop__/PlainStory.tsx +0 -71
  630. package/src/core/primitives/popover/__workshop__/RecursiveStory.tsx +0 -71
  631. package/src/core/primitives/popover/__workshop__/SidePanelStory.tsx +0 -89
  632. package/src/core/primitives/popover/__workshop__/TestStory.tsx +0 -97
  633. package/src/core/primitives/popover/__workshop__/index.ts +0 -49
  634. package/src/core/primitives/popover/constants.ts +0 -22
  635. package/src/core/primitives/popover/floating-ui/size.ts +0 -99
  636. package/src/core/primitives/popover/helpers.ts +0 -31
  637. package/src/core/primitives/popover/index.ts +0 -2
  638. package/src/core/primitives/popover/popover.tsx +0 -511
  639. package/src/core/primitives/popover/popoverCard.tsx +0 -166
  640. package/src/core/primitives/popover/types.ts +0 -7
  641. package/src/core/primitives/radio/__workshop__/example.tsx +0 -63
  642. package/src/core/primitives/radio/__workshop__/index.ts +0 -11
  643. package/src/core/primitives/radio/__workshop__/plain.tsx +0 -28
  644. package/src/core/primitives/radio/index.ts +0 -1
  645. package/src/core/primitives/radio/radio.tsx +0 -51
  646. package/src/core/primitives/radio/styles.ts +0 -117
  647. package/src/core/primitives/select/__workshop__/index.ts +0 -11
  648. package/src/core/primitives/select/__workshop__/plain.tsx +0 -27
  649. package/src/core/primitives/select/__workshop__/readOnly.tsx +0 -23
  650. package/src/core/primitives/select/index.ts +0 -1
  651. package/src/core/primitives/select/select.test.tsx +0 -52
  652. package/src/core/primitives/select/select.tsx +0 -94
  653. package/src/core/primitives/select/styles.ts +0 -166
  654. package/src/core/primitives/spinner/__workshop__/Props.tsx +0 -15
  655. package/src/core/primitives/spinner/__workshop__/index.ts +0 -14
  656. package/src/core/primitives/spinner/index.ts +0 -1
  657. package/src/core/primitives/spinner/spinner.tsx +0 -46
  658. package/src/core/primitives/stack/__workshop__/index.ts +0 -14
  659. package/src/core/primitives/stack/__workshop__/plain.tsx +0 -32
  660. package/src/core/primitives/stack/index.ts +0 -1
  661. package/src/core/primitives/stack/stack.test.tsx +0 -57
  662. package/src/core/primitives/stack/stack.tsx +0 -57
  663. package/src/core/primitives/stack/styles.ts +0 -32
  664. package/src/core/primitives/switch/__workshop__/example.tsx +0 -23
  665. package/src/core/primitives/switch/__workshop__/index.ts +0 -11
  666. package/src/core/primitives/switch/__workshop__/props.tsx +0 -21
  667. package/src/core/primitives/switch/index.ts +0 -1
  668. package/src/core/primitives/switch/styles.ts +0 -173
  669. package/src/core/primitives/switch/switch.tsx +0 -68
  670. package/src/core/primitives/text/__workshop__/colored.tsx +0 -30
  671. package/src/core/primitives/text/__workshop__/example.tsx +0 -39
  672. package/src/core/primitives/text/__workshop__/index.ts +0 -24
  673. package/src/core/primitives/text/__workshop__/opticalAlignment.tsx +0 -48
  674. package/src/core/primitives/text/index.ts +0 -1
  675. package/src/core/primitives/text/styles.ts +0 -74
  676. package/src/core/primitives/text/text.tsx +0 -89
  677. package/src/core/primitives/textArea/__workshop__/index.ts +0 -14
  678. package/src/core/primitives/textArea/__workshop__/plain.tsx +0 -50
  679. package/src/core/primitives/textArea/index.ts +0 -1
  680. package/src/core/primitives/textArea/textArea.tsx +0 -120
  681. package/src/core/primitives/textInput/__workshop__/clearButton.tsx +0 -30
  682. package/src/core/primitives/textInput/__workshop__/customValidity.tsx +0 -17
  683. package/src/core/primitives/textInput/__workshop__/index.ts +0 -44
  684. package/src/core/primitives/textInput/__workshop__/plain.tsx +0 -98
  685. package/src/core/primitives/textInput/__workshop__/readOnly.tsx +0 -9
  686. package/src/core/primitives/textInput/__workshop__/states.tsx +0 -53
  687. package/src/core/primitives/textInput/__workshop__/tones.tsx +0 -277
  688. package/src/core/primitives/textInput/__workshop__/typed.tsx +0 -23
  689. package/src/core/primitives/textInput/index.ts +0 -1
  690. package/src/core/primitives/textInput/textInput.test.tsx +0 -48
  691. package/src/core/primitives/textInput/textInput.tsx +0 -395
  692. package/src/core/primitives/tooltip/__workshop__/customPortal.tsx +0 -102
  693. package/src/core/primitives/tooltip/__workshop__/index.ts +0 -29
  694. package/src/core/primitives/tooltip/__workshop__/overflowingBoundary.tsx +0 -74
  695. package/src/core/primitives/tooltip/__workshop__/props.tsx +0 -107
  696. package/src/core/primitives/tooltip/__workshop__/resizableBoundary.tsx +0 -86
  697. package/src/core/primitives/tooltip/constants.ts +0 -23
  698. package/src/core/primitives/tooltip/index.ts +0 -2
  699. package/src/core/primitives/tooltip/tooltip.test.tsx +0 -452
  700. package/src/core/primitives/tooltip/tooltip.tsx +0 -495
  701. package/src/core/primitives/tooltip/tooltipCard.tsx +0 -109
  702. package/src/core/primitives/tooltip/tooltipDelayGroup/index.ts +0 -4
  703. package/src/core/primitives/tooltip/tooltipDelayGroup/tooltipDelayGroupContext.tsx +0 -11
  704. package/src/core/primitives/tooltip/tooltipDelayGroup/tooltipDelayGroupProvider.tsx +0 -57
  705. package/src/core/primitives/tooltip/tooltipDelayGroup/types.ts +0 -10
  706. package/src/core/primitives/tooltip/tooltipDelayGroup/useTooltipDelayGroup.ts +0 -13
  707. package/src/core/primitives/types.ts +0 -179
  708. package/src/core/styles/border/borderStyle.ts +0 -56
  709. package/src/core/styles/border/index.ts +0 -2
  710. package/src/core/styles/border/types.ts +0 -10
  711. package/src/core/styles/box/boxStyle.ts +0 -69
  712. package/src/core/styles/box/index.ts +0 -2
  713. package/src/core/styles/box/types.ts +0 -11
  714. package/src/core/styles/card/_cardColorStyle.ts +0 -108
  715. package/src/core/styles/card/index.ts +0 -1
  716. package/src/core/styles/flex/flexItemStyle.ts +0 -27
  717. package/src/core/styles/flex/flexStyle.ts +0 -70
  718. package/src/core/styles/flex/index.ts +0 -3
  719. package/src/core/styles/flex/types.ts +0 -25
  720. package/src/core/styles/focusRing/index.ts +0 -25
  721. package/src/core/styles/font/codeFontStyle.ts +0 -13
  722. package/src/core/styles/font/headingFontStyle.ts +0 -13
  723. package/src/core/styles/font/index.ts +0 -6
  724. package/src/core/styles/font/labelFontStyle.ts +0 -13
  725. package/src/core/styles/font/responsiveFont.ts +0 -103
  726. package/src/core/styles/font/textAlignStyle.ts +0 -19
  727. package/src/core/styles/font/textFontStyle.ts +0 -13
  728. package/src/core/styles/font/types.ts +0 -35
  729. package/src/core/styles/grid/gridItemStyle.ts +0 -82
  730. package/src/core/styles/grid/gridStyle.ts +0 -108
  731. package/src/core/styles/grid/index.ts +0 -3
  732. package/src/core/styles/grid/types.ts +0 -37
  733. package/src/core/styles/helpers.ts +0 -72
  734. package/src/core/styles/index.ts +0 -5
  735. package/src/core/styles/input/index.ts +0 -2
  736. package/src/core/styles/input/responsiveInputPaddingStyle.ts +0 -78
  737. package/src/core/styles/input/textInputStyle.ts +0 -263
  738. package/src/core/styles/internal.ts +0 -12
  739. package/src/core/styles/margin/index.ts +0 -2
  740. package/src/core/styles/margin/marginStyle.ts +0 -21
  741. package/src/core/styles/margin/marginsStyle.test.ts +0 -33
  742. package/src/core/styles/margin/types.ts +0 -9
  743. package/src/core/styles/padding/index.ts +0 -2
  744. package/src/core/styles/padding/paddingStyle.test.ts +0 -33
  745. package/src/core/styles/padding/paddingStyle.ts +0 -21
  746. package/src/core/styles/padding/types.ts +0 -12
  747. package/src/core/styles/radius/index.ts +0 -2
  748. package/src/core/styles/radius/radiusStyle.ts +0 -23
  749. package/src/core/styles/radius/types.ts +0 -8
  750. package/src/core/styles/shadow/index.ts +0 -2
  751. package/src/core/styles/shadow/shadowStyle.ts +0 -29
  752. package/src/core/styles/shadow/types.ts +0 -6
  753. package/src/core/styles/types.ts +0 -8
  754. package/src/core/theme/__workshop__/build/Root.tsx +0 -367
  755. package/src/core/theme/__workshop__/build/helpers.ts +0 -46
  756. package/src/core/theme/__workshop__/build/story.tsx +0 -465
  757. package/src/core/theme/__workshop__/canvas.tsx +0 -352
  758. package/src/core/theme/__workshop__/color.tsx +0 -62
  759. package/src/core/theme/__workshop__/debug/story.tsx +0 -408
  760. package/src/core/theme/__workshop__/index.ts +0 -39
  761. package/src/core/theme/__workshop__/layer.tsx +0 -78
  762. package/src/core/theme/__workshop__/nestedProvider.tsx +0 -15
  763. package/src/core/theme/index.ts +0 -5
  764. package/src/core/theme/theme.test.tsx +0 -73
  765. package/src/core/theme/themeColorProvider.tsx +0 -29
  766. package/src/core/theme/themeContext.ts +0 -10
  767. package/src/core/theme/themeProvider.tsx +0 -62
  768. package/src/core/theme/types.ts +0 -12
  769. package/src/core/theme/useRootTheme.ts +0 -17
  770. package/src/core/theme/useTheme.ts +0 -16
  771. package/src/core/types/avatar.ts +0 -14
  772. package/src/core/types/badge.ts +0 -12
  773. package/src/core/types/box.ts +0 -19
  774. package/src/core/types/button.ts +0 -21
  775. package/src/core/types/card.ts +0 -6
  776. package/src/core/types/component.ts +0 -32
  777. package/src/core/types/dialog.ts +0 -4
  778. package/src/core/types/flex.ts +0 -30
  779. package/src/core/types/grid.ts +0 -14
  780. package/src/core/types/gridItem.ts +0 -29
  781. package/src/core/types/index.ts +0 -15
  782. package/src/core/types/placement.ts +0 -18
  783. package/src/core/types/popover.ts +0 -4
  784. package/src/core/types/radius.ts +0 -4
  785. package/src/core/types/selectable.ts +0 -6
  786. package/src/core/types/text.ts +0 -4
  787. package/src/core/utils/arrow/arrow.tsx +0 -123
  788. package/src/core/utils/arrow/cmds.ts +0 -91
  789. package/src/core/utils/arrow/index.ts +0 -1
  790. package/src/core/utils/boundaryElement/__workshop__/index.ts +0 -14
  791. package/src/core/utils/boundaryElement/__workshop__/plain.tsx +0 -19
  792. package/src/core/utils/boundaryElement/boundaryElement.test.tsx +0 -100
  793. package/src/core/utils/boundaryElement/boundaryElementContext.ts +0 -7
  794. package/src/core/utils/boundaryElement/boundaryElementProvider.tsx +0 -24
  795. package/src/core/utils/boundaryElement/index.ts +0 -3
  796. package/src/core/utils/boundaryElement/types.ts +0 -7
  797. package/src/core/utils/boundaryElement/useBoundaryElement.ts +0 -26
  798. package/src/core/utils/conditionalWrapper/conditionalWrapper.tsx +0 -21
  799. package/src/core/utils/conditionalWrapper/index.ts +0 -1
  800. package/src/core/utils/elementQuery/__workshop__/customMedia.tsx +0 -30
  801. package/src/core/utils/elementQuery/__workshop__/index.ts +0 -14
  802. package/src/core/utils/elementQuery/elementQuery.tsx +0 -53
  803. package/src/core/utils/elementQuery/helpers.ts +0 -27
  804. package/src/core/utils/elementQuery/index.ts +0 -1
  805. package/src/core/utils/errorBoundary.tsx +0 -48
  806. package/src/core/utils/getElementRef.ts +0 -26
  807. package/src/core/utils/index.ts +0 -9
  808. package/src/core/utils/layer/__workshop__/_debug.tsx +0 -17
  809. package/src/core/utils/layer/__workshop__/index.ts +0 -24
  810. package/src/core/utils/layer/__workshop__/multipleRoots.tsx +0 -49
  811. package/src/core/utils/layer/__workshop__/nested.tsx +0 -98
  812. package/src/core/utils/layer/__workshop__/responsiveZOffset.tsx +0 -13
  813. package/src/core/utils/layer/getLayerContext.test.ts +0 -30
  814. package/src/core/utils/layer/getLayerContext.ts +0 -21
  815. package/src/core/utils/layer/index.ts +0 -4
  816. package/src/core/utils/layer/layer.test.tsx +0 -108
  817. package/src/core/utils/layer/layer.tsx +0 -98
  818. package/src/core/utils/layer/layerContext.ts +0 -7
  819. package/src/core/utils/layer/layerProvider.tsx +0 -111
  820. package/src/core/utils/layer/types.ts +0 -9
  821. package/src/core/utils/layer/useLayer.ts +0 -26
  822. package/src/core/utils/portal/__workshop__/index.ts +0 -14
  823. package/src/core/utils/portal/__workshop__/named.tsx +0 -63
  824. package/src/core/utils/portal/index.ts +0 -4
  825. package/src/core/utils/portal/portal.test.tsx +0 -103
  826. package/src/core/utils/portal/portal.ts +0 -32
  827. package/src/core/utils/portal/portalContext.ts +0 -31
  828. package/src/core/utils/portal/portalProvider.tsx +0 -47
  829. package/src/core/utils/portal/types.ts +0 -9
  830. package/src/core/utils/portal/usePortal.ts +0 -25
  831. package/src/core/utils/spanWithTextOverflow.tsx +0 -10
  832. package/src/core/utils/srOnly/index.ts +0 -1
  833. package/src/core/utils/srOnly/srOnly.tsx +0 -36
  834. package/src/core/utils/virtualList/__workshop__/changingProps.tsx +0 -36
  835. package/src/core/utils/virtualList/__workshop__/elementScroll.tsx +0 -24
  836. package/src/core/utils/virtualList/__workshop__/index.ts +0 -29
  837. package/src/core/utils/virtualList/__workshop__/infiniteList.tsx +0 -48
  838. package/src/core/utils/virtualList/__workshop__/windowScrolll.tsx +0 -22
  839. package/src/core/utils/virtualList/index.ts +0 -1
  840. package/src/core/utils/virtualList/virtualList.tsx +0 -200
  841. package/src/theme/build/_deprecated/color/_selectable/createSelectableTones.ts +0 -76
  842. package/src/theme/build/_deprecated/color/_solid/createSolidTones.ts +0 -54
  843. package/src/theme/build/_deprecated/color/button/createButtonModes.ts +0 -22
  844. package/src/theme/build/_deprecated/color/button/createButtonTones.ts +0 -55
  845. package/src/theme/build/_deprecated/color/card/createCardStates.ts +0 -60
  846. package/src/theme/build/_deprecated/color/color.test.ts +0 -63
  847. package/src/theme/build/_deprecated/color/defaults.ts +0 -390
  848. package/src/theme/build/_deprecated/color/factory.ts +0 -142
  849. package/src/theme/build/_deprecated/color/index.ts +0 -1
  850. package/src/theme/build/_deprecated/color/input/createInputModes.ts +0 -81
  851. package/src/theme/build/_deprecated/color/muted/createMuted.ts +0 -54
  852. package/src/theme/build/_deprecated/color/spot/createSpot.ts +0 -20
  853. package/src/theme/build/buildColorTheme.test.ts +0 -183
  854. package/src/theme/build/buildColorTheme.ts +0 -499
  855. package/src/theme/build/buildTheme.test.ts +0 -87
  856. package/src/theme/build/buildTheme.ts +0 -36
  857. package/src/theme/build/colorToken/colorToken.ts +0 -19
  858. package/src/theme/build/colorToken/compileColorToken.ts +0 -21
  859. package/src/theme/build/colorToken/index.ts +0 -2
  860. package/src/theme/build/colorToken/types.ts +0 -6
  861. package/src/theme/build/index.ts +0 -3
  862. package/src/theme/build/lib/color-fns/blend/index.ts +0 -3
  863. package/src/theme/build/lib/color-fns/blend/mix.ts +0 -21
  864. package/src/theme/build/lib/color-fns/blend/multiply.ts +0 -18
  865. package/src/theme/build/lib/color-fns/blend/screen.ts +0 -18
  866. package/src/theme/build/lib/color-fns/color-fns.test.ts +0 -68
  867. package/src/theme/build/lib/color-fns/contrastRatio.ts +0 -31
  868. package/src/theme/build/lib/color-fns/convert.ts +0 -150
  869. package/src/theme/build/lib/color-fns/index.ts +0 -6
  870. package/src/theme/build/lib/color-fns/parse.ts +0 -60
  871. package/src/theme/build/lib/color-fns/rgba.ts +0 -10
  872. package/src/theme/build/lib/color-fns/types.ts +0 -28
  873. package/src/theme/build/lib/isRecord.ts +0 -3
  874. package/src/theme/build/lib/lazy.ts +0 -30
  875. package/src/theme/build/lib/utils.ts +0 -19
  876. package/src/theme/build/merge.ts +0 -26
  877. package/src/theme/build/mixThemeColor.test.ts +0 -21
  878. package/src/theme/build/mixThemeColor.ts +0 -53
  879. package/src/theme/build/renderColorTheme.ts +0 -532
  880. package/src/theme/build/renderColorValue.ts +0 -85
  881. package/src/theme/build/resolveColorTokens.ts +0 -268
  882. package/src/theme/build/theme.test.ts +0 -27
  883. package/src/theme/config/helpers.ts +0 -55
  884. package/src/theme/config/index.ts +0 -4
  885. package/src/theme/config/system.ts +0 -115
  886. package/src/theme/config/tokens/color/index.ts +0 -1
  887. package/src/theme/config/tokens/color/types.ts +0 -133
  888. package/src/theme/config/tokens/index.ts +0 -4
  889. package/src/theme/config/tokens/parseTokenKey.test.ts +0 -64
  890. package/src/theme/config/tokens/parseTokenKey.ts +0 -67
  891. package/src/theme/config/tokens/parseTokenValue.test.ts +0 -42
  892. package/src/theme/config/tokens/parseTokenValue.ts +0 -133
  893. package/src/theme/config/tokens/types.ts +0 -53
  894. package/src/theme/config/types.ts +0 -46
  895. package/src/theme/defaults/colorPalette.ts +0 -5
  896. package/src/theme/defaults/colorTokens.ts +0 -648
  897. package/src/theme/defaults/config.ts +0 -84
  898. package/src/theme/defaults/fonts.ts +0 -227
  899. package/src/theme/getScopedTheme.ts +0 -98
  900. package/src/theme/index.ts +0 -5
  901. package/src/theme/system/avatar.ts +0 -14
  902. package/src/theme/system/color/_constants.ts +0 -45
  903. package/src/theme/system/color/_helpers.ts +0 -24
  904. package/src/theme/system/color/_system.ts +0 -40
  905. package/src/theme/system/color/avatar.ts +0 -15
  906. package/src/theme/system/color/badge.ts +0 -16
  907. package/src/theme/system/color/button.ts +0 -17
  908. package/src/theme/system/color/color.ts +0 -34
  909. package/src/theme/system/color/index.ts +0 -13
  910. package/src/theme/system/color/input.ts +0 -25
  911. package/src/theme/system/color/kbd.ts +0 -8
  912. package/src/theme/system/color/selectable.ts +0 -12
  913. package/src/theme/system/color/shadow.ts +0 -7
  914. package/src/theme/system/color/state.ts +0 -43
  915. package/src/theme/system/color/syntax.ts +0 -41
  916. package/src/theme/system/css.ts +0 -14
  917. package/src/theme/system/focusRing.ts +0 -7
  918. package/src/theme/system/font.ts +0 -52
  919. package/src/theme/system/index.ts +0 -11
  920. package/src/theme/system/input.ts +0 -33
  921. package/src/theme/system/layer.ts +0 -8
  922. package/src/theme/system/shadow.ts +0 -19
  923. package/src/theme/system/styles.ts +0 -13
  924. package/src/theme/system/theme.ts +0 -138
  925. package/src/theme/system/v0/avatar.ts +0 -10
  926. package/src/theme/system/v0/color/_generic.ts +0 -35
  927. package/src/theme/system/v0/color/_system.ts +0 -17
  928. package/src/theme/system/v0/color/base.ts +0 -21
  929. package/src/theme/system/v0/color/button.ts +0 -42
  930. package/src/theme/system/v0/color/card.ts +0 -19
  931. package/src/theme/system/v0/color/color.ts +0 -40
  932. package/src/theme/system/v0/color/index.ts +0 -11
  933. package/src/theme/system/v0/color/input.ts +0 -34
  934. package/src/theme/system/v0/color/muted.ts +0 -26
  935. package/src/theme/system/v0/color/selectable.ts +0 -31
  936. package/src/theme/system/v0/color/solid.ts +0 -26
  937. package/src/theme/system/v0/color/spot.ts +0 -13
  938. package/src/theme/system/v0/index.ts +0 -3
  939. package/src/theme/system/v0/input.ts +0 -23
  940. package/src/theme/versioning/getTheme_v2.ts +0 -57
  941. package/src/theme/versioning/index.ts +0 -5
  942. package/src/theme/versioning/is_v0.ts +0 -6
  943. package/src/theme/versioning/is_v2.ts +0 -6
  944. package/src/theme/versioning/themeColor_v0_v2.ts +0 -243
  945. package/src/theme/versioning/themeColor_v2_v2_9.ts +0 -49
  946. package/src/theme/versioning/v0_v2.ts +0 -94
  947. package/src/theme/versioning/v2_v0.ts +0 -135
@@ -0,0 +1,2722 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { useKitServices } from "../../context.js";
3
+ import { Button, IconButton } from "../../ui/button.js";
4
+ import { Segmented, Switch } from "../../ui/controls.js";
5
+ import { Menu, MenuCheckItem, MenuContent, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSub, MenuSubContent, MenuSubTrigger, MenuTrigger, Popover, PopoverAnchor, PopoverContent } from "../../ui/overlay.js";
6
+ import { GENERAL_TABLE, boolLabels, cellNote, cellText, cellType, cellValue, coerce, isCellObject, isEmptyCell, isObjLike, normalizeTable, orderedRows, parseDelimited, parseTableElement, pasteRange, tableFromRows, tableToRows, tkey, toBool, toNumber, withValue } from "../../schema/table.js";
7
+ import { Input, Textarea } from "../../ui/input.js";
8
+ import { FieldSection, FieldUnit, FieldUnitRow } from "../../engine/grouping.js";
9
+ import { Select } from "../../ui/select.js";
10
+ import { LinkField, hrefOf, linkText, normLink } from "../link.js";
11
+ import { SharedSortProvider, useSharedSort } from "../../engine/item-list.js";
12
+ import { RowList } from "../../engine/array.js";
13
+ import { ExpandedEditorModal } from "../../ui/expanded-editor-modal.js";
14
+ import { PathCrumbs } from "../../ui/path-crumbs.js";
15
+ import { ChoiceSwitch } from "../../ui/choice-switch.js";
16
+ import { LinkAddressButton, isScriptHref, tableLink } from "./table-link.js";
17
+ import { refLabel, useRefSearch } from "./refs.js";
18
+ import * as React from "react";
19
+ import { IconAlignLeft, IconArrowDown, IconArrowUp, IconArrowsMaximize, IconCheck, IconChevronDown, IconCurrencyDollar, IconDots, IconFileDatabase, IconFolder, IconGripVertical, IconHash, IconLayoutColumns, IconLetterT, IconLink, IconList, IconPlus, IconStar, IconTable, IconToggleRight } from "@tabler/icons-react";
20
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
21
+ import { ContextMenu } from "@base-ui/react/context-menu";
22
+ //#region src/kit/controls/table/table-editor.tsx
23
+ /**
24
+ * TABLE EDITOR (CPO D42, D49, D50, D52; port of V2 src/components/table/table-editor.tsx) — calm by default.
25
+ *
26
+ * Default nested array UX (D50): Title, Columns (an array list), Rows (nested under their groups, each the kit's own
27
+ * array row: first cell, summary, ⋯, ›), Note under the table, then a collapsed Table settings. A row or column
28
+ * drills through the kit form's navigation (standard breadcrumb + frame header, TableFrame); outside a form,
29
+ * through a local drill with the same trail. A row is one field per column; the column's type picks the
30
+ * control; per-cell exceptions (words instead, footnote, clear) sit behind a quiet ⋯ by the cell's label.
31
+ * Expanded the spreadsheet lives ONLY in the expanded-editor modal (D49), opened by ⤢ in the field's label row: click a
32
+ * cell and type, Tab / arrows / Enter move, "+" adds a column, grips reorder, ⋯ / Shift+F10 / right-click for
33
+ * column, row and cell options.
34
+ * Settings (D52) only presentation and structure, only what `field.table.settings` offers this kind.
35
+ *
36
+ * Kit deviations from V2 (no @dnd-kit / Radix in the kit): rows reorder inside their run with the kit's useDragReorder
37
+ * (pointer + ↑/↓ on the grip); moving a row to another group is the row's ⋯ › Move to group (V2 also allowed dragging it
38
+ * across). The cell context menu is Base UI's ContextMenu. Toasts come from KitServices (absent → silent). Link cells use
39
+ * the table's own address editor (table-link.tsx) in the spreadsheet and the global LinkField in a drilled row (as V2); reference cells search through the host (refs.ts).
40
+ */
41
+ var TYPE_UI = {
42
+ text: {
43
+ label: "Text",
44
+ icon: IconLetterT
45
+ },
46
+ number: {
47
+ label: "Number",
48
+ icon: IconHash
49
+ },
50
+ money: {
51
+ label: "Price",
52
+ icon: IconCurrencyDollar
53
+ },
54
+ boolean: {
55
+ label: "Yes / No",
56
+ icon: IconToggleRight
57
+ },
58
+ link: {
59
+ label: "Link",
60
+ icon: IconLink
61
+ },
62
+ rating: {
63
+ label: "Rating",
64
+ icon: IconStar
65
+ },
66
+ "richtext-inline": {
67
+ label: "Rich text",
68
+ icon: IconAlignLeft,
69
+ dev: true
70
+ },
71
+ reference: {
72
+ label: "Page or CMS item",
73
+ icon: IconFileDatabase,
74
+ dev: true
75
+ }
76
+ };
77
+ var NUMERIC = [
78
+ "number",
79
+ "money",
80
+ "rating"
81
+ ];
82
+ var CURRENCIES = [
83
+ "USD",
84
+ "EUR",
85
+ "GBP",
86
+ "INR"
87
+ ];
88
+ var TypeIcon = ({ type, className }) => {
89
+ const I = TYPE_UI[type].icon;
90
+ return /* @__PURE__ */ jsx(I, {
91
+ className: cn("size-3.5 shrink-0 text-kit-fg-4", className),
92
+ stroke: 1.75,
93
+ "aria-hidden": true
94
+ });
95
+ };
96
+ /** A ⋯ trigger: shown on hover / focus of its group, always on touch. */
97
+ var DOTS = "flex size-6 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 outline-none hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover data-[popup-open]:text-kit-fg";
98
+ var mapRow = (key, f) => (t) => ({
99
+ ...t,
100
+ rows: t.rows.map((r) => r._key === key ? f(r) : r)
101
+ });
102
+ var clean = (r) => {
103
+ const x = { ...r };
104
+ [
105
+ "group",
106
+ "footer",
107
+ "type",
108
+ "highlight"
109
+ ].forEach((k) => !x[k] && delete x[k]);
110
+ return x;
111
+ };
112
+ /** What a person typed → the cell. A value that doesn't fit its column (e.g. "Partly" in Yes / No) becomes a text cell. */
113
+ function typedCell(prev, col, row, raw) {
114
+ const colType = row.type ?? col.type;
115
+ const own = isCellObject(prev) ? prev.type : void 0;
116
+ const plain = raw.trim();
117
+ const note = cellNote(prev);
118
+ const fits = (ty) => !plain || (ty !== "number" && ty !== "money" && ty !== "rating" || toNumber(plain.replace(/(USD|EUR|GBP|JPY|INR|AUD|CAD|CHF)$/i, "")) != null) && (ty !== "boolean" || toBool(plain) != null);
119
+ let type = own;
120
+ if (own === "text" && fits(colType)) type = void 0;
121
+ else if (!own && !fits(colType)) type = "text";
122
+ const ty = type ?? colType;
123
+ let v;
124
+ if (ty === "link") {
125
+ const p = cellValue(prev);
126
+ const l = isObjLike(p) && !("ref" in p) ? p : null;
127
+ v = plain ? {
128
+ ...l ?? {},
129
+ label: plain,
130
+ href: l?.href ?? ""
131
+ } : null;
132
+ } else v = coerce(raw, {
133
+ type: ty,
134
+ max: col.max
135
+ });
136
+ return type || note ? {
137
+ value: v,
138
+ ...type ? { type } : {},
139
+ ...note ? { note } : {}
140
+ } : v;
141
+ }
142
+ /** Change a column's type; filled cells are re-read as the new type (words that don't fit become a text cell). */
143
+ function retype(t, key, type, resolveRef) {
144
+ const col = t.columns.find((c) => c._key === key);
145
+ if (!col || col.type === type) return t;
146
+ const next = {
147
+ ...col,
148
+ type,
149
+ ...type === "money" && !col.currency ? { currency: "USD" } : {}
150
+ };
151
+ if (type !== "number") delete next.unit;
152
+ if (type !== "money") delete next.currency;
153
+ if (type !== "rating") delete next.max;
154
+ if (type !== "boolean") {
155
+ delete next.trueLabel;
156
+ delete next.falseLabel;
157
+ }
158
+ if (type !== "reference") delete next.refTo;
159
+ if (type !== "number" && type !== "money") delete next.decimals;
160
+ return {
161
+ ...t,
162
+ columns: t.columns.map((c) => c._key === key ? next : c),
163
+ rows: t.rows.map((r) => {
164
+ const cell = r.cells[key];
165
+ if (isCellObject(cell) && cell.type || r.type) return r;
166
+ const v = cellValue(cell);
167
+ if (isEmptyCell(v)) return r;
168
+ const raw = col.type === "link" && isObjLike(v) ? v.label : col.type === "reference" && isObjLike(v) ? refLabel(v) : cellText(col, r, cell, resolveRef);
169
+ const written = type === "reference" ? raw ? {
170
+ value: raw,
171
+ type: "text"
172
+ } : null : typedCell(cell, next, r, raw);
173
+ return {
174
+ ...r,
175
+ cells: {
176
+ ...r.cells,
177
+ [key]: written
178
+ }
179
+ };
180
+ })
181
+ };
182
+ }
183
+ var displayRows = (t) => {
184
+ const { bodies, foot } = orderedRows(t);
185
+ const out = [];
186
+ bodies.forEach((b) => b.rows.forEach((row, i) => out.push({
187
+ row,
188
+ groupStart: i === 0 ? b.group : void 0
189
+ })));
190
+ foot.forEach((row, i) => out.push({
191
+ row,
192
+ footStart: i === 0
193
+ }));
194
+ return out;
195
+ };
196
+ /** Move a row to a displayed position; crossing into another group (or the totals) takes on that place. */
197
+ function moveRowTo(t, from, to) {
198
+ const order = displayRows(t).map((d) => d.row);
199
+ if (to < 0 || to >= order.length || from === to) return t;
200
+ const [r] = order.splice(from, 1);
201
+ const target = order[Math.min(to, order.length - 1)] ?? r;
202
+ order.splice(to, 0, clean({
203
+ ...r,
204
+ group: target.group,
205
+ footer: target.footer
206
+ }));
207
+ return {
208
+ ...t,
209
+ rows: order
210
+ };
211
+ }
212
+ var rowTitle = (t, r, i, resolveRef) => {
213
+ const c = t.columns[0];
214
+ return c && cellText(c, r, r.cells[c._key], resolveRef) || `Row ${i + 1}`;
215
+ };
216
+ var moveItem = (list, from, to) => {
217
+ const next = list.slice();
218
+ const [x] = next.splice(from, 1);
219
+ next.splice(to, 0, x);
220
+ return next;
221
+ };
222
+ var dropColumn = (t, key) => ({
223
+ ...t,
224
+ columns: t.columns.filter((c) => c._key !== key),
225
+ rows: t.rows.map((r) => ({
226
+ ...r,
227
+ cells: Object.fromEntries(Object.entries(r.cells).filter(([k]) => k !== key))
228
+ }))
229
+ });
230
+ var copyColumn = (t, i) => {
231
+ const c = t.columns[i];
232
+ const k = tkey("c");
233
+ const columns = [
234
+ ...t.columns.slice(0, i + 1),
235
+ {
236
+ ...c,
237
+ _key: k,
238
+ label: c.label ? `${c.label} copy` : "",
239
+ ...c.highlight ? { highlight: void 0 } : {}
240
+ },
241
+ ...t.columns.slice(i + 1)
242
+ ];
243
+ return {
244
+ ...t,
245
+ columns,
246
+ rows: t.rows.map((r) => r.cells[c._key] === void 0 ? r : {
247
+ ...r,
248
+ cells: {
249
+ ...r.cells,
250
+ [k]: r.cells[c._key]
251
+ }
252
+ })
253
+ };
254
+ };
255
+ /** CPO D49: the ONE way into the spreadsheet — opens it in the shared ExpandedEditorModal. Place it next to the title. */
256
+ function TableFullScreenButton({ onOpen, className }) {
257
+ return /* @__PURE__ */ jsx(IconButton, {
258
+ size: "sm",
259
+ label: "Edit in full screen",
260
+ className,
261
+ onClick: onOpen,
262
+ children: /* @__PURE__ */ jsx(IconArrowsMaximize, { stroke: 1.5 })
263
+ });
264
+ }
265
+ function TableEditor(props) {
266
+ const { value, onChange, readOnly, actions, label, options = GENERAL_TABLE, developer, resolveRef, nav, fullScreen } = props;
267
+ const t = React.useMemo(() => normalizeTable(value), [value]);
268
+ const [fullInner, setFullInner] = React.useState(false);
269
+ const full = fullScreen?.open ?? fullInner;
270
+ const setFull = fullScreen?.onOpenChange ?? setFullInner;
271
+ const root = React.useRef(null);
272
+ const { toast } = useKitServices();
273
+ const ctx = makeCtx({
274
+ t,
275
+ onChange,
276
+ options,
277
+ developer,
278
+ resolveRef,
279
+ readOnly,
280
+ toast
281
+ });
282
+ return /* @__PURE__ */ jsxs("div", {
283
+ ref: root,
284
+ className: "flex min-w-0 flex-col",
285
+ "data-table-editor": "",
286
+ onKeyDown: (e) => e.key !== "Escape" && !e.target.closest?.("[aria-roledescription=\"sortable\"]") && e.stopPropagation(),
287
+ onPaste: (e) => e.stopPropagation(),
288
+ onCut: (e) => e.stopPropagation(),
289
+ onCopy: (e) => e.stopPropagation(),
290
+ children: [/* @__PURE__ */ jsx(TableBody, {
291
+ ctx,
292
+ label,
293
+ nav,
294
+ head: /* @__PURE__ */ jsxs(Fragment, { children: [readOnly || fullScreen ? null : /* @__PURE__ */ jsx(TableFullScreenButton, {
295
+ className: "-my-1",
296
+ onOpen: () => setFull(true)
297
+ }), actions] })
298
+ }), /* @__PURE__ */ jsx(ExpandedEditorModal, {
299
+ open: full,
300
+ onOpenChange: setFull,
301
+ layout: "wide",
302
+ crumbs: [
303
+ props.parentTitle,
304
+ label || "Table",
305
+ t.caption || void 0
306
+ ].filter(Boolean),
307
+ meta: `${t.rows.length} ${t.rows.length === 1 ? "row" : "rows"} · ${t.columns.length} ${t.columns.length === 1 ? "column" : "columns"}`,
308
+ returnFocus: () => fullScreen?.returnFocus?.() ?? root.current?.querySelector("button[aria-label=\"Edit in full screen\"]") ?? null,
309
+ initialFocus: () => document.querySelector("[role=dialog] [data-cell=\"0:0\"], [role=dialog] [data-cell=\"-1:0\"]"),
310
+ children: full ? /* @__PURE__ */ jsx("div", {
311
+ "data-table-editor": "",
312
+ className: "flex min-h-0 flex-1 flex-col",
313
+ onPaste: (e) => e.stopPropagation(),
314
+ children: /* @__PURE__ */ jsx(Grid, {
315
+ ctx,
316
+ label,
317
+ full: true
318
+ })
319
+ }) : null
320
+ })]
321
+ });
322
+ }
323
+ function makeCtx({ t, onChange, options = {}, developer, resolveRef, readOnly, toast }) {
324
+ const types = Object.keys(TYPE_UI).filter((ty) => options.columnTypes ? options.columnTypes.includes(ty) : !TYPE_UI[ty].dev || developer);
325
+ return {
326
+ t,
327
+ set: onChange,
328
+ edit: (f) => onChange(f(t)),
329
+ options,
330
+ developer: !!developer,
331
+ types,
332
+ resolveRef,
333
+ lock: !!options.lockColumns || !!readOnly,
334
+ readOnly: !!readOnly,
335
+ undoable: (message, prev, description) => toast?.(message, {
336
+ description,
337
+ action: {
338
+ label: "Undo",
339
+ onClick: () => onChange(prev)
340
+ },
341
+ duration: 1e4
342
+ })
343
+ };
344
+ }
345
+ /**
346
+ * One row or one column of a table, as the body of a drilled frame (D50). The kit form shows it under the standard
347
+ * breadcrumb and frame header, exactly like an FAQ item; hosts without a form get the same body from TableEditor.
348
+ */
349
+ function TableItemEditor({ kind, index, value, onChange, options, developer, resolveRef, readOnly }) {
350
+ const t = React.useMemo(() => normalizeTable(value), [value]);
351
+ const { toast } = useKitServices();
352
+ const ctx = makeCtx({
353
+ t,
354
+ onChange,
355
+ options,
356
+ developer,
357
+ resolveRef,
358
+ readOnly,
359
+ toast
360
+ });
361
+ if (kind === "row") {
362
+ const row = t.rows[index];
363
+ return row ? /* @__PURE__ */ jsx(RowFields, {
364
+ ctx,
365
+ row
366
+ }) : /* @__PURE__ */ jsx(Gone, { kind: "row" });
367
+ }
368
+ const col = t.columns[index];
369
+ return col ? /* @__PURE__ */ jsx(ColumnFields, {
370
+ ctx,
371
+ col
372
+ }) : /* @__PURE__ */ jsx(Gone, { kind: "column" });
373
+ }
374
+ /** A frame restored onto a row or column that was deleted elsewhere says so, never an empty body. */
375
+ var Gone = ({ kind }) => /* @__PURE__ */ jsxs("p", {
376
+ role: "note",
377
+ className: "text-kit-sm text-kit-fg-3",
378
+ children: [
379
+ "This ",
380
+ kind,
381
+ " is no longer in the table."
382
+ ]
383
+ });
384
+ /** A column's minimum width: its longest header word + the type icon and ⋯ never break mid-word (≥ 96px, ≤ 240px). */
385
+ var colMinWidth = (c, full) => {
386
+ const longest = Math.max(0, ...c.label.split(/\s+/).map((w) => w.length));
387
+ return Math.min(240, Math.max(full ? 150 : 96, Math.ceil(longest * 7.6) + 58));
388
+ };
389
+ function Grid({ ctx, label, full }) {
390
+ const { t, set, lock, readOnly } = ctx;
391
+ const { toast } = useKitServices();
392
+ const rows = displayRows(t);
393
+ const cols = t.columns;
394
+ const host = React.useRef(null);
395
+ const pending = React.useRef(null);
396
+ const [, bump] = React.useReducer((n) => n + 1, 0);
397
+ const focus = (r, c) => {
398
+ pending.current = `${r}:${c}`;
399
+ bump();
400
+ };
401
+ React.useLayoutEffect(() => {
402
+ const p = pending.current;
403
+ if (!p) return;
404
+ const el = host.current?.querySelector(`[data-cell="${p}"]`);
405
+ if (!el) return;
406
+ pending.current = null;
407
+ el.focus({ preventScroll: true });
408
+ el.scrollIntoView?.({
409
+ block: "nearest",
410
+ inline: "nearest"
411
+ });
412
+ if (el instanceof HTMLTextAreaElement) el.setSelectionRange(el.value.length, el.value.length);
413
+ });
414
+ const bodyCount = t.rows.filter((r) => !r.footer).length;
415
+ const atMaxRows = !!ctx.options.maxRows && bodyCount >= ctx.options.maxRows;
416
+ const atMaxCols = !!ctx.options.maxColumns && cols.length >= ctx.options.maxColumns;
417
+ const addRow = (at = rows.length) => {
418
+ if (readOnly) return;
419
+ const anchor = rows[Math.min(at, rows.length) - 1]?.row;
420
+ const intoTotals = !!anchor?.footer && at < rows.length;
421
+ if (atMaxRows && !intoTotals) return toast?.("Limit reached", { description: `This table allows ${ctx.options.maxRows} rows at most.` });
422
+ const order = rows.map((d) => d.row);
423
+ order.splice(at, 0, {
424
+ _key: tkey("r"),
425
+ cells: {},
426
+ ...anchor?.group ? { group: anchor.group } : {},
427
+ ...intoTotals ? { footer: true } : {}
428
+ });
429
+ set({
430
+ ...t,
431
+ rows: order
432
+ });
433
+ focus(at, 0);
434
+ };
435
+ const addCol = (at = cols.length) => {
436
+ if (lock) return;
437
+ if (atMaxCols) return toast?.("Limit reached", { description: `This table allows ${ctx.options.maxColumns} columns at most.` });
438
+ const next = [...cols];
439
+ next.splice(at, 0, {
440
+ _key: tkey("c"),
441
+ label: "",
442
+ type: "text"
443
+ });
444
+ set({
445
+ ...t,
446
+ columns: next
447
+ });
448
+ focus(-1, at);
449
+ };
450
+ const move = (from, dir) => {
451
+ const r = from.r + (dir === "down" ? 1 : dir === "up" ? -1 : 0);
452
+ const c = from.c + (dir === "right" ? 1 : dir === "left" ? -1 : 0);
453
+ if (c < 0 || c >= cols.length || r < -1) return;
454
+ if (r >= rows.length) return addRow();
455
+ focus(r, c);
456
+ };
457
+ const onPaste = (e, r, c) => {
458
+ if (readOnly) return false;
459
+ const html = e.clipboardData.getData("text/html");
460
+ const text = e.clipboardData.getData("text/plain");
461
+ let range = [];
462
+ if (html && /<table[\s>]/i.test(html) && typeof DOMParser !== "undefined") {
463
+ const tbl = new DOMParser().parseFromString(html, "text/html").querySelector("table");
464
+ if (tbl) range = tableToRows(parseTableElement(tbl)).slice(r < 0 ? 0 : 1);
465
+ }
466
+ if (!range.length && /[\t\n]/.test(text.trim())) range = parseDelimited(text);
467
+ if (!range.length) return false;
468
+ e.preventDefault();
469
+ const blank = t.rows.every((x) => Object.values(x.cells).every((v) => isEmptyCell(cellValue(v)))) && cols.every((x) => !x.label.trim());
470
+ let next;
471
+ if (blank && !lock && range.length > 1) {
472
+ const n = tableFromRows(range, { header: true });
473
+ next = {
474
+ ...t,
475
+ columns: n.columns,
476
+ rows: n.rows,
477
+ headerColumn: n.headerColumn || t.headerColumn
478
+ };
479
+ } else next = pasteRange({
480
+ ...t,
481
+ rows: rows.map((d) => d.row)
482
+ }, {
483
+ row: r,
484
+ col: c
485
+ }, range, { lockColumns: lock });
486
+ const body = next.rows.filter((x) => !x.footer).length;
487
+ if (ctx.options.maxRows && body > ctx.options.maxRows) {
488
+ toast?.("Paste not applied", { description: `It would make ${body} rows; this table allows ${ctx.options.maxRows}.` });
489
+ return true;
490
+ }
491
+ if (ctx.options.maxColumns && next.columns.length > ctx.options.maxColumns) {
492
+ toast?.("Paste not applied", { description: `It would make ${next.columns.length} columns; this table allows ${ctx.options.maxColumns}.` });
493
+ return true;
494
+ }
495
+ set(next);
496
+ toast?.(`Pasted ${range.length} ${range.length === 1 ? "row" : "rows"}`);
497
+ return true;
498
+ };
499
+ const drag = React.useRef(null);
500
+ const helpId = `${React.useId()}-grid-help`;
501
+ const [over, setOver] = React.useState(null);
502
+ const drop = (kind, i) => {
503
+ const d = drag.current;
504
+ drag.current = null;
505
+ setOver(null);
506
+ if (!d || d.kind !== kind || d.i === i) return;
507
+ if (kind === "row") set(moveRowTo(t, d.i, i));
508
+ else if (!lock) set({
509
+ ...t,
510
+ columns: moveItem(cols, d.i, i)
511
+ });
512
+ };
513
+ return /* @__PURE__ */ jsxs("div", {
514
+ ref: host,
515
+ className: cn("min-w-0 overflow-x-auto rounded-kit-lg border border-kit-line bg-kit-surface", full && "max-h-full min-h-0 flex-1 overflow-auto"),
516
+ "data-full": full ? "" : void 0,
517
+ children: [
518
+ /* @__PURE__ */ jsxs("table", {
519
+ role: "grid",
520
+ "aria-label": label || t.caption || "Table",
521
+ "aria-describedby": helpId,
522
+ className: "w-full border-separate border-spacing-0 text-kit-sm",
523
+ children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
524
+ /* @__PURE__ */ jsx("th", {
525
+ className: cn("w-8 border-b border-kit-line bg-kit-subtle", full && "sticky left-0 top-0 z-[3]"),
526
+ "aria-hidden": true
527
+ }),
528
+ cols.map((c, ci) => /* @__PURE__ */ jsx("th", {
529
+ scope: "col",
530
+ style: { minWidth: colMinWidth(c, full) },
531
+ className: cn("group/col relative border-b border-l border-kit-line bg-kit-subtle p-0 text-left align-bottom font-medium", full && "sticky top-0 z-[2]", full && ci === 0 && "left-8 z-[3]", over?.kind === "col" && over.i === ci && "shadow-[inset_2px_0_0_var(--kit-fg-2)]"),
532
+ onDragOver: (e) => drag.current?.kind === "col" && (e.preventDefault(), setOver({
533
+ kind: "col",
534
+ i: ci
535
+ })),
536
+ onDrop: () => drop("col", ci),
537
+ children: /* @__PURE__ */ jsx(ColumnMenu, {
538
+ ctx,
539
+ col: c,
540
+ index: ci,
541
+ onInsert: (right) => addCol(right ? ci + 1 : ci),
542
+ children: (openMenu) => /* @__PURE__ */ jsxs(Fragment, { children: [
543
+ lock ? null : /* @__PURE__ */ jsx("span", {
544
+ draggable: true,
545
+ onDragStart: (e) => (drag.current = {
546
+ kind: "col",
547
+ i: ci
548
+ }, e.dataTransfer.setData("text/plain", c.label)),
549
+ className: "-ml-1 hidden cursor-grab text-kit-fg-4 group-hover/col:block",
550
+ "aria-hidden": true,
551
+ children: /* @__PURE__ */ jsx(IconGripVertical, {
552
+ className: "size-3.5",
553
+ stroke: 1.5
554
+ })
555
+ }),
556
+ /* @__PURE__ */ jsx(TypeIcon, { type: c.type }),
557
+ /* @__PURE__ */ jsx(CellInput, {
558
+ cell: `-1:${ci}`,
559
+ value: c.label,
560
+ display: c.label,
561
+ placeholder: ci === 0 && t.headerColumn ? "Row names" : "Column name",
562
+ readOnly: lock,
563
+ className: cn("font-medium text-kit-fg", !t.headerRow && "text-kit-fg-3"),
564
+ ariaLabel: `Column ${ci + 1} name${t.headerRow ? "" : " (not shown on the page)"}`,
565
+ onCommit: (v) => set({
566
+ ...t,
567
+ columns: t.columns.map((x) => x._key === c._key ? {
568
+ ...x,
569
+ label: v.replace(/\s+/g, " ").trim()
570
+ } : x)
571
+ }),
572
+ onMove: (dir) => move({
573
+ r: -1,
574
+ c: ci
575
+ }, dir),
576
+ onMenu: openMenu,
577
+ onPaste: (e) => onPaste(e, -1, ci)
578
+ })
579
+ ] })
580
+ })
581
+ }, c._key)),
582
+ /* @__PURE__ */ jsx("th", {
583
+ className: "w-9 border-b border-l border-kit-line bg-kit-subtle p-0",
584
+ children: lock ? null : /* @__PURE__ */ jsx(IconButton, {
585
+ size: "xs",
586
+ label: "Add column",
587
+ className: "mx-auto",
588
+ disabled: atMaxCols,
589
+ onClick: () => addCol(),
590
+ children: /* @__PURE__ */ jsx(IconPlus, { stroke: 1.75 })
591
+ })
592
+ })
593
+ ] }) }), /* @__PURE__ */ jsx("tbody", { children: rows.map(({ row, groupStart, footStart }, ri) => /* @__PURE__ */ jsxs(React.Fragment, { children: [groupStart || footStart ? /* @__PURE__ */ jsx("tr", {
594
+ "aria-hidden": true,
595
+ children: /* @__PURE__ */ jsx("td", {
596
+ colSpan: cols.length + 2,
597
+ className: "border-t border-kit-line bg-[var(--kit-subtle-2)] px-2 py-1 text-kit-2xs font-medium text-kit-fg-3",
598
+ children: groupStart ? groupStart.label || "Untitled group" : "Totals"
599
+ })
600
+ }) : null, /* @__PURE__ */ jsxs("tr", {
601
+ className: cn("group/row", over?.kind === "row" && over.i === ri && "shadow-[inset_0_2px_0_var(--kit-fg-2)]"),
602
+ onDragOver: (e) => drag.current?.kind === "row" && (e.preventDefault(), setOver({
603
+ kind: "row",
604
+ i: ri
605
+ })),
606
+ onDrop: () => drop("row", ri),
607
+ children: [
608
+ /* @__PURE__ */ jsx("td", {
609
+ className: cn("w-8 border-t border-kit-line bg-[var(--kit-subtle-2)] p-0 align-middle", full && "sticky left-0 z-[1] bg-kit-subtle"),
610
+ children: readOnly ? /* @__PURE__ */ jsx("div", {
611
+ className: "flex h-8 items-center justify-center text-kit-2xs text-kit-fg-4",
612
+ children: ri + 1
613
+ }) : /* @__PURE__ */ jsx(RowMenu, {
614
+ ctx,
615
+ row,
616
+ index: ri,
617
+ count: rows.length,
618
+ onInsert: (below) => addRow(below ? ri + 1 : ri),
619
+ children: (trigger) => /* @__PURE__ */ jsxs("div", {
620
+ draggable: true,
621
+ onDragStart: (e) => (drag.current = {
622
+ kind: "row",
623
+ i: ri
624
+ }, e.dataTransfer.setData("text/plain", String(ri))),
625
+ className: "flex h-8 cursor-grab items-center justify-center text-kit-2xs text-kit-fg-4",
626
+ children: [/* @__PURE__ */ jsx("span", {
627
+ className: "group-hover/row:hidden group-focus-within/row:hidden",
628
+ children: ri + 1
629
+ }), /* @__PURE__ */ jsx("span", {
630
+ className: "hidden group-hover/row:flex group-focus-within/row:flex",
631
+ children: trigger
632
+ })]
633
+ })
634
+ })
635
+ }),
636
+ cols.map((c, ci) => /* @__PURE__ */ jsx(GridCell, {
637
+ full,
638
+ ctx,
639
+ row,
640
+ col: c,
641
+ r: ri,
642
+ c: ci,
643
+ onMove: (dir) => move({
644
+ r: ri,
645
+ c: ci
646
+ }, dir),
647
+ onPaste: (e) => onPaste(e, ri, ci)
648
+ }, c._key)),
649
+ /* @__PURE__ */ jsx("td", { className: "border-l border-t border-kit-line" })
650
+ ]
651
+ })] }, row._key)) })]
652
+ }),
653
+ /* @__PURE__ */ jsx("p", {
654
+ id: helpId,
655
+ className: "sr-only",
656
+ children: "Tab and the arrow keys move between cells. Shift+F10 on a column, row or cell opens its options."
657
+ }),
658
+ readOnly ? null : /* @__PURE__ */ jsxs("button", {
659
+ type: "button",
660
+ onClick: () => addRow(),
661
+ disabled: atMaxRows,
662
+ className: "flex h-8 w-full items-center gap-1.5 border-t border-kit-line px-2.5 text-left text-kit-xs text-kit-fg-3 hover:bg-kit-subtle hover:text-kit-fg disabled:opacity-45",
663
+ children: [
664
+ /* @__PURE__ */ jsx(IconPlus, {
665
+ className: "size-3.5",
666
+ stroke: 1.75,
667
+ "aria-hidden": true
668
+ }),
669
+ " ",
670
+ atMaxRows ? `Add row · ${ctx.options.maxRows} at most` : "Add row"
671
+ ]
672
+ })
673
+ ]
674
+ });
675
+ }
676
+ /** A grid cell: always editable (no select-then-edit mode). Yes / No is a check toggle; links and references open a small editor. */
677
+ function GridCell({ ctx, row, col, r, c, onMove, onPaste, full }) {
678
+ const { t, edit, resolveRef, readOnly } = ctx;
679
+ const cell = row.cells[col._key];
680
+ const v = cellValue(cell);
681
+ const declared = cellType(col, row, cell);
682
+ const ty = declared === "boolean" && !isEmptyCell(v) && toBool(v) == null ? "text" : declared;
683
+ const write = (next) => edit(mapRow(row._key, (x) => ({
684
+ ...x,
685
+ cells: {
686
+ ...x.cells,
687
+ [col._key]: next ?? null
688
+ }
689
+ })));
690
+ const head = t.headerColumn && c === 0;
691
+ const note = cellNote(cell);
692
+ const n = note ? (t.footnotes ?? []).findIndex((f) => f._key === note) + 1 : 0;
693
+ const fn = note ? (t.footnotes ?? []).find((f) => f._key === note) : void 0;
694
+ const [noteOpen, setNoteOpen] = React.useState(false);
695
+ const name = `${col.label || `Column ${c + 1}`}, ${rowTitle(t, row, r, resolveRef)}`;
696
+ let body;
697
+ if (ty === "boolean") {
698
+ const b = toBool(v);
699
+ const { yes, no } = boolLabels(col);
700
+ body = /* @__PURE__ */ jsx("button", {
701
+ type: "button",
702
+ role: "checkbox",
703
+ "aria-checked": b === true,
704
+ "aria-label": `${name}: ${b == null ? "not set" : b ? yes : no}`,
705
+ "aria-readonly": readOnly || void 0,
706
+ "data-cell": `${r}:${c}`,
707
+ onClick: () => !readOnly && write(withValue(cell, b !== true)),
708
+ onKeyDown: (e) => {
709
+ const k = e.key;
710
+ if (k === "ArrowUp" || k === "ArrowDown" || k === "ArrowLeft" || k === "ArrowRight") {
711
+ e.preventDefault();
712
+ onMove(k.slice(5).toLowerCase());
713
+ } else if (k === "Enter") {
714
+ e.preventDefault();
715
+ onMove("down");
716
+ } else if (readOnly) return;
717
+ else if (k === "Delete" || k === "Backspace") {
718
+ e.preventDefault();
719
+ write(withValue(cell, null));
720
+ } else if (/^[yn]$/i.test(k)) {
721
+ e.preventDefault();
722
+ write(withValue(cell, /y/i.test(k)));
723
+ }
724
+ },
725
+ onPaste: (e) => onPaste(e),
726
+ className: "flex h-8 w-full items-center px-2 outline-none focus-visible:shadow-[inset_0_0_0_2px_var(--kit-fg-3)]",
727
+ children: b == null ? /* @__PURE__ */ jsx("span", {
728
+ className: "text-kit-fg-4",
729
+ children: "—"
730
+ }) : /* @__PURE__ */ jsx("span", {
731
+ className: cn("flex size-4 items-center justify-center rounded-kit-sm border", b ? "border-kit-inverse bg-kit-inverse text-kit-fg-inverse" : "border-kit-line-strong"),
732
+ children: b ? /* @__PURE__ */ jsx(IconCheck, {
733
+ className: "size-3",
734
+ stroke: 3,
735
+ "aria-hidden": true
736
+ }) : null
737
+ })
738
+ });
739
+ } else if (ty === "reference") body = /* @__PURE__ */ jsx(RefCell, {
740
+ ctx,
741
+ cell,
742
+ col,
743
+ cellId: `${r}:${c}`,
744
+ name,
745
+ onWrite: write,
746
+ onMove
747
+ });
748
+ else {
749
+ const draft = isEmptyCell(v) ? "" : NUMERIC.includes(ty) ? String(toNumber(v) ?? cellText(col, row, cell)) : ty === "link" && isObjLike(v) ? v.label : ty === "richtext-inline" ? String(v) : cellText(col, row, cell, resolveRef);
750
+ const link = ty === "link" ? isObjLike(v) && !("ref" in v) ? v : {
751
+ label: typeof v === "string" ? v : "",
752
+ href: ""
753
+ } : null;
754
+ body = /* @__PURE__ */ jsxs("div", {
755
+ className: "relative flex items-start",
756
+ children: [
757
+ ty === "rating" && !isEmptyCell(v) ? /* @__PURE__ */ jsx(IconStar, {
758
+ className: "ml-2 mt-2 size-3 shrink-0 text-kit-warning",
759
+ stroke: 2,
760
+ "aria-hidden": true
761
+ }) : null,
762
+ /* @__PURE__ */ jsx(CellInput, {
763
+ cell: `${r}:${c}`,
764
+ value: draft,
765
+ display: isEmptyCell(v) ? "" : ty === "rating" ? draft : cellText(col, row, cell, resolveRef),
766
+ placeholder: "—",
767
+ numeric: NUMERIC.includes(ty),
768
+ readOnly,
769
+ className: cn(head && "font-medium", NUMERIC.includes(ty) && "text-right tabular-nums"),
770
+ ariaLabel: name,
771
+ onCommit: (raw) => raw !== draft && write(typedCell(cell, col, row, raw)),
772
+ onMove,
773
+ onPaste
774
+ }),
775
+ link ? /* @__PURE__ */ jsx(LinkAddressButton, {
776
+ className: "mr-1 mt-1.5",
777
+ link,
778
+ readOnly,
779
+ onSave: (l) => write(withValue(cell, l))
780
+ }) : null
781
+ ]
782
+ });
783
+ }
784
+ return /* @__PURE__ */ jsxs("td", {
785
+ className: cn("relative border-l border-t border-kit-line p-0 align-top", head && "bg-[var(--kit-subtle-2)]", full && c === 0 && "sticky left-8 z-[1] bg-kit-surface", row.highlight && "bg-kit-accent-softer", col.highlight && "bg-kit-subtle"),
786
+ children: [readOnly ? body : /* @__PURE__ */ jsx(CellMenu, {
787
+ ctx,
788
+ row,
789
+ col,
790
+ cell,
791
+ onWrite: write,
792
+ onNote: () => window.setTimeout(() => setNoteOpen(true)),
793
+ children: body
794
+ }), /* @__PURE__ */ jsxs(Popover, {
795
+ open: noteOpen && !!fn,
796
+ onOpenChange: setNoteOpen,
797
+ children: [/* @__PURE__ */ jsx(PopoverAnchor, {
798
+ render: n > 0 ? /* @__PURE__ */ jsx("button", {
799
+ type: "button",
800
+ tabIndex: -1,
801
+ "aria-label": `Footnote ${n}`,
802
+ onClick: () => setNoteOpen(true),
803
+ className: "absolute right-0.5 top-0.5 rounded-kit-xs px-0.5 text-kit-2xs leading-3 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg"
804
+ }) : /* @__PURE__ */ jsx("span", {
805
+ className: "pointer-events-none absolute right-1 top-1 size-0",
806
+ "aria-hidden": true
807
+ }),
808
+ children: n > 0 ? n : null
809
+ }), /* @__PURE__ */ jsx(PopoverContent, {
810
+ align: "end",
811
+ className: "w-72 p-2",
812
+ children: fn ? /* @__PURE__ */ jsx(Input, {
813
+ size: "sm",
814
+ autoFocus: true,
815
+ value: fn.text,
816
+ readOnly,
817
+ placeholder: "What the footnote says",
818
+ "aria-label": `Footnote ${n}`,
819
+ onChange: (e) => ctx.set({
820
+ ...t,
821
+ footnotes: (t.footnotes ?? []).map((x) => x._key === fn._key ? {
822
+ ...x,
823
+ text: e.target.value
824
+ } : x)
825
+ }),
826
+ onKeyDown: (e) => e.key === "Enter" && (e.preventDefault(), setNoteOpen(false))
827
+ }) : null
828
+ })]
829
+ })]
830
+ });
831
+ }
832
+ /** One cell's text. Shows the written value at rest ("$39", "2.4 kg") and the raw value while typing; commits on leave. */
833
+ function CellInput({ cell, value, display, onCommit, onMove, onMenu, onPaste, placeholder, numeric, className, ariaLabel, readOnly }) {
834
+ const [focused, setFocused] = React.useState(false);
835
+ const [draft, setDraft] = React.useState(value);
836
+ const ref = React.useRef(null);
837
+ const shown = focused ? draft : display;
838
+ React.useLayoutEffect(() => {
839
+ const el = ref.current;
840
+ if (!el) return;
841
+ el.style.height = "0px";
842
+ el.style.height = `${Math.max(32, el.scrollHeight)}px`;
843
+ }, [shown]);
844
+ return /* @__PURE__ */ jsx("textarea", {
845
+ ref,
846
+ rows: 1,
847
+ "data-cell": cell,
848
+ "data-cell-editing": focused && draft !== value ? "" : void 0,
849
+ value: shown,
850
+ readOnly,
851
+ placeholder,
852
+ "aria-label": ariaLabel,
853
+ inputMode: numeric ? "decimal" : void 0,
854
+ spellCheck: !numeric,
855
+ onFocus: () => {
856
+ setDraft(value);
857
+ setFocused(true);
858
+ },
859
+ onBlur: () => {
860
+ setFocused(false);
861
+ if (!readOnly && draft !== value) onCommit(draft);
862
+ },
863
+ onChange: (e) => setDraft(e.target.value),
864
+ onPaste: (e) => onPaste?.(e),
865
+ onKeyDown: (e) => {
866
+ const el = e.currentTarget;
867
+ const k = e.key;
868
+ const atStart = el.selectionStart === 0 && el.selectionEnd === 0;
869
+ const atEnd = el.selectionStart === el.value.length && el.selectionEnd === el.value.length;
870
+ const oneLine = !el.value.includes("\n");
871
+ if (k === "F10" && e.shiftKey || k === "ContextMenu") {
872
+ if (onMenu) {
873
+ e.preventDefault();
874
+ onMenu();
875
+ }
876
+ } else if (k === "Enter" && !e.shiftKey && !e.nativeEvent.isComposing) {
877
+ e.preventDefault();
878
+ onMove("down");
879
+ } else if (k === "Escape" && draft !== value) {
880
+ e.preventDefault();
881
+ e.stopPropagation();
882
+ setDraft(value);
883
+ } else if (k === "ArrowUp" && (oneLine || atStart)) {
884
+ e.preventDefault();
885
+ onMove("up");
886
+ } else if (k === "ArrowDown" && (oneLine || atEnd)) {
887
+ e.preventDefault();
888
+ onMove("down");
889
+ } else if (k === "ArrowLeft" && atStart) {
890
+ e.preventDefault();
891
+ onMove("left");
892
+ } else if (k === "ArrowRight" && atEnd) {
893
+ e.preventDefault();
894
+ onMove("right");
895
+ }
896
+ },
897
+ className: cn("block min-h-8 w-full resize-none overflow-hidden bg-transparent px-2 py-1.5 text-kit-sm leading-5 text-kit-fg outline-none [overflow-wrap:normal] [word-break:normal] placeholder:text-kit-fg-4 focus:bg-kit-surface focus:shadow-[inset_0_0_0_2px_var(--kit-fg-3)]", className)
898
+ });
899
+ }
900
+ /**
901
+ * A reference cell: a page or entry chosen from the host's search (refs.ts). Stores `{ ref, label, href? }`: the label and
902
+ * public path travel with the id so the published table reads without a lookup.
903
+ */
904
+ function RefCell({ ctx, cell, col, cellId, name, onWrite, onMove }) {
905
+ const [open, setOpen] = React.useState(false);
906
+ const [q, setQ] = React.useState("");
907
+ const v = cellValue(cell);
908
+ const r = isObjLike(v) && "ref" in v ? v : null;
909
+ const label = r ? ctx.resolveRef?.(r.ref)?.label ?? refLabel(r) : typeof v === "string" ? v : "";
910
+ const search = useRefSearch(open, col.refTo?.length ? col.refTo : null, q);
911
+ const pick = (o) => {
912
+ onWrite(withValue(cell, {
913
+ ref: o.id,
914
+ label: o.title,
915
+ ...o.href ? { href: o.href } : {}
916
+ }));
917
+ setOpen(false);
918
+ };
919
+ return /* @__PURE__ */ jsxs(Popover, {
920
+ open,
921
+ onOpenChange: (o) => (setOpen(o), o || setQ("")),
922
+ children: [/* @__PURE__ */ jsx(PopoverAnchor, {
923
+ render: /* @__PURE__ */ jsx("button", {
924
+ type: "button",
925
+ "data-cell": cellId,
926
+ "aria-label": `${name}: ${label || "not chosen"}`,
927
+ "aria-haspopup": "dialog",
928
+ disabled: ctx.readOnly,
929
+ onClick: () => setOpen(true),
930
+ onKeyDown: (e) => {
931
+ const k = e.key;
932
+ if (k.startsWith("Arrow")) {
933
+ e.preventDefault();
934
+ onMove(k.slice(5).toLowerCase());
935
+ } else if (!ctx.readOnly && (k === "Delete" || k === "Backspace") && !isEmptyCell(v)) {
936
+ e.preventDefault();
937
+ onWrite(withValue(cell, null));
938
+ }
939
+ },
940
+ className: "flex min-h-8 w-full items-center px-2 text-left text-kit-sm text-kit-fg outline-none focus-visible:shadow-[inset_0_0_0_2px_var(--kit-fg-3)]"
941
+ }),
942
+ children: label ? /* @__PURE__ */ jsx("span", {
943
+ className: "truncate underline decoration-kit-fg-4 underline-offset-2",
944
+ children: label
945
+ }) : /* @__PURE__ */ jsx("span", {
946
+ className: "text-kit-fg-4",
947
+ children: "Choose…"
948
+ })
949
+ }), /* @__PURE__ */ jsxs(PopoverContent, {
950
+ align: "start",
951
+ className: "w-72 p-1.5",
952
+ children: [
953
+ /* @__PURE__ */ jsx(Input, {
954
+ size: "sm",
955
+ autoFocus: true,
956
+ value: q,
957
+ placeholder: "Search…",
958
+ "aria-label": "Find a page or entry",
959
+ onChange: (e) => setQ(e.target.value)
960
+ }),
961
+ /* @__PURE__ */ jsx("div", {
962
+ role: "status",
963
+ className: "sr-only",
964
+ children: search.status === "ready" ? `${search.options.length} results` : search.status === "loading" ? "Searching" : ""
965
+ }),
966
+ /* @__PURE__ */ jsxs("ul", {
967
+ className: "mt-1 max-h-56 overflow-auto",
968
+ "aria-label": "Pages and entries",
969
+ children: [
970
+ search.status === "ready" ? search.options.map((o) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("button", {
971
+ type: "button",
972
+ className: "flex w-full flex-col rounded-kit-md px-2 py-1.5 text-left hover:bg-kit-hover",
973
+ onClick: () => pick(o),
974
+ children: [/* @__PURE__ */ jsx("span", {
975
+ className: "truncate text-kit-sm text-kit-fg",
976
+ children: o.title
977
+ }), o.subtitle ? /* @__PURE__ */ jsx("span", {
978
+ className: "truncate text-kit-xs text-kit-fg-3",
979
+ children: o.subtitle
980
+ }) : null]
981
+ }) }, o.id)) : null,
982
+ search.status === "ready" && !search.options.length ? /* @__PURE__ */ jsxs("li", {
983
+ className: "px-2 py-1.5 text-kit-xs text-kit-fg-3",
984
+ children: [
985
+ "Nothing found",
986
+ q.trim() ? ` for “${q.trim()}”` : "",
987
+ "."
988
+ ]
989
+ }) : null,
990
+ search.status === "loading" ? /* @__PURE__ */ jsx("li", {
991
+ className: "px-2 py-1.5 text-kit-xs text-kit-fg-3",
992
+ children: "Searching…"
993
+ }) : null,
994
+ search.status === "error" ? /* @__PURE__ */ jsxs("li", {
995
+ role: "alert",
996
+ className: "px-2 py-1.5 text-kit-xs text-kit-danger-fg",
997
+ children: ["Couldn't search: ", search.message]
998
+ }) : null,
999
+ search.status === "unavailable" ? /* @__PURE__ */ jsx("li", {
1000
+ role: "note",
1001
+ className: "px-2 py-1.5 text-kit-xs text-kit-fg-3",
1002
+ children: "This view can't search pages or entries, so the cell can't change here."
1003
+ }) : null
1004
+ ]
1005
+ }),
1006
+ r && !ctx.readOnly ? /* @__PURE__ */ jsx(Button, {
1007
+ size: "sm",
1008
+ variant: "ghost",
1009
+ className: "mt-1 w-full justify-start text-kit-fg-2",
1010
+ onClick: () => (onWrite(withValue(cell, null)), setOpen(false)),
1011
+ children: "Clear"
1012
+ }) : null
1013
+ ]
1014
+ })]
1015
+ });
1016
+ }
1017
+ function ColumnMenu({ ctx, col, index, onInsert, children }) {
1018
+ const { t, set, edit, lock, types, readOnly } = ctx;
1019
+ const [open, setOpen] = React.useState(false);
1020
+ const [details, setDetails] = React.useState(false);
1021
+ const n = t.columns.length;
1022
+ const atMax = !!ctx.options.maxColumns && n >= ctx.options.maxColumns;
1023
+ const remove = () => {
1024
+ if (n <= 1) return;
1025
+ const prev = t;
1026
+ set(dropColumn(t, col._key));
1027
+ ctx.undoable("Column deleted", prev);
1028
+ };
1029
+ const shownTypes = types.includes(col.type) ? types : [...types, col.type];
1030
+ const hasDetails = !lock && (col.type === "number" || col.type === "money" || col.type === "boolean" || col.type === "rating");
1031
+ return /* @__PURE__ */ jsxs(Popover, {
1032
+ open: details,
1033
+ onOpenChange: setDetails,
1034
+ children: [/* @__PURE__ */ jsxs(PopoverAnchor, {
1035
+ render: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 pl-1.5 pr-0.5" }),
1036
+ children: [/* @__PURE__ */ jsx("div", {
1037
+ className: "flex min-w-0 flex-1 items-center gap-1",
1038
+ children: children(() => setOpen(true))
1039
+ }), readOnly ? null : /* @__PURE__ */ jsxs(Menu, {
1040
+ open,
1041
+ onOpenChange: setOpen,
1042
+ children: [/* @__PURE__ */ jsx(MenuTrigger, {
1043
+ tabIndex: -1,
1044
+ "aria-label": `Options for column ${col.label || index + 1}`,
1045
+ className: cn(DOTS, "opacity-0 focus-visible:opacity-100 group-hover/col:opacity-100 group-focus-within/col:opacity-100 data-[popup-open]:opacity-100 [@media(pointer:coarse)]:opacity-100"),
1046
+ children: /* @__PURE__ */ jsx(IconDots, {
1047
+ className: "size-3.5",
1048
+ stroke: 1.5
1049
+ })
1050
+ }), /* @__PURE__ */ jsxs(MenuContent, {
1051
+ align: "end",
1052
+ className: "min-w-52",
1053
+ children: [
1054
+ lock ? null : /* @__PURE__ */ jsxs(MenuSub, { children: [/* @__PURE__ */ jsxs(MenuSubTrigger, {
1055
+ icon: /* @__PURE__ */ jsx(TypeIcon, {
1056
+ type: col.type,
1057
+ className: "text-kit-fg-2"
1058
+ }),
1059
+ children: ["Type: ", TYPE_UI[col.type].label]
1060
+ }), /* @__PURE__ */ jsx(MenuSubContent, { children: /* @__PURE__ */ jsx(MenuRadioGroup, {
1061
+ value: col.type,
1062
+ onValueChange: (v) => edit((x) => retype(x, col._key, v, ctx.resolveRef)),
1063
+ children: shownTypes.map((ty) => /* @__PURE__ */ jsx(MenuRadioItem, {
1064
+ value: ty,
1065
+ children: /* @__PURE__ */ jsxs("span", {
1066
+ className: "flex items-center gap-2",
1067
+ children: [/* @__PURE__ */ jsx(TypeIcon, {
1068
+ type: ty,
1069
+ className: "text-kit-fg-2"
1070
+ }), TYPE_UI[ty].label]
1071
+ })
1072
+ }, ty))
1073
+ }) })] }),
1074
+ hasDetails ? /* @__PURE__ */ jsx(MenuItem, {
1075
+ onClick: () => window.setTimeout(() => setDetails(true)),
1076
+ children: col.type === "number" ? "Unit…" : col.type === "money" ? "Currency…" : col.type === "rating" ? "Scale…" : "Words for yes and no…"
1077
+ }) : null,
1078
+ lock ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
1079
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
1080
+ /* @__PURE__ */ jsx(MenuItem, {
1081
+ disabled: atMax,
1082
+ onClick: () => onInsert(false),
1083
+ children: "Insert column left"
1084
+ }),
1085
+ /* @__PURE__ */ jsx(MenuItem, {
1086
+ disabled: atMax,
1087
+ onClick: () => onInsert(true),
1088
+ children: "Insert column right"
1089
+ }),
1090
+ /* @__PURE__ */ jsx(MenuItem, {
1091
+ disabled: atMax,
1092
+ onClick: () => set(copyColumn(t, index)),
1093
+ children: "Duplicate column"
1094
+ }),
1095
+ /* @__PURE__ */ jsx(MenuItem, {
1096
+ disabled: index === 0,
1097
+ onClick: () => set({
1098
+ ...t,
1099
+ columns: moveItem(t.columns, index, index - 1)
1100
+ }),
1101
+ children: "Move left"
1102
+ }),
1103
+ /* @__PURE__ */ jsx(MenuItem, {
1104
+ disabled: index === n - 1,
1105
+ onClick: () => set({
1106
+ ...t,
1107
+ columns: moveItem(t.columns, index, index + 1)
1108
+ }),
1109
+ children: "Move right"
1110
+ })
1111
+ ] }),
1112
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
1113
+ /* @__PURE__ */ jsx(MenuCheckItem, {
1114
+ checked: t.headerRow,
1115
+ onCheckedChange: (v) => set({
1116
+ ...t,
1117
+ headerRow: v
1118
+ }),
1119
+ children: "Show column names"
1120
+ }),
1121
+ /* @__PURE__ */ jsx(MenuCheckItem, {
1122
+ checked: t.headerColumn,
1123
+ onCheckedChange: (v) => set({
1124
+ ...t,
1125
+ headerColumn: v
1126
+ }),
1127
+ children: "First column names each row"
1128
+ }),
1129
+ /* @__PURE__ */ jsx(MenuCheckItem, {
1130
+ checked: !!col.highlight,
1131
+ onCheckedChange: (v) => set({
1132
+ ...t,
1133
+ columns: t.columns.map((c) => ({
1134
+ ...c,
1135
+ highlight: c._key === col._key && v ? true : void 0
1136
+ }))
1137
+ }),
1138
+ children: "Highlight this column"
1139
+ }),
1140
+ lock ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MenuSeparator, {}), /* @__PURE__ */ jsx(MenuItem, {
1141
+ danger: true,
1142
+ disabled: n <= 1,
1143
+ onClick: remove,
1144
+ children: n <= 1 ? "Delete column · a table keeps one" : "Delete column"
1145
+ })] })
1146
+ ]
1147
+ })]
1148
+ })]
1149
+ }), /* @__PURE__ */ jsx(PopoverContent, {
1150
+ align: "end",
1151
+ className: "w-64 p-3",
1152
+ children: /* @__PURE__ */ jsx(ColumnDetails, {
1153
+ col,
1154
+ onPatch: (p) => set({
1155
+ ...t,
1156
+ columns: t.columns.map((c) => c._key === col._key ? withPatch(c, p) : c)
1157
+ })
1158
+ })
1159
+ })]
1160
+ });
1161
+ }
1162
+ /** A stored TableLink as the global link field's value (V2 tableLinkValue). */
1163
+ var tableLinkValue = (l) => ({
1164
+ ...normLink(l.href),
1165
+ newTab: !!l.newTab,
1166
+ target: l.newTab ? "_blank" : "_self",
1167
+ rel: l.rel ?? "follow"
1168
+ });
1169
+ /** Patch a column; a key set to undefined is removed (the stored value never carries an empty key). */
1170
+ function withPatch(c, p) {
1171
+ const next = {
1172
+ ...c,
1173
+ ...p
1174
+ };
1175
+ for (const k of Object.keys(p)) if (next[k] === void 0) delete next[k];
1176
+ return next;
1177
+ }
1178
+ function ColumnDetails({ col, onPatch, compact = true, readOnly }) {
1179
+ const id = React.useId();
1180
+ const row = (key, label, node, help) => /* @__PURE__ */ jsxs("label", {
1181
+ htmlFor: `${id}-${key}`,
1182
+ className: cn("flex flex-col", compact ? "gap-1" : "gap-1.5"),
1183
+ children: [
1184
+ /* @__PURE__ */ jsx("span", {
1185
+ className: cn("font-medium text-kit-fg-2", compact ? "text-kit-xs" : "text-kit-sm"),
1186
+ children: label
1187
+ }),
1188
+ node,
1189
+ help ? /* @__PURE__ */ jsx("span", {
1190
+ className: "text-kit-2xs leading-4 text-kit-fg-3",
1191
+ children: help
1192
+ }) : null
1193
+ ]
1194
+ });
1195
+ return /* @__PURE__ */ jsxs("div", {
1196
+ className: cn("flex flex-col", compact ? "gap-2.5" : "gap-4"),
1197
+ children: [
1198
+ col.type === "number" ? row("unit", "Unit", /* @__PURE__ */ jsx(Input, {
1199
+ id: `${id}-unit`,
1200
+ size: "sm",
1201
+ autoFocus: compact,
1202
+ readOnly,
1203
+ maxLength: 16,
1204
+ value: col.unit ?? "",
1205
+ placeholder: "kg, %, min",
1206
+ onChange: (e) => onPatch({ unit: e.target.value || void 0 })
1207
+ }), "Written after every value.") : null,
1208
+ col.type === "money" ? row("currency", "Currency", /* @__PURE__ */ jsx(Segmented, {
1209
+ size: "sm",
1210
+ "aria-label": "Currency",
1211
+ value: col.currency ?? "USD",
1212
+ onChange: (currency) => !readOnly && onPatch({ currency }),
1213
+ items: (CURRENCIES.includes(col.currency ?? "USD") ? CURRENCIES : [...CURRENCIES, col.currency]).map((c) => ({
1214
+ value: c,
1215
+ label: c
1216
+ }))
1217
+ })) : null,
1218
+ col.type === "rating" ? row("max", "Out of", /* @__PURE__ */ jsx(Input, {
1219
+ id: `${id}-max`,
1220
+ size: "sm",
1221
+ autoFocus: compact,
1222
+ readOnly,
1223
+ type: "number",
1224
+ min: 1,
1225
+ max: 10,
1226
+ value: col.max ?? 5,
1227
+ onChange: (e) => {
1228
+ const n = Math.round(Number(e.target.value));
1229
+ onPatch({ max: Number.isFinite(n) && n >= 1 ? Math.min(10, n) : void 0 });
1230
+ }
1231
+ })) : null,
1232
+ col.type === "boolean" ? /* @__PURE__ */ jsxs(Fragment, { children: [row("yes", "Yes says", /* @__PURE__ */ jsx(Input, {
1233
+ id: `${id}-yes`,
1234
+ size: "sm",
1235
+ autoFocus: compact,
1236
+ readOnly,
1237
+ maxLength: 300,
1238
+ value: col.trueLabel ?? "",
1239
+ placeholder: "Included",
1240
+ onChange: (e) => onPatch({ trueLabel: e.target.value || void 0 })
1241
+ }), "People who can't see the check mark hear these words."), row("no", "No says", /* @__PURE__ */ jsx(Input, {
1242
+ id: `${id}-no`,
1243
+ size: "sm",
1244
+ readOnly,
1245
+ maxLength: 300,
1246
+ value: col.falseLabel ?? "",
1247
+ placeholder: "Not included",
1248
+ onChange: (e) => onPatch({ falseLabel: e.target.value || void 0 })
1249
+ }))] }) : null
1250
+ ]
1251
+ });
1252
+ }
1253
+ function RowMenu({ ctx, row, index, count, onInsert, children }) {
1254
+ const { t, set, edit } = ctx;
1255
+ const atMax = !!ctx.options.maxRows && !row.footer && t.rows.filter((r) => !r.footer).length >= ctx.options.maxRows;
1256
+ const duplicate = () => {
1257
+ const order = displayRows(t).map((d) => d.row);
1258
+ order.splice(index + 1, 0, {
1259
+ ...row,
1260
+ _key: tkey("r"),
1261
+ cells: { ...row.cells }
1262
+ });
1263
+ set({
1264
+ ...t,
1265
+ rows: order
1266
+ });
1267
+ };
1268
+ const remove = () => {
1269
+ const prev = t;
1270
+ set({
1271
+ ...t,
1272
+ rows: t.rows.filter((r) => r._key !== row._key)
1273
+ });
1274
+ ctx.undoable("Row deleted", prev);
1275
+ };
1276
+ const groups = offered(ctx.options).groups ? t.rowGroups ?? [] : [];
1277
+ return /* @__PURE__ */ jsxs(Menu, { children: [children(/* @__PURE__ */ jsx(MenuTrigger, {
1278
+ tabIndex: -1,
1279
+ "aria-label": `Options for row ${index + 1}`,
1280
+ className: DOTS,
1281
+ children: /* @__PURE__ */ jsx(IconDots, {
1282
+ className: "size-3.5",
1283
+ stroke: 1.5
1284
+ })
1285
+ })), /* @__PURE__ */ jsxs(MenuContent, {
1286
+ className: "min-w-52",
1287
+ children: [
1288
+ /* @__PURE__ */ jsx(MenuItem, {
1289
+ disabled: atMax,
1290
+ onClick: () => onInsert(false),
1291
+ children: "Insert row above"
1292
+ }),
1293
+ /* @__PURE__ */ jsx(MenuItem, {
1294
+ disabled: atMax,
1295
+ onClick: () => onInsert(true),
1296
+ children: "Insert row below"
1297
+ }),
1298
+ /* @__PURE__ */ jsx(MenuItem, {
1299
+ disabled: atMax,
1300
+ onClick: duplicate,
1301
+ children: "Duplicate row"
1302
+ }),
1303
+ /* @__PURE__ */ jsx(MenuItem, {
1304
+ disabled: index === 0,
1305
+ onClick: () => set(moveRowTo(t, index, index - 1)),
1306
+ children: "Move up"
1307
+ }),
1308
+ /* @__PURE__ */ jsx(MenuItem, {
1309
+ disabled: index === count - 1,
1310
+ onClick: () => set(moveRowTo(t, index, index + 1)),
1311
+ children: "Move down"
1312
+ }),
1313
+ groups.length ? /* @__PURE__ */ jsxs(MenuSub, { children: [/* @__PURE__ */ jsx(MenuSubTrigger, { children: "Move to group" }), /* @__PURE__ */ jsx(MenuSubContent, { children: /* @__PURE__ */ jsxs(MenuRadioGroup, {
1314
+ value: row.group ?? "",
1315
+ onValueChange: (g) => edit(mapRow(row._key, (x) => clean({
1316
+ ...x,
1317
+ group: g || void 0,
1318
+ footer: void 0
1319
+ }))),
1320
+ children: [/* @__PURE__ */ jsx(MenuRadioItem, {
1321
+ value: "",
1322
+ children: "No group"
1323
+ }), groups.map((g) => /* @__PURE__ */ jsx(MenuRadioItem, {
1324
+ value: g._key,
1325
+ children: g.label || "Untitled group"
1326
+ }, g._key))]
1327
+ }) })] }) : null,
1328
+ offered(ctx.options).highlight ? /* @__PURE__ */ jsx(MenuCheckItem, {
1329
+ checked: !!row.highlight,
1330
+ onCheckedChange: (v) => edit(mapRow(row._key, (x) => clean({
1331
+ ...x,
1332
+ highlight: v
1333
+ }))),
1334
+ children: "Highlight this row"
1335
+ }) : null,
1336
+ offered(ctx.options).totals ? /* @__PURE__ */ jsx(MenuCheckItem, {
1337
+ checked: !!row.footer,
1338
+ onCheckedChange: (v) => edit(mapRow(row._key, (x) => clean({
1339
+ ...x,
1340
+ footer: v,
1341
+ group: void 0
1342
+ }))),
1343
+ children: "Totals row"
1344
+ }) : null,
1345
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
1346
+ /* @__PURE__ */ jsx(MenuItem, {
1347
+ danger: true,
1348
+ onClick: remove,
1349
+ children: "Delete row"
1350
+ })
1351
+ ]
1352
+ })] });
1353
+ }
1354
+ /** Right-click (or Shift+F10 / the menu key) on a cell: words instead of the column's type, a footnote, clear. */
1355
+ function CellMenu({ ctx, row, col, cell, onWrite, onNote, children }) {
1356
+ const { t, set } = ctx;
1357
+ const own = isCellObject(cell) ? cell.type : void 0;
1358
+ const note = cellNote(cell);
1359
+ const colType = row.type ?? col.type;
1360
+ const asText = own === "text";
1361
+ const atMax = !!ctx.options.maxRows && !row.footer && t.rows.filter((r) => !r.footer).length >= ctx.options.maxRows;
1362
+ const setOwn = (type) => {
1363
+ const value = coerce(cellText(col, row, cell, ctx.resolveRef), {
1364
+ type: type ?? colType,
1365
+ max: col.max
1366
+ });
1367
+ onWrite(type || note ? {
1368
+ value,
1369
+ ...type ? { type } : {},
1370
+ ...note ? { note } : {}
1371
+ } : value);
1372
+ };
1373
+ const insertRow = (below) => {
1374
+ const order = displayRows(t).map((d) => d.row);
1375
+ const at = order.findIndex((r) => r._key === row._key) + (below ? 1 : 0);
1376
+ order.splice(at, 0, clean({
1377
+ _key: tkey("r"),
1378
+ cells: {},
1379
+ group: row.group,
1380
+ footer: row.footer
1381
+ }));
1382
+ set({
1383
+ ...t,
1384
+ rows: order
1385
+ });
1386
+ };
1387
+ return /* @__PURE__ */ jsxs(ContextMenu.Root, { children: [/* @__PURE__ */ jsx(ContextMenu.Trigger, {
1388
+ render: /* @__PURE__ */ jsx("div", {}),
1389
+ children
1390
+ }), /* @__PURE__ */ jsxs(MenuContent, {
1391
+ className: "min-w-52",
1392
+ children: [
1393
+ colType !== "text" && colType !== "reference" && colType !== "richtext-inline" ? /* @__PURE__ */ jsx(MenuItem, {
1394
+ onClick: () => setOwn(asText ? void 0 : "text"),
1395
+ children: asText ? `Use ${TYPE_UI[colType].label} like the column` : "Write words in this cell instead"
1396
+ }) : null,
1397
+ offered(ctx.options).footnotes ? note ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MenuItem, {
1398
+ onClick: onNote,
1399
+ children: "Edit footnote"
1400
+ }), /* @__PURE__ */ jsx(MenuItem, {
1401
+ onClick: () => set(unlinkNote(t, row._key, col._key)),
1402
+ children: "Remove footnote"
1403
+ })] }) : /* @__PURE__ */ jsx(MenuItem, {
1404
+ onClick: () => (set(linkNote(t, row._key, col._key)[0]), onNote()),
1405
+ children: "Add a footnote"
1406
+ }) : null,
1407
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
1408
+ /* @__PURE__ */ jsx(MenuItem, {
1409
+ disabled: atMax,
1410
+ onClick: () => insertRow(true),
1411
+ children: "Insert row below"
1412
+ }),
1413
+ /* @__PURE__ */ jsx(MenuItem, {
1414
+ disabled: atMax,
1415
+ onClick: () => insertRow(false),
1416
+ children: "Insert row above"
1417
+ }),
1418
+ /* @__PURE__ */ jsx(MenuItem, {
1419
+ onClick: () => onWrite(withValue(cell, null)),
1420
+ children: "Clear cell"
1421
+ }),
1422
+ /* @__PURE__ */ jsx(MenuItem, {
1423
+ danger: true,
1424
+ onClick: () => {
1425
+ const prev = t;
1426
+ set({
1427
+ ...t,
1428
+ rows: t.rows.filter((r) => r._key !== row._key)
1429
+ });
1430
+ ctx.undoable("Row deleted", prev);
1431
+ },
1432
+ children: "Delete row"
1433
+ })
1434
+ ]
1435
+ })] });
1436
+ }
1437
+ var hasName = (t, r) => !!t.columns[0] && !isEmptyCell(cellValue(r.cells[t.columns[0]._key]));
1438
+ /** The row that was open when its drill closed, per table: focus lands back on it (form frames and the local drill). */
1439
+ var returnTo = /* @__PURE__ */ new Map();
1440
+ var ROWS_FIELD = {
1441
+ name: "rows",
1442
+ title: "Rows",
1443
+ type: "table",
1444
+ icon: "list"
1445
+ };
1446
+ var COLUMNS_FIELD = {
1447
+ name: "columns",
1448
+ title: "Columns",
1449
+ type: "table",
1450
+ icon: "layout-columns"
1451
+ };
1452
+ var noop = () => void 0;
1453
+ var colSummary = (c) => [TYPE_UI[c.type].label, c.type === "number" ? c.unit : c.type === "money" ? c.currency ?? "USD" : c.type === "rating" ? `out of ${c.max ?? 5}` : void 0].filter(Boolean).join(" · ");
1454
+ /** D52: the whole table is ONE group, shown the way every nested group is shown: a single 1px inset line on the left. */
1455
+ var TABLE_GROUP = "ml-1.5 border-l border-kit-line pl-3";
1456
+ /** A sub-part of the table field: the same label style as every field label (13/500, fg-2; fg while focus is inside). */
1457
+ var PART_LABEL = "text-kit-sm font-medium text-kit-fg-2 transition-colors group-focus-within/part:text-kit-fg";
1458
+ /** CPO D52: the settings a table kind offers, with their defaults (schema/table.ts › TableSettingsOptions). */
1459
+ var PHONES = [
1460
+ {
1461
+ value: "scroll",
1462
+ label: "Scroll"
1463
+ },
1464
+ {
1465
+ value: "stack",
1466
+ label: "Stack"
1467
+ },
1468
+ {
1469
+ value: "cards",
1470
+ label: "Cards"
1471
+ }
1472
+ ];
1473
+ function offered(options) {
1474
+ const s = options.settings ?? {};
1475
+ const phones = PHONES.filter((p) => !s.phones || s.phones.includes(p.value));
1476
+ return {
1477
+ headers: s.headers !== false,
1478
+ totals: s.totals !== false,
1479
+ phones: phones.length > 1 ? phones : [],
1480
+ highlight: s.highlight !== false,
1481
+ sticky: s.sticky !== false,
1482
+ sort: !!s.sort,
1483
+ search: !!s.search,
1484
+ jsonLd: (options.jsonLd ?? []).filter((x) => x !== "none"),
1485
+ groups: options.allowGroups !== false,
1486
+ footnotes: options.allowFootnotes !== false,
1487
+ note: options.allowNote !== false
1488
+ };
1489
+ }
1490
+ /** Unlink a footnote from one cell; the footnote itself goes when no other cell points at it. */
1491
+ function unlinkNote(t, rowKey, colKey) {
1492
+ let note;
1493
+ const rows = t.rows.map((r) => {
1494
+ if (r._key !== rowKey) return r;
1495
+ const c = r.cells[colKey];
1496
+ if (!isCellObject(c) || !c.note) return r;
1497
+ note = c.note;
1498
+ return {
1499
+ ...r,
1500
+ cells: {
1501
+ ...r.cells,
1502
+ [colKey]: c.type ? {
1503
+ value: c.value,
1504
+ type: c.type
1505
+ } : c.value
1506
+ }
1507
+ };
1508
+ });
1509
+ if (!note) return t;
1510
+ const used = rows.some((r) => Object.values(r.cells).some((c) => isCellObject(c) && c.note === note));
1511
+ return {
1512
+ ...t,
1513
+ rows,
1514
+ footnotes: used ? t.footnotes : (t.footnotes ?? []).filter((f) => f._key !== note)
1515
+ };
1516
+ }
1517
+ /** Link a new, empty footnote to one cell. Returns the table and the footnote's key (its input takes focus). */
1518
+ function linkNote(t, rowKey, colKey) {
1519
+ const f = {
1520
+ _key: tkey("f"),
1521
+ text: ""
1522
+ };
1523
+ return [{
1524
+ ...t,
1525
+ footnotes: [...t.footnotes ?? [], f],
1526
+ rows: t.rows.map((r) => {
1527
+ if (r._key !== rowKey) return r;
1528
+ const c = r.cells[colKey];
1529
+ const own = isCellObject(c) ? c.type : void 0;
1530
+ return {
1531
+ ...r,
1532
+ cells: {
1533
+ ...r.cells,
1534
+ [colKey]: {
1535
+ value: cellValue(c),
1536
+ ...own ? { type: own } : {},
1537
+ note: f._key
1538
+ }
1539
+ }
1540
+ };
1541
+ })
1542
+ }, f._key];
1543
+ }
1544
+ var focusSoon = (selector) => requestAnimationFrame(() => document.querySelector(selector)?.focus());
1545
+ function TableBody({ ctx, label, nav, head }) {
1546
+ const { t, set, readOnly, options } = ctx;
1547
+ const [open, setOpen] = React.useState(null);
1548
+ const host = React.useRef(null);
1549
+ const localId = React.useId();
1550
+ const id = nav?.id ?? localId;
1551
+ const focusRow = (key) => host.current?.querySelector(`[data-row-open="${CSS.escape(key)}"]`)?.focus({ preventScroll: false });
1552
+ React.useEffect(() => {
1553
+ if (open || !returnTo.has(id)) return;
1554
+ const raf = requestAnimationFrame(() => {
1555
+ const key = returnTo.get(id);
1556
+ returnTo.delete(id);
1557
+ const a = document.activeElement;
1558
+ if (key && (!a || a === document.body || a.matches("[data-frame-body]") || host.current?.contains(a) || !a.isConnected)) focusRow(key);
1559
+ });
1560
+ return () => cancelAnimationFrame(raf);
1561
+ }, [open, id]);
1562
+ const go = (kind, index, key) => {
1563
+ returnTo.set(id, key);
1564
+ if (nav) window.setTimeout(() => nav.open(kind, index), 0);
1565
+ else setOpen({
1566
+ kind,
1567
+ key
1568
+ });
1569
+ };
1570
+ const list = open ? open.kind === "rows" ? t.rows : t.columns : [];
1571
+ const at = open ? list.findIndex((x) => x._key === open.key) : -1;
1572
+ if (open && at >= 0) return /* @__PURE__ */ jsx("div", {
1573
+ className: TABLE_GROUP,
1574
+ children: /* @__PURE__ */ jsx(LocalDrill, {
1575
+ ctx,
1576
+ label,
1577
+ open,
1578
+ index: at,
1579
+ onBack: () => setOpen(null),
1580
+ onGo: (key) => setOpen({
1581
+ kind: open.kind,
1582
+ key
1583
+ })
1584
+ })
1585
+ });
1586
+ const base = nav?.basePath ?? [];
1587
+ const titleId = `${id}-title`;
1588
+ const noteId = `${id}-note`;
1589
+ return /* @__PURE__ */ jsxs("div", {
1590
+ ref: host,
1591
+ role: "group",
1592
+ "aria-label": label || "Table",
1593
+ className: cn(TABLE_GROUP, "flex flex-col gap-4 @max-[360px]:gap-3", !readOnly && "mb-2"),
1594
+ children: [
1595
+ /* @__PURE__ */ jsxs("div", {
1596
+ className: "group/part flex flex-col gap-1.5",
1597
+ children: [/* @__PURE__ */ jsxs("div", {
1598
+ className: "flex min-h-5 items-center gap-1.5",
1599
+ children: [
1600
+ /* @__PURE__ */ jsx("label", {
1601
+ htmlFor: titleId,
1602
+ className: PART_LABEL,
1603
+ children: "Title"
1604
+ }),
1605
+ options.requireCaption !== false && !t.caption.trim() ? /* @__PURE__ */ jsx("span", {
1606
+ className: "text-kit-xs text-kit-fg-3",
1607
+ children: "Required"
1608
+ }) : null,
1609
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
1610
+ head
1611
+ ]
1612
+ }), /* @__PURE__ */ jsx(Textarea, {
1613
+ id: titleId,
1614
+ rows: 1,
1615
+ maxLength: 300,
1616
+ value: t.caption,
1617
+ readOnly,
1618
+ placeholder: "What the table shows",
1619
+ onChange: (e) => set({
1620
+ ...t,
1621
+ caption: e.target.value.replace(/\n/g, " ")
1622
+ }),
1623
+ className: "min-h-8 resize-none py-1.5"
1624
+ })]
1625
+ }),
1626
+ /* @__PURE__ */ jsx(ColumnsPart, {
1627
+ ctx,
1628
+ basePath: base,
1629
+ onOpen: (i, key) => go("columns", i, key)
1630
+ }),
1631
+ /* @__PURE__ */ jsx(RowsPart, {
1632
+ ctx,
1633
+ basePath: base,
1634
+ onOpen: (i, key) => go("rows", i, key)
1635
+ }),
1636
+ offered(options).note ? /* @__PURE__ */ jsxs("div", {
1637
+ className: "group/part flex flex-col gap-1.5",
1638
+ children: [/* @__PURE__ */ jsx("label", {
1639
+ htmlFor: noteId,
1640
+ className: PART_LABEL,
1641
+ children: "Note under the table"
1642
+ }), /* @__PURE__ */ jsx(Textarea, {
1643
+ id: noteId,
1644
+ rows: 2,
1645
+ maxLength: 2e3,
1646
+ value: t.notes ?? "",
1647
+ readOnly,
1648
+ placeholder: "Source: our own tests, September 2026.",
1649
+ onChange: (e) => set({
1650
+ ...t,
1651
+ notes: e.target.value || void 0
1652
+ })
1653
+ })]
1654
+ }) : null,
1655
+ readOnly ? null : /* @__PURE__ */ jsx(TableSettings, { ctx })
1656
+ ]
1657
+ });
1658
+ }
1659
+ /** Columns: an array list like any other (type icon, name, "Yes / No" summary, ⋯, ›). */
1660
+ function ColumnsPart({ ctx, basePath, onOpen }) {
1661
+ const { t, set, lock, options } = ctx;
1662
+ const n = t.columns.length;
1663
+ const atMax = !!options.maxColumns && n >= options.maxColumns;
1664
+ const write = (columns) => set({
1665
+ ...t,
1666
+ columns
1667
+ });
1668
+ const add = () => {
1669
+ if (atMax) return;
1670
+ const col = {
1671
+ _key: tkey("c"),
1672
+ label: "",
1673
+ type: "text"
1674
+ };
1675
+ write([...t.columns, col]);
1676
+ onOpen(n, col._key);
1677
+ };
1678
+ const ops = {
1679
+ atMax,
1680
+ atMin: n <= 1,
1681
+ add,
1682
+ duplicate: (i) => !atMax && set(copyColumn(t, i)),
1683
+ move: (i, d) => i + d >= 0 && i + d < n && write(moveItem(t.columns, i, i + d)),
1684
+ reorder: (from, to) => write(moveItem(t.columns, from, to)),
1685
+ remove: (i, title) => {
1686
+ if (n <= 1) return;
1687
+ const prev = t;
1688
+ set(dropColumn(t, t.columns[i]._key));
1689
+ ctx.undoable(`“${title}” removed`, prev);
1690
+ },
1691
+ insertBlank: noop
1692
+ };
1693
+ const rows = t.columns.map((c, i) => ({
1694
+ id: c._key,
1695
+ index: i,
1696
+ item: c,
1697
+ path: [
1698
+ ...basePath,
1699
+ "columns",
1700
+ i
1701
+ ],
1702
+ preview: {
1703
+ title: c.label || "Untitled column",
1704
+ subtitle: colSummary(c),
1705
+ empty: !c.label
1706
+ }
1707
+ }));
1708
+ return /* @__PURE__ */ jsxs("div", {
1709
+ role: "group",
1710
+ "aria-label": "Columns",
1711
+ className: "group/part flex flex-col gap-1.5",
1712
+ children: [/* @__PURE__ */ jsx("span", {
1713
+ className: PART_LABEL,
1714
+ children: "Columns"
1715
+ }), /* @__PURE__ */ jsx(RowList, {
1716
+ field: {
1717
+ ...COLUMNS_FIELD,
1718
+ validation: { min: 1 }
1719
+ },
1720
+ rows,
1721
+ readOnly: lock,
1722
+ layout: "list",
1723
+ mode: "drill",
1724
+ openId: null,
1725
+ onOpen: (r) => onOpen(r.index, r.id),
1726
+ onCloseInline: noop,
1727
+ ops,
1728
+ renderInline: () => null,
1729
+ emptyLabel: "No columns yet.",
1730
+ leading: (r) => /* @__PURE__ */ jsx("span", {
1731
+ className: "flex size-7 shrink-0 items-center justify-center rounded-kit-md bg-kit-muted text-kit-fg-2",
1732
+ children: /* @__PURE__ */ jsx(TypeIcon, {
1733
+ type: r.item.type,
1734
+ className: "size-4 text-kit-fg-2"
1735
+ })
1736
+ }),
1737
+ addButton: /* @__PURE__ */ jsx(Button, {
1738
+ size: "sm",
1739
+ variant: "ghost",
1740
+ className: "text-kit-fg-2",
1741
+ leftIcon: /* @__PURE__ */ jsx(IconPlus, { stroke: 1.5 }),
1742
+ disabled: atMax,
1743
+ onClick: add,
1744
+ children: atMax ? `Add column · ${options.maxColumns} at most` : "Add column"
1745
+ })
1746
+ })]
1747
+ });
1748
+ }
1749
+ /**
1750
+ * Rows (D52): groups live in the row list itself. Loose rows first, then each group under a heading you rename in place
1751
+ * (its ⋯ moves or removes it), then Totals. "Add group" sits next to the last "Add row"; a row changes group by its ⋯ ›
1752
+ * Move to group. Every list is the kit's array row list; drag (and ↑/↓ on the grip) reorders inside a group.
1753
+ */
1754
+ function RowsPart({ ctx, basePath, onOpen }) {
1755
+ const { t, set, resolveRef, readOnly, options } = ctx;
1756
+ const can = offered(options);
1757
+ const groups = can.groups ? t.rowGroups ?? [] : [];
1758
+ const known = new Set(groups.map((g) => g._key));
1759
+ const body = t.rows.filter((r) => !r.footer);
1760
+ const runs = [];
1761
+ const loose = body.filter((r) => !r.group || !known.has(r.group));
1762
+ if (loose.length || !groups.length) runs.push({
1763
+ key: "loose",
1764
+ items: loose
1765
+ });
1766
+ groups.forEach((g) => runs.push({
1767
+ key: g._key,
1768
+ group: g,
1769
+ items: body.filter((r) => r.group === g._key)
1770
+ }));
1771
+ const foot = t.rows.filter((r) => r.footer);
1772
+ if (foot.length) runs.push({
1773
+ key: "totals",
1774
+ totals: true,
1775
+ items: foot
1776
+ });
1777
+ const lastBody = runs.filter((r) => !r.totals).length - 1;
1778
+ const atMax = !!options.maxRows && body.length >= options.maxRows;
1779
+ const place = (r, x) => clean({
1780
+ ...x,
1781
+ group: r.group?._key ?? (r.key === "loose" && x.group && !known.has(x.group) ? x.group : void 0),
1782
+ footer: r.totals || void 0
1783
+ });
1784
+ const writeRuns = (next) => set({
1785
+ ...t,
1786
+ rows: next.flatMap((r) => r.items.map((x) => place(r, x)))
1787
+ });
1788
+ const writeRun = (ri, items) => writeRuns(runs.map((r, j) => j === ri ? {
1789
+ ...r,
1790
+ items
1791
+ } : r));
1792
+ const add = (ri) => {
1793
+ if (atMax && !runs[ri].totals) return;
1794
+ const run = runs[ri];
1795
+ const row = place(run, {
1796
+ _key: tkey("r"),
1797
+ cells: {}
1798
+ });
1799
+ const rows = runs.flatMap((r, j) => j === ri ? [...r.items.map((x) => place(r, x)), row] : r.items.map((x) => place(r, x)));
1800
+ set({
1801
+ ...t,
1802
+ rows
1803
+ });
1804
+ onOpen(rows.indexOf(row), row._key);
1805
+ };
1806
+ const addGroup = () => {
1807
+ const g = {
1808
+ _key: tkey("rg"),
1809
+ label: ""
1810
+ };
1811
+ set({
1812
+ ...t,
1813
+ rowGroups: [...t.rowGroups ?? [], g]
1814
+ });
1815
+ focusSoon(`[data-group-name="${g._key}"]`);
1816
+ };
1817
+ const placeName = (k) => k === "totals" ? "Totals" : k === "loose" ? "No group" : groups.find((g) => g._key === k)?.label || "Untitled group";
1818
+ /** Move a row to the end of another run (a group, no group, or Totals). */
1819
+ const moveTo = (row, target) => {
1820
+ const prev = t;
1821
+ const rest = t.rows.filter((r) => r._key !== row._key);
1822
+ set({
1823
+ ...t,
1824
+ rows: [...rest, clean({
1825
+ ...row,
1826
+ group: target.totals ? void 0 : target.group,
1827
+ footer: target.totals || void 0
1828
+ })]
1829
+ });
1830
+ ctx.undoable(`Moved to ${placeName(target.totals ? "totals" : target.group ?? "loose")}`, prev);
1831
+ };
1832
+ const opsFor = (ri) => {
1833
+ const items = runs[ri].items;
1834
+ const runMax = atMax && !runs[ri].totals;
1835
+ return {
1836
+ atMax: runMax,
1837
+ atMin: false,
1838
+ add: () => add(ri),
1839
+ duplicate: (i) => !runMax && writeRun(ri, [
1840
+ ...items.slice(0, i + 1),
1841
+ {
1842
+ ...items[i],
1843
+ _key: tkey("r"),
1844
+ cells: { ...items[i].cells }
1845
+ },
1846
+ ...items.slice(i + 1)
1847
+ ]),
1848
+ move: (i, d) => i + d >= 0 && i + d < items.length && writeRun(ri, moveItem(items, i, i + d)),
1849
+ reorder: (from, to) => writeRun(ri, moveItem(items, from, to)),
1850
+ remove: (i, title) => {
1851
+ const prev = t;
1852
+ writeRun(ri, items.filter((_, j) => j !== i));
1853
+ ctx.undoable(`“${title}” removed`, prev);
1854
+ },
1855
+ insertBlank: noop
1856
+ };
1857
+ };
1858
+ const sub = (r) => t.columns.slice(1, 3).map((c) => {
1859
+ const s = cellText(c, r, r.cells[c._key], resolveRef);
1860
+ return s ? `${c.label || "Untitled"}: ${s}` : "";
1861
+ }).filter(Boolean).join(" · ");
1862
+ const model = (row, i) => {
1863
+ const named = hasName(t, row);
1864
+ return {
1865
+ id: row._key,
1866
+ index: i,
1867
+ item: row,
1868
+ path: [
1869
+ ...basePath,
1870
+ "rows",
1871
+ t.rows.indexOf(row)
1872
+ ],
1873
+ preview: {
1874
+ title: named ? rowTitle(t, row, i, resolveRef) : "Untitled row",
1875
+ subtitle: sub(row) || void 0,
1876
+ empty: !named
1877
+ }
1878
+ };
1879
+ };
1880
+ const moveMenu = (r) => {
1881
+ const row = r.item;
1882
+ const here = row.footer ? "totals" : row.group && known.has(row.group) ? row.group : "";
1883
+ const places = [
1884
+ ...groups.length ? [{
1885
+ value: "",
1886
+ label: "No group"
1887
+ }] : [],
1888
+ ...groups.map((g) => ({
1889
+ value: g._key,
1890
+ label: g.label || "Untitled group"
1891
+ })),
1892
+ ...can.totals && (foot.length || groups.length) ? [{
1893
+ value: "totals",
1894
+ label: "Totals"
1895
+ }] : []
1896
+ ];
1897
+ if (!places.some((p) => p.value !== here)) return null;
1898
+ return /* @__PURE__ */ jsxs(MenuSub, { children: [/* @__PURE__ */ jsx(MenuSubTrigger, {
1899
+ icon: /* @__PURE__ */ jsx(IconFolder, { stroke: 1.5 }),
1900
+ children: "Move to group"
1901
+ }), /* @__PURE__ */ jsx(MenuSubContent, {
1902
+ className: "min-w-44",
1903
+ children: /* @__PURE__ */ jsx(MenuRadioGroup, {
1904
+ value: here,
1905
+ onValueChange: (v) => v !== here && moveTo(row, v === "totals" ? { totals: true } : { group: v || void 0 }),
1906
+ children: places.map((p) => /* @__PURE__ */ jsx(MenuRadioItem, {
1907
+ value: p.value,
1908
+ children: p.label
1909
+ }, p.value || "none"))
1910
+ })
1911
+ })] });
1912
+ };
1913
+ const sharedSort = useSharedSort();
1914
+ const unnamed = t.rows.find((r) => !hasName(t, r) && t.columns.slice(1).some((c) => !isEmptyCell(cellValue(r.cells[c._key]))));
1915
+ const addRowButton = (ri) => /* @__PURE__ */ jsx(Button, {
1916
+ size: "sm",
1917
+ variant: "ghost",
1918
+ className: "text-kit-fg-2",
1919
+ leftIcon: /* @__PURE__ */ jsx(IconPlus, { stroke: 1.5 }),
1920
+ disabled: atMax && !runs[ri].totals,
1921
+ onClick: () => add(ri),
1922
+ children: atMax && !runs[ri].totals ? `Add row · ${options.maxRows} at most` : "Add row"
1923
+ });
1924
+ return /* @__PURE__ */ jsxs("div", {
1925
+ role: "group",
1926
+ "aria-label": "Rows",
1927
+ className: "group/part flex flex-col gap-1.5",
1928
+ children: [
1929
+ /* @__PURE__ */ jsx("span", {
1930
+ className: PART_LABEL,
1931
+ children: "Rows"
1932
+ }),
1933
+ unnamed && !readOnly ? /* @__PURE__ */ jsx("button", {
1934
+ type: "button",
1935
+ onClick: () => onOpen(t.rows.indexOf(unnamed), unnamed._key),
1936
+ className: "self-start text-left text-kit-xs text-kit-warning-fg underline-offset-2 hover:underline",
1937
+ children: "A row has values but no name. Open it"
1938
+ }) : null,
1939
+ /* @__PURE__ */ jsx(SharedSortProvider, {
1940
+ value: sharedSort.value,
1941
+ children: /* @__PURE__ */ jsx("div", {
1942
+ className: "flex flex-col gap-3",
1943
+ children: runs.map((run, ri) => {
1944
+ const list = /* @__PURE__ */ jsx(RowList, {
1945
+ field: ROWS_FIELD,
1946
+ rows: run.items.map(model),
1947
+ readOnly,
1948
+ layout: "list",
1949
+ mode: "drill",
1950
+ openId: null,
1951
+ onOpen: (r) => onOpen(t.rows.indexOf(r.item), r.id),
1952
+ onCloseInline: noop,
1953
+ ops: opsFor(ri),
1954
+ renderInline: () => null,
1955
+ menuExtra: moveMenu,
1956
+ emptyLabel: run.totals ? "No totals yet." : run.group ? "No rows in this group yet." : "No rows yet.",
1957
+ addButton: ri === lastBody && can.groups ? /* @__PURE__ */ jsxs("span", {
1958
+ className: "flex flex-wrap items-center gap-1",
1959
+ children: [addRowButton(ri), /* @__PURE__ */ jsx(Button, {
1960
+ size: "sm",
1961
+ variant: "ghost",
1962
+ className: "text-kit-fg-2",
1963
+ leftIcon: /* @__PURE__ */ jsx(IconPlus, { stroke: 1.5 }),
1964
+ onClick: addGroup,
1965
+ children: "Add group"
1966
+ })]
1967
+ }) : addRowButton(ri)
1968
+ });
1969
+ if (!run.group && !run.totals) return /* @__PURE__ */ jsx("div", { children: list }, run.key);
1970
+ return /* @__PURE__ */ jsxs("div", {
1971
+ role: "group",
1972
+ "aria-label": run.totals ? "Totals" : run.group.label || "Untitled group",
1973
+ className: "flex flex-col gap-1.5",
1974
+ children: [run.totals ? /* @__PURE__ */ jsx("span", {
1975
+ className: "flex h-7 items-center px-0.5 text-kit-sm font-medium text-kit-fg-2",
1976
+ children: "Totals"
1977
+ }) : /* @__PURE__ */ jsx(GroupHeading, {
1978
+ ctx,
1979
+ group: run.group,
1980
+ index: groups.indexOf(run.group),
1981
+ count: groups.length,
1982
+ rows: run.items.length
1983
+ }), /* @__PURE__ */ jsx("div", {
1984
+ className: "ml-1.5 border-l border-kit-line pl-3",
1985
+ children: list
1986
+ })]
1987
+ }, run.key);
1988
+ })
1989
+ })
1990
+ }),
1991
+ sharedSort.a11y
1992
+ ]
1993
+ });
1994
+ }
1995
+ /** A row group's heading, renamed in place. It reads as a label at rest; its ⋯ moves or removes the group. */
1996
+ function GroupHeading({ ctx, group, index, count, rows }) {
1997
+ const { t, set, readOnly } = ctx;
1998
+ const [draft, setDraft] = React.useState(group.label);
1999
+ const [seen, setSeen] = React.useState(group.label);
2000
+ if (seen !== group.label) {
2001
+ setSeen(group.label);
2002
+ setDraft(group.label);
2003
+ }
2004
+ const rename = (label) => label !== group.label && set({
2005
+ ...t,
2006
+ rowGroups: (t.rowGroups ?? []).map((g) => g._key === group._key ? {
2007
+ ...g,
2008
+ label
2009
+ } : g)
2010
+ });
2011
+ const moveGroup = (d) => set({
2012
+ ...t,
2013
+ rowGroups: moveItem(t.rowGroups ?? [], index, index + d)
2014
+ });
2015
+ const remove = () => {
2016
+ const prev = t;
2017
+ set({
2018
+ ...t,
2019
+ rowGroups: (t.rowGroups ?? []).filter((g) => g._key !== group._key),
2020
+ rows: t.rows.map((r) => r.group === group._key ? clean({
2021
+ ...r,
2022
+ group: void 0
2023
+ }) : r)
2024
+ });
2025
+ ctx.undoable(`“${group.label || "Untitled group"}” removed`, prev, rows ? `Its ${rows === 1 ? "row stays" : `${rows} rows stay`} in the table.` : void 0);
2026
+ };
2027
+ return /* @__PURE__ */ jsxs("div", {
2028
+ className: "group/gh flex min-w-0 items-center gap-1",
2029
+ children: [/* @__PURE__ */ jsx("input", {
2030
+ "data-group-name": group._key,
2031
+ value: draft,
2032
+ readOnly,
2033
+ maxLength: 300,
2034
+ placeholder: "Group name",
2035
+ "aria-label": "Group name",
2036
+ onChange: (e) => setDraft(e.target.value),
2037
+ onBlur: () => rename(draft.replace(/\s+/g, " ").trim()),
2038
+ onKeyDown: (e) => {
2039
+ if (e.key === "Enter") {
2040
+ e.preventDefault();
2041
+ e.currentTarget.blur();
2042
+ } else if (e.key === "Escape" && draft !== group.label) {
2043
+ e.preventDefault();
2044
+ e.stopPropagation();
2045
+ setDraft(group.label);
2046
+ }
2047
+ },
2048
+ className: "-mx-0.5 h-7 min-w-0 flex-1 truncate rounded-kit-md bg-transparent px-0.5 text-kit-sm font-medium text-kit-fg-2 outline-none transition-colors placeholder:font-normal placeholder:text-kit-fg-4 hover:bg-kit-hover focus:bg-kit-surface focus:px-2 focus:text-kit-fg focus:shadow-[inset_0_0_0_1px_var(--kit-line-strong)]"
2049
+ }), readOnly ? null : /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
2050
+ "aria-label": `Options for ${group.label || "this group"}`,
2051
+ className: cn(DOTS, "size-7 opacity-0 focus-visible:opacity-100 group-hover/gh:opacity-100 group-focus-within/gh:opacity-100 data-[popup-open]:opacity-100 [@media(pointer:coarse)]:opacity-100"),
2052
+ children: /* @__PURE__ */ jsx(IconDots, {
2053
+ className: "size-4",
2054
+ stroke: 1.5
2055
+ })
2056
+ }), /* @__PURE__ */ jsxs(MenuContent, {
2057
+ align: "end",
2058
+ className: "min-w-44",
2059
+ children: [
2060
+ /* @__PURE__ */ jsx(MenuItem, {
2061
+ icon: /* @__PURE__ */ jsx(IconArrowUp, { stroke: 1.5 }),
2062
+ disabled: index === 0,
2063
+ onClick: () => moveGroup(-1),
2064
+ children: "Move up"
2065
+ }),
2066
+ /* @__PURE__ */ jsx(MenuItem, {
2067
+ icon: /* @__PURE__ */ jsx(IconArrowDown, { stroke: 1.5 }),
2068
+ disabled: index >= count - 1,
2069
+ onClick: () => moveGroup(1),
2070
+ children: "Move down"
2071
+ }),
2072
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
2073
+ /* @__PURE__ */ jsx(MenuItem, {
2074
+ danger: true,
2075
+ onClick: remove,
2076
+ children: "Remove group"
2077
+ })
2078
+ ]
2079
+ })] })]
2080
+ });
2081
+ }
2082
+ /**
2083
+ * Height of the sticky bars pinned above a table in its scroll area: the rich-text editor publishes
2084
+ * --rt-sticky-top (field tabs + its toolbar), a kit form --kit-sticky-top (field tabs).
2085
+ */
2086
+ var STICKY_TOP = "var(--rt-sticky-top, var(--kit-sticky-top, 0px))";
2087
+ /** Scroll only the nearest scroll area (never the shell) so `el`'s top clears the sticky bars (its scroll-margin-top). */
2088
+ function revealBelowStickies(el) {
2089
+ if (!el) return;
2090
+ let area = el.parentElement;
2091
+ while (area && !/(auto|scroll)/.test(getComputedStyle(area).overflowY)) area = area.parentElement;
2092
+ const hidden = (area ? area.getBoundingClientRect().top : 0) + (parseFloat(getComputedStyle(el).scrollMarginTop) || 0) - el.getBoundingClientRect().top;
2093
+ if (hidden > 1) (area ?? document.scrollingElement)?.scrollBy?.({ top: -hidden });
2094
+ }
2095
+ /** Tables outside a kit form (the /style-guide/kit sandbox, demos): the same drill, with the same breadcrumb and header. */
2096
+ function LocalDrill({ ctx, label, open, index, onBack, onGo }) {
2097
+ const { t, resolveRef } = ctx;
2098
+ const rows = open.kind === "rows";
2099
+ const list = rows ? t.rows : t.columns;
2100
+ const titleAt = (i) => rows ? hasName(t, t.rows[i]) ? rowTitle(t, t.rows[i], i, resolveRef) : "Untitled row" : t.columns[i].label || "Untitled column";
2101
+ const row = rows ? t.rows[index] : void 0;
2102
+ const group = row?.group && !row.footer ? t.rowGroups?.find((g) => g._key === row.group) : void 0;
2103
+ const title = titleAt(index);
2104
+ const noun = rows ? "row" : "column";
2105
+ const rootRef = React.useRef(null);
2106
+ const headRef = React.useRef(null);
2107
+ React.useLayoutEffect(() => {
2108
+ headRef.current?.focus({ preventScroll: true });
2109
+ const raf = requestAnimationFrame(() => revealBelowStickies(rootRef.current));
2110
+ return () => cancelAnimationFrame(raf);
2111
+ }, [index]);
2112
+ const step = (d) => list[index + d] && onGo(list[index + d]._key);
2113
+ return /* @__PURE__ */ jsxs("div", {
2114
+ ref: rootRef,
2115
+ className: "flex flex-col gap-4",
2116
+ style: { scrollMarginTop: `calc(${STICKY_TOP} + 8px)` },
2117
+ onKeyDown: (e) => e.key === "Escape" && !e.defaultPrevented && (e.preventDefault(), onBack()),
2118
+ children: [
2119
+ /* @__PURE__ */ jsx("div", {
2120
+ className: "sticky z-[2] -my-1 bg-kit-surface py-1",
2121
+ style: { top: STICKY_TOP },
2122
+ children: /* @__PURE__ */ jsx(PathCrumbs, {
2123
+ size: "sm",
2124
+ label: "Table path",
2125
+ items: [
2126
+ {
2127
+ id: "table",
2128
+ label: label || "Table",
2129
+ icon: /* @__PURE__ */ jsx(IconTable, {}),
2130
+ onSelect: onBack
2131
+ },
2132
+ ...group ? [{
2133
+ id: "group",
2134
+ label: group.label || "Untitled group",
2135
+ icon: /* @__PURE__ */ jsx(IconFolder, {}),
2136
+ onSelect: onBack
2137
+ }] : [],
2138
+ {
2139
+ id: "current",
2140
+ label: title,
2141
+ icon: rows ? /* @__PURE__ */ jsx(IconList, {}) : /* @__PURE__ */ jsx(IconLayoutColumns, {})
2142
+ }
2143
+ ]
2144
+ })
2145
+ }),
2146
+ /* @__PURE__ */ jsxs("div", {
2147
+ ref: headRef,
2148
+ tabIndex: -1,
2149
+ className: "flex items-start gap-2.5 outline-none",
2150
+ children: [/* @__PURE__ */ jsxs("div", {
2151
+ className: "min-w-0 flex-1",
2152
+ children: [/* @__PURE__ */ jsx("h2", {
2153
+ className: "truncate text-kit-base font-semibold leading-6 text-kit-fg",
2154
+ children: title
2155
+ }), /* @__PURE__ */ jsx("p", {
2156
+ className: "truncate text-kit-xs leading-4 text-kit-fg-3",
2157
+ children: `${rows ? "Row" : "Column"} ${index + 1} of ${list.length} in ${label || "the table"}`
2158
+ })]
2159
+ }), /* @__PURE__ */ jsxs("div", {
2160
+ className: "-mr-1 flex shrink-0 items-center gap-0.5 pt-0.5",
2161
+ children: [/* @__PURE__ */ jsx(IconButton, {
2162
+ size: "sm",
2163
+ label: index > 0 ? `Previous ${noun}: ${titleAt(index - 1)}` : `First ${noun}`,
2164
+ disabled: index === 0,
2165
+ onClick: () => step(-1),
2166
+ children: /* @__PURE__ */ jsx(IconArrowUp, { stroke: 1.5 })
2167
+ }), /* @__PURE__ */ jsx(IconButton, {
2168
+ size: "sm",
2169
+ label: index < list.length - 1 ? `Next ${noun}: ${titleAt(index + 1)}` : `Last ${noun}`,
2170
+ disabled: index >= list.length - 1,
2171
+ onClick: () => step(1),
2172
+ children: /* @__PURE__ */ jsx(IconArrowDown, { stroke: 1.5 })
2173
+ })]
2174
+ })]
2175
+ }),
2176
+ rows ? /* @__PURE__ */ jsx(RowFields, {
2177
+ ctx,
2178
+ row: t.rows[index]
2179
+ }) : /* @__PURE__ */ jsx(ColumnFields, {
2180
+ ctx,
2181
+ col: t.columns[index]
2182
+ })
2183
+ ]
2184
+ });
2185
+ }
2186
+ function RowFields({ ctx, row }) {
2187
+ const { t, edit, readOnly, options } = ctx;
2188
+ const write = (col, next) => edit(mapRow(row._key, (x) => ({
2189
+ ...x,
2190
+ cells: {
2191
+ ...x.cells,
2192
+ [col._key]: next ?? null
2193
+ }
2194
+ })));
2195
+ const named = hasName(t, row);
2196
+ return /* @__PURE__ */ jsxs("div", {
2197
+ className: "flex flex-col gap-4",
2198
+ children: [t.columns.map((col, ci) => /* @__PURE__ */ jsx(CellField, {
2199
+ ctx,
2200
+ row,
2201
+ col,
2202
+ ci,
2203
+ needsName: ci === 0 && !named,
2204
+ onWrite: (c) => write(col, c)
2205
+ }, col._key)), readOnly || !offered(options).highlight ? null : /* @__PURE__ */ jsx(SwitchRow, {
2206
+ label: "Highlight this row",
2207
+ checked: !!row.highlight,
2208
+ onChange: (v) => edit(mapRow(row._key, (x) => clean({
2209
+ ...x,
2210
+ highlight: v
2211
+ })))
2212
+ })]
2213
+ });
2214
+ }
2215
+ /**
2216
+ * One cell as a field. Per-cell exceptions are quiet: a ⋯ by the label (shown on hover or focus) offers "Write words
2217
+ * instead" for a typed column, a footnote and Clear. A footnote is written right here, under the cell (D52).
2218
+ */
2219
+ function CellField({ ctx, row, col, ci, needsName, onWrite }) {
2220
+ const { t, set, resolveRef, readOnly, options } = ctx;
2221
+ const cell = row.cells[col._key];
2222
+ const declared = cellType(col, row, cell);
2223
+ const v = cellValue(cell);
2224
+ const ty = declared === "boolean" && !isEmptyCell(v) && toBool(v) == null ? "text" : declared;
2225
+ const colType = row.type ?? col.type;
2226
+ const asWords = ty === "text" && colType !== "text";
2227
+ const note = cellNote(cell);
2228
+ const fn = note ? (t.footnotes ?? []).find((f) => f._key === note) : void 0;
2229
+ const fi = fn ? (t.footnotes ?? []).indexOf(fn) : -1;
2230
+ const id = `${row._key}-${col._key}`;
2231
+ const name = col.label || `Column ${ci + 1}`;
2232
+ const canWords = !readOnly && colType !== "text" && colType !== "reference" && colType !== "richtext-inline";
2233
+ const canNote = !readOnly && offered(options).footnotes;
2234
+ const setWords = (on) => {
2235
+ const raw = cellText(col, row, cell, resolveRef);
2236
+ const type = on ? "text" : void 0;
2237
+ const value = coerce(raw, {
2238
+ type: type ?? colType,
2239
+ max: col.max
2240
+ });
2241
+ onWrite(type || note ? {
2242
+ value,
2243
+ ...type ? { type } : {},
2244
+ ...note ? { note } : {}
2245
+ } : value);
2246
+ };
2247
+ const addNote = () => {
2248
+ const [next, key] = linkNote(t, row._key, col._key);
2249
+ set(next);
2250
+ focusSoon(`[data-footnote="${key}"]`);
2251
+ };
2252
+ const b = toBool(v);
2253
+ let control;
2254
+ if (ty === "boolean") control = /* @__PURE__ */ jsxs("label", {
2255
+ className: "flex h-8 items-center gap-2.5",
2256
+ children: [/* @__PURE__ */ jsx(Switch, {
2257
+ id,
2258
+ size: "sm",
2259
+ "aria-labelledby": `${id}-name`,
2260
+ "aria-describedby": `${id}-says`,
2261
+ disabled: readOnly,
2262
+ checked: b === true,
2263
+ onCheckedChange: (x) => onWrite(withValue(cell, x))
2264
+ }), /* @__PURE__ */ jsx("span", {
2265
+ id: `${id}-says`,
2266
+ className: cn("text-kit-sm", b == null ? "text-kit-fg-4" : "text-kit-fg-2"),
2267
+ children: b == null ? "Not set" : b ? boolLabels(col).yes : boolLabels(col).no
2268
+ })]
2269
+ });
2270
+ else if (ty === "reference") control = /* @__PURE__ */ jsx("div", {
2271
+ className: "rounded-kit-md border border-kit-field-border bg-kit-field-bg",
2272
+ children: /* @__PURE__ */ jsx(RefCell, {
2273
+ ctx,
2274
+ cell,
2275
+ col,
2276
+ cellId: id,
2277
+ name,
2278
+ onWrite,
2279
+ onMove: noop
2280
+ })
2281
+ });
2282
+ else if (ty === "link") {
2283
+ const l = isObjLike(v) && !("ref" in v) ? v : {
2284
+ label: typeof v === "string" ? v : "",
2285
+ href: ""
2286
+ };
2287
+ control = /* @__PURE__ */ jsxs(FieldUnit, { children: [/* @__PURE__ */ jsx(FieldUnitRow, { children: /* @__PURE__ */ jsx("input", {
2288
+ id,
2289
+ className: "h-9 w-full min-w-0 bg-transparent px-2 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-4",
2290
+ readOnly,
2291
+ defaultValue: l.label,
2292
+ placeholder: "Link text",
2293
+ "aria-label": `${name} link text`,
2294
+ onBlur: (e) => e.target.value !== l.label && onWrite(withValue(cell, {
2295
+ ...l,
2296
+ label: e.target.value
2297
+ }))
2298
+ }, `l${l.label}`) }), /* @__PURE__ */ jsx(FieldUnitRow, { children: /* @__PURE__ */ jsx(LinkField, {
2299
+ "aria-label": `${name} link`,
2300
+ value: tableLinkValue(l),
2301
+ readOnly,
2302
+ className: "border-0 bg-transparent shadow-none",
2303
+ onChange: (n) => {
2304
+ const o = n && typeof n === "object" ? n : null;
2305
+ if (o && isScriptHref(hrefOf(o))) return;
2306
+ onWrite(withValue(cell, o ? tableLink(l.label || linkText(o), hrefOf(o), o.newTab, o.rel) : {
2307
+ label: l.label,
2308
+ href: ""
2309
+ }));
2310
+ }
2311
+ }) })] });
2312
+ } else control = /* @__PURE__ */ jsx(FormText, {
2313
+ id,
2314
+ readOnly,
2315
+ autoFocus: needsName,
2316
+ value: isEmptyCell(v) ? "" : NUMERIC.includes(ty) ? String(toNumber(v) ?? cellText(col, row, cell)) : ty === "richtext-inline" ? String(v) : cellText(col, row, cell, resolveRef),
2317
+ suffix: ty === "number" ? col.unit : ty === "money" ? col.currency ?? "USD" : ty === "rating" ? `/ ${col.max ?? 5}` : void 0,
2318
+ numeric: NUMERIC.includes(ty),
2319
+ onCommit: (raw) => onWrite(typedCell(cell, col, row, raw))
2320
+ });
2321
+ return /* @__PURE__ */ jsxs("div", {
2322
+ className: "group/cell flex min-w-0 flex-col gap-1.5",
2323
+ children: [
2324
+ /* @__PURE__ */ jsxs("div", {
2325
+ className: "flex min-h-5 min-w-0 items-center gap-1.5",
2326
+ children: [
2327
+ /* @__PURE__ */ jsx("label", {
2328
+ id: `${id}-name`,
2329
+ htmlFor: id,
2330
+ className: "truncate text-kit-sm font-medium text-kit-fg-2 transition-colors group-focus-within/cell:text-kit-fg",
2331
+ children: name
2332
+ }),
2333
+ needsName ? /* @__PURE__ */ jsx("span", {
2334
+ className: "shrink-0 text-kit-xs text-kit-warning-fg",
2335
+ children: "Needs a name"
2336
+ }) : null,
2337
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
2338
+ canWords || canNote || !readOnly && !isEmptyCell(v) ? /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
2339
+ "aria-label": `Options for ${name}`,
2340
+ className: cn(DOTS, "-my-1 opacity-0 focus-visible:opacity-100 group-hover/cell:opacity-100 group-focus-within/cell:opacity-100 data-[popup-open]:opacity-100 [@media(pointer:coarse)]:opacity-100"),
2341
+ children: /* @__PURE__ */ jsx(IconDots, {
2342
+ className: "size-3.5",
2343
+ stroke: 1.5
2344
+ })
2345
+ }), /* @__PURE__ */ jsxs(MenuContent, {
2346
+ align: "end",
2347
+ className: "min-w-52",
2348
+ children: [
2349
+ canWords ? /* @__PURE__ */ jsx(MenuItem, {
2350
+ onClick: () => setWords(!asWords),
2351
+ children: asWords ? `Use ${TYPE_UI[colType].label} like the column` : "Write words instead"
2352
+ }) : null,
2353
+ canNote ? note ? /* @__PURE__ */ jsx(MenuItem, {
2354
+ onClick: () => set(unlinkNote(t, row._key, col._key)),
2355
+ children: "Remove footnote"
2356
+ }) : /* @__PURE__ */ jsx(MenuItem, {
2357
+ onClick: addNote,
2358
+ children: "Add a footnote"
2359
+ }) : null,
2360
+ !isEmptyCell(v) ? /* @__PURE__ */ jsxs(Fragment, { children: [canWords || canNote ? /* @__PURE__ */ jsx(MenuSeparator, {}) : null, /* @__PURE__ */ jsx(MenuItem, {
2361
+ onClick: () => onWrite(withValue(cell, null)),
2362
+ children: "Clear"
2363
+ })] }) : null
2364
+ ]
2365
+ })] }) : null
2366
+ ]
2367
+ }),
2368
+ control,
2369
+ fn ? /* @__PURE__ */ jsxs("div", {
2370
+ className: "flex items-center gap-2",
2371
+ children: [/* @__PURE__ */ jsxs("span", {
2372
+ className: "shrink-0 text-kit-xs text-kit-fg-3",
2373
+ children: ["Footnote ", fi + 1]
2374
+ }), /* @__PURE__ */ jsx(Input, {
2375
+ size: "sm",
2376
+ "data-footnote": fn._key,
2377
+ value: fn.text,
2378
+ readOnly,
2379
+ maxLength: 2e3,
2380
+ placeholder: "What the footnote says",
2381
+ "aria-label": `${name}: footnote ${fi + 1}`,
2382
+ onChange: (e) => set({
2383
+ ...t,
2384
+ footnotes: (t.footnotes ?? []).map((x) => x._key === fn._key ? {
2385
+ ...x,
2386
+ text: e.target.value
2387
+ } : x)
2388
+ })
2389
+ })]
2390
+ }) : null
2391
+ ]
2392
+ });
2393
+ }
2394
+ function SwitchRow({ label, checked, onChange, disabled }) {
2395
+ return /* @__PURE__ */ jsxs("label", {
2396
+ className: "flex min-h-8 items-center justify-between gap-2 text-kit-sm text-kit-fg-2",
2397
+ children: [label, /* @__PURE__ */ jsx(Switch, {
2398
+ size: "sm",
2399
+ checked,
2400
+ disabled,
2401
+ onCheckedChange: onChange,
2402
+ "aria-label": label
2403
+ })]
2404
+ });
2405
+ }
2406
+ function ColumnFields({ ctx, col }) {
2407
+ const { t, set, lock, types, readOnly } = ctx;
2408
+ const id = React.useId();
2409
+ const patch = (p) => set({
2410
+ ...t,
2411
+ columns: t.columns.map((c) => c._key === col._key ? withPatch(c, p) : c)
2412
+ });
2413
+ return /* @__PURE__ */ jsxs("div", {
2414
+ className: "flex flex-col gap-4",
2415
+ children: [
2416
+ /* @__PURE__ */ jsxs("div", {
2417
+ className: "flex flex-col gap-1.5",
2418
+ children: [
2419
+ /* @__PURE__ */ jsx("label", {
2420
+ htmlFor: id,
2421
+ className: "text-kit-sm font-medium text-kit-fg-2",
2422
+ children: "Name"
2423
+ }),
2424
+ /* @__PURE__ */ jsx(Input, {
2425
+ id,
2426
+ size: "sm",
2427
+ autoFocus: !col.label && !lock,
2428
+ readOnly: lock,
2429
+ maxLength: 300,
2430
+ value: col.label,
2431
+ placeholder: "Column name",
2432
+ onChange: (e) => patch({ label: e.target.value })
2433
+ }),
2434
+ lock && !readOnly ? /* @__PURE__ */ jsx("span", {
2435
+ className: "text-kit-2xs leading-4 text-kit-fg-3",
2436
+ children: "This table's columns are set by its developer."
2437
+ }) : null
2438
+ ]
2439
+ }),
2440
+ /* @__PURE__ */ jsxs("div", {
2441
+ className: "flex flex-col gap-1.5",
2442
+ children: [/* @__PURE__ */ jsx("span", {
2443
+ className: "text-kit-sm font-medium text-kit-fg-2",
2444
+ children: "Type"
2445
+ }), lock ? /* @__PURE__ */ jsxs("span", {
2446
+ className: "flex h-8 items-center gap-2 text-kit-sm text-kit-fg-2",
2447
+ children: [/* @__PURE__ */ jsx(TypeIcon, {
2448
+ type: col.type,
2449
+ className: "text-kit-fg-2"
2450
+ }), TYPE_UI[col.type].label]
2451
+ }) : /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
2452
+ render: /* @__PURE__ */ jsx(Button, {
2453
+ size: "sm",
2454
+ variant: "secondary",
2455
+ className: "justify-between",
2456
+ leftIcon: /* @__PURE__ */ jsx(TypeIcon, {
2457
+ type: col.type,
2458
+ className: "text-kit-fg-2"
2459
+ }),
2460
+ rightIcon: /* @__PURE__ */ jsx(IconChevronDown, { stroke: 1.5 })
2461
+ }),
2462
+ children: /* @__PURE__ */ jsx("span", {
2463
+ className: "flex-1 text-left",
2464
+ children: TYPE_UI[col.type].label
2465
+ })
2466
+ }), /* @__PURE__ */ jsx(MenuContent, {
2467
+ align: "start",
2468
+ className: "min-w-52",
2469
+ children: /* @__PURE__ */ jsx(MenuRadioGroup, {
2470
+ value: col.type,
2471
+ onValueChange: (v) => ctx.edit((x) => retype(x, col._key, v, ctx.resolveRef)),
2472
+ children: (types.includes(col.type) ? types : [...types, col.type]).map((ty) => /* @__PURE__ */ jsx(MenuRadioItem, {
2473
+ value: ty,
2474
+ children: /* @__PURE__ */ jsxs("span", {
2475
+ className: "flex items-center gap-2",
2476
+ children: [/* @__PURE__ */ jsx(TypeIcon, {
2477
+ type: ty,
2478
+ className: "text-kit-fg-2"
2479
+ }), TYPE_UI[ty].label]
2480
+ })
2481
+ }, ty))
2482
+ })
2483
+ })] })]
2484
+ }),
2485
+ /* @__PURE__ */ jsx(ColumnDetails, {
2486
+ col,
2487
+ onPatch: patch,
2488
+ compact: false,
2489
+ readOnly: lock
2490
+ })
2491
+ ]
2492
+ });
2493
+ }
2494
+ function FormText({ id, value, onCommit, suffix, numeric, readOnly, autoFocus }) {
2495
+ const [draft, setDraft] = React.useState(value);
2496
+ const [seen, setSeen] = React.useState(value);
2497
+ if (seen !== value) {
2498
+ setSeen(value);
2499
+ setDraft(value);
2500
+ }
2501
+ return /* @__PURE__ */ jsxs("div", {
2502
+ className: "relative",
2503
+ children: [/* @__PURE__ */ jsx(Textarea, {
2504
+ id,
2505
+ rows: 1,
2506
+ value: draft,
2507
+ readOnly,
2508
+ autoFocus,
2509
+ maxLength: 5e3,
2510
+ inputMode: numeric ? "decimal" : void 0,
2511
+ onChange: (e) => setDraft(e.target.value),
2512
+ onBlur: () => draft !== value && onCommit(draft),
2513
+ className: cn("min-h-8 resize-none py-1.5", suffix && "pr-12")
2514
+ }), suffix ? /* @__PURE__ */ jsx("span", {
2515
+ className: "pointer-events-none absolute right-2.5 top-1.5 text-kit-xs text-kit-fg-3",
2516
+ children: suffix
2517
+ }) : null]
2518
+ });
2519
+ }
2520
+ var SEARCH = [
2521
+ {
2522
+ value: "none",
2523
+ label: "Nothing special"
2524
+ },
2525
+ {
2526
+ value: "ItemList",
2527
+ label: "A comparison"
2528
+ },
2529
+ {
2530
+ value: "Dataset",
2531
+ label: "A data report"
2532
+ },
2533
+ {
2534
+ value: "Offers",
2535
+ label: "A price list"
2536
+ }
2537
+ ];
2538
+ var NO_COLUMN = "__none";
2539
+ /** Totals on: an empty totals row appears at the end of the list. Off: empty totals rows go, filled ones rejoin the body. */
2540
+ function setTotals(t, on) {
2541
+ if (on) return t.rows.some((r) => r.footer) ? t : {
2542
+ ...t,
2543
+ rows: [...t.rows, {
2544
+ _key: tkey("r"),
2545
+ cells: {},
2546
+ footer: true
2547
+ }]
2548
+ };
2549
+ return {
2550
+ ...t,
2551
+ rows: t.rows.filter((r) => !r.footer || Object.values(r.cells).some((c) => !isEmptyCell(cellValue(c)))).map((r) => r.footer ? clean({
2552
+ ...r,
2553
+ footer: void 0
2554
+ }) : r)
2555
+ };
2556
+ }
2557
+ function TableSettings({ ctx }) {
2558
+ const { t, set, developer, options } = ctx;
2559
+ const can = offered(options);
2560
+ const d = t.design ?? {};
2561
+ const sortable = t.columns.some((c) => c.sortable);
2562
+ const totals = t.rows.some((r) => r.footer);
2563
+ const phones = d.responsive ?? "scroll";
2564
+ const highlighted = t.columns.find((c) => c.highlight);
2565
+ const pickable = t.columns.filter((_, i) => !(t.headerColumn && i === 0));
2566
+ const jsonOffered = SEARCH.filter((x) => x.value === "none" || can.jsonLd.includes(x.value));
2567
+ const showJson = can.jsonLd.length > 0 || !!t.jsonLd && t.jsonLd.type !== "none";
2568
+ if (!(can.headers || can.totals || can.phones.length || can.highlight || can.sort || can.search || showJson || developer)) return null;
2569
+ const design = (p) => set({
2570
+ ...t,
2571
+ design: withPatch(d, p)
2572
+ });
2573
+ const summary = [
2574
+ can.phones.length ? `${PHONES.find((p) => p.value === phones)?.label ?? "Scroll"} on phones` : "",
2575
+ can.highlight && highlighted ? `${highlighted.label || "A column"} highlighted` : "",
2576
+ can.totals && totals ? "Totals row" : ""
2577
+ ].filter(Boolean).join(" · ");
2578
+ const pick = (label, node) => /* @__PURE__ */ jsxs("div", {
2579
+ className: "flex flex-col gap-1.5",
2580
+ children: [/* @__PURE__ */ jsx("span", {
2581
+ className: "text-kit-sm font-medium text-kit-fg-2",
2582
+ children: label
2583
+ }), node]
2584
+ });
2585
+ return /* @__PURE__ */ jsxs(FieldSection, {
2586
+ title: "Table settings",
2587
+ defaultOpen: false,
2588
+ summary,
2589
+ className: "before:hidden",
2590
+ children: [
2591
+ can.headers ? /* @__PURE__ */ jsxs("div", {
2592
+ className: "flex flex-col",
2593
+ children: [
2594
+ /* @__PURE__ */ jsx(SwitchRow, {
2595
+ label: "Show column names",
2596
+ checked: t.headerRow,
2597
+ onChange: (v) => set({
2598
+ ...t,
2599
+ headerRow: v
2600
+ })
2601
+ }),
2602
+ /* @__PURE__ */ jsx(SwitchRow, {
2603
+ label: "First column names each row",
2604
+ checked: t.headerColumn,
2605
+ onChange: (v) => set({
2606
+ ...t,
2607
+ headerColumn: v
2608
+ })
2609
+ }),
2610
+ can.totals ? /* @__PURE__ */ jsx(SwitchRow, {
2611
+ label: "Totals row",
2612
+ checked: totals,
2613
+ onChange: (v) => set(setTotals(t, v))
2614
+ }) : null
2615
+ ]
2616
+ }) : can.totals ? /* @__PURE__ */ jsx(SwitchRow, {
2617
+ label: "Totals row",
2618
+ checked: totals,
2619
+ onChange: (v) => set(setTotals(t, v))
2620
+ }) : null,
2621
+ can.highlight ? pick("Highlight column", /* @__PURE__ */ jsx(Select, {
2622
+ "aria-label": "Highlight column",
2623
+ value: highlighted?._key ?? NO_COLUMN,
2624
+ onValueChange: (k) => set({
2625
+ ...t,
2626
+ columns: t.columns.map((c) => withPatch(c, { highlight: c._key === k ? true : void 0 }))
2627
+ }),
2628
+ options: [{
2629
+ value: NO_COLUMN,
2630
+ label: "None"
2631
+ }, ...pickable.map((c) => ({
2632
+ value: c._key,
2633
+ label: c.label || "Untitled column"
2634
+ }))]
2635
+ })) : null,
2636
+ can.phones.length ? pick("On phones", /* @__PURE__ */ jsx(ChoiceSwitch, {
2637
+ "aria-label": "On phones",
2638
+ value: phones,
2639
+ onChange: (responsive) => design({ responsive }),
2640
+ items: can.phones
2641
+ })) : null,
2642
+ can.sort || can.search ? /* @__PURE__ */ jsxs("div", {
2643
+ className: "flex flex-col",
2644
+ children: [can.sort ? /* @__PURE__ */ jsx(SwitchRow, {
2645
+ label: "Visitors can sort columns",
2646
+ checked: sortable,
2647
+ onChange: (v) => set({
2648
+ ...t,
2649
+ columns: t.columns.map((c, i) => withPatch(c, { sortable: v && !(t.headerColumn && i === 0) ? true : void 0 }))
2650
+ })
2651
+ }) : null, can.search ? /* @__PURE__ */ jsx(SwitchRow, {
2652
+ label: "Visitors can search rows",
2653
+ checked: !!t.filterable,
2654
+ onChange: (v) => set(dropUndefined({
2655
+ ...t,
2656
+ filterable: v || void 0
2657
+ }))
2658
+ }) : null]
2659
+ }) : null,
2660
+ showJson ? /* @__PURE__ */ jsxs(Fragment, { children: [pick("Help search engines read this as", /* @__PURE__ */ jsx(ChoiceSwitch, {
2661
+ "aria-label": "Help search engines read this as",
2662
+ value: t.jsonLd?.type ?? "none",
2663
+ onChange: (type) => set(dropUndefined({
2664
+ ...t,
2665
+ jsonLd: type === "none" ? void 0 : {
2666
+ ...t.jsonLd,
2667
+ type,
2668
+ ...type === "ItemList" ? { axis: t.jsonLd?.axis ?? "rows" } : {}
2669
+ }
2670
+ })),
2671
+ items: jsonOffered
2672
+ })), t.jsonLd?.type === "ItemList" && developer ? pick("The things compared are the", /* @__PURE__ */ jsx(ChoiceSwitch, {
2673
+ "aria-label": "The things compared are the",
2674
+ value: t.jsonLd.axis ?? "rows",
2675
+ onChange: (axis) => set({
2676
+ ...t,
2677
+ jsonLd: {
2678
+ ...t.jsonLd,
2679
+ axis
2680
+ }
2681
+ }),
2682
+ items: [{
2683
+ value: "rows",
2684
+ label: "Rows"
2685
+ }, {
2686
+ value: "columns",
2687
+ label: "Columns"
2688
+ }]
2689
+ })) : null] }) : null,
2690
+ developer ? /* @__PURE__ */ jsxs("div", {
2691
+ className: "flex flex-col",
2692
+ children: [
2693
+ /* @__PURE__ */ jsx(SwitchRow, {
2694
+ label: "Hide the title on the page",
2695
+ checked: !!d.hideCaption,
2696
+ onChange: (v) => design({ hideCaption: v || void 0 })
2697
+ }),
2698
+ can.sticky ? /* @__PURE__ */ jsx(SwitchRow, {
2699
+ label: "Keep column names in view",
2700
+ checked: !!d.sticky,
2701
+ onChange: (v) => design({ sticky: v || void 0 })
2702
+ }) : null,
2703
+ /* @__PURE__ */ jsx(SwitchRow, {
2704
+ label: "Striped rows",
2705
+ checked: !!d.striped,
2706
+ onChange: (v) => design({ striped: v || void 0 })
2707
+ }),
2708
+ /* @__PURE__ */ jsx(SwitchRow, {
2709
+ label: "Compact",
2710
+ checked: d.density === "compact",
2711
+ onChange: (v) => design({ density: v ? "compact" : void 0 })
2712
+ })
2713
+ ]
2714
+ }) : null
2715
+ ]
2716
+ });
2717
+ }
2718
+ var dropUndefined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
2719
+ //#endregion
2720
+ export { TableEditor, TableFullScreenButton, TableItemEditor };
2721
+
2722
+ //# sourceMappingURL=table-editor.js.map