@bettercms-ai/kit 1.0.0 → 2.0.0-next.1

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 (619) 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 +94 -31
  8. package/dist/adapters/lossy.js +419 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
  11. package/{adapters → dist/adapters}/prod-types.js +82 -13
  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 +1038 -204
  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} +131 -2
  22. package/{context.js → dist/context.js} +44 -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/dist/controls/form-picker-register.d.ts +7 -0
  50. package/{controls → dist/controls}/form-picker-register.js +2 -6
  51. package/dist/controls/form-picker-register.js.map +1 -0
  52. package/{controls → dist/controls}/form-picker.js +11 -9
  53. package/dist/controls/form-picker.js.map +1 -0
  54. package/{controls → dist/controls}/icon-register.js +1 -1
  55. package/dist/controls/icon-register.js.map +1 -0
  56. package/{controls → dist/controls}/icon.d.ts +4 -2
  57. package/{controls → dist/controls}/icon.js +32 -27
  58. package/dist/controls/icon.js.map +1 -0
  59. package/{controls → dist/controls}/index.d.ts +1 -1
  60. package/{controls → dist/controls}/index.js +4 -3
  61. package/dist/controls/index.js.map +1 -0
  62. package/{controls → dist/controls}/json-register.js +1 -1
  63. package/dist/controls/json-register.js.map +1 -0
  64. package/{controls → dist/controls}/json.js +13 -3
  65. package/dist/controls/json.js.map +1 -0
  66. package/{controls → dist/controls}/link.js +116 -200
  67. package/dist/controls/link.js.map +1 -0
  68. package/{controls → dist/controls}/location-register.js +1 -1
  69. package/dist/controls/location-register.js.map +1 -0
  70. package/{controls → dist/controls}/location.js +59 -40
  71. package/dist/controls/location.js.map +1 -0
  72. package/{controls → dist/controls}/media-register.js +1 -1
  73. package/dist/controls/media-register.js.map +1 -0
  74. package/{controls → dist/controls}/media-services.d.ts +6 -0
  75. package/dist/controls/media-services.js +0 -0
  76. package/{controls → dist/controls}/media.d.ts +21 -4
  77. package/{controls → dist/controls}/media.js +407 -130
  78. package/dist/controls/media.js.map +1 -0
  79. package/{controls → dist/controls}/number.js +10 -9
  80. package/dist/controls/number.js.map +1 -0
  81. package/{controls → dist/controls}/reference-register.js +1 -1
  82. package/dist/controls/reference-register.js.map +1 -0
  83. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  84. package/dist/controls/reference-services.js +0 -0
  85. package/{controls → dist/controls}/reference.d.ts +1 -1
  86. package/{controls → dist/controls}/reference.js +93 -77
  87. package/dist/controls/reference.js.map +1 -0
  88. package/dist/controls/rich-text/article-shell.d.ts +145 -0
  89. package/dist/controls/rich-text/article-shell.js +510 -0
  90. package/dist/controls/rich-text/article-shell.js.map +1 -0
  91. package/dist/controls/rich-text/author.d.ts +25 -0
  92. package/dist/controls/rich-text/author.js +104 -0
  93. package/dist/controls/rich-text/author.js.map +1 -0
  94. package/dist/controls/rich-text/blocks.d.ts +60 -0
  95. package/{controls → dist/controls}/rich-text/blocks.js +164 -389
  96. package/dist/controls/rich-text/blocks.js.map +1 -0
  97. package/dist/controls/rich-text/button.d.ts +23 -0
  98. package/dist/controls/rich-text/button.js +85 -0
  99. package/dist/controls/rich-text/button.js.map +1 -0
  100. package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
  101. package/{controls → dist/controls}/rich-text/catalog.js +94 -68
  102. package/dist/controls/rich-text/catalog.js.map +1 -0
  103. package/dist/controls/rich-text/checklist.d.ts +24 -0
  104. package/dist/controls/rich-text/checklist.js +115 -0
  105. package/dist/controls/rich-text/checklist.js.map +1 -0
  106. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  107. package/{controls → dist/controls}/rich-text/codec.js +7 -2
  108. package/dist/controls/rich-text/codec.js.map +1 -0
  109. package/dist/controls/rich-text/columns.d.ts +41 -0
  110. package/dist/controls/rich-text/columns.js +181 -0
  111. package/dist/controls/rich-text/columns.js.map +1 -0
  112. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  113. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  114. package/dist/controls/rich-text/component-card.js.map +1 -0
  115. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  116. package/dist/controls/rich-text/component-panel.js +141 -0
  117. package/dist/controls/rich-text/component-panel.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  119. package/{controls → dist/controls}/rich-text/control.js +84 -42
  120. package/dist/controls/rich-text/control.js.map +1 -0
  121. package/{controls → dist/controls}/rich-text/dom.d.ts +53 -9
  122. package/{controls → dist/controls}/rich-text/dom.js +388 -50
  123. package/dist/controls/rich-text/dom.js.map +1 -0
  124. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  125. package/{controls → dist/controls}/rich-text/editor.js +226 -44
  126. package/dist/controls/rich-text/editor.js.map +1 -0
  127. package/dist/controls/rich-text/embed.d.ts +28 -0
  128. package/dist/controls/rich-text/embed.js +210 -0
  129. package/dist/controls/rich-text/embed.js.map +1 -0
  130. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  131. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  132. package/dist/controls/rich-text/floating.js.map +1 -0
  133. package/dist/controls/rich-text/footnote.d.ts +41 -0
  134. package/dist/controls/rich-text/footnote.js +185 -0
  135. package/dist/controls/rich-text/footnote.js.map +1 -0
  136. package/dist/controls/rich-text/gallery.d.ts +28 -0
  137. package/dist/controls/rich-text/gallery.js +167 -0
  138. package/dist/controls/rich-text/gallery.js.map +1 -0
  139. package/{controls → dist/controls}/rich-text/index.js +1 -1
  140. package/dist/controls/rich-text/index.js.map +1 -0
  141. package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
  142. package/dist/controls/rich-text/link-form.js +147 -0
  143. package/dist/controls/rich-text/link-form.js.map +1 -0
  144. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  145. package/dist/controls/rich-text/markdown.js.map +1 -0
  146. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  147. package/dist/controls/rich-text/ops.js.map +1 -0
  148. package/dist/controls/rich-text/plain.d.ts +17 -0
  149. package/dist/controls/rich-text/plain.js +44 -0
  150. package/dist/controls/rich-text/plain.js.map +1 -0
  151. package/dist/controls/rich-text/related.d.ts +36 -0
  152. package/dist/controls/rich-text/related.js +213 -0
  153. package/dist/controls/rich-text/related.js.map +1 -0
  154. package/dist/controls/rich-text/toc.d.ts +46 -0
  155. package/dist/controls/rich-text/toc.js +161 -0
  156. package/dist/controls/rich-text/toc.js.map +1 -0
  157. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  158. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  159. package/dist/controls/rich-text/toolbar.js.map +1 -0
  160. package/{controls → dist/controls}/scale.js +5 -5
  161. package/dist/controls/scale.js.map +1 -0
  162. package/dist/controls/slot-register.d.ts +6 -0
  163. package/{controls → dist/controls}/slot-register.js +2 -5
  164. package/dist/controls/slot-register.js.map +1 -0
  165. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  166. package/dist/controls/slot-services.js +155 -0
  167. package/dist/controls/slot-services.js.map +1 -0
  168. package/{controls → dist/controls}/slot.js +42 -24
  169. package/dist/controls/slot.js.map +1 -0
  170. package/{controls → dist/controls}/table/index.js +1 -1
  171. package/dist/controls/table/index.js.map +1 -0
  172. package/{controls → dist/controls}/table/prod.js +3 -3
  173. package/dist/controls/table/prod.js.map +1 -0
  174. package/{controls → dist/controls}/table/refs.js +13 -2
  175. package/dist/controls/table/refs.js.map +1 -0
  176. package/{controls → dist/controls}/table/stored.js +1 -1
  177. package/dist/controls/table/stored.js.map +1 -0
  178. package/{controls → dist/controls}/table/table-editor.js +51 -48
  179. package/dist/controls/table/table-editor.js.map +1 -0
  180. package/{controls → dist/controls}/table/table-link.js +3 -3
  181. package/dist/controls/table/table-link.js.map +1 -0
  182. package/{controls → dist/controls}/table/table.js +3 -3
  183. package/dist/controls/table/table.js.map +1 -0
  184. package/{controls → dist/controls}/text.d.ts +2 -2
  185. package/{controls → dist/controls}/text.js +78 -43
  186. package/dist/controls/text.js.map +1 -0
  187. package/dist/controls/unknown-value.d.ts +17 -0
  188. package/dist/controls/unknown-value.js +66 -0
  189. package/dist/controls/unknown-value.js.map +1 -0
  190. package/dist/core/core.d.ts +70 -0
  191. package/dist/core/core.js +187 -0
  192. package/dist/core/core.js.map +1 -0
  193. package/dist/core/facets.d.ts +355 -0
  194. package/dist/core/facets.js +342 -0
  195. package/dist/core/facets.js.map +1 -0
  196. package/dist/core/index.d.ts +3 -0
  197. package/dist/core/index.js +3 -0
  198. package/{engine → dist/engine}/array.js +34 -21
  199. package/dist/engine/array.js.map +1 -0
  200. package/{engine → dist/engine}/bits.js +1 -1
  201. package/dist/engine/bits.js.map +1 -0
  202. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  203. package/{engine → dist/engine}/breadcrumb.js +12 -36
  204. package/dist/engine/breadcrumb.js.map +1 -0
  205. package/{engine → dist/engine}/expand.d.ts +2 -4
  206. package/{engine → dist/engine}/expand.js +5 -22
  207. package/dist/engine/expand.js.map +1 -0
  208. package/{engine → dist/engine}/field-list.js +1 -1
  209. package/dist/engine/field-list.js.map +1 -0
  210. package/{engine → dist/engine}/field-shell.js +249 -121
  211. package/dist/engine/field-shell.js.map +1 -0
  212. package/{engine → dist/engine}/frame.d.ts +3 -1
  213. package/{engine → dist/engine}/frame.js +16 -14
  214. package/dist/engine/frame.js.map +1 -0
  215. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  216. package/{engine → dist/engine}/group-summary.js +7 -3
  217. package/dist/engine/group-summary.js.map +1 -0
  218. package/{engine → dist/engine}/grouping.d.ts +19 -5
  219. package/{engine → dist/engine}/grouping.js +193 -21
  220. package/dist/engine/grouping.js.map +1 -0
  221. package/{engine → dist/engine}/item-list.d.ts +11 -1
  222. package/{engine → dist/engine}/item-list.js +35 -13
  223. package/dist/engine/item-list.js.map +1 -0
  224. package/{engine → dist/engine}/kit-field.js +45 -10
  225. package/dist/engine/kit-field.js.map +1 -0
  226. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  227. package/{engine → dist/engine}/schema-form.js +182 -40
  228. package/dist/engine/schema-form.js.map +1 -0
  229. package/{engine → dist/engine}/slot.js +5 -15
  230. package/dist/engine/slot.js.map +1 -0
  231. package/dist/index.js +58 -0
  232. package/dist/index.js.map +1 -0
  233. package/{kit.css → dist/kit.css} +19 -0
  234. package/{lib → dist/lib}/cn.js +7 -4
  235. package/dist/lib/cn.js.map +1 -0
  236. package/{lib → dist/lib}/columns.js +4 -1
  237. package/dist/lib/columns.js.map +1 -0
  238. package/{lib → dist/lib}/frames.js +2 -2
  239. package/dist/lib/frames.js.map +1 -0
  240. package/dist/lib/icon-image.d.ts +10 -0
  241. package/dist/lib/icon-image.js +8 -0
  242. package/dist/lib/icon-image.js.map +1 -0
  243. package/{lib → dist/lib}/icons.js +4 -3
  244. package/dist/lib/icons.js.map +1 -0
  245. package/dist/lib/input-modality.d.ts +11 -0
  246. package/dist/lib/input-modality.js +47 -0
  247. package/dist/lib/input-modality.js.map +1 -0
  248. package/dist/lib/key-event.d.ts +11 -0
  249. package/dist/lib/key-event.js +16 -0
  250. package/dist/lib/key-event.js.map +1 -0
  251. package/{lib → dist/lib}/path.js +4 -2
  252. package/dist/lib/path.js.map +1 -0
  253. package/{lib → dist/lib}/schema.d.ts +34 -3
  254. package/{lib → dist/lib}/schema.js +110 -13
  255. package/dist/lib/schema.js.map +1 -0
  256. package/{lib → dist/lib}/utils.js +1 -1
  257. package/dist/lib/utils.js.map +1 -0
  258. package/{lib → dist/lib}/validate.d.ts +11 -1
  259. package/{lib → dist/lib}/validate.js +85 -11
  260. package/dist/lib/validate.js.map +1 -0
  261. package/dist/library/analysis.d.ts +23 -0
  262. package/dist/library/analysis.js +160 -0
  263. package/dist/library/analysis.js.map +1 -0
  264. package/dist/library/catalog.d.ts +57 -0
  265. package/dist/library/catalog.js +307 -0
  266. package/dist/library/catalog.js.map +1 -0
  267. package/dist/library/coreNotes.d.ts +8 -0
  268. package/dist/library/coreNotes.js +111 -0
  269. package/dist/library/coreNotes.js.map +1 -0
  270. package/dist/library/coverage.d.ts +40 -0
  271. package/dist/library/coverage.js +59 -0
  272. package/dist/library/coverage.js.map +1 -0
  273. package/dist/library/entries/advanced.entries.d.ts +2 -0
  274. package/dist/library/entries/advanced.entries.js +6579 -0
  275. package/dist/library/entries/advanced.entries.js.map +1 -0
  276. package/dist/library/entries/commerce.entries.d.ts +2 -0
  277. package/dist/library/entries/commerce.entries.js +4140 -0
  278. package/dist/library/entries/commerce.entries.js.map +1 -0
  279. package/dist/library/entries/company.entries.d.ts +2 -0
  280. package/dist/library/entries/company.entries.js +2731 -0
  281. package/dist/library/entries/company.entries.js.map +1 -0
  282. package/dist/library/entries/conversion.entries.d.ts +2 -0
  283. package/dist/library/entries/conversion.entries.js +3707 -0
  284. package/dist/library/entries/conversion.entries.js.map +1 -0
  285. package/dist/library/entries/data.entries.d.ts +7 -0
  286. package/dist/library/entries/data.entries.js +4613 -0
  287. package/dist/library/entries/data.entries.js.map +1 -0
  288. package/dist/library/entries/events.entries.d.ts +2 -0
  289. package/dist/library/entries/events.entries.js +3428 -0
  290. package/dist/library/entries/events.entries.js.map +1 -0
  291. package/dist/library/entries/features.entries.d.ts +2 -0
  292. package/dist/library/entries/features.entries.js +3157 -0
  293. package/dist/library/entries/features.entries.js.map +1 -0
  294. package/dist/library/entries/heroes.entries.d.ts +2 -0
  295. package/dist/library/entries/heroes.entries.js +3401 -0
  296. package/dist/library/entries/heroes.entries.js.map +1 -0
  297. package/dist/library/entries/index.d.ts +3 -0
  298. package/dist/library/entries/index.js +35 -0
  299. package/dist/library/entries/index.js.map +1 -0
  300. package/dist/library/entries/listings.entries.d.ts +2 -0
  301. package/dist/library/entries/listings.entries.js +2976 -0
  302. package/dist/library/entries/listings.entries.js.map +1 -0
  303. package/dist/library/entries/longform.entries.d.ts +2 -0
  304. package/dist/library/entries/longform.entries.js +4227 -0
  305. package/dist/library/entries/longform.entries.js.map +1 -0
  306. package/dist/library/entries/media.entries.d.ts +2 -0
  307. package/dist/library/entries/media.entries.js +2781 -0
  308. package/dist/library/entries/media.entries.js.map +1 -0
  309. package/dist/library/entries/navigation.entries.d.ts +2 -0
  310. package/dist/library/entries/navigation.entries.js +4011 -0
  311. package/dist/library/entries/navigation.entries.js.map +1 -0
  312. package/dist/library/entries/pricing.entries.d.ts +2 -0
  313. package/dist/library/entries/pricing.entries.js +2383 -0
  314. package/dist/library/entries/pricing.entries.js.map +1 -0
  315. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  316. package/dist/library/entries/social-proof.entries.js +2297 -0
  317. package/dist/library/entries/social-proof.entries.js.map +1 -0
  318. package/dist/library/examples/bento.d.ts +92 -0
  319. package/dist/library/examples/bento.js +201 -0
  320. package/dist/library/examples/bento.js.map +1 -0
  321. package/dist/library/examples/blocks.d.ts +14 -0
  322. package/dist/library/examples/blocks.js +313 -0
  323. package/dist/library/examples/blocks.js.map +1 -0
  324. package/dist/library/examples/faq.d.ts +28 -0
  325. package/dist/library/examples/faq.js +230 -0
  326. package/dist/library/examples/faq.js.map +1 -0
  327. package/dist/library/examples/hero.d.ts +43 -0
  328. package/dist/library/examples/hero.js +222 -0
  329. package/dist/library/examples/hero.js.map +1 -0
  330. package/dist/library/examples/index.d.ts +36 -0
  331. package/dist/library/examples/index.js +109 -0
  332. package/dist/library/examples/index.js.map +1 -0
  333. package/dist/library/examples/journalStory.d.ts +93 -0
  334. package/dist/library/examples/journalStory.js +338 -0
  335. package/dist/library/examples/journalStory.js.map +1 -0
  336. package/dist/library/examples/megaMenu.d.ts +134 -0
  337. package/dist/library/examples/megaMenu.js +442 -0
  338. package/dist/library/examples/megaMenu.js.map +1 -0
  339. package/dist/library/examples/pricing.d.ts +103 -0
  340. package/dist/library/examples/pricing.js +479 -0
  341. package/dist/library/examples/pricing.js.map +1 -0
  342. package/dist/library/examples/tabs.d.ts +87 -0
  343. package/dist/library/examples/tabs.js +180 -0
  344. package/dist/library/examples/tabs.js.map +1 -0
  345. package/dist/library/export.d.ts +42 -0
  346. package/dist/library/export.js +80 -0
  347. package/dist/library/export.js.map +1 -0
  348. package/dist/library/index.d.ts +13 -0
  349. package/dist/library/index.js +6 -0
  350. package/dist/library/kit-catalog.json +1511 -0
  351. package/dist/library/types.d.ts +42 -0
  352. package/dist/library/types.js +0 -0
  353. package/{schema → dist/schema}/adapters.js +1 -2
  354. package/dist/schema/adapters.js.map +1 -0
  355. package/{schema → dist/schema}/help.d.ts +2 -0
  356. package/{schema → dist/schema}/help.js +6 -4
  357. package/dist/schema/help.js.map +1 -0
  358. package/{schema → dist/schema}/scale.js +1 -1
  359. package/dist/schema/scale.js.map +1 -0
  360. package/{schema → dist/schema}/sources.js +1 -1
  361. package/dist/schema/sources.js.map +1 -0
  362. package/{schema → dist/schema}/table.js +11 -10
  363. package/dist/schema/table.js.map +1 -0
  364. package/{schema → dist/schema}/types.d.ts +36 -1
  365. package/{schema → dist/schema}/types.js +1 -1
  366. package/dist/schema/types.js.map +1 -0
  367. package/dist/styles.css +2 -0
  368. package/dist/table/table-view.d.ts +14 -0
  369. package/dist/table/table-view.js +140 -0
  370. package/dist/table/table-view.js.map +1 -0
  371. package/dist/table/table.css +73 -0
  372. package/dist/testing/corpus.d.ts +63 -0
  373. package/dist/testing/corpus.js +129 -0
  374. package/dist/testing/corpus.js.map +1 -0
  375. package/dist/testing/test-form.d.ts +11 -0
  376. package/dist/testing/test-form.js +38 -0
  377. package/dist/testing/test-form.js.map +1 -0
  378. package/dist/theme.css +345 -0
  379. package/dist/theme.d.ts +22 -0
  380. package/dist/theme.js +43 -0
  381. package/dist/theme.js.map +1 -0
  382. package/dist/tokens.css +542 -0
  383. package/dist/types.js +0 -0
  384. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  385. package/{ui → dist/ui}/action-tray.js +20 -19
  386. package/dist/ui/action-tray.js.map +1 -0
  387. package/dist/ui/autocomplete.d.ts +58 -0
  388. package/dist/ui/autocomplete.js +194 -0
  389. package/dist/ui/autocomplete.js.map +1 -0
  390. package/{ui → dist/ui}/button.d.ts +3 -3
  391. package/{ui → dist/ui}/button.js +8 -11
  392. package/dist/ui/button.js.map +1 -0
  393. package/{ui → dist/ui}/choice-switch.js +1 -1
  394. package/dist/ui/choice-switch.js.map +1 -0
  395. package/{ui → dist/ui}/controls.js +51 -39
  396. package/dist/ui/controls.js.map +1 -0
  397. package/{ui → dist/ui}/display.d.ts +10 -3
  398. package/{ui → dist/ui}/display.js +57 -46
  399. package/dist/ui/display.js.map +1 -0
  400. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  401. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  402. package/dist/ui/expanded-editor-modal.js.map +1 -0
  403. package/{ui → dist/ui}/field-context.js +1 -1
  404. package/dist/ui/field-context.js.map +1 -0
  405. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  406. package/{ui → dist/ui}/floating-panel.js +28 -12
  407. package/dist/ui/floating-panel.js.map +1 -0
  408. package/{ui → dist/ui}/index.d.ts +4 -0
  409. package/dist/ui/index.js +18 -0
  410. package/{ui → dist/ui}/input.d.ts +1 -1
  411. package/{ui → dist/ui}/input.js +9 -9
  412. package/dist/ui/input.js.map +1 -0
  413. package/{ui → dist/ui}/mode-bar.js +3 -3
  414. package/dist/ui/mode-bar.js.map +1 -0
  415. package/{ui → dist/ui}/overlay.d.ts +77 -5
  416. package/dist/ui/overlay.js +697 -0
  417. package/dist/ui/overlay.js.map +1 -0
  418. package/{ui → dist/ui}/path-crumbs.js +37 -3
  419. package/dist/ui/path-crumbs.js.map +1 -0
  420. package/{ui → dist/ui}/presence.js +2 -2
  421. package/dist/ui/presence.js.map +1 -0
  422. package/{ui → dist/ui}/select.js +89 -87
  423. package/dist/ui/select.js.map +1 -0
  424. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  425. package/dist/ui/shortcut-hint.js.map +1 -0
  426. package/dist/ui/spinner.d.ts +24 -0
  427. package/dist/ui/spinner.js +42 -0
  428. package/dist/ui/spinner.js.map +1 -0
  429. package/dist/ui/split-button.d.ts +32 -0
  430. package/dist/ui/split-button.js +60 -0
  431. package/dist/ui/split-button.js.map +1 -0
  432. package/{ui → dist/ui}/surfaces.js +1 -1
  433. package/dist/ui/surfaces.js.map +1 -0
  434. package/dist/ui/tab.d.ts +38 -0
  435. package/dist/ui/tab.js +87 -0
  436. package/dist/ui/tab.js.map +1 -0
  437. package/dist/ui/toast.d.ts +20 -0
  438. package/dist/ui/toast.js +115 -0
  439. package/dist/ui/toast.js.map +1 -0
  440. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  441. package/{ui → dist/ui}/tooltip-root.js +9 -8
  442. package/dist/ui/tooltip-root.js.map +1 -0
  443. package/{ui → dist/ui}/variants.js +1 -1
  444. package/dist/ui/variants.js.map +1 -0
  445. package/package.json +83 -23
  446. package/adapters/icons.js.map +0 -1
  447. package/adapters/lossy.js +0 -233
  448. package/adapters/lossy.js.map +0 -1
  449. package/adapters/prod-types.js.map +0 -1
  450. package/adapters/schema.js.map +0 -1
  451. package/adapters/values.js.map +0 -1
  452. package/brand/logo.js +0 -9
  453. package/brand/logo.js.map +0 -1
  454. package/context.js.map +0 -1
  455. package/controls/button.js.map +0 -1
  456. package/controls/c1.js.map +0 -1
  457. package/controls/c2.js.map +0 -1
  458. package/controls/choice.js.map +0 -1
  459. package/controls/code-register.js.map +0 -1
  460. package/controls/code.js.map +0 -1
  461. package/controls/color.js.map +0 -1
  462. package/controls/date-register.js.map +0 -1
  463. package/controls/date-zone.js.map +0 -1
  464. package/controls/date.js.map +0 -1
  465. package/controls/form-picker-register.d.ts +0 -1
  466. package/controls/form-picker-register.js.map +0 -1
  467. package/controls/form-picker.js.map +0 -1
  468. package/controls/icon-register.js.map +0 -1
  469. package/controls/icon.js.map +0 -1
  470. package/controls/index.js.map +0 -1
  471. package/controls/json-register.js.map +0 -1
  472. package/controls/json.js.map +0 -1
  473. package/controls/link.js.map +0 -1
  474. package/controls/location-register.js.map +0 -1
  475. package/controls/location.js.map +0 -1
  476. package/controls/media-register.js.map +0 -1
  477. package/controls/media.js.map +0 -1
  478. package/controls/number.js.map +0 -1
  479. package/controls/reference-register.js.map +0 -1
  480. package/controls/reference.js.map +0 -1
  481. package/controls/rich-text/blocks.d.ts +0 -28
  482. package/controls/rich-text/blocks.js.map +0 -1
  483. package/controls/rich-text/catalog.js.map +0 -1
  484. package/controls/rich-text/codec.js.map +0 -1
  485. package/controls/rich-text/component-card.js.map +0 -1
  486. package/controls/rich-text/control.js.map +0 -1
  487. package/controls/rich-text/dom.js.map +0 -1
  488. package/controls/rich-text/editor.js.map +0 -1
  489. package/controls/rich-text/floating.js.map +0 -1
  490. package/controls/rich-text/index.js.map +0 -1
  491. package/controls/rich-text/link-form.js +0 -111
  492. package/controls/rich-text/link-form.js.map +0 -1
  493. package/controls/rich-text/markdown.js.map +0 -1
  494. package/controls/rich-text/ops.js.map +0 -1
  495. package/controls/rich-text/toolbar.js.map +0 -1
  496. package/controls/scale.js.map +0 -1
  497. package/controls/slot-register.d.ts +0 -1
  498. package/controls/slot-register.js.map +0 -1
  499. package/controls/slot-services.js +0 -38
  500. package/controls/slot-services.js.map +0 -1
  501. package/controls/slot.js.map +0 -1
  502. package/controls/table/index.js.map +0 -1
  503. package/controls/table/prod.js.map +0 -1
  504. package/controls/table/refs.js.map +0 -1
  505. package/controls/table/stored.js.map +0 -1
  506. package/controls/table/table-editor.js.map +0 -1
  507. package/controls/table/table-link.js.map +0 -1
  508. package/controls/table/table.js.map +0 -1
  509. package/controls/text.js.map +0 -1
  510. package/engine/array.js.map +0 -1
  511. package/engine/bits.js.map +0 -1
  512. package/engine/breadcrumb.js.map +0 -1
  513. package/engine/expand.js.map +0 -1
  514. package/engine/field-list.js.map +0 -1
  515. package/engine/field-shell.js.map +0 -1
  516. package/engine/frame.js.map +0 -1
  517. package/engine/group-summary.js.map +0 -1
  518. package/engine/grouping.js.map +0 -1
  519. package/engine/item-list.js.map +0 -1
  520. package/engine/kit-field.js.map +0 -1
  521. package/engine/schema-form.js.map +0 -1
  522. package/engine/slot.js.map +0 -1
  523. package/index.js +0 -55
  524. package/index.js.map +0 -1
  525. package/lib/cn.js.map +0 -1
  526. package/lib/columns.js.map +0 -1
  527. package/lib/frames.js.map +0 -1
  528. package/lib/icons.js.map +0 -1
  529. package/lib/path.js.map +0 -1
  530. package/lib/schema.js.map +0 -1
  531. package/lib/utils.js.map +0 -1
  532. package/lib/validate.js.map +0 -1
  533. package/schema/adapters.js.map +0 -1
  534. package/schema/help.js.map +0 -1
  535. package/schema/scale.js.map +0 -1
  536. package/schema/sources.js.map +0 -1
  537. package/schema/table.js.map +0 -1
  538. package/schema/types.js.map +0 -1
  539. package/ui/action-tray.js.map +0 -1
  540. package/ui/button.js.map +0 -1
  541. package/ui/choice-switch.js.map +0 -1
  542. package/ui/controls.js.map +0 -1
  543. package/ui/display.js.map +0 -1
  544. package/ui/expanded-editor-modal.js.map +0 -1
  545. package/ui/field-context.js.map +0 -1
  546. package/ui/floating-panel.js.map +0 -1
  547. package/ui/index.js +0 -13
  548. package/ui/input.js.map +0 -1
  549. package/ui/mode-bar.js.map +0 -1
  550. package/ui/overlay.js +0 -378
  551. package/ui/overlay.js.map +0 -1
  552. package/ui/path-crumbs.js.map +0 -1
  553. package/ui/presence.js.map +0 -1
  554. package/ui/select.js.map +0 -1
  555. package/ui/shortcut-hint.js.map +0 -1
  556. package/ui/surfaces.js.map +0 -1
  557. package/ui/tooltip-root.js.map +0 -1
  558. package/ui/variants.js.map +0 -1
  559. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  560. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  561. /package/{brand → dist/brand}/logo.d.ts +0 -0
  562. /package/{controls → dist/controls}/c1.d.ts +0 -0
  563. /package/{controls → dist/controls}/c2.d.ts +0 -0
  564. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  565. /package/{controls → dist/controls}/code.d.ts +0 -0
  566. /package/{controls → dist/controls}/color.d.ts +0 -0
  567. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  568. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  569. /package/{controls → dist/controls}/date.d.ts +0 -0
  570. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  571. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  572. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  573. /package/{controls → dist/controls}/json.d.ts +0 -0
  574. /package/{controls → dist/controls}/link.d.ts +0 -0
  575. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  576. /package/{controls → dist/controls}/location.d.ts +0 -0
  577. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  578. /package/{controls → dist/controls}/number.d.ts +0 -0
  579. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  580. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  581. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  582. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  583. /package/{controls → dist/controls}/scale.d.ts +0 -0
  584. /package/{controls → dist/controls}/slot.d.ts +0 -0
  585. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  586. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  587. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  588. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  589. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  590. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  591. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  592. /package/{engine → dist/engine}/array.d.ts +0 -0
  593. /package/{engine → dist/engine}/bits.d.ts +0 -0
  594. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  595. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  596. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  597. /package/{engine → dist/engine}/slot.d.ts +0 -0
  598. /package/{index.d.ts → dist/index.d.ts} +0 -0
  599. /package/{lib → dist/lib}/cn.d.ts +0 -0
  600. /package/{lib → dist/lib}/columns.d.ts +0 -0
  601. /package/{lib → dist/lib}/frames.d.ts +0 -0
  602. /package/{lib → dist/lib}/icons.d.ts +0 -0
  603. /package/{lib → dist/lib}/path.d.ts +0 -0
  604. /package/{lib → dist/lib}/utils.d.ts +0 -0
  605. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  606. /package/{schema → dist/schema}/scale.d.ts +0 -0
  607. /package/{schema → dist/schema}/sources.d.ts +0 -0
  608. /package/{schema → dist/schema}/table.d.ts +0 -0
  609. /package/{types.d.ts → dist/types.d.ts} +0 -0
  610. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  611. /package/{ui → dist/ui}/controls.d.ts +0 -0
  612. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  613. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  614. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  615. /package/{ui → dist/ui}/presence.d.ts +0 -0
  616. /package/{ui → dist/ui}/select.d.ts +0 -0
  617. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  618. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  619. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -5,9 +5,9 @@ import { Popover, PopoverContent, PopoverTrigger, Tooltip } from "../ui/overlay.
