@bettercms-ai/kit 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +90 -31
  8. package/dist/adapters/lossy.js +414 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
  11. package/{adapters → dist/adapters}/prod-types.js +71 -3
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +996 -179
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +92 -2
  22. package/{context.js → dist/context.js} +5 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/{controls → dist/controls}/form-picker-register.js +1 -1
  50. package/dist/controls/form-picker-register.js.map +1 -0
  51. package/{controls → dist/controls}/form-picker.js +11 -9
  52. package/dist/controls/form-picker.js.map +1 -0
  53. package/{controls → dist/controls}/icon-register.js +1 -1
  54. package/dist/controls/icon-register.js.map +1 -0
  55. package/{controls → dist/controls}/icon.d.ts +4 -2
  56. package/{controls → dist/controls}/icon.js +32 -27
  57. package/dist/controls/icon.js.map +1 -0
  58. package/{controls → dist/controls}/index.d.ts +1 -1
  59. package/{controls → dist/controls}/index.js +4 -3
  60. package/dist/controls/index.js.map +1 -0
  61. package/{controls → dist/controls}/json-register.js +1 -1
  62. package/dist/controls/json-register.js.map +1 -0
  63. package/{controls → dist/controls}/json.js +13 -3
  64. package/dist/controls/json.js.map +1 -0
  65. package/{controls → dist/controls}/link.js +6 -6
  66. package/dist/controls/link.js.map +1 -0
  67. package/{controls → dist/controls}/location-register.js +1 -1
  68. package/dist/controls/location-register.js.map +1 -0
  69. package/{controls → dist/controls}/location.js +64 -40
  70. package/dist/controls/location.js.map +1 -0
  71. package/{controls → dist/controls}/media-register.js +1 -1
  72. package/dist/controls/media-register.js.map +1 -0
  73. package/{controls → dist/controls}/media-services.d.ts +6 -0
  74. package/dist/controls/media-services.js +0 -0
  75. package/{controls → dist/controls}/media.d.ts +35 -4
  76. package/{controls → dist/controls}/media.js +491 -171
  77. package/dist/controls/media.js.map +1 -0
  78. package/{controls → dist/controls}/number.js +10 -9
  79. package/dist/controls/number.js.map +1 -0
  80. package/{controls → dist/controls}/reference-register.js +1 -1
  81. package/dist/controls/reference-register.js.map +1 -0
  82. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  83. package/dist/controls/reference-services.js +0 -0
  84. package/{controls → dist/controls}/reference.d.ts +1 -1
  85. package/{controls → dist/controls}/reference.js +93 -77
  86. package/dist/controls/reference.js.map +1 -0
  87. package/dist/controls/rich-text/blocks.d.ts +49 -0
  88. package/{controls → dist/controls}/rich-text/blocks.js +471 -144
  89. package/dist/controls/rich-text/blocks.js.map +1 -0
  90. package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
  91. package/{controls → dist/controls}/rich-text/catalog.js +75 -65
  92. package/dist/controls/rich-text/catalog.js.map +1 -0
  93. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  94. package/{controls → dist/controls}/rich-text/codec.js +3 -1
  95. package/dist/controls/rich-text/codec.js.map +1 -0
  96. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  97. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  98. package/dist/controls/rich-text/component-card.js.map +1 -0
  99. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  100. package/dist/controls/rich-text/component-panel.js +141 -0
  101. package/dist/controls/rich-text/component-panel.js.map +1 -0
  102. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  103. package/{controls → dist/controls}/rich-text/control.js +84 -42
  104. package/dist/controls/rich-text/control.js.map +1 -0
  105. package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
  106. package/{controls → dist/controls}/rich-text/dom.js +379 -50
  107. package/dist/controls/rich-text/dom.js.map +1 -0
  108. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  109. package/{controls → dist/controls}/rich-text/editor.js +148 -48
  110. package/dist/controls/rich-text/editor.js.map +1 -0
  111. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  112. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  113. package/dist/controls/rich-text/floating.js.map +1 -0
  114. package/{controls → dist/controls}/rich-text/index.js +1 -1
  115. package/dist/controls/rich-text/index.js.map +1 -0
  116. package/dist/controls/rich-text/link-form.js +147 -0
  117. package/dist/controls/rich-text/link-form.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  119. package/dist/controls/rich-text/markdown.js.map +1 -0
  120. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  121. package/dist/controls/rich-text/ops.js.map +1 -0
  122. package/dist/controls/rich-text/plain.d.ts +17 -0
  123. package/dist/controls/rich-text/plain.js +44 -0
  124. package/dist/controls/rich-text/plain.js.map +1 -0
  125. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  126. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  127. package/dist/controls/rich-text/toolbar.js.map +1 -0
  128. package/{controls → dist/controls}/scale.js +5 -5
  129. package/dist/controls/scale.js.map +1 -0
  130. package/{controls → dist/controls}/slot-register.js +1 -1
  131. package/dist/controls/slot-register.js.map +1 -0
  132. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  133. package/dist/controls/slot-services.js +155 -0
  134. package/dist/controls/slot-services.js.map +1 -0
  135. package/{controls → dist/controls}/slot.js +42 -24
  136. package/dist/controls/slot.js.map +1 -0
  137. package/{controls → dist/controls}/table/index.js +1 -1
  138. package/dist/controls/table/index.js.map +1 -0
  139. package/{controls → dist/controls}/table/prod.js +3 -3
  140. package/dist/controls/table/prod.js.map +1 -0
  141. package/{controls → dist/controls}/table/refs.js +13 -2
  142. package/dist/controls/table/refs.js.map +1 -0
  143. package/{controls → dist/controls}/table/stored.js +1 -1
  144. package/dist/controls/table/stored.js.map +1 -0
  145. package/{controls → dist/controls}/table/table-editor.js +51 -48
  146. package/dist/controls/table/table-editor.js.map +1 -0
  147. package/{controls → dist/controls}/table/table-link.js +3 -3
  148. package/dist/controls/table/table-link.js.map +1 -0
  149. package/{controls → dist/controls}/table/table.js +3 -3
  150. package/dist/controls/table/table.js.map +1 -0
  151. package/{controls → dist/controls}/text.d.ts +2 -2
  152. package/{controls → dist/controls}/text.js +78 -43
  153. package/dist/controls/text.js.map +1 -0
  154. package/dist/controls/unknown-value.d.ts +17 -0
  155. package/dist/controls/unknown-value.js +66 -0
  156. package/dist/controls/unknown-value.js.map +1 -0
  157. package/dist/core/core.d.ts +63 -0
  158. package/dist/core/core.js +171 -0
  159. package/dist/core/core.js.map +1 -0
  160. package/dist/core/facets.d.ts +347 -0
  161. package/dist/core/facets.js +334 -0
  162. package/dist/core/facets.js.map +1 -0
  163. package/dist/core/index.d.ts +3 -0
  164. package/dist/core/index.js +3 -0
  165. package/{engine → dist/engine}/array.js +34 -21
  166. package/dist/engine/array.js.map +1 -0
  167. package/{engine → dist/engine}/bits.js +1 -1
  168. package/dist/engine/bits.js.map +1 -0
  169. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  170. package/{engine → dist/engine}/breadcrumb.js +12 -36
  171. package/dist/engine/breadcrumb.js.map +1 -0
  172. package/{engine → dist/engine}/expand.d.ts +2 -4
  173. package/{engine → dist/engine}/expand.js +5 -22
  174. package/dist/engine/expand.js.map +1 -0
  175. package/{engine → dist/engine}/field-list.js +1 -1
  176. package/dist/engine/field-list.js.map +1 -0
  177. package/{engine → dist/engine}/field-shell.js +249 -121
  178. package/dist/engine/field-shell.js.map +1 -0
  179. package/{engine → dist/engine}/frame.d.ts +3 -1
  180. package/{engine → dist/engine}/frame.js +16 -14
  181. package/dist/engine/frame.js.map +1 -0
  182. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  183. package/{engine → dist/engine}/group-summary.js +7 -3
  184. package/dist/engine/group-summary.js.map +1 -0
  185. package/{engine → dist/engine}/grouping.d.ts +19 -5
  186. package/{engine → dist/engine}/grouping.js +193 -21
  187. package/dist/engine/grouping.js.map +1 -0
  188. package/{engine → dist/engine}/item-list.d.ts +11 -1
  189. package/{engine → dist/engine}/item-list.js +35 -13
  190. package/dist/engine/item-list.js.map +1 -0
  191. package/{engine → dist/engine}/kit-field.js +45 -10
  192. package/dist/engine/kit-field.js.map +1 -0
  193. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  194. package/{engine → dist/engine}/schema-form.js +182 -40
  195. package/dist/engine/schema-form.js.map +1 -0
  196. package/{engine → dist/engine}/slot.js +5 -15
  197. package/dist/engine/slot.js.map +1 -0
  198. package/dist/index.js +47 -0
  199. package/dist/index.js.map +1 -0
  200. package/{kit.css → dist/kit.css} +19 -0
  201. package/{lib → dist/lib}/cn.js +7 -4
  202. package/dist/lib/cn.js.map +1 -0
  203. package/{lib → dist/lib}/columns.js +4 -1
  204. package/dist/lib/columns.js.map +1 -0
  205. package/{lib → dist/lib}/frames.js +2 -2
  206. package/dist/lib/frames.js.map +1 -0
  207. package/dist/lib/icon-image.d.ts +10 -0
  208. package/dist/lib/icon-image.js +8 -0
  209. package/dist/lib/icon-image.js.map +1 -0
  210. package/{lib → dist/lib}/icons.js +4 -3
  211. package/dist/lib/icons.js.map +1 -0
  212. package/dist/lib/input-modality.d.ts +11 -0
  213. package/dist/lib/input-modality.js +47 -0
  214. package/dist/lib/input-modality.js.map +1 -0
  215. package/dist/lib/key-event.d.ts +11 -0
  216. package/dist/lib/key-event.js +16 -0
  217. package/dist/lib/key-event.js.map +1 -0
  218. package/{lib → dist/lib}/path.js +4 -2
  219. package/dist/lib/path.js.map +1 -0
  220. package/{lib → dist/lib}/schema.d.ts +34 -3
  221. package/{lib → dist/lib}/schema.js +110 -13
  222. package/dist/lib/schema.js.map +1 -0
  223. package/{lib → dist/lib}/utils.js +1 -1
  224. package/dist/lib/utils.js.map +1 -0
  225. package/{lib → dist/lib}/validate.d.ts +11 -1
  226. package/{lib → dist/lib}/validate.js +85 -11
  227. package/dist/lib/validate.js.map +1 -0
  228. package/dist/library/analysis.d.ts +23 -0
  229. package/dist/library/analysis.js +160 -0
  230. package/dist/library/analysis.js.map +1 -0
  231. package/dist/library/catalog.d.ts +57 -0
  232. package/dist/library/catalog.js +307 -0
  233. package/dist/library/catalog.js.map +1 -0
  234. package/dist/library/coreNotes.d.ts +8 -0
  235. package/dist/library/coreNotes.js +111 -0
  236. package/dist/library/coreNotes.js.map +1 -0
  237. package/dist/library/coverage.d.ts +40 -0
  238. package/dist/library/coverage.js +59 -0
  239. package/dist/library/coverage.js.map +1 -0
  240. package/dist/library/entries/advanced.entries.d.ts +2 -0
  241. package/dist/library/entries/advanced.entries.js +6579 -0
  242. package/dist/library/entries/advanced.entries.js.map +1 -0
  243. package/dist/library/entries/commerce.entries.d.ts +2 -0
  244. package/dist/library/entries/commerce.entries.js +4140 -0
  245. package/dist/library/entries/commerce.entries.js.map +1 -0
  246. package/dist/library/entries/company.entries.d.ts +2 -0
  247. package/dist/library/entries/company.entries.js +2731 -0
  248. package/dist/library/entries/company.entries.js.map +1 -0
  249. package/dist/library/entries/conversion.entries.d.ts +2 -0
  250. package/dist/library/entries/conversion.entries.js +3707 -0
  251. package/dist/library/entries/conversion.entries.js.map +1 -0
  252. package/dist/library/entries/data.entries.d.ts +7 -0
  253. package/dist/library/entries/data.entries.js +4613 -0
  254. package/dist/library/entries/data.entries.js.map +1 -0
  255. package/dist/library/entries/events.entries.d.ts +2 -0
  256. package/dist/library/entries/events.entries.js +3428 -0
  257. package/dist/library/entries/events.entries.js.map +1 -0
  258. package/dist/library/entries/features.entries.d.ts +2 -0
  259. package/dist/library/entries/features.entries.js +3157 -0
  260. package/dist/library/entries/features.entries.js.map +1 -0
  261. package/dist/library/entries/heroes.entries.d.ts +2 -0
  262. package/dist/library/entries/heroes.entries.js +3401 -0
  263. package/dist/library/entries/heroes.entries.js.map +1 -0
  264. package/dist/library/entries/index.d.ts +3 -0
  265. package/dist/library/entries/index.js +35 -0
  266. package/dist/library/entries/index.js.map +1 -0
  267. package/dist/library/entries/listings.entries.d.ts +2 -0
  268. package/dist/library/entries/listings.entries.js +2976 -0
  269. package/dist/library/entries/listings.entries.js.map +1 -0
  270. package/dist/library/entries/longform.entries.d.ts +2 -0
  271. package/dist/library/entries/longform.entries.js +4227 -0
  272. package/dist/library/entries/longform.entries.js.map +1 -0
  273. package/dist/library/entries/media.entries.d.ts +2 -0
  274. package/dist/library/entries/media.entries.js +2781 -0
  275. package/dist/library/entries/media.entries.js.map +1 -0
  276. package/dist/library/entries/navigation.entries.d.ts +2 -0
  277. package/dist/library/entries/navigation.entries.js +4011 -0
  278. package/dist/library/entries/navigation.entries.js.map +1 -0
  279. package/dist/library/entries/pricing.entries.d.ts +2 -0
  280. package/dist/library/entries/pricing.entries.js +2383 -0
  281. package/dist/library/entries/pricing.entries.js.map +1 -0
  282. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  283. package/dist/library/entries/social-proof.entries.js +2297 -0
  284. package/dist/library/entries/social-proof.entries.js.map +1 -0
  285. package/dist/library/examples/bento.d.ts +92 -0
  286. package/dist/library/examples/bento.js +201 -0
  287. package/dist/library/examples/bento.js.map +1 -0
  288. package/dist/library/examples/blocks.d.ts +14 -0
  289. package/dist/library/examples/blocks.js +313 -0
  290. package/dist/library/examples/blocks.js.map +1 -0
  291. package/dist/library/examples/faq.d.ts +28 -0
  292. package/dist/library/examples/faq.js +230 -0
  293. package/dist/library/examples/faq.js.map +1 -0
  294. package/dist/library/examples/hero.d.ts +43 -0
  295. package/dist/library/examples/hero.js +222 -0
  296. package/dist/library/examples/hero.js.map +1 -0
  297. package/dist/library/examples/index.d.ts +36 -0
  298. package/dist/library/examples/index.js +109 -0
  299. package/dist/library/examples/index.js.map +1 -0
  300. package/dist/library/examples/journalStory.d.ts +93 -0
  301. package/dist/library/examples/journalStory.js +338 -0
  302. package/dist/library/examples/journalStory.js.map +1 -0
  303. package/dist/library/examples/megaMenu.d.ts +134 -0
  304. package/dist/library/examples/megaMenu.js +442 -0
  305. package/dist/library/examples/megaMenu.js.map +1 -0
  306. package/dist/library/examples/pricing.d.ts +103 -0
  307. package/dist/library/examples/pricing.js +479 -0
  308. package/dist/library/examples/pricing.js.map +1 -0
  309. package/dist/library/examples/tabs.d.ts +87 -0
  310. package/dist/library/examples/tabs.js +180 -0
  311. package/dist/library/examples/tabs.js.map +1 -0
  312. package/dist/library/export.d.ts +42 -0
  313. package/dist/library/export.js +80 -0
  314. package/dist/library/export.js.map +1 -0
  315. package/dist/library/index.d.ts +13 -0
  316. package/dist/library/index.js +6 -0
  317. package/dist/library/kit-catalog.json +1510 -0
  318. package/dist/library/types.d.ts +42 -0
  319. package/dist/library/types.js +0 -0
  320. package/{schema → dist/schema}/adapters.js +1 -2
  321. package/dist/schema/adapters.js.map +1 -0
  322. package/{schema → dist/schema}/help.d.ts +2 -0
  323. package/{schema → dist/schema}/help.js +6 -4
  324. package/dist/schema/help.js.map +1 -0
  325. package/{schema → dist/schema}/scale.js +1 -1
  326. package/dist/schema/scale.js.map +1 -0
  327. package/{schema → dist/schema}/sources.js +1 -1
  328. package/dist/schema/sources.js.map +1 -0
  329. package/{schema → dist/schema}/table.js +11 -10
  330. package/dist/schema/table.js.map +1 -0
  331. package/{schema → dist/schema}/types.d.ts +29 -1
  332. package/{schema → dist/schema}/types.js +1 -1
  333. package/dist/schema/types.js.map +1 -0
  334. package/dist/styles.css +2 -0
  335. package/dist/table/table-view.d.ts +14 -0
  336. package/dist/table/table-view.js +140 -0
  337. package/dist/table/table-view.js.map +1 -0
  338. package/dist/table/table.css +73 -0
  339. package/dist/testing/corpus.d.ts +63 -0
  340. package/dist/testing/corpus.js +129 -0
  341. package/dist/testing/corpus.js.map +1 -0
  342. package/dist/testing/test-form.d.ts +11 -0
  343. package/dist/testing/test-form.js +38 -0
  344. package/dist/testing/test-form.js.map +1 -0
  345. package/dist/theme.css +345 -0
  346. package/dist/theme.d.ts +22 -0
  347. package/dist/theme.js +43 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens.css +542 -0
  350. package/dist/types.js +0 -0
  351. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  352. package/{ui → dist/ui}/action-tray.js +20 -19
  353. package/dist/ui/action-tray.js.map +1 -0
  354. package/dist/ui/autocomplete.d.ts +30 -0
  355. package/dist/ui/autocomplete.js +139 -0
  356. package/dist/ui/autocomplete.js.map +1 -0
  357. package/{ui → dist/ui}/button.d.ts +3 -3
  358. package/{ui → dist/ui}/button.js +6 -7
  359. package/dist/ui/button.js.map +1 -0
  360. package/{ui → dist/ui}/choice-switch.js +1 -1
  361. package/dist/ui/choice-switch.js.map +1 -0
  362. package/{ui → dist/ui}/controls.js +51 -39
  363. package/dist/ui/controls.js.map +1 -0
  364. package/{ui → dist/ui}/display.d.ts +10 -3
  365. package/{ui → dist/ui}/display.js +57 -46
  366. package/dist/ui/display.js.map +1 -0
  367. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  368. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  369. package/dist/ui/expanded-editor-modal.js.map +1 -0
  370. package/{ui → dist/ui}/field-context.js +1 -1
  371. package/dist/ui/field-context.js.map +1 -0
  372. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  373. package/{ui → dist/ui}/floating-panel.js +28 -12
  374. package/dist/ui/floating-panel.js.map +1 -0
  375. package/{ui → dist/ui}/index.d.ts +4 -0
  376. package/dist/ui/index.js +18 -0
  377. package/{ui → dist/ui}/input.d.ts +1 -1
  378. package/{ui → dist/ui}/input.js +9 -9
  379. package/dist/ui/input.js.map +1 -0
  380. package/{ui → dist/ui}/mode-bar.js +3 -3
  381. package/dist/ui/mode-bar.js.map +1 -0
  382. package/{ui → dist/ui}/overlay.d.ts +77 -5
  383. package/dist/ui/overlay.js +697 -0
  384. package/dist/ui/overlay.js.map +1 -0
  385. package/{ui → dist/ui}/path-crumbs.js +37 -3
  386. package/dist/ui/path-crumbs.js.map +1 -0
  387. package/{ui → dist/ui}/presence.js +2 -2
  388. package/dist/ui/presence.js.map +1 -0
  389. package/{ui → dist/ui}/select.js +89 -87
  390. package/dist/ui/select.js.map +1 -0
  391. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  392. package/dist/ui/shortcut-hint.js.map +1 -0
  393. package/dist/ui/spinner.d.ts +24 -0
  394. package/dist/ui/spinner.js +42 -0
  395. package/dist/ui/spinner.js.map +1 -0
  396. package/dist/ui/split-button.d.ts +32 -0
  397. package/dist/ui/split-button.js +60 -0
  398. package/dist/ui/split-button.js.map +1 -0
  399. package/{ui → dist/ui}/surfaces.js +1 -1
  400. package/dist/ui/surfaces.js.map +1 -0
  401. package/dist/ui/tab.d.ts +38 -0
  402. package/dist/ui/tab.js +87 -0
  403. package/dist/ui/tab.js.map +1 -0
  404. package/dist/ui/toast.d.ts +20 -0
  405. package/dist/ui/toast.js +115 -0
  406. package/dist/ui/toast.js.map +1 -0
  407. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  408. package/{ui → dist/ui}/tooltip-root.js +9 -8
  409. package/dist/ui/tooltip-root.js.map +1 -0
  410. package/{ui → dist/ui}/variants.js +1 -1
  411. package/dist/ui/variants.js.map +1 -0
  412. package/package.json +77 -23
  413. package/adapters/icons.js.map +0 -1
  414. package/adapters/lossy.js +0 -233
  415. package/adapters/lossy.js.map +0 -1
  416. package/adapters/prod-types.js.map +0 -1
  417. package/adapters/schema.js.map +0 -1
  418. package/adapters/values.js.map +0 -1
  419. package/brand/logo.js +0 -9
  420. package/brand/logo.js.map +0 -1
  421. package/context.js.map +0 -1
  422. package/controls/button.js.map +0 -1
  423. package/controls/c1.js.map +0 -1
  424. package/controls/c2.js.map +0 -1
  425. package/controls/choice.js.map +0 -1
  426. package/controls/code-register.js.map +0 -1
  427. package/controls/code.js.map +0 -1
  428. package/controls/color.js.map +0 -1
  429. package/controls/date-register.js.map +0 -1
  430. package/controls/date-zone.js.map +0 -1
  431. package/controls/date.js.map +0 -1
  432. package/controls/form-picker-register.js.map +0 -1
  433. package/controls/form-picker.js.map +0 -1
  434. package/controls/icon-register.js.map +0 -1
  435. package/controls/icon.js.map +0 -1
  436. package/controls/index.js.map +0 -1
  437. package/controls/json-register.js.map +0 -1
  438. package/controls/json.js.map +0 -1
  439. package/controls/link.js.map +0 -1
  440. package/controls/location-register.js.map +0 -1
  441. package/controls/location.js.map +0 -1
  442. package/controls/media-register.js.map +0 -1
  443. package/controls/media.js.map +0 -1
  444. package/controls/number.js.map +0 -1
  445. package/controls/reference-register.js.map +0 -1
  446. package/controls/reference.js.map +0 -1
  447. package/controls/rich-text/blocks.d.ts +0 -28
  448. package/controls/rich-text/blocks.js.map +0 -1
  449. package/controls/rich-text/catalog.js.map +0 -1
  450. package/controls/rich-text/codec.js.map +0 -1
  451. package/controls/rich-text/component-card.js.map +0 -1
  452. package/controls/rich-text/control.js.map +0 -1
  453. package/controls/rich-text/dom.js.map +0 -1
  454. package/controls/rich-text/editor.js.map +0 -1
  455. package/controls/rich-text/floating.js.map +0 -1
  456. package/controls/rich-text/index.js.map +0 -1
  457. package/controls/rich-text/link-form.js +0 -111
  458. package/controls/rich-text/link-form.js.map +0 -1
  459. package/controls/rich-text/markdown.js.map +0 -1
  460. package/controls/rich-text/ops.js.map +0 -1
  461. package/controls/rich-text/toolbar.js.map +0 -1
  462. package/controls/scale.js.map +0 -1
  463. package/controls/slot-register.js.map +0 -1
  464. package/controls/slot-services.js +0 -38
  465. package/controls/slot-services.js.map +0 -1
  466. package/controls/slot.js.map +0 -1
  467. package/controls/table/index.js.map +0 -1
  468. package/controls/table/prod.js.map +0 -1
  469. package/controls/table/refs.js.map +0 -1
  470. package/controls/table/stored.js.map +0 -1
  471. package/controls/table/table-editor.js.map +0 -1
  472. package/controls/table/table-link.js.map +0 -1
  473. package/controls/table/table.js.map +0 -1
  474. package/controls/text.js.map +0 -1
  475. package/engine/array.js.map +0 -1
  476. package/engine/bits.js.map +0 -1
  477. package/engine/breadcrumb.js.map +0 -1
  478. package/engine/expand.js.map +0 -1
  479. package/engine/field-list.js.map +0 -1
  480. package/engine/field-shell.js.map +0 -1
  481. package/engine/frame.js.map +0 -1
  482. package/engine/group-summary.js.map +0 -1
  483. package/engine/grouping.js.map +0 -1
  484. package/engine/item-list.js.map +0 -1
  485. package/engine/kit-field.js.map +0 -1
  486. package/engine/schema-form.js.map +0 -1
  487. package/engine/slot.js.map +0 -1
  488. package/index.js +0 -55
  489. package/index.js.map +0 -1
  490. package/lib/cn.js.map +0 -1
  491. package/lib/columns.js.map +0 -1
  492. package/lib/frames.js.map +0 -1
  493. package/lib/icons.js.map +0 -1
  494. package/lib/path.js.map +0 -1
  495. package/lib/schema.js.map +0 -1
  496. package/lib/utils.js.map +0 -1
  497. package/lib/validate.js.map +0 -1
  498. package/schema/adapters.js.map +0 -1
  499. package/schema/help.js.map +0 -1
  500. package/schema/scale.js.map +0 -1
  501. package/schema/sources.js.map +0 -1
  502. package/schema/table.js.map +0 -1
  503. package/schema/types.js.map +0 -1
  504. package/ui/action-tray.js.map +0 -1
  505. package/ui/button.js.map +0 -1
  506. package/ui/choice-switch.js.map +0 -1
  507. package/ui/controls.js.map +0 -1
  508. package/ui/display.js.map +0 -1
  509. package/ui/expanded-editor-modal.js.map +0 -1
  510. package/ui/field-context.js.map +0 -1
  511. package/ui/floating-panel.js.map +0 -1
  512. package/ui/index.js +0 -13
  513. package/ui/input.js.map +0 -1
  514. package/ui/mode-bar.js.map +0 -1
  515. package/ui/overlay.js +0 -378
  516. package/ui/overlay.js.map +0 -1
  517. package/ui/path-crumbs.js.map +0 -1
  518. package/ui/presence.js.map +0 -1
  519. package/ui/select.js.map +0 -1
  520. package/ui/shortcut-hint.js.map +0 -1
  521. package/ui/surfaces.js.map +0 -1
  522. package/ui/tooltip-root.js.map +0 -1
  523. package/ui/variants.js.map +0 -1
  524. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  525. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  526. /package/{brand → dist/brand}/logo.d.ts +0 -0
  527. /package/{controls → dist/controls}/c1.d.ts +0 -0
  528. /package/{controls → dist/controls}/c2.d.ts +0 -0
  529. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  530. /package/{controls → dist/controls}/code.d.ts +0 -0
  531. /package/{controls → dist/controls}/color.d.ts +0 -0
  532. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  533. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  534. /package/{controls → dist/controls}/date.d.ts +0 -0
  535. /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
  536. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  537. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  538. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  539. /package/{controls → dist/controls}/json.d.ts +0 -0
  540. /package/{controls → dist/controls}/link.d.ts +0 -0
  541. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  542. /package/{controls → dist/controls}/location.d.ts +0 -0
  543. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  544. /package/{controls → dist/controls}/number.d.ts +0 -0
  545. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  546. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  547. /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
  548. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  549. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  550. /package/{controls → dist/controls}/scale.d.ts +0 -0
  551. /package/{controls → dist/controls}/slot-register.d.ts +0 -0
  552. /package/{controls → dist/controls}/slot.d.ts +0 -0
  553. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  554. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  555. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  556. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  557. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  558. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  559. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  560. /package/{engine → dist/engine}/array.d.ts +0 -0
  561. /package/{engine → dist/engine}/bits.d.ts +0 -0
  562. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  563. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  564. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  565. /package/{engine → dist/engine}/slot.d.ts +0 -0
  566. /package/{index.d.ts → dist/index.d.ts} +0 -0
  567. /package/{lib → dist/lib}/cn.d.ts +0 -0
  568. /package/{lib → dist/lib}/columns.d.ts +0 -0
  569. /package/{lib → dist/lib}/frames.d.ts +0 -0
  570. /package/{lib → dist/lib}/icons.d.ts +0 -0
  571. /package/{lib → dist/lib}/path.d.ts +0 -0
  572. /package/{lib → dist/lib}/utils.d.ts +0 -0
  573. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  574. /package/{schema → dist/schema}/scale.d.ts +0 -0
  575. /package/{schema → dist/schema}/sources.d.ts +0 -0
  576. /package/{schema → dist/schema}/table.d.ts +0 -0
  577. /package/{types.d.ts → dist/types.d.ts} +0 -0
  578. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  579. /package/{ui → dist/ui}/controls.d.ts +0 -0
  580. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  581. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  582. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  583. /package/{ui → dist/ui}/presence.d.ts +0 -0
  584. /package/{ui → dist/ui}/select.d.ts +0 -0
  585. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  586. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  587. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.js","names":[],"sources":["../../src/engine/array.tsx"],"sourcesContent":["/**\n * ARRAYS — compact PREVIEW ROWS that rest closed (CPO D8 + production; V2 HEAD 9829bf1 kit/engine/array.tsx): grip ·\n * thumb · title + subtitle · validation dot · presence · always-visible ⋯ (Move up/down, Duplicate, Add above/below,\n * Remove). Opening a row follows ONE rule (CPO D43): ≤3 simple fields expand inline, else it drills in (`openMode`\n * overrides). Reorder by drag with layout animation; delete with an Undo toast; \"Add {noun}\" (a type menu when several\n * item types); min/max honoured.\n * Arrays of primitives render as a gallery (images), reference chips, or — for text, numbers and URLs — the ITEM LIST\n * (CPO D47): one input per row, no drill. Arrays of one-field objects (`[{ text }]`) use the same item list. Small\n * objects with an `included` / `isIncluded` switch get that switch as a check on the row itself.\n *\n * Host wiring (RowsHostContext): a drill row calls `drill(path)` (the frame push); without one it falls back to\n * `form.navigate` while the form draws frames (`form.canNavigate`), else drill rows are inert (no button, no ›).\n * Dialog items render the host's `NestedForm` (V2 kit-field NestedForm: its own navigation stack); without one the\n * dialog shows the item's FieldList.\n *\n * Kit deviations from V2: sorting is `useDragReorder` (no @dnd-kit in the kit; it keeps dnd-kit's pointer and keyboard\n * sensor semantics: Space / Enter picks up, arrows move, Space / Enter drops as one write, Escape cancels; the table editor's cross-list drag via\n * `sortableId` is not ported); toasts come from KitServices (absent → silent); the gallery and reference-chip controls come from\n * ARRAY_CONTROLS (registered by the controls lane); a host that never registered them edits the raw list (FallbackControl).\n */\nimport * as React from \"react\";\nimport type { ComponentType } from \"react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport {\n IconArrowDown, IconArrowUp, IconArrowsDiagonal, IconCheck, IconChevronDown, IconChevronRight, IconCopy, IconDots, IconGripVertical, IconMinus, IconPlus, IconRowInsertBottom, IconRowInsertTop, IconTrash, IconX,\n} from \"@tabler/icons-react\";\nimport { Button } from \"../ui/button\";\nimport { Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuTrigger, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Popover, PopoverAnchor, PopoverContent, Tooltip } from \"../ui/overlay\";\nimport { cn } from \"../lib/cn\";\nimport type { FieldPath, FieldSchema } from \"../schema/types\";\nimport type { ControlProps } from \"../types\";\nimport { useForm, useKitEnv, useKitServices } from \"../context\";\nimport { ensureKeys, isObj, itemId, newKey, pathKey } from \"../lib/path\";\nimport { initialFor, itemNoun, itemOpenMode, itemSchemaFor, itemSchemas, newItem, previewOf, primitiveItem, type Preview } from \"../lib/schema\";\nimport { IssueDot, Thumb } from \"./bits\";\nimport { KitIcon } from \"../lib/icons\";\nimport { FieldShell, PeerStack } from \"./field-shell\";\nimport { FieldLabelForContext } from \"../ui/field-context\";\nimport { FieldList } from \"./field-list\";\nimport { INSET_LINE, InsetScope } from \"./grouping\";\nimport { arrayMove, ItemList, OrderLockSlot, useDragReorder, type ItemKind, type ItemListAdapter } from \"./item-list\";\nimport { CONTROLS, FallbackControl, useFieldAccess } from \"./kit-field\";\n\n/* ── Host wiring ───────────────────────────────────────────────────── */\n/** V2 kit-field NestedForm's props: a dialog's own SchemaForm over `fields`, writing into the parent form at `path`. */\nexport interface NestedFormProps {\n fields: FieldSchema[];\n title: string;\n icon?: string;\n path: FieldPath;\n navRef?: React.Ref<{ back: () => boolean }>;\n}\nexport interface RowsHost {\n /** Push a frame for an item / block path (F7b frames). Default: `form.navigate` while `form.canNavigate`. */\n drill?: (path: FieldPath) => void;\n /** Dialog-mode items: V2's NestedForm (own navigation stack). Default: the item's FieldList. */\n NestedForm?: ComponentType<NestedFormProps>;\n}\nexport const RowsHostContext = React.createContext<RowsHost>({});\n/** The frame push for a drill row, or undefined when nothing can draw the frame (the row is then inert). */\nexport function useDrill(): ((path: FieldPath) => void) | undefined {\n const host = React.useContext(RowsHostContext);\n const form = useForm();\n return host.drill ?? (form?.canNavigate ? form.navigate : undefined);\n}\n\n/** Primitive-array controls V2 imports from controls/media (GalleryControl) and controls/reference (ReferencesControl). */\nexport const ARRAY_CONTROLS: { gallery?: ComponentType<ControlProps>; references?: ComponentType<ControlProps> } = {};\n\nconst plural = (noun: string) => (noun.endsWith(\"y\") && !/[aeiou]y$/.test(noun) ? `${noun.slice(0, -1)}ies` : noun.endsWith(\"s\") ? noun : `${noun}s`);\n\nexport function ArrayField({ field, path }: { field: FieldSchema; path: FieldPath; parent?: Record<string, unknown> }) {\n const prim = primitiveItem(field);\n if (prim) return <PrimitiveArray field={field} item={prim} path={path} />;\n const one = oneFieldItem(field);\n if (one) return <OneFieldArray field={field} item={one.item} inner={one.inner} path={path} />;\n return <ObjectArray field={field} path={path} />;\n}\n\n/** Item types that edit as one line in the item list. */\nconst LIST_KIND: Partial<Record<FieldSchema[\"type\"], ItemKind>> = { string: \"text\", text: \"text\", slug: \"text\", url: \"url\", email: \"email\", number: \"number\" };\n\n/** `[{ _key, text }]` — an object item with exactly one line-like field edits as the item list (unless the schema forces another open mode). */\nfunction oneFieldItem(field: FieldSchema): { item: FieldSchema; inner: FieldSchema } | undefined {\n if (field.openMode && field.openMode !== \"inline\") return undefined;\n const of = itemSchemas(field);\n const item = of.length === 1 ? of[0] : undefined;\n const inner = item?.type === \"object\" && item.fields?.length === 1 ? item.fields[0] : undefined;\n return item && inner && LIST_KIND[inner.type] && !inner.scale ? { item, inner } : undefined;\n}\n\n/** The boolean an item shows as a check on its row (\"included\" in a feature list). */\nconst ROW_TOGGLE = /^(is)?included$/i;\nexport const rowToggleField = (s?: FieldSchema) => s?.fields?.find((f) => f.type === \"boolean\" && ROW_TOGGLE.test(f.name));\n\n/** List meta on the message line: \"3 items · max 6\". */\nfunction listMeta(n: number, field: FieldSchema) {\n const { min, max } = field.validation ?? {};\n const base = `${n} ${n === 1 ? \"item\" : \"items\"}`;\n return max != null ? `${base} · max ${max}` : min != null ? `${base} · min ${min}` : n ? base : \"\";\n}\n\n/* ── Primitive arrays ──────────────────────────────────────────────── */\nfunction PrimitiveArray({ field, item, path }: { field: FieldSchema; item: FieldSchema; path: FieldPath }) {\n const form = useForm()!;\n const id = React.useId();\n const { readOnly } = useFieldAccess(field);\n const key = pathKey(path);\n const value = form.getAt(path);\n const list = Array.isArray(value) ? value : [];\n const onChange = (v: unknown) => form.setAt(path, v);\n const props = { field, value: list, onChange, id, readOnly, path, onBlur: () => form.touch(key) };\n const kind = LIST_KIND[item.type];\n const adapter = React.useMemo<ItemListAdapter | undefined>(\n () =>\n kind\n ? {\n kind,\n read: (v) => (v == null ? \"\" : String(v)),\n write: (v) => v,\n valuePath: (i) => [i],\n placeholder: item.placeholder ?? (item.title && !/^(item|value)$/i.test(item.title) ? item.title : undefined),\n }\n : undefined,\n [kind, item.placeholder, item.title],\n );\n const Gallery = ARRAY_CONTROLS.gallery;\n const References = ARRAY_CONTROLS.references;\n const control =\n item.type === \"image\" ? (Gallery ? <Gallery {...props} /> : <FallbackControl {...props} />) :\n item.type === \"reference\" ? (References ? <References {...props} field={{ ...field, reference: item.reference }} /> : <FallbackControl {...props} />) :\n adapter ? <ItemList field={field} path={path} list={list} readOnly={readOnly} adapter={adapter} inputId={id} /> :\n <InlineList field={field} item={item} path={path} list={list} readOnly={readOnly} />;\n return (\n <FieldShell field={field} path={path} id={id} value={list} onChange={onChange} readOnly={readOnly} issue={form.visibleIssue(key)} meta={item.type === \"reference\" ? undefined : <span className=\"text-kit-xs text-kit-fg-3\">{listMeta(list.length, field)}</span>}>\n <div className=\"@container\">{control}</div>\n </FieldShell>\n );\n}\n\n/* ── One-field object arrays: same item list, value lives at item[inner.name] ── */\nfunction OneFieldArray({ field, item, inner, path }: { field: FieldSchema; item: FieldSchema; inner: FieldSchema; path: FieldPath }) {\n const form = useForm()!;\n const id = React.useId();\n const { readOnly } = useFieldAccess(field);\n const key = pathKey(path);\n const value = form.getAt(path);\n const list = Array.isArray(value) ? value : [];\n const adapter = React.useMemo<ItemListAdapter>(\n () => ({\n kind: LIST_KIND[inner.type]!,\n read: (v) => {\n const x = isObj(v) ? v[inner.name] : undefined;\n return x == null ? \"\" : String(x);\n },\n write: (v, prev) => ({ ...(isObj(prev) ? prev : (newItem(field, item) as object)), [inner.name]: v }),\n keyOf: (v) => (isObj(v) && typeof v._key === \"string\" ? v._key : undefined),\n valuePath: (i) => [i, inner.name],\n placeholder: inner.placeholder ?? item.preview?.fallback?.replace(/^Untitled /i, \"\").replace(/^./, (c) => c.toUpperCase()),\n }),\n [field, item, inner],\n );\n // legacy rows without `_key` get one on first render so rows stay stable while typing and dragging\n React.useEffect(() => {\n if (!readOnly && list.some((it) => isObj(it) && typeof it._key !== \"string\")) form.setAt(path, ensureKeys(list));\n }, [list, readOnly]); // eslint-disable-line react-hooks/exhaustive-deps\n return (\n <FieldShell field={field} path={path} id={id} value={list} onChange={(v) => form.setAt(path, v)} readOnly={readOnly} issue={form.visibleIssue(key)} meta={<span className=\"text-kit-xs text-kit-fg-3\">{listMeta(list.length, field)}</span>}>\n <div className=\"@container\">\n <ItemList field={field} path={path} list={list} readOnly={readOnly} adapter={adapter} inputId={id} />\n </div>\n </FieldShell>\n );\n}\n\nfunction InlineList({ field, item, path, list, readOnly }: { field: FieldSchema; item: FieldSchema; path: FieldPath; list: unknown[]; readOnly: boolean }) {\n const form = useForm()!;\n const Control = CONTROLS[item.type] ?? FallbackControl;\n const max = field.validation?.max;\n const ids = list.map((_, i) => `p${i}`);\n const sort = useDragReorder(ids, (from, to) => form.setAt(path, arrayMove(list, from, to)), { disabled: readOnly || !!field.orderLocked });\n // The same remove the preview rows have: an Undo toast that puts the row back at its index (D-10a issue 10).\n const ops = useListOps(field, path, list, (next) => form.setAt(path, next));\n const rowControl = (v: unknown, i: number) => (\n <Control field={{ ...item, title: `${item.title} ${i + 1}` }} value={v} onChange={(n) => form.setAt([...path, i], n)} id={`${pathKey(path)}-${i}`} path={[...path, i]} readOnly={readOnly} />\n );\n return (\n <div className=\"flex flex-col gap-1.5\">\n {list.map((v, i) => (\n <InlineRow key={ids[i]} id={ids[i]} labelId={`${pathKey(path)}-${i}-label`} sort={sort} readOnly={readOnly} orderLocked={!!field.orderLocked} onRemove={() => ops.remove(i, `${item.title} ${i + 1}`)}>\n {/* V2 draws no label on a row, so the row's name is an sr-only span (no <label> element) at the id a FieldShell's\n label has (`${id}-label`): aria-labelledby controls (rich text) and the row group read it, and the kit\n Input/Textarea/Select/Switch/Checkbox whose id is the row's take it through FieldLabelForContext (<label for>\n semantics without the element) */}\n <span id={`${pathKey(path)}-${i}-label`} className=\"sr-only\">{`${item.title} ${i + 1}`}</span>\n <FieldLabelForContext.Provider value={{ htmlFor: `${pathKey(path)}-${i}`, labelId: `${pathKey(path)}-${i}-label` }}>\n {rowControl(v, i)}\n </FieldLabelForContext.Provider>\n </InlineRow>\n ))}\n {sort.a11y}\n {readOnly ? null : (\n <Button size=\"sm\" variant=\"ghost\" className=\"self-start text-kit-fg-2\" leftIcon={<IconPlus stroke={1.5} />} disabled={max != null && list.length >= max} onClick={() => form.setAt(path, [...list, initialFor(item)])}>\n Add {itemNoun(field)}\n </Button>\n )}\n </div>\n );\n}\nfunction InlineRow({ id, labelId, sort, children, onRemove, readOnly, orderLocked }: { id: string; labelId: string; sort: ReturnType<typeof useDragReorder>; children: React.ReactNode; onRemove: () => void; readOnly: boolean; orderLocked?: boolean }) {\n return (\n <div ref={sort.register(id)} style={sort.style(id)} className={cn(\"group/il flex items-start gap-1\", sort.active === id && \"relative z-10\")}>\n {readOnly ? null : orderLocked ? (\n <OrderLockSlot className=\"mt-1.5\" />\n ) : (\n <button type=\"button\" aria-label=\"Drag to reorder\" {...sort.handle(id)} className=\"mt-1.5 flex h-5 w-4 shrink-0 cursor-grab touch-none items-center justify-center text-kit-fg-4 hover:text-kit-fg-2 active:cursor-grabbing\">\n <IconGripVertical className=\"size-3.5\" stroke={1.5} />\n </button>\n )}\n <div role=\"group\" aria-labelledby={labelId} className=\"min-w-0 flex-1\">{children}</div>\n {readOnly ? null : (\n <Tooltip content=\"Remove\">\n <button type=\"button\" aria-label=\"Remove\" onClick={onRemove} className=\"mt-1 flex size-6 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 opacity-0 transition-opacity hover:bg-kit-hover hover:text-kit-fg focus-visible:opacity-100 group-hover/il:opacity-100\">\n <IconX className=\"size-3.5\" stroke={1.5} />\n </button>\n </Tooltip>\n )}\n </div>\n );\n}\n\n/* ── Object arrays: preview rows ───────────────────────────────────── */\nexport interface RowModel {\n id: string;\n index: number;\n item: unknown;\n preview: Preview;\n path: FieldPath;\n chip?: string;\n extra?: string;\n /** an included-style switch that is OFF: the title reads muted */\n dim?: boolean;\n}\n\nfunction ObjectArray({ field, path }: { field: FieldSchema; path: FieldPath }) {\n const form = useForm()!;\n const host = React.useContext(RowsHostContext);\n const drill = useDrill();\n const id = React.useId();\n const { readOnly } = useFieldAccess(field);\n const key = pathKey(path);\n const value = form.getAt(path);\n const list = Array.isArray(value) ? value : [];\n const of = itemSchemas(field);\n const mode = itemOpenMode(field);\n const rows: RowModel[] = list.map((it, i) => {\n const s = itemSchemaFor(field, it);\n const tf = rowToggleField(s);\n return {\n id: itemId(it, i), index: i, item: it, preview: previewOf(s, it, i, s?.title ?? itemNoun(field)), path: [...path, i], chip: of.length > 1 ? s?.title : undefined,\n dim: tf ? isObj(it) && it[tf.name] === false : undefined,\n };\n });\n const write = (next: unknown[]) => form.setAt(path, ensureKeys(next));\n const ops = useListOps(field, path, list, write, (i) => (mode === \"drill\" ? drill?.([...path, i]) : undefined));\n const [openId, setOpenId] = React.useState<string | null>(null);\n const dialogNav = React.useRef<{ back: () => boolean }>(null);\n const Nested = host.NestedForm;\n return (\n <FieldShell field={field} path={path} id={id} value={list} onChange={(v) => form.setAt(path, v)} readOnly={readOnly} issue={form.visibleIssue(key)} meta={<span className=\"text-kit-xs text-kit-fg-3\">{listMeta(list.length, field)}</span>}>\n <RowList\n field={field}\n rows={rows}\n readOnly={readOnly}\n layout={field.arrayLayout ?? \"list\"}\n mode={mode}\n openId={openId}\n onOpen={\n mode === \"drill\"\n ? drill && ((r) => drill(r.path))\n : (r) => setOpenId(openId === r.id ? null : r.id)\n }\n onCloseInline={() => setOpenId(null)}\n ops={ops}\n dialogNav={dialogNav}\n rowToggle={(r) => {\n const tf = rowToggleField(itemSchemaFor(field, r.item));\n if (!tf) return null;\n const on = isObj(r.item) && r.item[tf.name] !== false;\n return <RowCheck on={on} label={tf.title} title={r.preview.title} readOnly={readOnly} onToggle={() => form.setAt([...r.path, tf.name], !on)} />;\n }}\n renderInline={(r) => {\n const s = itemSchemaFor(field, r.item);\n // dialogs get their own navigation stack (nested lists drill inside the dialog)\n if (mode === \"dialog\" && Nested) return <Nested fields={s?.fields ?? []} title={r.preview.title} icon={s?.icon} path={r.path} navRef={dialogNav} />;\n // the row's own check IS the included switch — don't repeat it in the card\n const tf = rowToggleField(s);\n return <FieldList fields={(s?.fields ?? []).filter((f) => f !== tf)} basePath={r.path} memoryKey={`inl:${pathKey(r.path)}`} />;\n }}\n emptyLabel={`No ${plural(itemNoun(field))} yet.`}\n addButton={<AddItemButton field={field} disabled={readOnly || (field.validation?.max != null && list.length >= field.validation.max)} onAdd={ops.add} />}\n />\n </FieldShell>\n );\n}\n\n/** Shared list operations (arrays and slots). Remove shows an Undo toast; add can drill into the new item. */\nexport function useListOps(field: FieldSchema, _path: FieldPath, list: unknown[], write: (next: unknown[]) => void, afterAdd?: (index: number) => void) {\n const { toast } = useKitServices();\n const { min, max } = field.validation ?? {};\n const atMax = max != null && list.length >= max;\n const atMin = min != null && list.length <= min;\n const limit = () => toast?.(\"Limit reached\", { description: `${field.title} allows ${max} at most.` });\n return {\n atMax,\n atMin,\n add: (item: unknown, at = list.length) => {\n if (atMax) return limit();\n const next = [...list.slice(0, at), item, ...list.slice(at)];\n write(next);\n window.setTimeout(() => afterAdd?.(at), 0);\n },\n duplicate: (i: number) => {\n if (atMax) return limit();\n const copy = isObj(list[i]) ? { ...(structuredClone(list[i]) as object), _key: newKey() } : list[i];\n write([...list.slice(0, i + 1), copy, ...list.slice(i + 1)]);\n },\n move: (i: number, d: -1 | 1) => write(arrayMove(list, i, i + d)),\n reorder: (from: number, to: number) => write(arrayMove(list, from, to)),\n remove: (i: number, title: string) => {\n if (atMin) return toast?.(`At least ${min} required`, { description: `${field.title} needs ${min} or more.` });\n const prev = list;\n write(list.filter((_, j) => j !== i));\n toast?.(`“${title}” removed`, { action: { label: \"Undo\", onClick: () => write(prev) }, duration: 10_000 });\n },\n insertBlank: (at: number) => {\n const s = itemSchemas(field)[0];\n if (!s || atMax) return;\n const next = [...list.slice(0, at), newItem(field, s), ...list.slice(at)];\n write(next);\n },\n };\n}\nexport type ListOps = ReturnType<typeof useListOps>;\n\nfunction AddItemButton({ field, onAdd, disabled }: { field: FieldSchema; onAdd: (item: unknown) => void; disabled?: boolean }) {\n const of = itemSchemas(field);\n const noun = itemNoun(field);\n if (of.length <= 1)\n return (\n <Button size=\"sm\" variant=\"ghost\" className=\"text-kit-fg-2\" leftIcon={<IconPlus stroke={1.5} />} disabled={disabled} onClick={() => of[0] && onAdd(newItem(field, of[0]))}>\n Add {noun}\n </Button>\n );\n return (\n <Menu>\n <MenuTrigger render={<Button size=\"sm\" variant=\"ghost\" className=\"text-kit-fg-2\" leftIcon={<IconPlus stroke={1.5} />} disabled={disabled} />}>Add {noun}</MenuTrigger>\n <MenuContent align=\"start\" className=\"w-64\">\n <MenuLabel>Add to {field.title.toLowerCase()}</MenuLabel>\n {of.map((s) => (\n <MenuItem key={s.name} icon={<KitIcon name={s.icon} />} onClick={() => onAdd(newItem(field, s))} className=\"h-auto py-1.5\">\n <span className=\"flex flex-col\">\n <span>{s.title}</span>\n {s.description ? <span className=\"whitespace-normal text-kit-xs text-kit-fg-3\">{s.description}</span> : null}\n </span>\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n );\n}\n\n/** The row list used by arrays AND slots. Without `onOpen` the rows are inert (a drill nothing can draw yet). */\nexport function RowList({\n field,\n rows,\n readOnly,\n layout,\n mode,\n openId,\n onOpen,\n onCloseInline,\n ops,\n renderInline,\n emptyLabel,\n addButton,\n leading,\n rowToggle,\n dialogNav,\n menuExtra,\n}: {\n dialogNav?: React.RefObject<{ back: () => boolean } | null>;\n field: FieldSchema;\n rows: RowModel[];\n readOnly: boolean;\n layout: \"list\" | \"grid\";\n mode: ReturnType<typeof itemOpenMode>;\n openId: string | null;\n onOpen?: (r: RowModel) => void;\n onCloseInline: () => void;\n ops: ListOps;\n renderInline: (r: RowModel) => React.ReactNode;\n emptyLabel: string;\n addButton: React.ReactNode;\n leading?: (r: RowModel) => React.ReactNode;\n /** a control BEFORE the title button (never inside it): the included check of feature rows */\n rowToggle?: (r: RowModel) => React.ReactNode;\n /** extra items in a row's ⋯ menu, above Remove (a table row's \"Move to group\") */\n menuExtra?: (r: RowModel) => React.ReactNode;\n}) {\n const sort = useDragReorder(rows.map((r) => r.id), ops.reorder, { axis: layout === \"grid\" ? \"grid\" : \"y\", disabled: readOnly || !!field.orderLocked, distance: 5 });\n const openRow = rows.find((r) => r.id === openId);\n if (rows.length === 0)\n return (\n <div className=\"flex flex-col items-center gap-2 rounded-kit-lg border border-dashed border-kit-line-strong px-4 py-5 text-center\">\n <span className=\"text-kit-sm text-kit-fg-3\">{emptyLabel}</span>\n {readOnly ? null : addButton}\n </div>\n );\n return (\n <div className=\"flex flex-col gap-1.5\">\n <div className={cn(layout === \"grid\" ? \"grid grid-cols-2 gap-1.5 @[520px]:grid-cols-3\" : \"overflow-hidden rounded-kit-lg border border-kit-line bg-kit-surface\")}>\n <AnimatePresence initial={false}>\n {rows.map((r) => (\n <Row\n key={r.id}\n r={r}\n count={rows.length}\n field={field}\n readOnly={readOnly}\n grid={layout === \"grid\"}\n mode={mode}\n open={openId === r.id}\n onOpen={onOpen ? () => onOpen(r) : undefined}\n ops={ops}\n sort={sort}\n leading={leading?.(r)}\n toggle={rowToggle?.(r)}\n extra={menuExtra?.(r)}\n inline={mode === \"inline\" && openId === r.id ? renderInline(r) : null}\n popover={mode === \"popover\" && openId === r.id ? renderInline(r) : null}\n onClosePopover={onCloseInline}\n />\n ))}\n </AnimatePresence>\n </div>\n {sort.a11y}\n {readOnly ? null : <div className=\"flex items-center\">{addButton}</div>}\n {mode === \"dialog\" && openRow ? (\n <Modal\n open\n onOpenChange={(o, d) => {\n if (o) return;\n // Escape steps back inside the dialog's own frames first\n if (d.reason === \"escape-key\" && dialogNav?.current?.back()) return d.cancel();\n onCloseInline();\n }}\n >\n <ModalContent size=\"lg\">\n <ModalHeader title={openRow.preview.title} description={`${field.title} · ${openRow.index + 1} of ${rows.length}`} icon={<KitIcon name={openRow.preview.icon ?? field.icon} />} />\n <ModalBody className=\"flex min-h-[320px] flex-col gap-5\">{renderInline(openRow)}</ModalBody>\n <ModalFooter>\n <span className=\"mr-auto text-kit-xs text-kit-fg-3\">Changes save as you type</span>\n <Button variant=\"primary\" onClick={onCloseInline}>Done</Button>\n </ModalFooter>\n </ModalContent>\n </Modal>\n ) : null}\n </div>\n );\n}\n\nfunction Row({\n r, count, field, readOnly, grid, mode, open, onOpen, ops, sort, leading, toggle, extra, inline, popover, onClosePopover,\n}: {\n r: RowModel; count: number; field: FieldSchema; readOnly: boolean; grid: boolean; mode: string; open: boolean; onOpen?: () => void; ops: ListOps;\n sort: ReturnType<typeof useDragReorder>; leading?: React.ReactNode; toggle?: React.ReactNode; extra?: React.ReactNode; inline: React.ReactNode; popover: React.ReactNode; onClosePopover: () => void;\n}) {\n const form = useForm(); // null when a RowList is used outside a kit form (a table in a design-system demo)\n const env = useKitEnv();\n /* V2 used `${r.id}-body`; ids without a _key fall back to i0, i1… and sample data reuses _keys across lists, so two\n arrays could share an id and aria-controls would point at the wrong body. The useId prefix keeps it unique. */\n const uid = React.useId();\n const isDragging = sort.active === r.id;\n // while anything is being dragged, rows move without the enter / exit height animation and without layout animation\n const dragging = sort.active != null;\n const roll = form?.rollup(r.path) ?? { errors: 0, warnings: 0 };\n const peers = Object.entries(env.presence).filter(([k]) => k === pathKey(r.path) || k.startsWith(`${pathKey(r.path)}.`)).flatMap(([, p]) => p);\n /* D61 Review changes: a changed item gets the author-colour bar on its row edge and \"2 changed\" in its summary */\n const nChanged = env.review?.count(r.path) ?? 0;\n const changeBar = nChanged ? <span aria-hidden className=\"pointer-events-none absolute inset-y-1.5 left-0 z-[1] w-0.5 rounded-full\" style={{ background: env.review!.color(r.path) ?? \"var(--kit-warning)\" }} /> : null;\n const changedNote = nChanged ? `${nChanged} changed` : \"\";\n const menu = readOnly ? null : (\n <Menu>\n <MenuTrigger\n aria-label={`${r.preview.title} actions`}\n onClick={(e) => e.stopPropagation()}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover data-[popup-open]:text-kit-fg\"\n >\n <IconDots className=\"size-4\" stroke={1.5} />\n </MenuTrigger>\n <MenuContent align=\"end\" className=\"w-52\">\n <MenuItem icon={<IconArrowUp stroke={1.5} />} disabled={!!field.orderLocked || r.index === 0} onClick={() => ops.move(r.index, -1)}>Move up</MenuItem>\n <MenuItem icon={<IconArrowDown stroke={1.5} />} disabled={!!field.orderLocked || r.index === count - 1} onClick={() => ops.move(r.index, 1)}>Move down</MenuItem>\n <MenuSeparator />\n <MenuItem icon={<IconCopy stroke={1.5} />} disabled={ops.atMax} onClick={() => ops.duplicate(r.index)}>{ops.atMax ? \"Duplicate · limit reached\" : \"Duplicate\"}</MenuItem>\n {field.type === \"array\" ? (\n <>\n <MenuItem icon={<IconRowInsertTop stroke={1.5} />} disabled={ops.atMax} onClick={() => ops.insertBlank(r.index)}>Add item above</MenuItem>\n <MenuItem icon={<IconRowInsertBottom stroke={1.5} />} disabled={ops.atMax} onClick={() => ops.insertBlank(r.index + 1)}>Add item below</MenuItem>\n </>\n ) : null}\n {extra ? (\n <>\n <MenuSeparator />\n {extra}\n </>\n ) : null}\n <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} disabled={ops.atMin} onClick={() => ops.remove(r.index, r.preview.title)}>{ops.atMin ? `Remove · at least ${field.validation?.min} required` : \"Remove\"}</MenuItem>\n </MenuContent>\n </Menu>\n );\n const grip = readOnly ? null : field.orderLocked ? (\n <OrderLockSlot className=\"h-7 items-center\" />\n ) : (\n <button\n type=\"button\"\n aria-label={`Reorder ${r.preview.title}`}\n onClick={(e) => e.stopPropagation()}\n {...sort.handle(r.id)}\n className=\"relative flex h-7 w-4 shrink-0 cursor-grab touch-none items-center justify-center text-kit-fg-4 transition-colors before:absolute before:-inset-2 hover:text-kit-fg-2 active:cursor-grabbing\"\n >\n <IconGripVertical className=\"size-3.5\" stroke={1.5} />\n </button>\n );\n if (grid) {\n const tile = (\n <>\n <span className=\"flex aspect-[4/3] items-center justify-center bg-kit-muted\">\n {r.preview.media ? <img src={r.preview.media} alt=\"\" className=\"size-full object-cover\" /> : <KitIcon name={r.preview.icon ?? field.icon} className=\"size-5 text-kit-fg-3\" />}\n </span>\n <span className=\"block truncate px-2 pb-1.5 pt-1.5 text-kit-xs font-medium text-kit-fg\">{r.preview.title}</span>\n </>\n );\n return (\n <div ref={sort.register(r.id)} style={sort.style(r.id)} className={cn(\"relative\", isDragging && \"z-10\")}>\n <motion.div\n layout={!isDragging ? \"position\" : false}\n initial={{ opacity: 0, scale: 0.97 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.97 }}\n className={cn(\"group/row relative overflow-hidden rounded-kit-lg border border-kit-line bg-kit-surface transition-colors hover:border-kit-line-strong\", isDragging && \"shadow-kit-lg\")}\n >\n {onOpen ? (\n <button type=\"button\" onClick={onOpen} aria-label={`Open ${r.preview.title}, ${r.index + 1} of ${count}`} aria-haspopup={mode === \"popover\" || mode === \"dialog\" ? \"dialog\" : undefined} className=\"block w-full text-left\">\n {tile}\n </button>\n ) : (\n <div className=\"block w-full text-left\">{tile}</div>\n )}\n <div className=\"absolute right-1 top-1 flex items-center gap-0.5 rounded-kit-md bg-kit-surface/90 opacity-0 shadow-kit-xs transition-opacity group-hover/row:opacity-100 [@media(pointer:coarse)]:opacity-100\">\n {grip}\n {menu}\n </div>\n <IssueDot errors={roll.errors} warnings={roll.warnings} className=\"absolute left-2 top-2 ring-2 ring-kit-surface\" />\n {changeBar}\n </motion.div>\n </div>\n );\n }\n /* CPO D43 — a row says what opening it does: › drills into a new frame, ⌄ expands in place (rotates when open),\n ⧉ opens a popover or dialog. The WHOLE row is the hit area (hover tint); the title button carries focus,\n Enter / Space and the label (\"Open Starter\" / \"Expand Net-60 terms\"). */\n const inlineMode = mode === \"inline\";\n const bodyId = `${uid}${r.id}-body`;\n const verb = inlineMode ? (open ? \"Collapse\" : \"Expand\") : \"Open\";\n const trailing = !onOpen ? null : inlineMode ? (\n <IconChevronDown aria-hidden className={cn(\"size-4 shrink-0 text-kit-fg-3 transition-transform duration-200\", open && \"rotate-180 text-kit-fg-2\")} stroke={1.5} />\n ) : mode === \"drill\" ? (\n <IconChevronRight aria-hidden className=\"size-4 shrink-0 text-kit-fg-3 transition-transform duration-150 group-hover/row:translate-x-0.5\" stroke={1.5} />\n ) : (\n <IconArrowsDiagonal aria-hidden className=\"size-3.5 shrink-0 text-kit-fg-3\" stroke={1.5} />\n );\n const titleInner = (\n <>\n {leading ?? (toggle && !r.preview.media ? null : <Thumb media={r.preview.media} icon={r.preview.icon ?? field.icon} />)}\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"flex items-center gap-1.5 truncate text-kit-sm\", r.preview.empty || r.dim ? \"text-kit-fg-3\" : \"text-kit-fg\", open && \"font-medium\")}>\n <span className=\"truncate\">{r.preview.title}</span>\n {r.chip ? <span className=\"shrink-0 rounded-kit-md bg-kit-muted px-1 text-kit-2xs font-medium text-kit-fg-2\">{r.chip}</span> : null}\n </span>\n {/* the title already says what the item is; no \"Item 2 of 4\" filler (the position is in the aria label) */}\n {(r.extra ?? r.preview.subtitle) || changedNote ? (\n <span className=\"block truncate text-kit-xs text-kit-fg-3\">\n {changedNote ? <span className=\"text-kit-fg-2\">{changedNote}{r.extra ?? r.preview.subtitle ? \" · \" : \"\"}</span> : null}\n {r.extra ?? r.preview.subtitle}\n </span>\n ) : null}\n </span>\n </>\n );\n const rowInner = (\n <div\n onClick={(e) => {\n // anywhere on the row opens it, except its own controls (grip, ⋯, presence). The ⋯ menu renders in a portal but\n // React still bubbles its clicks here, so a click whose target is outside the row's own DOM (any menu item:\n // menuitem, menuitemradio, menuitemcheckbox, a submenu) never opens the row.\n const target = e.target as HTMLElement;\n if (!onOpen || !e.currentTarget.contains(target) || target.closest(\"button,[role^=menuitem],a,input\")) return;\n onOpen();\n }}\n className={cn(onOpen ? \"group/row flex min-h-12 cursor-pointer items-center gap-2 py-1.5 pl-1.5 pr-2 transition-colors\" : \"group/row flex min-h-12 items-center gap-2 py-1.5 pl-1.5 pr-2 transition-colors\", open ? \"bg-kit-subtle\" : onOpen && \"hover:bg-kit-subtle\")}\n >\n {grip}\n {toggle}\n {onOpen ? (\n <button\n type=\"button\"\n onClick={onOpen}\n data-row-open={r.id}\n aria-expanded={mode === \"drill\" ? undefined : open}\n aria-controls={inlineMode && open ? bodyId : undefined}\n aria-haspopup={mode === \"popover\" || mode === \"dialog\" ? \"dialog\" : undefined}\n aria-label={`${verb} ${r.preview.title}${r.chip ? `, ${r.chip}` : \"\"}${changedNote ? `, ${changedNote}` : \"\"}, ${r.index + 1} of ${count}`}\n className=\"flex min-w-0 flex-1 items-center gap-2.5 rounded-kit-md text-left outline-none\"\n >\n {titleInner}\n </button>\n ) : (\n <div data-row-open={r.id} className=\"flex min-w-0 flex-1 items-center gap-2.5 text-left\">\n {titleInner}\n </div>\n )}\n <IssueDot errors={roll.errors} warnings={roll.warnings} />\n {peers.length ? <PeerStack peers={peers} size={16} /> : null}\n {menu}\n {trailing}\n </div>\n );\n return (\n <div\n ref={sort.register(r.id)}\n style={sort.style(r.id)}\n data-row-id={r.id}\n className={cn(\"relative border-b border-kit-line-subtle bg-kit-surface last:border-b-0\", isDragging && \"z-10 rounded-kit-lg shadow-kit-lg ring-1 ring-kit-line-strong\")}\n >\n {changeBar}\n <motion.div\n layout={!isDragging && !dragging ? \"position\" : false}\n initial={dragging ? false : { opacity: 0, height: 0 }}\n animate={{ opacity: 1, height: \"auto\" }}\n exit={dragging ? { opacity: 0, height: 0, transition: { duration: 0 } } : { opacity: 0, height: 0 }}\n transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }}\n className=\"overflow-hidden\"\n >\n {mode === \"popover\" ? (\n <Popover open={open} onOpenChange={(o) => !o && onClosePopover()}>\n <PopoverAnchor render={rowInner} />\n <PopoverContent className=\"w-[340px] p-4\" align=\"end\" side=\"left\" sideOffset={10}>\n {popover}\n </PopoverContent>\n </Popover>\n ) : (\n rowInner\n )}\n {inlineMode ? (\n <AnimatePresence initial={false}>\n {open ? (\n <motion.div initial={{ height: 0, opacity: 0 }} animate={{ height: \"auto\", opacity: 1 }} exit={{ height: 0, opacity: 0 }} transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }} className=\"overflow-hidden\">\n {/* D63: the row's fields sit behind the one inset line under its title; no tint, no card inside the row */}\n <div className=\"px-3 pb-3 pt-1\">\n <div id={bodyId} role=\"group\" aria-label={r.preview.title} data-group=\"inset\" className={INSET_LINE}><InsetScope>{inline}</InsetScope></div>\n </div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n ) : null}\n </motion.div>\n </div>\n );\n}\n\n/** The included / not-included check on a feature row (D47): a real checkbox, outside the row's open button. */\nfunction RowCheck({ on, label, title, readOnly, onToggle }: { on: boolean; label: string; title: string; readOnly: boolean; onToggle: () => void }) {\n return (\n <Tooltip content={on ? label : `Not ${label.toLowerCase()}`}>\n <button\n type=\"button\"\n role=\"checkbox\"\n aria-checked={on}\n aria-label={`${label}: ${title}`}\n disabled={readOnly}\n onClick={(e) => {\n e.stopPropagation();\n onToggle();\n }}\n className=\"group/chk flex size-7 shrink-0 items-center justify-center rounded-kit-md transition-colors hover:bg-kit-hover disabled:pointer-events-none\"\n >\n <span\n className={cn(\n \"flex size-[18px] items-center justify-center rounded-full transition-colors\",\n on ? \"bg-kit-control-checked text-kit-fg-inverse\" : \"border border-dashed border-kit-field-border-hover text-kit-fg-3 group-hover/chk:border-[var(--kit-emphasis-line)]\",\n )}\n >\n {on ? <IconCheck className=\"size-3\" stroke={2.5} /> : <IconMinus className=\"size-3\" stroke={2} />}\n </span>\n </button>\n </Tooltip>\n );\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { KitIcon } from "../lib/icons.js";
