@bettercms-ai/kit 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +90 -31
  8. package/dist/adapters/lossy.js +414 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
  11. package/{adapters → dist/adapters}/prod-types.js +71 -3
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +996 -179
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +92 -2
  22. package/{context.js → dist/context.js} +5 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/{controls → dist/controls}/form-picker-register.js +1 -1
  50. package/dist/controls/form-picker-register.js.map +1 -0
  51. package/{controls → dist/controls}/form-picker.js +11 -9
  52. package/dist/controls/form-picker.js.map +1 -0
  53. package/{controls → dist/controls}/icon-register.js +1 -1
  54. package/dist/controls/icon-register.js.map +1 -0
  55. package/{controls → dist/controls}/icon.d.ts +4 -2
  56. package/{controls → dist/controls}/icon.js +32 -27
  57. package/dist/controls/icon.js.map +1 -0
  58. package/{controls → dist/controls}/index.d.ts +1 -1
  59. package/{controls → dist/controls}/index.js +4 -3
  60. package/dist/controls/index.js.map +1 -0
  61. package/{controls → dist/controls}/json-register.js +1 -1
  62. package/dist/controls/json-register.js.map +1 -0
  63. package/{controls → dist/controls}/json.js +13 -3
  64. package/dist/controls/json.js.map +1 -0
  65. package/{controls → dist/controls}/link.js +6 -6
  66. package/dist/controls/link.js.map +1 -0
  67. package/{controls → dist/controls}/location-register.js +1 -1
  68. package/dist/controls/location-register.js.map +1 -0
  69. package/{controls → dist/controls}/location.js +64 -40
  70. package/dist/controls/location.js.map +1 -0
  71. package/{controls → dist/controls}/media-register.js +1 -1
  72. package/dist/controls/media-register.js.map +1 -0
  73. package/{controls → dist/controls}/media-services.d.ts +6 -0
  74. package/dist/controls/media-services.js +0 -0
  75. package/{controls → dist/controls}/media.d.ts +35 -4
  76. package/{controls → dist/controls}/media.js +491 -171
  77. package/dist/controls/media.js.map +1 -0
  78. package/{controls → dist/controls}/number.js +10 -9
  79. package/dist/controls/number.js.map +1 -0
  80. package/{controls → dist/controls}/reference-register.js +1 -1
  81. package/dist/controls/reference-register.js.map +1 -0
  82. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  83. package/dist/controls/reference-services.js +0 -0
  84. package/{controls → dist/controls}/reference.d.ts +1 -1
  85. package/{controls → dist/controls}/reference.js +93 -77
  86. package/dist/controls/reference.js.map +1 -0
  87. package/dist/controls/rich-text/blocks.d.ts +49 -0
  88. package/{controls → dist/controls}/rich-text/blocks.js +471 -144
  89. package/dist/controls/rich-text/blocks.js.map +1 -0
  90. package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
  91. package/{controls → dist/controls}/rich-text/catalog.js +75 -65
  92. package/dist/controls/rich-text/catalog.js.map +1 -0
  93. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  94. package/{controls → dist/controls}/rich-text/codec.js +3 -1
  95. package/dist/controls/rich-text/codec.js.map +1 -0
  96. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  97. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  98. package/dist/controls/rich-text/component-card.js.map +1 -0
  99. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  100. package/dist/controls/rich-text/component-panel.js +141 -0
  101. package/dist/controls/rich-text/component-panel.js.map +1 -0
  102. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  103. package/{controls → dist/controls}/rich-text/control.js +84 -42
  104. package/dist/controls/rich-text/control.js.map +1 -0
  105. package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
  106. package/{controls → dist/controls}/rich-text/dom.js +379 -50
  107. package/dist/controls/rich-text/dom.js.map +1 -0
  108. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  109. package/{controls → dist/controls}/rich-text/editor.js +148 -48
  110. package/dist/controls/rich-text/editor.js.map +1 -0
  111. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  112. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  113. package/dist/controls/rich-text/floating.js.map +1 -0
  114. package/{controls → dist/controls}/rich-text/index.js +1 -1
  115. package/dist/controls/rich-text/index.js.map +1 -0
  116. package/dist/controls/rich-text/link-form.js +147 -0
  117. package/dist/controls/rich-text/link-form.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  119. package/dist/controls/rich-text/markdown.js.map +1 -0
  120. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  121. package/dist/controls/rich-text/ops.js.map +1 -0
  122. package/dist/controls/rich-text/plain.d.ts +17 -0
  123. package/dist/controls/rich-text/plain.js +44 -0
  124. package/dist/controls/rich-text/plain.js.map +1 -0
  125. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  126. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  127. package/dist/controls/rich-text/toolbar.js.map +1 -0
  128. package/{controls → dist/controls}/scale.js +5 -5
  129. package/dist/controls/scale.js.map +1 -0
  130. package/{controls → dist/controls}/slot-register.js +1 -1
  131. package/dist/controls/slot-register.js.map +1 -0
  132. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  133. package/dist/controls/slot-services.js +155 -0
  134. package/dist/controls/slot-services.js.map +1 -0
  135. package/{controls → dist/controls}/slot.js +42 -24
  136. package/dist/controls/slot.js.map +1 -0
  137. package/{controls → dist/controls}/table/index.js +1 -1
  138. package/dist/controls/table/index.js.map +1 -0
  139. package/{controls → dist/controls}/table/prod.js +3 -3
  140. package/dist/controls/table/prod.js.map +1 -0
  141. package/{controls → dist/controls}/table/refs.js +13 -2
  142. package/dist/controls/table/refs.js.map +1 -0
  143. package/{controls → dist/controls}/table/stored.js +1 -1
  144. package/dist/controls/table/stored.js.map +1 -0
  145. package/{controls → dist/controls}/table/table-editor.js +51 -48
  146. package/dist/controls/table/table-editor.js.map +1 -0
  147. package/{controls → dist/controls}/table/table-link.js +3 -3
  148. package/dist/controls/table/table-link.js.map +1 -0
  149. package/{controls → dist/controls}/table/table.js +3 -3
  150. package/dist/controls/table/table.js.map +1 -0
  151. package/{controls → dist/controls}/text.d.ts +2 -2
  152. package/{controls → dist/controls}/text.js +78 -43
  153. package/dist/controls/text.js.map +1 -0
  154. package/dist/controls/unknown-value.d.ts +17 -0
  155. package/dist/controls/unknown-value.js +66 -0
  156. package/dist/controls/unknown-value.js.map +1 -0
  157. package/dist/core/core.d.ts +63 -0
  158. package/dist/core/core.js +171 -0
  159. package/dist/core/core.js.map +1 -0
  160. package/dist/core/facets.d.ts +347 -0
  161. package/dist/core/facets.js +334 -0
  162. package/dist/core/facets.js.map +1 -0
  163. package/dist/core/index.d.ts +3 -0
  164. package/dist/core/index.js +3 -0
  165. package/{engine → dist/engine}/array.js +34 -21
  166. package/dist/engine/array.js.map +1 -0
  167. package/{engine → dist/engine}/bits.js +1 -1
  168. package/dist/engine/bits.js.map +1 -0
  169. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  170. package/{engine → dist/engine}/breadcrumb.js +12 -36
  171. package/dist/engine/breadcrumb.js.map +1 -0
  172. package/{engine → dist/engine}/expand.d.ts +2 -4
  173. package/{engine → dist/engine}/expand.js +5 -22
  174. package/dist/engine/expand.js.map +1 -0
  175. package/{engine → dist/engine}/field-list.js +1 -1
  176. package/dist/engine/field-list.js.map +1 -0
  177. package/{engine → dist/engine}/field-shell.js +249 -121
  178. package/dist/engine/field-shell.js.map +1 -0
  179. package/{engine → dist/engine}/frame.d.ts +3 -1
  180. package/{engine → dist/engine}/frame.js +16 -14
  181. package/dist/engine/frame.js.map +1 -0
  182. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  183. package/{engine → dist/engine}/group-summary.js +7 -3
  184. package/dist/engine/group-summary.js.map +1 -0
  185. package/{engine → dist/engine}/grouping.d.ts +19 -5
  186. package/{engine → dist/engine}/grouping.js +193 -21
  187. package/dist/engine/grouping.js.map +1 -0
  188. package/{engine → dist/engine}/item-list.d.ts +11 -1
  189. package/{engine → dist/engine}/item-list.js +35 -13
  190. package/dist/engine/item-list.js.map +1 -0
  191. package/{engine → dist/engine}/kit-field.js +45 -10
  192. package/dist/engine/kit-field.js.map +1 -0
  193. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  194. package/{engine → dist/engine}/schema-form.js +182 -40
  195. package/dist/engine/schema-form.js.map +1 -0
  196. package/{engine → dist/engine}/slot.js +5 -15
  197. package/dist/engine/slot.js.map +1 -0
  198. package/dist/index.js +47 -0
  199. package/dist/index.js.map +1 -0
  200. package/{kit.css → dist/kit.css} +19 -0
  201. package/{lib → dist/lib}/cn.js +7 -4
  202. package/dist/lib/cn.js.map +1 -0
  203. package/{lib → dist/lib}/columns.js +4 -1
  204. package/dist/lib/columns.js.map +1 -0
  205. package/{lib → dist/lib}/frames.js +2 -2
  206. package/dist/lib/frames.js.map +1 -0
  207. package/dist/lib/icon-image.d.ts +10 -0
  208. package/dist/lib/icon-image.js +8 -0
  209. package/dist/lib/icon-image.js.map +1 -0
  210. package/{lib → dist/lib}/icons.js +4 -3
  211. package/dist/lib/icons.js.map +1 -0
  212. package/dist/lib/input-modality.d.ts +11 -0
  213. package/dist/lib/input-modality.js +47 -0
  214. package/dist/lib/input-modality.js.map +1 -0
  215. package/dist/lib/key-event.d.ts +11 -0
  216. package/dist/lib/key-event.js +16 -0
  217. package/dist/lib/key-event.js.map +1 -0
  218. package/{lib → dist/lib}/path.js +4 -2
  219. package/dist/lib/path.js.map +1 -0
  220. package/{lib → dist/lib}/schema.d.ts +34 -3
  221. package/{lib → dist/lib}/schema.js +110 -13
  222. package/dist/lib/schema.js.map +1 -0
  223. package/{lib → dist/lib}/utils.js +1 -1
  224. package/dist/lib/utils.js.map +1 -0
  225. package/{lib → dist/lib}/validate.d.ts +11 -1
  226. package/{lib → dist/lib}/validate.js +85 -11
  227. package/dist/lib/validate.js.map +1 -0
  228. package/dist/library/analysis.d.ts +23 -0
  229. package/dist/library/analysis.js +160 -0
  230. package/dist/library/analysis.js.map +1 -0
  231. package/dist/library/catalog.d.ts +57 -0
  232. package/dist/library/catalog.js +307 -0
  233. package/dist/library/catalog.js.map +1 -0
  234. package/dist/library/coreNotes.d.ts +8 -0
  235. package/dist/library/coreNotes.js +111 -0
  236. package/dist/library/coreNotes.js.map +1 -0
  237. package/dist/library/coverage.d.ts +40 -0
  238. package/dist/library/coverage.js +59 -0
  239. package/dist/library/coverage.js.map +1 -0
  240. package/dist/library/entries/advanced.entries.d.ts +2 -0
  241. package/dist/library/entries/advanced.entries.js +6579 -0
  242. package/dist/library/entries/advanced.entries.js.map +1 -0
  243. package/dist/library/entries/commerce.entries.d.ts +2 -0
  244. package/dist/library/entries/commerce.entries.js +4140 -0
  245. package/dist/library/entries/commerce.entries.js.map +1 -0
  246. package/dist/library/entries/company.entries.d.ts +2 -0
  247. package/dist/library/entries/company.entries.js +2731 -0
  248. package/dist/library/entries/company.entries.js.map +1 -0
  249. package/dist/library/entries/conversion.entries.d.ts +2 -0
  250. package/dist/library/entries/conversion.entries.js +3707 -0
  251. package/dist/library/entries/conversion.entries.js.map +1 -0
  252. package/dist/library/entries/data.entries.d.ts +7 -0
  253. package/dist/library/entries/data.entries.js +4613 -0
  254. package/dist/library/entries/data.entries.js.map +1 -0
  255. package/dist/library/entries/events.entries.d.ts +2 -0
  256. package/dist/library/entries/events.entries.js +3428 -0
  257. package/dist/library/entries/events.entries.js.map +1 -0
  258. package/dist/library/entries/features.entries.d.ts +2 -0
  259. package/dist/library/entries/features.entries.js +3157 -0
  260. package/dist/library/entries/features.entries.js.map +1 -0
  261. package/dist/library/entries/heroes.entries.d.ts +2 -0
  262. package/dist/library/entries/heroes.entries.js +3401 -0
  263. package/dist/library/entries/heroes.entries.js.map +1 -0
  264. package/dist/library/entries/index.d.ts +3 -0
  265. package/dist/library/entries/index.js +35 -0
  266. package/dist/library/entries/index.js.map +1 -0
  267. package/dist/library/entries/listings.entries.d.ts +2 -0
  268. package/dist/library/entries/listings.entries.js +2976 -0
  269. package/dist/library/entries/listings.entries.js.map +1 -0
  270. package/dist/library/entries/longform.entries.d.ts +2 -0
  271. package/dist/library/entries/longform.entries.js +4227 -0
  272. package/dist/library/entries/longform.entries.js.map +1 -0
  273. package/dist/library/entries/media.entries.d.ts +2 -0
  274. package/dist/library/entries/media.entries.js +2781 -0
  275. package/dist/library/entries/media.entries.js.map +1 -0
  276. package/dist/library/entries/navigation.entries.d.ts +2 -0
  277. package/dist/library/entries/navigation.entries.js +4011 -0
  278. package/dist/library/entries/navigation.entries.js.map +1 -0
  279. package/dist/library/entries/pricing.entries.d.ts +2 -0
  280. package/dist/library/entries/pricing.entries.js +2383 -0
  281. package/dist/library/entries/pricing.entries.js.map +1 -0
  282. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  283. package/dist/library/entries/social-proof.entries.js +2297 -0
  284. package/dist/library/entries/social-proof.entries.js.map +1 -0
  285. package/dist/library/examples/bento.d.ts +92 -0
  286. package/dist/library/examples/bento.js +201 -0
  287. package/dist/library/examples/bento.js.map +1 -0
  288. package/dist/library/examples/blocks.d.ts +14 -0
  289. package/dist/library/examples/blocks.js +313 -0
  290. package/dist/library/examples/blocks.js.map +1 -0
  291. package/dist/library/examples/faq.d.ts +28 -0
  292. package/dist/library/examples/faq.js +230 -0
  293. package/dist/library/examples/faq.js.map +1 -0
  294. package/dist/library/examples/hero.d.ts +43 -0
  295. package/dist/library/examples/hero.js +222 -0
  296. package/dist/library/examples/hero.js.map +1 -0
  297. package/dist/library/examples/index.d.ts +36 -0
  298. package/dist/library/examples/index.js +109 -0
  299. package/dist/library/examples/index.js.map +1 -0
  300. package/dist/library/examples/journalStory.d.ts +93 -0
  301. package/dist/library/examples/journalStory.js +338 -0
  302. package/dist/library/examples/journalStory.js.map +1 -0
  303. package/dist/library/examples/megaMenu.d.ts +134 -0
  304. package/dist/library/examples/megaMenu.js +442 -0
  305. package/dist/library/examples/megaMenu.js.map +1 -0
  306. package/dist/library/examples/pricing.d.ts +103 -0
  307. package/dist/library/examples/pricing.js +479 -0
  308. package/dist/library/examples/pricing.js.map +1 -0
  309. package/dist/library/examples/tabs.d.ts +87 -0
  310. package/dist/library/examples/tabs.js +180 -0
  311. package/dist/library/examples/tabs.js.map +1 -0
  312. package/dist/library/export.d.ts +42 -0
  313. package/dist/library/export.js +80 -0
  314. package/dist/library/export.js.map +1 -0
  315. package/dist/library/index.d.ts +13 -0
  316. package/dist/library/index.js +6 -0
  317. package/dist/library/kit-catalog.json +1510 -0
  318. package/dist/library/types.d.ts +42 -0
  319. package/dist/library/types.js +0 -0
  320. package/{schema → dist/schema}/adapters.js +1 -2
  321. package/dist/schema/adapters.js.map +1 -0
  322. package/{schema → dist/schema}/help.d.ts +2 -0
  323. package/{schema → dist/schema}/help.js +6 -4
  324. package/dist/schema/help.js.map +1 -0
  325. package/{schema → dist/schema}/scale.js +1 -1
  326. package/dist/schema/scale.js.map +1 -0
  327. package/{schema → dist/schema}/sources.js +1 -1
  328. package/dist/schema/sources.js.map +1 -0
  329. package/{schema → dist/schema}/table.js +11 -10
  330. package/dist/schema/table.js.map +1 -0
  331. package/{schema → dist/schema}/types.d.ts +29 -1
  332. package/{schema → dist/schema}/types.js +1 -1
  333. package/dist/schema/types.js.map +1 -0
  334. package/dist/styles.css +2 -0
  335. package/dist/table/table-view.d.ts +14 -0
  336. package/dist/table/table-view.js +140 -0
  337. package/dist/table/table-view.js.map +1 -0
  338. package/dist/table/table.css +73 -0
  339. package/dist/testing/corpus.d.ts +63 -0
  340. package/dist/testing/corpus.js +129 -0
  341. package/dist/testing/corpus.js.map +1 -0
  342. package/dist/testing/test-form.d.ts +11 -0
  343. package/dist/testing/test-form.js +38 -0
  344. package/dist/testing/test-form.js.map +1 -0
  345. package/dist/theme.css +345 -0
  346. package/dist/theme.d.ts +22 -0
  347. package/dist/theme.js +43 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens.css +542 -0
  350. package/dist/types.js +0 -0
  351. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  352. package/{ui → dist/ui}/action-tray.js +20 -19
  353. package/dist/ui/action-tray.js.map +1 -0
  354. package/dist/ui/autocomplete.d.ts +30 -0
  355. package/dist/ui/autocomplete.js +139 -0
  356. package/dist/ui/autocomplete.js.map +1 -0
  357. package/{ui → dist/ui}/button.d.ts +3 -3
  358. package/{ui → dist/ui}/button.js +6 -7
  359. package/dist/ui/button.js.map +1 -0
  360. package/{ui → dist/ui}/choice-switch.js +1 -1
  361. package/dist/ui/choice-switch.js.map +1 -0
  362. package/{ui → dist/ui}/controls.js +51 -39
  363. package/dist/ui/controls.js.map +1 -0
  364. package/{ui → dist/ui}/display.d.ts +10 -3
  365. package/{ui → dist/ui}/display.js +57 -46
  366. package/dist/ui/display.js.map +1 -0
  367. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  368. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  369. package/dist/ui/expanded-editor-modal.js.map +1 -0
  370. package/{ui → dist/ui}/field-context.js +1 -1
  371. package/dist/ui/field-context.js.map +1 -0
  372. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  373. package/{ui → dist/ui}/floating-panel.js +28 -12
  374. package/dist/ui/floating-panel.js.map +1 -0
  375. package/{ui → dist/ui}/index.d.ts +4 -0
  376. package/dist/ui/index.js +18 -0
  377. package/{ui → dist/ui}/input.d.ts +1 -1
  378. package/{ui → dist/ui}/input.js +9 -9
  379. package/dist/ui/input.js.map +1 -0
  380. package/{ui → dist/ui}/mode-bar.js +3 -3
  381. package/dist/ui/mode-bar.js.map +1 -0
  382. package/{ui → dist/ui}/overlay.d.ts +77 -5
  383. package/dist/ui/overlay.js +697 -0
  384. package/dist/ui/overlay.js.map +1 -0
  385. package/{ui → dist/ui}/path-crumbs.js +37 -3
  386. package/dist/ui/path-crumbs.js.map +1 -0
  387. package/{ui → dist/ui}/presence.js +2 -2
  388. package/dist/ui/presence.js.map +1 -0
  389. package/{ui → dist/ui}/select.js +89 -87
  390. package/dist/ui/select.js.map +1 -0
  391. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  392. package/dist/ui/shortcut-hint.js.map +1 -0
  393. package/dist/ui/spinner.d.ts +24 -0
  394. package/dist/ui/spinner.js +42 -0
  395. package/dist/ui/spinner.js.map +1 -0
  396. package/dist/ui/split-button.d.ts +32 -0
  397. package/dist/ui/split-button.js +60 -0
  398. package/dist/ui/split-button.js.map +1 -0
  399. package/{ui → dist/ui}/surfaces.js +1 -1
  400. package/dist/ui/surfaces.js.map +1 -0
  401. package/dist/ui/tab.d.ts +38 -0
  402. package/dist/ui/tab.js +87 -0
  403. package/dist/ui/tab.js.map +1 -0
  404. package/dist/ui/toast.d.ts +20 -0
  405. package/dist/ui/toast.js +115 -0
  406. package/dist/ui/toast.js.map +1 -0
  407. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  408. package/{ui → dist/ui}/tooltip-root.js +9 -8
  409. package/dist/ui/tooltip-root.js.map +1 -0
  410. package/{ui → dist/ui}/variants.js +1 -1
  411. package/dist/ui/variants.js.map +1 -0
  412. package/package.json +77 -23
  413. package/adapters/icons.js.map +0 -1
  414. package/adapters/lossy.js +0 -233
  415. package/adapters/lossy.js.map +0 -1
  416. package/adapters/prod-types.js.map +0 -1
  417. package/adapters/schema.js.map +0 -1
  418. package/adapters/values.js.map +0 -1
  419. package/brand/logo.js +0 -9
  420. package/brand/logo.js.map +0 -1
  421. package/context.js.map +0 -1
  422. package/controls/button.js.map +0 -1
  423. package/controls/c1.js.map +0 -1
  424. package/controls/c2.js.map +0 -1
  425. package/controls/choice.js.map +0 -1
  426. package/controls/code-register.js.map +0 -1
  427. package/controls/code.js.map +0 -1
  428. package/controls/color.js.map +0 -1
  429. package/controls/date-register.js.map +0 -1
  430. package/controls/date-zone.js.map +0 -1
  431. package/controls/date.js.map +0 -1
  432. package/controls/form-picker-register.js.map +0 -1
  433. package/controls/form-picker.js.map +0 -1
  434. package/controls/icon-register.js.map +0 -1
  435. package/controls/icon.js.map +0 -1
  436. package/controls/index.js.map +0 -1
  437. package/controls/json-register.js.map +0 -1
  438. package/controls/json.js.map +0 -1
  439. package/controls/link.js.map +0 -1
  440. package/controls/location-register.js.map +0 -1
  441. package/controls/location.js.map +0 -1
  442. package/controls/media-register.js.map +0 -1
  443. package/controls/media.js.map +0 -1
  444. package/controls/number.js.map +0 -1
  445. package/controls/reference-register.js.map +0 -1
  446. package/controls/reference.js.map +0 -1
  447. package/controls/rich-text/blocks.d.ts +0 -28
  448. package/controls/rich-text/blocks.js.map +0 -1
  449. package/controls/rich-text/catalog.js.map +0 -1
  450. package/controls/rich-text/codec.js.map +0 -1
  451. package/controls/rich-text/component-card.js.map +0 -1
  452. package/controls/rich-text/control.js.map +0 -1
  453. package/controls/rich-text/dom.js.map +0 -1
  454. package/controls/rich-text/editor.js.map +0 -1
  455. package/controls/rich-text/floating.js.map +0 -1
  456. package/controls/rich-text/index.js.map +0 -1
  457. package/controls/rich-text/link-form.js +0 -111
  458. package/controls/rich-text/link-form.js.map +0 -1
  459. package/controls/rich-text/markdown.js.map +0 -1
  460. package/controls/rich-text/ops.js.map +0 -1
  461. package/controls/rich-text/toolbar.js.map +0 -1
  462. package/controls/scale.js.map +0 -1
  463. package/controls/slot-register.js.map +0 -1
  464. package/controls/slot-services.js +0 -38
  465. package/controls/slot-services.js.map +0 -1
  466. package/controls/slot.js.map +0 -1
  467. package/controls/table/index.js.map +0 -1
  468. package/controls/table/prod.js.map +0 -1
  469. package/controls/table/refs.js.map +0 -1
  470. package/controls/table/stored.js.map +0 -1
  471. package/controls/table/table-editor.js.map +0 -1
  472. package/controls/table/table-link.js.map +0 -1
  473. package/controls/table/table.js.map +0 -1
  474. package/controls/text.js.map +0 -1
  475. package/engine/array.js.map +0 -1
  476. package/engine/bits.js.map +0 -1
  477. package/engine/breadcrumb.js.map +0 -1
  478. package/engine/expand.js.map +0 -1
  479. package/engine/field-list.js.map +0 -1
  480. package/engine/field-shell.js.map +0 -1
  481. package/engine/frame.js.map +0 -1
  482. package/engine/group-summary.js.map +0 -1
  483. package/engine/grouping.js.map +0 -1
  484. package/engine/item-list.js.map +0 -1
  485. package/engine/kit-field.js.map +0 -1
  486. package/engine/schema-form.js.map +0 -1
  487. package/engine/slot.js.map +0 -1
  488. package/index.js +0 -55
  489. package/index.js.map +0 -1
  490. package/lib/cn.js.map +0 -1
  491. package/lib/columns.js.map +0 -1
  492. package/lib/frames.js.map +0 -1
  493. package/lib/icons.js.map +0 -1
  494. package/lib/path.js.map +0 -1
  495. package/lib/schema.js.map +0 -1
  496. package/lib/utils.js.map +0 -1
  497. package/lib/validate.js.map +0 -1
  498. package/schema/adapters.js.map +0 -1
  499. package/schema/help.js.map +0 -1
  500. package/schema/scale.js.map +0 -1
  501. package/schema/sources.js.map +0 -1
  502. package/schema/table.js.map +0 -1
  503. package/schema/types.js.map +0 -1
  504. package/ui/action-tray.js.map +0 -1
  505. package/ui/button.js.map +0 -1
  506. package/ui/choice-switch.js.map +0 -1
  507. package/ui/controls.js.map +0 -1
  508. package/ui/display.js.map +0 -1
  509. package/ui/expanded-editor-modal.js.map +0 -1
  510. package/ui/field-context.js.map +0 -1
  511. package/ui/floating-panel.js.map +0 -1
  512. package/ui/index.js +0 -13
  513. package/ui/input.js.map +0 -1
  514. package/ui/mode-bar.js.map +0 -1
  515. package/ui/overlay.js +0 -378
  516. package/ui/overlay.js.map +0 -1
  517. package/ui/path-crumbs.js.map +0 -1
  518. package/ui/presence.js.map +0 -1
  519. package/ui/select.js.map +0 -1
  520. package/ui/shortcut-hint.js.map +0 -1
  521. package/ui/surfaces.js.map +0 -1
  522. package/ui/tooltip-root.js.map +0 -1
  523. package/ui/variants.js.map +0 -1
  524. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  525. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  526. /package/{brand → dist/brand}/logo.d.ts +0 -0
  527. /package/{controls → dist/controls}/c1.d.ts +0 -0
  528. /package/{controls → dist/controls}/c2.d.ts +0 -0
  529. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  530. /package/{controls → dist/controls}/code.d.ts +0 -0
  531. /package/{controls → dist/controls}/color.d.ts +0 -0
  532. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  533. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  534. /package/{controls → dist/controls}/date.d.ts +0 -0
  535. /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
  536. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  537. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  538. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  539. /package/{controls → dist/controls}/json.d.ts +0 -0
  540. /package/{controls → dist/controls}/link.d.ts +0 -0
  541. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  542. /package/{controls → dist/controls}/location.d.ts +0 -0
  543. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  544. /package/{controls → dist/controls}/number.d.ts +0 -0
  545. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  546. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  547. /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
  548. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  549. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  550. /package/{controls → dist/controls}/scale.d.ts +0 -0
  551. /package/{controls → dist/controls}/slot-register.d.ts +0 -0
  552. /package/{controls → dist/controls}/slot.d.ts +0 -0
  553. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  554. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  555. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  556. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  557. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  558. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  559. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  560. /package/{engine → dist/engine}/array.d.ts +0 -0
  561. /package/{engine → dist/engine}/bits.d.ts +0 -0
  562. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  563. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  564. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  565. /package/{engine → dist/engine}/slot.d.ts +0 -0
  566. /package/{index.d.ts → dist/index.d.ts} +0 -0
  567. /package/{lib → dist/lib}/cn.d.ts +0 -0
  568. /package/{lib → dist/lib}/columns.d.ts +0 -0
  569. /package/{lib → dist/lib}/frames.d.ts +0 -0
  570. /package/{lib → dist/lib}/icons.d.ts +0 -0
  571. /package/{lib → dist/lib}/path.d.ts +0 -0
  572. /package/{lib → dist/lib}/utils.d.ts +0 -0
  573. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  574. /package/{schema → dist/schema}/scale.d.ts +0 -0
  575. /package/{schema → dist/schema}/sources.d.ts +0 -0
  576. /package/{schema → dist/schema}/table.d.ts +0 -0
  577. /package/{types.d.ts → dist/types.d.ts} +0 -0
  578. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  579. /package/{ui → dist/ui}/controls.d.ts +0 -0
  580. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  581. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  582. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  583. /package/{ui → dist/ui}/presence.d.ts +0 -0
  584. /package/{ui → dist/ui}/select.d.ts +0 -0
  585. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  586. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  587. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"array.js","names":[],"sources":["../../src/kit/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, 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 });\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} onRemove={() => form.setAt(path, list.filter((_, j) => j !== i))}>\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 }: { id: string; labelId: string; sort: ReturnType<typeof useDragReorder>; children: React.ReactNode; onRemove: () => void; readOnly: 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 : (\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, 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 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={r.index === 0} onClick={() => ops.move(r.index, -1)}>Move up</MenuItem>\n <MenuItem icon={<IconArrowDown stroke={1.5} />} disabled={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 : (\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 </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 ? <span className=\"block truncate text-kit-xs text-kit-fg-3\">{r.extra ?? r.preview.subtitle}</span> : 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(\"group/row flex min-h-12 items-center gap-2 py-1.5 pl-1.5 pr-2 transition-colors\", onOpen && \"cursor-pointer\", 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}` : \"\"}, ${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 <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-inverse 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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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"bits.js","names":[],"sources":["../../src/kit/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,KAAK;;AAGnE,SAAgB,SAAS,EAAE,QAAQ,UAAU,aAAwE;AACnH,KAAI,CAAC,UAAU,CAAC,SAAU,QAAO;CACjC,MAAM,OAAO,SAAS,GAAG,OAAO,GAAG,WAAW,IAAI,UAAU,SAAS,WAAW,GAAG,SAAS,GAAG,aAAa,IAAI,eAAe;AAC/H,QACE,oBAAC,SAAD;EAAS,SAAS;YAChB,oBAAC,QAAD;GAAM,MAAK;GAAM,cAAY;GAAM,WAAW,GAAG,qDAAqD,SAAS,kBAAkB,kBAAkB,UAAU;GAAI,CAAA;EACzJ,CAAA;;;;;AAOd,SAAgB,MAAM,EAAE,OAAO,MAAM,OAAO,IAAI,aAAmF;AACjI,KAAI,MAAO,QAAO,oBAAC,OAAD;EAAK,KAAK;EAAO,KAAI;EAAG,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM;EAAE,WAAW,GAAG,+DAA+D,UAAU;EAAI,CAAA;AAC3K,QACE,oBAAC,QAAD;EAAM,OAAO;GAAE,OAAO;GAAM,QAAQ;GAAM;EAAE,WAAW,GAAG,uFAAuF,UAAU;YACzJ,oBAAC,SAAD;GAAS,MAAM;GAAM,WAAU;GAAW,CAAA;EACrC,CAAA;;AAIX,SAAgB,OAAO,EAAE,YAA2C;AAClE,QACE,oBAAC,OAAD;EAAK,aAAU;EAAY,WAAU;EAClC;EACG,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"breadcrumb.js","names":[],"sources":["../../src/kit/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 { AnimatePresence, motion } from \"framer-motion\";\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, height + fade 180ms, ease [0.22, 1, 0.36, 1]. The document variant sticks under the\n * 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 return (\n <AnimatePresence initial={false}>\n {crumbs.length > 1 ? (\n <motion.div\n key=\"crumbs\"\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: 0.18, ease: [0.22, 1, 0.36, 1] }}\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 </motion.div>\n ) : null}\n </AnimatePresence>\n );\n}\n"],"mappings":";;;;;;;;AAuBA,IAAM,gBAA8B,SAAS,oBAAC,SAAD,EAAe,MAAQ,CAAA;;AAGpE,SAAgB,aAAa,QAAoB,YAAuC,UAAwB,cAA2B;AACzI,QAAO,OAAO,KAAK,OAAO;EACxB,IAAI,EAAE;EACN,OAAO,EAAE;EACT,MAAM,EAAE,OAAO,QAAQ,EAAE,KAAK,GAAG,KAAA;EACjC,QAAQ,EAAE;EACV,gBAAgB,WAAW,EAAE,KAAK;EACnC,EAAE;;AAGL,SAAgB,cAAc,EAAE,QAAQ,YAAY,WAAW,WAAsH;AACnL,KAAI,OAAO,SAAS,EAAG,QAAO;AAC9B,QAAO,oBAAC,YAAD;EAAY,OAAO,aAAa,QAAQ,YAAY,QAAQ;EAAE,cAAa;EAAM,OAAM;EAAa,WAAW,aAAa;EAAU,CAAA;;;;;;AAO/I,SAAgB,eACd,QACA,QACA,QACA,WACY;AACZ,QAAO,OAAO,KAAK,GAAG,OAAO;EAC3B,KAAK,WAAW,EAAE,KAAK;EACvB,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,GAAG,GAAG,EAAE,KAAK,CAAC;EACnF,EAAE;;;AAIL,IAAa,kBAAkB,WAAuB,OAAO,KAAK,MAAM,GAAG,EAAE,IAAI,QAAQ,EAAE,MAAM,QAAQ,EAAE,QAAQ,GAAG,QAAQ,EAAE,UAAU,IAAI,CAAC,KAAK,IAAS;;;;;;AAO7J,SAAgB,YAAY,EAC1B,QACA,YACA,SACA,WAMC;AACD,QACE,oBAAC,iBAAD;EAAiB,SAAS;YACvB,OAAO,SAAS,IACf,oBAAC,OAAO,KAAR;GAEE,SAAS;IAAE,QAAQ;IAAG,SAAS;IAAG;GAClC,SAAS;IAAE,QAAQ;IAAQ,SAAS;IAAG;GACvC,MAAM;IAAE,QAAQ;IAAG,SAAS;IAAG;GAC/B,YAAY;IAAE,UAAU;IAAM,MAAM;KAAC;KAAM;KAAG;KAAM;KAAE;IAAE;GACxD,qBAAA;GACA,WAAW,GACT,0EACA,YAAY,aAAa,gHAAgH,OAC1I;aAED,oBAAC,eAAD;IAAuB;IAAoB;IAAqB;IAAW,CAAA;GAChE,EAZP,SAYO,GACX;EACY,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"expand.js","names":[],"sources":["../../src/kit/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 (\"312 words\", \"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\n/** Words in a value: a string (tags stripped), Portable Text blocks, or a rich-text envelope ({ html } / { value }). */\nexport function wordsIn(value: unknown): number {\n const text = textOf(value).trim();\n return text ? text.split(/\\s+/).length : 0;\n}\nfunction textOf(v: unknown): string {\n if (typeof v === \"string\") return v.replace(/<[^>]*>/g, \" \").replace(/&nbsp;/g, \" \");\n if (Array.isArray(v)) return v.map(textOf).join(\" \");\n if (!isObj(v)) return \"\";\n if (typeof v.text === \"string\") return v.text;\n if (Array.isArray(v.children)) return textOf(v.children);\n if (typeof v.html === \"string\") return textOf(v.html);\n if (\"value\" in v) return textOf(v.value);\n return \"\";\n}\nconst count = (n: number, one: string, many = `${one}s`) => `${n} ${n === 1 ? one : many}`;\nconst words = (v: unknown) => count(wordsIn(v), \"word\");\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\", meta: words, 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 +0,0 @@
1
- {"version":3,"file":"field-list.js","names":[],"sources":["../../src/kit/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;CAAU,CAAA;AAEnH,SAAgB,UAAU,OAAuB;AAC/C,QAAO,oBAAC,aAAD;EAAkB,GAAI;EAAO,aAAa;EAAkB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"field-shell.js","names":[],"sources":["../../src/kit/engine/field-shell.tsx"],"sourcesContent":["/**\n * FIELD SHELL — the one field chrome (V2 HEAD 9829bf1 kit/engine/field-shell.tsx; production FieldShell + CPO D8).\n *\n * [Label *] [ⓘ] [override dot] [changed dot] [synced] [EN] …… [42 / 60] [action] [Reset] [undo] [comments] [presence] [⋯]\n * help text (CPO D39: 12/16 --fg-3, 4px under the label, 1–2 lines; hidden while an error shows)\n * ┌ control ───────────────────────────────┐ ← peer editing: the control's border in their colour\n * └────────────────────────────────────────┘\n * error / warning message ……………………… meta (42 / 60)\n *\n * Accessories (add-comment, ⋯) take NO space at rest; they appear on hover/focus (always on touch). A comment\n * COUNT chip is always visible. AI lives in ⋯ (\"Rewrite with AI\"), never as a label sparkle (CPO-142).\n *\n * Services (toast, AI rewrite, in-place comments) come from KitServices; a missing service hides its surface.\n */\nimport * as React from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n IconAlertCircle, IconAlertTriangle, IconArrowBackUp, IconBraces, IconClipboard, IconCopy, IconDots, IconHistory,\n IconMessage, IconMessagePlus, IconRefresh, IconRotate, IconWorld,\n} from \"@tabler/icons-react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { Button, Sparkle } from \"../ui/button\";\nimport { Avatar, avatarRingSpread } from \"../ui/display\";\nimport { HelpMore } from \"../ui/input\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverAnchor, PopoverContent, Tooltip } from \"../ui/overlay\";\nimport { presenceColor } from \"../ui/presence\";\nimport { cn } from \"../lib/cn\";\nimport { HISTORY_SEGMENT, type FieldPath, type FieldSchema } from \"../schema/types\";\nimport { resolveHelp } from \"../schema/help\";\nimport { AI_PRESETS, FieldHeaderSlot, seesDevSurfaces, useForm, useKitEnv, useKitServices, type AiPreset, type KitPeer } from \"../context\";\nimport { pathKey, same } from \"../lib/path\";\nimport { isTextual, plainText } from \"../lib/schema\";\nimport { textLength, type KitIssue } from \"../lib/validate\";\nimport { RowChrome } from \"./bits\";\n\n/* ── Clipboard shared by every field (typed, so Paste can refuse with a reason) ── */\n/** `html`: a rich text value as its editor html (read through the host's codec), so Paste re-stores it for the target field. */\nlet clip: { type: string; value: unknown; label: string; html?: string } | null = null;\n/** Test seam: forget the shared field clipboard. */\nexport const resetFieldClipboard = () => {\n clip = null;\n};\nconst KIND: Record<string, string> = { image: \"an image\", file: \"a file\", video: \"a video\", reference: \"a reference\", link: \"a link\", button: \"a button\", array: \"a list\", slot: \"blocks\", object: \"a group of fields\", boolean: \"an on/off value\", number: \"a number\", color: \"a colour\" };\nconst kindOf = (t: string) => (isTextual(t as FieldSchema[\"type\"]) ? \"text\" : KIND[t] ?? t);\n\ntype RichTextCodec = NonNullable<ReturnType<typeof useKitServices>[\"richText\"]>;\nconst escHtml = (s: string) => s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n/** Plain text as editor html: one escaped paragraph per line. */\nconst paragraphs = (text: string) =>\n text\n .split(/\\n+/)\n .map((l) => l.trim())\n .filter(Boolean)\n .map((l) => `<p>${escHtml(l)}</p>`)\n .join(\"\");\n/**\n * Html into a rich text field, stored in the field's own shape through the host's codec. A write that would drop\n * something is refused with the words the codec names; nothing is stored.\n */\nfunction richTextWrite(codec: RichTextCodec, field: FieldSchema, path: FieldPath, html: string, prev: unknown): { value: unknown } | { refused: string } {\n try {\n const out = codec.write(html, { field, path }, prev);\n return out.losses.length ? { refused: `${field.title} can't keep ${out.losses.join(\", \")}` } : { value: out.value };\n } catch (err) {\n return { refused: `${field.title} could not store this text (${err instanceof Error ? err.message : String(err)})` };\n }\n}\n/** A rich text value as editor html, when the host's codec reads it. */\nfunction richTextHtml(codec: RichTextCodec | undefined, field: FieldSchema, path: FieldPath, value: unknown): string | undefined {\n if (!codec || field.type !== \"richtext\") return undefined;\n try {\n return codec.read(value, { field, path }).html;\n } catch {\n return undefined; // Paste falls back to the value's words\n }\n}\n\nexport const apiName = (schemaName: string, path: FieldPath) =>\n [schemaName, ...path.filter((s) => s !== HISTORY_SEGMENT)].reduce<string>((a, s) => (typeof s === \"number\" ? `${a}[${s}]` : a ? `${a}.${s}` : String(s)), \"\");\n\n/** A long label truncates on one line; past this many characters a native `title` carries the full label (DESIGN 4.4). */\nexport const LABEL_HINT_AT = 28;\n\nconst REVEAL =\n \"hidden group-hover/field:inline-flex group-focus-within/field:inline-flex data-[state=open]:inline-flex data-[popup-open]:inline-flex [@media(pointer:coarse)]:inline-flex\";\n\nexport interface FieldShellProps {\n field: FieldSchema;\n path: FieldPath;\n id: string;\n value: unknown;\n onChange: (v: unknown) => void;\n readOnly?: boolean;\n issue?: KitIssue;\n /** label-row action (e.g. slug \"Generate\") */\n action?: React.ReactNode;\n /** \"card\" = the boolean switch card · \"row\" = the control IS a labelled row (a drill-in object, CPO D45): no label row,\n * the chrome goes into the row through `RowChrome` */\n layout?: \"stack\" | \"card\" | \"row\";\n /** layout fields get no comment control */\n noComments?: boolean;\n /** right side of the message line (counters, \"3 items · max 6\") */\n meta?: React.ReactNode;\n className?: string;\n children: React.ReactNode;\n}\n\nexport function FieldShell({ field, path, id, value, onChange, readOnly, issue, action, layout = \"stack\", noComments, meta, className, children }: FieldShellProps) {\n const env = useKitEnv();\n const form = useForm();\n const services = useKitServices();\n const key = pathKey(path);\n /* A host can lift this field's chrome into its own header (All fields: a block whose only field is \"Stats\" under a\n \"Stats\" section) — then there is no label row at all; the label stays for screen readers. */\n const slot = React.useContext(FieldHeaderSlot);\n const lifted = slot && slot.key === key && layout === \"stack\" ? slot.el : null;\n const [ai, setAi] = React.useState(false);\n const [commentsOpen, setCommentsOpen] = React.useState(false);\n /* V2 fieldPopoverCollision: the comments popover stays inside the scrolling area the field sits in */\n const [commentArea, setCommentArea] = React.useState<CommentCollision>({ collisionPadding: 12 });\n const peers = env.presence[key] ?? [];\n const editor = peers.find((p) => p.status !== \"viewing\");\n const InPlaceComments = services.FieldComments;\n const canComment = !noComments && (!!env.onComment || !!InPlaceComments);\n const openCount = env.comments[key] ?? 0; // with no env.onComment and a count hook, CommentButton reads the store\n const useStoreCount = env.onComment ? undefined : services.useFieldCommentCount;\n const changed = !!form?.hasPublished && !same(value, form.publishedAt(path));\n /* component instance (D28): a top-level field either inherits the component's value or overrides it */\n const inh = form?.inherited && path.length === 1 ? form.inherited : undefined;\n const overridden = !!inh && inh.isOverridden(key);\n const canUndo = !!form?.canUndo(key) && !readOnly;\n const synced = field.synced?.from; // a whole synced form shows one notice at its root, not a chip per field\n const limit = field.validation?.max ?? field.validation?.recommendedMax;\n const len = textLength(value);\n /* counters stay quiet: shown while the field has focus, or when the value nears its limit */\n const near = !!limit && len >= limit * 0.8;\n const counter =\n limit && (field.type === \"string\" || field.type === \"text\" || field.type === \"richtext\") ? (\n <span\n data-slot=\"field-counter\"\n className={cn(\n \"tabular-nums text-kit-xs\",\n !near && \"hidden group-focus-within/field:inline\",\n field.validation?.max && len > field.validation.max ? \"text-kit-danger-fg\" : field.validation?.recommendedMax && len > field.validation.recommendedMax ? \"text-kit-warning-fg\" : \"text-kit-fg-3\",\n )}\n >\n {len} / {limit}\n </span>\n ) : null;\n\n /* ── Help (CPO D39) ── one line under the label; longer text behind ⓘ. Dense hosts (env.helpDisplay \"tooltip\")\n move the line into the ⓘ too. An error REPLACES the help (warnings keep it: they're advice, not a block). */\n const dense = env.helpDisplay === \"tooltip\";\n const help = resolveHelp(field); // arrays / slots / objects reach the shell without KitField: conventions apply here too\n const more = field.helpMore || undefined;\n const erroring = issue?.level === \"error\";\n const helpInline = !!help && !dense && !erroring;\n const tip = dense ? [help, more].filter(Boolean).join(\" \") : more;\n const helpId = `${id}-help`;\n const moreId = `${id}-more`;\n const msgId = `${id}-msg`;\n const describedBy = [helpInline && helpId, tip && moreId, issue && msgId].filter(Boolean).join(\" \");\n /* Controls are many (input, textarea, contenteditable, pickers); the shell owns the ids, so it wires\n aria-describedby onto whatever element carries the field id, keeping any ids the control set itself. */\n React.useEffect(() => {\n const el = document.getElementById(id);\n if (!el) return;\n const own = (el.getAttribute(\"aria-describedby\") ?? \"\").split(\" \").filter((t) => t && !t.startsWith(`${id}-`));\n const next = [...own, ...describedBy.split(\" \").filter(Boolean)].join(\" \");\n if (next) el.setAttribute(\"aria-describedby\", next);\n else el.removeAttribute(\"aria-describedby\");\n }, [id, describedBy]);\n const info = tip ? (\n <HelpMore id={moreId} label={field.title}>\n {tip}\n </HelpMore>\n ) : null;\n\n const label = (\n <>\n <span className=\"truncate\">{field.title}</span>\n {field.validation?.required ? (\n <>\n <span aria-hidden className=\"text-kit-fg-2\">*</span>\n <span className=\"sr-only\">(required)</span>\n </>\n ) : null}\n </>\n );\n const badges = (\n <>\n {overridden ? (\n <Tooltip content={`Overrides ${inh!.from}. Changes to the component no longer reach this field.`}>\n <span role=\"img\" className=\"size-1.5 shrink-0 rounded-full bg-kit-accent\" aria-label={`Overrides ${inh!.from}`} />\n </Tooltip>\n ) : null}\n {changed ? (\n <Tooltip content=\"Changed since publish\">\n <span role=\"img\" className=\"size-1.5 shrink-0 rounded-full bg-kit-warning\" aria-label=\"Changed since publish\" />\n </Tooltip>\n ) : null}\n {synced ? (\n <Tooltip content={`Synced from ${synced}. Changes apply on every page that uses it.`}>\n <span className=\"inline-flex h-4 shrink-0 items-center gap-0.5 rounded-kit-md bg-kit-info-soft px-1 text-kit-2xs font-medium text-kit-info-fg\">\n <IconRefresh className=\"size-2.5\" stroke={2} aria-hidden />\n Synced\n </span>\n </Tooltip>\n ) : null}\n {field.localized ? (\n <Tooltip content=\"Translatable · English (default). Spanish and French are missing.\">\n <span className=\"inline-flex h-4 shrink-0 items-center gap-0.5 rounded-kit-md bg-kit-muted px-1 text-kit-2xs font-medium text-kit-fg-3\">\n <IconWorld className=\"size-2.5\" stroke={2} aria-hidden />\n EN\n </span>\n </Tooltip>\n ) : null}\n </>\n );\n const accessories = (\n <>\n {action}\n {overridden && !readOnly ? (\n <Tooltip content={`Use ${inh!.from}'s value again`}>\n <button\n type=\"button\"\n onClick={(e) => {\n const box = (e.currentTarget as HTMLElement).closest<HTMLElement>(\"[data-field-key]\");\n inh!.reset(key);\n // the button goes away with the override: keep focus in the field, never on <body>\n requestAnimationFrame(() => (document.getElementById(id) ?? box?.querySelector<HTMLElement>(\"textarea, input, [contenteditable=true], button\"))?.focus({ preventScroll: true }));\n }}\n aria-label={`Reset ${field.title} to ${inh!.from}`}\n className=\"inline-flex h-5 items-center rounded-kit-md px-1 text-kit-xs text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\"\n >\n Reset\n </button>\n </Tooltip>\n ) : null}\n {canUndo ? (\n <Tooltip content={`Undo last change to ${field.title}`}>\n <button type=\"button\" aria-label={`Undo last change to ${field.title}`} onClick={() => form?.undo(key)} className=\"inline-flex size-5 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconArrowBackUp className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n </Tooltip>\n ) : null}\n {canComment ? (\n <CommentButton\n count={openCount}\n useCount={useStoreCount ? () => useStoreCount(env.docId, key) : undefined}\n label={field.title}\n open={commentsOpen}\n onOpen={(el) => {\n if (env.onComment) return env.onComment(path, field); // the host owns comments (e.g. the document editor)\n setCommentArea(fieldPopoverCollision(el.closest(\"[data-field-key]\")));\n setCommentsOpen(true);\n }}\n />\n ) : null}\n <PeerStack peers={peers} />\n <FieldMenu field={field} path={path} value={value} onChange={onChange} readOnly={!!readOnly} changed={changed} onAi={() => setAi(true)} />\n </>\n );\n\n // Peer editing (Figma / Notion / Sanity): only the field's own input border takes their --presence-n colour (full strength:\n // the old 70% mix read as a validation error at 1.96:1) —\n // no outline around the input + preview, no name tag over the border, no layout shift. Who it is: the face in the label row.\n const control = (\n <div\n className={cn(\"relative\", editor && \"[&_.border-kit-field-border]:border-[var(--peer)]\")}\n style={editor ? ({ \"--peer\": editor.color ?? presenceColor(editor.id ?? editor.name) } as React.CSSProperties) : undefined}\n >\n {children}\n </div>\n );\n\n const message =\n issue || meta ? (\n <div className=\"flex min-h-4 items-start justify-between gap-3\">\n <AnimatePresence initial={false}>\n {issue ? (\n <motion.p\n key={issue.message}\n id={msgId}\n initial={{ opacity: 0, y: -2 }}\n animate={{ opacity: 1, y: 0 }}\n role={issue.level === \"error\" ? \"alert\" : \"status\"}\n className={cn(\"flex min-w-0 items-start gap-1 text-kit-xs\", issue.level === \"error\" ? \"text-kit-danger-fg\" : \"text-kit-warning-fg\")}\n >\n {issue.level === \"error\" ? <IconAlertCircle className=\"mt-px size-3.5 shrink-0\" stroke={1.5} aria-hidden /> : <IconAlertTriangle className=\"mt-px size-3.5 shrink-0\" stroke={1.5} aria-hidden />}\n {issue.message}\n </motion.p>\n ) : (\n <span />\n )}\n </AnimatePresence>\n {meta ? <span className=\"flex shrink-0 items-center gap-2\">{meta}</span> : null}\n </div>\n ) : null;\n\n const labelEl = (\n <label\n htmlFor={id}\n id={`${id}-label`}\n className=\"flex min-w-0 items-center gap-1 text-kit-sm font-medium text-kit-fg-2 transition-colors group-focus-within/field:text-kit-fg\"\n title={field.title.length > LABEL_HINT_AT ? field.title : undefined}\n >\n {label}\n </label>\n );\n\n const body =\n layout === \"row\" ? (\n <div className={cn(\"group/field flex min-w-0 flex-col gap-1.5\", className)} data-field-key={key} data-field={path.length === 1 ? key : undefined} data-slot=\"kit-field\">\n <RowChrome.Provider value={<>{info}{badges}{accessories}</>}>{control}</RowChrome.Provider>\n {message}\n </div>\n ) : layout === \"card\" ? (\n <div className={cn(\"group/field flex flex-col gap-1.5\", className)} data-field-key={key} data-field={path.length === 1 ? key : undefined} data-slot=\"kit-field\">\n <div className={cn(\"flex items-center gap-3 rounded-kit-lg border bg-kit-surface px-3 py-2.5 transition-colors\", issue?.level === \"error\" ? \"border-[var(--kit-field-invalid)]\" : \"border-kit-line hover:border-kit-line-strong\")}>\n {control}\n <label htmlFor={id} id={`${id}-label`} className=\"min-w-0 flex-1 cursor-pointer\">\n <span className=\"flex min-w-0 items-center gap-1.5 text-kit-sm font-medium text-kit-fg\">\n {label}\n {info}\n {badges}\n </span>\n {helpInline ? (\n <span id={helpId} data-slot=\"field-help\" className=\"block text-kit-xs leading-4 text-kit-fg-3\">\n {help}\n </span>\n ) : null}\n </label>\n <span className=\"shrink-0 text-kit-xs text-kit-fg-3\">{value ? \"On\" : \"Off\"}</span>\n <span className=\"flex shrink-0 items-center gap-0.5 empty:hidden\">{accessories}</span>\n </div>\n {message}\n </div>\n ) : (\n <div\n className={cn(\"group/field flex min-w-0 flex-col gap-1.5\", className)}\n data-field-key={key}\n data-field={path.length === 1 ? key : undefined}\n data-slot=\"kit-field\"\n data-inherited={inh && !overridden ? \"\" : undefined}\n data-overridden={overridden ? \"\" : undefined}\n >\n {lifted ? (\n <>\n <label htmlFor={id} id={`${id}-label`} className=\"sr-only\">\n {label}\n </label>\n {createPortal(\n <span className=\"flex items-center gap-0.5 [&>button]:!inline-flex\">\n {info}\n {badges}\n {counter}\n {accessories}\n </span>,\n lifted,\n )}\n </>\n ) : (\n <div data-slot=\"field-label-row\" className=\"flex min-h-5 min-w-0 items-center gap-1.5\">\n {labelEl}\n {info}\n {badges}\n <span className=\"flex-1\" />\n {counter}\n <span className=\"flex shrink-0 items-center gap-0.5\">{accessories}</span>\n </div>\n )}\n {helpInline ? (\n <p id={helpId} data-slot=\"field-help\" className=\"-mt-0.5 text-kit-xs leading-4 text-kit-fg-3\">\n {help}\n </p>\n ) : null}\n {control}\n {message}\n </div>\n );\n\n /* The AI popover and the comments popover both anchor to the field (two stacked anchor divs). */\n return (\n <Popover open={ai} onOpenChange={setAi}>\n <PopoverAnchor className=\"min-w-0\">\n <Popover\n open={commentsOpen}\n onOpenChange={(open, d) => {\n /* V2 guardEscape: Escape inside the composer (data-esc-owner) belongs to the draft, not the popover */\n if (!open && d.reason === \"escape-key\" && (document.activeElement as HTMLElement | null)?.hasAttribute(\"data-esc-owner\")) return d.cancel();\n setCommentsOpen(open);\n }}\n >\n <PopoverAnchor className=\"min-w-0\">{body}</PopoverAnchor>\n {commentsOpen && InPlaceComments ? (\n <PopoverContent align=\"start\" sideOffset={8} {...commentArea} initialFocus={false} className=\"w-[clamp(280px,var(--anchor-width),420px)] p-0\">\n <InPlaceComments\n docId={env.docId}\n fieldKey={key}\n label={field.title}\n quote={plainText(value).slice(0, 80) || undefined}\n onClose={() => setCommentsOpen(false)}\n onOpenPanel={\n env.onComment\n ? () => {\n env.onComment?.(path, field);\n setCommentsOpen(false);\n }\n : undefined\n }\n />\n </PopoverContent>\n ) : null}\n </Popover>\n </PopoverAnchor>\n {ai ? (\n <PopoverContent align=\"start\" sideOffset={8} className=\"w-[clamp(300px,var(--anchor-width),440px)] p-0\">\n <AiRewrite field={field} path={path} value={value} onChange={onChange} onClose={() => setAi(false)} />\n </PopoverContent>\n ) : null}\n </Popover>\n );\n}\n\ntype CommentCollision = { collisionBoundary?: Element; collisionPadding: number | Partial<Record<\"top\" | \"right\" | \"bottom\" | \"left\", number>> };\n/** V2 features/comments fieldPopoverCollision: inside a scrolling panel, collide with that panel below its sticky header. */\nfunction fieldPopoverCollision(anchor: Element | null): CommentCollision {\n let area = anchor?.parentElement ?? null;\n while (area && !/(auto|scroll)/.test(getComputedStyle(area).overflowY)) area = area.parentElement;\n if (!area || area === document.scrollingElement) return { collisionPadding: 12 };\n const sticky = parseFloat(getComputedStyle(area).getPropertyValue(\"--kit-sticky-top\")) || 0;\n return { collisionBoundary: area, collisionPadding: { top: sticky + 8, right: 8, bottom: 8, left: 8 } };\n}\n\n/** Comment count chip (always visible) or the hover-revealed \"Add comment\" icon. `useCount` (the host's store hook)\n * replaces `count` when the kit draws the comments in place. */\nfunction CommentButton({ useCount, ...props }: CommentButtonProps & { useCount?: () => number }) {\n return useCount ? <StoreCommentButton useCount={useCount} {...props} /> : <CountedCommentButton {...props} />;\n}\ninterface CommentButtonProps {\n count: number;\n label: string;\n open: boolean;\n onOpen: (el: HTMLElement) => void;\n}\nfunction StoreCommentButton({ useCount, ...props }: CommentButtonProps & { useCount: () => number }) {\n return <CountedCommentButton {...props} count={useCount()} />;\n}\nfunction CountedCommentButton({ count, label, open, onOpen }: CommentButtonProps) {\n if (count > 0)\n return (\n <Tooltip content={`${count} open comment${count === 1 ? \"\" : \"s\"} on ${label}`}>\n <button\n type=\"button\"\n onClick={(e) => onOpen(e.currentTarget)}\n data-state={open ? \"open\" : \"closed\"}\n aria-label={`${count} open comments on ${label}`}\n className=\"inline-flex h-5 items-center gap-1 rounded-full bg-[var(--kit-chip-ink-bg)] px-1.5 text-kit-2xs font-medium text-[var(--kit-chip-ink-fg)] hover:opacity-90\"\n >\n <IconMessage className=\"size-3\" stroke={2} aria-hidden />\n <span className=\"tabular-nums\">{count}</span>\n </button>\n </Tooltip>\n );\n return (\n <Tooltip content=\"Add comment\">\n <button\n type=\"button\"\n onClick={(e) => onOpen(e.currentTarget)}\n data-state={open ? \"open\" : \"closed\"}\n aria-label={`Add comment to ${label}`}\n className={cn(REVEAL, \"-my-0.5 size-6 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\")}\n >\n <IconMessagePlus className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n </Tooltip>\n );\n}\n\n/** Who is in this field: 16px faces in the label row's action slot (no overlap with the label or the input), name on hover. */\nexport function PeerStack({ peers, size = 16 }: { peers: KitPeer[]; size?: number }) {\n const shown = peers.slice(0, 3);\n const rest = peers.length - shown.length;\n // Each slot reserves the ring band (1px surface gap + 1px presence colour) on every side, so the ring sits inside\n // the slot: a clipping ancestor or the row's edge can never shave it. Faces still overlap by 25% of their size.\n const ring = \"var(--kit-avatar-ring, var(--kit-surface))\";\n const band = avatarRingSpread({ ring, ringWidth: 1, ringAccent: \"x\" });\n const box = size + band * 2;\n const overlap = -(Math.round(size * 0.25) + band * 2);\n return (\n <AnimatePresence initial={false}>\n {shown.length ? (\n <motion.span key=\"peers\" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} transition={{ duration: 0.25 }} className=\"flex h-5 items-center\" data-slot=\"field-presence\">\n {/* D34 stack rules: same size, 25% overlap, first face on top; the ring is box-shadow (surface gap + the\n peer's presence colour) so the photo keeps its full size. */}\n {shown.map((p, i) => (\n <Tooltip key={p.name + i} content={`${p.name} · ${p.status === \"viewing\" ? \"Viewing\" : \"Editing\"} this field`}>\n <span\n style={{ marginLeft: i ? overlap : 0, zIndex: shown.length - i + 1, width: box, height: box }}\n className={cn(\"relative inline-flex shrink-0 rounded-full transition-transform duration-150 hover:!z-30 hover:-translate-y-px\", p.status === \"viewing\" && \"opacity-60\")}\n >\n <Avatar name={p.name} src={p.avatar} size={size} ring={ring} ringWidth={1} ringAccent={p.color ?? presenceColor(p.id ?? p.name)} decorative />\n </span>\n </Tooltip>\n ))}\n {rest > 0 ? (\n <Tooltip content={peers.slice(shown.length).map((p) => p.name).join(\", \")}>\n <span style={{ marginLeft: overlap, width: box, height: box, padding: band }} className=\"relative z-[1] inline-flex shrink-0\">\n <span\n style={{ width: size, height: size, boxShadow: `0 0 0 ${band}px var(--kit-surface)`, fontSize: Math.max(8, Math.round(size * 0.5)) }}\n className=\"inline-flex items-center justify-center rounded-full bg-kit-muted font-medium leading-none tabular-nums text-kit-fg-2\"\n >\n +{rest}\n </span>\n </span>\n </Tooltip>\n ) : null}\n </motion.span>\n ) : null}\n </AnimatePresence>\n );\n}\n\n/* ── ⋯ Field actions (DESIGN 8.25) ─────────────────────────────────── */\nfunction FieldMenu({ field, path, value, onChange, readOnly, changed, onAi }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void; readOnly: boolean; changed: boolean; onAi: () => void }) {\n const form = useForm();\n const env = useKitEnv();\n const { toast, aiRewrite, richText } = useKitServices();\n const key = pathKey(path);\n const api = apiName(form?.schema.name ?? \"doc\", path);\n const textual = isTextual(field.type);\n // rich text is rewritten only where the host's codec can store the result in the field's own shape\n const prose = field.type === \"string\" || field.type === \"text\" || (field.type === \"richtext\" && !!richText);\n const editable = !readOnly;\n const dev = seesDevSurfaces(env);\n return (\n <Menu>\n <Tooltip content=\"Field actions\">\n <MenuTrigger\n aria-label={`${field.title} actions`}\n className={cn(REVEAL, \"-my-0.5 size-6 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-3.5\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n </Tooltip>\n <MenuContent align=\"end\" className=\"w-60\">\n <MenuItem\n icon={<IconCopy stroke={1.5} />}\n onClick={() => {\n const html = richTextHtml(richText, field, path, value);\n clip = { type: field.type, value: structuredCloneish(value), label: field.title, ...(html !== undefined ? { html } : {}) };\n const text = textual ? plainText(value) || \"\" : typeof value === \"string\" ? value : JSON.stringify(value ?? null, null, 2);\n void navigator.clipboard?.writeText(text).catch(() => {});\n toast?.success(`${field.title} copied`);\n }}\n >\n Copy value\n </MenuItem>\n {editable ? <PasteItem field={field} path={path} value={value} onChange={onChange} /> : null}\n {editable && form?.hasPublished && changed ? (\n <MenuItem\n icon={<IconRotate stroke={1.5} />}\n onClick={() => {\n const prev = value;\n onChange(form.publishedAt(path));\n toast?.(`${field.title} reset to published`, { action: { label: \"Undo\", onClick: () => onChange(prev) }, duration: 10_000 });\n }}\n >\n Reset to published\n </MenuItem>\n ) : null}\n {form?.canNavigate ? (\n <MenuItem icon={<IconHistory stroke={1.5} />} onClick={() => form.navigate([...path, HISTORY_SEGMENT])}>\n History\n </MenuItem>\n ) : null}\n {editable && prose && aiRewrite ? (\n <>\n <MenuSeparator />\n {form?.aiKeys.has(key) ? (\n <MenuItem\n icon={<IconArrowBackUp stroke={1.5} />}\n onClick={() => {\n form.undo(key);\n form.markAi(key, false);\n }}\n >\n Undo AI change\n </MenuItem>\n ) : null}\n <MenuItem icon={<Sparkle size={16} />} onClick={() => window.setTimeout(onAi, 0)}>\n Rewrite with AI\n </MenuItem>\n </>\n ) : null}\n {dev ? <MenuSeparator /> : null}\n {dev ? (\n <MenuItem\n icon={<IconBraces stroke={1.5} />}\n onClick={() => {\n void navigator.clipboard?.writeText(api).catch(() => {});\n toast?.success(`Copied ${api}`);\n }}\n >\n <span className=\"flex w-full items-center justify-between gap-3\">\n Copy API name\n <span className=\"truncate font-kit-mono text-kit-2xs text-kit-fg-3\">{api.length > 22 ? `…${api.slice(-20)}` : api}</span>\n </span>\n </MenuItem>\n ) : null}\n </MenuContent>\n </Menu>\n );\n}\n/** Reads the shared clipboard when the menu opens (it mounts with the popup), so a copy in another field is seen. */\nfunction PasteItem({ field, path, value, onChange }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void }) {\n const { toast, richText } = useKitServices();\n const textual = isTextual(field.type);\n // text into rich text needs the host's codec to store it in the field's shape\n const needsCodec = !!clip && field.type === \"richtext\" && clip.type !== \"richtext\" && !richText;\n const pasteOk = clip && !needsCodec && (clip.type === field.type || (textual && isTextual(clip.type as FieldSchema[\"type\"])));\n const pasteReason = !clip\n ? \"Copy a value from a field first.\"\n : needsCodec\n ? \"This rich text field takes a copied rich text value only.\"\n : pasteOk\n ? null\n : `Clipboard holds ${kindOf(clip.type)}. This field takes ${kindOf(field.type)}.`;\n return (\n <MenuItem\n icon={<IconClipboard stroke={1.5} />}\n disabled={!pasteOk}\n className={cn(pasteReason && \"h-auto py-1.5\")}\n onClick={() => {\n if (!clip) return;\n const prev = value;\n let next: unknown;\n if (field.type === \"richtext\" && richText && (clip.type !== \"richtext\" || clip.html !== undefined)) {\n // through the codec: the target field's own shape and Accept list, refused by name when it would drop something\n const out = richTextWrite(richText, field, path, clip.html ?? paragraphs(plainText(clip.value)), prev);\n if (\"refused\" in out) {\n toast?.(`Not pasted: ${out.refused}.`);\n return;\n }\n next = out.value;\n } else next = textual && clip.type === \"richtext\" && field.type !== \"richtext\" ? plainText(clip.value) : structuredCloneish(clip.value);\n onChange(next);\n toast?.(`Pasted into ${field.title}`, { action: { label: \"Undo\", onClick: () => onChange(prev) }, duration: 10_000 });\n }}\n >\n <span className=\"flex flex-col\">\n Paste value\n {pasteReason ? <span className=\"whitespace-normal text-kit-xs text-kit-fg-3\">{pasteReason}</span> : null}\n </span>\n </MenuItem>\n );\n}\nfunction structuredCloneish<T>(v: T): T {\n try {\n return structuredClone(v);\n } catch {\n return v;\n }\n}\n\n/* ── Rewrite with AI (preview before apply) ────────────────────────── */\nfunction AiRewrite({ field, path, value, onChange, onClose }: { field: FieldSchema; path: FieldPath; value: unknown; onChange: (v: unknown) => void; onClose: () => void }) {\n const form = useForm();\n const { toast, aiRewrite, richText } = useKitServices();\n const key = pathKey(path);\n const [preset, setPreset] = React.useState<AiPreset | null>(null);\n const [out, setOut] = React.useState<string | null>(null);\n const [failed, setFailed] = React.useState(false);\n const attempt = React.useRef(0);\n const latest = React.useRef(0);\n const source = plainText(value);\n const run = (p: AiPreset) => {\n if (!aiRewrite) return;\n setPreset(p);\n setOut(null);\n setFailed(false);\n const ticket = ++latest.current;\n Promise.resolve()\n .then(() => aiRewrite(source, p, attempt.current++))\n .then(\n (result) => {\n if (latest.current === ticket) setOut(result);\n },\n () => {\n if (latest.current === ticket) setFailed(true);\n },\n );\n };\n const apply = () => {\n if (!out) return;\n const prev = value;\n let next: unknown = out;\n if (field.type === \"richtext\") {\n const stored = richText ? richTextWrite(richText, field, path, paragraphs(out), prev) : { refused: `${field.title} has no rich text storage here` };\n if (\"refused\" in stored) {\n toast?.(`Not applied: ${stored.refused}.`);\n return;\n }\n next = stored.value;\n }\n onChange(next);\n form?.markAi(key, true);\n toast?.(\"Rewritten with AI\", {\n icon: <Sparkle size={14} />,\n action: {\n label: \"Undo\",\n onClick: () => {\n onChange(prev);\n form?.markAi(key, false);\n },\n },\n duration: 10_000,\n });\n onClose();\n };\n return (\n <div className=\"flex flex-col\">\n <div className=\"flex items-center gap-2 border-b border-kit-line px-3 py-2.5\">\n <Sparkle size={16} />\n <span className=\"text-kit-sm font-medium text-kit-fg\">Rewrite {field.title.toLowerCase()}</span>\n </div>\n <div className=\"flex flex-wrap gap-1 px-3 pt-2.5\">\n {AI_PRESETS.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n onClick={() => run(p.id)}\n className={cn(\"h-6 rounded-full border px-2 text-kit-xs transition-colors\", preset === p.id ? \"border-[var(--kit-emphasis-line)] bg-kit-surface text-kit-fg\" : \"border-kit-line text-kit-fg-2 hover:border-kit-line-strong hover:text-kit-fg\")}\n >\n {p.label}\n </button>\n ))}\n </div>\n <div className=\"px-3 py-3\">\n {!preset ? (\n <p className=\"text-kit-xs text-kit-fg-3\">Pick a direction. You'll see the suggestion before anything changes.</p>\n ) : failed ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n Couldn't rewrite {field.title.toLowerCase()}. Try again.\n </p>\n ) : out == null ? (\n <p className=\"text-kit-sm\">\n <Shimmer>Rewriting {field.title.toLowerCase()}…</Shimmer>\n </p>\n ) : (\n <div className=\"rounded-kit-lg bg-kit-subtle p-2.5 text-kit-sm leading-5 text-kit-fg\">\n <TypeOut text={out} />\n </div>\n )}\n </div>\n <div className=\"flex items-center justify-between gap-2 border-t border-kit-line px-3 py-2\">\n <Button size=\"xs\" variant=\"ghost\" onClick={onClose}>\n Discard\n </Button>\n <div className=\"flex gap-1\">\n {out || failed ? (\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconRefresh stroke={1.5} />} onClick={() => preset && run(preset)}>\n Try again\n </Button>\n ) : null}\n <Button size=\"xs\" variant=\"primary\" disabled={!out} onClick={apply}>\n Apply\n </Button>\n </div>\n </div>\n </div>\n );\n}\n\n/* V2 components/motion.tsx Shimmer + TypeOut, kept local to the AI popover (their only kit user). */\nfunction Shimmer({ children }: { children: React.ReactNode }) {\n return (\n <span className=\"bg-[linear-gradient(90deg,var(--kit-fg-3)_0%,var(--kit-fg)_45%,var(--kit-fg-3)_90%)] bg-[length:200%_100%] bg-clip-text text-transparent [animation:kit-shimmer-text_1.6s_linear_infinite] motion-reduce:[animation:none]\">\n {children}\n </span>\n );\n}\nfunction TypeOut({ text, speed = 14 }: { text: string; speed?: number }) {\n const [n, setN] = React.useState(0);\n React.useEffect(() => {\n setN(0);\n const id = setInterval(() => {\n setN((x) => {\n const next = Math.min(text.length, x + Math.max(1, Math.round(text.length / 120)));\n if (next >= text.length) clearInterval(id);\n return next;\n });\n }, speed);\n return () => clearInterval(id);\n }, [text, speed]);\n return (\n <span>\n {text.slice(0, n)}\n {n < text.length ? <span className=\"ml-0.5 inline-block h-[1em] w-[2px] translate-y-[2px] animate-pulse bg-kit-fg\" /> : null}\n </span>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"frame.js","names":[],"sources":["../../src/kit/engine/frame.tsx"],"sourcesContent":["/**\n * FrameView — what the panel shows for the current breadcrumb: the root fields, a drilled object / array item /\n * slot block (with \"2 of 4\" stepper, variant switcher and per-slot layout settings), the one button screen,\n * or a field's history as a stacked panel. Port of V2 engine/frame.tsx.\n *\n * FrameStage + useFrameNavigation — V2 schema-form's drill-in stage (direction-aware slide, scroll memory per frame,\n * focus on the entering frame, Esc / ⌥↑↓). Exported here so SchemaForm wires them without re-deriving the motion.\n *\n * FrameSlots — the frame draws other lanes' pieces (FieldList / FieldSection from grouping, ButtonScreen from link,\n * TableFrame from table). They arrive through context so this file never imports a module that does not exist yet;\n * a missing slot falls back to a plain field list (FieldList), the raw value (ButtonScreen, through\n * FallbackControl), a named note (TableFrame) or nothing (FieldSection). SchemaForm always hands ButtonScreen and TableFrame.\n */\nimport * as React from \"react\";\nimport { AnimatePresence, motion, useReducedMotion } from \"framer-motion\";\nimport { IconArrowBackUp, IconArrowDown, IconArrowUp, IconCopy, IconDots, IconTrash } from \"@tabler/icons-react\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Avatar } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Tooltip } from \"../ui/overlay\";\nimport { Segmented } from \"../ui/controls\";\nimport { fitsSegmented } from \"../ui/choice-switch\";\nimport { Select } from \"../ui/select\";\nimport { resolveFieldAccess, seesDevSurfaces, useForm, useKitEnv, useKitServices } from \"../context\";\nimport { cn } from \"../lib/cn\";\nimport { relTime } from \"../lib/utils\";\nimport { HISTORY_SEGMENT, type FieldGroup, type FieldPath, type FieldSchema, type Fieldset } from \"../schema/types\";\nimport type { Frame } from \"../lib/frames\";\nimport { frameKeyOf, isObj, newKey, pathKey, same } from \"../lib/path\";\nimport { isHidden, isTextual, plainText, previewOf, summarize } from \"../lib/schema\";\nimport { Thumb } from \"./bits\";\nimport { FallbackControl, KitField } from \"./kit-field\";\nimport { apiName } from \"./field-shell\";\n\n/* ── Slots (other lanes) ───────────────────────────────────────────── */\nexport interface FrameFieldListProps {\n fields: FieldSchema[];\n fieldsets?: Fieldset[];\n groups?: FieldGroup[];\n basePath: FieldPath;\n memoryKey: string;\n}\nexport interface FrameSlots {\n /** grouping lane: engine/field-list.tsx `FieldList` */\n FieldList?: React.ComponentType<FrameFieldListProps>;\n /** grouping lane: engine/grouping.tsx `FieldSection` (the slot-settings section of a slot block) */\n FieldSection?: React.ComponentType<{ title: string; description?: string; collapsible?: boolean; children: React.ReactNode }>;\n /** link lane: controls/link.tsx `ButtonScreen` + `normLink` (the \"button\" frame) */\n ButtonScreen?: React.ComponentType<{ value: unknown; onChange: (v: unknown) => void; title: string; readOnly?: boolean }>;\n normLink?: (v: unknown) => { label?: string };\n /** table lane: controls/table.tsx `TableFrame` (tableRow / tableColumn frames) */\n TableFrame?: React.ComponentType<{ frame: Frame }>;\n}\nconst SlotsCtx = React.createContext<FrameSlots>({});\nexport const FrameSlotsProvider = SlotsCtx.Provider;\nexport const useFrameSlots = () => React.useContext(SlotsCtx);\n\n/** Stand-in until the grouping lane's FieldList lands: the frame's visible fields in schema order. */\nfunction PlainFieldList({ fields, basePath }: FrameFieldListProps) {\n const form = useForm()!;\n const raw = basePath.length ? form.getAt(basePath) : form.value;\n const parent = isObj(raw) ? raw : {};\n const shown = fields.filter((f) => !isHidden(f, parent));\n return (\n <div className=\"flex flex-col gap-5\">\n {shown.map((f) => (\n <div key={f.name} className=\"min-w-0\">\n <KitField field={f} path={[...basePath, f.name]} parent={parent} />\n </div>\n ))}\n {shown.length === 0 ? <p className=\"py-6 text-center text-kit-sm text-kit-fg-3\">No fields here yet.</p> : null}\n </div>\n );\n}\n\n/** A button frame outside SchemaForm (no ButtonScreen slot) edits the button's raw value (FallbackControl), never an empty body. */\nfunction RawButtonScreen({ frame }: { frame: Frame }) {\n const form = useForm()!;\n const id = React.useId();\n const field = frame.field ?? { name: String(frame.path.at(-1) ?? \"button\"), title: frame.title, type: \"button\" as const };\n return <FallbackControl field={field} value={form.getAt(frame.path)} onChange={(n) => form.setAt(frame.path, n)} id={id} path={frame.path} />;\n}\n\n/** The button frame: header (the button's label) + the kit ButtonScreen, read-only when the lens can't edit the field. */\nfunction ButtonFrame({ frame, parentTitle }: { frame: Frame; parentTitle?: string }) {\n const form = useForm()!;\n const env = useKitEnv();\n const slots = useFrameSlots();\n const v = form.getAt(frame.path);\n const ButtonScreen = slots.ButtonScreen;\n const readOnly = frame.field ? resolveFieldAccess(frame.field, env).readOnly : !!env.readOnly;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={parentTitle ? `${frame.title} in ${parentTitle}` : frame.title} title={slots.normLink?.(v).label || frame.title} />\n {ButtonScreen ? <ButtonScreen value={v} onChange={(n) => form.setAt(frame.path, n)} title={frame.title} readOnly={readOnly} /> : <RawButtonScreen frame={frame} />}\n </div>\n );\n}\n\n/* ── FrameView ─────────────────────────────────────────────────────── */\nexport function FrameView({ frame, parentTitle }: { frame: Frame; parentTitle?: string }) {\n const form = useForm()!;\n const slots = useFrameSlots();\n const FieldList = slots.FieldList ?? PlainFieldList;\n if (frame.kind === \"history\") return <HistoryView field={frame.field!} path={frame.path.slice(0, -1)} />;\n if (frame.kind === \"button\") return <ButtonFrame frame={frame} parentTitle={parentTitle} />;\n // D50: a table row or column drills exactly like an array item: the same header (title, n of N, ↑ ↓ ⋯), its cells below\n if (frame.kind === \"tableRow\" || frame.kind === \"tableColumn\") {\n const it = frame.item!;\n const TableFrame = slots.TableFrame;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={`${it.itemSchema?.title} ${it.index + 1} of ${it.count} in ${frame.field?.title ?? \"the table\"}`} title={frame.title} />\n {TableFrame ? (\n <TableFrame frame={frame} />\n ) : (\n /* Only the kit table control opens a row or column frame; until it is ported the table is the host's control,\n which edits rows in place. A path restored into one says so instead of drawing an empty body. */\n <p role=\"note\" data-kit-legacy=\"table\" className=\"text-kit-sm text-kit-fg-3\">\n This table's rows and columns are edited in the table itself.\n </p>\n )}\n </div>\n );\n }\n if (frame.kind === \"root\") return <FieldList fields={frame.fields} fieldsets={frame.fieldsets} groups={frame.groups} basePath={[]} memoryKey=\"root\" />;\n const it = frame.item;\n const block = it?.block;\n const variants = block?.variants ?? [];\n const raw = form.getAt(frame.path);\n const cur = isObj(raw) ? raw : {};\n const FieldSection = slots.FieldSection;\n return (\n <div className=\"flex flex-col gap-5\">\n <FrameHeader frame={frame} context={frameContext(frame, parentTitle)} title={frame.title} />\n {block && variants.length > 1 ? (\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-kit-sm font-medium text-kit-fg-2\">Layout</span>\n {fitsSegmented(variants.map((v) => v.name)) ? (\n <Segmented\n aria-label=\"Layout\"\n value={String(cur._variant ?? variants[0].id)}\n onChange={(v) => form.setAt([...frame.path, \"_variant\"], v)}\n items={variants.map((v) => ({ value: v.id, label: v.name }))}\n className=\"w-full [&>button]:flex-1\"\n />\n ) : (\n <Select\n aria-label=\"Variant\"\n value={String(cur._variant ?? variants[0].id)}\n onValueChange={(v) => form.setAt([...frame.path, \"_variant\"], v)}\n options={variants.map((v) => ({ value: v.id, label: v.name, description: v.description }))}\n />\n )}\n </div>\n ) : null}\n <FieldList fields={frame.fields} fieldsets={frame.fieldsets} groups={frame.groups} basePath={frame.path} memoryKey={`f:${frame.kind}:${it?.block?.name ?? it?.itemSchema?.name ?? frame.field?.name ?? \"\"}`} />\n {it?.slotField?.slotSettings?.length && FieldSection ? (\n <FieldSection title={`Layout in ${it.slotField.title.toLowerCase()}`} description=\"How this block sits in its parent. The block's own content is above.\" collapsible={false}>\n <FieldList fields={it.slotField.slotSettings} basePath={[...frame.path, \"_settings\"]} memoryKey={`slotset:${it.slotField.name}`} />\n </FieldSection>\n ) : null}\n </div>\n );\n}\n\n/**\n * The context line under a drilled frame's title: \"Tier 1 of 3 in Tiers\" for an item (the item noun is the item\n * schema's title, which the adapter reads back from prod `ui.itemLabel`), \"Address in Author\" for an object.\n */\nexport function frameContext(frame: Frame, parentTitle?: string): string {\n const it = frame.item;\n if (it) {\n const noun = (frame.kind === \"block\" ? it.block?.title : it.itemSchema?.title) ?? \"Item\";\n const owner = (frame.kind === \"block\" ? it.slotField?.title : frame.field?.title) ?? \"the list\";\n return `${noun} ${it.index + 1} of ${it.count} in ${owner}`;\n }\n return parentTitle ? `${frame.field?.title ?? \"Group\"} in ${parentTitle}` : \"Group\";\n}\n\n/**\n * CPO D43 — the drilled frame's header answers \"what am I editing, and where does it live?\":\n * [media?] Starter [↑] [↓] [⋯]\n * Tier 1 of 3 in Tiers\n * The big title lives HERE only; the breadcrumb above is the path (its current crumb is small, D38). Prev / next are\n * labelled icon buttons whose tooltips name the sibling (\"Previous tier: Starter\"). No eyebrow, no duplicate counter.\n * Title 14/24 semibold (owner call). The native title= on the truncating h2 is V2 parity (kit-engine deviation from\n * the dashboard's no-title rule, see run ledger #32).\n */\nexport function FrameHeader({ frame, context, title }: { frame: Frame; context: string; title: string }) {\n const form = useForm()!;\n const { toast } = useKitServices();\n const it = frame.item;\n const media = it ? previewOf(it.block ?? it.itemSchema, form.getAt(frame.path), it.index).media : undefined;\n const step = (d: -1 | 1) => {\n if (!it) return;\n const n = it.index + d;\n if (n < 0 || n >= it.count) return;\n form.navigate([...it.arrayPath, n]);\n };\n const listRaw = it ? form.getAt(it.arrayPath) : undefined;\n const list = Array.isArray(listRaw) ? listRaw : [];\n const noun = (it?.block?.title ?? it?.itemSchema?.title ?? \"item\").toLowerCase();\n const sibling = (i: number) =>\n it && i >= 0 && i < it.count ? (it.titleAt ? it.titleAt(i) : previewOf(it.block ?? it.itemSchema, list[i], i, it.block?.title ?? it.itemSchema?.title).title) : \"\";\n const prev = it ? sibling(it.index - 1) : \"\";\n const next = it ? sibling(it.index + 1) : \"\";\n /* Duplicate / Remove move to another frame: the menu must not hand focus back to its trigger in the exiting frame\n (it unmounts, focus would drop to <body>); the stage focuses the entering frame instead */\n const moved = React.useRef(false);\n return (\n <div className=\"flex items-start gap-2.5 outline-none\" data-frame-header tabIndex={-1}>\n {media ? <Thumb media={media} size={36} /> : null}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"truncate text-kit-base font-semibold leading-6 text-kit-fg\" title={title}>\n {title}\n </h2>\n <p className=\"truncate text-kit-xs leading-4 text-kit-fg-3\">{context}</p>\n </div>\n {it ? (\n <div className=\"-mr-1 flex shrink-0 items-center gap-0.5 pt-0.5\">\n <IconButton\n label={prev ? `Previous ${noun}: ${prev}` : `No previous ${noun}`}\n tooltip={prev ? `Previous ${noun}: ${prev}` : `First ${noun}`}\n size=\"sm\"\n disabled={it.index === 0}\n onClick={() => step(-1)}\n >\n <IconArrowUp stroke={1.5} />\n </IconButton>\n <IconButton\n label={next ? `Next ${noun}: ${next}` : `No next ${noun}`}\n tooltip={next ? `Next ${noun}: ${next}` : `Last ${noun}`}\n size=\"sm\"\n disabled={it.index >= it.count - 1}\n onClick={() => step(1)}\n >\n <IconArrowDown stroke={1.5} />\n </IconButton>\n <Menu>\n <Tooltip content={`${title} actions`}>\n <MenuTrigger\n render={\n <IconButton label={`${title} actions`} tooltip={false} size=\"sm\">\n <IconDots stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n <MenuContent align=\"end\" className=\"w-48\" finalFocus={() => !moved.current}>\n <MenuItem\n icon={<IconCopy stroke={1.5} />}\n onClick={() => {\n moved.current = true;\n const copy = isObj(list[it.index]) ? { ...(structuredClone(list[it.index]) as object), _key: newKey() } : list[it.index];\n form.setAt(it.arrayPath, [...list.slice(0, it.index + 1), copy, ...list.slice(it.index + 1)]);\n form.navigate([...it.arrayPath, it.index + 1]);\n toast?.success(\"Duplicated\", { description: \"You're now editing the copy.\" });\n }}\n >\n Duplicate\n </MenuItem>\n <MenuSeparator />\n <MenuItem\n danger\n icon={<IconTrash stroke={1.5} />}\n onClick={() => {\n moved.current = true;\n const prevList = list;\n form.navigate(parentFramePath(it.arrayPath));\n form.setAt(it.arrayPath, list.filter((_, j) => j !== it.index));\n toast?.(`“${title}” removed`, { action: { label: \"Undo\", onClick: () => form.setAt(it.arrayPath, prevList) }, duration: 10_000 });\n }}\n >\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n </div>\n ) : null}\n </div>\n );\n}\n/** The frame that owns an array: drop the array field name (and the item index above it, if any). */\nconst parentFramePath = (arrayPath: FieldPath): FieldPath => arrayPath.slice(0, -1);\n\n/* ── History (stacked panel) ───────────────────────────────────────── */\n/**\n * V2 drew demo people (seed `currentUser` / `members`, a fixed \"26 hours ago\" / \"3 days ago\"). The kit has no seed:\n * session versions carry their own `by` and `at`; the opened and published baselines have no author or time here, so\n * their row says only what they are.\n */\nexport function HistoryView({ field, path }: { field: FieldSchema; path: FieldPath }) {\n const env = useKitEnv();\n const form = useForm()!;\n const { toast } = useKitServices();\n const key = pathKey(path);\n const now = form.getAt(path);\n const session = form.history(key);\n const baseline = form.baselineAt(path);\n const published = form.hasPublished ? form.publishedAt(path) : undefined;\n type V = { id: string; label: string; by?: string; at?: number; value: unknown; current?: boolean };\n const versions: V[] = [];\n versions.push({ id: \"now\", label: \"Current draft\", by: session[0]?.by ?? \"You\", at: Date.now(), value: now, current: true });\n session.slice(1).forEach((h, i) => versions.push({ id: `s${i}`, label: h.label ?? \"Edit\", by: h.by, at: h.at, value: h.value }));\n if (!same(baseline, now) && !session.some((h) => same(h.value, baseline))) versions.push({ id: \"open\", label: \"When you opened it\", value: baseline });\n if (published !== undefined) versions.push({ id: \"pub\", label: \"Published\", value: published });\n const show = (v: unknown) => {\n if (isTextual(field.type)) return plainText(v) || \"Empty\";\n if (Array.isArray(v)) return `${v.length} ${v.length === 1 ? \"item\" : \"items\"}`;\n if (isObj(v)) return summarize(field.fields ?? [], v) || plainText(v) || \"Set\";\n if (typeof v === \"boolean\") return v ? \"On\" : \"Off\";\n return v == null || v === \"\" ? \"Empty\" : String(v);\n };\n const meta = (v: V) => {\n if (v.current) return `Now · ${v.by}`;\n if (v.at === undefined) return v.label;\n return `${relTime(v.at)}${v.by ? ` · ${v.by}` : \"\"}${v.label ? ` · ${v.label}` : \"\"}`;\n };\n return (\n <div className=\"flex flex-col gap-4\">\n <div>\n {seesDevSurfaces(env) ? <div className=\"text-kit-2xs font-medium text-kit-fg-3\">{apiName(form.schema.name, path)}</div> : null}\n <h2 className=\"text-kit-base font-semibold text-kit-fg\">History of {field.title.toLowerCase()}</h2>\n <p className=\"mt-1 text-kit-xs text-kit-fg-3\">Restoring lands in the draft and doesn't publish. Publish afterwards to go live.</p>\n </div>\n <ul className=\"overflow-hidden rounded-kit-lg border border-kit-line\">\n {versions.map((v, i) => (\n <li key={v.id} data-version={v.id} className=\"group/ver flex items-start gap-2.5 border-b border-kit-line-subtle px-3 py-2.5 last:border-b-0\">\n {v.by ? <Avatar name={v.by} size={22} /> : <span aria-hidden className=\"size-[22px] shrink-0 rounded-full bg-kit-muted\" />}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-1.5 text-kit-sm\">\n <span className=\"font-medium text-kit-fg\">{v.current ? \"Current draft\" : `Version ${versions.length - i}`}</span>\n {v.id === \"pub\" ? <span className=\"rounded-kit-md bg-kit-success-soft px-1 text-kit-2xs text-kit-success-fg\">Published</span> : null}\n </div>\n <div className=\"text-kit-xs text-kit-fg-3\">{meta(v)}</div>\n <div className={cn(\"mt-1 line-clamp-2 rounded-kit-md bg-kit-subtle px-2 py-1 text-kit-xs text-kit-fg-2\", field.type === \"color\" && \"flex items-center gap-1.5\")}>\n {field.type === \"color\" && typeof v.value === \"string\" ? <span className=\"size-3 rounded-kit-md\" style={{ background: v.value }} /> : null}\n {show(v.value)}\n </div>\n </div>\n {v.current ? null : (\n <Button\n size=\"xs\"\n variant=\"secondary\"\n className=\"opacity-0 transition-opacity focus-visible:opacity-100 group-hover/ver:opacity-100 [@media(pointer:coarse)]:opacity-100\"\n leftIcon={<IconArrowBackUp stroke={1.5} />}\n onClick={() => {\n const prev = now;\n form.setAt(path, v.value, { label: \"Restored\" });\n form.navigate(parentOfField(path));\n toast?.(\"Restored as a draft\", { description: field.title, action: { label: \"Undo\", onClick: () => form.setAt(path, prev) }, duration: 10_000 });\n }}\n >\n Restore\n </Button>\n )}\n </li>\n ))}\n </ul>\n </div>\n );\n}\n/** Navigate back from a field's history to the frame that shows the field. */\nexport function parentOfField(path: FieldPath): FieldPath {\n // walk up to the nearest drillable frame boundary: an array index or the root\n for (let i = path.length - 1; i >= 0; i--) if (typeof path[i] === \"number\") return path.slice(0, i + 1);\n return path.length > 1 ? path.slice(0, -1) : [];\n}\n\n/* ── Stage: direction-aware slide, scroll memory, focus, keys (V2 schema-form) ───────────────── */\n/** The title shown as `parentTitle` for the current frame (the root crumb's label for depth 1). */\nexport function parentTitleOf(frames: Frame[], rootLabel: string): string | undefined {\n if (frames.length < 2) return undefined;\n return frames.length === 2 ? rootLabel : frames[frames.length - 2].title;\n}\n\n/** Floating layers (Base UI popups carry these roles); keys and focus coming from one belong to that layer. */\nconst LAYER = \"[role=dialog],[role=menu],[role=listbox]\";\n\n/** Slide direction for a frame change: deeper → 1, shallower → −1, a sibling step → by index. */\nexport function frameDirection(prev: { depth: number; index: number; key: string }, frames: Frame[], key: string): 0 | 1 | -1 {\n if (prev.key === key) return 0;\n const cur = frames[frames.length - 1];\n if (frames.length > prev.depth) return 1;\n if (frames.length < prev.depth) return -1;\n return (cur.item?.index ?? 0) >= prev.index ? 1 : -1;\n}\n\n/**\n * The drill-in stack's behaviour. `root` wraps the form (keys bubble to it), `scroller` is the scrolling element (or\n * null when the host scrolls). Returns the current frame, its key, the slide direction and the form's onKeyDown.\n */\nexport function useFrameNavigation({\n frames,\n navigate,\n root,\n scroller,\n}: {\n frames: Frame[];\n navigate: (path: FieldPath) => void;\n root: React.RefObject<HTMLElement | null>;\n scroller: React.RefObject<HTMLElement | null>;\n}) {\n const current = frames[frames.length - 1];\n const frameKey = frameKeyOf(current.path);\n const prev = React.useRef({ depth: frames.length, index: current.item?.index ?? 0, key: frameKey });\n const dir = frameDirection(prev.current, frames, frameKey);\n const dirRef = React.useRef<number>(1);\n if (dir) dirRef.current = dir;\n\n const scrollMem = React.useRef(new Map<string, number>());\n React.useLayoutEffect(() => {\n const was = prev.current.key;\n if (was === frameKey) return;\n if (scroller.current) scrollMem.current.set(was, scroller.current.scrollTop);\n prev.current = { depth: frames.length, index: current.item?.index ?? 0, key: frameKey };\n const el = scroller.current;\n if (el) el.scrollTop = scrollMem.current.get(frameKey) ?? 0;\n const active = document.activeElement;\n /* a move started from a portalled menu (FrameHeader ⋯ → Duplicate / Remove) leaves focus in that layer, outside root */\n const layer = active && active !== document.body ? active.closest(LAYER) : null;\n const fromLayer = !!layer && !layer.contains(root.current);\n if (root.current && (active === document.body || root.current.contains(active) || fromLayer)) {\n // the exiting frame is still mounted during its exit animation — focus the ENTERING one\n const target = root.current.querySelector<HTMLElement>(`[data-frame-body=\"${CSS.escape(frameKey)}\"]`);\n target?.focus({ preventScroll: true });\n }\n });\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (e.defaultPrevented) return;\n const t = e.target as HTMLElement;\n // ignore keys from floating layers opened by this form; a form INSIDE a dialog still handles its own keys\n // (V2 also listed Radix's popper wrapper; Base UI popups carry these roles themselves)\n const layer = t.closest(LAYER);\n if (layer && root.current && !layer.contains(root.current)) return;\n if (e.key === \"Escape\" && frames.length > 1 && !t.isContentEditable) {\n e.preventDefault();\n e.stopPropagation();\n navigate(frames[frames.length - 2].path);\n return;\n }\n const it = current.item;\n if (it && (e.key === \"ArrowUp\" || e.key === \"ArrowDown\")) {\n const typing = t.matches(\"input,textarea,select\") || t.isContentEditable;\n if (e.altKey || (!typing && t.matches(\"[data-frame-body],[data-frame-header]\"))) {\n const n = it.index + (e.key === \"ArrowUp\" ? -1 : 1);\n if (n >= 0 && n < it.count) {\n e.preventDefault();\n navigate([...it.arrayPath, n]);\n }\n }\n }\n };\n\n return { current, frameKey, dir: dirRef.current, onKeyDown };\n}\n\nconst EASE: [number, number, number, number] = [0.22, 1, 0.36, 1];\n\n/**\n * The frame body with V2's slide: 24px along the travel direction + fade, 220ms, ease [0.22, 1, 0.36, 1]; reduced\n * motion keeps only the fade. `before` renders inside the root frame above its fields (the synced-from note).\n */\nexport function FrameStage({\n frames,\n frameKey,\n dir,\n rootLabel,\n variant,\n before,\n}: {\n frames: Frame[];\n frameKey: string;\n dir: number;\n rootLabel: string;\n variant: \"panel\" | \"document\";\n before?: React.ReactNode;\n}) {\n const reduce = useReducedMotion();\n const current = frames[frames.length - 1];\n return (\n <div className=\"relative\" style={{ overflowX: \"clip\" }}>\n <AnimatePresence mode=\"popLayout\" initial={false} custom={dir}>\n <motion.div\n key={frameKey}\n custom={dir}\n variants={{\n enter: (d: number) => ({ x: reduce ? 0 : d * 24, opacity: 0 }),\n center: { x: 0, opacity: 1 },\n exit: (d: number) => ({ x: reduce ? 0 : d * -24, opacity: 0 }),\n }}\n initial=\"enter\"\n animate=\"center\"\n exit=\"exit\"\n transition={{ duration: 0.22, ease: EASE }}\n data-frame-body={frameKey}\n tabIndex={-1}\n className={cn(\"outline-none focus-visible:shadow-none\", variant === \"document\" ? \"py-1\" : \"px-4 py-4\")}\n >\n {current.kind === \"root\" ? before : null}\n <FrameView frame={current} parentTitle={parentTitleOf(frames, rootLabel)} />\n </motion.div>\n </AnimatePresence>\n </div>\n );\n}\n\nexport { HISTORY_SEGMENT };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDA,IAAM,WAAW,MAAM,cAA0B,EAAE,CAAC;AACpD,IAAa,qBAAqB,SAAS;AAC3C,IAAa,sBAAsB,MAAM,WAAW,SAAS;;AAG7D,SAAS,eAAe,EAAE,QAAQ,YAAiC;CACjE,MAAM,OAAO,SAAS;CACtB,MAAM,MAAM,SAAS,SAAS,KAAK,MAAM,SAAS,GAAG,KAAK;CAC1D,MAAM,SAAS,MAAM,IAAI,GAAG,MAAM,EAAE;CACpC,MAAM,QAAQ,OAAO,QAAQ,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC;AACxD,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACG,MAAM,KAAK,MACV,oBAAC,OAAD;GAAkB,WAAU;aAC1B,oBAAC,UAAD;IAAU,OAAO;IAAG,MAAM,CAAC,GAAG,UAAU,EAAE,KAAK;IAAU;IAAU,CAAA;GAC/D,EAFI,EAAE,KAEN,CACN,EACD,MAAM,WAAW,IAAI,oBAAC,KAAD;GAAG,WAAU;aAA6C;GAAuB,CAAA,GAAG,KACtG;;;;AAKV,SAAS,gBAAgB,EAAE,SAA2B;CACpD,MAAM,OAAO,SAAS;CACtB,MAAM,KAAK,MAAM,OAAO;AAExB,QAAO,oBAAC,iBAAD;EAAwB,OADjB,MAAM,SAAS;GAAE,MAAM,OAAO,MAAM,KAAK,GAAG,GAAG,IAAI,SAAS;GAAE,OAAO,MAAM;GAAO,MAAM;GAAmB;EACnF,OAAO,KAAK,MAAM,MAAM,KAAK;EAAE,WAAW,MAAM,KAAK,MAAM,MAAM,MAAM,EAAE;EAAM;EAAI,MAAM,MAAM;EAAQ,CAAA;;;AAI/I,SAAS,YAAY,EAAE,OAAO,eAAuD;CACnF,MAAM,OAAO,SAAS;CACtB,MAAM,MAAM,WAAW;CACvB,MAAM,QAAQ,eAAe;CAC7B,MAAM,IAAI,KAAK,MAAM,MAAM,KAAK;CAChC,MAAM,eAAe,MAAM;CAC3B,MAAM,WAAW,MAAM,QAAQ,mBAAmB,MAAM,OAAO,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI;AACrF,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,oBAAC,aAAD;GAAoB;GAAO,SAAS,cAAc,GAAG,MAAM,MAAM,MAAM,gBAAgB,MAAM;GAAO,OAAO,MAAM,WAAW,EAAE,CAAC,SAAS,MAAM;GAAS,CAAA,EACtJ,eAAe,oBAAC,cAAD;GAAc,OAAO;GAAG,WAAW,MAAM,KAAK,MAAM,MAAM,MAAM,EAAE;GAAE,OAAO,MAAM;GAAiB;GAAY,CAAA,GAAG,oBAAC,iBAAD,EAAwB,OAAS,CAAA,CAC9J;;;AAKV,SAAgB,UAAU,EAAE,OAAO,eAAuD;CACxF,MAAM,OAAO,SAAS;CACtB,MAAM,QAAQ,eAAe;CAC7B,MAAM,YAAY,MAAM,aAAa;AACrC,KAAI,MAAM,SAAS,UAAW,QAAO,oBAAC,aAAD;EAAa,OAAO,MAAM;EAAQ,MAAM,MAAM,KAAK,MAAM,GAAG,GAAG;EAAI,CAAA;AACxG,KAAI,MAAM,SAAS,SAAU,QAAO,oBAAC,aAAD;EAAoB;EAAoB;EAAe,CAAA;AAE3F,KAAI,MAAM,SAAS,cAAc,MAAM,SAAS,eAAe;EAC7D,MAAM,KAAK,MAAM;EACjB,MAAM,aAAa,MAAM;AACzB,SACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,aAAD;IAAoB;IAAO,SAAS,GAAG,GAAG,YAAY,MAAM,GAAG,GAAG,QAAQ,EAAE,MAAM,GAAG,MAAM,MAAM,MAAM,OAAO,SAAS;IAAe,OAAO,MAAM;IAAS,CAAA,EAC3J,aACC,oBAAC,YAAD,EAAmB,OAAS,CAAA,GAI5B,oBAAC,KAAD;IAAG,MAAK;IAAO,mBAAgB;IAAQ,WAAU;cAA4B;IAEzE,CAAA,CAEF;;;AAGV,KAAI,MAAM,SAAS,OAAQ,QAAO,oBAAC,WAAD;EAAW,QAAQ,MAAM;EAAQ,WAAW,MAAM;EAAW,QAAQ,MAAM;EAAQ,UAAU,EAAE;EAAE,WAAU;EAAS,CAAA;CACtJ,MAAM,KAAK,MAAM;CACjB,MAAM,QAAQ,IAAI;CAClB,MAAM,WAAW,OAAO,YAAY,EAAE;CACtC,MAAM,MAAM,KAAK,MAAM,MAAM,KAAK;CAClC,MAAM,MAAM,MAAM,IAAI,GAAG,MAAM,EAAE;CACjC,MAAM,eAAe,MAAM;AAC3B,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,aAAD;IAAoB;IAAO,SAAS,aAAa,OAAO,YAAY;IAAE,OAAO,MAAM;IAAS,CAAA;GAC3F,SAAS,SAAS,SAAS,IAC1B,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,QAAD;KAAM,WAAU;eAAwC;KAAa,CAAA,EACpE,cAAc,SAAS,KAAK,MAAM,EAAE,KAAK,CAAC,GACzC,oBAAC,WAAD;KACE,cAAW;KACX,OAAO,OAAO,IAAI,YAAY,SAAS,GAAG,GAAG;KAC7C,WAAW,MAAM,KAAK,MAAM,CAAC,GAAG,MAAM,MAAM,WAAW,EAAE,EAAE;KAC3D,OAAO,SAAS,KAAK,OAAO;MAAE,OAAO,EAAE;MAAI,OAAO,EAAE;MAAM,EAAE;KAC5D,WAAU;KACV,CAAA,GAEF,oBAAC,QAAD;KACE,cAAW;KACX,OAAO,OAAO,IAAI,YAAY,SAAS,GAAG,GAAG;KAC7C,gBAAgB,MAAM,KAAK,MAAM,CAAC,GAAG,MAAM,MAAM,WAAW,EAAE,EAAE;KAChE,SAAS,SAAS,KAAK,OAAO;MAAE,OAAO,EAAE;MAAI,OAAO,EAAE;MAAM,aAAa,EAAE;MAAa,EAAE;KAC1F,CAAA,CAEA;QACJ;GACJ,oBAAC,WAAD;IAAW,QAAQ,MAAM;IAAQ,WAAW,MAAM;IAAW,QAAQ,MAAM;IAAQ,UAAU,MAAM;IAAM,WAAW,KAAK,MAAM,KAAK,GAAG,IAAI,OAAO,QAAQ,IAAI,YAAY,QAAQ,MAAM,OAAO,QAAQ;IAAQ,CAAA;GAC9M,IAAI,WAAW,cAAc,UAAU,eACtC,oBAAC,cAAD;IAAc,OAAO,aAAa,GAAG,UAAU,MAAM,aAAa;IAAI,aAAY;IAAuE,aAAa;cACpK,oBAAC,WAAD;KAAW,QAAQ,GAAG,UAAU;KAAc,UAAU,CAAC,GAAG,MAAM,MAAM,YAAY;KAAE,WAAW,WAAW,GAAG,UAAU;KAAU,CAAA;IACtH,CAAA,GACb;GACA;;;;;;;AAQV,SAAgB,aAAa,OAAc,aAA8B;CACvE,MAAM,KAAK,MAAM;AACjB,KAAI,IAAI;EACN,MAAM,QAAQ,MAAM,SAAS,UAAU,GAAG,OAAO,QAAQ,GAAG,YAAY,UAAU;EAClF,MAAM,SAAS,MAAM,SAAS,UAAU,GAAG,WAAW,QAAQ,MAAM,OAAO,UAAU;AACrF,SAAO,GAAG,KAAK,GAAG,GAAG,QAAQ,EAAE,MAAM,GAAG,MAAM,MAAM;;AAEtD,QAAO,cAAc,GAAG,MAAM,OAAO,SAAS,QAAQ,MAAM,gBAAgB;;;;;;;;;;;AAY9E,SAAgB,YAAY,EAAE,OAAO,SAAS,SAA2D;CACvG,MAAM,OAAO,SAAS;CACtB,MAAM,EAAE,UAAU,gBAAgB;CAClC,MAAM,KAAK,MAAM;CACjB,MAAM,QAAQ,KAAK,UAAU,GAAG,SAAS,GAAG,YAAY,KAAK,MAAM,MAAM,KAAK,EAAE,GAAG,MAAM,CAAC,QAAQ,KAAA;CAClG,MAAM,QAAQ,MAAc;AAC1B,MAAI,CAAC,GAAI;EACT,MAAM,IAAI,GAAG,QAAQ;AACrB,MAAI,IAAI,KAAK,KAAK,GAAG,MAAO;AAC5B,OAAK,SAAS,CAAC,GAAG,GAAG,WAAW,EAAE,CAAC;;CAErC,MAAM,UAAU,KAAK,KAAK,MAAM,GAAG,UAAU,GAAG,KAAA;CAChD,MAAM,OAAO,MAAM,QAAQ,QAAQ,GAAG,UAAU,EAAE;CAClD,MAAM,QAAQ,IAAI,OAAO,SAAS,IAAI,YAAY,SAAS,QAAQ,aAAa;CAChF,MAAM,WAAW,MACf,MAAM,KAAK,KAAK,IAAI,GAAG,QAAS,GAAG,UAAU,GAAG,QAAQ,EAAE,GAAG,UAAU,GAAG,SAAS,GAAG,YAAY,KAAK,IAAI,GAAG,GAAG,OAAO,SAAS,GAAG,YAAY,MAAM,CAAC,QAAS;CAClK,MAAM,OAAO,KAAK,QAAQ,GAAG,QAAQ,EAAE,GAAG;CAC1C,MAAM,OAAO,KAAK,QAAQ,GAAG,QAAQ,EAAE,GAAG;CAG1C,MAAM,QAAQ,MAAM,OAAO,MAAM;AACjC,QACE,qBAAC,OAAD;EAAK,WAAU;EAAwC,qBAAA;EAAkB,UAAU;YAAnF;GACG,QAAQ,oBAAC,OAAD;IAAc;IAAO,MAAM;IAAM,CAAA,GAAG;GAC7C,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,MAAD;KAAI,WAAU;KAAoE;eAC/E;KACE,CAAA,EACL,oBAAC,KAAD;KAAG,WAAU;eAAgD;KAAY,CAAA,CACrE;;GACL,KACC,qBAAC,OAAD;IAAK,WAAU;cAAf;KACE,oBAAC,YAAD;MACE,OAAO,OAAO,YAAY,KAAK,IAAI,SAAS,eAAe;MAC3D,SAAS,OAAO,YAAY,KAAK,IAAI,SAAS,SAAS;MACvD,MAAK;MACL,UAAU,GAAG,UAAU;MACvB,eAAe,KAAK,GAAG;gBAEvB,oBAAC,aAAD,EAAa,QAAQ,KAAO,CAAA;MACjB,CAAA;KACb,oBAAC,YAAD;MACE,OAAO,OAAO,QAAQ,KAAK,IAAI,SAAS,WAAW;MACnD,SAAS,OAAO,QAAQ,KAAK,IAAI,SAAS,QAAQ;MAClD,MAAK;MACL,UAAU,GAAG,SAAS,GAAG,QAAQ;MACjC,eAAe,KAAK,EAAE;gBAEtB,oBAAC,eAAD,EAAe,QAAQ,KAAO,CAAA;MACnB,CAAA;KACb,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,SAAD;MAAS,SAAS,GAAG,MAAM;gBACzB,oBAAC,aAAD,EACE,QACE,oBAAC,YAAD;OAAY,OAAO,GAAG,MAAM;OAAW,SAAS;OAAO,MAAK;iBAC1D,oBAAC,UAAD,EAAU,QAAQ,KAAO,CAAA;OACd,CAAA,EAEf,CAAA;MACM,CAAA,EACV,qBAAC,aAAD;MAAa,OAAM;MAAM,WAAU;MAAO,kBAAkB,CAAC,MAAM;gBAAnE;OACE,oBAAC,UAAD;QACE,MAAM,oBAAC,UAAD,EAAU,QAAQ,KAAO,CAAA;QAC/B,eAAe;AACb,eAAM,UAAU;SAChB,MAAM,OAAO,MAAM,KAAK,GAAG,OAAO,GAAG;UAAE,GAAI,gBAAgB,KAAK,GAAG,OAAO;UAAa,MAAM,QAAQ;UAAE,GAAG,KAAK,GAAG;AAClH,cAAK,MAAM,GAAG,WAAW;UAAC,GAAG,KAAK,MAAM,GAAG,GAAG,QAAQ,EAAE;UAAE;UAAM,GAAG,KAAK,MAAM,GAAG,QAAQ,EAAE;UAAC,CAAC;AAC7F,cAAK,SAAS,CAAC,GAAG,GAAG,WAAW,GAAG,QAAQ,EAAE,CAAC;AAC9C,gBAAO,QAAQ,cAAc,EAAE,aAAa,gCAAgC,CAAC;;kBAEhF;QAEU,CAAA;OACX,oBAAC,eAAD,EAAiB,CAAA;OACjB,oBAAC,UAAD;QACE,QAAA;QACA,MAAM,oBAAC,WAAD,EAAW,QAAQ,KAAO,CAAA;QAChC,eAAe;AACb,eAAM,UAAU;SAChB,MAAM,WAAW;AACjB,cAAK,SAAS,gBAAgB,GAAG,UAAU,CAAC;AAC5C,cAAK,MAAM,GAAG,WAAW,KAAK,QAAQ,GAAG,MAAM,MAAM,GAAG,MAAM,CAAC;AAC/D,iBAAQ,IAAI,MAAM,YAAY;UAAE,QAAQ;WAAE,OAAO;WAAQ,eAAe,KAAK,MAAM,GAAG,WAAW,SAAS;WAAE;UAAE,UAAU;UAAQ,CAAC;;kBAEpI;QAEU,CAAA;OACC;QACT,EAAA,CAAA;KACH;QACJ;GACA;;;;AAIV,IAAM,mBAAmB,cAAoC,UAAU,MAAM,GAAG,GAAG;;;;;;AAQnF,SAAgB,YAAY,EAAE,OAAO,QAAiD;CACpF,MAAM,MAAM,WAAW;CACvB,MAAM,OAAO,SAAS;CACtB,MAAM,EAAE,UAAU,gBAAgB;CAClC,MAAM,MAAM,QAAQ,KAAK;CACzB,MAAM,MAAM,KAAK,MAAM,KAAK;CAC5B,MAAM,UAAU,KAAK,QAAQ,IAAI;CACjC,MAAM,WAAW,KAAK,WAAW,KAAK;CACtC,MAAM,YAAY,KAAK,eAAe,KAAK,YAAY,KAAK,GAAG,KAAA;CAE/D,MAAM,WAAgB,EAAE;AACxB,UAAS,KAAK;EAAE,IAAI;EAAO,OAAO;EAAiB,IAAI,QAAQ,IAAI,MAAM;EAAO,IAAI,KAAK,KAAK;EAAE,OAAO;EAAK,SAAS;EAAM,CAAC;AAC5H,SAAQ,MAAM,EAAE,CAAC,SAAS,GAAG,MAAM,SAAS,KAAK;EAAE,IAAI,IAAI;EAAK,OAAO,EAAE,SAAS;EAAQ,IAAI,EAAE;EAAI,IAAI,EAAE;EAAI,OAAO,EAAE;EAAO,CAAC,CAAC;AAChI,KAAI,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,MAAM,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,CAAE,UAAS,KAAK;EAAE,IAAI;EAAQ,OAAO;EAAsB,OAAO;EAAU,CAAC;AACtJ,KAAI,cAAc,KAAA,EAAW,UAAS,KAAK;EAAE,IAAI;EAAO,OAAO;EAAa,OAAO;EAAW,CAAC;CAC/F,MAAM,QAAQ,MAAe;AAC3B,MAAI,UAAU,MAAM,KAAK,CAAE,QAAO,UAAU,EAAE,IAAI;AAClD,MAAI,MAAM,QAAQ,EAAE,CAAE,QAAO,GAAG,EAAE,OAAO,GAAG,EAAE,WAAW,IAAI,SAAS;AACtE,MAAI,MAAM,EAAE,CAAE,QAAO,UAAU,MAAM,UAAU,EAAE,EAAE,EAAE,IAAI,UAAU,EAAE,IAAI;AACzE,MAAI,OAAO,MAAM,UAAW,QAAO,IAAI,OAAO;AAC9C,SAAO,KAAK,QAAQ,MAAM,KAAK,UAAU,OAAO,EAAE;;CAEpD,MAAM,QAAQ,MAAS;AACrB,MAAI,EAAE,QAAS,QAAO,SAAS,EAAE;AACjC,MAAI,EAAE,OAAO,KAAA,EAAW,QAAO,EAAE;AACjC,SAAO,GAAG,QAAQ,EAAE,GAAG,GAAG,EAAE,KAAK,MAAM,EAAE,OAAO,KAAK,EAAE,QAAQ,MAAM,EAAE,UAAU;;AAEnF,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf,CACE,qBAAC,OAAD,EAAA,UAAA;GACG,gBAAgB,IAAI,GAAG,oBAAC,OAAD;IAAK,WAAU;cAA0C,QAAQ,KAAK,OAAO,MAAM,KAAK;IAAO,CAAA,GAAG;GAC1H,qBAAC,MAAD;IAAI,WAAU;cAAd,CAAwD,eAAY,MAAM,MAAM,aAAa,CAAM;;GACnG,oBAAC,KAAD;IAAG,WAAU;cAAiC;IAAoF,CAAA;GAC9H,EAAA,CAAA,EACN,oBAAC,MAAD;GAAI,WAAU;aACX,SAAS,KAAK,GAAG,MAChB,qBAAC,MAAD;IAAe,gBAAc,EAAE;IAAI,WAAU;cAA7C;KACG,EAAE,KAAK,oBAAC,QAAD;MAAQ,MAAM,EAAE;MAAI,MAAM;MAAM,CAAA,GAAG,oBAAC,QAAD;MAAM,eAAA;MAAY,WAAU;MAAmD,CAAA;KAC1H,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,qBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,oBAAC,QAAD;SAAM,WAAU;mBAA2B,EAAE,UAAU,kBAAkB,WAAW,SAAS,SAAS;SAAW,CAAA,EAChH,EAAE,OAAO,QAAQ,oBAAC,QAAD;SAAM,WAAU;mBAA2E;SAAgB,CAAA,GAAG,KAC5H;;OACN,oBAAC,OAAD;QAAK,WAAU;kBAA6B,KAAK,EAAE;QAAO,CAAA;OAC1D,qBAAC,OAAD;QAAK,WAAW,GAAG,sFAAsF,MAAM,SAAS,WAAW,4BAA4B;kBAA/J,CACG,MAAM,SAAS,WAAW,OAAO,EAAE,UAAU,WAAW,oBAAC,QAAD;SAAM,WAAU;SAAwB,OAAO,EAAE,YAAY,EAAE,OAAO;SAAI,CAAA,GAAG,MACrI,KAAK,EAAE,MAAM,CACV;;OACF;;KACL,EAAE,UAAU,OACX,oBAAC,QAAD;MACE,MAAK;MACL,SAAQ;MACR,WAAU;MACV,UAAU,oBAAC,iBAAD,EAAiB,QAAQ,KAAO,CAAA;MAC1C,eAAe;OACb,MAAM,OAAO;AACb,YAAK,MAAM,MAAM,EAAE,OAAO,EAAE,OAAO,YAAY,CAAC;AAChD,YAAK,SAAS,cAAc,KAAK,CAAC;AAClC,eAAQ,uBAAuB;QAAE,aAAa,MAAM;QAAO,QAAQ;SAAE,OAAO;SAAQ,eAAe,KAAK,MAAM,MAAM,KAAK;SAAE;QAAE,UAAU;QAAQ,CAAC;;gBAEnJ;MAEQ,CAAA;KAER;MA7BI,EAAE,GA6BN,CACL;GACC,CAAA,CACD;;;;AAIV,SAAgB,cAAc,MAA4B;AAExD,MAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,IAAK,KAAI,OAAO,KAAK,OAAO,SAAU,QAAO,KAAK,MAAM,GAAG,IAAI,EAAE;AACvG,QAAO,KAAK,SAAS,IAAI,KAAK,MAAM,GAAG,GAAG,GAAG,EAAE;;;AAKjD,SAAgB,cAAc,QAAiB,WAAuC;AACpF,KAAI,OAAO,SAAS,EAAG,QAAO,KAAA;AAC9B,QAAO,OAAO,WAAW,IAAI,YAAY,OAAO,OAAO,SAAS,GAAG;;;AAIrE,IAAM,QAAQ;;AAGd,SAAgB,eAAe,MAAqD,QAAiB,KAAyB;AAC5H,KAAI,KAAK,QAAQ,IAAK,QAAO;CAC7B,MAAM,MAAM,OAAO,OAAO,SAAS;AACnC,KAAI,OAAO,SAAS,KAAK,MAAO,QAAO;AACvC,KAAI,OAAO,SAAS,KAAK,MAAO,QAAO;AACvC,SAAQ,IAAI,MAAM,SAAS,MAAM,KAAK,QAAQ,IAAI;;;;;;AAOpD,SAAgB,mBAAmB,EACjC,QACA,UACA,MACA,YAMC;CACD,MAAM,UAAU,OAAO,OAAO,SAAS;CACvC,MAAM,WAAW,WAAW,QAAQ,KAAK;CACzC,MAAM,OAAO,MAAM,OAAO;EAAE,OAAO,OAAO;EAAQ,OAAO,QAAQ,MAAM,SAAS;EAAG,KAAK;EAAU,CAAC;CACnG,MAAM,MAAM,eAAe,KAAK,SAAS,QAAQ,SAAS;CAC1D,MAAM,SAAS,MAAM,OAAe,EAAE;AACtC,KAAI,IAAK,QAAO,UAAU;CAE1B,MAAM,YAAY,MAAM,uBAAO,IAAI,KAAqB,CAAC;AACzD,OAAM,sBAAsB;EAC1B,MAAM,MAAM,KAAK,QAAQ;AACzB,MAAI,QAAQ,SAAU;AACtB,MAAI,SAAS,QAAS,WAAU,QAAQ,IAAI,KAAK,SAAS,QAAQ,UAAU;AAC5E,OAAK,UAAU;GAAE,OAAO,OAAO;GAAQ,OAAO,QAAQ,MAAM,SAAS;GAAG,KAAK;GAAU;EACvF,MAAM,KAAK,SAAS;AACpB,MAAI,GAAI,IAAG,YAAY,UAAU,QAAQ,IAAI,SAAS,IAAI;EAC1D,MAAM,SAAS,SAAS;EAExB,MAAM,QAAQ,UAAU,WAAW,SAAS,OAAO,OAAO,QAAQ,MAAM,GAAG;EAC3E,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,MAAM,SAAS,KAAK,QAAQ;AAC1D,MAAI,KAAK,YAAY,WAAW,SAAS,QAAQ,KAAK,QAAQ,SAAS,OAAO,IAAI,WAEjE,MAAK,QAAQ,cAA2B,qBAAqB,IAAI,OAAO,SAAS,CAAC,IAAI,EAC7F,MAAM,EAAE,eAAe,MAAM,CAAC;GAExC;CAEF,MAAM,aAAa,MAA2B;AAC5C,MAAI,EAAE,iBAAkB;EACxB,MAAM,IAAI,EAAE;EAGZ,MAAM,QAAQ,EAAE,QAAQ,MAAM;AAC9B,MAAI,SAAS,KAAK,WAAW,CAAC,MAAM,SAAS,KAAK,QAAQ,CAAE;AAC5D,MAAI,EAAE,QAAQ,YAAY,OAAO,SAAS,KAAK,CAAC,EAAE,mBAAmB;AACnE,KAAE,gBAAgB;AAClB,KAAE,iBAAiB;AACnB,YAAS,OAAO,OAAO,SAAS,GAAG,KAAK;AACxC;;EAEF,MAAM,KAAK,QAAQ;AACnB,MAAI,OAAO,EAAE,QAAQ,aAAa,EAAE,QAAQ,cAAc;GACxD,MAAM,SAAS,EAAE,QAAQ,wBAAwB,IAAI,EAAE;AACvD,OAAI,EAAE,UAAW,CAAC,UAAU,EAAE,QAAQ,wCAAwC,EAAG;IAC/E,MAAM,IAAI,GAAG,SAAS,EAAE,QAAQ,YAAY,KAAK;AACjD,QAAI,KAAK,KAAK,IAAI,GAAG,OAAO;AAC1B,OAAE,gBAAgB;AAClB,cAAS,CAAC,GAAG,GAAG,WAAW,EAAE,CAAC;;;;;AAMtC,QAAO;EAAE;EAAS;EAAU,KAAK,OAAO;EAAS;EAAW;;AAG9D,IAAM,OAAyC;CAAC;CAAM;CAAG;CAAM;CAAE;;;;;AAMjE,SAAgB,WAAW,EACzB,QACA,UACA,KACA,WACA,SACA,UAQC;CACD,MAAM,SAAS,kBAAkB;CACjC,MAAM,UAAU,OAAO,OAAO,SAAS;AACvC,QACE,oBAAC,OAAD;EAAK,WAAU;EAAW,OAAO,EAAE,WAAW,QAAQ;YACpD,oBAAC,iBAAD;GAAiB,MAAK;GAAY,SAAS;GAAO,QAAQ;aACxD,qBAAC,OAAO,KAAR;IAEE,QAAQ;IACR,UAAU;KACR,QAAQ,OAAe;MAAE,GAAG,SAAS,IAAI,IAAI;MAAI,SAAS;MAAG;KAC7D,QAAQ;MAAE,GAAG;MAAG,SAAS;MAAG;KAC5B,OAAO,OAAe;MAAE,GAAG,SAAS,IAAI,IAAI;MAAK,SAAS;MAAG;KAC9D;IACD,SAAQ;IACR,SAAQ;IACR,MAAK;IACL,YAAY;KAAE,UAAU;KAAM,MAAM;KAAM;IAC1C,mBAAiB;IACjB,UAAU;IACV,WAAW,GAAG,0CAA0C,YAAY,aAAa,SAAS,YAAY;cAdxG,CAgBG,QAAQ,SAAS,SAAS,SAAS,MACpC,oBAAC,WAAD;KAAW,OAAO;KAAS,aAAa,cAAc,QAAQ,UAAU;KAAI,CAAA,CACjE;MAjBN,SAiBM;GACG,CAAA;EACd,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"group-summary.js","names":[],"sources":["../../src/kit/engine/group-summary.ts"],"sourcesContent":["/**\n * groupSummary (V2 HEAD 9829bf1 kit/engine/grouping.tsx): what a collapsed group holds, in one line. Lives on its own\n * until the grouping lane ports grouping.tsx, which then re-exports it from there.\n */\nimport { isHidden, isEmptyValue, plainText } from \"../lib/schema\";\nimport { isObj } from \"../lib/path\";\nimport { resolveScale } from \"../schema/scale\";\nimport type { FieldSchema } from \"../schema/types\";\n\n/** \"Top 56 · Bottom 88 · Sides M\". Short values (numbers, scales, 1–4 letter options, on-switches) get their field's\n * name in front so they mean something; text speaks for itself. Media, references and code are skipped. */\nexport function groupSummary(fields: FieldSchema[], value: unknown, max = 3): string {\n if (!isObj(value)) return \"\";\n const parts: string[] = [];\n for (const f of fields) {\n if (parts.length >= max) break;\n if (isHidden(f, value)) continue;\n const x = value[f.name];\n if (isEmptyValue(x)) continue;\n switch (f.type) {\n case \"image\": case \"file\": case \"video\": case \"reference\": case \"json\": case \"code\": case \"object\": case \"slot\": case \"geopoint\":\n continue;\n case \"boolean\":\n if (x === true) parts.push(f.title);\n continue;\n case \"number\": {\n const label = f.scale ? resolveScale(f.scale, x).label : `${x}${f.numeric?.unit ? ` ${f.numeric.unit}` : \"\"}`;\n parts.push(`${f.title} ${label}`);\n continue;\n }\n case \"rating\":\n parts.push(`${f.title} ${x} / 5`);\n continue;\n case \"select\": {\n const label = f.options?.find((o) => o.value === x)?.label ?? String(x);\n parts.push(label.length <= 4 ? `${f.title} ${label}` : label);\n continue;\n }\n case \"multiselect\": case \"tags\":\n if (Array.isArray(x)) parts.push(x.length <= 2 ? x.map((v) => f.options?.find((o) => o.value === v)?.label ?? String(v)).join(\", \") : `${x.length} ${f.title.toLowerCase()}`);\n continue;\n case \"array\":\n if (Array.isArray(x)) parts.push(`${x.length} ${f.title.toLowerCase()}`);\n continue;\n case \"color\":\n parts.push(`${f.title} ${String(x)}`);\n continue;\n default: {\n const t = plainText(x);\n if (t) parts.push(t.length > 32 ? `${t.slice(0, 30)}…` : t);\n }\n }\n }\n return parts.join(\" · \");\n}\n"],"mappings":";;;;;;;;;;AAWA,SAAgB,aAAa,QAAuB,OAAgB,MAAM,GAAW;AACnF,KAAI,CAAC,MAAM,MAAM,CAAE,QAAO;CAC1B,MAAM,QAAkB,EAAE;AAC1B,MAAK,MAAM,KAAK,QAAQ;AACtB,MAAI,MAAM,UAAU,IAAK;AACzB,MAAI,SAAS,GAAG,MAAM,CAAE;EACxB,MAAM,IAAI,MAAM,EAAE;AAClB,MAAI,aAAa,EAAE,CAAE;AACrB,UAAQ,EAAE,MAAV;GACE,KAAK;GAAS,KAAK;GAAQ,KAAK;GAAS,KAAK;GAAa,KAAK;GAAQ,KAAK;GAAQ,KAAK;GAAU,KAAK;GAAQ,KAAK,WACpH;GACF,KAAK;AACH,QAAI,MAAM,KAAM,OAAM,KAAK,EAAE,MAAM;AACnC;GACF,KAAK,UAAU;IACb,MAAM,QAAQ,EAAE,QAAQ,aAAa,EAAE,OAAO,EAAE,CAAC,QAAQ,GAAG,IAAI,EAAE,SAAS,OAAO,IAAI,EAAE,QAAQ,SAAS;AACzG,UAAM,KAAK,GAAG,EAAE,MAAM,GAAG,QAAQ;AACjC;;GAEF,KAAK;AACH,UAAM,KAAK,GAAG,EAAE,MAAM,GAAG,EAAE,MAAM;AACjC;GACF,KAAK,UAAU;IACb,MAAM,QAAQ,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,EAAE,EAAE,SAAS,OAAO,EAAE;AACvE,UAAM,KAAK,MAAM,UAAU,IAAI,GAAG,EAAE,MAAM,GAAG,UAAU,MAAM;AAC7D;;GAEF,KAAK;GAAe,KAAK;AACvB,QAAI,MAAM,QAAQ,EAAE,CAAE,OAAM,KAAK,EAAE,UAAU,IAAI,EAAE,KAAK,MAAM,EAAE,SAAS,MAAM,MAAM,EAAE,UAAU,EAAE,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,KAAK,KAAK,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,aAAa,GAAG;AAC7K;GACF,KAAK;AACH,QAAI,MAAM,QAAQ,EAAE,CAAE,OAAM,KAAK,GAAG,EAAE,OAAO,GAAG,EAAE,MAAM,aAAa,GAAG;AACxE;GACF,KAAK;AACH,UAAM,KAAK,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,GAAG;AACrC;GACF,SAAS;IACP,MAAM,IAAI,UAAU,EAAE;AACtB,QAAI,EAAG,OAAM,KAAK,EAAE,SAAS,KAAK,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE;;;;AAIjE,QAAO,MAAM,KAAK,MAAM"}