@bettercms-ai/kit 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +90 -31
  8. package/dist/adapters/lossy.js +414 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
  11. package/{adapters → dist/adapters}/prod-types.js +71 -3
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +996 -179
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +92 -2
  22. package/{context.js → dist/context.js} +5 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/{controls → dist/controls}/form-picker-register.js +1 -1
  50. package/dist/controls/form-picker-register.js.map +1 -0
  51. package/{controls → dist/controls}/form-picker.js +11 -9
  52. package/dist/controls/form-picker.js.map +1 -0
  53. package/{controls → dist/controls}/icon-register.js +1 -1
  54. package/dist/controls/icon-register.js.map +1 -0
  55. package/{controls → dist/controls}/icon.d.ts +4 -2
  56. package/{controls → dist/controls}/icon.js +32 -27
  57. package/dist/controls/icon.js.map +1 -0
  58. package/{controls → dist/controls}/index.d.ts +1 -1
  59. package/{controls → dist/controls}/index.js +4 -3
  60. package/dist/controls/index.js.map +1 -0
  61. package/{controls → dist/controls}/json-register.js +1 -1
  62. package/dist/controls/json-register.js.map +1 -0
  63. package/{controls → dist/controls}/json.js +13 -3
  64. package/dist/controls/json.js.map +1 -0
  65. package/{controls → dist/controls}/link.js +6 -6
  66. package/dist/controls/link.js.map +1 -0
  67. package/{controls → dist/controls}/location-register.js +1 -1
  68. package/dist/controls/location-register.js.map +1 -0
  69. package/{controls → dist/controls}/location.js +64 -40
  70. package/dist/controls/location.js.map +1 -0
  71. package/{controls → dist/controls}/media-register.js +1 -1
  72. package/dist/controls/media-register.js.map +1 -0
  73. package/{controls → dist/controls}/media-services.d.ts +6 -0
  74. package/dist/controls/media-services.js +0 -0
  75. package/{controls → dist/controls}/media.d.ts +35 -4
  76. package/{controls → dist/controls}/media.js +491 -171
  77. package/dist/controls/media.js.map +1 -0
  78. package/{controls → dist/controls}/number.js +10 -9
  79. package/dist/controls/number.js.map +1 -0
  80. package/{controls → dist/controls}/reference-register.js +1 -1
  81. package/dist/controls/reference-register.js.map +1 -0
  82. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  83. package/dist/controls/reference-services.js +0 -0
  84. package/{controls → dist/controls}/reference.d.ts +1 -1
  85. package/{controls → dist/controls}/reference.js +93 -77
  86. package/dist/controls/reference.js.map +1 -0
  87. package/dist/controls/rich-text/blocks.d.ts +49 -0
  88. package/{controls → dist/controls}/rich-text/blocks.js +471 -144
  89. package/dist/controls/rich-text/blocks.js.map +1 -0
  90. package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
  91. package/{controls → dist/controls}/rich-text/catalog.js +75 -65
  92. package/dist/controls/rich-text/catalog.js.map +1 -0
  93. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  94. package/{controls → dist/controls}/rich-text/codec.js +3 -1
  95. package/dist/controls/rich-text/codec.js.map +1 -0
  96. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  97. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  98. package/dist/controls/rich-text/component-card.js.map +1 -0
  99. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  100. package/dist/controls/rich-text/component-panel.js +141 -0
  101. package/dist/controls/rich-text/component-panel.js.map +1 -0
  102. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  103. package/{controls → dist/controls}/rich-text/control.js +84 -42
  104. package/dist/controls/rich-text/control.js.map +1 -0
  105. package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
  106. package/{controls → dist/controls}/rich-text/dom.js +379 -50
  107. package/dist/controls/rich-text/dom.js.map +1 -0
  108. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  109. package/{controls → dist/controls}/rich-text/editor.js +148 -48
  110. package/dist/controls/rich-text/editor.js.map +1 -0
  111. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  112. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  113. package/dist/controls/rich-text/floating.js.map +1 -0
  114. package/{controls → dist/controls}/rich-text/index.js +1 -1
  115. package/dist/controls/rich-text/index.js.map +1 -0
  116. package/dist/controls/rich-text/link-form.js +147 -0
  117. package/dist/controls/rich-text/link-form.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  119. package/dist/controls/rich-text/markdown.js.map +1 -0
  120. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  121. package/dist/controls/rich-text/ops.js.map +1 -0
  122. package/dist/controls/rich-text/plain.d.ts +17 -0
  123. package/dist/controls/rich-text/plain.js +44 -0
  124. package/dist/controls/rich-text/plain.js.map +1 -0
  125. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  126. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  127. package/dist/controls/rich-text/toolbar.js.map +1 -0
  128. package/{controls → dist/controls}/scale.js +5 -5
  129. package/dist/controls/scale.js.map +1 -0
  130. package/{controls → dist/controls}/slot-register.js +1 -1
  131. package/dist/controls/slot-register.js.map +1 -0
  132. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  133. package/dist/controls/slot-services.js +155 -0
  134. package/dist/controls/slot-services.js.map +1 -0
  135. package/{controls → dist/controls}/slot.js +42 -24
  136. package/dist/controls/slot.js.map +1 -0
  137. package/{controls → dist/controls}/table/index.js +1 -1
  138. package/dist/controls/table/index.js.map +1 -0
  139. package/{controls → dist/controls}/table/prod.js +3 -3
  140. package/dist/controls/table/prod.js.map +1 -0
  141. package/{controls → dist/controls}/table/refs.js +13 -2
  142. package/dist/controls/table/refs.js.map +1 -0
  143. package/{controls → dist/controls}/table/stored.js +1 -1
  144. package/dist/controls/table/stored.js.map +1 -0
  145. package/{controls → dist/controls}/table/table-editor.js +51 -48
  146. package/dist/controls/table/table-editor.js.map +1 -0
  147. package/{controls → dist/controls}/table/table-link.js +3 -3
  148. package/dist/controls/table/table-link.js.map +1 -0
  149. package/{controls → dist/controls}/table/table.js +3 -3
  150. package/dist/controls/table/table.js.map +1 -0
  151. package/{controls → dist/controls}/text.d.ts +2 -2
  152. package/{controls → dist/controls}/text.js +78 -43
  153. package/dist/controls/text.js.map +1 -0
  154. package/dist/controls/unknown-value.d.ts +17 -0
  155. package/dist/controls/unknown-value.js +66 -0
  156. package/dist/controls/unknown-value.js.map +1 -0
  157. package/dist/core/core.d.ts +63 -0
  158. package/dist/core/core.js +171 -0
  159. package/dist/core/core.js.map +1 -0
  160. package/dist/core/facets.d.ts +347 -0
  161. package/dist/core/facets.js +334 -0
  162. package/dist/core/facets.js.map +1 -0
  163. package/dist/core/index.d.ts +3 -0
  164. package/dist/core/index.js +3 -0
  165. package/{engine → dist/engine}/array.js +34 -21
  166. package/dist/engine/array.js.map +1 -0
  167. package/{engine → dist/engine}/bits.js +1 -1
  168. package/dist/engine/bits.js.map +1 -0
  169. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  170. package/{engine → dist/engine}/breadcrumb.js +12 -36
  171. package/dist/engine/breadcrumb.js.map +1 -0
  172. package/{engine → dist/engine}/expand.d.ts +2 -4
  173. package/{engine → dist/engine}/expand.js +5 -22
  174. package/dist/engine/expand.js.map +1 -0
  175. package/{engine → dist/engine}/field-list.js +1 -1
  176. package/dist/engine/field-list.js.map +1 -0
  177. package/{engine → dist/engine}/field-shell.js +249 -121
  178. package/dist/engine/field-shell.js.map +1 -0
  179. package/{engine → dist/engine}/frame.d.ts +3 -1
  180. package/{engine → dist/engine}/frame.js +16 -14
  181. package/dist/engine/frame.js.map +1 -0
  182. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  183. package/{engine → dist/engine}/group-summary.js +7 -3
  184. package/dist/engine/group-summary.js.map +1 -0
  185. package/{engine → dist/engine}/grouping.d.ts +19 -5
  186. package/{engine → dist/engine}/grouping.js +193 -21
  187. package/dist/engine/grouping.js.map +1 -0
  188. package/{engine → dist/engine}/item-list.d.ts +11 -1
  189. package/{engine → dist/engine}/item-list.js +35 -13
  190. package/dist/engine/item-list.js.map +1 -0
  191. package/{engine → dist/engine}/kit-field.js +45 -10
  192. package/dist/engine/kit-field.js.map +1 -0
  193. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  194. package/{engine → dist/engine}/schema-form.js +182 -40
  195. package/dist/engine/schema-form.js.map +1 -0
  196. package/{engine → dist/engine}/slot.js +5 -15
  197. package/dist/engine/slot.js.map +1 -0
  198. package/dist/index.js +47 -0
  199. package/dist/index.js.map +1 -0
  200. package/{kit.css → dist/kit.css} +19 -0
  201. package/{lib → dist/lib}/cn.js +7 -4
  202. package/dist/lib/cn.js.map +1 -0
  203. package/{lib → dist/lib}/columns.js +4 -1
  204. package/dist/lib/columns.js.map +1 -0
  205. package/{lib → dist/lib}/frames.js +2 -2
  206. package/dist/lib/frames.js.map +1 -0
  207. package/dist/lib/icon-image.d.ts +10 -0
  208. package/dist/lib/icon-image.js +8 -0
  209. package/dist/lib/icon-image.js.map +1 -0
  210. package/{lib → dist/lib}/icons.js +4 -3
  211. package/dist/lib/icons.js.map +1 -0
  212. package/dist/lib/input-modality.d.ts +11 -0
  213. package/dist/lib/input-modality.js +47 -0
  214. package/dist/lib/input-modality.js.map +1 -0
  215. package/dist/lib/key-event.d.ts +11 -0
  216. package/dist/lib/key-event.js +16 -0
  217. package/dist/lib/key-event.js.map +1 -0
  218. package/{lib → dist/lib}/path.js +4 -2
  219. package/dist/lib/path.js.map +1 -0
  220. package/{lib → dist/lib}/schema.d.ts +34 -3
  221. package/{lib → dist/lib}/schema.js +110 -13
  222. package/dist/lib/schema.js.map +1 -0
  223. package/{lib → dist/lib}/utils.js +1 -1
  224. package/dist/lib/utils.js.map +1 -0
  225. package/{lib → dist/lib}/validate.d.ts +11 -1
  226. package/{lib → dist/lib}/validate.js +85 -11
  227. package/dist/lib/validate.js.map +1 -0
  228. package/dist/library/analysis.d.ts +23 -0
  229. package/dist/library/analysis.js +160 -0
  230. package/dist/library/analysis.js.map +1 -0
  231. package/dist/library/catalog.d.ts +57 -0
  232. package/dist/library/catalog.js +307 -0
  233. package/dist/library/catalog.js.map +1 -0
  234. package/dist/library/coreNotes.d.ts +8 -0
  235. package/dist/library/coreNotes.js +111 -0
  236. package/dist/library/coreNotes.js.map +1 -0
  237. package/dist/library/coverage.d.ts +40 -0
  238. package/dist/library/coverage.js +59 -0
  239. package/dist/library/coverage.js.map +1 -0
  240. package/dist/library/entries/advanced.entries.d.ts +2 -0
  241. package/dist/library/entries/advanced.entries.js +6579 -0
  242. package/dist/library/entries/advanced.entries.js.map +1 -0
  243. package/dist/library/entries/commerce.entries.d.ts +2 -0
  244. package/dist/library/entries/commerce.entries.js +4140 -0
  245. package/dist/library/entries/commerce.entries.js.map +1 -0
  246. package/dist/library/entries/company.entries.d.ts +2 -0
  247. package/dist/library/entries/company.entries.js +2731 -0
  248. package/dist/library/entries/company.entries.js.map +1 -0
  249. package/dist/library/entries/conversion.entries.d.ts +2 -0
  250. package/dist/library/entries/conversion.entries.js +3707 -0
  251. package/dist/library/entries/conversion.entries.js.map +1 -0
  252. package/dist/library/entries/data.entries.d.ts +7 -0
  253. package/dist/library/entries/data.entries.js +4613 -0
  254. package/dist/library/entries/data.entries.js.map +1 -0
  255. package/dist/library/entries/events.entries.d.ts +2 -0
  256. package/dist/library/entries/events.entries.js +3428 -0
  257. package/dist/library/entries/events.entries.js.map +1 -0
  258. package/dist/library/entries/features.entries.d.ts +2 -0
  259. package/dist/library/entries/features.entries.js +3157 -0
  260. package/dist/library/entries/features.entries.js.map +1 -0
  261. package/dist/library/entries/heroes.entries.d.ts +2 -0
  262. package/dist/library/entries/heroes.entries.js +3401 -0
  263. package/dist/library/entries/heroes.entries.js.map +1 -0
  264. package/dist/library/entries/index.d.ts +3 -0
  265. package/dist/library/entries/index.js +35 -0
  266. package/dist/library/entries/index.js.map +1 -0
  267. package/dist/library/entries/listings.entries.d.ts +2 -0
  268. package/dist/library/entries/listings.entries.js +2976 -0
  269. package/dist/library/entries/listings.entries.js.map +1 -0
  270. package/dist/library/entries/longform.entries.d.ts +2 -0
  271. package/dist/library/entries/longform.entries.js +4227 -0
  272. package/dist/library/entries/longform.entries.js.map +1 -0
  273. package/dist/library/entries/media.entries.d.ts +2 -0
  274. package/dist/library/entries/media.entries.js +2781 -0
  275. package/dist/library/entries/media.entries.js.map +1 -0
  276. package/dist/library/entries/navigation.entries.d.ts +2 -0
  277. package/dist/library/entries/navigation.entries.js +4011 -0
  278. package/dist/library/entries/navigation.entries.js.map +1 -0
  279. package/dist/library/entries/pricing.entries.d.ts +2 -0
  280. package/dist/library/entries/pricing.entries.js +2383 -0
  281. package/dist/library/entries/pricing.entries.js.map +1 -0
  282. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  283. package/dist/library/entries/social-proof.entries.js +2297 -0
  284. package/dist/library/entries/social-proof.entries.js.map +1 -0
  285. package/dist/library/examples/bento.d.ts +92 -0
  286. package/dist/library/examples/bento.js +201 -0
  287. package/dist/library/examples/bento.js.map +1 -0
  288. package/dist/library/examples/blocks.d.ts +14 -0
  289. package/dist/library/examples/blocks.js +313 -0
  290. package/dist/library/examples/blocks.js.map +1 -0
  291. package/dist/library/examples/faq.d.ts +28 -0
  292. package/dist/library/examples/faq.js +230 -0
  293. package/dist/library/examples/faq.js.map +1 -0
  294. package/dist/library/examples/hero.d.ts +43 -0
  295. package/dist/library/examples/hero.js +222 -0
  296. package/dist/library/examples/hero.js.map +1 -0
  297. package/dist/library/examples/index.d.ts +36 -0
  298. package/dist/library/examples/index.js +109 -0
  299. package/dist/library/examples/index.js.map +1 -0
  300. package/dist/library/examples/journalStory.d.ts +93 -0
  301. package/dist/library/examples/journalStory.js +338 -0
  302. package/dist/library/examples/journalStory.js.map +1 -0
  303. package/dist/library/examples/megaMenu.d.ts +134 -0
  304. package/dist/library/examples/megaMenu.js +442 -0
  305. package/dist/library/examples/megaMenu.js.map +1 -0
  306. package/dist/library/examples/pricing.d.ts +103 -0
  307. package/dist/library/examples/pricing.js +479 -0
  308. package/dist/library/examples/pricing.js.map +1 -0
  309. package/dist/library/examples/tabs.d.ts +87 -0
  310. package/dist/library/examples/tabs.js +180 -0
  311. package/dist/library/examples/tabs.js.map +1 -0
  312. package/dist/library/export.d.ts +42 -0
  313. package/dist/library/export.js +80 -0
  314. package/dist/library/export.js.map +1 -0
  315. package/dist/library/index.d.ts +13 -0
  316. package/dist/library/index.js +6 -0
  317. package/dist/library/kit-catalog.json +1510 -0
  318. package/dist/library/types.d.ts +42 -0
  319. package/dist/library/types.js +0 -0
  320. package/{schema → dist/schema}/adapters.js +1 -2
  321. package/dist/schema/adapters.js.map +1 -0
  322. package/{schema → dist/schema}/help.d.ts +2 -0
  323. package/{schema → dist/schema}/help.js +6 -4
  324. package/dist/schema/help.js.map +1 -0
  325. package/{schema → dist/schema}/scale.js +1 -1
  326. package/dist/schema/scale.js.map +1 -0
  327. package/{schema → dist/schema}/sources.js +1 -1
  328. package/dist/schema/sources.js.map +1 -0
  329. package/{schema → dist/schema}/table.js +11 -10
  330. package/dist/schema/table.js.map +1 -0
  331. package/{schema → dist/schema}/types.d.ts +29 -1
  332. package/{schema → dist/schema}/types.js +1 -1
  333. package/dist/schema/types.js.map +1 -0
  334. package/dist/styles.css +2 -0
  335. package/dist/table/table-view.d.ts +14 -0
  336. package/dist/table/table-view.js +140 -0
  337. package/dist/table/table-view.js.map +1 -0
  338. package/dist/table/table.css +73 -0
  339. package/dist/testing/corpus.d.ts +63 -0
  340. package/dist/testing/corpus.js +129 -0
  341. package/dist/testing/corpus.js.map +1 -0
  342. package/dist/testing/test-form.d.ts +11 -0
  343. package/dist/testing/test-form.js +38 -0
  344. package/dist/testing/test-form.js.map +1 -0
  345. package/dist/theme.css +345 -0
  346. package/dist/theme.d.ts +22 -0
  347. package/dist/theme.js +43 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens.css +542 -0
  350. package/dist/types.js +0 -0
  351. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  352. package/{ui → dist/ui}/action-tray.js +20 -19
  353. package/dist/ui/action-tray.js.map +1 -0
  354. package/dist/ui/autocomplete.d.ts +30 -0
  355. package/dist/ui/autocomplete.js +139 -0
  356. package/dist/ui/autocomplete.js.map +1 -0
  357. package/{ui → dist/ui}/button.d.ts +3 -3
  358. package/{ui → dist/ui}/button.js +6 -7
  359. package/dist/ui/button.js.map +1 -0
  360. package/{ui → dist/ui}/choice-switch.js +1 -1
  361. package/dist/ui/choice-switch.js.map +1 -0
  362. package/{ui → dist/ui}/controls.js +51 -39
  363. package/dist/ui/controls.js.map +1 -0
  364. package/{ui → dist/ui}/display.d.ts +10 -3
  365. package/{ui → dist/ui}/display.js +57 -46
  366. package/dist/ui/display.js.map +1 -0
  367. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  368. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  369. package/dist/ui/expanded-editor-modal.js.map +1 -0
  370. package/{ui → dist/ui}/field-context.js +1 -1
  371. package/dist/ui/field-context.js.map +1 -0
  372. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  373. package/{ui → dist/ui}/floating-panel.js +28 -12
  374. package/dist/ui/floating-panel.js.map +1 -0
  375. package/{ui → dist/ui}/index.d.ts +4 -0
  376. package/dist/ui/index.js +18 -0
  377. package/{ui → dist/ui}/input.d.ts +1 -1
  378. package/{ui → dist/ui}/input.js +9 -9
  379. package/dist/ui/input.js.map +1 -0
  380. package/{ui → dist/ui}/mode-bar.js +3 -3
  381. package/dist/ui/mode-bar.js.map +1 -0
  382. package/{ui → dist/ui}/overlay.d.ts +77 -5
  383. package/dist/ui/overlay.js +697 -0
  384. package/dist/ui/overlay.js.map +1 -0
  385. package/{ui → dist/ui}/path-crumbs.js +37 -3
  386. package/dist/ui/path-crumbs.js.map +1 -0
  387. package/{ui → dist/ui}/presence.js +2 -2
  388. package/dist/ui/presence.js.map +1 -0
  389. package/{ui → dist/ui}/select.js +89 -87
  390. package/dist/ui/select.js.map +1 -0
  391. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  392. package/dist/ui/shortcut-hint.js.map +1 -0
  393. package/dist/ui/spinner.d.ts +24 -0
  394. package/dist/ui/spinner.js +42 -0
  395. package/dist/ui/spinner.js.map +1 -0
  396. package/dist/ui/split-button.d.ts +32 -0
  397. package/dist/ui/split-button.js +60 -0
  398. package/dist/ui/split-button.js.map +1 -0
  399. package/{ui → dist/ui}/surfaces.js +1 -1
  400. package/dist/ui/surfaces.js.map +1 -0
  401. package/dist/ui/tab.d.ts +38 -0
  402. package/dist/ui/tab.js +87 -0
  403. package/dist/ui/tab.js.map +1 -0
  404. package/dist/ui/toast.d.ts +20 -0
  405. package/dist/ui/toast.js +115 -0
  406. package/dist/ui/toast.js.map +1 -0
  407. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  408. package/{ui → dist/ui}/tooltip-root.js +9 -8
  409. package/dist/ui/tooltip-root.js.map +1 -0
  410. package/{ui → dist/ui}/variants.js +1 -1
  411. package/dist/ui/variants.js.map +1 -0
  412. package/package.json +77 -23
  413. package/adapters/icons.js.map +0 -1
  414. package/adapters/lossy.js +0 -233
  415. package/adapters/lossy.js.map +0 -1
  416. package/adapters/prod-types.js.map +0 -1
  417. package/adapters/schema.js.map +0 -1
  418. package/adapters/values.js.map +0 -1
  419. package/brand/logo.js +0 -9
  420. package/brand/logo.js.map +0 -1
  421. package/context.js.map +0 -1
  422. package/controls/button.js.map +0 -1
  423. package/controls/c1.js.map +0 -1
  424. package/controls/c2.js.map +0 -1
  425. package/controls/choice.js.map +0 -1
  426. package/controls/code-register.js.map +0 -1
  427. package/controls/code.js.map +0 -1
  428. package/controls/color.js.map +0 -1
  429. package/controls/date-register.js.map +0 -1
  430. package/controls/date-zone.js.map +0 -1
  431. package/controls/date.js.map +0 -1
  432. package/controls/form-picker-register.js.map +0 -1
  433. package/controls/form-picker.js.map +0 -1
  434. package/controls/icon-register.js.map +0 -1
  435. package/controls/icon.js.map +0 -1
  436. package/controls/index.js.map +0 -1
  437. package/controls/json-register.js.map +0 -1
  438. package/controls/json.js.map +0 -1
  439. package/controls/link.js.map +0 -1
  440. package/controls/location-register.js.map +0 -1
  441. package/controls/location.js.map +0 -1
  442. package/controls/media-register.js.map +0 -1
  443. package/controls/media.js.map +0 -1
  444. package/controls/number.js.map +0 -1
  445. package/controls/reference-register.js.map +0 -1
  446. package/controls/reference.js.map +0 -1
  447. package/controls/rich-text/blocks.d.ts +0 -28
  448. package/controls/rich-text/blocks.js.map +0 -1
  449. package/controls/rich-text/catalog.js.map +0 -1
  450. package/controls/rich-text/codec.js.map +0 -1
  451. package/controls/rich-text/component-card.js.map +0 -1
  452. package/controls/rich-text/control.js.map +0 -1
  453. package/controls/rich-text/dom.js.map +0 -1
  454. package/controls/rich-text/editor.js.map +0 -1
  455. package/controls/rich-text/floating.js.map +0 -1
  456. package/controls/rich-text/index.js.map +0 -1
  457. package/controls/rich-text/link-form.js +0 -111
  458. package/controls/rich-text/link-form.js.map +0 -1
  459. package/controls/rich-text/markdown.js.map +0 -1
  460. package/controls/rich-text/ops.js.map +0 -1
  461. package/controls/rich-text/toolbar.js.map +0 -1
  462. package/controls/scale.js.map +0 -1
  463. package/controls/slot-register.js.map +0 -1
  464. package/controls/slot-services.js +0 -38
  465. package/controls/slot-services.js.map +0 -1
  466. package/controls/slot.js.map +0 -1
  467. package/controls/table/index.js.map +0 -1
  468. package/controls/table/prod.js.map +0 -1
  469. package/controls/table/refs.js.map +0 -1
  470. package/controls/table/stored.js.map +0 -1
  471. package/controls/table/table-editor.js.map +0 -1
  472. package/controls/table/table-link.js.map +0 -1
  473. package/controls/table/table.js.map +0 -1
  474. package/controls/text.js.map +0 -1
  475. package/engine/array.js.map +0 -1
  476. package/engine/bits.js.map +0 -1
  477. package/engine/breadcrumb.js.map +0 -1
  478. package/engine/expand.js.map +0 -1
  479. package/engine/field-list.js.map +0 -1
  480. package/engine/field-shell.js.map +0 -1
  481. package/engine/frame.js.map +0 -1
  482. package/engine/group-summary.js.map +0 -1
  483. package/engine/grouping.js.map +0 -1
  484. package/engine/item-list.js.map +0 -1
  485. package/engine/kit-field.js.map +0 -1
  486. package/engine/schema-form.js.map +0 -1
  487. package/engine/slot.js.map +0 -1
  488. package/index.js +0 -55
  489. package/index.js.map +0 -1
  490. package/lib/cn.js.map +0 -1
  491. package/lib/columns.js.map +0 -1
  492. package/lib/frames.js.map +0 -1
  493. package/lib/icons.js.map +0 -1
  494. package/lib/path.js.map +0 -1
  495. package/lib/schema.js.map +0 -1
  496. package/lib/utils.js.map +0 -1
  497. package/lib/validate.js.map +0 -1
  498. package/schema/adapters.js.map +0 -1
  499. package/schema/help.js.map +0 -1
  500. package/schema/scale.js.map +0 -1
  501. package/schema/sources.js.map +0 -1
  502. package/schema/table.js.map +0 -1
  503. package/schema/types.js.map +0 -1
  504. package/ui/action-tray.js.map +0 -1
  505. package/ui/button.js.map +0 -1
  506. package/ui/choice-switch.js.map +0 -1
  507. package/ui/controls.js.map +0 -1
  508. package/ui/display.js.map +0 -1
  509. package/ui/expanded-editor-modal.js.map +0 -1
  510. package/ui/field-context.js.map +0 -1
  511. package/ui/floating-panel.js.map +0 -1
  512. package/ui/index.js +0 -13
  513. package/ui/input.js.map +0 -1
  514. package/ui/mode-bar.js.map +0 -1
  515. package/ui/overlay.js +0 -378
  516. package/ui/overlay.js.map +0 -1
  517. package/ui/path-crumbs.js.map +0 -1
  518. package/ui/presence.js.map +0 -1
  519. package/ui/select.js.map +0 -1
  520. package/ui/shortcut-hint.js.map +0 -1
  521. package/ui/surfaces.js.map +0 -1
  522. package/ui/tooltip-root.js.map +0 -1
  523. package/ui/variants.js.map +0 -1
  524. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  525. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  526. /package/{brand → dist/brand}/logo.d.ts +0 -0
  527. /package/{controls → dist/controls}/c1.d.ts +0 -0
  528. /package/{controls → dist/controls}/c2.d.ts +0 -0
  529. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  530. /package/{controls → dist/controls}/code.d.ts +0 -0
  531. /package/{controls → dist/controls}/color.d.ts +0 -0
  532. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  533. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  534. /package/{controls → dist/controls}/date.d.ts +0 -0
  535. /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
  536. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  537. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  538. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  539. /package/{controls → dist/controls}/json.d.ts +0 -0
  540. /package/{controls → dist/controls}/link.d.ts +0 -0
  541. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  542. /package/{controls → dist/controls}/location.d.ts +0 -0
  543. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  544. /package/{controls → dist/controls}/number.d.ts +0 -0
  545. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  546. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  547. /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
  548. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  549. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  550. /package/{controls → dist/controls}/scale.d.ts +0 -0
  551. /package/{controls → dist/controls}/slot-register.d.ts +0 -0
  552. /package/{controls → dist/controls}/slot.d.ts +0 -0
  553. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  554. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  555. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  556. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  557. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  558. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  559. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  560. /package/{engine → dist/engine}/array.d.ts +0 -0
  561. /package/{engine → dist/engine}/bits.d.ts +0 -0
  562. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  563. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  564. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  565. /package/{engine → dist/engine}/slot.d.ts +0 -0
  566. /package/{index.d.ts → dist/index.d.ts} +0 -0
  567. /package/{lib → dist/lib}/cn.d.ts +0 -0
  568. /package/{lib → dist/lib}/columns.d.ts +0 -0
  569. /package/{lib → dist/lib}/frames.d.ts +0 -0
  570. /package/{lib → dist/lib}/icons.d.ts +0 -0
  571. /package/{lib → dist/lib}/path.d.ts +0 -0
  572. /package/{lib → dist/lib}/utils.d.ts +0 -0
  573. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  574. /package/{schema → dist/schema}/scale.d.ts +0 -0
  575. /package/{schema → dist/schema}/sources.d.ts +0 -0
  576. /package/{schema → dist/schema}/table.d.ts +0 -0
  577. /package/{types.d.ts → dist/types.d.ts} +0 -0
  578. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  579. /package/{ui → dist/ui}/controls.d.ts +0 -0
  580. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  581. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  582. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  583. /package/{ui → dist/ui}/presence.d.ts +0 -0
  584. /package/{ui → dist/ui}/select.d.ts +0 -0
  585. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  586. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  587. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"link.js","names":[],"sources":["../../src/kit/controls/link.tsx"],"sourcesContent":["/**\n * LINK — the ONE link element of the product (V2 HEAD kit/controls/link.tsx, DESIGN §8.7, CPO D43 · D48 · D57).\n *\n * - <LinkForm> Type (Page · CMS item · URL · Email · Phone · Section · File) → the target for that type (search over\n * the host's pages and CMS items, paste detection, URL / email / phone / #anchor validation; File =\n * the host's media library) → Section on the picked page → options (new tab · rel · email subject).\n * - <LinkPopoverBody> the link panel: what it links to now + LinkForm + Remove link · Cancel · Apply.\n * - <LinkField> a link at rest (one bordered row): click edits in place (quick edit), the sliders icon opens the panel.\n * - <LinkPicker> the target input inside all of the above.\n * - <LinkLine> how a link READS at rest: page icon + title + path · external icon + domain · mail / phone.\n *\n * Where the targets come from. The kit never fetches: the host hands its own link-target query in as a React hook,\n * `KitServices.useLinkTargets` (KitLinkServices below), and the media library as `KitServices.MediaPicker`. With no hook a\n * page link is typed as a path and the list says so in words; with no media picker the File type is not offered.\n * Section anchors come from the host that knows the page (SectionAnchorsProvider); without one a section is typed (#faq).\n *\n * Stored shape (prod `link`, adapters/values.ts linkToProd / linkFromProd). The kit value is what the field already\n * stores: a STRING href stays a string (legacy fields and the sites that read `href={link}`), an object stays an object.\n * An empty field takes `field.valueShape` and, with none, the string (prod LinkField's default). In the string shape the\n * options (new tab, rel) need the object, so they hide — V2's `valueShape=\"string\"`. An object never carries `target`\n * (derived from newTab), `rel: \"follow\"` (follow = no rel) or `newTab: false`, so it reads back exactly as written.\n *\n * Deviations from V2, each because prod has no source for it: no \"From this entry\" {{token}} targets (no binding store\n * behind them), no seeded page anchors, no fabricated CDN address for a file (a file without a public url is refused).\n */\nimport * as React from \"react\";\nimport {\n IconAdjustmentsHorizontal, IconArrowUpRight, IconAt, IconCheck, IconChevronDown, IconExternalLink, IconFile, IconFileDatabase,\n IconFolderOpen, IconHash, IconLink, IconMail, IconPaperclip, IconPhone, IconWorld, IconX,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices } from \"../context\";\nimport { Button, IconButton } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { Switch } from \"../ui/controls\";\nimport { Select } from \"../ui/select\";\nimport { Menu, MenuContent, MenuItem, MenuTrigger, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\n\nexport type LinkType = \"page\" | \"url\" | \"section\" | \"email\" | \"phone\" | \"file\" | \"entry\";\nexport type LinkRel = \"follow\" | \"nofollow\" | \"ugc\" | \"sponsored\";\nexport type ButtonStyle = \"primary\" | \"secondary\" | \"outline\" | \"link\";\nexport interface LinkValue {\n type?: LinkType;\n href: string;\n /** button label / link text */\n label?: string;\n /** resolved title of the target (page or entry name) */\n title?: string;\n pageId?: string;\n entryId?: string;\n anchor?: string;\n assetId?: string;\n email?: string;\n subject?: string;\n phone?: string;\n /** legacy target: read as newTab, never written */\n target?: \"_self\" | \"_blank\";\n newTab?: boolean;\n rel?: LinkRel;\n /* button-only (controls/button.tsx) */\n style?: ButtonStyle;\n variant?: string;\n size?: \"sm\" | \"md\" | \"lg\";\n arrow?: boolean;\n icon?: string;\n fullWidth?: boolean;\n}\n\n/* ── Host services ───────────────────────────────────────────────────── */\n/** A place a link can point at, as the host lists it. */\nexport interface LinkTarget {\n id: string;\n title: string;\n /** the public path (\"/about\", \"/blog/hello\") or a file's url */\n href: string;\n kind: \"page\" | \"entry\" | \"file\" | \"section\";\n /** collection name for an entry, file kind for a file */\n meta?: string;\n /** list group: \"Pages\", the collection's name, \"Files\", \"On this page\" */\n group: string;\n /** draft · published · scheduled · archived … (shown when it is not live) */\n status?: string;\n /** \"#faq\" anchors on that page, when the host knows them */\n anchors?: string[];\n /** a section without an anchor yet gets it when picked */\n onChoose?: () => void;\n}\n/**\n * The link services a host provides next to KitServices (registerKitServices / KitServicesProvider take them as is).\n * `useLinkTargets` is a React HOOK (called on every render of a link control), so a host passes the same function for\n * the life of the form.\n */\nexport type KitLinkServices = Pick<KitServices, \"useLinkTargets\">;\ntype LinkHost = { targets: LinkTarget[]; loading: boolean; error?: string; unavailable: boolean };\nconst NO_TARGETS: LinkTarget[] = [];\nconst useNoTargets = () => ({ targets: NO_TARGETS, loading: false, error: undefined as string | undefined });\n\n/** The host's pages, CMS items (and files, when it lists them). */\nexport function useLinkTargets(): LinkHost {\n const svc = useKitServices();\n const useHost = svc.useLinkTargets ?? useNoTargets;\n const r = useHost();\n return { targets: r.targets ?? NO_TARGETS, loading: !!r.loading, error: r.error, unavailable: !svc.useLinkTargets };\n}\n\n/** A section on the page being edited that a link can jump to (`id` on the block). */\nexport interface SectionAnchor {\n /** \"#faq\" */\n anchor: string;\n /** what a person reads: the block's name */\n label: string;\n /** the block has no anchor yet: give it this one when a link picks it */\n ensure?: () => void;\n}\nconst SectionAnchorsCtx = React.createContext<SectionAnchor[] | null>(null);\n/** The host that knows the page being edited lists its section anchors, so the Section type is a pick. */\nexport function SectionAnchorsProvider({ anchors, children }: { anchors: SectionAnchor[]; children: React.ReactNode }) {\n return <SectionAnchorsCtx.Provider value={anchors}>{children}</SectionAnchorsCtx.Provider>;\n}\nfunction useSectionTargets(): LinkTarget[] {\n const anchors = React.useContext(SectionAnchorsCtx);\n return React.useMemo(\n () =>\n (anchors ?? []).map((a) => ({\n id: `section:${a.anchor}`,\n title: a.label,\n href: a.anchor.startsWith(\"#\") ? a.anchor : `#${a.anchor}`,\n kind: \"section\" as const,\n group: \"On this page\",\n onChoose: a.ensure,\n })),\n [anchors],\n );\n}\n\n/** A file from the media library as a link target, or the reason it can't be one. */\nexport function fileTarget(a: Pick<KitMediaAsset, \"id\" | \"name\" | \"url\">): LinkTarget | { problem: string } {\n if (!a.url || a.url.startsWith(\"blob:\")) return { problem: \"This file has no public address yet. Wait for the upload to finish, then pick it again.\" };\n const name = a.name || fileName(a.url);\n return { id: a.id, title: name, href: a.url, kind: \"file\", meta: name.split(\".\").pop()?.toUpperCase(), group: \"Files\" };\n}\n\n/* ── Value helpers ───────────────────────────────────────────────────── */\nexport const normLink = (v: unknown): LinkValue => {\n const o: LinkValue = typeof v === \"string\" ? { href: v } : isObj(v) ? ({ ...(v as object), href: typeof v.href === \"string\" ? v.href : \"\" } as LinkValue) : { href: \"\" };\n if (o.newTab === undefined && o.target === \"_blank\") o.newTab = true;\n if (!o.type) o.type = detectType(o.href);\n return o;\n};\n\nexport function detectType(raw: string): LinkType {\n const s = raw.trim();\n if (!s) return \"page\";\n if (s.startsWith(\"#\")) return \"section\";\n if (/^mailto:/i.test(s) || /^[^\\s@/]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) return \"email\";\n if (/^tel:/i.test(s) || /^\\+?[\\d\\s().-]{7,}$/.test(s)) return \"phone\";\n if (/\\.(pdf|zip|docx?|csv)$/i.test(s)) return \"file\";\n if (/^https?:\\/\\//i.test(s) || /^www\\./i.test(s) || /^[a-z0-9-]+(\\.[a-z0-9-]+)+(\\/|$)/i.test(s)) return \"url\";\n return \"page\";\n}\n\nexport const LINK_TYPES: { type: LinkType; label: string; icon: React.ReactNode; placeholder: string; target: string }[] = [\n { type: \"page\", label: \"Page\", icon: <IconFile stroke={1.5} />, placeholder: \"Search pages and CMS items, or paste a link\", target: \"Page\" },\n { type: \"entry\", label: \"CMS item\", icon: <IconFileDatabase stroke={1.5} />, placeholder: \"Search CMS items\", target: \"CMS item\" },\n { type: \"url\", label: \"URL\", icon: <IconWorld stroke={1.5} />, placeholder: \"https://example.com\", target: \"Address\" },\n { type: \"email\", label: \"Email\", icon: <IconAt stroke={1.5} />, placeholder: \"name@company.com\", target: \"Email address\" },\n { type: \"phone\", label: \"Phone\", icon: <IconPhone stroke={1.5} />, placeholder: \"+1 541 555 0182\", target: \"Phone number\" },\n { type: \"section\", label: \"Section\", icon: <IconHash stroke={1.5} />, placeholder: \"#section-on-this-page\", target: \"Section on this page\" },\n { type: \"file\", label: \"File\", icon: <IconPaperclip stroke={1.5} />, placeholder: \"Search files\", target: \"File\" },\n];\nconst typeMeta = (t?: string) => LINK_TYPES.find((x) => x.type === t) ?? LINK_TYPES[0];\n\n/** The target a value points at: by id first, then by an exact path (\"/about\" typed by hand still reads as About). */\nexport function findTarget(targets: LinkTarget[], v: LinkValue): LinkTarget | undefined {\n const byId = targets.find((t) => (v.pageId && t.id === v.pageId) || (v.entryId && t.id === v.entryId) || (v.assetId && t.id === v.assetId));\n if (byId) return byId;\n if (v.type === \"section\") return v.href ? targets.find((t) => t.kind === \"section\" && t.href === (v.href.startsWith(\"#\") ? v.href : `#${v.href}`)) : undefined;\n if (!v.href || (v.type !== \"page\" && v.type !== \"entry\" && v.type !== \"file\")) return undefined;\n if (v.type === \"file\") {\n const f = targets.find((t) => t.kind === \"file\" && t.href === v.href);\n // a file picked from the library reads as the file by the name stored with it\n return f ?? (v.title ? { id: v.assetId ?? v.href, title: v.title, href: v.href, kind: \"file\", group: \"Files\" } : undefined);\n }\n const path = v.href.replace(/[?#].*$/, \"\").replace(/\\/$/, \"\") || \"/\";\n return targets.find((t) => t.kind !== \"file\" && t.kind !== \"section\" && t.href === path);\n}\n\n/** The final href for a link value. */\nexport function hrefOf(v: LinkValue): string {\n switch (v.type) {\n case \"email\": {\n const addr = (v.email ?? v.href).replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\");\n return addr ? `mailto:${addr}${v.subject ? `?subject=${encodeURIComponent(v.subject)}` : \"\"}` : \"\";\n }\n case \"phone\": {\n const n = (v.phone ?? v.href).replace(/^tel:/i, \"\").replace(/[^\\d+]/g, \"\");\n return n ? `tel:${n}` : \"\";\n }\n case \"section\":\n return v.href.startsWith(\"#\") ? v.href : v.href ? `#${v.href}` : \"\";\n default: {\n // idempotent: a stored href already carries its anchor, so a changed or removed anchor replaces it\n const base = v.anchor !== undefined ? v.href.replace(/#.*$/, \"\") : v.href;\n return `${base}${v.anchor && v.anchor !== \"none\" ? v.anchor : \"\"}`;\n }\n }\n}\n\nconst BAD_URL = \"Enter a full address, like https://example.com.\";\n/** Why a link can't be saved yet, in plain words. Undefined when it is fine (or empty). */\nexport function linkProblem(v: LinkValue): string | undefined {\n if (!hasLink(v)) return undefined;\n const raw = (v.type === \"email\" ? v.email ?? v.href : v.type === \"phone\" ? v.phone ?? v.href : v.href).trim();\n if (/^(javascript|data|vbscript):/i.test(raw.replace(/[\\u0000- ]/g, \"\"))) return \"Script links aren't allowed.\";\n switch (v.type) {\n case \"url\": {\n if (raw.startsWith(\"/\") || raw.startsWith(\"#\")) return undefined;\n try {\n const u = new URL(/^[a-z][a-z0-9+.-]*:/i.test(raw) ? raw : `https://${raw}`);\n if (!/^https?:$/.test(u.protocol)) return BAD_URL;\n return /\\.[a-z]{2,}$/i.test(u.hostname) || u.hostname === \"localhost\" ? undefined : BAD_URL;\n } catch {\n return BAD_URL;\n }\n }\n case \"email\":\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$/.test(raw.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\")) ? undefined : \"Enter an email address, like name@company.com.\";\n case \"phone\":\n return raw.replace(/^tel:/i, \"\").replace(/\\D/g, \"\").length >= 7 ? undefined : \"Enter a phone number with at least 7 digits.\";\n case \"section\":\n return /^#?[A-Za-z][\\w-]*$/.test(raw) ? undefined : \"Use letters, numbers and dashes, like #faq.\";\n case \"page\":\n case \"entry\":\n return raw.startsWith(\"/\") || raw.startsWith(\"#\") || v.pageId || v.entryId ? undefined : \"Pick a page, or start a path with /, like /about.\";\n default:\n return undefined;\n }\n}\n\n/** One list for every link editor (dropdown, never a segmented row — D40). */\nexport const REL_ITEMS: { value: LinkRel; label: string; description: string }[] = [\n { value: \"follow\", label: \"Do-follow\", description: \"Normal link. Search engines follow it.\" },\n { value: \"nofollow\", label: \"No-follow\", description: \"Search engines don't follow or credit it.\" },\n { value: \"sponsored\", label: \"Sponsored\", description: \"Paid, affiliate or ad link.\" },\n { value: \"ugc\", label: \"UGC\", description: \"Link added by users, e.g. comments.\" },\n];\n\nexport const hasLink = (v: LinkValue) => !!(v.href || v.email || v.phone);\nexport const TARGET_KEYS = { title: undefined, pageId: undefined, entryId: undefined, assetId: undefined, anchor: undefined } as const;\n\n/** The value a picked target produces (keeps label, style and options). */\nexport function withTarget(v: LinkValue, t: LinkTarget): LinkValue {\n return {\n ...v,\n ...TARGET_KEYS,\n email: undefined,\n phone: undefined,\n subject: undefined,\n type: t.kind === \"file\" ? \"file\" : t.kind === \"entry\" ? \"entry\" : t.kind === \"section\" ? \"section\" : \"page\",\n href: t.href,\n title: t.title,\n pageId: t.kind === \"page\" ? t.id : undefined,\n entryId: t.kind === \"entry\" ? t.id : undefined,\n assetId: t.kind === \"file\" ? t.id : undefined,\n };\n}\n/** The value typed text produces (auto-detects URL / email / phone / #section unless the type was chosen). */\nexport function withText(v: LinkValue, s: string, type?: LinkType): LinkValue {\n const t = type ?? detectType(s);\n const n: LinkValue = { ...v, ...TARGET_KEYS, type: t, email: undefined, phone: undefined };\n if (t === \"email\") Object.assign(n, { email: s.replace(/^mailto:/i, \"\"), href: s });\n else if (t === \"phone\") Object.assign(n, { phone: s.replace(/^tel:/i, \"\"), href: s });\n else n.href = s;\n return n;\n}\n/** Clean a value before it is stored: add https:// to bare domains, refuse script URLs, store the href the site renders. */\nexport function finalizeLink(v: LinkValue): LinkValue | null {\n const out: LinkValue = { ...v };\n if (/^(javascript|data|vbscript):/i.test(out.href.replace(/[\\u0000- ]/g, \"\"))) return null;\n if (out.type === \"url\" && out.href && !/^(https?:|\\/|#)/.test(out.href)) out.href = `https://${out.href.replace(/^\\/+/, \"\")}`;\n // the stored href is the one the site renders (mailto:, tel:, #anchor); every consumer reads `href` as is\n if (hasLink(out)) out.href = hrefOf(out);\n return out;\n}\n/**\n * The object as prod stores it, keyed like the value it replaces (`original`), so an edit changes only what was edited:\n * no undefined keys; no `rel: \"follow\"` (follow is no rel: the backend normalises it away and a button refuses it); no\n * `newTab: false` and no `target` unless the stored value had that key (a stored `target` is kept in sync with newTab,\n * and is then the one that carries it).\n */\nexport function storedLink<T extends LinkValue>(v: T, original?: unknown): T {\n const had = (k: string) => isObj(original) && k in original;\n const out: Record<string, unknown> = {};\n for (const [k, x] of Object.entries(v)) {\n if (x === undefined || k === \"target\") continue;\n if (k === \"rel\" && x === \"follow\") continue;\n if (k === \"newTab\" && !had(\"newTab\") && (x === false || had(\"target\"))) continue;\n out[k] = x;\n }\n if (had(\"target\")) out.target = v.newTab ? \"_blank\" : \"_self\";\n return out as T;\n}\n/** Text the picker's input shows for a value that has no picked target. */\nconst inputText = (v: LinkValue) =>\n v.type === \"email\" ? (v.email ?? v.href.replace(/^mailto:/i, \"\")) : v.type === \"phone\" ? (v.phone ?? v.href.replace(/^tel:/i, \"\")) : v.href;\n\nconst STATUS_LABEL: Record<string, string> = { draft: \"Draft\", changed: \"Edited\", scheduled: \"Scheduled\", review: \"In review\", archived: \"Archived\" };\n\n/* ── How a link reads ───────────────────────────────────────────────── */\nexport function linkIcon(v: LinkValue, target?: LinkTarget): React.ReactNode {\n if (!hasLink(v)) return <IconLink stroke={1.5} />;\n if (target) return target.kind === \"entry\" ? <IconFileDatabase stroke={1.5} /> : target.kind === \"file\" ? <IconPaperclip stroke={1.5} /> : target.kind === \"section\" ? <IconHash stroke={1.5} /> : <IconFile stroke={1.5} />;\n switch (v.type) {\n case \"url\": return <IconExternalLink stroke={1.5} />;\n case \"email\": return <IconMail stroke={1.5} />;\n case \"phone\": return <IconPhone stroke={1.5} />;\n case \"section\": return <IconHash stroke={1.5} />;\n case \"file\": return <IconPaperclip stroke={1.5} />;\n case \"entry\": return <IconFileDatabase stroke={1.5} />;\n default: return <IconFile stroke={1.5} />;\n }\n}\n/** Primary + secondary text: page title + path · domain + rest of the URL · address · number. */\nexport function describeLink(v: LinkValue, target?: LinkTarget): { primary: string; secondary?: string } {\n if (!hasLink(v)) return { primary: \"\" };\n const anchor = v.anchor && v.anchor !== \"none\" ? v.anchor : \"\";\n if (target) return { primary: target.title, secondary: target.kind === \"section\" ? `${target.href} on this page` : target.kind === \"file\" ? fileKind(target) : `${target.href}${anchor}` };\n switch (v.type) {\n case \"url\": {\n try {\n const u = new URL(/^https?:/i.test(v.href) ? v.href : `https://${v.href}`);\n const rest = `${u.pathname === \"/\" ? \"\" : u.pathname}${u.search}${u.hash}`;\n return { primary: u.hostname.replace(/^www\\./, \"\"), secondary: rest || undefined };\n } catch {\n return { primary: v.href };\n }\n }\n case \"email\": return { primary: v.email ?? v.href.replace(/^mailto:/i, \"\").replace(/\\?.*$/, \"\"), secondary: v.subject ? `Subject: ${v.subject}` : undefined };\n case \"phone\": return { primary: v.phone ?? v.href.replace(/^tel:/i, \"\") };\n case \"section\": return { primary: v.href, secondary: \"On this page\" };\n // a stored href already carries its anchor (finalizeLink)\n default: return { primary: v.title || v.href, secondary: v.title ? v.href : undefined };\n }\n}\n/** \"PDF file\": the name is already the title */\nconst fileKind = (t: LinkTarget) => `${t.meta ?? (fileName(t.href).split(\".\").pop() ?? \"\").toUpperCase()} file`.trim();\nfunction fileName(href: string) {\n const last = href.replace(/[?#].*$/, \"\").split(\"/\").pop() ?? href;\n try {\n return decodeURIComponent(last);\n } catch {\n return last;\n }\n}\n/** What a person reads for a link (one string — menus, aria labels, history). */\nexport const linkText = (v: LinkValue) => (hasLink(v) ? v.title || describeLink(v).primary : \"\");\n\n/** A link at rest: icon · title (fg) · path (fg-3) · new-tab mark. Empty → \"Add link\". */\nexport function LinkLine({ v, target, placeholder = \"Add link\", className }: { v: LinkValue; target?: LinkTarget; placeholder?: string; className?: string }) {\n const d = describeLink(v, target);\n const empty = !hasLink(v);\n return (\n <span className={cn(\"flex min-w-0 flex-1 items-center gap-2\", className)}>\n <span className={cn(\"flex shrink-0 [&_svg]:size-4\", empty ? \"text-kit-fg-3\" : \"text-kit-fg-2\")} aria-hidden>{linkIcon(v, target)}</span>\n <span className={cn(\"min-w-0 shrink truncate text-kit-sm\", empty ? \"text-kit-fg-3\" : \"text-kit-fg\")}>{empty ? placeholder : d.primary}</span>\n {d.secondary ? <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{d.secondary}</span> : <span className=\"flex-1\" />}\n {!empty && v.newTab ? (\n <span className=\"inline-flex shrink-0 items-center gap-0.5 text-kit-2xs text-kit-fg-3\">\n <IconArrowUpRight className=\"size-3\" stroke={1.5} aria-hidden />\n New tab\n </span>\n ) : null}\n </span>\n );\n}\n\n/* ── The picker: ONE link input for the whole product ───────────────── */\ntype Row = { key: string; group: string; target: LinkTarget };\n\n/** While the media library is open from a picker, focus sits in its dialog: a quick edit must not close under it. */\nlet libraryOpen = false;\n/** Marks the floating results list, so a quick edit losing focus to it is not \"focus left the editor\". */\nconst LIST_ATTR = \"data-kit-link-list\";\n\nexport interface LinkPickerProps {\n value: LinkValue;\n /** every change: typed text, a picked target, a cleared value */\n onChange: (v: LinkValue) => void;\n /** a target was chosen from the list (quick editors commit here) */\n onPick?: (v: LinkValue) => void;\n /** Enter with no list row active */\n onEnter?: (v: LinkValue) => void;\n /** Escape with the list closed */\n onEscape?: () => void;\n autoFocus?: boolean;\n /** open straight into search (quick edit), even when a target is picked */\n startSearching?: boolean;\n id?: string;\n \"aria-label\"?: string;\n size?: \"sm\" | \"md\";\n /** no border of its own — it sits inside a unit that already draws one (button field) */\n bare?: boolean;\n /** the host shows its own type control (link panel): hide the inline type menu and search only this type */\n lockedType?: LinkType;\n /** results render in the flow under the input instead of a floating list — panels/popovers, never over them */\n inlineList?: boolean;\n /** the link types this place allows. Default: all of them */\n types?: LinkType[];\n /** the value can't be saved as it is (shown as the field's error state) */\n invalid?: boolean;\n \"aria-describedby\"?: string;\n className?: string;\n}\n\nexport function LinkPicker({\n value, onChange, onPick, onEnter, onEscape, autoFocus, startSearching, id, \"aria-label\": ariaLabel = \"Link to\", size = \"md\", bare, lockedType,\n inlineList, types, invalid, \"aria-describedby\": describedBy, className,\n}: LinkPickerProps) {\n const v = normLink(value);\n const host = useLinkTargets();\n const sections = useSectionTargets();\n const { MediaPicker } = useKitServices();\n const targets = React.useMemo(() => [...host.targets, ...sections], [host.targets, sections]);\n const picked = findTarget(targets, v);\n const [library, setLibraryState] = React.useState(false);\n const setLibrary = (o: boolean) => {\n libraryOpen = o;\n setLibraryState(o);\n };\n React.useEffect(() => () => void (libraryOpen = false), []);\n const [fileProblem, setFileProblem] = React.useState<string>();\n const [searching, setSearching] = React.useState(!!startSearching || !picked);\n const [text, setText] = React.useState(() => (picked ? \"\" : inputText(v)));\n const [manualTypeState, setManualType] = React.useState<LinkType | null>(null);\n const manualType = lockedType ?? manualTypeState;\n const [open, setOpen] = React.useState(false);\n const [active, setActive] = React.useState(-1);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const wrapRef = React.useRef<HTMLDivElement>(null);\n const listId = React.useId();\n const type = manualType ?? v.type ?? \"page\";\n const meta = typeMeta(manualType ?? (searching && !text ? \"page\" : v.type));\n const showChip = !!picked && !searching;\n\n React.useEffect(() => {\n if (autoFocus)\n requestAnimationFrame(() => {\n inputRef.current?.focus({ preventScroll: true });\n inputRef.current?.select(); // quick edit: typing replaces, paste replaces\n });\n }, [autoFocus]);\n\n /* rows: the host's pages + every collection's entries (+ files when it lists them) */\n const q = text.trim().toLowerCase().replace(/^[/#]/, \"\");\n const searchable = type === \"page\" || type === \"entry\" || type === \"file\" || (type === \"section\" && sections.length > 0);\n const urlish = type !== \"section\" && (/^(https?:|www\\.|mailto:|tel:|#)/i.test(text.trim()) || (text.trim() !== \"\" && detectType(text) !== \"page\" && !manualType));\n const rows: Row[] = React.useMemo(() => {\n if (!searchable || urlish) return [];\n const pool = targets.filter((t) => (type === \"file\" ? t.kind === \"file\" : type === \"entry\" ? t.kind === \"entry\" : type === \"section\" ? t.kind === \"section\" : t.kind === \"page\" || t.kind === \"entry\"));\n const hit = (t: LinkTarget) => !q || t.title.toLowerCase().includes(q) || t.href.toLowerCase().includes(q) || (t.meta ?? \"\").toLowerCase().includes(q);\n const out: Row[] = [];\n const perGroup = new Map<string, number>();\n const cap = q ? 6 : type === \"page\" ? 4 : 6;\n for (const t of pool) {\n if (!hit(t)) continue;\n const n = perGroup.get(t.group) ?? 0;\n if (n >= cap) continue;\n perGroup.set(t.group, n + 1);\n out.push({ key: `${t.kind}:${t.id}`, group: t.group, target: t });\n }\n // keep each group together, groups in first-seen order (Pages first)\n const order = [...new Set(out.map((r) => r.group))];\n return out.sort((a, b) => order.indexOf(a.group) - order.indexOf(b.group)).slice(0, 24);\n }, [targets, type, q, searchable, urlish]);\n /* No silent empty list: when nothing can be listed, the list says why in one line. */\n const note: string | undefined = (() => {\n if (!searchable || urlish || rows.length) return undefined;\n if (type === \"section\") return undefined;\n if (type === \"file\") return MediaPicker ? \"Choose a file from the library with the folder button.\" : undefined;\n if (host.unavailable) return \"Page search isn't available here. Type a path, like /about.\";\n if (host.error) return `${host.error.replace(/\\.?$/, \".\")} Type a path, like /about.`;\n if (host.loading) return \"Loading pages…\";\n return q ? `Nothing matches “${text.trim()}”. Type a path, like /about.` : type === \"entry\" ? \"No CMS items yet.\" : \"No pages yet. Type a path, like /about.\";\n })();\n const listOpen = open && searching && (rows.length > 0 || !!note);\n /* Esc closes the results first, the surrounding panel only on the next Esc: the list claims the key on window, in the\n capture phase, while it is open. */\n React.useEffect(() => {\n if (!listOpen) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== \"Escape\" || !wrapRef.current?.contains(document.activeElement)) return;\n e.preventDefault();\n e.stopPropagation();\n setOpen(false);\n };\n window.addEventListener(\"keydown\", onKey, true);\n return () => window.removeEventListener(\"keydown\", onKey, true);\n }, [listOpen]);\n\n const choose = (t: LinkTarget) => {\n t.onChoose?.();\n const n = withTarget(v, t);\n setText(\"\");\n setManualType(null);\n setSearching(false);\n setOpen(false);\n setFileProblem(undefined);\n onChange(n);\n onPick?.(n);\n };\n const type_ = (s: string) => {\n setText(s);\n setOpen(true);\n setActive(s.trim() ? 0 : -1);\n onChange(withText(v, s, manualType ?? undefined));\n };\n const clear = () => {\n setText(\"\");\n setManualType(null);\n setSearching(true);\n onChange({ ...withText(v, \"\"), href: \"\" });\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n const setType = (t: LinkType) => {\n setManualType(t);\n setText(\"\");\n setSearching(true);\n onChange({ ...withText(v, \"\", t), href: \"\" });\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n };\n\n const h = size === \"sm\" ? \"h-8\" : \"h-9\";\n const list = (\n <div id={listId} role=\"listbox\" aria-label={type === \"file\" ? \"Files\" : type === \"section\" ? \"Sections on this page\" : \"Pages and CMS items\"} className=\"max-h-72 overflow-y-auto overscroll-contain\">\n {rows.map((r, i) => (\n <React.Fragment key={r.key}>\n {i === 0 || rows[i - 1].group !== r.group ? (\n <div role=\"presentation\" className=\"px-2 pb-1 pt-2 text-kit-xs font-medium text-kit-fg-3 first:pt-1\">\n {r.group}\n </div>\n ) : null}\n <div\n id={`${listId}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n onMouseEnter={() => setActive(i)}\n onClick={() => choose(r.target)}\n className={cn(\"flex h-8 cursor-pointer items-center gap-2 rounded-kit-md px-2 text-kit-sm\", i === active && \"bg-kit-hover\")}\n >\n <span className=\"flex shrink-0 text-kit-fg-3 [&_svg]:size-4\" aria-hidden>\n {linkIcon({ href: r.target.href, type: r.target.kind }, r.target)}\n </span>\n <span className=\"min-w-0 shrink truncate text-kit-fg\">{r.target.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{r.target.kind === \"file\" ? fileName(r.target.href) : r.target.href}</span>\n {r.target.status && STATUS_LABEL[r.target.status] ? <span className=\"shrink-0 text-kit-2xs text-kit-fg-3\">{STATUS_LABEL[r.target.status]}</span> : null}\n </div>\n </React.Fragment>\n ))}\n {!rows.length && note ? (\n <p role=\"status\" className=\"px-2 py-1.5 text-kit-xs text-kit-fg-3\">\n {note}\n </p>\n ) : rows.length && host.error && type !== \"file\" && type !== \"section\" ? (\n /* some targets loaded and some did not (a collection's items): the gap is named under the list */\n <p role=\"status\" className=\"px-2 py-1.5 text-kit-xs text-kit-fg-3\">\n {host.error.replace(/\\.?$/, \".\")}\n </p>\n ) : null}\n </div>\n );\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const typeMenu = (\n <Menu>\n <MenuTrigger\n render={\n <button\n type=\"button\"\n aria-label={`Link type: ${meta.label}`}\n className=\"ml-0.5 flex h-7 shrink-0 items-center gap-0.5 rounded-kit-md px-1.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover [&_svg]:size-3.5\"\n />\n }\n >\n {meta.icon}\n <IconChevronDown className=\"!size-3\" stroke={1.5} />\n </MenuTrigger>\n <MenuContent className=\"min-w-48\">\n {allowed.map((t) => (\n <MenuItem key={t.type} icon={t.icon} onClick={() => setType(t.type)}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n {t.label}\n {t.type === type ? <IconCheck className=\"size-3.5 text-kit-fg-2\" stroke={2} /> : null}\n </span>\n </MenuItem>\n ))}\n </MenuContent>\n </Menu>\n );\n\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-1\", className)}>\n <Popover open={listOpen && !inlineList} onOpenChange={(o) => !o && setOpen(false)}>\n <div ref={wrapRef} className=\"min-w-0\">\n <PopoverAnchor\n className={cn(\n \"flex min-w-0 items-center\",\n bare\n ? \"bg-transparent\"\n : \"rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover focus-within:border-kit-field-border-focus\",\n !bare && invalid && \"border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]\",\n h,\n )}\n >\n {showChip ? (\n <>\n <span className=\"ml-2 flex shrink-0 text-kit-fg-2 [&_svg]:size-4\" aria-hidden>\n {linkIcon(v, picked)}\n </span>\n <button\n id={id}\n type=\"button\"\n onClick={() => {\n setSearching(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }}\n aria-label={`${ariaLabel}: ${picked!.title}, ${picked!.href}. Change`}\n className=\"flex h-full min-w-0 flex-1 items-center gap-2 px-2 text-left outline-none\"\n >\n <span className=\"min-w-0 shrink truncate text-kit-sm text-kit-fg\">{picked!.title}</span>\n <span className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">{describeLink(v, picked).secondary}</span>\n </button>\n <IconButton label=\"Clear link\" size=\"xs\" className=\"mr-1\" onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n </>\n ) : (\n <>\n {lockedType !== undefined || inlineList ? (\n <span className=\"ml-2.5 flex shrink-0 text-kit-fg-3 [&_svg]:size-4\" aria-hidden>\n {meta.icon}\n </span>\n ) : (\n typeMenu\n )}\n <input\n ref={inputRef}\n id={id}\n role=\"combobox\"\n aria-label={ariaLabel}\n aria-invalid={invalid || undefined}\n aria-describedby={describedBy}\n aria-expanded={listOpen}\n aria-controls={listOpen ? listId : undefined}\n aria-autocomplete=\"list\"\n aria-activedescendant={listOpen && active >= 0 && rows[active] ? `${listId}-${active}` : undefined}\n value={text}\n onChange={(e) => type_(e.target.value)}\n onFocus={() => setOpen(true)}\n onBlur={(e) => {\n if (wrapRef.current?.contains(e.relatedTarget as Node)) return;\n if (inlineList) setOpen(false);\n // came from a chip: nothing typed → show the chip again\n if (picked && !text) setSearching(false);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" && rows.length) {\n e.preventDefault();\n setOpen(true);\n setActive((a) => (a + 1) % rows.length);\n } else if (e.key === \"ArrowUp\" && rows.length) {\n e.preventDefault();\n setActive((a) => (a <= 0 ? rows.length - 1 : a - 1));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n if (listOpen && active >= 0 && rows[active]) choose(rows[active].target);\n else onEnter?.(withText(v, text, manualType ?? undefined));\n } else if (e.key === \"Escape\") {\n if (listOpen) {\n e.preventDefault();\n e.stopPropagation();\n setOpen(false);\n } else if (picked && !text && !startSearching) {\n e.preventDefault();\n e.stopPropagation();\n setSearching(false);\n } else if (onEscape) {\n e.preventDefault();\n e.stopPropagation();\n onEscape();\n }\n }\n }}\n placeholder={picked && !text ? picked.title : meta.placeholder}\n autoComplete=\"off\"\n spellCheck={false}\n className=\"h-full min-w-0 flex-1 bg-transparent px-2 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\"\n />\n {text ? (\n <IconButton label=\"Clear\" size=\"xs\" className=\"mr-1\" onMouseDown={(e) => e.preventDefault()} onClick={clear}>\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n {type === \"file\" && MediaPicker ? (\n <IconButton\n label=\"Choose or upload a file\"\n size=\"xs\"\n className=\"mr-1 text-kit-fg-3\"\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => {\n setOpen(false);\n setLibrary(true);\n }}\n >\n <IconFolderOpen stroke={1.5} />\n </IconButton>\n ) : null}\n </>\n )}\n </PopoverAnchor>\n </div>\n <PopoverContent\n keepFocus\n align=\"start\"\n side=\"bottom\"\n sideOffset={4}\n data-kit-link-list=\"\"\n className=\"w-[max(var(--anchor-width),280px)] max-w-[min(420px,calc(100vw-24px))] p-1\"\n >\n {list}\n </PopoverContent>\n </Popover>\n {inlineList && listOpen ? (\n <div className=\"rounded-kit-md border border-kit-line bg-kit-surface p-1 [&_[role=listbox]]:max-h-56\" onMouseDown={(e) => e.preventDefault()}>\n {list}\n </div>\n ) : null}\n {fileProblem ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {fileProblem}\n </p>\n ) : null}\n {/* File: the host's media library (search, folders, upload) is one click away; mounted only while open */}\n {library && MediaPicker ? (\n <MediaPicker\n open\n accept={[\"file\"]}\n onOpenChange={(o) => !o && setLibrary(false)}\n onPick={(a) => {\n if (!a[0]) return;\n const t = fileTarget(a[0]);\n if (\"problem\" in t) setFileProblem(t.problem);\n else choose(t);\n }}\n />\n ) : null}\n </div>\n );\n}\n\n/* ── Shared options (subject · open in new tab · rel) ───────────────── */\nexport function LinkOptions({ v, onChange, compact, disabled }: { v: LinkValue; onChange: (v: LinkValue) => void; compact?: boolean; disabled?: boolean }) {\n const tabId = React.useId();\n return (\n <div className={cn(\"flex flex-col\", compact ? \"gap-2\" : \"gap-2.5\")}>\n {v.type === \"email\" ? (\n <label className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Subject</span>\n <Input size=\"sm\" value={v.subject ?? \"\"} onChange={(e) => onChange({ ...v, subject: e.target.value })} placeholder=\"Wholesale inquiry\" className=\"max-w-52\" />\n </label>\n ) : null}\n <label htmlFor={tabId} className=\"flex min-h-7 items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Open in new tab</span>\n <Switch disabled={disabled} id={tabId} size=\"sm\" checked={!!v.newTab} onCheckedChange={(c) => onChange({ ...v, newTab: c, target: undefined })} />\n </label>\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Rel</span>\n <Select disabled={disabled} aria-label=\"Rel\" size=\"sm\" className=\"w-[168px]\" value={v.rel ?? \"follow\"} onValueChange={(r) => onChange({ ...v, rel: r as LinkRel })} options={REL_ITEMS} />\n </div>\n </div>\n );\n}\n\n/* ── The link element ───────────────────────────────────────────────\n * CPO D48 + D57: the ONE way to edit a link, wherever a link is edited: Type (dropdown) → the target for that type\n * (results appear only once you focus or type, in the flow below the input, never over the panel; File adds the media\n * library) → the error in plain words when it can't be saved → Section on the picked page → the options as plain rows\n * (new tab, rel, subject). Hosts wrap it: the link panel (LinkPopoverBody), the button screen. Controlled: the host owns\n * the value; remount (key) to start over.\n */\nexport function LinkForm({\n value,\n onChange,\n onEnter,\n hideOptions,\n types,\n autoFocus,\n readOnly,\n className,\n}: {\n value: LinkValue;\n onChange: (v: LinkValue) => void;\n /** Enter in the target with a value that can be saved */\n onEnter?: (v: LinkValue) => void;\n /** string-only values: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n /** focus the Type control on open (D48: never the search) */\n autoFocus?: boolean;\n /** the lens can't edit the link: every control is disabled */\n readOnly?: boolean;\n className?: string;\n}) {\n const v = normLink(value);\n const { MediaPicker } = useKitServices();\n const allowed = LINK_TYPES.filter((t) => (!types || types.includes(t.type)) && (t.type !== \"file\" || MediaPicker || v.type === \"file\"));\n const [kind, setKind] = React.useState<LinkType>(() => {\n const k = v.type === \"entry\" && hasLink(v) ? \"page\" : v.type ?? \"page\";\n return allowed.some((t) => t.type === k) ? k : allowed[0]?.type ?? \"page\";\n });\n const [resetKey, setResetKey] = React.useState(0);\n const [touched, setTouched] = React.useState(false);\n const { targets } = useLinkTargets();\n const anchors = findTarget(targets, v)?.anchors;\n const typeId = React.useId();\n const targetId = React.useId();\n const errId = React.useId();\n const problem = touched ? linkProblem(v) : undefined;\n // the type select follows what the target turned out to be (a picked CMS item, a pasted URL) while \"Page\" is searching\n const shownType: LinkType = kind === \"page\" && hasLink(v) ? v.type ?? \"page\" : kind;\n React.useEffect(() => {\n if (autoFocus) requestAnimationFrame(() => document.getElementById(typeId)?.focus({ preventScroll: true }));\n }, [autoFocus, typeId]);\n const changeType = (t: LinkType) => {\n setKind(t);\n setTouched(false);\n onChange({ ...withText(v, \"\", t === \"page\" ? undefined : t), href: \"\", type: t, anchor: undefined });\n setResetKey((k) => k + 1);\n requestAnimationFrame(() => document.getElementById(targetId)?.focus());\n };\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <div className=\"flex items-center justify-between gap-3\">\n <label htmlFor={typeId} className=\"text-kit-xs text-kit-fg-2\">\n Type\n </label>\n <Select disabled={readOnly} id={typeId} size=\"sm\" className=\"w-[180px]\" value={shownType} onValueChange={(t) => changeType(t as LinkType)} options={allowed.map((t) => ({ value: t.type, label: t.label, icon: t.icon }))} />\n </div>\n <div\n className=\"flex flex-col gap-1.5\"\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node)) setTouched(true);\n }}\n >\n <label htmlFor={targetId} className=\"text-kit-xs text-kit-fg-2\">\n {typeMeta(kind).target}\n </label>\n <LinkPicker\n key={resetKey}\n id={targetId}\n size=\"sm\"\n value={v}\n onChange={onChange}\n onPick={() => setTouched(true)}\n onEnter={(n) => {\n setTouched(true);\n if (!linkProblem(n)) onEnter?.(n);\n }}\n lockedType={kind === \"page\" ? undefined : kind}\n inlineList\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n aria-label={typeMeta(kind).target}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {problem}\n </p>\n ) : null}\n </div>\n {anchors?.length ? (\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-kit-xs text-kit-fg-2\">Section</span>\n <Select disabled={readOnly} aria-label=\"Section\"\n size=\"sm\"\n className=\"w-[180px]\"\n value={v.anchor ?? \"none\"}\n onValueChange={(a) => onChange({ ...v, anchor: a })}\n options={[{ value: \"none\", label: \"Top of page\" }, ...anchors.map((a) => ({ value: a, label: a }))]}\n />\n </div>\n ) : null}\n {hideOptions ? null : <LinkOptions v={v} onChange={onChange} compact disabled={readOnly} />}\n </div>\n );\n}\n\n/* ── The link panel ─────────────────────────────────────────────────\n * What it links to now → the link element (LinkForm) → Remove link · Cancel · Apply (Apply only when something changed\n * and the link can be saved). Esc closes the results first, then the panel.\n */\nexport function LinkPopoverBody({\n initial,\n onSave,\n onDetach,\n onCancel,\n hideOptions,\n types,\n}: {\n initial: LinkValue;\n onSave: (v: LinkValue) => void;\n onDetach?: () => void;\n onCancel?: () => void;\n /** string-only fields: no new tab / rel */\n hideOptions?: boolean;\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n}) {\n const start = normLink(initial);\n const [v, setV] = React.useState<LinkValue>(start);\n const { targets } = useLinkTargets();\n const startTarget = findTarget(targets, start);\n const fin = (x: LinkValue) => {\n const f = finalizeLink(x);\n return f ? JSON.stringify(storedLink(f)) : \"\";\n };\n const changed = fin(v) !== fin(start);\n const ok = hasLink(v) && !linkProblem(v);\n const apply = (n = v) => {\n const out = finalizeLink(n);\n if (out && hasLink(out) && !linkProblem(out)) onSave(out);\n };\n return (\n <form\n className=\"flex flex-col gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n apply();\n }}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Link</span>\n {hasLink(start) ? (\n <span className=\"flex min-w-0 text-kit-fg-2\">\n <LinkLine v={start} target={startTarget} />\n </span>\n ) : (\n <span className=\"text-kit-xs text-kit-fg-3\">No link yet</span>\n )}\n </div>\n <LinkForm value={v} onChange={setV} onEnter={(n) => apply(n)} hideOptions={hideOptions} types={types} autoFocus />\n <div className=\"flex items-center gap-2 border-t border-kit-line pt-2.5\">\n {onDetach ? (\n <Button type=\"button\" size=\"xs\" variant=\"danger-ghost\" onClick={onDetach}>\n Remove link\n </Button>\n ) : null}\n <span className=\"flex-1\" />\n {onCancel ? (\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={onCancel}>\n Cancel\n </Button>\n ) : null}\n <Button type=\"submit\" size=\"xs\" variant=\"primary\" disabled={!changed || !ok}>\n Apply\n </Button>\n </div>\n </form>\n );\n}\n\n/* ── Quick edit: the link row turns into the picker in place ───────── */\nexport function LinkQuickEdit({\n value,\n onCommit,\n onDone,\n ariaLabel,\n size,\n bare,\n types,\n}: {\n value: LinkValue;\n /** null = cleared */\n onCommit: (v: LinkValue | null) => void;\n onDone: () => void;\n ariaLabel: string;\n size?: \"sm\" | \"md\";\n bare?: boolean;\n types?: LinkType[];\n}) {\n const [draft, setDraft] = React.useState(value);\n const [problem, setProblem] = React.useState<string>();\n const done = React.useRef(false);\n const ref = React.useRef<HTMLDivElement>(null);\n const errId = React.useId();\n const commit = (n: LinkValue, strict = true) => {\n if (done.current) return;\n if (hasLink(n) && strict && linkProblem(n)) return setProblem(linkProblem(n));\n done.current = true;\n if (!hasLink(n)) onCommit(null);\n else {\n const out = finalizeLink(n);\n // a script link is dropped, never written (finalizeLink refuses it)\n if (out) onCommit(out);\n }\n onDone();\n };\n return (\n <div\n ref={ref}\n className=\"flex min-w-0 flex-col gap-1\"\n onBlur={(e) => {\n const next = e.relatedTarget as HTMLElement | null;\n if (libraryOpen || (next && (ref.current?.contains(next) || next.closest?.(`[${LIST_ATTR}],[role=menu]`)))) return;\n // focus left the editor: keep what was typed (nothing changed → nothing written)\n window.setTimeout(() => {\n if (libraryOpen || done.current || ref.current?.contains(document.activeElement)) return;\n if (hrefOf(draft) === hrefOf(value) && draft.pageId === value.pageId && draft.entryId === value.entryId) {\n done.current = true;\n onDone();\n } else commit(draft, false);\n }, 0);\n }}\n >\n <LinkPicker\n value={draft}\n onChange={(n) => {\n setDraft(n);\n setProblem(undefined);\n }}\n onPick={(n) => commit(n)}\n onEnter={(n) => commit(n)}\n onEscape={() => {\n done.current = true;\n onDone();\n }}\n autoFocus\n startSearching\n aria-label={ariaLabel}\n size={size}\n bare={bare}\n types={types}\n invalid={!!problem}\n aria-describedby={problem ? errId : undefined}\n />\n {problem ? (\n <p id={errId} role=\"alert\" className={cn(\"text-kit-xs text-kit-danger-fg\", bare && \"px-2.5 pb-1.5\")}>\n {problem}\n </p>\n ) : null}\n </div>\n );\n}\n\n/* ── Link field: one bordered row; click edits in place, the sliders icon opens the link panel ── */\nexport interface LinkFieldProps {\n /** a LinkValue or a plain href string */\n value: unknown;\n /** null = cleared (object shape); \"\" = cleared (string shape) */\n onChange: (v: LinkValue | string | null) => void;\n /** \"string\": the value is the href alone. New tab and rel need the object shape, so they hide. */\n valueShape?: \"string\" | \"object\";\n id?: string;\n \"aria-label\": string;\n readOnly?: boolean;\n size?: \"sm\" | \"md\";\n /** the link types this place allows. Default: all */\n types?: LinkType[];\n invalid?: boolean;\n placeholder?: string;\n className?: string;\n}\nexport function LinkField({ value, onChange: write, valueShape, id: idProp, \"aria-label\": label, readOnly, size = \"sm\", types, invalid, placeholder, className }: LinkFieldProps) {\n const v = normLink(value);\n const stringOnly = valueShape === \"string\";\n const onChange = (n: LinkValue | null) => write(stringOnly ? (n ? hrefOf(n) : \"\") : n ? storedLink(n, value) : null);\n const autoId = React.useId();\n const id = idProp ?? autoId;\n const [editing, setEditing] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const { targets } = useLinkTargets();\n const target = findTarget(targets, v);\n const has = hasLink(v);\n if (editing && !readOnly)\n return (\n <LinkQuickEdit\n value={v}\n ariaLabel={label}\n size={size}\n types={types}\n onCommit={onChange}\n onDone={() => {\n setEditing(false);\n requestAnimationFrame(() => document.getElementById(id)?.focus({ preventScroll: true }));\n }}\n />\n );\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverAnchor\n data-kit-link-field=\"\"\n className={cn(\n \"group/link relative flex min-w-0 items-center rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover\",\n size === \"md\" ? \"h-9\" : \"h-8\",\n readOnly && \"hover:border-kit-field-border\",\n invalid && \"border-[var(--kit-field-invalid)]\",\n className,\n )}\n >\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n onClick={() => setEditing(true)}\n aria-label={has ? `${label}: ${describeLink(v, target).primary}. Edit link` : `Add ${label.toLowerCase()}`}\n aria-invalid={invalid || undefined}\n className=\"flex h-full min-w-0 flex-1 items-center px-2.5 text-left outline-none disabled:cursor-default\"\n >\n <LinkLine v={v} target={target} placeholder={placeholder} />\n </button>\n {readOnly ? null : (\n <span className=\"mr-1 flex shrink-0 items-center gap-0.5\">\n <Tooltip content=\"Link options\">\n <PopoverTrigger\n render={\n <IconButton label=\"Link options\" tooltip={false} size=\"xs\" className=\"text-kit-fg-3\">\n <IconAdjustmentsHorizontal stroke={1.5} />\n </IconButton>\n }\n />\n </Tooltip>\n {has ? (\n <IconButton\n label={`Clear ${label.toLowerCase()}`}\n size=\"xs\"\n className=\"hidden text-kit-fg-3 group-hover/link:inline-flex group-focus-within/link:inline-flex [@media(pointer:coarse)]:inline-flex\"\n onClick={() => onChange(null)}\n >\n <IconX stroke={1.5} />\n </IconButton>\n ) : null}\n </span>\n )}\n </PopoverAnchor>\n <PopoverContent className=\"w-[340px] p-3\" align=\"start\">\n <LinkPopoverBody\n initial={v}\n hideOptions={stringOnly}\n types={types}\n onSave={(n) => {\n onChange(n);\n setOpen(false);\n }}\n onDetach={\n has\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n onCancel={() => setOpen(false)}\n />\n </PopoverContent>\n </Popover>\n );\n}\n\n/**\n * The shape a link field writes: the shape its value already has (a string stays a string, an object an object), and\n * for an empty field `field.valueShape`, else the string prod stores by default.\n */\nexport function linkShapeOf(value: unknown, valueShape?: \"string\" | \"object\"): \"string\" | \"object\" {\n if (isObj(value)) return \"object\";\n if (typeof value === \"string\" && value !== \"\") return \"string\";\n return valueShape ?? \"string\";\n}\n\n/** The Block Kit `link` field: the LinkField above, sized for the form it sits in. */\nexport function LinkControl({ value, onChange, readOnly, id, field, invalid }: ControlProps) {\n const { variant } = useKitEnv();\n return (\n <LinkField\n id={id}\n value={value}\n onChange={onChange}\n valueShape={linkShapeOf(value, field.valueShape)}\n aria-label={field.title}\n readOnly={readOnly}\n size={variant === \"document\" ? \"md\" : \"sm\"}\n invalid={invalid}\n />\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"location-register.js","names":[],"sources":["../../src/kit/controls/location-register.ts"],"sourcesContent":["/** Lane C3: the geopoint (prod `location`) field in the engine's dispatch table (one line per type; merge by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { LocationControl } from \"./location\";\n\nCONTROLS.geopoint = LocationControl;\n"],"mappings":";;;;AAIA,SAAS,WAAW"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"location.js","names":[],"sources":["../../src/kit/controls/location.tsx"],"sourcesContent":["/**\n * LOCATION — the geopoint field (DESIGN 8.21), V2 GeoControl fitted to what prod stores.\n *\n * Value (backend reference-validation `location`, the classic LocationField): `{ lat, lng, label? }`, lat −90…90 and\n * lng −180…180, finite numbers; null when empty. Keys the stored object carries beyond those are kept.\n *\n * A coordinate is written only when it is whole: both numbers, in range. Until then the field says what is missing\n * (\"Add the longitude too\") and keeps the stored value, because the backend refuses half a coordinate. Emptying all\n * three boxes clears the value. Pasting \"44.0582, -121.3153\" into either box fills both.\n *\n * The card above the inputs shows the pin and the coordinates, with a link that opens them on OpenStreetMap; it\n * draws no map tiles (no vendor, key or bundle).\n */\nimport * as React from \"react\";\nimport { IconExternalLink, IconMapPin } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport type { ControlProps } from \"../types\";\nimport { Input } from \"../ui/input\";\n\ninterface Draft {\n lat: string;\n lng: string;\n label: string;\n}\nconst num = (v: unknown) => (typeof v === \"number\" && Number.isFinite(v) ? String(v) : \"\");\nconst draftOf = (v: unknown): Draft => (isObj(v) ? { lat: num(v.lat), lng: num(v.lng), label: typeof v.label === \"string\" ? v.label : \"\" } : { lat: \"\", lng: \"\", label: \"\" });\nconst PAIR = /^\\s*(-?\\d+(?:\\.\\d+)?)\\s*[,;\\s]\\s*(-?\\d+(?:\\.\\d+)?)\\s*$/;\n\n/** The value a draft writes, or the reason it can't be written yet. */\nexport function locationFromDraft(d: Draft, prev: unknown): { ok: true; value: Record<string, unknown> | null } | { ok: false; reason: string } {\n const lat = d.lat.trim();\n const lng = d.lng.trim();\n const label = d.label.trim();\n if (!lat && !lng && !label) return { ok: true, value: null };\n if (!lat || !lng) return { ok: false, reason: !lat && !lng ? \"Add a latitude and a longitude to save this location.\" : !lat ? \"Add the latitude too: a location needs both.\" : \"Add the longitude too: a location needs both.\" };\n const la = Number(lat);\n const lo = Number(lng);\n if (!Number.isFinite(la) || Math.abs(la) > 90) return { ok: false, reason: \"Latitude must be a number from −90 to 90.\" };\n if (!Number.isFinite(lo) || Math.abs(lo) > 180) return { ok: false, reason: \"Longitude must be a number from −180 to 180.\" };\n const out: Record<string, unknown> = { ...(isObj(prev) ? prev : {}), lat: la, lng: lo };\n if (label) out.label = label;\n else delete out.label;\n return { ok: true, value: out };\n}\n\nexport function LocationControl({ field, value, onChange, readOnly, id, invalid }: ControlProps) {\n const [draft, setDraft] = React.useState<Draft>(() => draftOf(value));\n const [seen, setSeen] = React.useState(value);\n const [mine, setMine] = React.useState<unknown>(undefined);\n // a value set from elsewhere (undo, another editor) replaces the draft; our own writes keep what the author typed\n if (value !== seen) {\n setSeen(value);\n if (value !== mine) setDraft(draftOf(value));\n }\n const result = locationFromDraft(draft, value);\n const reasonId = `${id}-reason`;\n\n const update = (patch: Partial<Draft>) => {\n const next = { ...draft, ...patch };\n setDraft(next);\n const r = locationFromDraft(next, value);\n if (!r.ok) return;\n const same = JSON.stringify(r.value) === JSON.stringify(value ?? null);\n if (same) return;\n setMine(r.value);\n onChange(r.value);\n };\n const coordinate = (key: \"lat\" | \"lng\") => (e: React.ChangeEvent<HTMLInputElement>) => {\n const pair = PAIR.exec(e.target.value);\n update(pair ? { lat: pair[1], lng: pair[2] } : ({ [key]: e.target.value } as Partial<Draft>));\n };\n\n const shown = isObj(value) && typeof value.lat === \"number\" && typeof value.lng === \"number\" ? { lat: value.lat, lng: value.lng } : null;\n return (\n <div className={cn(\"overflow-hidden rounded-kit-lg border\", invalid ? \"border-[var(--kit-field-invalid)]\" : \"border-kit-line\")}>\n <div\n className=\"relative h-28 overflow-hidden bg-kit-subtle\"\n style={{ backgroundImage: \"linear-gradient(var(--kit-line-subtle) 1px, transparent 1px), linear-gradient(90deg, var(--kit-line-subtle) 1px, transparent 1px)\", backgroundSize: \"16px 16px\" }}\n >\n {shown ? (\n <>\n <div className=\"absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-full flex-col items-center\" aria-hidden>\n <span className=\"flex size-7 items-center justify-center rounded-full bg-kit-inverse text-kit-fg-inverse shadow-kit-md\">\n <IconMapPin className=\"size-4\" stroke={1.5} />\n </span>\n <span className=\"size-2 -translate-y-0.5 rotate-45 bg-kit-inverse\" />\n </div>\n <a\n href={`https://www.openstreetmap.org/?mlat=${shown.lat}&mlon=${shown.lng}#map=15/${shown.lat}/${shown.lng}`}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"absolute bottom-2 right-2 flex items-center gap-1 rounded-kit-md bg-kit-surface/90 px-1.5 py-0.5 font-kit-mono text-kit-2xs tabular-nums text-kit-fg-2 shadow-kit-xs outline-none hover:text-kit-fg focus-visible:outline-2 focus-visible:outline-kit-focus-ring\"\n aria-label={`Open ${shown.lat.toFixed(4)}, ${shown.lng.toFixed(4)} on OpenStreetMap (new tab)`}\n >\n {shown.lat.toFixed(4)}, {shown.lng.toFixed(4)}\n <IconExternalLink className=\"size-3\" stroke={1.5} aria-hidden />\n </a>\n </>\n ) : (\n <p className=\"absolute inset-0 flex items-center justify-center text-kit-xs text-kit-fg-3\">No coordinates yet</p>\n )}\n </div>\n <div className=\"flex flex-col gap-2 p-2\">\n <Input\n id={id}\n value={draft.label}\n readOnly={readOnly}\n placeholder=\"Label, e.g. Head office\"\n aria-label={`${field.title} label`}\n leading={<IconMapPin stroke={1.5} />}\n onChange={(e) => update({ label: e.target.value })}\n />\n <div className=\"grid grid-cols-2 gap-2\">\n <Input\n id={`${id}-lat`}\n size=\"sm\"\n inputMode=\"decimal\"\n value={draft.lat}\n readOnly={readOnly}\n aria-label={`${field.title} latitude`}\n aria-invalid={(!result.ok && /latitude/i.test(result.reason)) || undefined}\n aria-describedby={!result.ok ? reasonId : undefined}\n placeholder=\"−90 to 90\"\n onChange={coordinate(\"lat\")}\n leading={<span className=\"text-kit-2xs\">Lat</span>}\n />\n <Input\n id={`${id}-lng`}\n size=\"sm\"\n inputMode=\"decimal\"\n value={draft.lng}\n readOnly={readOnly}\n aria-label={`${field.title} longitude`}\n aria-invalid={(!result.ok && /longitude/i.test(result.reason)) || undefined}\n aria-describedby={!result.ok ? reasonId : undefined}\n placeholder=\"−180 to 180\"\n onChange={coordinate(\"lng\")}\n leading={<span className=\"text-kit-2xs\">Long</span>}\n />\n </div>\n {!result.ok ? (\n <p id={reasonId} role=\"status\" className=\"text-kit-xs text-kit-warning-fg\">\n {result.reason}\n </p>\n ) : null}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"media-register.js","names":[],"sources":["../../src/kit/controls/media-register.ts"],"sourcesContent":["/** Lane C4: the media controls in the engine's dispatch tables (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { ARRAY_CONTROLS } from \"../engine/array\";\nimport { FileControl, GalleryControl, ImageControl, VideoControl } from \"./media\";\n\nCONTROLS.image = ImageControl;\nCONTROLS.file = FileControl;\nCONTROLS.video = VideoControl;\nARRAY_CONTROLS.gallery = GalleryControl;\n"],"mappings":";;;;;AAKA,SAAS,QAAQ;AACjB,SAAS,OAAO;AAChB,SAAS,QAAQ;AACjB,eAAe,UAAU"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"media.js","names":[],"sources":["../../src/kit/controls/media.tsx"],"sourcesContent":["/**\n * MEDIA — image · gallery · file · video (V2 HEAD 9829bf1 kit/controls/media.tsx, DESIGN.md 8.15).\n *\n * Production parity: dashed drop well (\"Add an image / Or drop or paste one here\"), filled 16:9 preview with Replace and\n * Remove pills, the caption \"{file} · W × H · No alt text\" and a ⋯ whose \"Alt text and details\" opens a popover (alt\n * text, focal point, file name). The media library picker, the upload and the asset metadata are KitServices\n * (media-services.ts): the kit never imports a feature, and a missing service is named in words, never faked.\n *\n * Kit deviations from V2, each because of what the backend stores (adapters/values.ts):\n * - no \"Crop for this placement\" dropdown: `imageToProd` cannot store a crop preset (it becomes a pixel rect only with\n * the asset's size, and never reads back as the preset), so the dock would refuse every write that carried one;\n * - a picked asset's width / height / size are read for the caption, never written into the value (prod rebuilds the\n * value from url, id, name, altText and focal; the rest would be refused);\n * - where the host stores the URL string only (`imageStoresUrl`, the dock's top-level image props) the value stays a\n * string, and alt text and focal point are the media library's (said in the details popover);\n * - no built-in demo picker, no simulated upload, no stock poster frames;\n * - the gallery sorts with the engine's `useDragReorder` (@dnd-kit is not on the kit allow-list);\n * - a typed video URL is held as a draft until it is one prod stores (http(s) or a site path), so the dock never\n * refuses a half-typed address.\n */\nimport * as React from \"react\";\nimport {\n IconAlertTriangle,\n IconDots,\n IconDownload,\n IconExternalLink,\n IconFileText,\n IconFocusCentered,\n IconLink,\n IconPhoto,\n IconPlayerPlay,\n IconPlus,\n IconReplace,\n IconTrash,\n IconUpload,\n IconVideo,\n IconWorld,\n IconX,\n} from \"@tabler/icons-react\";\nimport type {} from \"./media-services\";\nimport { Button } from \"../ui/button\";\nimport { Input, Textarea } from \"../ui/input\";\nimport { Progress } from \"../ui/controls\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverAnchor, PopoverContent, Tooltip } from \"../ui/overlay\";\nimport { cn } from \"../lib/cn\";\nimport { isObj } from \"../lib/path\";\nimport { useDragReorder } from \"../engine/item-list\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices } from \"../context\";\nimport type { ControlProps } from \"../types\";\n\n/* ── Values ─────────────────────────────────────────────────────────── */\n/** The image value the kit edits (V2 ImageValue, minus what prod cannot store: crop, caption, width, height, size). */\nexport interface ImageValue {\n url: string;\n alt?: string;\n /** percent */\n focal?: { x: number; y: number };\n name?: string;\n id?: string;\n [key: string]: unknown;\n}\n\nexport const fileNameFromUrl = (url: string) => {\n const last = url.split(\"?\")[0].split(\"#\")[0].split(\"/\").filter(Boolean).pop() ?? \"\";\n try {\n return decodeURIComponent(last);\n } catch {\n return last;\n }\n};\n\nexport const normImage = (v: unknown): ImageValue | null => {\n if (typeof v === \"string\") return v ? { url: v } : null;\n return isObj(v) && typeof v.url === \"string\" && v.url ? (v as ImageValue) : null;\n};\n\n/** What an asset becomes in a value: the keys prod keeps (url, id, name, alt), nothing measured. */\nexport const fromAsset = (a: KitMediaAsset): ImageValue => {\n const out: ImageValue = { url: a.url, id: a.id };\n if (a.name) out.name = a.name;\n if (a.alt) out.alt = a.alt;\n return out;\n};\n\nexport const formatBytes = (n: number) => (n >= 1_000_000 ? `${(n / 1_000_000).toFixed(1)} MB` : `${Math.max(1, Math.round(n / 1000))} KB`);\n\nconst HTTP = /^https?:\\/\\/\\S+$/i;\n/** An http(s) URL or a site path: what prod's video value takes (video-value.ts isVideoUrl). */\nexport const isVideoUrl = (s: string) => s === \"\" || HTTP.test(s.trim()) || /^\\/(?!\\/)\\S*$/.test(s.trim());\n\nconst NO_ASSET = () => undefined;\nconst NO_SRC = (u: string) => u;\n\n/** The services the media controls read, each hook stable across renders. */\nfunction useMedia() {\n const s = useKitServices();\n return { s, useAsset: s.useMediaAsset ?? NO_ASSET, src: s.mediaSrc ?? NO_SRC };\n}\n\n/** Files the field takes, by `accept` (an `image/*`, `.pdf`, `*` list). */\nexport function acceptsFile(accept: string, file: Pick<File, \"type\" | \"name\">): boolean {\n return accept.split(\",\").some((raw) => {\n const rule = raw.trim().toLowerCase();\n if (!rule || rule === \"*\" || rule === \"*/*\") return true;\n if (rule.startsWith(\".\")) return file.name.toLowerCase().endsWith(rule);\n if (rule.endsWith(\"/*\")) return file.type.toLowerCase().startsWith(rule.slice(0, -1));\n return file.type.toLowerCase() === rule;\n });\n}\n\n/* ── Picker and upload (services) ─────────────────────────────────────── */\nexport function MediaPicker(p: React.ComponentProps<NonNullable<KitServices[\"MediaPicker\"]>>) {\n const Picker = useKitServices().MediaPicker;\n return Picker ? <Picker {...p} /> : null;\n}\n\n/**\n * Upload through the host's media library: progress while it runs, the assets handed to `onDone`, and a named reason\n * when it fails or a file is the wrong kind. `run` is undefined when the host has no upload service.\n */\nexport function useUpload(accept: string, kind: string, onDone: (a: KitMediaAsset[]) => void) {\n const { uploadMedia, onUploaded, toast } = useKitServices();\n const [progress, setProgress] = React.useState<number | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n const alive = React.useRef(true);\n React.useEffect(\n () => () => {\n alive.current = false;\n },\n [],\n );\n const run = uploadMedia\n ? (files: File[]) => {\n if (!files.length || progress != null) return;\n const bad = files.find((f) => !acceptsFile(accept, f));\n if (bad) {\n setError(`${bad.name || \"That file\"} isn't ${kind === \"file\" ? \"a file this field takes\" : `an ${kind}`}.`);\n return;\n }\n setError(null);\n setProgress(0);\n uploadMedia(files, { onProgress: (f) => alive.current && setProgress(Math.round(Math.min(1, Math.max(0, f)) * 100)) })\n .then((assets) => {\n if (!alive.current) return;\n setProgress(null);\n onUploaded?.(assets);\n onDone(assets);\n toast?.success(files.length > 1 ? `${files.length} files uploaded` : `${assets[0]?.name ?? files[0].name} uploaded`, { description: \"Added to the media library\" });\n })\n .catch((e: unknown) => {\n if (!alive.current) return;\n setProgress(null);\n setError(`Upload failed: ${e instanceof Error ? e.message : String(e)}`);\n });\n }\n : undefined;\n return { progress, error, setError, run };\n}\n\n/** A line under a control that says why something did not happen (role=\"alert\": it is the answer to an action). */\nfunction Reason({ children, tone = \"danger\" }: { children: React.ReactNode; tone?: \"danger\" | \"muted\" }) {\n return (\n <p role={tone === \"danger\" ? \"alert\" : \"note\"} className={cn(\"text-kit-xs\", tone === \"danger\" ? \"text-kit-danger-fg\" : \"text-kit-fg-3\")}>\n {children}\n </p>\n );\n}\n\n/* ── Drop well (drag · paste · upload · library · URL) ─────────────── */\nfunction DropWell({\n id,\n title,\n hint,\n accept,\n multiple,\n icon,\n disabled,\n onFiles,\n onLibrary,\n onUrl,\n refuse,\n progress,\n}: {\n id?: string;\n title: string;\n hint: string;\n accept: string;\n multiple?: boolean;\n icon: React.ReactNode;\n disabled?: boolean;\n /** undefined: the host has no upload service (no Upload button, drop or paste) */\n onFiles?: (f: File[]) => void;\n /** undefined: the host has no media library */\n onLibrary?: () => void;\n onUrl?: (url: string) => void;\n /** set: Media library and Upload stay drawn (V2's well) when the host has no such service, and a click, drop or\n * paste says why through this instead */\n refuse?: (reason: string) => void;\n progress: number | null;\n}) {\n const [over, setOver] = React.useState(false);\n const [urlMode, setUrlMode] = React.useState(false);\n const [url, setUrl] = React.useState(\"\");\n const [urlError, setUrlError] = React.useState<string | null>(null);\n const input = React.useRef<HTMLInputElement>(null);\n const takesFiles = (!!onFiles || !!refuse) && !disabled;\n const files = (f: File[]) => (onFiles ? onFiles(f) : refuse?.(NO_UPLOAD));\n const pickFiles = () => (onFiles ? input.current?.click() : refuse?.(NO_UPLOAD));\n return (\n <div\n id={id}\n tabIndex={disabled ? -1 : 0}\n role=\"group\"\n aria-label={takesFiles ? `${title}. Paste an image or press Enter to upload` : title}\n onPaste={(e) => {\n const pasted = Array.from(e.clipboardData.files);\n if (pasted.length && takesFiles) {\n e.preventDefault();\n files(pasted);\n }\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && e.target === e.currentTarget && takesFiles) {\n e.preventDefault();\n pickFiles();\n }\n }}\n onDragOver={(e) => {\n if (!takesFiles) return;\n e.preventDefault();\n setOver(true);\n }}\n onDragLeave={(e) => {\n // entering a child (the URL button, the input) fires dragleave on the well: only leaving the well clears it\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setOver(false);\n }}\n onDrop={(e) => {\n if (!takesFiles) return;\n e.preventDefault();\n setOver(false);\n files(Array.from(e.dataTransfer.files));\n }}\n data-slot=\"kit-drop-well\"\n className={cn(\n \"relative flex flex-col items-center gap-2.5 rounded-kit-lg border border-dashed px-4 py-5 text-center transition-colors\",\n over ? \"border-kit-accent bg-kit-accent-softer\" : \"border-kit-line-strong bg-kit-subtle hover:border-kit-field-border-hover\",\n )}\n >\n <span className={cn(\"flex size-9 items-center justify-center rounded-kit-lg border border-kit-line bg-kit-control-bg text-kit-fg-3 [&_svg]:size-[18px]\", over && \"text-kit-accent-fg\")}>{icon}</span>\n <div>\n <div className=\"text-kit-sm font-medium text-kit-fg\">{over ? \"Drop to upload\" : title}</div>\n {takesFiles ? <div className=\"text-kit-xs text-kit-fg-3\">{hint}</div> : null}\n </div>\n {urlMode && onUrl ? (\n <form\n className=\"flex w-full max-w-sm flex-col gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const v = url.trim();\n if (HTTP.test(v)) {\n onUrl(v);\n setUrlMode(false);\n setUrl(\"\");\n setUrlError(null);\n } else setUrlError(\"Use a full image URL, like https://…/photo.jpg\");\n }}\n onKeyDown={(e) => {\n if (e.key === \"Escape\") {\n e.stopPropagation();\n setUrlMode(false);\n setUrlError(null);\n }\n }}\n >\n <div className=\"flex items-center gap-1.5\">\n <Input\n autoFocus\n size=\"sm\"\n value={url}\n aria-label=\"Image URL\"\n aria-invalid={urlError ? true : undefined}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://…/photo.jpg\"\n leading={<IconLink stroke={1.5} />}\n className=\"flex-1\"\n />\n <Button size=\"sm\" type=\"submit\" variant=\"primary\">\n Add\n </Button>\n </div>\n {urlError ? <Reason>{urlError}</Reason> : null}\n </form>\n ) : (\n <div className=\"flex flex-wrap justify-center gap-1.5\">\n {onLibrary || refuse ? (\n <Button size=\"sm\" variant=\"secondary\" onClick={onLibrary ?? (() => refuse!(NO_LIBRARY))} disabled={disabled}>\n Media library\n </Button>\n ) : null}\n {onFiles || refuse ? (\n <Button size=\"sm\" variant=\"ghost\" leftIcon={<IconUpload stroke={1.5} />} onClick={pickFiles} disabled={disabled}>\n Upload\n </Button>\n ) : null}\n {onUrl ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={() => setUrlMode(true)} disabled={disabled}>\n Paste URL\n </Button>\n ) : null}\n </div>\n )}\n {onFiles ? (\n <input\n ref={input}\n type=\"file\"\n hidden\n tabIndex={-1}\n aria-hidden\n accept={accept}\n multiple={multiple}\n onChange={(e) => {\n onFiles(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n ) : null}\n {progress != null ? (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 rounded-kit-lg bg-kit-surface px-8\">\n <span className=\"text-kit-sm text-kit-fg-2\">\n <span role=\"status\">Uploading…</span> {progress}%\n </span>\n <Progress value={progress} tone=\"ink\" label=\"Upload progress\" className=\"max-w-56\" />\n </div>\n ) : null}\n </div>\n );\n}\n\n/** Why the drop well offers nothing to pick with (no library, no upload): said once, in words. */\nconst NO_SOURCE = \"No media library or upload is connected to this editor, so nothing can be chosen here.\";\nconst NO_LIBRARY = \"No media library is connected to this editor, so nothing can be picked from it here.\";\nconst NO_UPLOAD = \"No upload is connected to this editor, so files can't be uploaded here.\";\n\n/* ── Image ─────────────────────────────────────────────────────────── */\nfunction ImageDetails({\n v,\n onChange,\n readOnly,\n label,\n urlOnly,\n size,\n asset,\n}: {\n v: ImageValue;\n onChange: (n: ImageValue) => void;\n readOnly?: boolean;\n label: string;\n urlOnly: boolean;\n size?: { w: number; h: number };\n asset?: KitMediaAsset;\n}) {\n const { src } = useMedia();\n const focal = v.focal ?? { x: 50, y: 50 };\n const setFocal = (x: number, y: number) => onChange({ ...v, focal: { x: Math.round(Math.min(100, Math.max(0, x))), y: Math.round(Math.min(100, Math.max(0, y))) } });\n const fromPointer = (e: React.PointerEvent<HTMLDivElement>) => {\n const r = e.currentTarget.getBoundingClientRect();\n if (!r.width || !r.height) return;\n setFocal(((e.clientX - r.left) / r.width) * 100, ((e.clientY - r.top) / r.height) * 100);\n };\n return (\n <div className=\"flex flex-col gap-3\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-kit-sm font-medium text-kit-fg\">Alt text and details</span>\n {size ? (\n <span className=\"tabular-nums text-kit-2xs text-kit-fg-3\">\n {size.w} × {size.h}\n </span>\n ) : null}\n </div>\n {urlOnly ? (\n <>\n <Reason tone=\"muted\">This placement stores the image address only, so its alt text and focal point are the media library's.</Reason>\n {asset?.alt ? (\n <div className=\"flex flex-col gap-1\">\n <span className=\"text-kit-xs text-kit-fg-3\">Alt text in the media library</span>\n <span className=\"text-kit-sm text-kit-fg\">{asset.alt}</span>\n </div>\n ) : null}\n </>\n ) : (\n <>\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-kit-xs text-kit-fg-3\">Alt text</span>\n <Textarea\n rows={2}\n value={v.alt ?? \"\"}\n readOnly={readOnly}\n onChange={(e) => {\n const alt = e.target.value;\n const next = { ...v };\n if (alt) next.alt = alt;\n else delete next.alt;\n onChange(next);\n }}\n placeholder=\"Describe the image for accessibility\"\n className=\"min-h-14 text-kit-sm\"\n aria-label={`${label} alt text`}\n />\n </label>\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center justify-between\">\n <span className=\"flex items-center gap-1 text-kit-xs text-kit-fg-3\">\n <IconFocusCentered className=\"size-3.5\" stroke={1.5} aria-hidden />\n Focal point\n </span>\n <span className=\"tabular-nums text-kit-2xs text-kit-fg-3\">\n Focal {focal.x}%, {focal.y}%\n </span>\n </div>\n <div\n role=\"slider\"\n aria-label=\"Focal point. Click the subject.\"\n aria-valuetext={`${focal.x}% across, ${focal.y}% down`}\n aria-valuenow={focal.x}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-readonly={readOnly || undefined}\n tabIndex={0}\n onPointerDown={(e) => !readOnly && fromPointer(e)}\n onKeyDown={(e) => {\n const d = e.shiftKey ? 10 : 2;\n const m: Record<string, [number, number]> = { ArrowLeft: [-d, 0], ArrowRight: [d, 0], ArrowUp: [0, -d], ArrowDown: [0, d] };\n const step = m[e.key];\n if (!step || readOnly) return;\n e.preventDefault();\n setFocal(focal.x + step[0], focal.y + step[1]);\n }}\n className=\"relative mt-1 aspect-[3/2] cursor-crosshair overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted\"\n >\n <img src={src(v.url)} alt=\"\" draggable={false} className=\"pointer-events-none size-full select-none object-cover transition-[object-position] duration-200 motion-reduce:transition-none\" style={{ objectPosition: `${focal.x}% ${focal.y}%` }} />\n <span\n aria-hidden\n className=\"pointer-events-none absolute size-5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-kit-fg-inverse bg-kit-inverse/30 shadow-kit-md transition-[left,top] duration-150 motion-reduce:transition-none\"\n style={{ left: `${focal.x}%`, top: `${focal.y}%` }}\n />\n </div>\n <span className=\"text-kit-2xs text-kit-fg-3\">Click the subject. It stays in frame on every screen size.</span>\n </div>\n </>\n )}\n <div className=\"flex flex-col gap-1.5\">\n <span className=\"text-kit-xs text-kit-fg-3\">File name</span>\n <span className=\"truncate font-kit-mono text-kit-xs text-kit-fg\">{asset?.name ?? v.name ?? fileNameFromUrl(v.url)}</span>\n </div>\n </div>\n );\n}\n\n/** The width × height a stored image value carries (positive numbers only), else undefined. */\nfunction storedSize(value: unknown): { w: number; h: number } | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const { width, height } = value as { width?: unknown; height?: unknown };\n return typeof width === \"number\" && typeof height === \"number\" && width > 0 && height > 0 ? { w: width, h: height } : undefined;\n}\n\nconst PILL = \"flex h-7 items-center gap-1 rounded-full border border-kit-swatch-ring bg-kit-control-bg px-2.5 text-kit-xs font-medium text-kit-fg shadow-kit-sm\";\n\nexport function ImageControl({ field, value, onChange: write, readOnly, id, path }: ControlProps) {\n const { s, useAsset, src } = useMedia();\n const env = useKitEnv();\n const urlOnly = !!s.imageStoresUrl?.(path);\n const legacyString = typeof value === \"string\" || field.valueShape === \"string\";\n const v = normImage(value);\n const asset = useAsset({ id: v?.id, url: v?.url ?? \"\" });\n const [natural, setNatural] = React.useState<{ w: number; h: number } | undefined>();\n React.useEffect(() => setNatural(undefined), [v?.url]);\n // V2's order: the library asset's dimensions, then the ones stored on the value (an imported or retina source keeps\n // its real size there), and only then the loaded preview's natural size (a resized preview reads smaller)\n const stored = storedSize(value);\n const size = asset?.width && asset.height ? { w: asset.width, h: asset.height } : stored ?? natural;\n\n /* the URL-string placements write the URL; legacy strings stay strings until alt or focal needs the object */\n const onChange = (n: ImageValue | null) => {\n if (!n) return write(urlOnly ? \"\" : null);\n if (urlOnly) return write(n.url);\n if (legacyString && !n.alt && !n.focal) return write(n.url);\n write(n);\n };\n const [picker, setPicker] = React.useState(false);\n const [details, setDetails] = React.useState(false);\n const up = useUpload(\"image/*\", \"image\", (a) => a[0] && onChange(fromAsset(a[0])));\n const library = s.MediaPicker && !readOnly ? () => setPicker(true) : undefined;\n\n if (!v)\n return (\n <div className=\"flex flex-col gap-1.5\">\n <DropWell\n id={id}\n title=\"Add an image\"\n hint=\"Or drop or paste one here\"\n accept=\"image/*\"\n icon={<IconPhoto stroke={1.5} />}\n onFiles={up.run}\n onLibrary={library}\n onUrl={readOnly ? undefined : (url) => onChange({ url, name: fileNameFromUrl(url) || undefined })}\n refuse={up.setError}\n disabled={readOnly}\n progress={up.progress}\n />\n {up.error ? <Reason>{up.error}</Reason> : null}\n <MediaPicker open={picker} onOpenChange={setPicker} accept={[\"image\", \"svg\"]} onPick={(a) => a[0] && onChange(fromAsset(a[0]))} />\n </div>\n );\n\n const focal = v.focal ?? { x: 50, y: 50 };\n const alt = urlOnly ? asset?.alt : v.alt;\n const name = asset?.name ?? v.name ?? fileNameFromUrl(v.url);\n const replace = (a: KitMediaAsset) => {\n const next = fromAsset(a);\n if (!next.alt && v.alt) next.alt = v.alt;\n if (v.focal) next.focal = v.focal;\n onChange(next);\n };\n const openDetails = () => window.setTimeout(() => setDetails(true), 0);\n return (\n <Popover open={details} onOpenChange={setDetails}>\n <PopoverAnchor\n className={cn(\"flex flex-col gap-1.5\", env.variant === \"document\" && \"max-w-xl\")}\n onPaste={(e: React.ClipboardEvent) => {\n const files = Array.from(e.clipboardData.files);\n if (files.length && up.run && !readOnly) {\n e.preventDefault();\n up.run(files);\n }\n }}\n >\n <div className=\"group/img relative aspect-video overflow-hidden rounded-kit-lg border border-kit-line bg-kit-muted\">\n <button\n id={id}\n type=\"button\"\n disabled={readOnly}\n onClick={() => (library ? library() : openDetails())}\n aria-label={library ? `Replace ${field.title}` : `${field.title} details`}\n className=\"block size-full outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none\"\n >\n <img\n src={src(v.url)}\n alt={alt ?? \"\"}\n onLoad={(e) => {\n const img = e.currentTarget;\n if (img.naturalWidth && img.naturalHeight) setNatural({ w: img.naturalWidth, h: img.naturalHeight });\n }}\n className=\"size-full object-cover\"\n style={{ objectPosition: `${focal.x}% ${focal.y}%` }}\n />\n </button>\n {readOnly ? null : (\n <div className=\"absolute right-2 top-2 flex gap-1 opacity-0 transition-opacity focus-within:opacity-100 group-hover/img:opacity-100 [@media(pointer:coarse)]:opacity-100\">\n {library ? (\n <button type=\"button\" onClick={library} className={PILL}>\n <IconReplace className=\"size-3.5\" stroke={1.5} aria-hidden />\n Replace\n </button>\n ) : null}\n <Tooltip content=\"Remove image\">\n <button type=\"button\" aria-label=\"Remove image\" onClick={() => onChange(null)} className={cn(PILL, \"size-7 justify-center px-0\")}>\n <IconX className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n </Tooltip>\n </div>\n )}\n {up.progress != null ? (\n <div className=\"absolute inset-x-3 bottom-3\">\n <Progress value={up.progress} tone=\"ink\" size=\"sm\" label=\"Upload progress\" />\n </div>\n ) : null}\n </div>\n <div className=\"flex min-w-0 items-center gap-1.5 pl-0.5\">\n <span data-slot=\"kit-image-caption\" className=\"min-w-0 flex-1 truncate text-kit-xs text-kit-fg-3\">\n {name}\n {size ? (\n <>\n {\" · \"}\n <span className=\"tabular-nums\">\n {size.w} × {size.h}\n </span>\n </>\n ) : null}\n {\" · \"}\n {alt ? (\n <span className=\"text-kit-fg-2\">Alt text set</span>\n ) : (\n <span className=\"inline-flex items-center gap-0.5 text-kit-warning-fg\">\n <IconAlertTriangle className=\"size-3\" stroke={1.5} aria-hidden />\n No alt text\n </span>\n )}\n </span>\n <Menu>\n <MenuTrigger\n aria-label=\"Image actions\"\n className=\"flex size-6 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover\"\n >\n <IconDots className=\"size-4\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n <MenuContent align=\"end\" className=\"w-52\">\n <MenuItem icon={<IconFocusCentered stroke={1.5} />} onClick={openDetails}>\n Alt text and details\n </MenuItem>\n {library ? (\n <MenuItem icon={<IconReplace stroke={1.5} />} onClick={library}>\n Replace\n </MenuItem>\n ) : null}\n <MenuItem icon={<IconExternalLink stroke={1.5} />} onClick={() => window.open(src(v.url), \"_blank\", \"noopener\")}>\n Open original\n </MenuItem>\n {readOnly ? null : (\n <>\n <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => onChange(null)}>\n Remove\n </MenuItem>\n </>\n )}\n </MenuContent>\n </Menu>\n </div>\n {up.error ? <Reason>{up.error}</Reason> : null}\n </PopoverAnchor>\n <PopoverContent className=\"w-[320px]\" align=\"start\" side=\"bottom\">\n <ImageDetails v={v} onChange={onChange} readOnly={readOnly} label={field.title} urlOnly={urlOnly} size={size} asset={asset} />\n </PopoverContent>\n <MediaPicker open={picker} onOpenChange={setPicker} accept={[\"image\", \"svg\"]} onPick={(a) => a[0] && replace(a[0])} />\n </Popover>\n );\n}\n\n/* ── Gallery (array of images) ─────────────────────────────────────── */\ntype GItem = { key: string; v: ImageValue; raw: unknown };\n\nfunction Thumb({\n item,\n label,\n readOnly,\n sort,\n onRemove,\n onOpen,\n}: {\n item: GItem;\n label: string;\n readOnly?: boolean;\n sort: ReturnType<typeof useDragReorder>;\n onRemove: () => void;\n onOpen: () => void;\n}) {\n const { src } = useMedia();\n const handle = sort.handle(item.key);\n return (\n <div\n ref={sort.register(item.key)}\n role=\"listitem\"\n style={sort.style(item.key)}\n className={cn(\"group/thumb relative aspect-square overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted\", sort.active === item.key && \"z-10 shadow-kit-lg ring-2 ring-kit-line-strong\")}\n >\n <div\n {...(readOnly ? {} : handle)}\n tabIndex={0}\n aria-label={readOnly ? label : `${label}, drag to reorder`}\n onDoubleClick={onOpen}\n onKeyDown={(e) => {\n if (!readOnly && (e.key === \"Delete\" || e.key === \"Backspace\")) {\n e.preventDefault();\n onRemove();\n return;\n }\n if (e.key === \"Enter\") {\n e.preventDefault();\n onOpen();\n return;\n }\n if (!readOnly) handle.onKeyDown(e);\n }}\n className={cn(\n \"size-full touch-none outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none\",\n !readOnly && \"cursor-grab active:cursor-grabbing\",\n )}\n >\n <img src={src(item.v.url)} alt={item.v.alt ?? \"\"} className=\"pointer-events-none size-full select-none object-cover\" draggable={false} />\n </div>\n {!item.v.alt ? <span role=\"img\" className=\"absolute bottom-1 left-1 size-1.5 rounded-full bg-kit-warning ring-2 ring-kit-surface\" aria-label=\"No alt text\" /> : null}\n {readOnly ? null : (\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n onPointerDown={(e) => e.stopPropagation()}\n onClick={onRemove}\n className=\"absolute right-1 top-1 flex size-6 items-center justify-center rounded-kit-md bg-kit-inverse/80 text-kit-fg-inverse opacity-0 transition-opacity focus-visible:opacity-100 group-hover/thumb:opacity-100 [@media(pointer:coarse)]:opacity-100\"\n >\n <IconX className=\"size-3.5\" stroke={1.5} aria-hidden />\n </button>\n )}\n </div>\n );\n}\n\n/** An array of images: a sortable grid of tiles with a dashed \"Add images\" tile last (hidden at `max`). */\nexport function GalleryControl({ value, onChange, readOnly, field, id }: ControlProps) {\n const { s, src } = useMedia();\n const raw = Array.isArray(value) ? value : [];\n /* a key that survives a move (keyboard reorder refocuses the grip by key); an index suffix only for duplicates */\n const seen = new Map<string, number>();\n const items: GItem[] = raw.map((x) => {\n const v = normImage(x) ?? { url: \"\" };\n const base = v.id ?? v.url;\n const n = seen.get(base) ?? 0;\n seen.set(base, n + 1);\n return { key: n ? `${base}#${n}` : base, v, raw: x };\n });\n /* strings stay strings (a legacy list of URLs); a picked asset joins as the object prod stores */\n const asStrings = raw.length > 0 && raw.every((x) => typeof x === \"string\");\n const out = (v: ImageValue) => (asStrings && !v.alt && !v.focal ? v.url : v);\n const write = (list: unknown[]) => onChange(list);\n const add = (assets: KitMediaAsset[]) => write([...raw, ...assets.map((a) => out(fromAsset(a)))]);\n const [picker, setPicker] = React.useState(false);\n const up = useUpload(\"image/*\", \"image\", add);\n const keys = items.map((it) => it.key);\n const sort = useDragReorder(\n keys,\n (from, to) => {\n const next = [...raw];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n write(next);\n },\n { axis: \"grid\", disabled: readOnly },\n );\n const max = field.validation?.max;\n const canAdd = !readOnly && (max == null || items.length < max) && (s.MediaPicker || up.run);\n const noun = (i: number, it: GItem) => it.v.name ?? (fileNameFromUrl(it.v.url) || `Image ${i + 1}`);\n return (\n <div className=\"flex flex-col gap-2\">\n <div id={id} role=\"list\" aria-label={field.title} className=\"grid grid-cols-3 gap-1.5 @[520px]:grid-cols-5\">\n {items.map((it, i) => (\n <Thumb\n key={it.key}\n item={it}\n label={noun(i, it)}\n readOnly={readOnly}\n sort={sort}\n onOpen={() => window.open(src(it.v.url), \"_blank\", \"noopener\")}\n onRemove={() => write(raw.filter((_, j) => j !== i))}\n />\n ))}\n {canAdd ? (\n // a real grid cell, not `display: contents`: V2 draws the tile as the grid's own child, and a box-less wrapper\n // would put the tile beside nothing (the Panel walker measures its gap from the thumbs beside it)\n <div role=\"listitem\" className=\"grid\">\n <button\n type=\"button\"\n onClick={() => (s.MediaPicker ? setPicker(true) : up.run && document.getElementById(`${id}-files`)?.click())}\n onPaste={(e) => {\n const files = Array.from(e.clipboardData.files);\n if (files.length && up.run) {\n e.preventDefault();\n up.run(files);\n }\n }}\n onDragOver={(e) => up.run && e.preventDefault()}\n onDrop={(e) => {\n if (!up.run) return;\n e.preventDefault();\n up.run(Array.from(e.dataTransfer.files));\n }}\n className=\"flex aspect-square flex-col items-center justify-center gap-1 rounded-kit-md border border-dashed border-kit-line-strong bg-kit-subtle text-kit-xs text-kit-fg-3 transition-colors hover:border-kit-field-border-hover hover:text-kit-fg\"\n >\n <IconPlus className=\"size-4\" stroke={1.5} aria-hidden />\n Add images\n </button>\n </div>\n ) : null}\n </div>\n {sort.a11y}\n {up.run && !s.MediaPicker ? (\n <input\n id={`${id}-files`}\n type=\"file\"\n hidden\n tabIndex={-1}\n aria-hidden\n accept=\"image/*\"\n multiple\n onChange={(e) => {\n up.run?.(Array.from(e.target.files ?? []));\n e.target.value = \"\";\n }}\n />\n ) : null}\n {up.progress != null ? <Progress value={up.progress} tone=\"ink\" size=\"sm\" label=\"Upload progress\" /> : null}\n {up.error ? <Reason>{up.error}</Reason> : null}\n {!readOnly && !s.MediaPicker && !up.run ? <Reason tone=\"muted\">{NO_SOURCE}</Reason> : null}\n <MediaPicker open={picker} onOpenChange={setPicker} multiple accept={[\"image\", \"svg\"]} onPick={(a) => a.length && add(max != null ? a.slice(0, Math.max(0, max - items.length)) : a)} />\n </div>\n );\n}\n\n/* ── File ──────────────────────────────────────────────────────────── */\n/** A file value prod stores: the same envelope as an image, `{ url, id?, name? }` (or a legacy URL string). */\ntype FileValue = { url: string; id?: string; name?: string; [key: string]: unknown };\nconst normFile = (v: unknown): FileValue | null => {\n if (typeof v === \"string\") return v ? { url: v } : null;\n return isObj(v) && typeof v.url === \"string\" && v.url ? (v as FileValue) : null;\n};\nconst fileFromAsset = (a: KitMediaAsset): FileValue => ({ url: a.url, id: a.id, ...(a.name ? { name: a.name } : {}) });\n\nexport function FileControl({ value, onChange, readOnly, id }: ControlProps) {\n const { s, useAsset, src } = useMedia();\n const v = normFile(value);\n const asset = useAsset({ id: v?.id, url: v?.url ?? \"\" });\n const [picker, setPicker] = React.useState(false);\n const up = useUpload(\"*\", \"file\", (a) => a[0] && onChange(fileFromAsset(a[0])));\n const library = s.MediaPicker && !readOnly ? () => setPicker(true) : undefined;\n const pickerEl = <MediaPicker open={picker} onOpenChange={setPicker} accept={[\"file\"]} onPick={(a) => a[0] && onChange(fileFromAsset(a[0]))} />;\n if (!v)\n return (\n <div className=\"flex flex-col gap-1.5\">\n <DropWell id={id} title=\"Add a file\" hint=\"Or drop or paste one here\" accept=\"*\" icon={<IconFileText stroke={1.5} />} onFiles={up.run} onLibrary={library} refuse={up.setError} disabled={readOnly} progress={up.progress} />\n {up.error ? <Reason>{up.error}</Reason> : null}\n {pickerEl}\n </div>\n );\n const name = asset?.name ?? v.name ?? fileNameFromUrl(v.url);\n const ext = (name.includes(\".\") ? name.split(\".\").pop() : \"\")?.toUpperCase() || \"FILE\";\n const meta = [ext.toLowerCase(), asset?.size ? formatBytes(asset.size) : null].filter(Boolean).join(\" · \");\n return (\n <div className=\"flex flex-col gap-1.5\">\n <div className=\"flex items-center gap-3 rounded-kit-lg border border-kit-line bg-kit-control-bg p-2\">\n <span aria-hidden className=\"flex size-14 shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-subtle font-kit-mono text-kit-2xs font-medium text-kit-fg-2\">\n {ext}\n </span>\n <div className=\"min-w-0 flex-1\">\n <a id={id} href={src(v.url)} target=\"_blank\" rel=\"noreferrer\" className=\"block truncate text-kit-sm font-medium text-kit-accent-fg hover:underline\">\n {name}\n </a>\n <div className=\"text-kit-xs text-kit-fg-3\">{meta}</div>\n </div>\n {library ? (\n <Button size=\"sm\" variant=\"ghost\" onClick={library}>\n Replace\n </Button>\n ) : null}\n <Menu>\n <MenuTrigger aria-label=\"File actions\" className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover\">\n <IconDots className=\"size-4\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n <MenuContent align=\"end\">\n <MenuItem icon={<IconDownload stroke={1.5} />} onClick={() => window.open(src(v.url), \"_blank\", \"noopener\")}>\n Open\n </MenuItem>\n {readOnly ? null : (\n <>\n <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => onChange(null)}>\n Remove\n </MenuItem>\n </>\n )}\n </MenuContent>\n </Menu>\n </div>\n {pickerEl}\n </div>\n );\n}\n\n/* ── Video (paste a URL → preview) ─────────────────────────────────── */\nexport const videoProvider = (url: string) =>\n /youtu/.test(url) ? \"YouTube\" : /vimeo/.test(url) ? \"Vimeo\" : /loom/.test(url) ? \"Loom\" : /\\.(mp4|webm|mov)(\\?|$)/i.test(url) ? \"MP4\" : url ? \"Link\" : \"\";\nexport const youTubeId = (url: string) => url.match(/(?:youtu\\.be\\/|v=|embed\\/|shorts\\/)([\\w-]{11})/)?.[1];\nconst isFileVideo = (url: string) => /\\.(mp4|webm|mov)(\\?|$)/i.test(url);\n\nexport function VideoPreview({ url, poster, title }: { url: string; poster?: string; title: string }) {\n const { src } = useMedia();\n const [playing, setPlaying] = React.useState(false);\n React.useEffect(() => setPlaying(false), [url]);\n const yt = youTubeId(url);\n const thumb = poster ? src(poster) : yt ? `https://i.ytimg.com/vi/${yt}/hqdefault.jpg` : undefined;\n if (playing && yt)\n return <iframe title={title} src={`https://www.youtube-nocookie.com/embed/${yt}?autoplay=1`} allow=\"autoplay; encrypted-media\" className=\"aspect-video w-full rounded-kit-lg border border-kit-line\" />;\n if (playing && isFileVideo(url)) return <video src={src(url)} poster={thumb} controls autoPlay className=\"aspect-video w-full rounded-kit-lg border border-kit-line bg-kit-inverse\" />;\n const playable = !!yt || isFileVideo(url);\n return (\n <div className=\"relative aspect-video overflow-hidden rounded-kit-lg border border-kit-line bg-kit-inverse\">\n {thumb ? <img src={thumb} alt={`${title} poster`} className=\"size-full object-cover opacity-85\" /> : null}\n <button\n type=\"button\"\n aria-label={playable ? \"Play preview\" : \"Open video link\"}\n onClick={() => (playable ? setPlaying(true) : window.open(src(url), \"_blank\", \"noopener\"))}\n className=\"absolute inset-0 m-auto flex size-12 items-center justify-center rounded-full bg-kit-control-bg text-kit-fg shadow-kit-lg transition-transform hover:scale-105\"\n >\n {playable ? <IconPlayerPlay className=\"size-5\" stroke={1.5} aria-hidden /> : <IconExternalLink className=\"size-5\" stroke={1.5} aria-hidden />}\n </button>\n <span className=\"absolute left-2 top-2 inline-flex items-center gap-1 rounded-kit-md bg-kit-inverse/70 px-1.5 py-0.5 text-kit-xs text-kit-fg-inverse\">\n <IconVideo className=\"size-3.5\" stroke={1.5} aria-hidden />\n {videoProvider(url)}\n </span>\n </div>\n );\n}\n\n/**\n * A URL input with a live preview. The value keeps its stored shape: a URL string stays a string, a `{ url, poster… }`\n * object keeps its other keys. What is typed is a draft until it is an address prod stores (http(s) or a site path);\n * until then the field keeps the saved value and says why under the input.\n */\nexport function VideoControl({ field, value, onChange, readOnly, id, onBlur }: ControlProps) {\n const obj = isObj(value) && typeof value.url === \"string\" ? (value as { url: string; poster?: string }) : null;\n const stored = typeof value === \"string\" ? value : (obj?.url ?? \"\");\n const [draft, setDraft] = React.useState(stored);\n const [touched, setTouched] = React.useState(false);\n React.useEffect(() => setDraft(stored), [stored]);\n const commit = (raw: string) => {\n const url = raw.trim();\n if (url === stored || !isVideoUrl(url)) return;\n if (url === \"\") return onChange(obj ? null : \"\");\n onChange(obj ? { ...obj, url } : url);\n };\n const bad = draft.trim() !== \"\" && !isVideoUrl(draft);\n const errorId = `${id}-error`;\n return (\n <div className=\"flex flex-col gap-2\">\n <Input\n id={id}\n value={draft}\n readOnly={readOnly}\n aria-invalid={bad && touched ? true : undefined}\n aria-describedby={bad && touched ? errorId : undefined}\n onBlur={() => {\n setTouched(true);\n onBlur?.();\n }}\n onKeyDown={(e) => {\n if (e.key === \"Escape\" && draft !== stored) {\n e.stopPropagation();\n setDraft(stored);\n }\n }}\n placeholder=\"Paste a YouTube, Vimeo, Loom or MP4 link\"\n leading={<IconWorld stroke={1.5} />}\n onChange={(e) => {\n setDraft(e.target.value);\n commit(e.target.value);\n }}\n />\n {bad && touched ? (\n <p id={errorId} role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n Not saved: use a full link starting with https://, or a site path starting with /.\n </p>\n ) : null}\n {/* V2 promises \"a poster frame automatically\", which nothing here makes; this note says what is true and, like V2's,\n wraps to two lines at Panel widths (420 and 360) */}\n {stored ? <VideoPreview url={stored} poster={obj?.poster} title={field.title} /> : <p className=\"text-kit-xs text-kit-fg-3\">No video yet. The embed lazy-loads on the page, so it doesn't block the first paint.</p>}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"number.js","names":[],"sources":["../../src/kit/controls/number.tsx"],"sourcesContent":["/**\n * NUMBER — a plain input, NO stepper (prod CPO-068), V2 HEAD 9829bf1 kit/controls/number.tsx, DESIGN §8.4.\n * ↑/↓ step (Shift ×10), the value commits on blur or Enter, clamped to min/max and rounded to the step's precision only when the schema sets a step (V2 rounds to a default step of 1; prod never rounds, so a typed 2.5 stays 2.5);\n * the unit suffix scrubs on drag (Shift ×10); the wheel never changes a value (it blurs).\n * A number with a scale (`field.scale`, or `layout: \"slider\"` + min/max) is the scale control, which the choice lane\n * registers in NUMBER_SCALE; a host that never registered it edits the raw value (FallbackControl), never a plain box.\n * RATING — stars across the prod scale (config.min 0 · max 5 · step 1 unset) plus a number box for half steps.\n *\n * Stored shapes (prod `number`, `typeof === \"number\"`): a number, or null when cleared. A rating stays on its scale\n * (ratingToProd refuses anything off it), so the control only ever writes a step of the scale or null.\n */\nimport * as React from \"react\";\nimport type { ComponentType } from \"react\";\nimport { IconStarFilled } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { useKitEnv } from \"../context\";\nimport { fieldScale } from \"../schema/scale\";\nimport { FallbackControl } from \"../engine/kit-field\";\nimport { Tooltip } from \"../ui/overlay\";\nimport type { ControlProps } from \"../types\";\nimport { TEXT_FOCUS } from \"./text\";\n\n/** Registered by the choice / scale lane: the control for a number with a scale. */\nexport const NUMBER_SCALE: { control?: ComponentType<ControlProps> } = {};\n\nexport const toNum = (v: unknown): number | null =>\n typeof v === \"number\" && Number.isFinite(v) ? v : typeof v === \"string\" && v.trim() !== \"\" && Number.isFinite(Number(v)) ? Number(v) : null;\n/** What a keystroke may leave in a number box: an optional minus, digits, one decimal point. */\nconst NUMBER_TYPING = /^-?\\d*\\.?\\d*$/;\nconst decimals = (n: number) => (String(n).split(\".\")[1] ?? \"\").length;\n\nexport function NumberControl(p: ControlProps) {\n if (!fieldScale(p.field)) return <PlainNumber {...p} />;\n const Scale = NUMBER_SCALE.control ?? FallbackControl;\n return <Scale {...p} />;\n}\n\nexport function PlainNumber({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const { variant } = useKitEnv();\n const n = toNum(value);\n const step = field.numeric?.step && field.numeric.step > 0 ? field.numeric.step : 1;\n const lo = field.numeric?.min ?? -Infinity;\n const hi = field.numeric?.max ?? Infinity;\n /* Round to the step only when the schema sets one: with no step a typed 2.5 stays 2.5 (prod NumberField never rounds).\n The rounding then only trims float noise from ↑/↓ (2.5 + 1 → 3.5, 0.1 + 0.2 → 0.3). */\n const setStep = !!field.numeric?.step && field.numeric.step > 0;\n const clamp = (x: number, from?: number) => {\n const precision = setStep ? decimals(step) : from == null ? null : Math.max(decimals(step), decimals(from));\n return Math.min(hi, Math.max(lo, precision == null ? x : Number(x.toFixed(precision))));\n };\n const [draft, setDraft] = React.useState<string | null>(null);\n const start = React.useRef<{ x: number; v: number } | null>(null);\n const unit = field.numeric?.unit;\n const commit = () => {\n if (draft !== null) {\n const t = draft.trim();\n const x = Number(t);\n if (t === \"\") onChange(null);\n else if (t !== \"-\" && t !== \".\" && Number.isFinite(x)) onChange(clamp(x));\n }\n setDraft(null);\n };\n return (\n <div\n data-slot=\"kit-number\"\n className={cn(\n \"flex w-full max-w-40 items-center rounded-kit-md border border-kit-field-border bg-kit-field-bg shadow-kit-field transition-colors hover:border-kit-field-border-hover focus-within:border-kit-field-border-focus\",\n variant === \"document\" ? \"h-9\" : \"h-8\",\n invalid && \"border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]\",\n readOnly && \"opacity-80\",\n )}\n >\n <input\n id={id}\n inputMode=\"decimal\"\n value={draft ?? (n == null ? \"\" : String(n))}\n readOnly={readOnly}\n aria-invalid={invalid}\n placeholder={field.placeholder ?? \"0\"}\n onWheel={(e) => e.currentTarget.blur()}\n onChange={(e) => NUMBER_TYPING.test(e.target.value) && setDraft(e.target.value)}\n onBlur={() => {\n commit();\n onBlur?.();\n }}\n onKeyDown={(e) => {\n if (readOnly) return;\n if (e.key === \"Enter\") e.currentTarget.blur();\n if (e.key === \"Escape\" && draft !== null) {\n e.stopPropagation();\n setDraft(null);\n }\n if (e.key === \"ArrowUp\" || e.key === \"ArrowDown\") {\n e.preventDefault();\n const base = draft !== null && Number.isFinite(Number(draft)) && draft.trim() !== \"\" ? Number(draft) : (n ?? 0);\n const d = (e.key === \"ArrowUp\" ? 1 : -1) * step * (e.shiftKey ? 10 : 1);\n setDraft(null);\n onChange(clamp(base + d, base));\n }\n }}\n className={cn(TEXT_FOCUS, \"h-full min-w-0 flex-1 bg-transparent px-2.5 text-kit-sm tabular-nums text-kit-fg outline-none placeholder:text-kit-fg-4\")}\n />\n {unit ? (\n <Tooltip content={readOnly ? undefined : \"Drag to adjust · Shift for ×10\"}>\n <span\n data-slot=\"kit-number-unit\"\n onPointerDown={(e) => {\n if (readOnly) return;\n e.currentTarget.setPointerCapture?.(e.pointerId);\n start.current = { x: e.clientX, v: n ?? 0 };\n }}\n onPointerMove={(e) => {\n if (!start.current) return;\n const dx = e.clientX - start.current.x;\n const next = clamp(start.current.v + Math.round(dx / 4) * step * (e.shiftKey ? 10 : 1), start.current.v);\n if (next !== n) onChange(next);\n }}\n onPointerUp={() => (start.current = null)}\n onPointerCancel={() => (start.current = null)}\n className={cn(\"flex h-full select-none items-center pl-1 pr-2.5 text-kit-xs text-kit-fg-3\", !readOnly && \"cursor-ew-resize hover:text-kit-fg\")}\n >\n {unit}\n </span>\n </Tooltip>\n ) : null}\n </div>\n );\n}\n\n/** Prod's rating scale, from the field's numeric bounds (0 · 5 · 1 unset). */\nexport function ratingScale(field: ControlProps[\"field\"]) {\n const min = field.numeric?.min ?? 0;\n const max = field.numeric?.max ?? 5;\n const step = field.numeric?.step && field.numeric.step > 0 ? field.numeric.step : 1;\n return { min, max, step };\n}\n/** A typed rating snapped onto its scale; null when it cannot be (empty, not a number). */\nexport function snapRating(x: number, { min, max, step }: { min: number; max: number; step: number }): number {\n const snapped = min + Math.round((x - min) / step) * step;\n return Number(Math.min(max, Math.max(min, snapped)).toFixed(decimals(step)));\n}\n\nexport function RatingControl({ field, value, onChange, readOnly, id, invalid, onBlur }: ControlProps) {\n const scale = ratingScale(field);\n const stars = Math.max(1, Math.min(10, Math.ceil(scale.max)));\n const n = toNum(value);\n const [hover, setHover] = React.useState<number | null>(null);\n const [draft, setDraft] = React.useState<string | null>(null);\n const shown = hover ?? n ?? 0;\n const commit = () => {\n if (draft !== null) {\n const t = draft.trim();\n if (t === \"\") onChange(null);\n else if (Number.isFinite(Number(t)) && t !== \".\") onChange(snapRating(Number(t), scale));\n }\n setDraft(null);\n };\n return (\n <div className=\"flex items-center gap-3\">\n <div role=\"radiogroup\" aria-label={`${field.title} rating`} className=\"flex items-center\" onMouseLeave={() => setHover(null)}>\n {Array.from({ length: stars }, (_, k) => k + 1).map((i) => {\n const fill = Math.max(0, Math.min(1, shown - (i - 1)));\n const pick = snapRating(i, scale);\n return (\n <button\n key={i}\n type=\"button\"\n role=\"radio\"\n aria-checked={n != null && Math.ceil(n) === i}\n aria-label={`${i} star${i > 1 ? \"s\" : \"\"}`}\n disabled={readOnly}\n onMouseEnter={() => setHover(i)}\n onClick={() => onChange(pick)}\n className=\"relative flex size-7 items-center justify-center transition-transform hover:scale-110 disabled:hover:scale-100\"\n >\n <IconStarFilled className=\"size-[18px] text-kit-line-strong\" />\n <span className=\"absolute inset-0 flex items-center justify-center overflow-hidden\" style={{ clipPath: `inset(0 ${100 - fill * 100}% 0 0)` }}>\n <IconStarFilled className=\"size-[18px] text-kit-warning\" />\n </span>\n </button>\n );\n })}\n </div>\n <input\n id={id}\n inputMode=\"decimal\"\n value={draft ?? (n == null ? \"\" : String(n))}\n readOnly={readOnly}\n aria-invalid={invalid}\n placeholder=\"–\"\n onWheel={(e) => e.currentTarget.blur()}\n onChange={(e) => /^\\d*\\.?\\d*$/.test(e.target.value) && setDraft(e.target.value)}\n onBlur={() => {\n commit();\n onBlur?.();\n }}\n onKeyDown={(e) => e.key === \"Enter\" && e.currentTarget.blur()}\n className={cn(\n TEXT_FOCUS,\n \"h-7 w-12 rounded-kit-md border border-kit-field-border bg-kit-field-bg px-2 text-kit-sm tabular-nums text-kit-fg shadow-kit-field outline-none hover:border-kit-field-border-hover focus:border-kit-field-border-focus aria-[invalid=true]:border-[var(--kit-field-invalid)]\",\n )}\n />\n <span className=\"text-kit-xs text-kit-fg-3\">out of {scale.max}</span>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAa,eAA0D,EAAE;AAEzE,IAAa,SAAS,MACpB,OAAO,MAAM,YAAY,OAAO,SAAS,EAAE,GAAG,IAAI,OAAO,MAAM,YAAY,EAAE,MAAM,KAAK,MAAM,OAAO,SAAS,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,GAAG;;AAEzI,IAAM,gBAAgB;AACtB,IAAM,YAAY,OAAe,OAAO,EAAE,CAAC,MAAM,IAAI,CAAC,MAAM,IAAI;AAEhE,SAAgB,cAAc,GAAiB;AAC7C,KAAI,CAAC,WAAW,EAAE,MAAM,CAAE,QAAO,oBAAC,aAAD,EAAa,GAAI,GAAK,CAAA;AAEvD,QAAO,oBADO,aAAa,WAAW,iBAC/B,EAAO,GAAI,GAAK,CAAA;;AAGzB,SAAgB,YAAY,EAAE,OAAO,OAAO,UAAU,UAAU,IAAI,SAAS,UAAwB;CACnG,MAAM,EAAE,YAAY,WAAW;CAC/B,MAAM,IAAI,MAAM,MAAM;CACtB,MAAM,OAAO,MAAM,SAAS,QAAQ,MAAM,QAAQ,OAAO,IAAI,MAAM,QAAQ,OAAO;CAClF,MAAM,KAAK,MAAM,SAAS,OAAO;CACjC,MAAM,KAAK,MAAM,SAAS,OAAO;CAGjC,MAAM,UAAU,CAAC,CAAC,MAAM,SAAS,QAAQ,MAAM,QAAQ,OAAO;CAC9D,MAAM,SAAS,GAAW,SAAkB;EAC1C,MAAM,YAAY,UAAU,SAAS,KAAK,GAAG,QAAQ,OAAO,OAAO,KAAK,IAAI,SAAS,KAAK,EAAE,SAAS,KAAK,CAAC;AAC3G,SAAO,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,aAAa,OAAO,IAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,CAAC,CAAC;;CAEzF,MAAM,CAAC,OAAO,YAAY,MAAM,SAAwB,KAAK;CAC7D,MAAM,QAAQ,MAAM,OAAwC,KAAK;CACjE,MAAM,OAAO,MAAM,SAAS;CAC5B,MAAM,eAAe;AACnB,MAAI,UAAU,MAAM;GAClB,MAAM,IAAI,MAAM,MAAM;GACtB,MAAM,IAAI,OAAO,EAAE;AACnB,OAAI,MAAM,GAAI,UAAS,KAAK;YACnB,MAAM,OAAO,MAAM,OAAO,OAAO,SAAS,EAAE,CAAE,UAAS,MAAM,EAAE,CAAC;;AAE3E,WAAS,KAAK;;AAEhB,QACE,qBAAC,OAAD;EACE,aAAU;EACV,WAAW,GACT,qNACA,YAAY,aAAa,QAAQ,OACjC,WAAW,6EACX,YAAY,aACb;YAPH,CASE,oBAAC,SAAD;GACM;GACJ,WAAU;GACV,OAAO,UAAU,KAAK,OAAO,KAAK,OAAO,EAAE;GACjC;GACV,gBAAc;GACd,aAAa,MAAM,eAAe;GAClC,UAAU,MAAM,EAAE,cAAc,MAAM;GACtC,WAAW,MAAM,cAAc,KAAK,EAAE,OAAO,MAAM,IAAI,SAAS,EAAE,OAAO,MAAM;GAC/E,cAAc;AACZ,YAAQ;AACR,cAAU;;GAEZ,YAAY,MAAM;AAChB,QAAI,SAAU;AACd,QAAI,EAAE,QAAQ,QAAS,GAAE,cAAc,MAAM;AAC7C,QAAI,EAAE,QAAQ,YAAY,UAAU,MAAM;AACxC,OAAE,iBAAiB;AACnB,cAAS,KAAK;;AAEhB,QAAI,EAAE,QAAQ,aAAa,EAAE,QAAQ,aAAa;AAChD,OAAE,gBAAgB;KAClB,MAAM,OAAO,UAAU,QAAQ,OAAO,SAAS,OAAO,MAAM,CAAC,IAAI,MAAM,MAAM,KAAK,KAAK,OAAO,MAAM,GAAI,KAAK;KAC7G,MAAM,KAAK,EAAE,QAAQ,YAAY,IAAI,MAAM,QAAQ,EAAE,WAAW,KAAK;AACrE,cAAS,KAAK;AACd,cAAS,MAAM,OAAO,GAAG,KAAK,CAAC;;;GAGnC,WAAW,GAAG,YAAY,0HAA0H;GACpJ,CAAA,EACD,OACC,oBAAC,SAAD;GAAS,SAAS,WAAW,KAAA,IAAY;aACvC,oBAAC,QAAD;IACE,aAAU;IACV,gBAAgB,MAAM;AACpB,SAAI,SAAU;AACd,OAAE,cAAc,oBAAoB,EAAE,UAAU;AAChD,WAAM,UAAU;MAAE,GAAG,EAAE;MAAS,GAAG,KAAK;MAAG;;IAE7C,gBAAgB,MAAM;AACpB,SAAI,CAAC,MAAM,QAAS;KACpB,MAAM,KAAK,EAAE,UAAU,MAAM,QAAQ;KACrC,MAAM,OAAO,MAAM,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,EAAE,GAAG,QAAQ,EAAE,WAAW,KAAK,IAAI,MAAM,QAAQ,EAAE;AACxG,SAAI,SAAS,EAAG,UAAS,KAAK;;IAEhC,mBAAoB,MAAM,UAAU;IACpC,uBAAwB,MAAM,UAAU;IACxC,WAAW,GAAG,8EAA8E,CAAC,YAAY,qCAAqC;cAE7I;IACI,CAAA;GACC,CAAA,GACR,KACA;;;;AAKV,SAAgB,YAAY,OAA8B;AAIxD,QAAO;EAAE,KAHG,MAAM,SAAS,OAAO;EAGpB,KAFF,MAAM,SAAS,OAAO;EAEf,MADN,MAAM,SAAS,QAAQ,MAAM,QAAQ,OAAO,IAAI,MAAM,QAAQ,OAAO;EACzD;;;AAG3B,SAAgB,WAAW,GAAW,EAAE,KAAK,KAAK,QAA4D;CAC5G,MAAM,UAAU,MAAM,KAAK,OAAO,IAAI,OAAO,KAAK,GAAG;AACrD,QAAO,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC,CAAC,QAAQ,SAAS,KAAK,CAAC,CAAC;;AAG9E,SAAgB,cAAc,EAAE,OAAO,OAAO,UAAU,UAAU,IAAI,SAAS,UAAwB;CACrG,MAAM,QAAQ,YAAY,MAAM;CAChC,MAAM,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC;CAC7D,MAAM,IAAI,MAAM,MAAM;CACtB,MAAM,CAAC,OAAO,YAAY,MAAM,SAAwB,KAAK;CAC7D,MAAM,CAAC,OAAO,YAAY,MAAM,SAAwB,KAAK;CAC7D,MAAM,QAAQ,SAAS,KAAK;CAC5B,MAAM,eAAe;AACnB,MAAI,UAAU,MAAM;GAClB,MAAM,IAAI,MAAM,MAAM;AACtB,OAAI,MAAM,GAAI,UAAS,KAAK;YACnB,OAAO,SAAS,OAAO,EAAE,CAAC,IAAI,MAAM,IAAK,UAAS,WAAW,OAAO,EAAE,EAAE,MAAM,CAAC;;AAE1F,WAAS,KAAK;;AAEhB,QACE,qBAAC,OAAD;EAAK,WAAU;YAAf;GACE,oBAAC,OAAD;IAAK,MAAK;IAAa,cAAY,GAAG,MAAM,MAAM;IAAU,WAAU;IAAoB,oBAAoB,SAAS,KAAK;cACzH,MAAM,KAAK,EAAE,QAAQ,OAAO,GAAG,GAAG,MAAM,IAAI,EAAE,CAAC,KAAK,MAAM;KACzD,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,SAAS,IAAI,GAAG,CAAC;KACtD,MAAM,OAAO,WAAW,GAAG,MAAM;AACjC,YACE,qBAAC,UAAD;MAEE,MAAK;MACL,MAAK;MACL,gBAAc,KAAK,QAAQ,KAAK,KAAK,EAAE,KAAK;MAC5C,cAAY,GAAG,EAAE,OAAO,IAAI,IAAI,MAAM;MACtC,UAAU;MACV,oBAAoB,SAAS,EAAE;MAC/B,eAAe,SAAS,KAAK;MAC7B,WAAU;gBATZ,CAWE,oBAAC,gBAAD,EAAgB,WAAU,oCAAqC,CAAA,EAC/D,oBAAC,QAAD;OAAM,WAAU;OAAoE,OAAO,EAAE,UAAU,WAAW,MAAM,OAAO,IAAI,SAAS;iBAC1I,oBAAC,gBAAD,EAAgB,WAAU,gCAAiC,CAAA;OACtD,CAAA,CACA;QAdF,EAcE;MAEX;IACE,CAAA;GACN,oBAAC,SAAD;IACM;IACJ,WAAU;IACV,OAAO,UAAU,KAAK,OAAO,KAAK,OAAO,EAAE;IACjC;IACV,gBAAc;IACd,aAAY;IACZ,UAAU,MAAM,EAAE,cAAc,MAAM;IACtC,WAAW,MAAM,cAAc,KAAK,EAAE,OAAO,MAAM,IAAI,SAAS,EAAE,OAAO,MAAM;IAC/E,cAAc;AACZ,aAAQ;AACR,eAAU;;IAEZ,YAAY,MAAM,EAAE,QAAQ,WAAW,EAAE,cAAc,MAAM;IAC7D,WAAW,GACT,YACA,+QACD;IACD,CAAA;GACF,qBAAC,QAAD;IAAM,WAAU;cAAhB,CAA4C,WAAQ,MAAM,IAAW;;GACjE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference-register.js","names":[],"sources":["../../src/kit/controls/reference-register.ts"],"sourcesContent":["/** Lane C4: the reference controls in the engine's dispatch tables (one line per type; merge with other lanes by line). */\nimport { CONTROLS } from \"../engine/kit-field\";\nimport { ARRAY_CONTROLS } from \"../engine/array\";\nimport { ReferenceControl, ReferencesControl } from \"./reference\";\n\nCONTROLS.reference = ReferenceControl;\nARRAY_CONTROLS.references = ReferencesControl;\n"],"mappings":";;;;;AAKA,SAAS,YAAY;AACrB,eAAe,aAAa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reference.js","names":[],"sources":["../../src/kit/controls/reference.tsx"],"sourcesContent":["/**\n * REFERENCE — single: a select-like trigger (\"Select a CMS item\") → a 300px search popover with \"None\", result rows,\n * drafts labelled, and \"Create new\" inline when the host can create. Never lists the document being edited. No one-click\n * clear (⋯ → Remove). MULTI-REFERENCE — reorderable chips + \"+ Add\", \"n / max\"; at the limit the picker swaps in place.\n * (V2 HEAD 9829bf1 kit/controls/reference.tsx, DESIGN.md 6.8, 8.16, 9.6.)\n *\n * The rows come from the host (reference-services.ts): `searchReferences` is POST /content/reference-options, which\n * already applies the field's `reference.filter` and scope; `truncated` says its filter scan stopped early, and the\n * picker says so. The stored value is the target id (\"en_12\"; a list for many), exactly V2's shape.\n *\n * Kit deviations from V2: no seed rows (every row is a real record from the service); matching is the server's title /\n * slug search, so rows keep the server's order; a stored id the lookup cannot find shows as a \"Missing\" card, or in a\n * multi list one compact \"n missing\" chip with Remove (DESIGN 9.6's production rule), instead of disappearing; chips sort with the engine's `useDragReorder`\n * (@dnd-kit is not on the kit allow-list).\n */\nimport * as React from \"react\";\nimport { IconArrowUpRight, IconCheck, IconChevronDown, IconDatabase, IconDots, IconFileDatabase, IconFileText, IconForms, IconPlus, IconReplace, IconSearch, IconShoppingBag, IconTrash, IconX } from \"@tabler/icons-react\";\nimport type { KitReferenceKind, KitReferenceOption } from \"./reference-services\";\nimport { Button } from \"../ui/button\";\nimport { Avatar } from \"../ui/display\";\nimport { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverContent, PopoverTrigger } from \"../ui/overlay\";\nimport { cn } from \"../lib/cn\";\nimport { useDragReorder } from \"../engine/item-list\";\nimport { useKitEnv, useKitServices } from \"../context\";\nimport type { ControlProps } from \"../types\";\n\nconst NON_ENTRY = new Set([\"page\", \"form\", \"collection\", \"shopify\"]);\nconst isEntryTarget = (t: string) => !NON_ENTRY.has(t);\nconst targetsOf = (field: ControlProps[\"field\"]) => field.reference?.to ?? [];\n\n/** The noun the picker uses (D48: \"CMS item\" where V2 says \"entry\"). */\nexport function referenceNoun(to: string[]): string {\n if (to.length === 1) return to[0] === \"page\" ? \"page\" : to[0] === \"form\" ? \"form\" : to[0] === \"collection\" ? \"collection\" : to[0] === \"shopify\" ? \"product\" : \"CMS item\";\n return to.length && to.every(isEntryTarget) ? \"CMS item\" : \"item\";\n}\nconst plural = (noun: string) => (noun === \"CMS item\" ? \"CMS items\" : `${noun}s`);\nconst withArticle = (noun: string) => `${/^[aeiou]/i.test(noun) ? \"an\" : \"a\"} ${noun}`;\nconst reasonOf = (e: unknown) => (e instanceof Error ? e.message : String(e));\nconst PAGE = 25;\n/** V2 (Radix) slides a picker that would overflow along the edge, keeping it over the panel; Base UI would flip it to\n * end-aligned, which hangs it left over the preview */\nconst SHIFT = { align: \"shift\" } as const;\n\nconst KIND_ICON: Record<KitReferenceKind, React.ComponentType<{ className?: string; stroke?: number }>> = {\n entry: IconFileDatabase,\n page: IconFileText,\n form: IconForms,\n collection: IconDatabase,\n shopify: IconShoppingBag,\n};\n\nexport function RefThumb({ o, size = 28 }: { o: Pick<KitReferenceOption, \"kind\" | \"title\" | \"photo\"> | null; size?: number }) {\n // a person with a photo is drawn as V2 draws an author: their round avatar (initials if the image fails)\n if (o?.photo) return <Avatar name={o.title} src={o.photo} size={size} decorative />;\n const Icon = o ? KIND_ICON[o.kind] : IconFileDatabase;\n return (\n <span aria-hidden style={{ width: size, height: size }} className=\"flex shrink-0 items-center justify-center rounded-kit-md border border-kit-line bg-kit-subtle text-kit-fg-3\">\n <Icon className={size > 24 ? \"size-4\" : \"size-3.5\"} stroke={1.5} />\n </span>\n );\n}\n\nfunction DraftChip({ status }: { status?: string | null }) {\n return status === \"draft\" ? <span className=\"shrink-0 rounded-kit-md bg-kit-muted px-1 text-kit-2xs text-kit-fg-3\">Draft</span> : null;\n}\n\n/* ── Lookup: stored ids → their records ────────────────────────────── */\n/**\n * The records behind `ids`, read once per id through `lookupReferences`. An id the service does not hand back is\n * `missing`; a failed read is `error` (in words). A row picked in the picker is `remember`ed, so it shows at once.\n */\nexport function useReferenceRecords(ids: string[], to: string[]) {\n const { lookupReferences } = useKitServices();\n const [known, setKnown] = React.useState<Record<string, KitReferenceOption>>({});\n const [missing, setMissing] = React.useState<ReadonlySet<string>>(new Set());\n const [error, setError] = React.useState<string | null>(null);\n const inflight = React.useRef(new Set<string>());\n const alive = React.useRef(true);\n // set on every mount: StrictMode mounts, unmounts and mounts again, and a flag only cleared would drop every read\n React.useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n const idsKey = ids.join(\"|\");\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!lookupReferences) return;\n const asked = ids.filter((x) => !known[x] && !missing.has(x) && !inflight.current.has(x));\n if (!asked.length) return;\n for (const x of asked) inflight.current.add(x);\n lookupReferences(asked, to)\n .then((rows) => {\n if (!alive.current) return;\n const found = new Set(rows.map((r) => r.id));\n setKnown((k) => ({ ...k, ...Object.fromEntries(rows.map((r) => [r.id, r])) }));\n setMissing((m) => new Set([...m, ...asked.filter((x) => !found.has(x))]));\n setError(null);\n })\n .catch((e: unknown) => alive.current && setError(`The saved ${plural(referenceNoun(to))} could not be read: ${reasonOf(e)}`))\n .finally(() => {\n for (const x of asked) inflight.current.delete(x);\n });\n }, [idsKey, toKey, lookupReferences, known, missing]); // eslint-disable-line react-hooks/exhaustive-deps\n const remember = React.useCallback((o: KitReferenceOption) => {\n setKnown((k) => ({ ...k, [o.id]: o }));\n setMissing((m) => (m.has(o.id) ? new Set([...m].filter((x) => x !== o.id)) : m));\n }, []);\n return { known, missing, loading: !!lookupReferences && ids.some((x) => !known[x] && !missing.has(x)) && !error, error, remember, canLookup: !!lookupReferences };\n}\n\n/* ── The search popover body, shared by single and multi ───────────── */\nfunction PickerBody({\n to,\n filter,\n selected,\n multi,\n max,\n noun,\n onPick,\n onNone,\n canCreate,\n onCreated,\n}: {\n to: string[];\n filter?: string;\n selected: string[];\n multi?: boolean;\n max?: number;\n noun: string;\n onPick: (o: KitReferenceOption) => void;\n onNone?: () => void;\n canCreate: boolean;\n onCreated: (o: KitReferenceOption) => void;\n}) {\n const { searchReferences, createReference } = useKitServices();\n const env = useKitEnv();\n const [q, setQ] = React.useState(\"\");\n const [query, setQuery] = React.useState(\"\");\n const [rows, setRows] = React.useState<KitReferenceOption[]>([]);\n const [truncated, setTruncated] = React.useState(false);\n const [loading, setLoading] = React.useState(true);\n const [error, setError] = React.useState<string | null>(null);\n const [active, setActive] = React.useState(0);\n const [creating, setCreating] = React.useState(false);\n const [createBusy, setCreateBusy] = React.useState(false);\n const [createError, setCreateError] = React.useState<string | null>(null);\n const listId = React.useId();\n\n React.useEffect(() => {\n const t = window.setTimeout(() => setQuery(q.trim()), q.trim() ? 180 : 0);\n return () => window.clearTimeout(t);\n }, [q]);\n const toKey = to.join(\"|\");\n React.useEffect(() => {\n if (!searchReferences) return;\n const ctrl = new AbortController();\n setLoading(true);\n searchReferences({ to, filter, q: query, limit: PAGE, excludeId: env.docId, signal: ctrl.signal })\n .then((r) => {\n if (ctrl.signal.aborted) return;\n setRows(r.options.filter((o) => o.id !== env.docId));\n setTruncated(r.truncated);\n setError(null);\n setActive(0);\n })\n .catch((e: unknown) => !ctrl.signal.aborted && setError(reasonOf(e)))\n .finally(() => !ctrl.signal.aborted && setLoading(false));\n return () => ctrl.abort();\n }, [query, toKey, filter, env.docId, searchReferences]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const none = onNone && !q;\n const total = rows.length + (none ? 1 : 0);\n const at = (i: number) => (none ? (i === 0 ? null : rows[i - 1]) : rows[i]);\n const full = multi && max != null && selected.length >= max;\n const choose = (i: number) => {\n const o = at(i);\n if (o) onPick(o);\n else if (none) onNone!();\n };\n const optionId = (i: number) => `${listId}-${i}`;\n const create = async (title: string) => {\n if (!createReference) return;\n setCreateBusy(true);\n setCreateError(null);\n try {\n const o = await createReference({ to: to[0], title });\n setCreating(false);\n onCreated(o);\n } catch (e) {\n setCreateError(`Not created: ${reasonOf(e)}`);\n } finally {\n setCreateBusy(false);\n }\n };\n // V2's search copy: \"pages\" for a page picker, \"entries\" for every other one\n const searchLabel = `Search ${noun === \"page\" ? \"pages\" : \"entries\"}`;\n return (\n <div className=\"flex flex-col\">\n <label className=\"flex h-10 items-center gap-2 border-b border-kit-line px-3 text-kit-fg-3\">\n <IconSearch className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n <input\n autoFocus\n value={q}\n onChange={(e) => {\n setQ(e.target.value);\n setActive(0);\n }}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(total - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n setActive(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n setActive(Math.max(0, total - 1));\n } else if (e.key === \"Enter\" && total) {\n e.preventDefault();\n choose(Math.min(active, total - 1));\n }\n }}\n placeholder={`${searchLabel}…`}\n role=\"combobox\"\n aria-expanded\n aria-autocomplete=\"list\"\n aria-controls={listId}\n aria-activedescendant={total ? optionId(Math.min(active, total - 1)) : undefined}\n aria-label={searchLabel}\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 id={listId} className=\"max-h-72 overflow-y-auto p-1\" role=\"listbox\" aria-label={`${noun} results`} aria-multiselectable={multi || undefined} aria-busy={loading || undefined}>\n {none ? (\n <div\n id={optionId(0)}\n role=\"option\"\n aria-selected={false}\n onMouseEnter={() => setActive(0)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={onNone}\n className={cn(\"flex h-8 w-full cursor-pointer items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-3\", active === 0 && \"bg-kit-hover\")}\n >\n None\n </div>\n ) : null}\n {rows.map((o, j) => {\n const i = j + (none ? 1 : 0);\n const on = selected.includes(o.id);\n return (\n <div\n key={`${o.kind}:${o.id}`}\n id={optionId(i)}\n role=\"option\"\n aria-selected={on}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => onPick(o)}\n className={cn(\"flex w-full cursor-pointer items-center gap-2.5 rounded-kit-md p-1.5 text-left\", i === active && \"bg-kit-hover\")}\n >\n {multi ? (\n <span aria-hidden className={cn(\"flex size-4 shrink-0 items-center justify-center rounded-kit-sm border\", on ? \"border-kit-accent bg-kit-accent text-kit-accent-on\" : \"border-kit-line-strong\", !on && full && \"opacity-40\")}>\n {on ? <IconCheck className=\"size-3\" stroke={3} /> : null}\n </span>\n ) : null}\n <RefThumb o={o} size={28} />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-kit-sm text-kit-fg\">{o.title}</span>\n {o.subtitle ? <span className=\"block truncate text-kit-xs text-kit-fg-3\">{o.subtitle}</span> : null}\n </span>\n <DraftChip status={o.status} />\n {!multi && on ? <IconCheck className=\"size-4 shrink-0 text-kit-fg\" stroke={2} aria-hidden /> : null}\n </div>\n );\n })}\n {!loading && !error && rows.length === 0 ? <div className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">No matches</div> : null}\n {loading && rows.length === 0 ? (\n <div role=\"status\" className=\"px-3 py-6 text-center text-kit-sm text-kit-fg-3\">\n Searching…\n </div>\n ) : null}\n {error ? (\n <p role=\"alert\" className=\"px-3 py-3 text-kit-xs text-kit-danger-fg\">\n {plural(noun).replace(/^./, (c) => c.toUpperCase())} could not be listed: {error}\n </p>\n ) : null}\n </div>\n {truncated && !error ? (\n <p role=\"note\" className=\"border-t border-kit-line px-3 py-2 text-kit-xs text-kit-warning-fg\">\n Some {plural(noun)} were not checked against this field's filter, so the list may be incomplete. Search by name to narrow it.\n </p>\n ) : null}\n {multi ? (\n <div className={cn(\"border-t border-kit-line px-3 py-2 text-kit-xs\", full ? \"text-kit-warning-fg\" : \"text-kit-fg-3\")}>\n {selected.length}\n {max != null ? ` of ${max}` : \"\"} selected{full ? ` · Limit is ${max}. Picking another swaps out the last one.` : \"\"}\n </div>\n ) : null}\n {canCreate ? (\n <div className=\"border-t border-kit-line p-1.5\">\n {creating ? (\n <form\n className=\"flex flex-col gap-1.5\"\n onSubmit={(e) => {\n e.preventDefault();\n e.stopPropagation();\n const t = String(new FormData(e.currentTarget).get(\"t\") ?? \"\").trim();\n if (t) void create(t);\n }}\n >\n <div className=\"flex items-center gap-1.5\">\n <input\n name=\"t\"\n autoFocus\n defaultValue={q}\n aria-label={`New ${noun} name`}\n placeholder={`New ${noun} name`}\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 />\n <Button size=\"sm\" type=\"submit\" variant=\"primary\" loading={createBusy} disabled={createBusy}>\n Create\n </Button>\n </div>\n {createError ? (\n <p role=\"alert\" className=\"px-1 text-kit-xs text-kit-danger-fg\">\n {createError}\n </p>\n ) : null}\n </form>\n ) : (\n <button\n type=\"button\"\n onClick={() => setCreating(true)}\n className=\"flex h-8 w-full items-center gap-2 rounded-kit-md px-2 text-left text-kit-sm text-kit-fg-2 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconPlus className=\"size-4\" stroke={1.5} aria-hidden />\n Create new {noun}\n {q ? <span className=\"truncate text-kit-fg-3\">“{q}”</span> : null}\n </button>\n )}\n </div>\n ) : null}\n </div>\n );\n}\n\n/** \"Create new\" only where the host can create a draft in the ONE entry model the field targets. */\nfunction useCanCreate(to: string[]) {\n const { createReference } = useKitServices();\n return !!createReference && to.length === 1 && isEntryTarget(to[0]);\n}\n\n/** Why the field cannot change its value here (no search service), in words. */\nfunction NoSearch({ title }: { title: string }) {\n return (\n <p role=\"note\" className=\"text-kit-xs text-kit-fg-3\">\n No reference search is connected to this editor, so {title} can't be changed here.\n </p>\n );\n}\n\n/* ── Single reference ──────────────────────────────────────────────── */\nexport function ReferenceControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const env = useKitEnv();\n const { searchReferences, toast } = useKitServices();\n const to = targetsOf(field);\n const noun = referenceNoun(to);\n const current = typeof value === \"string\" && value ? value : null;\n const ids = React.useMemo(() => (current ? [current] : []), [current]);\n const rec = useReferenceRecords(ids, to);\n const canCreate = useCanCreate(to) && !readOnly;\n const [open, setOpen] = React.useState(false);\n const pick = (o: KitReferenceOption) => {\n rec.remember(o);\n onChange(o.id);\n setOpen(false);\n };\n /* the trigger opens like V2's even with no search service; the popover then says why nothing can be picked */\n const editable = !readOnly;\n const body = !editable ? null : !searchReferences ? (\n <PopoverContent className=\"w-[300px] p-3\" align=\"start\" collisionAvoidance={SHIFT}>\n <NoSearch title={field.title} />\n </PopoverContent>\n ) : (\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n <PickerBody\n to={to}\n filter={field.reference?.filter}\n selected={current ? [current] : []}\n noun={noun}\n onPick={pick}\n onNone={\n current\n ? () => {\n onChange(null);\n setOpen(false);\n }\n : undefined\n }\n canCreate={canCreate}\n onCreated={(o) => {\n pick(o);\n toast?.success(`${noun.replace(/^./, (c) => c.toUpperCase())} created as a draft`, { description: `“${o.title}”` });\n }}\n />\n </PopoverContent>\n );\n\n const missing = !!current && rec.missing.has(current);\n if (current && !missing) {\n const o = rec.known[current];\n const title = o?.title ?? (rec.loading ? \"Loading…\" : current);\n const subtitle = o ? o.subtitle : rec.error ?? (!rec.canLookup ? `Saved ${noun} id` : null);\n const openable = !!o && o.kind === \"entry\" && !!o.modelSlug && !!env.onOpenReference;\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <div data-slot=\"kit-reference-card\" className=\"flex items-center gap-2.5 rounded-kit-lg border border-kit-line bg-kit-control-bg p-1.5 pr-1 transition-colors hover:border-kit-line-strong\">\n <PopoverTrigger\n id={id}\n disabled={!editable}\n aria-label={`${field.title}: ${title}.${editable ? \" Change\" : \"\"}`}\n className=\"flex min-w-0 flex-1 items-center gap-2.5 rounded-kit-md text-left outline-none focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] disabled:cursor-default [html[data-input-modality=pointer]_&]:focus-visible:outline-none\"\n >\n <RefThumb o={o ?? null} size={32} />\n <span className=\"min-w-0 flex-1\">\n <span className={cn(\"block truncate text-kit-sm font-medium text-kit-fg\", !o && !rec.canLookup && \"font-kit-mono text-kit-xs\")}>{title}</span>\n {subtitle ? <span className={cn(\"block truncate text-kit-xs\", rec.error && !o ? \"text-kit-danger-fg\" : \"text-kit-fg-3\")}>{subtitle}</span> : null}\n </span>\n <DraftChip status={o?.status} />\n </PopoverTrigger>\n {readOnly ? null : (\n <Menu>\n <MenuTrigger\n aria-label={`${o?.title ?? field.title} actions`}\n className=\"flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover\"\n >\n <IconDots className=\"size-4\" stroke={1.5} aria-hidden />\n </MenuTrigger>\n <MenuContent align=\"end\" className=\"w-48\">\n {openable ? (\n <MenuItem icon={<IconArrowUpRight stroke={1.5} />} onClick={() => env.onOpenReference!({ collectionId: o!.modelSlug!, entryId: o!.id, title: o!.title })}>\n Open {o!.title.length > 18 ? `${o!.title.slice(0, 16)}…` : o!.title}\n </MenuItem>\n ) : null}\n {editable ? (\n <MenuItem icon={<IconReplace stroke={1.5} />} onClick={() => window.setTimeout(() => setOpen(true), 0)}>\n Replace\n </MenuItem>\n ) : null}\n {openable || editable ? <MenuSeparator /> : null}\n <MenuItem danger icon={<IconTrash stroke={1.5} />} onClick={() => onChange(null)}>\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\n )}\n </div>\n {body}\n </Popover>\n );\n }\n /* empty, or a saved id the lookup cannot find: V2's select trigger (V2 draws an unresolved id as no selection). Ours\n says \"Missing\" on it instead of hiding the saved id (DESIGN 9.6); the picker's None clears it, a row replaces it. */\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n id={id}\n disabled={!editable}\n data-slot={missing ? \"kit-reference-card\" : undefined}\n data-missing={missing || undefined}\n aria-label={missing ? `${field.title}: Missing ${noun}.${editable ? \" Change\" : \"\"}` : `${field.title}: select ${withArticle(noun)}`}\n className={cn(\n \"flex h-8 w-full items-center gap-2 rounded-kit-md border bg-kit-field-bg px-2.5 text-left text-kit-sm transition-colors hover:border-kit-field-border-hover disabled:cursor-not-allowed disabled:opacity-60 data-[popup-open]:border-kit-field-border-focus\",\n missing ? \"border-kit-warning-line text-kit-warning-fg\" : \"border-kit-field-border text-kit-fg-3\",\n )}\n >\n <IconFileDatabase className=\"size-4 shrink-0\" stroke={1.5} aria-hidden />\n {missing ? (\n <span className=\"flex-1 truncate\">\n Missing {noun}\n <span className=\"sr-only\">. Deleted, or not visible to you. The saved id stays until you replace or remove it.</span>\n </span>\n ) : (\n <span className=\"flex-1 truncate\">Select {withArticle(noun)}</span>\n )}\n <IconChevronDown className=\"size-3.5 shrink-0\" stroke={1.5} aria-hidden />\n </PopoverTrigger>\n {body}\n </Popover>\n );\n}\n\n/* ── Multi-reference: an array of ids ─────────────────────────────── */\nfunction RefChip({\n id,\n o,\n canLookup,\n readOnly,\n sort,\n onRemove,\n}: {\n id: string;\n o?: KitReferenceOption;\n /** false: no lookup service, so the saved id is all there is to show (never a \"Loading…\" that never ends) */\n canLookup: boolean;\n readOnly?: boolean;\n sort: ReturnType<typeof useDragReorder>;\n onRemove: () => void;\n}) {\n const handle = sort.handle(id);\n const title = o?.title ?? (canLookup ? \"Loading…\" : id);\n return (\n <span\n ref={sort.register(id)}\n style={sort.style(id)}\n className={cn(\n \"inline-flex h-6 max-w-full items-center gap-1.5 rounded-kit-md border border-kit-line bg-kit-control-bg pl-0.5 pr-1 text-kit-sm text-kit-fg shadow-kit-xs\",\n sort.active === id && \"z-10 shadow-kit-md\",\n )}\n >\n <span\n {...(readOnly ? {} : handle)}\n tabIndex={0}\n aria-label={readOnly ? title : `${title}, drag to reorder`}\n onKeyDown={(e) => {\n if (readOnly) return;\n if (e.key === \"Delete\" || e.key === \"Backspace\") {\n e.preventDefault();\n onRemove();\n return;\n }\n handle.onKeyDown(e);\n }}\n className={cn(\n \"inline-flex min-w-0 touch-none items-center gap-1.5 rounded-kit-sm outline-none focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none\",\n !readOnly && \"cursor-grab active:cursor-grabbing\",\n )}\n >\n <RefThumb o={o ?? null} size={20} />\n <span className=\"truncate\">{title}</span>\n </span>\n {readOnly ? null : (\n <button type=\"button\" aria-label={`Remove ${title}`} onPointerDown={(e) => e.stopPropagation()} onClick={onRemove} className=\"flex rounded-kit-sm p-0.5 text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n );\n}\n\n/** Multi-reference: an array of reference ids. `field` is the ARRAY field; the engine hands it the item's `reference`. */\nexport function ReferencesControl({ field, value, onChange, readOnly, id }: ControlProps) {\n const { searchReferences } = useKitServices();\n const item = Array.isArray(field.of) ? field.of[0] : undefined;\n const to = item?.reference?.to ?? field.reference?.to ?? [];\n const filter = item?.reference?.filter ?? field.reference?.filter;\n const noun = referenceNoun(to);\n const ids = React.useMemo(() => (Array.isArray(value) ? value : []).filter((x): x is string => typeof x === \"string\" && x !== \"\"), [value]);\n const rec = useReferenceRecords(ids, to);\n const canCreate = useCanCreate(to) && !readOnly;\n const max = field.validation?.max;\n /* ids the lookup cannot find are drawn as ONE compact \"n missing\" chip after Add (V2 hides them; one row keeps V2's height),\n so the chips that sort are the rest; a reorder puts them back around the missing ids, which keep their places */\n const missingIds = ids.filter((x) => rec.missing.has(x));\n const shown = missingIds.length ? ids.filter((x) => !rec.missing.has(x)) : ids;\n const sort = useDragReorder(\n shown,\n (from, to2) => {\n const next = [...shown];\n const [moved] = next.splice(from, 1);\n next.splice(to2, 0, moved);\n let i = 0;\n onChange(ids.map((x) => (rec.missing.has(x) ? x : next[i++])));\n },\n { axis: \"grid\", disabled: readOnly },\n );\n const missingNoun = missingIds.length === 1 ? noun : plural(noun);\n const toggle = (o: KitReferenceOption) => {\n rec.remember(o);\n if (ids.includes(o.id)) return onChange(ids.filter((x) => x !== o.id));\n if (max != null && ids.length >= max) return onChange([...ids.slice(0, -1), o.id]); // swap in place at the limit\n onChange([...ids, o.id]);\n };\n return (\n <div className=\"flex flex-col gap-1\">\n {/* the field label points at the Add trigger; read-only there is none, so the box carries the id. The chips sit\n straight in the wrapping box, as V2's do (a wrapper would take them out of the box's flow). */}\n <div\n id={readOnly ? id : undefined}\n role=\"group\"\n aria-label={field.title}\n className=\"flex min-h-8 flex-wrap items-center gap-1 rounded-kit-md border border-kit-field-border bg-kit-field-bg p-1 transition-colors hover:border-kit-field-border-hover\"\n >\n {shown.map((x) => (\n <RefChip key={x} id={x} o={rec.known[x]} canLookup={rec.canLookup} readOnly={readOnly} sort={sort} onRemove={() => onChange(ids.filter((y) => y !== x))} />\n ))}\n {sort.a11y}\n {!readOnly ? (\n <Popover>\n <PopoverTrigger id={id} aria-label={`Add to ${field.title}`} className=\"inline-flex h-6 items-center gap-1 rounded-kit-md px-1.5 text-kit-sm text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg\">\n <IconPlus className=\"size-3.5\" stroke={1.5} aria-hidden />\n Add\n </PopoverTrigger>\n <PopoverContent className=\"w-[300px] p-0\" align=\"start\" collisionAvoidance={SHIFT}>\n {/* no search service: the picker says why instead of listing anything */}\n {!searchReferences ? (\n <div className=\"p-3\">\n <NoSearch title={field.title} />\n </div>\n ) : (\n <PickerBody\n to={to}\n filter={filter}\n selected={ids}\n multi\n max={max}\n noun={noun}\n onPick={toggle}\n canCreate={canCreate}\n onCreated={(o) => {\n rec.remember(o);\n onChange(max != null && ids.length >= max ? [...ids.slice(0, -1), o.id] : [...ids, o.id]);\n }}\n />\n )}\n </PopoverContent>\n </Popover>\n ) : ids.length === 0 ? (\n <span className=\"px-1.5 text-kit-sm text-kit-fg-3\">None</span>\n ) : null}\n {/* after Add, so Add keeps V2's place (V2 draws nothing for these ids) */}\n {missingIds.length ? (\n <span\n data-missing\n data-slot=\"kit-reference-missing\"\n className=\"inline-flex h-6 max-w-full items-center gap-1 rounded-kit-md border border-kit-warning-line bg-kit-control-bg pl-1.5 pr-1 text-kit-sm text-kit-warning-fg shadow-kit-xs\"\n >\n <span className=\"truncate tabular-nums\">\n {missingIds.length} missing\n <span className=\"sr-only\">\n {\" \"}\n {missingNoun}. Deleted, or not visible to you. The saved {missingIds.length === 1 ? \"id stays\" : \"ids stay\"} until you remove {missingIds.length === 1 ? \"it\" : \"them\"}.\n </span>\n </span>\n {readOnly ? null : (\n <button\n type=\"button\"\n aria-label={`Remove ${missingIds.length} missing ${missingNoun}`}\n onClick={() => onChange(ids.filter((y) => !rec.missing.has(y)))}\n className=\"flex rounded-kit-sm p-0.5 hover:bg-kit-hover hover:text-kit-fg\"\n >\n <IconX className=\"size-3\" stroke={1.5} aria-hidden />\n </button>\n )}\n </span>\n ) : null}\n </div>\n {rec.error ? (\n <p role=\"alert\" className=\"text-kit-xs text-kit-danger-fg\">\n {rec.error}\n </p>\n ) : null}\n {max != null ? (\n <span className=\"self-end tabular-nums text-kit-xs text-kit-fg-3\">\n {ids.length} / {max}\n </span>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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"}