3
3
  import { Tooltip } from "../ui/overlay.js";
4
4
  import * as React from "react";
5
5
  import { jsx } from "react/jsx-runtime";
6
- //#region src/kit/engine/bits.tsx
6
+ //#region src/engine/bits.tsx
7
7
  /**
8
8
  * CPO D45: a field that IS its own row (an object that drills in) has no label row above it; its shell hands the
9
9
  * chrome (ⓘ, badges, comments, presence, ⋯) to the row through this context, and the row draws it before its chevron.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bits.js","names":[],"sources":["../../src/engine/bits.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { KitIcon } from \"../lib/icons\";\nimport { cn } from \"../lib/cn\";\nimport { Tooltip } from \"../ui/overlay\";\n\n/**\n * CPO D45: a field that IS its own row (an object that drills in) has no label row above it; its shell hands the\n * chrome (ⓘ, badges, comments, presence, ⋯) to the row through this context, and the row draws it before its chevron.\n */\nexport const RowChrome = React.createContext<React.ReactNode>(null);\n\n/** Validation rollup dot: red for errors, amber for warnings. Never colour alone — the tooltip names it. */\nexport function IssueDot({ errors, warnings, className }: { errors: number; warnings?: number; className?: string }) {\n if (!errors && !warnings) return null;\n const text = errors ? `${errors} ${errors === 1 ? \"issue\" : \"issues\"} to fix` : `${warnings} ${warnings === 1 ? \"suggestion\" : \"suggestions\"}`;\n return (\n <Tooltip content={text}>\n <span role=\"img\" aria-label={text} className={cn(\"relative inline-flex size-2 shrink-0 rounded-full\", errors ? \"bg-kit-danger\" : \"bg-kit-warning\", className)} />\n </Tooltip>\n );\n}\n\n/**\n * 28px leading tile for rows: image when there is one, else the type icon.\n */\nexport function Thumb({ media, icon, size = 28, className }: { media?: string; icon?: string; size?: number; className?: string }) {\n if (media) return <img src={media} alt=\"\" style={{ width: size, height: size }} className={cn(\"shrink-0 rounded-kit-md border border-kit-line object-cover\", className)} />;\n return (\n <span style={{ width: size, height: size }} className={cn(\"flex shrink-0 items-center justify-center rounded-kit-md bg-kit-muted text-kit-fg-2\", className)}>\n <KitIcon name={icon} className=\"size-4\" />\n </span>\n );\n}\n\nexport function Kbdish({ children }: { children: React.ReactNode }) {\n return (\n <kbd data-hint=\"shortcuts\" className=\"inline-flex h-4 min-w-4 items-center justify-center rounded-kit-md border border-kit-line bg-kit-subtle px-1 font-kit-sans text-kit-2xs text-kit-fg-3\">\n {children}\n </kbd>\n );\n}\n"],"mappings":";;;;;;;;;;AASA,IAAa,YAAY,MAAM,cAA+B,IAAI;;AAGlE,SAAgB,SAAS,EAAE,QAAQ,UAAU,aAAwE;CACnH,IAAI,CAAC,UAAU,CAAC,UAAU,OAAO;CACjC,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,WAAW,IAAI,UAAU,SAAS,WAAW,GAAG,SAAS,GAAG,aAAa,IAAI,eAAe;CAC/H,OACE,oBAAC,SAAD;EAAS,SAAS;EAChB,UAAA,oBAAC,QAAD;GAAM,MAAK;GAAM,cAAY;GAAM,WAAW,GAAG,qDAAqD,SAAS,kBAAkB,kBAAkB,SAAS;EAAI,CAAA;CACzJ,CAAA;AAEb;;;;AAKA,SAAgB,MAAM,EAAE,OAAO,MAAM,OAAO,IAAI,aAAmF;CACjI,IAAI,OAAO,OAAO,oBAAC,OAAD;EAAK,KAAK;EAAO,KAAI;EAAG,OAAO;GAAE,OAAO;GAAM,QAAQ;EAAK;EAAG,WAAW,GAAG,+DAA+D,SAAS;CAAI,CAAA;CAC1K,OACE,oBAAC,QAAD;EAAM,OAAO;GAAE,OAAO;GAAM,QAAQ;EAAK;EAAG,WAAW,GAAG,uFAAuF,SAAS;EACxJ,UAAA,oBAAC,SAAD;GAAS,MAAM;GAAM,WAAU;EAAU,CAAA;CACrC,CAAA;AAEV;AAEA,SAAgB,OAAO,EAAE,YAA2C;CAClE,OACE,oBAAC,OAAD;EAAK,aAAU;EAAY,WAAU;EAClC;CACE,CAAA;AAET"}