5
5
  import { Select } from "../ui/select.js";
6
6
  import { ALL_ZONES, browserZone, parseStored, resolveShown, todayIn, useDefaultZone, validZone, wallInstant, writeValue, zoneCity, zoneLabel, zonePolicy, zoneShortOffset } from "./date-zone.js";
7
7
  import * as React from "react";
8
- import { IconAlertTriangle, IconCalendar, IconChevronDown, IconChevronLeft, IconChevronRight, IconClock, IconLock, IconWorld } from "@tabler/icons-react";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
10
- //#region src/kit/controls/date.tsx
9
+ import { IconAlertTriangle, IconCalendar, IconChevronDown, IconChevronLeft, IconChevronRight, IconClock, IconLock, IconWorld } from "@tabler/icons-react";
10
+ //#region src/controls/date.tsx
11
11
  /**
12
12
  * DATE / DATETIME — one picker for date, time and time zone (DESIGN 8.9, CPO D43). V2 controls/date.tsx, with the
13
13
  * stored shapes prod keeps (date-zone.ts header) and a calendar you can drive from the keyboard:
@@ -171,7 +171,7 @@ function MiniCalendar({ value, today, onSelect }) {
171
171
  day: "numeric",
172
172
  year: "numeric"
173
173
  }),
174
- className: cn("flex size-8 items-center justify-center rounded-kit-md text-kit-sm tabular-nums transition-colors", sel ? "bg-kit-inverse font-medium text-kit-fg-inverse" : out ? "text-kit-fg-4 hover:bg-kit-hover" : "text-kit-fg hover:bg-kit-hover", !sel && d === today && "ring-1 ring-inset ring-kit-line-strong"),
174
+ className: cn("tabular-nums flex size-8 items-center justify-center rounded-kit-md text-kit-sm transition-colors", sel ? "bg-kit-inverse font-medium text-kit-fg-inverse" : out ? "text-kit-fg-4 hover:bg-kit-hover" : "text-kit-fg hover:bg-kit-hover", !sel && d === today && "ring-1 ring-inset ring-kit-line-strong"),
175
175
  children: Number(d.slice(8))
176
176
  }, d);
177
177
  })]
@@ -205,6 +205,11 @@ function zoneOptions(current, def, at) {
205
205
  return [...suggested, ...ALL_ZONES.filter((z) => !seen.has(z)).map((z) => option(z, z.includes("/") ? z.split("/")[0] : "Other"))];
206
206
  }
207
207
  function ZoneSelect({ zone, def, at, disabled, onPick }) {
208
+ const options = React.useMemo(() => zoneOptions(zone, def, at), [
209
+ zone,
210
+ def,
211
+ at
212
+ ]);
208
213
  return /* @__PURE__ */ jsx(Select, {
209
214
  "aria-label": "Time zone",
210
215
  size: "md",
@@ -214,11 +219,7 @@ function ZoneSelect({ zone, def, at, disabled, onPick }) {
214
219
  menuClassName: "w-[300px]",
215
220
  value: zone,
216
221
  onValueChange: onPick,
217
- options: React.useMemo(() => zoneOptions(zone, def, at), [
218
- zone,
219
- def,
220
- at
221
- ]),
222
+ options,
222
223
  disabled
223
224
  });
224
225
  }