@@ -34,12 +34,12 @@ export declare function framesToCrumbs(frames: Frame[], schema: Pick<TypeSchema,
34
34
  export declare const crumbSignature: (crumbs: KitCrumb[]) => string;
35
35
  /**
36
36
  * The form's own crumb bar (when the host does not take the trail through `onCrumbs`): it opens on the first drill
37
- * and closes back at the root, height + fade 180ms, ease [0.22, 1, 0.36, 1]. The document variant sticks under the
38
- * host's sticky header and bleeds to the gutter.
37
+ * and closes back at the root, at once. A drill is a 100+/day action, and V2's 180ms height motion was layout work
38
+ * every frame (canvas revamp V81). The document variant sticks under the host's sticky header and bleeds to the gutter.
39
39
  */
40
40
  export declare function FrameCrumbs({ crumbs, onNavigate, variant, iconFor, }: {
41
41
  crumbs: KitCrumb[];
42
42
  onNavigate: (path: FieldPath) => void;
43
43
  variant: "panel" | "document";
44
44
  iconFor?: CrumbIconFor;
45
- }): import("react/jsx-runtime").JSX.Element;
45
+ }): import("react/jsx-runtime").JSX.Element | null;
@@ -4,8 +4,7 @@ import { KitIcon } from "../lib/icons.js";
4
4
  import { PathCrumbs } from "../ui/path-crumbs.js";