@@ -293,7 +294,7 @@ function DateControl({ field, value, onChange, readOnly, id, invalid }) {
293
294
  disabled: readOnly,
294
295
  "aria-invalid": invalid || void 0,
295
296
  "aria-label": wall ? `${field.title}: ${full}. Change` : `${field.title}: pick a date`,
296
- className: cn("@container/date flex w-full min-w-0 items-center gap-2 rounded-kit-md border bg-kit-field-bg px-2.5 text-left text-kit-sm text-kit-fg shadow-kit-field outline-none transition-colors disabled:opacity-60", invalid ? "border-[var(--kit-field-invalid)]" : "border-kit-field-border hover:border-kit-field-border-hover data-[popup-open]:border-kit-field-border-focus focus-visible:border-kit-field-border-focus", variant === "document" ? "h-9" : "h-8")
297
+ className: cn("@container/date flex w-full min-w-0 items-center gap-2 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2.5 text-left text-kit-sm text-kit-fg shadow-kit-field transition-colors hover:border-kit-field-border-hover data-[popup-open]:border-kit-field-border-focus", variant === "document" ? "h-9" : "h-8", invalid && "border-[var(--kit-field-invalid)]")
297
298
  }),
298
299
  children: [
299
300
  /* @__PURE__ */ jsx(IconCalendar, {
@@ -348,20 +349,27 @@ function DateControl({ field, value, onChange, readOnly, id, invalid }) {
348
349
  className: "mt-3 flex w-[248px] flex-col gap-2 border-t border-kit-line pt-3",
349
350
  children: [/* @__PURE__ */ jsxs("label", {
350
351
  className: "flex items-center gap-2",
351
- children: [/* @__PURE__ */ jsx(IconClock, {
352
- className: "size-4 shrink-0 text-kit-fg-3",
353
- stroke: 1.5,
354
- "aria-hidden": true
355
- }), /* @__PURE__ */ jsx("input", {
356
- type: "time",
357
- value: time,
358
- onChange: (e) => e.target.value && commit({
359
- ymd: wall?.ymd ?? today,
360
- time: e.target.value
352
+ children: [
353
+ /* @__PURE__ */ jsx(IconClock, {
354
+ className: "size-4 shrink-0 text-kit-fg-3",
355
+ stroke: 1.5,
356
+ "aria-hidden": true
361
357
  }),
362
- className: "h-8 min-w-0 flex-1 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none hover:border-kit-field-border-hover focus:border-kit-field-border-focus",
363
- "aria-label": "Time"
364
- })]
358
+ /* @__PURE__ */ jsx("span", {
359
+ className: "sr-only",
360
+ children: "Time"
361
+ }),
362
+ /* @__PURE__ */ jsx("input", {
363
+ type: "time",
364
+ value: time,
365
+ onChange: (e) => e.target.value && commit({
366
+ ymd: wall?.ymd ?? today,
367
+ time: e.target.value
368
+ }),
369
+ className: "h-8 min-w-0 flex-1 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none hover:border-kit-field-border-hover focus:border-kit-field-border-focus",
370
+ "aria-label": "Time"
371
+ })
372
+ ]
365
373
  }), zoned ? /* @__PURE__ */ jsxs("div", {
366
374
  className: "flex items-center gap-2",
367
375
  children: [/* @__PURE__ */ jsx(IconWorld, {
@@ -381,7 +389,7 @@ function DateControl({ field, value, onChange, readOnly, id, invalid }) {
381
389
  content: policy.mode === "site" ? "Uses the site's time zone (Site settings › General)." : "Set by the developer for this field.",
382
390
  children: /* @__PURE__ */ jsxs("span", {
383
391
  tabIndex: 0,
384
- className: "flex h-8 min-w-0 flex-1 items-center gap-1.5 rounded-kit-md bg-kit-subtle px-2 text-kit-sm text-kit-fg-2 outline-none focus-visible:outline-2 focus-visible:outline-kit-focus-ring",
392
+ className: "flex h-8 min-w-0 flex-1 items-center gap-1.5 rounded-kit-md bg-kit-subtle px-2 text-kit-sm text-kit-fg-2 outline-none",
385
393
  children: [/* @__PURE__ */ jsx("span", {
386
394
  className: "min-w-0 flex-1 truncate",
387
395
  children: zoneLabel(zone, at)
@@ -453,6 +461,6 @@ function Unreadable({ id, title, value }) {
453
461
  });
454
462
  }
455
463
  //#endregion
456
- export { DateControl };
464
+ export { DateControl, MiniCalendar };
457
465
 
458
466
  //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","names":[],"sources":["../../src/controls/date.tsx"],"sourcesContent":["/**\n * DATE / DATETIME — one picker for date, time and time zone (DESIGN 8.9, CPO D43). V2 controls/date.tsx, with the\n * stored shapes prod keeps (date-zone.ts header) and a calendar you can drive from the keyboard:\n *\n * arrows move a day / a week · Home / End go to the week's start / end · Page Up / Down move a month (Shift: a year)\n * Enter or Space picks · the calendar is one tab stop (the picked day, else today, else the 1st)\n *\n * A value this picker cannot read (an object, a word) is shown with its reason and never overwritten by a stray\n * click. A wall time a clock change skips is refused with the reason, not shifted.\n */\nimport * as React from \"react\";\nimport { IconAlertTriangle, IconCalendar, IconChevronDown, IconChevronLeft, IconChevronRight, IconClock, IconLock, IconWorld } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { useKitEnv } from \"../context\";\nimport type { ControlProps } from \"../types\";\nimport { Button } from \"../ui/button\";\nimport { Popover, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport { Select, type SelectOption } from \"../ui/select\";\nimport {\n ALL_ZONES, browserZone, parseStored, resolveShown, todayIn, useDefaultZone, validZone, wallInstant, writeValue, zoneCity, zoneLabel,\n zonePolicy, zoneShortOffset, type Wall,\n} from \"./date-zone\";\n\n/* ── Day arithmetic on \"YYYY-MM-DD\" (UTC, so no local zone leaks in) ──── */\nconst pad = (n: number) => String(n).padStart(2, \"0\");\nconst toUtc = (ymd: string) => {\n const [y, m, d] = ymd.split(\"-\").map(Number);\n return new Date(Date.UTC(y, m - 1, d));\n};\nconst fromUtc = (d: Date) => `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;\nconst addDays = (ymd: string, n: number) => {\n const d = toUtc(ymd);\n d.setUTCDate(d.getUTCDate() + n);\n return fromUtc(d);\n};\nconst addMonths = (ymd: string, n: number) => {\n const d = toUtc(ymd);\n const day = d.getUTCDate();\n const t = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + n, 1));\n const last = new Date(Date.UTC(t.getUTCFullYear(), t.getUTCMonth() + 1, 0)).getUTCDate();\n t.setUTCDate(Math.min(day, last));\n return fromUtc(t);\n};\nconst monthOf = (ymd: string) => ymd.slice(0, 7);\nconst fmt = (ymd: string, o: Intl.DateTimeFormatOptions) => toUtc(ymd).toLocaleDateString(\"en-US\", { ...o, timeZone: \"UTC\" });\nconst fmtTime = (hm: string) => {\n const [h, m] = hm.split(\":\").map(Number);\n return new Date(Date.UTC(2000, 0, 1, h, m)).toLocaleTimeString(\"en-US\", { hour: \"numeric\", minute: \"2-digit\", timeZone: \"UTC\" });\n};\n\n/* ── Calendar ─────────────────────────────────────────────────────────── */\nconst WD = [\"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\", \"Su\"];\nexport function MiniCalendar({ value, today, onSelect }: { value: string | null; today: string; onSelect: (ymd: string) => void }) {\n const [view, setView] = React.useState(() => `${monthOf(value ?? today)}-01`);\n const [cursor, setCursor] = React.useState<string>(value ?? today);\n const grid = React.useRef<HTMLDivElement>(null);\n const refocus = React.useRef(false);\n const viewMonth = monthOf(view);\n /* the one tab stop: the cursor when it is in view, else the picked day, today, or the 1st */\n const stop = [cursor, value, today].find((d) => d && monthOf(d) === viewMonth) ?? view;\n const lead = (toUtc(view).getUTCDay() + 6) % 7;\n const cells = Array.from({ length: 42 }, (_, i) => addDays(view, i - lead));\n\n React.useEffect(() => {\n if (!refocus.current) return;\n refocus.current = false;\n grid.current?.querySelector<HTMLButtonElement>(`[data-day=\"${cursor}\"]`)?.focus();\n }, [cursor, view]);\n\n const go = (ymd: string) => {\n refocus.current = true;\n setCursor(ymd);\n if (monthOf(ymd) !== viewMonth) setView(`${monthOf(ymd)}-01`);\n };\n const onKeyDown = (e: React.KeyboardEvent) => {\n const from = (e.target as HTMLElement).dataset.day;\n if (!from) return;\n const dow = (toUtc(from).getUTCDay() + 6) % 7;\n const to = ({\n ArrowLeft: () => addDays(from, -1),\n ArrowRight: () => addDays(from, 1),\n ArrowUp: () => addDays(from, -7),\n ArrowDown: () => addDays(from, 7),\n Home: () => addDays(from, -dow),\n End: () => addDays(from, 6 - dow),\n PageUp: () => addMonths(from, e.shiftKey ? -12 : -1),\n PageDown: () => addMonths(from, e.shiftKey ? 12 : 1),\n } as Record<string, () => string>)[e.key];\n if (!to) return;\n e.preventDefault();\n go(to());\n };\n const page = (n: number) => {\n const next = addMonths(view, n);\n setView(next);\n setCursor(next);\n };\n\n return (\n <div className=\"w-[248px]\">\n <div className=\"mb-2 flex items-center justify-between\">\n <button type=\"button\" aria-label=\"Previous month\" onClick={() => page(-1)} className=\"flex size-7 items-center justify-center rounded-kit-md text-kit-fg-2 hover:bg-kit-hover\">\n <IconChevronLeft className=\"size-4\" stroke={1.5} />\n </button>\n <span className=\"text-kit-sm font-medium text-kit-fg\" aria-live=\"polite\">{fmt(view, { month: \"long\", year: \"numeric\" })}</span>\n <button type=\"button\" aria-label=\"Next month\" onClick={() => page(1)} className=\"flex size-7 items-center justify-center rounded-kit-md text-kit-fg-2 hover:bg-kit-hover\">\n <IconChevronRight className=\"size-4\" stroke={1.5} />\n </button>\n </div>\n <div ref={grid} role=\"group\" aria-label={fmt(view, { month: \"long\", year: \"numeric\" })} className=\"grid grid-cols-7 gap-0.5 text-center\" onKeyDown={onKeyDown}>\n {WD.map((d) => (\n <span key={d} aria-hidden className=\"pb-1 text-kit-2xs text-kit-fg-3\">{d}</span>\n ))}\n {cells.map((d) => {\n const out = monthOf(d) !== viewMonth;\n const sel = d === value;\n return (\n <button\n key={d}\n type=\"button\"\n data-day={d}\n tabIndex={d === stop ? 0 : -1}\n onClick={() => {\n setCursor(d);\n onSelect(d);\n }}\n aria-pressed={sel}\n aria-current={d === today ? \"date\" : undefined}\n aria-label={fmt(d, { weekday: \"long\", month: \"long\", day: \"numeric\", year: \"numeric\" })}\n className={cn(\n \"tabular-nums flex size-8 items-center justify-center rounded-kit-md text-kit-sm transition-colors\",\n sel ? \"bg-kit-inverse font-medium text-kit-fg-inverse\" : out ? \"text-kit-fg-4 hover:bg-kit-hover\" : \"text-kit-fg hover:bg-kit-hover\",\n !sel && d === today && \"ring-1 ring-inset ring-kit-line-strong\",\n )}\n >\n {Number(d.slice(8))}\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n\n/* ── Zone list ────────────────────────────────────────────────────────── */\n/** One searchable list: Suggested (the default zone, your zone, the value's zone) first, then every IANA zone by region. */\nfunction zoneOptions(current: string, def: { zone: string; source: string }, at: Date): SelectOption[] {\n const suggested: SelectOption[] = [];\n const seen = new Set<string>();\n const option = (z: string, group: string, description?: string): SelectOption => ({\n value: z,\n label: zoneLabel(z, at),\n description,\n group,\n keywords: [z, zoneCity(z), zoneShortOffset(z, at), ...(description ? [description] : [])],\n });\n const push = (z: string, note: string) => {\n if (seen.has(z) || !validZone(z)) return;\n seen.add(z);\n suggested.push(option(z, \"Suggested\", note));\n };\n push(def.zone, def.source === \"site\" ? \"Site time zone\" : \"Your time zone\");\n push(browserZone(), \"Your time zone\");\n push(current, \"Current\");\n return [...suggested, ...ALL_ZONES.filter((z) => !seen.has(z)).map((z) => option(z, z.includes(\"/\") ? z.split(\"/\")[0] : \"Other\"))];\n}\n\nfunction ZoneSelect({ zone, def, at, disabled, onPick }: { zone: string; def: { zone: string; source: string }; at: Date; disabled: boolean; onPick: (z: string) => void }) {\n const options = React.useMemo(() => zoneOptions(zone, def, at), [zone, def, at]);\n return (\n <Select\n aria-label=\"Time zone\"\n size=\"md\"\n className=\"min-w-0 flex-1\"\n searchable\n searchPlaceholder=\"Search city, region or offset\"\n menuClassName=\"w-[300px]\"\n value={zone}\n onValueChange={onPick}\n options={options}\n disabled={disabled}\n />\n );\n}\n\n/* ── The control ──────────────────────────────────────────────────────── */\nexport function DateControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n const withTime = field.type === \"datetime\";\n const policy = zonePolicy(field);\n const def = useDefaultZone();\n const [picked, setPicked] = React.useState<string>();\n const [open, setOpen] = React.useState(false);\n const [problem, setProblem] = React.useState<string | null>(null);\n const parsed = React.useMemo(() => parseStored(value), [value]);\n const { wall, zone } = React.useMemo(() => resolveShown(parsed, policy.mode, { fixed: policy.zone, def: def.zone, picked }), [parsed, policy.mode, policy.zone, def.zone, picked]);\n const zoned = policy.mode !== \"none\";\n const time = wall?.time ?? \"09:00\";\n const today = todayIn(zoned ? zone : undefined);\n const at = React.useMemo(() => (wall ? wallInstant(zone, wall) : new Date()), [wall, zone]);\n\n if (!parsed.readable) return <Unreadable id={id} title={field.title} value={value} />;\n\n const commit = (next: Wall, z = zone) => {\n const r = writeValue({ withTime, mode: policy.mode, wall: next, zone: z });\n if (!r.ok) {\n setProblem(r.reason);\n return false;\n }\n setProblem(null);\n onChange(r.value);\n return true;\n };\n const pickDay = (ymd: string) => {\n if (commit({ ymd, time }) && !withTime) setOpen(false);\n };\n\n const timeText = withTime && wall ? fmtTime(wall.time) : \"\";\n const showZone = zoned && withTime;\n const full = wall ? `${fmt(wall.ymd, { weekday: \"long\", month: \"long\", day: \"numeric\", year: \"numeric\" })}${timeText ? ` at ${timeText}` : \"\"}${showZone ? ` (${zoneLabel(zone, at)})` : \"\"}` : \"\";\n\n return (\n <Popover\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setProblem(null);\n }}\n >\n <PopoverTrigger\n render={\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n aria-invalid={invalid || undefined}\n aria-label={wall ? `${field.title}: ${full}. Change` : `${field.title}: pick a date`}\n className={cn(\n \"@container/date flex w-full min-w-0 items-center gap-2 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2.5 text-left text-kit-sm text-kit-fg shadow-kit-field transition-colors hover:border-kit-field-border-hover data-[popup-open]:border-kit-field-border-focus\",\n variant === \"document\" ? \"h-9\" : \"h-8\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n )}\n />\n }\n >\n <IconCalendar className=\"size-4 shrink-0 text-kit-fg-3\" stroke={1.5} aria-hidden />\n {wall ? (\n /* never truncate the date itself: drop the weekday first, then the zone (it stays in the label and popover) */\n <span className=\"flex min-w-0 flex-1 items-baseline gap-1.5 whitespace-nowrap\" data-slot=\"date-text\">\n <span className=\"shrink-0\">\n <span className=\"hidden @[260px]/date:inline\">{fmt(wall.ymd, { weekday: \"short\" })}, </span>\n {fmt(wall.ymd, { month: \"short\", day: \"numeric\", year: \"numeric\" })}\n {timeText ? <span className=\"text-kit-fg-2\"> · {timeText}</span> : null}\n </span>\n {showZone ? <span className=\"hidden min-w-0 truncate text-kit-xs text-kit-fg-3 @[200px]/date:inline\">{zoneShortOffset(zone, at)}</span> : null}\n </span>\n ) : (\n <span className=\"min-w-0 flex-1 truncate text-kit-fg-3\">{withTime ? \"Pick a date and time\" : \"Pick a date\"}</span>\n )}\n <IconChevronDown className=\"size-3.5 shrink-0 text-kit-fg-3\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n <PopoverContent className=\"w-auto\" aria-label={withTime ? `${field.title}: date and time` : `${field.title}: date`}>\n <MiniCalendar value={wall?.ymd ?? null} today={today} onSelect={pickDay} />\n {withTime ? (\n <div className=\"mt-3 flex w-[248px] flex-col gap-2 border-t border-kit-line pt-3\">\n <label className=\"flex items-center gap-2\">\n <IconClock className=\"size-4 shrink-0 text-kit-fg-3\" stroke={1.5} aria-hidden />\n <span className=\"sr-only\">Time</span>\n <input\n type=\"time\"\n value={time}\n onChange={(e) => e.target.value && commit({ ymd: wall?.ymd ?? today, time: e.target.value })}\n className=\"h-8 min-w-0 flex-1 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none hover:border-kit-field-border-hover focus:border-kit-field-border-focus\"\n aria-label=\"Time\"\n />\n </label>\n {zoned ? (\n <div className=\"flex items-center gap-2\">\n <IconWorld className=\"size-4 shrink-0 text-kit-fg-3\" stroke={1.5} aria-hidden />\n {policy.mode === \"pick\" ? (\n <ZoneSelect\n zone={zone}\n def={def}\n at={at}\n disabled={!wall}\n onPick={(z) => {\n if (!wall) return;\n // keep the wall time the author typed; the instant moves with the zone (6.4)\n if (commit(wall, z)) setPicked(z);\n }}\n />\n ) : (\n <Tooltip content={policy.mode === \"site\" ? \"Uses the site's time zone (Site settings › General).\" : \"Set by the developer for this field.\"}>\n <span tabIndex={0} className=\"flex h-8 min-w-0 flex-1 items-center gap-1.5 rounded-kit-md bg-kit-subtle px-2 text-kit-sm text-kit-fg-2 outline-none\">\n <span className=\"min-w-0 flex-1 truncate\">{zoneLabel(zone, at)}</span>\n <IconLock className=\"size-3.5 shrink-0 text-kit-fg-3\" stroke={1.5} role=\"img\" aria-label={policy.mode === \"site\" ? \"Site time zone\" : \"Fixed time zone\"} />\n </span>\n </Tooltip>\n )}\n </div>\n ) : null}\n </div>\n ) : null}\n {problem ? (\n <p role=\"alert\" className=\"mt-2 flex w-[248px] items-start gap-1.5 text-kit-xs text-kit-danger-fg\">\n <IconAlertTriangle className=\"mt-0.5 size-3.5 shrink-0\" stroke={1.5} aria-hidden />\n {problem}\n </p>\n ) : null}\n <div className=\"mt-2 flex justify-between\">\n <Button size=\"xs\" variant=\"ghost\" onClick={() => pickDay(today)}>\n Today\n </Button>\n {wall ? (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n // null, not \"\": the backend skips an empty value but refuses \"\" as \"not a valid date\"\n onChange(null);\n setProblem(null);\n setOpen(false);\n }}\n >\n Clear\n </Button>\n ) : null}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\n/** A stored value this picker cannot read: shown with the reason, kept as it is, never replaced by a stray pick. */\nfunction Unreadable({ id, title, value }: { id: string; title: string; value: unknown }) {\n const raw = typeof value === \"string\" ? value : JSON.stringify(value);\n return (\n <output\n id={id}\n tabIndex={0}\n data-slot=\"date-unreadable\"\n className=\"flex min-w-0 items-start gap-2 rounded-kit-md border border-dashed border-kit-line-strong bg-kit-subtle px-2.5 py-2 text-kit-xs text-kit-fg-2 outline-none focus-visible:outline-2 focus-visible:outline-kit-focus-ring\"\n >\n <IconAlertTriangle className=\"mt-0.5 size-3.5 shrink-0 text-kit-warning-fg\" stroke={1.5} aria-hidden />\n <span className=\"min-w-0\">\n {title} holds a value this picker can't read, so it is kept as it is:{\" \"}\n <span className=\"break-all font-kit-mono text-kit-fg\">{raw}</span>\n </span>\n </output>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Lane L3: a reference to forms only (`reference: { to: ["form"] }`, a component's `form` prop) draws the form picker
3
+ * when the host provides the project's forms; any other reference keeps the reference control. It wraps the registered
4
+ * reference control, so it imports reference-register itself: a bundler may reorder the barrel's bare imports (the
5
+ * 2.0 dist ran this one first, and reference-register then replaced the wrapper).
6
+ */
7
+ import "./reference-register";
@@ -1,14 +1,10 @@
1
1
  import { useKitServices } from "../context.js";
2
2
  import { CONTROLS } from "../engine/kit-field.js";
3
3
  import { ReferenceControl } from "./reference.js";
4
+ import "./reference-register.js";
4
5
  import { FormPickerControl, isFormOnly } from "./form-picker.js";
5
6
  import { createElement } from "react";
6
- //#region src/kit/controls/form-picker-register.ts
7
- /**
8
- * Lane L3: a reference to forms only (`reference: { to: ["form"] }`, a component's `form` prop) draws the form picker
9
- * when the host provides the project's forms; any other reference keeps the reference control. Imported after
10
- * reference-register (kit barrel), so it wraps the registered reference control.
11
- */
7
+ //#region src/controls/form-picker-register.ts
12
8
  var Reference = CONTROLS.reference ?? ReferenceControl;
13
9
  CONTROLS.reference = function ReferenceOrFormControl(props) {
14
10
  const { forms, useFormOptions } = useKitServices();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-picker-register.js","names":[],"sources":["../../src/controls/form-picker-register.ts"],"sourcesContent":["/**\n * Lane L3: a reference to forms only (`reference: { to: [\"form\"] }`, a component's `form` prop) draws the form picker\n * when the host provides the project's forms; any other reference keeps the reference control. It wraps the registered\n * reference control, so it imports reference-register itself: a bundler may reorder the barrel's bare imports (the\n * 2.0 dist ran this one first, and reference-register then replaced the wrapper).\n */\nimport \"./reference-register\";\nimport { createElement } from \"react\";\nimport type { ControlProps } from \"../types\";\nimport { useKitServices } from \"../context\";\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { ReferenceControl } from \"./reference\";\nimport { FormPickerControl, isFormOnly } from \"./form-picker\";\n\nconst Reference = CONTROLS.reference ?? ReferenceControl;\nCONTROLS.reference = function ReferenceOrFormControl(props: ControlProps) {\n const { forms, useFormOptions } = useKitServices();\n return createElement(isFormOnly(props.field) && (forms || useFormOptions) ? FormPickerControl : Reference, props);\n};\n"],"mappings":";;;;;;;AAcA,IAAM,YAAY,SAAS,aAAa;AACxC,SAAS,YAAY,SAAS,uBAAuB,OAAqB;CACxE,MAAM,EAAE,OAAO,mBAAmB,eAAe;CACjD,OAAO,cAAc,WAAW,MAAM,KAAK,MAAM,SAAS,kBAAkB,oBAAoB,WAAW,KAAK;AAClH"}
@@ -2,7 +2,7 @@ import { KitServicesProvider, useKitEnv, useKitServices } from "../context.js";
2
2
  import { ReferenceControl } from "./reference.js";
3
3
  import * as React from "react";
4
4
  import { jsx, jsxs } from "react/jsx-runtime";
5
- //#region src/kit/controls/form-picker.tsx
5
+ //#region src/controls/form-picker.tsx
6
6
  /**
7
7
  * FORM PICKER — a reference to the project's forms (`reference: { to: ["form"] }`; a component's `form` prop), drawn as
8
8
  * V2 draws it: the reference control's card and 300px search popover, its rows the host's forms (V2 read them from
@@ -62,19 +62,21 @@ function FormPickerControl(props) {
62
62
  };
63
63
  const formId = typeof props.value === "string" && props.value ? props.value : null;
64
64
  const Details = services.FormDetails;
65
+ const control = /* @__PURE__ */ jsx(KitServicesProvider, {
66
+ value,
67
+ children: /* @__PURE__ */ jsx(ReferenceControl, {
68
+ ...props,
69
+ onChange: (v) => props.onChange(v == null || v === "" ? void 0 : v)
70
+ })
71
+ });
72
+ if (!formId || !Details) return control;
65
73
  return /* @__PURE__ */ jsxs("div", {
66
74
  className: "flex min-w-0 flex-col gap-2",
67
- children: [/* @__PURE__ */ jsx(KitServicesProvider, {
68
- value,
69
- children: /* @__PURE__ */ jsx(ReferenceControl, {
70
- ...props,
71
- onChange: (v) => props.onChange(v == null || v === "" ? void 0 : v)
72
- })
73
- }), formId && Details ? /* @__PURE__ */ jsx(Details, {
75
+ children: [control, /* @__PURE__ */ jsx(Details, {
74
76
  formId,
75
77
  readOnly: props.readOnly,
76
78
  onPick: (id) => props.onChange(id)
77
- }) : null]
79
+ })]
78
80
  });
79
81
  }
80
82
  //#endregion
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-picker.js","names":[],"sources":["../../src/controls/form-picker.tsx"],"sourcesContent":["/**\n * FORM PICKER — a reference to the project's forms (`reference: { to: [\"form\"] }`; a component's `form` prop), drawn as\n * V2 draws it: the reference control's card and 300px search popover, its rows the host's forms (V2 read them from\n * `services.forms`, with \"{n} fields · {n} submissions\" under each name).\n *\n * The rows come from the host, never a seed: `forms` (V2's synchronous list) or `useFormOptions`, a React HOOK for a host\n * that loads them (the dock: GET /forms). While they load, the saved form shows its id; a failed load is said in words\n * on the card and in the picker. D58: submission counts are form data, so a viewer without `forms.submissions` sees\n * them dropped from the subtitle (V2 rule).\n *\n * Remove clears the value (`undefined`): a form prop stores `{ formId }` or nothing, never a null envelope.\n * `FormDetails`, when the host has one, draws under a chosen form (where the form renders on the site, editing its fields).\n */\nimport * as React from \"react\";\nimport { KitServicesProvider, useKitEnv, useKitServices, type KitServices } from \"../context\";\nimport type { FieldSchema } from \"../schema/types\";\nimport type { ControlProps } from \"../types\";\nimport { ReferenceControl } from \"./reference\";\nimport type { KitReferenceOption, KitReferenceQuery } from \"./reference-services\";\n\nexport interface KitFormOption {\n id: string;\n title: string;\n /** \"5 fields · 128 submissions\" */\n subtitle?: string;\n /** \"draft\" shows the Draft chip (a draft form refuses submissions) */\n status?: string | null;\n}\n\ndeclare module \"../context\" {\n interface KitServices {\n /** A React HOOK: the project's forms, for a host that loads them. One identity for the life of the form. */\n useFormOptions?: () => { forms: KitFormOption[]; loading?: boolean; error?: string };\n /** Drawn under a chosen form: the host's own detail for it (where it renders, its fields). */\n FormDetails?: React.ComponentType<{ formId: string; readOnly?: boolean; onPick?: (formId: string) => void }>;\n }\n}\n\n/** A reference whose only target is forms (no filter: a filtered one stays on the reference search). */\nexport const isFormOnly = (field: FieldSchema) => {\n const to = field.reference?.to ?? [];\n return to.length === 1 && to[0] === \"form\" && !field.reference?.filter;\n};\n\nconst SUBMISSIONS = / · [\\d,]+ submissions?$/;\n\nfunction useFormRows(services: KitServices): { forms: KitFormOption[] | null; error?: string } {\n const loaded = services.useFormOptions ? services.useFormOptions() : null;\n if (loaded) return { forms: loaded.loading ? null : loaded.forms, error: loaded.error };\n return { forms: services.forms?.() ?? [] };\n}\n\nexport function FormPickerControl(props: ControlProps) {\n const services = useKitServices();\n const subs = useKitEnv().can(\"forms.submissions\");\n const { forms, error } = useFormRows(services);\n // by content: `forms()` may hand back a new list on every render, and the search must keep one identity (the picker\n // searches again whenever it changes)\n const rowsKey = JSON.stringify(forms);\n const options = React.useMemo<KitReferenceOption[] | null>(\n () =>\n forms?.map((f) => ({ id: f.id, kind: \"form\" as const, title: f.title, subtitle: (subs ? f.subtitle : f.subtitle?.replace(SUBMISSIONS, \"\")) || null, status: f.status ?? null })) ?? null,\n [rowsKey, subs], // eslint-disable-line react-hooks/exhaustive-deps\n );\n // the reference control over these rows: search by name, read the saved id back. While the forms load there is no\n // lookup, so the card shows the saved id (never a \"Missing\" that is only \"not loaded yet\").\n const reads = React.useMemo(() => {\n const fail = () => Promise.reject(new Error(error));\n return {\n searchReferences: error\n ? fail\n : async (q: KitReferenceQuery) => {\n const t = q.q.trim().toLowerCase();\n const rows = (options ?? []).filter((o) => o.id !== q.excludeId && (!t || o.title.toLowerCase().includes(t)));\n return { options: rows.slice(0, q.limit), truncated: false };\n },\n lookupReferences: error ? fail : options ? async (ids: string[]) => options.filter((o) => ids.includes(o.id)) : undefined,\n };\n }, [options, error]);\n const value: KitServices = { ...services, ...reads, createReference: undefined };\n const formId = typeof props.value === \"string\" && props.value ? props.value : null;\n const Details = services.FormDetails;\n const control = (\n <KitServicesProvider value={value}>\n <ReferenceControl {...props} onChange={(v) => props.onChange(v == null || v === \"\" ? undefined : v)} />\n </KitServicesProvider>\n );\n // V2 draws the reference control alone; only the host's details under a chosen form need the stack\n if (!formId || !Details) return control;\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n {control}\n <Details formId={formId} readOnly={props.readOnly} onPick={(id) => props.onChange(id)} />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuCA,IAAa,cAAc,UAAuB;CAChD,MAAM,KAAK,MAAM,WAAW,MAAM,CAAC;CACnC,OAAO,GAAG,WAAW,KAAK,GAAG,OAAO,UAAU,CAAC,MAAM,WAAW;AAClE;AAEA,IAAM,cAAc;AAEpB,SAAS,YAAY,UAA0E;CAC7F,MAAM,SAAS,SAAS,iBAAiB,SAAS,eAAe,IAAI;CACrE,IAAI,QAAQ,OAAO;EAAE,OAAO,OAAO,UAAU,OAAO,OAAO;EAAO,OAAO,OAAO;CAAM;CACtF,OAAO,EAAE,OAAO,SAAS,QAAQ,KAAK,CAAC,EAAE;AAC3C;AAEA,SAAgB,kBAAkB,OAAqB;CACrD,MAAM,WAAW,eAAe;CAChC,MAAM,OAAO,UAAU,CAAC,CAAC,IAAI,mBAAmB;CAChD,MAAM,EAAE,OAAO,UAAU,YAAY,QAAQ;CAG7C,MAAM,UAAU,KAAK,UAAU,KAAK;CACpC,MAAM,UAAU,MAAM,cAElB,OAAO,KAAK,OAAO;EAAE,IAAI,EAAE;EAAI,MAAM;EAAiB,OAAO,EAAE;EAAO,WAAW,OAAO,EAAE,WAAW,EAAE,UAAU,QAAQ,aAAa,EAAE,MAAM;EAAM,QAAQ,EAAE,UAAU;CAAK,EAAE,KAAK,MACtL,CAAC,SAAS,IAAI,CAChB;CAGA,MAAM,QAAQ,MAAM,cAAc;EAChC,MAAM,aAAa,QAAQ,OAAO,IAAI,MAAM,KAAK,CAAC;EAClD,OAAO;GACL,kBAAkB,QACd,OACA,OAAO,MAAyB;IAC9B,MAAM,IAAI,EAAE,EAAE,KAAK,CAAC,CAAC,YAAY;IAEjC,OAAO;KAAE,UADK,WAAW,CAAC,EAAA,CAAG,QAAQ,MAAM,EAAE,OAAO,EAAE,cAAc,CAAC,KAAK,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,EACxF,CAAA,CAAK,MAAM,GAAG,EAAE,KAAK;KAAG,WAAW;IAAM;GAC7D;GACJ,kBAAkB,QAAQ,OAAO,UAAU,OAAO,QAAkB,QAAQ,QAAQ,MAAM,IAAI,SAAS,EAAE,EAAE,CAAC,IAAI,KAAA;EAClH;CACF,GAAG,CAAC,SAAS,KAAK,CAAC;CACnB,MAAM,QAAqB;EAAE,GAAG;EAAU,GAAG;EAAO,iBAAiB,KAAA;CAAU;CAC/E,MAAM,SAAS,OAAO,MAAM,UAAU,YAAY,MAAM,QAAQ,MAAM,QAAQ;CAC9E,MAAM,UAAU,SAAS;CACzB,MAAM,UACJ,oBAAC,qBAAD;EAA4B;EAC1B,UAAA,oBAAC,kBAAD;GAAkB,GAAI;GAAO,WAAW,MAAM,MAAM,SAAS,KAAK,QAAQ,MAAM,KAAK,KAAA,IAAY,CAAC;EAAI,CAAA;CACnF,CAAA;CAGvB,IAAI,CAAC,UAAU,CAAC,SAAS,OAAO;CAChC,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACG,SACD,oBAAC,SAAD;GAAiB;GAAQ,UAAU,MAAM;GAAU,SAAS,OAAO,MAAM,SAAS,EAAE;EAAI,CAAA,CACrF;;AAET"}
@@ -1,6 +1,6 @@
1
1
  import { CONTROLS } from "../engine/kit-field.js";
2
2
  import { IconControl } from "./icon.js";
3
- //#region src/kit/controls/icon-register.ts
3
+ //#region src/controls/icon-register.ts
4
4
  /** Lane C3: the icon field in the engine's dispatch table (one line per type; merge with other lanes by line). */
5
5
  CONTROLS.icon = IconControl;
6
6
  //#endregion
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon-register.js","names":[],"sources":["../../src/controls/icon-register.ts"],"sourcesContent":["/** Lane C3: the icon field in the engine's dispatch table (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { IconControl } from \"./icon\";\n\nCONTROLS.icon = IconControl;\n"],"mappings":";;;;AAIA,SAAS,OAAO"}
@@ -29,10 +29,12 @@ declare module "../context" {
29
29
  }>;
30
30
  }
31
31
  }
32
- /** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin. */
33
- export declare function IconPicker({ value, onPick, onChooseMedia }: {
32
+ /** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin.
33
+ * `field`: the icon field's popover (V2 IconFieldPicker, a 22rem list); otherwise the app-UI grid (V2 IconPickerGrid, max-h-56). */
34
+ export declare function IconPicker({ value, onPick, onChooseMedia, field }: {
34
35
  value?: string;
35
36
  onPick: (name: string | null) => void;
36
37
  onChooseMedia?: () => void;
38
+ field?: boolean;
37
39
  }): import("react/jsx-runtime").JSX.Element;
38
40
  export declare function IconControl({ field, value, onChange, readOnly, id, invalid }: ControlProps): import("react/jsx-runtime").JSX.Element;
@@ -1,17 +1,17 @@
1
+ import { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from "../adapters/prod-types.js";
2
+ import { tablerIconOf } from "../adapters/icons.js";
1
3
  import { cn } from "../lib/cn.js";
4
+ import { useKitServices } from "../context.js";
2
5
  import { isObj } from "../lib/path.js";
3
6
  import { iconLabel } from "../lib/icons.js";
4
- import { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from "../adapters/prod-types.js";
5
- import { useKitServices } from "../context.js";
6
7
  import { TooltipLayer } from "../ui/tooltip-root.js";
7
8
  import { Button } from "../ui/button.js";
8
9
  import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay.js";
9
- import { tablerIconOf } from "../adapters/icons.js";
10
10
  import * as React from "react";
11
- import { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from "@tabler/icons-react";
12
11
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ import { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from "@tabler/icons-react";
13
13
  import { Tooltip } from "@base-ui/react/tooltip";
14
- //#region src/kit/controls/icon.tsx
14
+ //#region src/controls/icon.tsx
15
15
  /**
16
16
  * ICON — the icon field (DESIGN 8.14), V2 controls/icon.tsx fitted to what prod stores.
17
17
  *
@@ -153,15 +153,16 @@ function IconGrid({ items, selected, onPick, label, tip }) {
153
153
  "aria-label": it.label,
154
154
  tabIndex: it.key === stop ? 0 : -1,
155
155
  onClick: () => onPick(it.key),
156
- className: cn("flex aspect-square min-w-0 items-center justify-center overflow-hidden rounded-kit-md text-kit-fg-2 outline-none transition-colors hover:bg-kit-hover hover:text-kit-fg focus-visible:outline-2 focus-visible:outline-kit-focus-ring", it.key === selected && "bg-kit-selected text-kit-fg ring-1 ring-inset ring-kit-line-strong"),
156
+ className: cn("flex aspect-square items-center justify-center rounded-kit-md text-kit-fg-2 transition-colors hover:bg-kit-hover hover:text-kit-fg", it.key === selected && "bg-kit-selected text-kit-fg ring-1 ring-inset ring-kit-line-strong"),
157
157
  children: it.node
158
158
  })
159
159
  }, it.key))
160
160
  });
161
161
  }
162
162
  var NONE = "__none";
163
- /** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin. */
164
- function IconPicker({ value, onPick, onChooseMedia }) {
163
+ /** The picker: search, Recent, then the whole set ("No icon" first). Search spans the name and its Tabler twin.
164
+ * `field`: the icon field's popover (V2 IconFieldPicker, a 22rem list); otherwise the app-UI grid (V2 IconPickerGrid, max-h-56). */
165
+ function IconPicker({ value, onPick, onChooseMedia, field }) {
165
166
  const [q, setQ] = React.useState("");
166
167
  const root = React.useRef(null);
167
168
  const tip = React.useMemo(() => Tooltip.createHandle(), []);
@@ -209,20 +210,23 @@ function IconPicker({ value, onPick, onChooseMedia }) {
209
210
  })]
210
211
  }),
211
212
  /* @__PURE__ */ jsx("div", {
212
- className: "max-h-56 overflow-y-auto pr-0.5",
213
- children: needle ? hits.length ? /* @__PURE__ */ jsx(IconGrid, {
214
- label: "Icons",
215
- selected: value,
216
- onPick: pick,
217
- tip,
218
- items: hits.map(item)
219
- }) : /* @__PURE__ */ jsxs("p", {
220
- className: "py-6 text-center text-kit-sm text-kit-fg-3",
221
- children: [
222
- "No icons match “",
223
- q.trim(),
224
- "”"
225
- ]
213
+ className: field ? "max-h-[22rem] overflow-y-auto pr-0.5" : "max-h-56 overflow-y-auto pr-0.5",
214
+ children: needle ? /* @__PURE__ */ jsx("div", {
215
+ className: "flex flex-col gap-2",
216
+ children: hits.length ? /* @__PURE__ */ jsx(Group, { children: /* @__PURE__ */ jsx(IconGrid, {
217
+ label: "Icons",
218
+ selected: value,
219
+ onPick: pick,
220
+ tip,
221
+ items: hits.map(item)
222
+ }) }) : /* @__PURE__ */ jsxs("p", {
223
+ className: "py-6 text-center text-kit-sm text-kit-fg-3",
224
+ children: [
225
+ "No icons match “",
226
+ q.trim(),
227
+ "”"
228
+ ]
229
+ })
226
230
  }) : /* @__PURE__ */ jsxs("div", {
227
231
  className: "flex flex-col gap-2",
228
232
  children: [recent.length ? /* @__PURE__ */ jsx(Group, {
@@ -312,11 +316,11 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
312
316
  type: "button",
313
317
  disabled: readOnly,
314
318
  "aria-invalid": invalid || void 0,
315
- className: cn("flex h-8 w-full min-w-0 items-center gap-2.5 rounded-kit-md border bg-kit-field-bg px-1 pr-2.5 text-left text-kit-sm outline-none transition-colors disabled:opacity-60 focus-visible:border-kit-field-border-focus", invalid ? "border-[var(--kit-field-invalid)]" : "border-kit-line-strong hover:border-kit-field-border-hover data-[popup-open]:border-kit-field-border-focus")
319
+ className: cn("flex h-8 w-full items-center gap-2.5 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-1 pr-2.5 text-left text-kit-sm transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg", invalid && "border-[var(--kit-field-invalid)]")
316
320
  }),
317
321
  children: [
318
322
  /* @__PURE__ */ jsx("span", {
319
- className: "flex size-6 shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg",
323
+ className: "flex size-6 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg",
320
324
  children: tile
321
325
  }),
322
326
  /* @__PURE__ */ jsx("span", {
@@ -324,16 +328,17 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
324
328
  children: text
325
329
  }),
326
330
  /* @__PURE__ */ jsx(IconChevronDown, {
327
- className: "size-3.5 shrink-0 text-kit-fg-3",
331
+ className: "size-3.5 text-kit-fg-3",
328
332
  stroke: 1.5,
329
333
  "aria-hidden": true
330
334
  })
331
335
  ]
332
336
  }), /* @__PURE__ */ jsx(PopoverContent, {
333
- className: "w-[312px] p-2",
337
+ className: "w-[320px] p-2",
334
338
  align: "start",
335
339
  "aria-label": `${field.title}: choose an icon`,
336
340
  children: /* @__PURE__ */ jsx(IconPicker, {
341
+ field: true,
337
342
  value: read.kind === "name" ? read.name : read.kind === "empty" ? void 0 : "",
338
343
  onPick: commit,
339
344
  onChooseMedia: MediaPicker ? () => {
@@ -350,6 +355,6 @@ function IconControl({ field, value, onChange, readOnly, id, invalid }) {
350
355
  }) : null] });
351
356
  }
352
357
  //#endregion
353
- export { IconControl };
358
+ export { IconControl, IconPicker };
354
359
 
355
360
  //# sourceMappingURL=icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icon.js","names":[],"sources":["../../src/controls/icon.tsx"],"sourcesContent":["/**\n * ICON — the icon field (DESIGN 8.14), V2 controls/icon.tsx fitted to what prod stores.\n *\n * Values (backend reference-validation `icon`, the classic PropsPanel IconValueInput):\n * \"arrow-right\" a name from the BetterCMS icon set (DOCK_ICON_NAMES, 472 names)\n * \"https://…/logo.svg\" an uploaded icon: an image URL (picked from the media library; a component prop\n * stores the URL string, like the classic panel's codec=\"url\")\n * { url, … } an uploaded icon stored as an image value: shown and kept until replaced\n * null no icon (\"No icon\"; the backend skips an empty value)\n *\n * The grid offers the BetterCMS set, the one prod accepts. Search also matches a name's Tabler twin through the\n * Tabler ↔ dock adapter (adapters/icons.ts), so \"map\" finds earth-americas. A stored name outside the set (a stale\n * Tabler or Lucide name) is shown with its reason and kept until the author picks another.\n *\n * Glyphs: the host draws them (KitServices.IconGlyph: the dashboard's DockIcon, the set the site renders). With no\n * host renderer the kit draws the Tabler twin, loaded on first use; a name with no Tabler twin shows its name.\n */\nimport * as React from \"react\";\nimport type { Icon as TablerIcon } from \"@tabler/icons-react\";\nimport { IconAlertTriangle, IconChevronDown, IconPhoto, IconSearch, IconX } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { iconLabel } from \"../lib/icons\";\nimport { useKitServices } from \"../context\";\nimport { DOCK_ICON_NAMES, DOCK_ICON_NAME_SET } from \"../adapters/prod-types\";\nimport { tablerIconOf } from \"../adapters/icons\";\nimport type { ControlProps } from \"../types\";\nimport { Button } from \"../ui/button\";\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { TooltipLayer } from \"../ui/tooltip-root\";\n\n/* ── Glyphs ───────────────────────────────────────────────────────────── */\ndeclare module \"../context\" {\n interface KitServices {\n /**\n * Draws one icon of the BetterCMS set by name, aria-hidden (the name beside it is the accessible text): the glyphs\n * the site renders. The dashboard passes `DockIcon` (src/components/dock/DockIcon). Absent → the Tabler twin.\n */\n IconGlyph?: React.ComponentType<{ name: string; className?: string }>;\n }\n}\n\nlet tablerSet: Record<string, unknown> | null = null;\nlet tablerLoad: Promise<void> | null = null;\nconst pascal = (kebab: string) => `Icon${kebab.split(\"-\").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(\"\")}`;\n\n/** The full Tabler set, loaded once and only when no host renderer is provided. */\nfunction useTablerSet(need: boolean): Record<string, unknown> | null {\n const [, landed] = React.useReducer((n: number) => n + 1, 0);\n React.useEffect(() => {\n if (!need || tablerSet) return;\n let live = true;\n tablerLoad ??= import(\"@tabler/icons-react\").then((m) => {\n tablerSet = m as unknown as Record<string, unknown>;\n });\n tablerLoad.then(() => live && landed(), () => {});\n return () => {\n live = false;\n };\n }, [need]);\n return tablerSet;\n}\n\nfunction Glyph({ name, className }: { name: string; className?: string }) {\n const Host = useKitServices().IconGlyph;\n const set = useTablerSet(!Host);\n if (Host) return <Host name={name} className={className} />;\n const T = set?.[pascal(tablerIconOf(name))] as TablerIcon | undefined;\n if (T) return <T className={className} stroke={1.5} aria-hidden />;\n // no Tabler twin (or the set is still loading): the name itself, never a stand-in shape\n return (\n <span aria-hidden className=\"max-w-full truncate px-0.5 text-[9px] leading-3 text-kit-fg-3\">\n {name}\n </span>\n );\n}\n\n/* ── Values ───────────────────────────────────────────────────────────── */\ntype Read =\n | { kind: \"empty\" }\n | { kind: \"name\"; name: string }\n | { kind: \"unknown\"; name: string }\n | { kind: \"upload\"; url: string }\n | { kind: \"unreadable\" };\nconst isUrlish = (s: string) => /[/.]/.test(s);\nfunction readIcon(v: unknown): Read {\n if (v == null || v === \"\") return { kind: \"empty\" };\n if (typeof v === \"string\") return DOCK_ICON_NAME_SET.has(v) ? { kind: \"name\", name: v } : isUrlish(v) ? { kind: \"upload\", url: v } : { kind: \"unknown\", name: v };\n if (isObj(v) && typeof v.url === \"string\" && v.url) return { kind: \"upload\", url: v.url };\n return { kind: \"unreadable\" };\n}\nconst fileName = (url: string) => decodeURIComponent(url.split(/[?#]/)[0].split(\"/\").pop() || url);\n\n/** Names picked this session, newest first (shown as \"Recent\"). */\nconst recents: string[] = [];\nconst pushRecent = (name: string) => {\n const i = recents.indexOf(name);\n if (i !== -1) recents.splice(i, 1);\n recents.unshift(name);\n recents.length = Math.min(recents.length, COLS);\n};\n\n/* ── The grid: one tab stop, arrow keys, Home / End ───────────────────── */\nconst COLS = 8;\nconst norm = (q: string) => q.toLowerCase().trim().replace(/\\s+/g, \"-\");\ninterface GridItem {\n key: string;\n label: string;\n node: React.ReactNode;\n}\n\ntype TipHandle = ReturnType<typeof TooltipPrimitive.createHandle<string>>;\n\n/** Up / down within a grid keep the column; past its edge they land in the same column of the next / previous grid. */\nfunction verticalTarget(grids: HTMLButtonElement[][], g: number, j: number, down: boolean): HTMLButtonElement | \"search\" | undefined {\n const col = j % COLS;\n const cur = grids[g];\n const within = down ? j + COLS : j - COLS;\n if (within >= 0 && within < cur.length) return cur[within];\n if (down && Math.floor(j / COLS) < Math.floor((cur.length - 1) / COLS)) return cur[cur.length - 1]; // a short last row\n const next = grids[down ? g + 1 : g - 1];\n if (!next) return down ? undefined : \"search\";\n if (down) return next[Math.min(col, next.length - 1)];\n const lastRow = Math.floor((next.length - 1) / COLS) * COLS;\n return next[Math.min(lastRow + col, next.length - 1)];\n}\n\nfunction IconGrid({ items, selected, onPick, label, tip }: { items: GridItem[]; selected?: string; onPick: (key: string) => void; label: string; tip: TipHandle }) {\n const ref = React.useRef<HTMLDivElement>(null);\n const stop = items.some((i) => i.key === selected) ? selected : items[0]?.key;\n const move = (e: React.KeyboardEvent) => {\n // one keyboard space across every group in the picker (Recent, the set, search results)\n const scope = ref.current?.closest(\"[data-icon-picker]\") ?? ref.current;\n const grids = Array.from(scope?.querySelectorAll<HTMLElement>(\"[data-icon-grid]\") ?? []).map((g) => Array.from(g.querySelectorAll<HTMLButtonElement>(\"[data-grid-item]\")));\n const btns = grids.flat();\n const i = btns.indexOf(document.activeElement as HTMLButtonElement);\n if (i === -1) return;\n const g = grids.findIndex((list) => list.includes(btns[i]));\n const j = grids[g].indexOf(btns[i]);\n let to: HTMLButtonElement | \"search\" | undefined;\n if (e.key === \"ArrowRight\") to = btns[Math.min(i + 1, btns.length - 1)];\n else if (e.key === \"ArrowLeft\") to = btns[Math.max(i - 1, 0)];\n else if (e.key === \"Home\") to = btns[0];\n else if (e.key === \"End\") to = btns[btns.length - 1];\n else if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") to = verticalTarget(grids, g, j, e.key === \"ArrowDown\") ?? btns[i];\n else return;\n e.preventDefault();\n if (to === \"search\") scope?.querySelector<HTMLInputElement>(\"input[data-icon-search]\")?.focus();\n else to?.focus();\n };\n return (\n <div ref={ref} data-icon-grid className=\"grid gap-0.5\" style={{ gridTemplateColumns: `repeat(${COLS}, minmax(0, 1fr))` }} role=\"listbox\" aria-label={label} onKeyDown={move}>\n {items.map((it) => (\n // one shared tooltip for the whole picker (hundreds of icons): each trigger hands it its label\n <TooltipPrimitive.Trigger\n key={it.key}\n handle={tip}\n payload={it.label}\n delay={500}\n render={\n <button\n type=\"button\"\n role=\"option\"\n data-grid-item\n data-icon={it.key}\n aria-selected={it.key === selected}\n aria-label={it.label}\n tabIndex={it.key === stop ? 0 : -1}\n onClick={() => onPick(it.key)}\n className={cn(\n \"flex aspect-square items-center justify-center rounded-kit-md text-kit-fg-2 transition-colors hover:bg-kit-hover hover:text-kit-fg\",\n it.key === selected && \"bg-kit-selected text-kit-fg ring-1 ring-inset ring-kit-line-strong\",\n )}\n >\n {it.node}\n </button>\n }\n />\n ))}\n </div>\n );\n}\n\nconst NONE = \"__none\";\n\n/** The picker: search, Recent, then the whole set (\"No icon\" first). Search spans the name and its Tabler twin.\n * `field`: the icon field's popover (V2 IconFieldPicker, a 22rem list); otherwise the app-UI grid (V2 IconPickerGrid, max-h-56). */\nexport function IconPicker({ value, onPick, onChooseMedia, field }: { value?: string; onPick: (name: string | null) => void; onChooseMedia?: () => void; field?: boolean }) {\n const [q, setQ] = React.useState(\"\");\n const root = React.useRef<HTMLDivElement>(null);\n const tip = React.useMemo(() => TooltipPrimitive.createHandle<string>(), []);\n const needle = norm(q);\n const item = (name: string): GridItem => ({ key: name, label: iconLabel(name), node: <Glyph name={name} className=\"size-[18px]\" /> });\n const pick = (key: string) => onPick(key === NONE ? null : key);\n const hits = needle ? DOCK_ICON_NAMES.filter((n) => n.includes(needle) || tablerIconOf(n).includes(needle)) : [];\n const recent = recents.filter((n) => DOCK_ICON_NAME_SET.has(n));\n return (\n <div ref={root} data-icon-picker className=\"flex flex-col gap-2\">\n <TooltipPrimitive.Root handle={tip}>{({ payload }) => (payload ? <TooltipLayer>{payload}</TooltipLayer> : null)}</TooltipPrimitive.Root>\n <label className=\"flex h-8 items-center gap-2 rounded-kit-md bg-kit-muted px-2.5 text-kit-fg-3 focus-within:bg-kit-field-bg focus-within:ring-1 focus-within:ring-kit-line-strong\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n data-icon-search\n value={q}\n onChange={(e) => setQ(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n root.current?.querySelector<HTMLButtonElement>(\"[data-grid-item]\")?.focus();\n }\n }}\n placeholder=\"Search icons\"\n aria-label=\"Search icons\"\n className=\"h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n </label>\n <div className={field ? \"max-h-[22rem] overflow-y-auto pr-0.5\" : \"max-h-56 overflow-y-auto pr-0.5\"}>\n {needle ? (\n <div className=\"flex flex-col gap-2\">\n {hits.length ? (\n <Group>\n <IconGrid label=\"Icons\" selected={value} onPick={pick} tip={tip} items={hits.map(item)} />\n </Group>\n ) : (\n <p className=\"py-6 text-center text-kit-sm text-kit-fg-3\">No icons match “{q.trim()}”</p>\n )}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {recent.length ? (\n <Group title=\"Recent\">\n <IconGrid label=\"Recent icons\" selected={value} onPick={pick} tip={tip} items={recent.map(item)} />\n </Group>\n ) : null}\n <Group title={recent.length ? \"All icons\" : undefined}>\n <IconGrid\n label=\"Icons\"\n selected={value ?? NONE}\n onPick={pick}\n tip={tip}\n items={[{ key: NONE, label: \"No icon\", node: <IconX className=\"size-4\" stroke={1.5} aria-hidden /> }, ...DOCK_ICON_NAMES.map(item)]}\n />\n </Group>\n </div>\n )}\n </div>\n {onChooseMedia ? (\n <div className=\"flex items-center justify-between gap-2 border-t border-kit-line pt-2\">\n <span className=\"whitespace-nowrap text-kit-xs text-kit-fg-3\">Images keep their colours.</span>\n <Button size=\"xs\" variant=\"ghost\" leftIcon={<IconPhoto stroke={1.5} />} onClick={onChooseMedia}>\n Choose from media\n </Button>\n </div>\n ) : null}\n </div>\n );\n}\n\nfunction Group({ title, children }: { title?: string; children: React.ReactNode }) {\n return (\n <div className=\"flex flex-col gap-1\">\n {title ? <div className=\"px-0.5 text-kit-2xs font-medium text-kit-fg-3\">{title}</div> : null}\n {children}\n </div>\n );\n}\n\n/* ── The control ──────────────────────────────────────────────────────── */\nexport function IconControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { MediaPicker, mediaSrc } = useKitServices();\n const [open, setOpen] = React.useState(false);\n const [mediaOpen, setMediaOpen] = React.useState(false);\n const read = readIcon(value);\n\n const commit = (v: string | null) => {\n onChange(v);\n if (v && DOCK_ICON_NAME_SET.has(v)) pushRecent(v);\n setOpen(false);\n };\n\n const tile =\n read.kind === \"name\" ? (\n <Glyph name={read.name} className=\"size-4\" />\n ) : read.kind === \"upload\" ? (\n <img src={mediaSrc ? mediaSrc(read.url) : read.url} alt=\"\" className=\"size-4 object-contain\" />\n ) : read.kind === \"empty\" ? (\n <span className=\"size-3 rounded-kit-md border border-dashed border-[var(--kit-emphasis-line)]\" />\n ) : (\n <IconAlertTriangle className=\"size-3.5 text-kit-warning-fg\" stroke={1.5} aria-hidden />\n );\n const text =\n read.kind === \"name\"\n ? iconLabel(read.name)\n : read.kind === \"upload\"\n ? fileName(read.url)\n : read.kind === \"unknown\"\n ? `“${read.name}” isn't in the icon set`\n : read.kind === \"unreadable\"\n ? \"This value isn't an icon this picker can read\"\n : \"Choose an icon\";\n const warn = read.kind === \"unknown\" || read.kind === \"unreadable\";\n\n return (\n <>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n render={\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n aria-invalid={invalid || undefined}\n className={cn(\n \"flex h-8 w-full items-center gap-2.5 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-1 pr-2.5 text-left text-kit-sm transition-colors hover:border-kit-line-strong data-[popup-open]:border-kit-line-strong data-[popup-open]:bg-kit-field-bg\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n )}\n />\n }\n >\n <span className=\"flex size-6 items-center justify-center rounded-kit-md border border-kit-line bg-kit-control-bg text-kit-fg\">{tile}</span>\n <span className={cn(\"min-w-0 flex-1 truncate\", warn ? \"text-kit-warning-fg\" : read.kind === \"empty\" ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{text}</span>\n <IconChevronDown className=\"size-3.5 text-kit-fg-3\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n <PopoverContent className=\"w-[320px] p-2\" align=\"start\" aria-label={`${field.title}: choose an icon`}>\n <IconPicker\n field\n value={read.kind === \"name\" ? read.name : read.kind === \"empty\" ? undefined : \"\"}\n onPick={commit}\n onChooseMedia={\n MediaPicker\n ? () => {\n setOpen(false);\n setMediaOpen(true);\n }\n : undefined\n }\n />\n </PopoverContent>\n </Popover>\n {MediaPicker && mediaOpen ? (\n <MediaPicker open={mediaOpen} onOpenChange={setMediaOpen} accept={[\"svg\", \"image\"]} onPick={(assets) => assets[0]?.url && commit(assets[0].url)} />\n ) : null}\n </>\n );\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  export * from "./c1";
2
2
  export * from "./c2";
3
3
  export { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, type LinkTarget, type KitLinkServices, type SectionAnchor } from "./link";
4
- export { ButtonControl, ButtonScreen } from "./button";
4
+ export { ButtonControl, ButtonLinkEditor, ButtonScreen } from "./button";
5
5
  export declare function registerKitControls(): void;
@@ -1,10 +1,10 @@
1
1
  import { __exportAll } from "../_virtual/_rolldown/runtime.js";
2
2
  import { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider } from "./link.js";
3
- import { ButtonControl, ButtonScreen } from "./button.js";
3
+ import { ButtonControl, ButtonLinkEditor, ButtonScreen } from "./button.js";
4
4
  import { CONTROLS } from "../engine/kit-field.js";
5
5
  import { C1_ACTIONS, C1_CONTROLS, registerC1Controls } from "./c1.js";
6
6
  import { C2_CONTROLS, registerC2Controls } from "./c2.js";
7
- //#region src/kit/controls/index.ts
7
+ //#region src/controls/index.ts
8
8
  /**
9
9
  * The ported kit controls, and the one call that puts them in the engine's CONTROLS / ACTIONS tables (and the scale
10
10
  * capsule into the number control). A registered type stops drawing the host's legacy control; a type nobody
@@ -12,6 +12,7 @@ import { C2_CONTROLS, registerC2Controls } from "./c2.js";
12
12
  */
13
13
  var controls_exports = /* @__PURE__ */ __exportAll({
14
14
  ButtonControl: () => ButtonControl,
15
+ ButtonLinkEditor: () => ButtonLinkEditor,
15
16
  ButtonScreen: () => ButtonScreen,
16
17
  C1_ACTIONS: () => C1_ACTIONS,
17
18
  C1_CONTROLS: () => C1_CONTROLS,
@@ -32,6 +33,6 @@ function registerKitControls() {
32
33
  CONTROLS.button = ButtonControl;
33
34
  }
34
35
  //#endregion
35
- export { controls_exports, registerKitControls };
36
+ export { ButtonControl, ButtonLinkEditor, ButtonScreen, C1_ACTIONS, C1_CONTROLS, C2_CONTROLS, LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, controls_exports, registerC1Controls, registerC2Controls, registerKitControls };
36
37
 
37
38
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/controls/index.ts"],"sourcesContent":["/**\n * The ported kit controls, and the one call that puts them in the engine's CONTROLS / ACTIONS tables (and the scale\n * capsule into the number control). A registered type stops drawing the host's legacy control; a type nobody\n * registers keeps it. The kit barrel calls `registerKitControls()` once, so every host that imports the kit gets them.\n */\nimport { ButtonControl } from \"./button\";\nimport { LinkControl } from \"./link\";\nimport { registerC1Controls } from \"./c1\";\nimport { registerC2Controls } from \"./c2\";\nimport { CONTROLS } from \"../engine/kit-field\";\n\nexport * from \"./c1\";\nexport * from \"./c2\";\nexport { LinkControl, LinkField, LinkForm, LinkLine, SectionAnchorsProvider, type LinkTarget, type KitLinkServices, type SectionAnchor } from \"./link\";\nexport { ButtonControl, ButtonLinkEditor, ButtonScreen } from \"./button\";\n\nexport function registerKitControls() {\n registerC1Controls();\n registerC2Controls();\n CONTROLS.link = LinkControl;\n CONTROLS.button = ButtonControl;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAgB,sBAAsB;CACpC,mBAAmB;CACnB,mBAAmB;CACnB,SAAS,OAAO;CAChB,SAAS,SAAS;AACpB"}
@@ -1,6 +1,6 @@
1
1
  import { JsonControl } from "./json.js";
2
2
  import { CONTROLS } from "../engine/kit-field.js";
3
- //#region src/kit/controls/json-register.ts
3
+ //#region src/controls/json-register.ts
4
4
  /** Lane C3: the json field in the engine's dispatch table (one line per type; merge with other lanes by line). */
5
5
  CONTROLS.json = JsonControl;
6
6
  //#endregion
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-register.js","names":[],"sources":["../../src/controls/json-register.ts"],"sourcesContent":["/** Lane C3: the json field in the engine's dispatch table (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { JsonControl } from \"./json\";\n\nCONTROLS.json = JsonControl;\n"],"mappings":";;;;AAIA,SAAS,OAAO"}
@@ -2,7 +2,7 @@ import { useKitEnv } from "../context.js";
2
2
  import { CodeDialogField, CodeSurface, jsonProblem } from "./code.js";
3
3
  import * as React from "react";
4
4
  import { jsx } from "react/jsx-runtime";
5
- //#region src/kit/controls/json.tsx
5
+ //#region src/controls/json.tsx
6
6
  /**
7
7
  * JSON — the json field (DESIGN 8.21), on the code surface (code.tsx).
8
8
  *
@@ -11,8 +11,18 @@ import { jsx } from "react/jsx-runtime";
11
11
  * Text that does not parse is never written: the panel's Done refuses with "Invalid JSON · {reason}", the inline
12
12
  * (document) surface keeps the last valid value and shows the reason under the code.
13
13
  */
14
- /** The text a stored JSON value is edited as. */
15
- var jsonText = (v) => v == null || v === "" ? "" : typeof v === "string" ? v : JSON.stringify(v, null, 2);
14
+ /** The text a stored JSON value is edited as. A stored string that is JSON text stays as written; any other string is a
15
+ * JSON string value, so it reads as its literal ("hello" → `"hello"`), never as "Invalid JSON". */
16
+ var jsonText = (v) => {
17
+ if (v == null || v === "") return "";
18
+ if (typeof v !== "string") return JSON.stringify(v, null, 2);
19
+ try {
20
+ JSON.parse(v);
21
+ return v;
22
+ } catch {
23
+ return JSON.stringify(v);
24
+ }
25
+ };
16
26
  var parse = (text) => text.trim() ? JSON.parse(text) : null;
17
27
  function JsonControl({ field, value, onChange, readOnly, id, invalid }) {
18
28
  const { variant } = useKitEnv();
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","names":[],"sources":["../../src/controls/json.tsx"],"sourcesContent":["/**\n * JSON — the json field (DESIGN 8.21), on the code surface (code.tsx).\n *\n * Values: whatever JSON the field holds (an object, a list, a number, or a JSON string a textarea wrote). An edit is\n * written PARSED, the way the classic JsonField writes it, and an emptied box writes null; the backend takes both.\n * Text that does not parse is never written: the panel's Done refuses with \"Invalid JSON · {reason}\", the inline\n * (document) surface keeps the last valid value and shows the reason under the code.\n */\nimport * as React from \"react\";\nimport { useKitEnv } from \"../context\";\nimport type { ControlProps } from \"../types\";\nimport { CodeDialogField, CodeSurface, jsonProblem } from \"./code\";\n\n/** The text a stored JSON value is edited as. A stored string that is JSON text stays as written; any other string is a\n * JSON string value, so it reads as its literal (\"hello\" → `\"hello\"`), never as \"Invalid JSON\". */\nconst jsonText = (v: unknown): string => {\n if (v == null || v === \"\") return \"\";\n if (typeof v !== \"string\") return JSON.stringify(v, null, 2);\n try {\n JSON.parse(v);\n return v;\n } catch {\n return JSON.stringify(v);\n }\n};\nconst parse = (text: string): unknown => (text.trim() ? JSON.parse(text) : null);\n\nexport function JsonControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n const text = jsonText(value);\n if (variant === \"document\") return <InlineJson id={id} value={value} text={text} onChange={onChange} readOnly={readOnly} invalid={invalid} />;\n return (\n <CodeDialogField\n kind=\"json\"\n id={id}\n title={field.title}\n description={field.description || undefined}\n text={text}\n readOnly={readOnly}\n invalid={invalid}\n onDone={(draft) => {\n if (draft === text) return null; // nothing edited: Done closes even over a stored string that isn't JSON\n const why = jsonProblem(draft);\n if (why) return `Invalid JSON · ${why}`;\n if (draft !== text) onChange(parse(draft));\n return null;\n }}\n />\n );\n}\n\n/** The document variant: the surface inline over a draft that survives invalid intermediates. */\nfunction InlineJson({ id, value, text, onChange, readOnly, invalid }: { id: string; value: unknown; text: string; onChange: (v: unknown) => void; readOnly?: boolean; invalid?: boolean }) {\n const [draft, setDraft] = React.useState(text);\n const [mine, setMine] = React.useState<unknown>(undefined);\n const [seen, setSeen] = React.useState(value);\n // a value set from elsewhere (undo, another editor) replaces the draft; our own writes keep the author's text\n if (value !== seen) {\n setSeen(value);\n if (value !== mine) setDraft(text);\n }\n return (\n <CodeSurface\n kind=\"json\"\n id={id}\n invalid={invalid}\n readOnly={readOnly}\n value={draft}\n onChange={(next) => {\n setDraft(next);\n if (jsonProblem(next)) return;\n const parsed = parse(next);\n setMine(parsed);\n onChange(parsed);\n }}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,IAAM,YAAY,MAAuB;CACvC,IAAI,KAAK,QAAQ,MAAM,IAAI,OAAO;CAClC,IAAI,OAAO,MAAM,UAAU,OAAO,KAAK,UAAU,GAAG,MAAM,CAAC;CAC3D,IAAI;EACF,KAAK,MAAM,CAAC;EACZ,OAAO;CACT,QAAQ;EACN,OAAO,KAAK,UAAU,CAAC;CACzB;AACF;AACA,IAAM,SAAS,SAA2B,KAAK,KAAK,IAAI,KAAK,MAAM,IAAI,IAAI;AAE3E,SAAgB,YAAY,EAAE,OAAO,OAAO,UAAU,UAAU,IAAI,WAAyB;CAC3F,MAAM,EAAE,YAAY,UAAU;CAC9B,MAAM,OAAO,SAAS,KAAK;CAC3B,IAAI,YAAY,YAAY,OAAO,oBAAC,YAAD;EAAgB;EAAW;EAAa;EAAgB;EAAoB;EAAmB;CAAU,CAAA;CAC5I,OACE,oBAAC,iBAAD;EACE,MAAK;EACD;EACJ,OAAO,MAAM;EACb,aAAa,MAAM,eAAe,KAAA;EAC5B;EACI;EACD;EACT,SAAS,UAAU;GACjB,IAAI,UAAU,MAAM,OAAO;GAC3B,MAAM,MAAM,YAAY,KAAK;GAC7B,IAAI,KAAK,OAAO,kBAAkB;GAClC,IAAI,UAAU,MAAM,SAAS,MAAM,KAAK,CAAC;GACzC,OAAO;EACT;CACD,CAAA;AAEL;;AAGA,SAAS,WAAW,EAAE,IAAI,OAAO,MAAM,UAAU,UAAU,WAAgI;CACzL,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,IAAI;CAC7C,MAAM,CAAC,MAAM,WAAW,MAAM,SAAkB,KAAA,CAAS;CACzD,MAAM,CAAC,MAAM,WAAW,MAAM,SAAS,KAAK;CAE5C,IAAI,UAAU,MAAM;EAClB,QAAQ,KAAK;EACb,IAAI,UAAU,MAAM,SAAS,IAAI;CACnC;CACA,OACE,oBAAC,aAAD;EACE,MAAK;EACD;EACK;EACC;EACV,OAAO;EACP,WAAW,SAAS;GAClB,SAAS,IAAI;GACb,IAAI,YAAY,IAAI,GAAG;GACvB,MAAM,SAAS,MAAM,IAAI;GACzB,QAAQ,MAAM;GACd,SAAS,MAAM;EACjB;CACD,CAAA;AAEL"}