5
5
  import "react";
6
6
  import { jsx } from "react/jsx-runtime";
7
- import { AnimatePresence, motion } from "framer-motion";
8
- //#region src/kit/engine/breadcrumb.tsx
7
+ //#region src/engine/breadcrumb.tsx
9
8
  var fallbackIcon = (name) => /* @__PURE__ */ jsx(KitIcon, { name });
10
9
  /** KitCrumbs → PathCrumbs items (hosts that merge the kit trail into their own header use this). */
11
10
  function kitPathItems(crumbs, onNavigate, iconFor = fallbackIcon) {
@@ -43,42 +42,19 @@ function framesToCrumbs(frames, schema, rollup, rootLabel) {
43
42
  var crumbSignature = (crumbs) => crumbs.map((c) => `${c.key}\u0001${c.title}\u0001${c.icon ?? ""}\u0001${c.errors ?? 0}`).join("");
44
43
  /**
45
44
  * The form's own crumb bar (when the host does not take the trail through `onCrumbs`): it opens on the first drill
46
- * and closes back at the root, height + fade 180ms, ease [0.22, 1, 0.36, 1]. The document variant sticks under the
47
- * host's sticky header and bleeds to the gutter.
45
+ * and closes back at the root, at once. A drill is a 100+/day action, and V2's 180ms height motion was layout work
46
+ * every frame (canvas revamp V81). The document variant sticks under the host's sticky header and bleeds to the gutter.
48
47
  */
49
48
  function FrameCrumbs({ crumbs, onNavigate, variant, iconFor }) {
50
- return /* @__PURE__ */ jsx(AnimatePresence, {
51
- initial: false,
52
- children: crumbs.length > 1 ? /* @__PURE__ */ jsx(motion.div, {
53
- initial: {
54
- height: 0,
55
- opacity: 0
56
- },
57
- animate: {
58
- height: "auto",
59
- opacity: 1
60
- },
61
- exit: {
62
- height: 0,
63
- opacity: 0
64
- },
65
- transition: {
66
- duration: .18,
67
- ease: [
68
- .22,
69
- 1,
70
- .36,
71
- 1
72
- ]
73
- },
74
- "data-frame-crumbs": true,
75
- className: cn("z-[5] shrink-0 overflow-hidden border-b border-kit-line bg-kit-surface", variant === "document" ? "sticky top-[var(--kit-sticky-top,0px)] mx-[calc(var(--kit-gutter,0.5rem)*-1)] px-[var(--kit-gutter,0.5rem)]" : "px-3"),
76
- children: /* @__PURE__ */ jsx(KitBreadcrumb, {
77
- crumbs,
78
- onNavigate,
79
- iconFor
80
- })
81
- }, "crumbs") : null
49
+ if (crumbs.length < 2) return null;
50
+ return /* @__PURE__ */ jsx("div", {
51
+ "data-frame-crumbs": true,
52
+ className: cn("z-[5] shrink-0 overflow-hidden border-b border-kit-line bg-kit-surface", variant === "document" ? "sticky top-[var(--kit-sticky-top,0px)] mx-[calc(var(--kit-gutter,0.5rem)*-1)] px-[var(--kit-gutter,0.5rem)]" : "px-3"),
53
+ children: /* @__PURE__ */ jsx(KitBreadcrumb, {
54
+ crumbs,
55
+ onNavigate,
56
+ iconFor
57
+ })
82
58
  });
83
59
  }
84
60
  //#endregion
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumb.js","names":[],"sources":["../../src/engine/breadcrumb.tsx"],"sourcesContent":["/**\n * KitBreadcrumb — the drill-in trail, rendered by the shared <PathCrumbs> (CPO D38): ← back (Esc) · root · … ·\n * current chip. It collapses by the width it actually has (truncate → icon-only → \"⋯ +N\" Pathway popover), each\n * crumb carries its type icon, and a red dot marks any crumb whose subtree has errors. Port of V2 engine/breadcrumb.tsx.\n */\nimport * as React from \"react\";\nimport { KitIcon } from \"../lib/icons\";\nimport { PathCrumbs, type PathCrumb } from \"../ui/path-crumbs\";\nimport { cn } from \"../lib/cn\";\nimport { frameKeyOf } from \"../lib/path\";\nimport type { Frame } from \"../lib/frames\";\nimport type { FieldPath, TypeSchema } from \"../schema/types\";\n\nexport interface KitCrumb {\n key: string;\n title: string;\n icon?: string;\n path: FieldPath;\n errors?: number;\n}\n\nexport type CrumbIconFor = (name: string) => React.ReactNode;\nconst fallbackIcon: CrumbIconFor = (name) => <KitIcon name={name} />;\n\n/** KitCrumbs → PathCrumbs items (hosts that merge the kit trail into their own header use this). */\nexport function kitPathItems(crumbs: KitCrumb[], onNavigate: (path: FieldPath) => void, iconFor: CrumbIconFor = fallbackIcon): PathCrumb[] {\n return crumbs.map((c) => ({\n id: c.key,\n label: c.title,\n icon: c.icon ? iconFor(c.icon) : undefined,\n errors: c.errors,\n onSelect: () => onNavigate(c.path),\n }));\n}\n\nexport function KitBreadcrumb({ crumbs, onNavigate, className, iconFor }: { crumbs: KitCrumb[]; onNavigate: (path: FieldPath) => void; className?: string; iconFor?: CrumbIconFor }) {\n if (crumbs.length < 2) return null;\n return <PathCrumbs items={kitPathItems(crumbs, onNavigate, iconFor)} backShortcut=\"Esc\" label=\"Field path\" className={className ?? \"h-10\"} />;\n}\n\n/**\n * Frames → crumbs (V2 schema-form): the root crumb is the host's label (or the schema title) with the schema icon;\n * every other crumb carries the error count of its subtree (a history crumb counts its field's).\n */\nexport function framesToCrumbs(\n frames: Frame[],\n schema: Pick<TypeSchema, \"title\" | \"icon\">,\n rollup: (prefix: FieldPath) => { errors: number },\n rootLabel?: string,\n): KitCrumb[] {\n return frames.map((f, i) => ({\n key: frameKeyOf(f.path),\n title: i === 0 ? rootLabel ?? schema.title : f.title,\n icon: f.icon ?? (i === 0 ? schema.icon : undefined),\n path: f.path,\n errors: i === 0 ? 0 : rollup(f.kind === \"history\" ? f.path.slice(0, -1) : f.path).errors,\n }));\n}\n\n/** A stable signature of the crumbs, so a host's `onCrumbs` fires only when the trail actually changed. */\nexport const crumbSignature = (crumbs: KitCrumb[]) => crumbs.map((c) => `${c.key}\\u0001${c.title}\\u0001${c.icon ?? \"\"}\\u0001${c.errors ?? 0}`).join(\"\\u0002\");\n\n/**\n * The form's own crumb bar (when the host does not take the trail through `onCrumbs`): it opens on the first drill\n * and closes back at the root, at once. A drill is a 100+/day action, and V2's 180ms height motion was layout work\n * every frame (canvas revamp V81). The document variant sticks under the host's sticky header and bleeds to the gutter.\n */\nexport function FrameCrumbs({\n crumbs,\n onNavigate,\n variant,\n iconFor,\n}: {\n crumbs: KitCrumb[];\n onNavigate: (path: FieldPath) => void;\n variant: \"panel\" | \"document\";\n iconFor?: CrumbIconFor;\n}) {\n if (crumbs.length < 2) return null;\n return (\n <div\n data-frame-crumbs\n className={cn(\n \"z-[5] shrink-0 overflow-hidden border-b border-kit-line bg-kit-surface\",\n variant === \"document\" ? \"sticky top-[var(--kit-sticky-top,0px)] mx-[calc(var(--kit-gutter,0.5rem)*-1)] px-[var(--kit-gutter,0.5rem)]\" : \"px-3\",\n )}\n >\n <KitBreadcrumb crumbs={crumbs} onNavigate={onNavigate} iconFor={iconFor} />\n </div>\n );\n}\n"],"mappings":";;;;;;;AAsBA,IAAM,gBAA8B,SAAS,oBAAC,SAAD,EAAe,KAAO,CAAA;;AAGnE,SAAgB,aAAa,QAAoB,YAAuC,UAAwB,cAA2B;CACzI,OAAO,OAAO,KAAK,OAAO;EACxB,IAAI,EAAE;EACN,OAAO,EAAE;EACT,MAAM,EAAE,OAAO,QAAQ,EAAE,IAAI,IAAI,KAAA;EACjC,QAAQ,EAAE;EACV,gBAAgB,WAAW,EAAE,IAAI;CACnC,EAAE;AACJ;AAEA,SAAgB,cAAc,EAAE,QAAQ,YAAY,WAAW,WAAsH;CACnL,IAAI,OAAO,SAAS,GAAG,OAAO;CAC9B,OAAO,oBAAC,YAAD;EAAY,OAAO,aAAa,QAAQ,YAAY,OAAO;EAAG,cAAa;EAAM,OAAM;EAAa,WAAW,aAAa;CAAS,CAAA;AAC9I;;;;;AAMA,SAAgB,eACd,QACA,QACA,QACA,WACY;CACZ,OAAO,OAAO,KAAK,GAAG,OAAO;EAC3B,KAAK,WAAW,EAAE,IAAI;EACtB,OAAO,MAAM,IAAI,aAAa,OAAO,QAAQ,EAAE;EAC/C,MAAM,EAAE,SAAS,MAAM,IAAI,OAAO,OAAO,KAAA;EACzC,MAAM,EAAE;EACR,QAAQ,MAAM,IAAI,IAAI,OAAO,EAAE,SAAS,YAAY,EAAE,KAAK,MAAM,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;CACpF,EAAE;AACJ;;AAGA,IAAa,kBAAkB,WAAuB,OAAO,KAAK,MAAM,GAAG,EAAE,IAAI,QAAQ,EAAE,MAAM,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE,UAAU,GAAG,CAAC,CAAC,KAAK,GAAQ;;;;;;AAO5J,SAAgB,YAAY,EAC1B,QACA,YACA,SACA,WAMC;CACD,IAAI,OAAO,SAAS,GAAG,OAAO;CAC9B,OACE,oBAAC,OAAD;EACE,qBAAA;EACA,WAAW,GACT,0EACA,YAAY,aAAa,gHAAgH,MAC3I;EAEA,UAAA,oBAAC,eAAD;GAAuB;GAAoB;GAAqB;EAAU,CAAA;CACvE,CAAA;AAET"}
@@ -19,8 +19,8 @@ import type { ControlProps } from "../types";
19
19
  export interface ExpandSpec {
20
20
  /** "reading" centres a ~720px writing column; "wide" uses the whole dialog (tables, code) */
21
21
  layout: "reading" | "wide";
22
- /** the header's quiet meta line for this value ("312 words", "6 rows · 4 columns") */
23
- meta: (value: unknown) => string;
22
+ /** the header's quiet meta line for this value ("12 lines", "6 rows · 4 columns") */
23
+ meta?: (value: unknown) => string;
24
24
  /** the label-row button's name and tooltip */
25
25
  label: "Expand editor" | "Edit in full screen";
26
26
  /** V2: the document variant already draws the full editor in its column, so writing types offer no ⤢ there */
@@ -28,8 +28,6 @@ export interface ExpandSpec {
28
28
  /** expanding needs a kit control: the host's control for this type cannot edit it (read-only card) */
29
29
  needsKitControl?: boolean;
30
30
  }
31
- /** Words in a value: a string (tags stripped), Portable Text blocks, or a rich-text envelope ({ html } / { value }). */
32
- export declare function wordsIn(value: unknown): number;
33
31
  /** Type → how it expands. Additive like CONTROLS: one entry per type. Plain long text (`text`) has none: V2's
34
32
  * TextControl is a bare textarea that grows to its value, so an extra ⤢ would only add a tab stop V2 lacks. */
35
33
  export declare const EXPANDABLE: Partial<Record<SchemaType, ExpandSpec>>;
@@ -1,13 +1,13 @@
1
1
  import { cn } from "../lib/cn.js";
2
- import { isObj, pathKey } from "../lib/path.js";
3
2
  import { useForm, useKitEnv } from "../context.js";
3
+ import { isObj, pathKey } from "../lib/path.js";
4
4
  import { Tooltip } from "../ui/overlay.js";
5
5
  import { resolveFrames } from "../lib/frames.js";
6
6
  import { ExpandedEditorModal } from "../ui/expanded-editor-modal.js";
7
7
  import * as React from "react";
8
- import { IconArrowsMaximize } from "@tabler/icons-react";
9
8
  import { jsx } from "react/jsx-runtime";
10
- //#region src/kit/engine/expand.tsx
9
+ import { IconArrowsMaximize } from "@tabler/icons-react";
10
+ //#region src/engine/expand.tsx
11
11
  /**
12
12
  * Expanded editing (CPO D49), owned by the engine: rich text, code and tables open in the ONE shared
13
13
  * ExpandedEditorModal (ui/expanded-editor-modal.tsx). V2 did this per control (RichTextControl + RichTextExpandAction,
@@ -22,23 +22,7 @@ import { jsx } from "react/jsx-runtime";
22
22
  * Offered only where expanding edits something: never read-only, never a type whose control behind it cannot edit
23
23
  * (code and tables expand only once a kit control is registered for them; the host draws those read-only today).
24
24
  */
25
- /** Words in a value: a string (tags stripped), Portable Text blocks, or a rich-text envelope ({ html } / { value }). */
26
- function wordsIn(value) {
27
- const text = textOf(value).trim();
28
- return text ? text.split(/\s+/).length : 0;
29
- }
30
- function textOf(v) {
31
- if (typeof v === "string") return v.replace(/<[^>]*>/g, " ").replace(/&nbsp;/g, " ");
32
- if (Array.isArray(v)) return v.map(textOf).join(" ");
33
- if (!isObj(v)) return "";
34
- if (typeof v.text === "string") return v.text;
35
- if (Array.isArray(v.children)) return textOf(v.children);
36
- if (typeof v.html === "string") return textOf(v.html);
37
- if ("value" in v) return textOf(v.value);
38
- return "";
39
- }
40
25
  var count = (n, one, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;
41
- var words = (v) => count(wordsIn(v), "word");
42
26
  function codeLines(v) {
43
27
  const src = typeof v === "string" ? v : isObj(v) && typeof v.code === "string" ? v.code : "";
44
28
  return count(src ? src.split("\n").length : 0, "line");
@@ -53,7 +37,6 @@ function tableSize(v) {
53
37
  var EXPANDABLE = {
54
38
  richtext: {
55
39
  layout: "reading",
56
- meta: words,
57
40
  label: "Expand editor",
58
41
  panelOnly: true
59
42
  },
@@ -139,7 +122,7 @@ function ExpandedField({ field, path, spec, Control, value, onChange, onBlur, in
139
122
  open,
140
123
  onOpenChange: (o) => openExpanded(o ? key : null),
141
124
  crumbs,
142
- meta: spec.meta(value),
125
+ meta: spec.meta?.(value),
143
126
  layout: spec.layout,
144
127
  returnFocus: () => document.querySelector(`[data-field-key="${CSS.escape(pathKey(path))}"] [data-kit-expand]`) ?? document.getElementById(id),
145
128
  children: open ? /* @__PURE__ */ jsx("div", {
@@ -165,6 +148,6 @@ function ExpandedField({ field, path, spec, Control, value, onChange, onBlur, in
165
148
  });
166
149
  }
167
150
  //#endregion
168
- export { ExpandAction, ExpandedField, expandKey, expandSpecFor, isExpandShortcut, openExpanded };
151
+ export { EXPANDABLE, ExpandAction, ExpandedField, expandKey, expandSpecFor, isExpandShortcut, openExpanded, useExpandedKey };
169
152
 
170
153
  //# sourceMappingURL=expand.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expand.js","names":[],"sources":["../../src/engine/expand.tsx"],"sourcesContent":["/**\n * Expanded editing (CPO D49), owned by the engine: rich text, code and tables open in the ONE shared\n * ExpandedEditorModal (ui/expanded-editor-modal.tsx). V2 did this per control (RichTextControl + RichTextExpandAction,\n * TableControl + TableFullScreenAction); the engine opens the modal around WHATEVER control the field has: the kit\n * control from CONTROLS, or the host's when a control hands a stored value off (LegacyFallback). The modal body is that same control on the same value and the same onChange, so the field underneath\n * and the expanded one stay in sync and every write keeps the exact stored shape the inline control writes.\n *\n * Ways in (V2): the ⤢ button in the field's label row (shown on hover, always on touch), and ⌘↵ / Ctrl+↵ while the\n * field's control has focus. Inside the modal ⌘↵ or Esc closes it (menus and popovers inside close first) and focus\n * returns to whatever opened it. A control lane may open or close it from its own toolbar with `openExpanded`.\n *\n * Offered only where expanding edits something: never read-only, never a type whose control behind it cannot edit\n * (code and tables expand only once a kit control is registered for them; the host draws those read-only today).\n */\nimport * as React from \"react\";\nimport type { ComponentType } from \"react\";\nimport { IconArrowsMaximize } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { resolveFrames } from \"../lib/frames\";\nimport { isObj, pathKey } from \"../lib/path\";\nimport type { FieldPath, FieldSchema, SchemaType } from \"../schema/types\";\nimport type { ControlProps } from \"../types\";\nimport { useForm, useKitEnv } from \"../context\";\nimport { Tooltip } from \"../ui/overlay\";\nimport { ExpandedEditorModal } from \"../ui/expanded-editor-modal\";\n\nexport interface ExpandSpec {\n /** \"reading\" centres a ~720px writing column; \"wide\" uses the whole dialog (tables, code) */\n layout: \"reading\" | \"wide\";\n /** the header's quiet meta line for this value (\"12 lines\", \"6 rows · 4 columns\") */\n meta?: (value: unknown) => string;\n /** the label-row button's name and tooltip */\n label: \"Expand editor\" | \"Edit in full screen\";\n /** V2: the document variant already draws the full editor in its column, so writing types offer no ⤢ there */\n panelOnly?: boolean;\n /** expanding needs a kit control: the host's control for this type cannot edit it (read-only card) */\n needsKitControl?: boolean;\n}\n\nconst count = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;\nfunction codeLines(v: unknown) {\n const src = typeof v === \"string\" ? v : isObj(v) && typeof v.code === \"string\" ? v.code : \"\";\n return count(src ? src.split(\"\\n\").length : 0, \"line\");\n}\nfunction tableSize(v: unknown) {\n const rows = isObj(v) && Array.isArray(v.rows) ? v.rows.length : 0;\n const cols = isObj(v) && Array.isArray(v.columns) ? v.columns.length : 0;\n return `${count(rows, \"row\")} · ${count(cols, \"column\")}`;\n}\n\n/** Type → how it expands. Additive like CONTROLS: one entry per type. Plain long text (`text`) has none: V2's\n * TextControl is a bare textarea that grows to its value, so an extra ⤢ would only add a tab stop V2 lacks. */\nexport const EXPANDABLE: Partial<Record<SchemaType, ExpandSpec>> = {\n richtext: { layout: \"reading\", label: \"Expand editor\", panelOnly: true },\n code: { layout: \"wide\", meta: codeLines, label: \"Expand editor\", needsKitControl: true },\n table: { layout: \"wide\", meta: tableSize, label: \"Edit in full screen\", needsKitControl: true },\n};\n\n/** The spec when this field can expand here, else null. */\nexport function expandSpecFor(field: FieldSchema, opts: { readOnly: boolean; hasKitControl: boolean; variant: string }): ExpandSpec | null {\n const spec = EXPANDABLE[field.type];\n if (!spec || opts.readOnly) return null;\n if (spec.needsKitControl && !opts.hasKitControl) return null;\n if (spec.panelOnly && opts.variant === \"document\") return null;\n return spec;\n}\n\n/* ── which field (docId:pathKey) has its expanded editor open: one at a time, shared with toolbar buttons ── */\nlet openKey: string | null = null;\nconst subs = new Set<() => void>();\nexport function openExpanded(key: string | null) {\n if (openKey === key) return;\n openKey = key;\n subs.forEach((s) => s());\n}\nexport const expandKey = (docId: string, path: FieldPath) => `${docId}:${pathKey(path)}`;\nexport function useExpandedKey() {\n return React.useSyncExternalStore(\n (cb) => {\n subs.add(cb);\n return () => subs.delete(cb);\n },\n () => openKey,\n () => openKey,\n );\n}\n\n/** ⌘↵ / Ctrl+↵ (no Shift or Alt): the expand shortcut. */\nexport const isExpandShortcut = (e: React.KeyboardEvent | KeyboardEvent) => e.key === \"Enter\" && (e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey;\n\n/** The label-row ⤢ (V2 RichTextExpandAction / TableFullScreenButton): hidden at rest until hover, always on touch. */\nexport function ExpandAction({ field, path, spec }: { field: FieldSchema; path: FieldPath; spec: ExpandSpec }) {\n const env = useKitEnv();\n const wide = spec.label === \"Edit in full screen\";\n return (\n <Tooltip content={spec.label} shortcut=\"⌘↵\">\n <button\n type=\"button\"\n aria-label={wide ? `Edit ${field.title} in full screen` : `Expand ${field.title}`}\n aria-haspopup=\"dialog\"\n data-kit-expand=\"\"\n onClick={() => openExpanded(expandKey(env.docId, path))}\n className={cn(\n \"-my-0.5 inline-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\",\n \"focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid]\",\n // V2: quiet at rest (hover / touch shows it). Keyboard focus keeps it visible, so Tab never lands on nothing.\n \"opacity-0 group-hover/field:opacity-100 focus-visible:opacity-100 [@media(pointer:coarse)]:opacity-100\",\n )}\n >\n <IconArrowsMaximize aria-hidden className=\"size-3.5\" stroke={1.5} />\n </button>\n </Tooltip>\n );\n}\n\n/** The modal's breadcrumb: the document, the frames down to this field's parent, then the field. */\nfunction useCrumbs(field: FieldSchema, path: FieldPath): string[] {\n const form = useForm();\n const env = useKitEnv();\n if (!form) return [env.docTitle, field.title].filter(Boolean) as string[];\n const { frames } = resolveFrames(form.schema, form.value, path.slice(0, -1), form.resolveSchema);\n const titles = frames.filter((f) => f.kind !== \"history\").map((f, i) => (i === 0 ? env.docTitle || f.title : f.title));\n return [...titles, field.title].filter(Boolean);\n}\n\n/**\n * The field's expanded editor: the same control, value and onChange in the modal. Mounted only while open, so the\n * inline control and this one never fight over the same DOM id (the modal one gets `${id}-expanded`).\n */\nexport function ExpandedField({\n field,\n path,\n spec,\n Control,\n value,\n onChange,\n onBlur,\n invalid,\n id,\n parent,\n}: {\n field: FieldSchema;\n path: FieldPath;\n spec: ExpandSpec;\n Control: ComponentType<ControlProps>;\n value: unknown;\n onChange: (v: unknown) => void;\n onBlur?: () => void;\n invalid?: boolean;\n id: string;\n parent?: Record<string, unknown>;\n}) {\n const env = useKitEnv();\n const key = expandKey(env.docId, path);\n const open = useExpandedKey() === key;\n const crumbs = useCrumbs(field, path);\n // close when this field goes away (block deselected, drilled elsewhere, schema changed)\n React.useEffect(\n () => () => {\n if (openKey === key) openExpanded(null);\n },\n [key],\n );\n return (\n <ExpandedEditorModal\n open={open}\n onOpenChange={(o) => openExpanded(o ? key : null)}\n crumbs={crumbs}\n meta={spec.meta?.(value)}\n layout={spec.layout}\n returnFocus={() =>\n document.querySelector<HTMLElement>(`[data-field-key=\"${CSS.escape(pathKey(path))}\"] [data-kit-expand]`) ??\n document.getElementById(id)\n }\n >\n {open ? (\n <div\n data-kit-expanded={field.type}\n className={cn(\"min-w-0\", spec.layout === \"wide\" && \"flex min-h-0 flex-1 flex-col\")}\n onBlur={onBlur}\n onKeyDown={(e) => {\n if (!isExpandShortcut(e)) return;\n e.preventDefault();\n openExpanded(null);\n }}\n >\n <Control field={field} value={value} onChange={onChange} id={`${id}-expanded`} invalid={invalid} path={path} parent={parent} onBlur={onBlur} />\n </div>\n ) : null}\n </ExpandedEditorModal>\n );\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { FieldList as FieldList$1 } from "./grouping.js";
2
2
  import { KitField } from "./kit-field.js";
3
3
  import { jsx } from "react/jsx-runtime";
4
- //#region src/kit/engine/field-list.tsx
4
+ //#region src/engine/field-list.tsx
5
5
  var renderKitField = (field, path, parent) => /* @__PURE__ */ jsx(KitField, {
6
6
  field,
7
7
  path,
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-list.js","names":[],"sources":["../../src/engine/field-list.tsx"],"sourcesContent":["/**\n * FieldList — lays out one frame's fields (CPO D45 grouping; V2 HEAD 9829bf1 kit/engine/field-list.tsx): group TABS\n * (with error dots) at the top of the frame only, FIELDSETS as <FieldSection>, breakpoint objects as ONE\n * <BreakpointGroup>, an auto \"Advanced\" section, and `hidden` conditions that appear / disappear with a height animation.\n *\n * The layout itself lives in grouping.tsx (`FieldList` there takes `renderField`, so grouping never imports KitField).\n * This module is V2's FieldList as the rest of the engine uses it: the same props, each field drawn by KitField — which\n * is where an object too big to inset becomes its drill row (NavRow), an array its rows, a slot its blocks.\n * Frames (frame.tsx `FrameSlots.FieldList`), expanded array rows and popovers render this.\n */\nimport type { FieldGroup, FieldPath, FieldSchema, Fieldset } from \"../schema/types\";\nimport { FieldList as GroupedFieldList, type RenderField } from \"./grouping\";\nimport { KitField } from \"./kit-field\";\n\nexport interface FieldListProps {\n fields: FieldSchema[];\n fieldsets?: Fieldset[];\n groups?: FieldGroup[];\n basePath: FieldPath;\n /** where to remember the selected tab / open fieldsets */\n memoryKey: string;\n}\n\nconst renderKitField: RenderField = (field, path, parent) => <KitField field={field} path={path} parent={parent} />;\n\nexport function FieldList(props: FieldListProps) {\n return <GroupedFieldList {...props} renderField={renderKitField} />;\n}\n"],"mappings":";;;;AAuBA,IAAM,kBAA+B,OAAO,MAAM,WAAW,oBAAC,UAAD;CAAiB;CAAa;CAAc;AAAS,CAAA;AAElH,SAAgB,UAAU,OAAuB;CAC/C,OAAO,oBAAC,aAAD;EAAkB,GAAI;EAAO,aAAa;CAAiB,CAAA;AACpE"}