@bettercms-ai/kit 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (587) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +90 -31
  8. package/dist/adapters/lossy.js +414 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +82 -4
  11. package/{adapters → dist/adapters}/prod-types.js +71 -3
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +996 -179
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +92 -2
  22. package/{context.js → dist/context.js} +5 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/{controls → dist/controls}/form-picker-register.js +1 -1
  50. package/dist/controls/form-picker-register.js.map +1 -0
  51. package/{controls → dist/controls}/form-picker.js +11 -9
  52. package/dist/controls/form-picker.js.map +1 -0
  53. package/{controls → dist/controls}/icon-register.js +1 -1
  54. package/dist/controls/icon-register.js.map +1 -0
  55. package/{controls → dist/controls}/icon.d.ts +4 -2
  56. package/{controls → dist/controls}/icon.js +32 -27
  57. package/dist/controls/icon.js.map +1 -0
  58. package/{controls → dist/controls}/index.d.ts +1 -1
  59. package/{controls → dist/controls}/index.js +4 -3
  60. package/dist/controls/index.js.map +1 -0
  61. package/{controls → dist/controls}/json-register.js +1 -1
  62. package/dist/controls/json-register.js.map +1 -0
  63. package/{controls → dist/controls}/json.js +13 -3
  64. package/dist/controls/json.js.map +1 -0
  65. package/{controls → dist/controls}/link.js +6 -6
  66. package/dist/controls/link.js.map +1 -0
  67. package/{controls → dist/controls}/location-register.js +1 -1
  68. package/dist/controls/location-register.js.map +1 -0
  69. package/{controls → dist/controls}/location.js +64 -40
  70. package/dist/controls/location.js.map +1 -0
  71. package/{controls → dist/controls}/media-register.js +1 -1
  72. package/dist/controls/media-register.js.map +1 -0
  73. package/{controls → dist/controls}/media-services.d.ts +6 -0
  74. package/dist/controls/media-services.js +0 -0
  75. package/{controls → dist/controls}/media.d.ts +35 -4
  76. package/{controls → dist/controls}/media.js +491 -171
  77. package/dist/controls/media.js.map +1 -0
  78. package/{controls → dist/controls}/number.js +10 -9
  79. package/dist/controls/number.js.map +1 -0
  80. package/{controls → dist/controls}/reference-register.js +1 -1
  81. package/dist/controls/reference-register.js.map +1 -0
  82. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  83. package/dist/controls/reference-services.js +0 -0
  84. package/{controls → dist/controls}/reference.d.ts +1 -1
  85. package/{controls → dist/controls}/reference.js +93 -77
  86. package/dist/controls/reference.js.map +1 -0
  87. package/dist/controls/rich-text/blocks.d.ts +49 -0
  88. package/{controls → dist/controls}/rich-text/blocks.js +471 -144
  89. package/dist/controls/rich-text/blocks.js.map +1 -0
  90. package/{controls → dist/controls}/rich-text/catalog.d.ts +4 -1
  91. package/{controls → dist/controls}/rich-text/catalog.js +75 -65
  92. package/dist/controls/rich-text/catalog.js.map +1 -0
  93. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  94. package/{controls → dist/controls}/rich-text/codec.js +3 -1
  95. package/dist/controls/rich-text/codec.js.map +1 -0
  96. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  97. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  98. package/dist/controls/rich-text/component-card.js.map +1 -0
  99. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  100. package/dist/controls/rich-text/component-panel.js +141 -0
  101. package/dist/controls/rich-text/component-panel.js.map +1 -0
  102. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  103. package/{controls → dist/controls}/rich-text/control.js +84 -42
  104. package/dist/controls/rich-text/control.js.map +1 -0
  105. package/{controls → dist/controls}/rich-text/dom.d.ts +52 -9
  106. package/{controls → dist/controls}/rich-text/dom.js +379 -50
  107. package/dist/controls/rich-text/dom.js.map +1 -0
  108. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  109. package/{controls → dist/controls}/rich-text/editor.js +148 -48
  110. package/dist/controls/rich-text/editor.js.map +1 -0
  111. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  112. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  113. package/dist/controls/rich-text/floating.js.map +1 -0
  114. package/{controls → dist/controls}/rich-text/index.js +1 -1
  115. package/dist/controls/rich-text/index.js.map +1 -0
  116. package/dist/controls/rich-text/link-form.js +147 -0
  117. package/dist/controls/rich-text/link-form.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  119. package/dist/controls/rich-text/markdown.js.map +1 -0
  120. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  121. package/dist/controls/rich-text/ops.js.map +1 -0
  122. package/dist/controls/rich-text/plain.d.ts +17 -0
  123. package/dist/controls/rich-text/plain.js +44 -0
  124. package/dist/controls/rich-text/plain.js.map +1 -0
  125. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  126. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  127. package/dist/controls/rich-text/toolbar.js.map +1 -0
  128. package/{controls → dist/controls}/scale.js +5 -5
  129. package/dist/controls/scale.js.map +1 -0
  130. package/{controls → dist/controls}/slot-register.js +1 -1
  131. package/dist/controls/slot-register.js.map +1 -0
  132. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  133. package/dist/controls/slot-services.js +155 -0
  134. package/dist/controls/slot-services.js.map +1 -0
  135. package/{controls → dist/controls}/slot.js +42 -24
  136. package/dist/controls/slot.js.map +1 -0
  137. package/{controls → dist/controls}/table/index.js +1 -1
  138. package/dist/controls/table/index.js.map +1 -0
  139. package/{controls → dist/controls}/table/prod.js +3 -3
  140. package/dist/controls/table/prod.js.map +1 -0
  141. package/{controls → dist/controls}/table/refs.js +13 -2
  142. package/dist/controls/table/refs.js.map +1 -0
  143. package/{controls → dist/controls}/table/stored.js +1 -1
  144. package/dist/controls/table/stored.js.map +1 -0
  145. package/{controls → dist/controls}/table/table-editor.js +51 -48
  146. package/dist/controls/table/table-editor.js.map +1 -0
  147. package/{controls → dist/controls}/table/table-link.js +3 -3
  148. package/dist/controls/table/table-link.js.map +1 -0
  149. package/{controls → dist/controls}/table/table.js +3 -3
  150. package/dist/controls/table/table.js.map +1 -0
  151. package/{controls → dist/controls}/text.d.ts +2 -2
  152. package/{controls → dist/controls}/text.js +78 -43
  153. package/dist/controls/text.js.map +1 -0
  154. package/dist/controls/unknown-value.d.ts +17 -0
  155. package/dist/controls/unknown-value.js +66 -0
  156. package/dist/controls/unknown-value.js.map +1 -0
  157. package/dist/core/core.d.ts +63 -0
  158. package/dist/core/core.js +171 -0
  159. package/dist/core/core.js.map +1 -0
  160. package/dist/core/facets.d.ts +347 -0
  161. package/dist/core/facets.js +334 -0
  162. package/dist/core/facets.js.map +1 -0
  163. package/dist/core/index.d.ts +3 -0
  164. package/dist/core/index.js +3 -0
  165. package/{engine → dist/engine}/array.js +34 -21
  166. package/dist/engine/array.js.map +1 -0
  167. package/{engine → dist/engine}/bits.js +1 -1
  168. package/dist/engine/bits.js.map +1 -0
  169. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  170. package/{engine → dist/engine}/breadcrumb.js +12 -36
  171. package/dist/engine/breadcrumb.js.map +1 -0
  172. package/{engine → dist/engine}/expand.d.ts +2 -4
  173. package/{engine → dist/engine}/expand.js +5 -22
  174. package/dist/engine/expand.js.map +1 -0
  175. package/{engine → dist/engine}/field-list.js +1 -1
  176. package/dist/engine/field-list.js.map +1 -0
  177. package/{engine → dist/engine}/field-shell.js +249 -121
  178. package/dist/engine/field-shell.js.map +1 -0
  179. package/{engine → dist/engine}/frame.d.ts +3 -1
  180. package/{engine → dist/engine}/frame.js +16 -14
  181. package/dist/engine/frame.js.map +1 -0
  182. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  183. package/{engine → dist/engine}/group-summary.js +7 -3
  184. package/dist/engine/group-summary.js.map +1 -0
  185. package/{engine → dist/engine}/grouping.d.ts +19 -5
  186. package/{engine → dist/engine}/grouping.js +193 -21
  187. package/dist/engine/grouping.js.map +1 -0
  188. package/{engine → dist/engine}/item-list.d.ts +11 -1
  189. package/{engine → dist/engine}/item-list.js +35 -13
  190. package/dist/engine/item-list.js.map +1 -0
  191. package/{engine → dist/engine}/kit-field.js +45 -10
  192. package/dist/engine/kit-field.js.map +1 -0
  193. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  194. package/{engine → dist/engine}/schema-form.js +182 -40
  195. package/dist/engine/schema-form.js.map +1 -0
  196. package/{engine → dist/engine}/slot.js +5 -15
  197. package/dist/engine/slot.js.map +1 -0
  198. package/dist/index.js +47 -0
  199. package/dist/index.js.map +1 -0
  200. package/{kit.css → dist/kit.css} +19 -0
  201. package/{lib → dist/lib}/cn.js +7 -4
  202. package/dist/lib/cn.js.map +1 -0
  203. package/{lib → dist/lib}/columns.js +4 -1
  204. package/dist/lib/columns.js.map +1 -0
  205. package/{lib → dist/lib}/frames.js +2 -2
  206. package/dist/lib/frames.js.map +1 -0
  207. package/dist/lib/icon-image.d.ts +10 -0
  208. package/dist/lib/icon-image.js +8 -0
  209. package/dist/lib/icon-image.js.map +1 -0
  210. package/{lib → dist/lib}/icons.js +4 -3
  211. package/dist/lib/icons.js.map +1 -0
  212. package/dist/lib/input-modality.d.ts +11 -0
  213. package/dist/lib/input-modality.js +47 -0
  214. package/dist/lib/input-modality.js.map +1 -0
  215. package/dist/lib/key-event.d.ts +11 -0
  216. package/dist/lib/key-event.js +16 -0
  217. package/dist/lib/key-event.js.map +1 -0
  218. package/{lib → dist/lib}/path.js +4 -2
  219. package/dist/lib/path.js.map +1 -0
  220. package/{lib → dist/lib}/schema.d.ts +34 -3
  221. package/{lib → dist/lib}/schema.js +110 -13
  222. package/dist/lib/schema.js.map +1 -0
  223. package/{lib → dist/lib}/utils.js +1 -1
  224. package/dist/lib/utils.js.map +1 -0
  225. package/{lib → dist/lib}/validate.d.ts +11 -1
  226. package/{lib → dist/lib}/validate.js +85 -11
  227. package/dist/lib/validate.js.map +1 -0
  228. package/dist/library/analysis.d.ts +23 -0
  229. package/dist/library/analysis.js +160 -0
  230. package/dist/library/analysis.js.map +1 -0
  231. package/dist/library/catalog.d.ts +57 -0
  232. package/dist/library/catalog.js +307 -0
  233. package/dist/library/catalog.js.map +1 -0
  234. package/dist/library/coreNotes.d.ts +8 -0
  235. package/dist/library/coreNotes.js +111 -0
  236. package/dist/library/coreNotes.js.map +1 -0
  237. package/dist/library/coverage.d.ts +40 -0
  238. package/dist/library/coverage.js +59 -0
  239. package/dist/library/coverage.js.map +1 -0
  240. package/dist/library/entries/advanced.entries.d.ts +2 -0
  241. package/dist/library/entries/advanced.entries.js +6579 -0
  242. package/dist/library/entries/advanced.entries.js.map +1 -0
  243. package/dist/library/entries/commerce.entries.d.ts +2 -0
  244. package/dist/library/entries/commerce.entries.js +4140 -0
  245. package/dist/library/entries/commerce.entries.js.map +1 -0
  246. package/dist/library/entries/company.entries.d.ts +2 -0
  247. package/dist/library/entries/company.entries.js +2731 -0
  248. package/dist/library/entries/company.entries.js.map +1 -0
  249. package/dist/library/entries/conversion.entries.d.ts +2 -0
  250. package/dist/library/entries/conversion.entries.js +3707 -0
  251. package/dist/library/entries/conversion.entries.js.map +1 -0
  252. package/dist/library/entries/data.entries.d.ts +7 -0
  253. package/dist/library/entries/data.entries.js +4613 -0
  254. package/dist/library/entries/data.entries.js.map +1 -0
  255. package/dist/library/entries/events.entries.d.ts +2 -0
  256. package/dist/library/entries/events.entries.js +3428 -0
  257. package/dist/library/entries/events.entries.js.map +1 -0
  258. package/dist/library/entries/features.entries.d.ts +2 -0
  259. package/dist/library/entries/features.entries.js +3157 -0
  260. package/dist/library/entries/features.entries.js.map +1 -0
  261. package/dist/library/entries/heroes.entries.d.ts +2 -0
  262. package/dist/library/entries/heroes.entries.js +3401 -0
  263. package/dist/library/entries/heroes.entries.js.map +1 -0
  264. package/dist/library/entries/index.d.ts +3 -0
  265. package/dist/library/entries/index.js +35 -0
  266. package/dist/library/entries/index.js.map +1 -0
  267. package/dist/library/entries/listings.entries.d.ts +2 -0
  268. package/dist/library/entries/listings.entries.js +2976 -0
  269. package/dist/library/entries/listings.entries.js.map +1 -0
  270. package/dist/library/entries/longform.entries.d.ts +2 -0
  271. package/dist/library/entries/longform.entries.js +4227 -0
  272. package/dist/library/entries/longform.entries.js.map +1 -0
  273. package/dist/library/entries/media.entries.d.ts +2 -0
  274. package/dist/library/entries/media.entries.js +2781 -0
  275. package/dist/library/entries/media.entries.js.map +1 -0
  276. package/dist/library/entries/navigation.entries.d.ts +2 -0
  277. package/dist/library/entries/navigation.entries.js +4011 -0
  278. package/dist/library/entries/navigation.entries.js.map +1 -0
  279. package/dist/library/entries/pricing.entries.d.ts +2 -0
  280. package/dist/library/entries/pricing.entries.js +2383 -0
  281. package/dist/library/entries/pricing.entries.js.map +1 -0
  282. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  283. package/dist/library/entries/social-proof.entries.js +2297 -0
  284. package/dist/library/entries/social-proof.entries.js.map +1 -0
  285. package/dist/library/examples/bento.d.ts +92 -0
  286. package/dist/library/examples/bento.js +201 -0
  287. package/dist/library/examples/bento.js.map +1 -0
  288. package/dist/library/examples/blocks.d.ts +14 -0
  289. package/dist/library/examples/blocks.js +313 -0
  290. package/dist/library/examples/blocks.js.map +1 -0
  291. package/dist/library/examples/faq.d.ts +28 -0
  292. package/dist/library/examples/faq.js +230 -0
  293. package/dist/library/examples/faq.js.map +1 -0
  294. package/dist/library/examples/hero.d.ts +43 -0
  295. package/dist/library/examples/hero.js +222 -0
  296. package/dist/library/examples/hero.js.map +1 -0
  297. package/dist/library/examples/index.d.ts +36 -0
  298. package/dist/library/examples/index.js +109 -0
  299. package/dist/library/examples/index.js.map +1 -0
  300. package/dist/library/examples/journalStory.d.ts +93 -0
  301. package/dist/library/examples/journalStory.js +338 -0
  302. package/dist/library/examples/journalStory.js.map +1 -0
  303. package/dist/library/examples/megaMenu.d.ts +134 -0
  304. package/dist/library/examples/megaMenu.js +442 -0
  305. package/dist/library/examples/megaMenu.js.map +1 -0
  306. package/dist/library/examples/pricing.d.ts +103 -0
  307. package/dist/library/examples/pricing.js +479 -0
  308. package/dist/library/examples/pricing.js.map +1 -0
  309. package/dist/library/examples/tabs.d.ts +87 -0
  310. package/dist/library/examples/tabs.js +180 -0
  311. package/dist/library/examples/tabs.js.map +1 -0
  312. package/dist/library/export.d.ts +42 -0
  313. package/dist/library/export.js +80 -0
  314. package/dist/library/export.js.map +1 -0
  315. package/dist/library/index.d.ts +13 -0
  316. package/dist/library/index.js +6 -0
  317. package/dist/library/kit-catalog.json +1510 -0
  318. package/dist/library/types.d.ts +42 -0
  319. package/dist/library/types.js +0 -0
  320. package/{schema → dist/schema}/adapters.js +1 -2
  321. package/dist/schema/adapters.js.map +1 -0
  322. package/{schema → dist/schema}/help.d.ts +2 -0
  323. package/{schema → dist/schema}/help.js +6 -4
  324. package/dist/schema/help.js.map +1 -0
  325. package/{schema → dist/schema}/scale.js +1 -1
  326. package/dist/schema/scale.js.map +1 -0
  327. package/{schema → dist/schema}/sources.js +1 -1
  328. package/dist/schema/sources.js.map +1 -0
  329. package/{schema → dist/schema}/table.js +11 -10
  330. package/dist/schema/table.js.map +1 -0
  331. package/{schema → dist/schema}/types.d.ts +29 -1
  332. package/{schema → dist/schema}/types.js +1 -1
  333. package/dist/schema/types.js.map +1 -0
  334. package/dist/styles.css +2 -0
  335. package/dist/table/table-view.d.ts +14 -0
  336. package/dist/table/table-view.js +140 -0
  337. package/dist/table/table-view.js.map +1 -0
  338. package/dist/table/table.css +73 -0
  339. package/dist/testing/corpus.d.ts +63 -0
  340. package/dist/testing/corpus.js +129 -0
  341. package/dist/testing/corpus.js.map +1 -0
  342. package/dist/testing/test-form.d.ts +11 -0
  343. package/dist/testing/test-form.js +38 -0
  344. package/dist/testing/test-form.js.map +1 -0
  345. package/dist/theme.css +345 -0
  346. package/dist/theme.d.ts +22 -0
  347. package/dist/theme.js +43 -0
  348. package/dist/theme.js.map +1 -0
  349. package/dist/tokens.css +542 -0
  350. package/dist/types.js +0 -0
  351. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  352. package/{ui → dist/ui}/action-tray.js +20 -19
  353. package/dist/ui/action-tray.js.map +1 -0
  354. package/dist/ui/autocomplete.d.ts +30 -0
  355. package/dist/ui/autocomplete.js +139 -0
  356. package/dist/ui/autocomplete.js.map +1 -0
  357. package/{ui → dist/ui}/button.d.ts +3 -3
  358. package/{ui → dist/ui}/button.js +6 -7
  359. package/dist/ui/button.js.map +1 -0
  360. package/{ui → dist/ui}/choice-switch.js +1 -1
  361. package/dist/ui/choice-switch.js.map +1 -0
  362. package/{ui → dist/ui}/controls.js +51 -39
  363. package/dist/ui/controls.js.map +1 -0
  364. package/{ui → dist/ui}/display.d.ts +10 -3
  365. package/{ui → dist/ui}/display.js +57 -46
  366. package/dist/ui/display.js.map +1 -0
  367. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  368. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  369. package/dist/ui/expanded-editor-modal.js.map +1 -0
  370. package/{ui → dist/ui}/field-context.js +1 -1
  371. package/dist/ui/field-context.js.map +1 -0
  372. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  373. package/{ui → dist/ui}/floating-panel.js +28 -12
  374. package/dist/ui/floating-panel.js.map +1 -0
  375. package/{ui → dist/ui}/index.d.ts +4 -0
  376. package/dist/ui/index.js +18 -0
  377. package/{ui → dist/ui}/input.d.ts +1 -1
  378. package/{ui → dist/ui}/input.js +9 -9
  379. package/dist/ui/input.js.map +1 -0
  380. package/{ui → dist/ui}/mode-bar.js +3 -3
  381. package/dist/ui/mode-bar.js.map +1 -0
  382. package/{ui → dist/ui}/overlay.d.ts +77 -5
  383. package/dist/ui/overlay.js +697 -0
  384. package/dist/ui/overlay.js.map +1 -0
  385. package/{ui → dist/ui}/path-crumbs.js +37 -3
  386. package/dist/ui/path-crumbs.js.map +1 -0
  387. package/{ui → dist/ui}/presence.js +2 -2
  388. package/dist/ui/presence.js.map +1 -0
  389. package/{ui → dist/ui}/select.js +89 -87
  390. package/dist/ui/select.js.map +1 -0
  391. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  392. package/dist/ui/shortcut-hint.js.map +1 -0
  393. package/dist/ui/spinner.d.ts +24 -0
  394. package/dist/ui/spinner.js +42 -0
  395. package/dist/ui/spinner.js.map +1 -0
  396. package/dist/ui/split-button.d.ts +32 -0
  397. package/dist/ui/split-button.js +60 -0
  398. package/dist/ui/split-button.js.map +1 -0
  399. package/{ui → dist/ui}/surfaces.js +1 -1
  400. package/dist/ui/surfaces.js.map +1 -0
  401. package/dist/ui/tab.d.ts +38 -0
  402. package/dist/ui/tab.js +87 -0
  403. package/dist/ui/tab.js.map +1 -0
  404. package/dist/ui/toast.d.ts +20 -0
  405. package/dist/ui/toast.js +115 -0
  406. package/dist/ui/toast.js.map +1 -0
  407. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  408. package/{ui → dist/ui}/tooltip-root.js +9 -8
  409. package/dist/ui/tooltip-root.js.map +1 -0
  410. package/{ui → dist/ui}/variants.js +1 -1
  411. package/dist/ui/variants.js.map +1 -0
  412. package/package.json +77 -23
  413. package/adapters/icons.js.map +0 -1
  414. package/adapters/lossy.js +0 -233
  415. package/adapters/lossy.js.map +0 -1
  416. package/adapters/prod-types.js.map +0 -1
  417. package/adapters/schema.js.map +0 -1
  418. package/adapters/values.js.map +0 -1
  419. package/brand/logo.js +0 -9
  420. package/brand/logo.js.map +0 -1
  421. package/context.js.map +0 -1
  422. package/controls/button.js.map +0 -1
  423. package/controls/c1.js.map +0 -1
  424. package/controls/c2.js.map +0 -1
  425. package/controls/choice.js.map +0 -1
  426. package/controls/code-register.js.map +0 -1
  427. package/controls/code.js.map +0 -1
  428. package/controls/color.js.map +0 -1
  429. package/controls/date-register.js.map +0 -1
  430. package/controls/date-zone.js.map +0 -1
  431. package/controls/date.js.map +0 -1
  432. package/controls/form-picker-register.js.map +0 -1
  433. package/controls/form-picker.js.map +0 -1
  434. package/controls/icon-register.js.map +0 -1
  435. package/controls/icon.js.map +0 -1
  436. package/controls/index.js.map +0 -1
  437. package/controls/json-register.js.map +0 -1
  438. package/controls/json.js.map +0 -1
  439. package/controls/link.js.map +0 -1
  440. package/controls/location-register.js.map +0 -1
  441. package/controls/location.js.map +0 -1
  442. package/controls/media-register.js.map +0 -1
  443. package/controls/media.js.map +0 -1
  444. package/controls/number.js.map +0 -1
  445. package/controls/reference-register.js.map +0 -1
  446. package/controls/reference.js.map +0 -1
  447. package/controls/rich-text/blocks.d.ts +0 -28
  448. package/controls/rich-text/blocks.js.map +0 -1
  449. package/controls/rich-text/catalog.js.map +0 -1
  450. package/controls/rich-text/codec.js.map +0 -1
  451. package/controls/rich-text/component-card.js.map +0 -1
  452. package/controls/rich-text/control.js.map +0 -1
  453. package/controls/rich-text/dom.js.map +0 -1
  454. package/controls/rich-text/editor.js.map +0 -1
  455. package/controls/rich-text/floating.js.map +0 -1
  456. package/controls/rich-text/index.js.map +0 -1
  457. package/controls/rich-text/link-form.js +0 -111
  458. package/controls/rich-text/link-form.js.map +0 -1
  459. package/controls/rich-text/markdown.js.map +0 -1
  460. package/controls/rich-text/ops.js.map +0 -1
  461. package/controls/rich-text/toolbar.js.map +0 -1
  462. package/controls/scale.js.map +0 -1
  463. package/controls/slot-register.js.map +0 -1
  464. package/controls/slot-services.js +0 -38
  465. package/controls/slot-services.js.map +0 -1
  466. package/controls/slot.js.map +0 -1
  467. package/controls/table/index.js.map +0 -1
  468. package/controls/table/prod.js.map +0 -1
  469. package/controls/table/refs.js.map +0 -1
  470. package/controls/table/stored.js.map +0 -1
  471. package/controls/table/table-editor.js.map +0 -1
  472. package/controls/table/table-link.js.map +0 -1
  473. package/controls/table/table.js.map +0 -1
  474. package/controls/text.js.map +0 -1
  475. package/engine/array.js.map +0 -1
  476. package/engine/bits.js.map +0 -1
  477. package/engine/breadcrumb.js.map +0 -1
  478. package/engine/expand.js.map +0 -1
  479. package/engine/field-list.js.map +0 -1
  480. package/engine/field-shell.js.map +0 -1
  481. package/engine/frame.js.map +0 -1
  482. package/engine/group-summary.js.map +0 -1
  483. package/engine/grouping.js.map +0 -1
  484. package/engine/item-list.js.map +0 -1
  485. package/engine/kit-field.js.map +0 -1
  486. package/engine/schema-form.js.map +0 -1
  487. package/engine/slot.js.map +0 -1
  488. package/index.js +0 -55
  489. package/index.js.map +0 -1
  490. package/lib/cn.js.map +0 -1
  491. package/lib/columns.js.map +0 -1
  492. package/lib/frames.js.map +0 -1
  493. package/lib/icons.js.map +0 -1
  494. package/lib/path.js.map +0 -1
  495. package/lib/schema.js.map +0 -1
  496. package/lib/utils.js.map +0 -1
  497. package/lib/validate.js.map +0 -1
  498. package/schema/adapters.js.map +0 -1
  499. package/schema/help.js.map +0 -1
  500. package/schema/scale.js.map +0 -1
  501. package/schema/sources.js.map +0 -1
  502. package/schema/table.js.map +0 -1
  503. package/schema/types.js.map +0 -1
  504. package/ui/action-tray.js.map +0 -1
  505. package/ui/button.js.map +0 -1
  506. package/ui/choice-switch.js.map +0 -1
  507. package/ui/controls.js.map +0 -1
  508. package/ui/display.js.map +0 -1
  509. package/ui/expanded-editor-modal.js.map +0 -1
  510. package/ui/field-context.js.map +0 -1
  511. package/ui/floating-panel.js.map +0 -1
  512. package/ui/index.js +0 -13
  513. package/ui/input.js.map +0 -1
  514. package/ui/mode-bar.js.map +0 -1
  515. package/ui/overlay.js +0 -378
  516. package/ui/overlay.js.map +0 -1
  517. package/ui/path-crumbs.js.map +0 -1
  518. package/ui/presence.js.map +0 -1
  519. package/ui/select.js.map +0 -1
  520. package/ui/shortcut-hint.js.map +0 -1
  521. package/ui/surfaces.js.map +0 -1
  522. package/ui/tooltip-root.js.map +0 -1
  523. package/ui/variants.js.map +0 -1
  524. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  525. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  526. /package/{brand → dist/brand}/logo.d.ts +0 -0
  527. /package/{controls → dist/controls}/c1.d.ts +0 -0
  528. /package/{controls → dist/controls}/c2.d.ts +0 -0
  529. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  530. /package/{controls → dist/controls}/code.d.ts +0 -0
  531. /package/{controls → dist/controls}/color.d.ts +0 -0
  532. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  533. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  534. /package/{controls → dist/controls}/date.d.ts +0 -0
  535. /package/{controls → dist/controls}/form-picker-register.d.ts +0 -0
  536. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  537. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  538. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  539. /package/{controls → dist/controls}/json.d.ts +0 -0
  540. /package/{controls → dist/controls}/link.d.ts +0 -0
  541. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  542. /package/{controls → dist/controls}/location.d.ts +0 -0
  543. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  544. /package/{controls → dist/controls}/number.d.ts +0 -0
  545. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  546. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  547. /package/{controls → dist/controls}/rich-text/link-form.d.ts +0 -0
  548. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  549. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  550. /package/{controls → dist/controls}/scale.d.ts +0 -0
  551. /package/{controls → dist/controls}/slot-register.d.ts +0 -0
  552. /package/{controls → dist/controls}/slot.d.ts +0 -0
  553. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  554. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  555. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  556. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  557. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  558. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  559. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  560. /package/{engine → dist/engine}/array.d.ts +0 -0
  561. /package/{engine → dist/engine}/bits.d.ts +0 -0
  562. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  563. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  564. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  565. /package/{engine → dist/engine}/slot.d.ts +0 -0
  566. /package/{index.d.ts → dist/index.d.ts} +0 -0
  567. /package/{lib → dist/lib}/cn.d.ts +0 -0
  568. /package/{lib → dist/lib}/columns.d.ts +0 -0
  569. /package/{lib → dist/lib}/frames.d.ts +0 -0
  570. /package/{lib → dist/lib}/icons.d.ts +0 -0
  571. /package/{lib → dist/lib}/path.d.ts +0 -0
  572. /package/{lib → dist/lib}/utils.d.ts +0 -0
  573. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  574. /package/{schema → dist/schema}/scale.d.ts +0 -0
  575. /package/{schema → dist/schema}/sources.d.ts +0 -0
  576. /package/{schema → dist/schema}/table.d.ts +0 -0
  577. /package/{types.d.ts → dist/types.d.ts} +0 -0
  578. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  579. /package/{ui → dist/ui}/controls.d.ts +0 -0
  580. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  581. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  582. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  583. /package/{ui → dist/ui}/presence.d.ts +0 -0
  584. /package/{ui → dist/ui}/select.d.ts +0 -0
  585. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  586. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  587. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","names":[],"sources":["../../src/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 * - \"Crop for this placement\" is V2's five-crop dropdown, stored as the rect prod keeps (cut from the picture's own size,\n * centred on the focal point); a stored rect reads back as its preset when the size is known, and is kept as it is\n * otherwise. With no size yet, the dropdown waits, and says why;\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 IconCrop,\n IconDots,\n IconDownload,\n IconExternalLink,\n IconFileText,\n IconFocusCentered,\n IconLink,\n IconPhoto,\n IconPlayerPlay,\n IconPlus,\n IconRefresh,\n IconReplace,\n IconTrash,\n IconUpload,\n IconVideo,\n IconWorld,\n IconX,\n} from \"@tabler/icons-react\";\nimport type {} from \"./media-services\";\nimport { Button, IconButton } 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 { RowChrome } from \"../engine/bits\";\nimport { Select } from \"../ui/select\";\nimport { cropPreset, cropRect, isCropRect, type V2ImageCrop } from \"../adapters/values\";\nimport type { ProdImageCrop } from \"../adapters/prod-types\";\nimport { useKitEnv, useKitServices, type KitMediaAsset, type KitServices, type KitSiteIcon } from \"../context\";\nimport type { ControlProps } from \"../types\";\nimport { isIconImage } from \"../lib/icon-image\";\n\n/* ── Values ─────────────────────────────────────────────────────────── */\n/** The image value the kit edits (V2 ImageValue, minus what prod cannot store: caption, width, height, size). */\nexport interface ImageValue {\n url: string;\n alt?: string;\n /** percent */\n focal?: { x: number; y: number };\n /** This placement's crop, as prod stores it (0–1 edges of the picture). Absent: the whole picture. */\n crop?: ProdImageCrop | V2ImageCrop;\n name?: string;\n id?: string;\n [key: string]: unknown;\n}\n\nexport const fileNameFromUrl = (url: string) => {\n // An inline (data:) image has no file and no host. It was labelled \"Uploaded image\", which is false for most of\n // them: a fresh Image block's 800 × 600 stand-in is one, and nobody uploaded it. Its source is named by what the\n // URI does carry, its type: \"Embedded SVG image\".\n const inline = /^data:image\\/([a-z0-9.+-]+)/i.exec(url.trim());\n if (inline) return `Embedded ${inline[1].replace(/\\+xml$/i, \"\").replace(/^jpeg$/i, \"jpg\").toUpperCase()} image`;\n // V2 `lib/image-edit.ts` fileNameFromUrl: the last path segment that has an extension, else \"Image from <host>\". A\n // URL with no file in it (picsum's `/800/600`) printed its last segment (\"600\") as the name.\n try {\n const u = new URL(url, typeof window === \"undefined\" ? \"https://x.invalid\" : window.location.href);\n if (u.protocol === \"data:\" || u.protocol === \"blob:\") return \"Image\";\n const file = u.pathname.split(\"/\").filter(Boolean).reverse().find((x) => /\\.[a-z0-9]{2,5}$/i.test(x));\n return file ? decodeURIComponent(file) : `Image from ${u.hostname.replace(/^www\\./, \"\")}`;\n } catch {\n return \"Image\";\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 // an icon picked from the site by its url alone has no asset id\n const out: ImageValue = a.id ? { url: a.url, id: a.id } : { url: a.url };\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_ICONS = (): KitSiteIcon[] => [];\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 <>\n <form\n className=\"flex w-full max-w-sm items-center 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 <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 />\n <Button size=\"sm\" type=\"submit\" variant=\"primary\">\n Add\n </Button>\n </form>\n {/* V2 says this in a toast; the kit says it in place, under the form (a toast service may be absent) */}\n {urlError ? <Reason>{urlError}</Reason> : null}\n </>\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 ─────────────────────────────────────────────────────────── */\n/** Transparency checker on the kit tokens (white in light, dimmed in dark), as the media grid draws it. */\nconst CHECKER =\n \"bg-kit-checker-a [background-image:conic-gradient(var(--kit-checker-b)_25%,var(--kit-checker-a)_0_50%,var(--kit-checker-b)_0_75%,var(--kit-checker-a)_0)] [background-size:12px_12px]\";\n\n/** The preview frame's shape bounds: a tall or panoramic picture never makes the dock tall or a sliver. */\nconst FRAME_MIN = 1;\nconst FRAME_MAX = 2;\n\n/**\n * How a preview frames a picture of any shape: the frame follows the picture's ratio between square and 2:1, and the\n * picture fits inside it WHOLE, filling the frame's width or height (a portrait is boxed at the sides, a panorama above\n * and below, on the checker). With no known size (still loading, or an SVG with no intrinsic size) the frame is 16:9\n * and the picture is contained. Before 2026-10-16 every picture was cropped to a fixed 16:9 (`object-cover`).\n */\nexport function frameFit(size: { w: number; h: number } | undefined): { frame: number; image: number | null; fill: \"width\" | \"height\" | \"contain\" } {\n if (!size || !(size.w > 0) || !(size.h > 0)) return { frame: 16 / 9, image: null, fill: \"contain\" };\n const image = size.w / size.h;\n const frame = Math.min(FRAME_MAX, Math.max(FRAME_MIN, image));\n return { frame, image, fill: image < frame ? \"height\" : \"width\" };\n}\n\n/** The picture's classes for a fit: it keeps its own ratio and the frame's width or height, never cut. */\nconst FIT_CLASS: Record<ReturnType<typeof frameFit>[\"fill\"], string> = {\n width: \"h-auto max-h-full w-full object-contain\",\n height: \"h-full w-auto max-w-full object-contain\",\n contain: \"size-full object-contain\",\n};\n\n/** V2's five crops (kit media.tsx CROPS, D46). */\nconst CROPS: { value: V2ImageCrop; label: string; ratio: string; description: string }[] = [\n { value: \"original\", label: \"Original\", ratio: \"auto\", description: \"Keep the uploaded shape\" },\n { value: \"16:9\", label: \"16:9\", ratio: \"16/9\", description: \"Widescreen\" },\n { value: \"4:3\", label: \"4:3\", ratio: \"4/3\", description: \"Landscape\" },\n { value: \"1:1\", label: \"1:1\", ratio: \"1/1\", description: \"Square\" },\n { value: \"4:5\", label: \"4:5\", ratio: \"4/5\", description: \"Portrait\" },\n];\nconst CUSTOM_CROP = \"custom\";\n\n/** The crop a value shows: its preset, a stored rect read against the picture's size, or a rect that is none of them. */\nexport function cropChoice(crop: ImageValue[\"crop\"], size?: { w: number; h: number }): V2ImageCrop | typeof CUSTOM_CROP {\n if (!crop) return \"original\";\n if (typeof crop === \"string\") return crop;\n if (!isCropRect(crop)) return \"original\";\n return (size && cropPreset(crop, size.w, size.h)) || CUSTOM_CROP;\n}\n\n/** A custom rect's own shape (its fractions of the picture, in pixels), when the picture's size is known. */\nfunction customRatio(crop: ImageValue[\"crop\"], size?: { w: number; h: number }): string | undefined {\n if (!size || !crop || typeof crop === \"string\" || !isCropRect(crop)) return undefined;\n const w = (1 - crop.left - crop.right) * size.w;\n const h = (1 - crop.top - crop.bottom) * size.h;\n return w > 0 && h > 0 ? String(w / h) : undefined;\n}\n\n/** The value with `choice` cut from the picture (centred on its focal point), or with no crop for Original. */\nexport function withCrop(v: ImageValue, choice: V2ImageCrop, size: { w: number; h: number }): ImageValue {\n const next = { ...v };\n delete next.crop;\n const rect = choice === \"original\" ? undefined : cropRect(choice, size.w, size.h, v.focal);\n if (rect) next.crop = rect;\n return next;\n}\n\nfunction ImageDetails({\n v,\n onChange,\n readOnly,\n label,\n urlOnly,\n altOnly = false,\n size,\n asset,\n}: {\n v: ImageValue;\n onChange: (n: ImageValue) => void;\n readOnly?: boolean;\n label: string;\n urlOnly: boolean;\n /** Only the alt text is kept with this image (`imageAltOnly`). */\n altOnly?: 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 choice = cropChoice(v.crop, size);\n const crop = CROPS.find((c) => c.value === choice);\n // The click pad is the shape the picture is shown in, so a click lands on the subject: a preset crop's shape, a\n // custom rect's, else the picture's own (fitted whole, as the preview). 3:2 only before the size is known.\n const own = choice === \"original\" && size ? frameFit(size) : null;\n const pad = own?.image ? own : null;\n const padRatio =\n crop && crop.ratio !== \"auto\" ? crop.ratio : pad ? String(pad.image) : customRatio(v.crop, size) ?? \"3/2\";\n // A preset crop is cut around the focal point (V2 centres the crop on it): moving the point recuts the window.\n const setFocal = (x: number, y: number) => {\n const next: ImageValue = { ...v, focal: { x: Math.round(Math.min(100, Math.max(0, x))), y: Math.round(Math.min(100, Math.max(0, y))) } };\n onChange(crop && crop.value !== \"original\" && size ? withCrop(next, crop.value, size) : next);\n };\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 {altOnly ? (\n <Reason tone=\"muted\">This image block keeps its address and alt text. A crop or focal point isn't stored with it.</Reason>\n ) : (\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 <IconCrop className=\"size-3.5\" stroke={1.5} aria-hidden />\n Crop for this placement\n </span>\n <span className=\"flex items-center gap-1 text-kit-2xs text-kit-fg-3\">\n <IconFocusCentered className=\"size-3\" stroke={1.5} aria-hidden />\n Focal {focal.x}%, {focal.y}%\n </span>\n </div>\n {/* V2 D46: five crops as a dropdown. A crop is cut from the picture's own size, so it waits for it. */}\n <Select\n size=\"sm\"\n aria-label={`${label} crop`}\n disabled={readOnly || !size}\n triggerClassName=\"w-full\"\n value={choice}\n onValueChange={(c) => size && c !== CUSTOM_CROP && onChange(withCrop(v, c as V2ImageCrop, size))}\n options={[\n ...CROPS.map((c) => ({ value: c.value, label: c.label, meta: c.description })),\n ...(choice === CUSTOM_CROP ? [{ value: CUSTOM_CROP, label: \"Custom\", meta: \"Cut elsewhere\", disabled: true }] : []),\n ]}\n />\n {!size && !readOnly ? <span className=\"text-kit-2xs text-kit-fg-3\">The crop is cut from the picture's size, which is still loading.</span> : null}\n <div\n className={cn(pad ? \"mt-1 flex items-center justify-center overflow-hidden rounded-kit-md border border-kit-line\" : \"contents\", pad && CHECKER)}\n style={pad ? { aspectRatio: pad.frame } : undefined}\n >\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 data-pad-ratio={padRatio}\n // V2's pad; inside the AD-FRAMEFIT frame (Original, size known) it is the picture's own box in it\n className={\n pad\n ? cn(\"relative cursor-crosshair overflow-hidden\", pad.fill === \"height\" ? \"h-full\" : \"w-full\")\n : \"relative mt-1 cursor-crosshair overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted\"\n }\n style={{ aspectRatio: padRatio }}\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\" 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-media-handle bg-kit-media-handle-ring shadow-kit-md transition-[left,top] duration-150\"\n style={{ left: `${focal.x}%`, top: `${focal.y}%` }}\n />\n </div>\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 )}\n {urlOnly || altOnly ? (\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 ) : (\n // V2: the file name this placement shows, editable (stored as the value's `name`).\n <label className=\"flex flex-col gap-1.5\">\n <span className=\"text-kit-xs text-kit-fg-3\">File name</span>\n <Input\n size=\"sm\"\n value={v.name ?? asset?.name ?? fileNameFromUrl(v.url)}\n readOnly={readOnly}\n spellCheck={false}\n autoComplete=\"off\"\n onChange={(e) => {\n const next = { ...v };\n if (e.target.value) next.name = e.target.value;\n else delete next.name;\n onChange(next);\n }}\n className=\"font-kit-mono [&_input]:font-kit-mono\"\n aria-label={`${label} file name`}\n />\n </label>\n )}\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\n/* ── Icon: an inline-SVG image is one 32px row, not a picture card ─── */\n/**\n * V2's icon control shape (controls/icon.tsx): ONE button — a 24px glyph tile, the field's name, a quiet replace cue —\n * that opens the library. No Replace pill, no ×, no alt text, crop or details: an icon's alt text is \"\" (aria-hidden on\n * the page) and Remove sits in the picker's footer. Empty: a dashed tile, \"Add icon\", and an SVG dropped on it uploads.\n */\nfunction IconImageRow({\n id,\n title,\n url,\n readOnly,\n onOpen,\n onFiles,\n busy,\n pickerOpen,\n}: {\n id: string;\n title: string;\n url?: string;\n readOnly?: boolean;\n onOpen?: () => void;\n onFiles?: (files: File[]) => void;\n busy: boolean;\n pickerOpen: boolean;\n}) {\n const row = React.useRef<HTMLButtonElement>(null);\n const [over, setOver] = React.useState(false);\n // However the picker closes (Escape, Cancel, a pick, Remove), focus comes back to the row that opened it.\n const wasOpen = React.useRef(false);\n React.useEffect(() => {\n if (wasOpen.current && !pickerOpen) row.current?.focus({ preventScroll: true });\n wasOpen.current = pickerOpen;\n }, [pickerOpen]);\n const empty = !url;\n const inert = readOnly || busy || !onOpen;\n const droppable = empty && !inert && !!onFiles;\n // the field's own chrome (comments, presence, the field menu): the shell draws no label row for an icon, so the row\n // carries it at its trailing edge, as NavRow does\n const chrome = React.useContext(RowChrome);\n return (\n <div\n className={cn(\n \"flex h-8 min-w-0 items-center rounded-kit-md border bg-kit-field-bg pointer-coarse:min-h-11\",\n \"transition-colors duration-[120ms] ease-out motion-reduce:transition-none\",\n over ? \"border-kit-emphasis-line bg-kit-hover\" : \"border-kit-line-strong\",\n inert ? \"opacity-60\" : \"[@media(hover:hover)]:hover:bg-kit-hover\",\n )}\n >\n <Tooltip content={title}>\n <button\n ref={row}\n id={id}\n type=\"button\"\n data-slot=\"kit-icon-row\"\n disabled={inert}\n onClick={onOpen}\n aria-label={empty ? `Add icon, ${title}` : `Replace ${title}`}\n onDragOver={droppable ? (e) => { e.preventDefault(); setOver(true); } : undefined}\n onDragLeave={droppable ? () => setOver(false) : undefined}\n onDrop={droppable ? (e) => { e.preventDefault(); setOver(false); onFiles(Array.from(e.dataTransfer.files)); } : undefined}\n className=\"flex min-w-0 flex-1 touch-manipulation items-center gap-3 self-stretch rounded-[5px] pl-[3px] pr-2 text-left text-kit-sm focus-visible:-outline-offset-2 disabled:cursor-not-allowed\"\n >\n <span\n aria-hidden\n className={cn(\n \"grid size-6 shrink-0 place-items-center overflow-hidden rounded-kit-sm border\",\n empty ? \"border-dashed border-kit-emphasis-line\" : cn(\"border-kit-line p-1\", CHECKER),\n )}\n >\n {empty ? <IconPlus className=\"size-3.5 text-kit-fg-3\" stroke={1.5} /> : <img src={url} alt=\"\" className=\"size-full object-contain\" />}\n </span>\n <span aria-hidden className={cn(\"min-w-0 flex-1 truncate\", empty ? \"text-kit-fg-3\" : \"text-kit-fg\")}>\n {empty ? (busy ? \"Uploading…\" : \"Add icon\") : title}\n </span>\n {empty ? null : <IconRefresh aria-hidden className=\"size-3.5 shrink-0 text-kit-fg-3\" stroke={1.5} />}\n </button>\n </Tooltip>\n {chrome ? <span data-slot=\"kit-icon-row-chrome\" className=\"flex shrink-0 items-center gap-0.5 pr-1 empty:hidden\">{chrome}</span> : null}\n </div>\n );\n}\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 altOnly = !urlOnly && !!s.imageAltOnly?.(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 // an inline-SVG icon takes SVG files only: a raster there never reaches the page (publish answers svgUnavailable)\n const accept = field.svgOnly ? \"image/svg+xml\" : \"image/*\";\n const kinds: (\"image\" | \"svg\")[] = field.svgOnly ? [\"svg\"] : [\"image\", \"svg\"];\n /*\n * The loaded preview's size, keyed to the URL it was read from. It used to be cleared by an effect on [url], which\n * also ran on MOUNT: a cached picture (the Values popover opened again) finished loading before that effect ran, so\n * the reset wiped the size its load had just set and the caption lost \"· 2400 × 1600\". A picture that is already\n * complete when it mounts is read there too, since its load may have fired before the handler was attached.\n */\n const [loaded, setLoaded] = React.useState<{ url: string; w: number; h: number } | undefined>();\n const natural = loaded && v && loaded.url === v.url ? { w: loaded.w, h: loaded.h } : undefined;\n const readNatural = (img: HTMLImageElement | null) => {\n if (!img || !v || !img.complete || !img.naturalWidth || !img.naturalHeight) return;\n const next = { url: v.url, w: img.naturalWidth, h: img.naturalHeight };\n setLoaded((prev) => (prev && prev.url === next.url && prev.w === next.w && prev.h === next.h ? prev : next));\n };\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. Elsewhere a value stored as a URL string becomes V2's object as soon as\n it carries more than the URL (a name, alt text, a focal point or a crop): an older string is still read as is. */\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 && !n.crop && !n.name && !n.id) 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(accept, \"image\", (a) => a[0] && onChange(fromAsset(a[0])));\n const library = s.MediaPicker && !readOnly ? () => setPicker(true) : undefined;\n const known = (s.useSiteIcons ?? NO_ICONS)();\n\n if (isIconImage(field, value)) {\n // This field's own icon leads, marked, so the author sees what they are replacing.\n const icons = s.useSiteIcons\n ? [\n ...(v ? [{ url: v.url, value, current: true }] : []),\n ...known.filter((i) => i.url !== v?.url && !(v?.id && i.assetId === v.id)).map(({ url, value: stored }) => ({ url, value: stored })),\n ]\n : undefined;\n const pickIcon = (stored: unknown) => {\n const n = normImage(stored);\n if (n) onChange(fromAsset({ id: n.id ?? \"\", url: n.url, name: n.name, alt: n.alt ?? (typeof n.altText === \"string\" ? n.altText : undefined), kind: \"svg\" }));\n setPicker(false);\n };\n return (\n <div className=\"flex flex-col gap-1.5\">\n <IconImageRow\n id={id}\n title={field.title}\n url={v ? src(v.url) : undefined}\n readOnly={readOnly}\n onOpen={library}\n onFiles={up.run}\n busy={up.progress != null}\n pickerOpen={picker}\n />\n {up.error ? <Reason>{up.error}</Reason> : null}\n {!readOnly && !library ? <Reason tone=\"muted\">{NO_LIBRARY}</Reason> : null}\n <MediaPicker\n open={picker}\n onOpenChange={setPicker}\n accept={[\"svg\"]}\n title={v ? \"Replace icon\" : \"Select an icon\"}\n onPick={(a) => a[0] && onChange(fromAsset(a[0]))}\n onRemove={v && !readOnly ? () => { onChange(null); setPicker(false); } : undefined}\n icons={icons}\n onPickIcon={readOnly ? undefined : pickIcon}\n />\n </div>\n );\n }\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={accept}\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={kinds} onPick={(a) => a[0] && onChange(fromAsset(a[0]))} />\n </div>\n );\n\n const fit = frameFit(size);\n // A raster is never blown up past its own pixels (a 32px icon at the dock's width is a blur); an SVG scales sharp.\n const vector = asset?.kind === \"svg\" || !!field.svgOnly || /\\.svg(?:$|[?#])/i.test(v.url);\n const cap = fit.image && size && !vector ? size : undefined;\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\n data-slot=\"kit-image-frame\"\n data-frame-ratio={String(fit.frame)}\n className={cn(\"group/img relative overflow-hidden rounded-kit-lg border border-kit-line\", CHECKER)}\n style={{ aspectRatio: fit.frame }}\n >\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=\"flex size-full items-center justify-center 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 ref={readNatural}\n onLoad={(e) => readNatural(e.currentTarget)}\n data-fill={fit.fill}\n data-image-ratio={fit.image ?? undefined}\n data-cap={cap ? `${cap.w}x${cap.h}` : undefined}\n className={FIT_CLASS[fit.fill]}\n style={\n fit.image\n ? { aspectRatio: fit.image, ...(cap ? { maxWidth: `min(100%, ${cap.w}px)`, maxHeight: `min(100%, ${cap.h}px)` } : {}) }\n : undefined\n }\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=\"flex h-7 items-center gap-1 rounded-full border border-kit-swatch-ring bg-kit-media-control px-2.5 text-kit-xs font-medium text-kit-media-control-fg shadow-kit-sm\">\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=\"flex size-7 items-center justify-center rounded-full border border-kit-swatch-ring bg-kit-media-control text-kit-media-control-fg shadow-kit-sm\">\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 {/* V2: Replace and Remove are always listed, disabled when they can't act (read-only, or no library) */}\n <MenuItem icon={<IconReplace stroke={1.5} />} disabled={!library} onClick={library}>\n Replace\n </MenuItem>\n <MenuItem icon={<IconExternalLink stroke={1.5} />} onClick={() => window.open(src(v.url), \"_blank\", \"noopener\")}>\n Open original\n </MenuItem>\n <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} disabled={readOnly} onClick={() => !readOnly && onChange(null)}>\n Remove\n </MenuItem>\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} altOnly={altOnly} size={size} asset={asset} />\n </PopoverContent>\n <MediaPicker open={picker} onOpenChange={setPicker} accept={kinds} 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 // V2's thumb; the checker in place of bg-kit-muted is AD-FRAMEFIT\n className={cn(\n \"group/thumb relative aspect-square cursor-grab touch-none overflow-hidden rounded-kit-md border border-kit-line active:cursor-grabbing\",\n CHECKER,\n sort.active === item.key && \"z-10 opacity-90 shadow-kit-lg ring-2 ring-kit-line-strong\",\n )}\n >\n <div\n {...(readOnly ? {} : handle)}\n role={undefined}\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=\"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 {/* the whole picture, any shape, on the checker (a cover crop hid a portrait's subject and a logo's edges) */}\n <img src={src(item.v.url)} alt={item.v.alt ?? \"\"} data-slot=\"kit-gallery-thumb\" className=\"pointer-events-none size-full select-none object-contain\" 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 // AD-A11Y-GALLERY: V2's classes, plus a name per picture and a touch-only reveal (no hover on touch)\n aria-label={(() => {\n const what = item.v.alt || item.v.name || fileNameFromUrl(item.v.url);\n return what ? `Remove ${what}` : \"Remove image\";\n })()}\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 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, path }: ControlProps) {\n const { s, src } = useMedia();\n const env = useKitEnv();\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 // the host's image editor where it has one (`editImage`), else the picture itself\n onOpen={() => (s.editImage && !readOnly ? s.editImage({ docId: env.docId, path: [...path, i], title: noun(i, it) }) : 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 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 render={<IconButton label=\"File actions\" size=\"sm\" />}>\n <IconDots stroke={1.5} />\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 <MenuSeparator />\n <MenuItem danger icon={<IconTrash stroke={1.5} />} disabled={readOnly} onClick={() => !readOnly && onChange(null)}>\n Remove\n </MenuItem>\n </MenuContent>\n </Menu>\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-media-backdrop\" />;\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-media-backdrop\">\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-media-control text-kit-media-control-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-scrim px-1.5 py-0.5 text-kit-xs text-kit-on-scrim\">\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwEA,IAAa,mBAAmB,QAAgB;CAI9C,MAAM,SAAS,+BAA+B,KAAK,IAAI,KAAK,CAAC;CAC7D,IAAI,QAAQ,OAAO,YAAY,OAAO,EAAE,CAAC,QAAQ,WAAW,EAAE,CAAC,CAAC,QAAQ,WAAW,KAAK,CAAC,CAAC,YAAY,EAAE;CAGxG,IAAI;EACF,MAAM,IAAI,IAAI,IAAI,KAAK,OAAO,WAAW,cAAc,sBAAsB,OAAO,SAAS,IAAI;EACjG,IAAI,EAAE,aAAa,WAAW,EAAE,aAAa,SAAS,OAAO;EAC7D,MAAM,OAAO,EAAE,SAAS,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,MAAM,oBAAoB,KAAK,CAAC,CAAC;EACpG,OAAO,OAAO,mBAAmB,IAAI,IAAI,cAAc,EAAE,SAAS,QAAQ,UAAU,EAAE;CACxF,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAa,aAAa,MAAkC;CAC1D,IAAI,OAAO,MAAM,UAAU,OAAO,IAAI,EAAE,KAAK,EAAE,IAAI;CACnD,OAAO,MAAM,CAAC,KAAK,OAAO,EAAE,QAAQ,YAAY,EAAE,MAAO,IAAmB;AAC9E;;AAGA,IAAa,aAAa,MAAiC;CAEzD,MAAM,MAAkB,EAAE,KAAK;EAAE,KAAK,EAAE;EAAK,IAAI,EAAE;CAAG,IAAI,EAAE,KAAK,EAAE,IAAI;CACvE,IAAI,EAAE,MAAM,IAAI,OAAO,EAAE;CACzB,IAAI,EAAE,KAAK,IAAI,MAAM,EAAE;CACvB,OAAO;AACT;AAEA,IAAa,eAAe,MAAe,KAAK,MAAY,IAAI,IAAI,IAAA,CAAW,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,GAAI,CAAC,EAAE;AAEtI,IAAM,OAAO;;AAEb,IAAa,cAAc,MAAc,MAAM,MAAM,KAAK,KAAK,EAAE,KAAK,CAAC,KAAK,gBAAgB,KAAK,EAAE,KAAK,CAAC;AAEzG,IAAM,iBAAiB,KAAA;AACvB,IAAM,iBAAgC,CAAC;AACvC,IAAM,UAAU,MAAc;;AAG9B,SAAS,WAAW;CAClB,MAAM,IAAI,eAAe;CACzB,OAAO;EAAE;EAAG,UAAU,EAAE,iBAAiB;EAAU,KAAK,EAAE,YAAY;CAAO;AAC/E;;AAGA,SAAgB,YAAY,QAAgB,MAA4C;CACtF,OAAO,OAAO,MAAM,GAAG,CAAC,CAAC,MAAM,QAAQ;EACrC,MAAM,OAAO,IAAI,KAAK,CAAC,CAAC,YAAY;EACpC,IAAI,CAAC,QAAQ,SAAS,OAAO,SAAS,OAAO,OAAO;EACpD,IAAI,KAAK,WAAW,GAAG,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC,CAAC,SAAS,IAAI;EACtE,IAAI,KAAK,SAAS,IAAI,GAAG,OAAO,KAAK,KAAK,YAAY,CAAC,CAAC,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC;EACpF,OAAO,KAAK,KAAK,YAAY,MAAM;CACrC,CAAC;AACH;AAGA,SAAgB,YAAY,GAAkE;CAC5F,MAAM,SAAS,eAAe,CAAC,CAAC;CAChC,OAAO,SAAS,oBAAC,QAAD,EAAQ,GAAI,EAAI,CAAA,IAAI;AACtC;;;;;AAMA,SAAgB,UAAU,QAAgB,MAAc,QAAsC;CAC5F,MAAM,EAAE,aAAa,YAAY,UAAU,eAAe;CAC1D,MAAM,CAAC,UAAU,eAAe,MAAM,SAAwB,IAAI;CAClE,MAAM,CAAC,OAAO,YAAY,MAAM,SAAwB,IAAI;CAC5D,MAAM,QAAQ,MAAM,OAAO,IAAI;CAC/B,MAAM,sBACQ;EACV,MAAM,UAAU;CAClB,GACA,CAAC,CACH;CA0BA,OAAO;EAAE;EAAU;EAAO;EAAU,KAzBxB,eACP,UAAkB;GACjB,IAAI,CAAC,MAAM,UAAU,YAAY,MAAM;GACvC,MAAM,MAAM,MAAM,MAAM,MAAM,CAAC,YAAY,QAAQ,CAAC,CAAC;GACrD,IAAI,KAAK;IACP,SAAS,GAAG,IAAI,QAAQ,YAAY,SAAS,SAAS,SAAS,4BAA4B,MAAM,OAAO,EAAE;IAC1G;GACF;GACA,SAAS,IAAI;GACb,YAAY,CAAC;GACb,YAAY,OAAO,EAAE,aAAa,MAAM,MAAM,WAAW,YAAY,KAAK,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC,CACnH,MAAM,WAAW;IAChB,IAAI,CAAC,MAAM,SAAS;IACpB,YAAY,IAAI;IAChB,aAAa,MAAM;IACnB,OAAO,MAAM;IACb,OAAO,QAAQ,MAAM,SAAS,IAAI,GAAG,MAAM,OAAO,mBAAmB,GAAG,OAAO,EAAE,EAAE,QAAQ,MAAM,EAAE,CAAC,KAAK,YAAY,EAAE,aAAa,6BAA6B,CAAC;GACpK,CAAC,CAAC,CACD,OAAO,MAAe;IACrB,IAAI,CAAC,MAAM,SAAS;IACpB,YAAY,IAAI;IAChB,SAAS,kBAAkB,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG;GACzE,CAAC;EACL,IACA,KAAA;CACoC;AAC1C;;AAGA,SAAS,OAAO,EAAE,UAAU,OAAO,YAAsE;CACvG,OACE,oBAAC,KAAD;EAAG,MAAM,SAAS,WAAW,UAAU;EAAQ,WAAW,GAAG,eAAe,SAAS,WAAW,uBAAuB,eAAe;EACnI;CACA,CAAA;AAEP;AAGA,SAAS,SAAS,EAChB,IACA,OACA,MACA,QACA,UACA,MACA,UACA,SACA,WACA,OACA,QACA,YAkBC;CACD,MAAM,CAAC,MAAM,WAAW,MAAM,SAAS,KAAK;CAC5C,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,KAAK;CAClD,MAAM,CAAC,KAAK,UAAU,MAAM,SAAS,EAAE;CACvC,MAAM,CAAC,UAAU,eAAe,MAAM,SAAwB,IAAI;CAClE,MAAM,QAAQ,MAAM,OAAyB,IAAI;CACjD,MAAM,cAAc,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC;CAC/C,MAAM,SAAS,MAAe,UAAU,QAAQ,CAAC,IAAI,SAAS,SAAS;CACvE,MAAM,kBAAmB,UAAU,MAAM,SAAS,MAAM,IAAI,SAAS,SAAS;CAC9E,OACE,qBAAC,OAAD;EACM;EACJ,UAAU,WAAW,KAAK;EAC1B,MAAK;EACL,cAAY,aAAa,GAAG,MAAM,6CAA6C;EAC/E,UAAU,MAAM;GACd,MAAM,SAAS,MAAM,KAAK,EAAE,cAAc,KAAK;GAC/C,IAAI,OAAO,UAAU,YAAY;IAC/B,EAAE,eAAe;IACjB,MAAM,MAAM;GACd;EACF;EACA,YAAY,MAAM;GAChB,IAAI,EAAE,QAAQ,WAAW,EAAE,WAAW,EAAE,iBAAiB,YAAY;IACnE,EAAE,eAAe;IACjB,UAAU;GACZ;EACF;EACA,aAAa,MAAM;GACjB,IAAI,CAAC,YAAY;GACjB,EAAE,eAAe;GACjB,QAAQ,IAAI;EACd;EACA,cAAc,MAAM;GAElB,IAAI,CAAC,EAAE,cAAc,SAAS,EAAE,aAA4B,GAAG,QAAQ,KAAK;EAC9E;EACA,SAAS,MAAM;GACb,IAAI,CAAC,YAAY;GACjB,EAAE,eAAe;GACjB,QAAQ,KAAK;GACb,MAAM,MAAM,KAAK,EAAE,aAAa,KAAK,CAAC;EACxC;EACA,aAAU;EACV,WAAW,GACT,2HACA,OAAO,2CAA2C,0EACpD;EArCF,UAAA;GAuCE,oBAAC,QAAD;IAAM,WAAW,GAAG,qIAAqI,QAAQ,oBAAoB;IAAI,UAAA;GAAW,CAAA;GACpM,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,OAAD;IAAK,WAAU;IAAuC,UAAA,OAAO,mBAAmB;GAAW,CAAA,GAC1F,aAAa,oBAAC,OAAD;IAAK,WAAU;IAA6B,UAAA;GAAU,CAAA,IAAI,IACrE,EAAA,CAAA;GACJ,WAAW,QACV,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,QAAD;IACE,WAAU;IACV,WAAW,MAAM;KACf,EAAE,eAAe;KACjB,EAAE,gBAAgB;KAClB,MAAM,IAAI,IAAI,KAAK;KACnB,IAAI,KAAK,KAAK,CAAC,GAAG;MAChB,MAAM,CAAC;MACP,WAAW,KAAK;MAChB,OAAO,EAAE;MACT,YAAY,IAAI;KAClB,OAAO,YAAY,gDAAgD;IACrE;IACA,YAAY,MAAM;KAChB,IAAI,EAAE,QAAQ,UAAU;MACtB,EAAE,gBAAgB;MAClB,WAAW,KAAK;MAChB,YAAY,IAAI;KAClB;IACF;IAnBF,UAAA,CAqBE,oBAAC,OAAD;KACE,WAAA;KACA,MAAK;KACL,OAAO;KACP,cAAW;KACX,gBAAc,WAAW,OAAO,KAAA;KAChC,WAAW,MAAM,OAAO,EAAE,OAAO,KAAK;KACtC,aAAY;KACZ,SAAS,oBAAC,UAAD,EAAU,QAAQ,IAAM,CAAA;IAClC,CAAA,GACD,oBAAC,QAAD;KAAQ,MAAK;KAAK,MAAK;KAAS,SAAQ;KAAU,UAAA;IAE1C,CAAA,CACJ;GAEL,CAAA,GAAA,WAAW,oBAAC,QAAD,EAAA,UAAS,SAAiB,CAAA,IAAI,IAC1C,EAAA,CAAA,IAEF,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACG,aAAa,SACZ,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAY,SAAS,oBAAoB,OAAQ,UAAU;MAAc;MAAU,UAAA;KAErG,CAAA,IACN;KACH,WAAW,SACV,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAQ,UAAU,oBAAC,YAAD,EAAY,QAAQ,IAAM,CAAA;MAAG,SAAS;MAAqB;MAAU,UAAA;KAEzG,CAAA,IACN;KACH,QACC,oBAAC,QAAD;MAAQ,MAAK;MAAK,SAAQ;MAAQ,eAAe,WAAW,IAAI;MAAa;MAAU,UAAA;KAE/E,CAAA,IACN;IACD;;GAEN,UACC,oBAAC,SAAD;IACE,KAAK;IACL,MAAK;IACL,QAAA;IACA,UAAU;IACV,eAAA;IACQ;IACE;IACV,WAAW,MAAM;KACf,QAAQ,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC;KACxC,EAAE,OAAO,QAAQ;IACnB;GACD,CAAA,IACC;GACH,YAAY,OACX,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACE,oBAAC,QAAD;OAAM,MAAK;OAAS,UAAA;MAAgB,CAAA;MAAC;MAAE;MAAS;KAC5C;IACN,CAAA,GAAA,oBAAC,UAAD;KAAU,OAAO;KAAU,MAAK;KAAM,OAAM;KAAkB,WAAU;IAAY,CAAA,CACjF;GACH,CAAA,IAAA;EACD;;AAET;;AAGA,IAAM,YAAY;AAClB,IAAM,aAAa;AACnB,IAAM,YAAY;;AAIlB,IAAM,UACJ;;AAGF,IAAM,YAAY;AAClB,IAAM,YAAY;;;;;;;AAQlB,SAAgB,SAAS,MAA2H;CAClJ,IAAI,CAAC,QAAQ,EAAE,KAAK,IAAI,MAAM,EAAE,KAAK,IAAI,IAAI,OAAO;EAAE,OAAO,KAAK;EAAG,OAAO;EAAM,MAAM;CAAU;CAClG,MAAM,QAAQ,KAAK,IAAI,KAAK;CAC5B,MAAM,QAAQ,KAAK,IAAI,WAAW,KAAK,IAAI,WAAW,KAAK,CAAC;CAC5D,OAAO;EAAE;EAAO;EAAO,MAAM,QAAQ,QAAQ,WAAW;CAAQ;AAClE;;AAGA,IAAM,YAAiE;CACrE,OAAO;CACP,QAAQ;CACR,SAAS;AACX;;AAGA,IAAM,QAAqF;CACzF;EAAE,OAAO;EAAY,OAAO;EAAY,OAAO;EAAQ,aAAa;CAA0B;CAC9F;EAAE,OAAO;EAAQ,OAAO;EAAQ,OAAO;EAAQ,aAAa;CAAa;CACzE;EAAE,OAAO;EAAO,OAAO;EAAO,OAAO;EAAO,aAAa;CAAY;CACrE;EAAE,OAAO;EAAO,OAAO;EAAO,OAAO;EAAO,aAAa;CAAS;CAClE;EAAE,OAAO;EAAO,OAAO;EAAO,OAAO;EAAO,aAAa;CAAW;AACtE;AACA,IAAM,cAAc;;AAGpB,SAAgB,WAAW,MAA0B,MAAmE;CACtH,IAAI,CAAC,MAAM,OAAO;CAClB,IAAI,OAAO,SAAS,UAAU,OAAO;CACrC,IAAI,CAAC,WAAW,IAAI,GAAG,OAAO;CAC9B,OAAQ,QAAQ,WAAW,MAAM,KAAK,GAAG,KAAK,CAAC,KAAM;AACvD;;AAGA,SAAS,YAAY,MAA0B,MAAqD;CAClG,IAAI,CAAC,QAAQ,CAAC,QAAQ,OAAO,SAAS,YAAY,CAAC,WAAW,IAAI,GAAG,OAAO,KAAA;CAC5E,MAAM,KAAK,IAAI,KAAK,OAAO,KAAK,SAAS,KAAK;CAC9C,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,UAAU,KAAK;CAC9C,OAAO,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,IAAI,KAAA;AAC1C;;AAGA,SAAgB,SAAS,GAAe,QAAqB,MAA4C;CACvG,MAAM,OAAO,EAAE,GAAG,EAAE;CACpB,OAAO,KAAK;CACZ,MAAM,OAAO,WAAW,aAAa,KAAA,IAAY,SAAS,QAAQ,KAAK,GAAG,KAAK,GAAG,EAAE,KAAK;CACzF,IAAI,MAAM,KAAK,OAAO;CACtB,OAAO;AACT;AAEA,SAAS,aAAa,EACpB,GACA,UACA,UACA,OACA,SACA,UAAU,OACV,MACA,SAWC;CACD,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,QAAQ,EAAE,SAAS;EAAE,GAAG;EAAI,GAAG;CAAG;CACxC,MAAM,SAAS,WAAW,EAAE,MAAM,IAAI;CACtC,MAAM,OAAO,MAAM,MAAM,MAAM,EAAE,UAAU,MAAM;CAGjD,MAAM,MAAM,WAAW,cAAc,OAAO,SAAS,IAAI,IAAI;CAC7D,MAAM,MAAM,KAAK,QAAQ,MAAM;CAC/B,MAAM,WACJ,QAAQ,KAAK,UAAU,SAAS,KAAK,QAAQ,MAAM,OAAO,IAAI,KAAK,IAAI,YAAY,EAAE,MAAM,IAAI,KAAK;CAEtG,MAAM,YAAY,GAAW,MAAc;EACzC,MAAM,OAAmB;GAAE,GAAG;GAAG,OAAO;IAAE,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;IAAG,GAAG,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;GAAE;EAAE;EACvI,SAAS,QAAQ,KAAK,UAAU,cAAc,OAAO,SAAS,MAAM,KAAK,OAAO,IAAI,IAAI,IAAI;CAC9F;CACA,MAAM,eAAe,MAA0C;EAC7D,MAAM,IAAI,EAAE,cAAc,sBAAsB;EAChD,IAAI,CAAC,EAAE,SAAS,CAAC,EAAE,QAAQ;EAC3B,UAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAS,MAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAU,GAAG;CACzF;CACA,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAAsC,UAAA;IAA0B,CAAA,GAC/E,OACC,qBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA;MACG,KAAK;MAAE;MAAI,KAAK;KACb;IACJ,CAAA,IAAA,IACD;;GACJ,UACC,qBAAA,UAAA,EAAA,UAAA,CACE,oBAAC,QAAD;IAAQ,MAAK;IAAQ,UAAA;GAA8G,CAAA,GAClI,OAAO,MACN,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA4B,UAAA;IAAmC,CAAA,GAC/E,oBAAC,QAAD;KAAM,WAAU;KAA2B,UAAA,MAAM;IAAU,CAAA,CACxD;GACH,CAAA,IAAA,IACJ,EAAA,CAAA,IAEF,qBAAA,UAAA,EAAA,UAAA,CACE,qBAAC,SAAD;IAAO,WAAU;IAAjB,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA4B,UAAA;IAAc,CAAA,GAC1D,oBAAC,UAAD;KACE,MAAM;KACN,OAAO,EAAE,OAAO;KACN;KACV,WAAW,MAAM;MACf,MAAM,MAAM,EAAE,OAAO;MACrB,MAAM,OAAO,EAAE,GAAG,EAAE;MACpB,IAAI,KAAK,KAAK,MAAM;WACf,OAAO,KAAK;MACjB,SAAS,IAAI;KACf;KACA,aAAY;KACZ,WAAU;KACV,cAAY,GAAG,MAAM;IACtB,CAAA,CACI;GACN,CAAA,GAAA,UACC,oBAAC,QAAD;IAAQ,MAAK;IAAQ,UAAA;GAAoG,CAAA,IAE3H,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA;KACE,qBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,qBAAC,QAAD;OAAM,WAAU;OAAhB,UAAA,CACE,oBAAC,UAAD;QAAU,WAAU;QAAW,QAAQ;QAAK,eAAA;OAAa,CAAA,GAAC,yBAEtD;MACN,CAAA,GAAA,qBAAC,QAAD;OAAM,WAAU;OAAhB,UAAA;QACE,oBAAC,mBAAD;SAAmB,WAAU;SAAS,QAAQ;SAAK,eAAA;QAAa,CAAA;QAAC;QAC1D,MAAM;QAAE;QAAI,MAAM;QAAE;OACvB;MACH,CAAA,CAAA;;KAEL,oBAAC,QAAD;MACE,MAAK;MACL,cAAY,GAAG,MAAM;MACrB,UAAU,YAAY,CAAC;MACvB,kBAAiB;MACjB,OAAO;MACP,gBAAgB,MAAM,QAAQ,MAAM,eAAe,SAAS,SAAS,GAAG,GAAkB,IAAI,CAAC;MAC/F,SAAS,CACP,GAAG,MAAM,KAAK,OAAO;OAAE,OAAO,EAAE;OAAO,OAAO,EAAE;OAAO,MAAM,EAAE;MAAY,EAAE,GAC7E,GAAI,WAAW,cAAc,CAAC;OAAE,OAAO;OAAa,OAAO;OAAU,MAAM;OAAiB,UAAU;MAAK,CAAC,IAAI,CAAC,CACnH;KACD,CAAA;KACA,CAAC,QAAQ,CAAC,WAAW,oBAAC,QAAD;MAAM,WAAU;MAA6B,UAAA;KAAsE,CAAA,IAAI;KAC7I,oBAAC,OAAD;MACE,WAAW,GAAG,MAAM,gGAAgG,YAAY,OAAO,OAAO;MAC9I,OAAO,MAAM,EAAE,aAAa,IAAI,MAAM,IAAI,KAAA;MAE5C,UAAA,qBAAC,OAAD;OACE,MAAK;OACL,cAAW;OACX,kBAAgB,GAAG,MAAM,EAAE,YAAY,MAAM,EAAE;OAC/C,iBAAe,MAAM;OACrB,iBAAe;OACf,iBAAe;OACf,iBAAe,YAAY,KAAA;OAC3B,UAAU;OACV,gBAAgB,MAAM,CAAC,YAAY,YAAY,CAAC;OAChD,YAAY,MAAM;QAChB,MAAM,IAAI,EAAE,WAAW,KAAK;QAE5B,MAAM,OAAO;SADiC,WAAW,CAAC,CAAC,GAAG,CAAC;SAAG,YAAY,CAAC,GAAG,CAAC;SAAG,SAAS,CAAC,GAAG,CAAC,CAAC;SAAG,WAAW,CAAC,GAAG,CAAC;QAC3G,EAAE,EAAE;QACjB,IAAI,CAAC,QAAQ,UAAU;QACvB,EAAE,eAAe;QACjB,SAAS,MAAM,IAAI,KAAK,IAAI,MAAM,IAAI,KAAK,EAAE;OAC/C;OACA,kBAAgB;OAEhB,WACE,MACI,GAAG,6CAA6C,IAAI,SAAS,WAAW,WAAW,QAAQ,IAC3F;OAEN,OAAO,EAAE,aAAa,SAAS;OAzBjC,UAAA,CA2BE,oBAAC,OAAD;QAAK,KAAK,IAAI,EAAE,GAAG;QAAG,KAAI;QAAG,WAAW;QAAO,WAAU;QAAmG,OAAO,EAAE,gBAAgB,GAAG,MAAM,EAAE,IAAI,MAAM,EAAE,GAAG;OAAI,CAAA,GACnN,oBAAC,QAAD;QACE,eAAA;QACA,WAAU;QACV,OAAO;SAAE,MAAM,GAAG,MAAM,EAAE;SAAI,KAAK,GAAG,MAAM,EAAE;QAAG;OAClD,CAAA,CACE;;KACA,CAAA;KACL,oBAAC,QAAD;MAAM,WAAU;MAA6B,UAAA;KAAgE,CAAA;IAC1G;GAEL,CAAA,CAAA,EAAA,CAAA;GAEH,WAAW,UACV,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA4B,UAAA;IAAe,CAAA,GAC3D,oBAAC,QAAD;KAAM,WAAU;KAAkD,UAAA,OAAO,QAAQ,EAAE,QAAQ,gBAAgB,EAAE,GAAG;IAAQ,CAAA,CACrH;GAGL,CAAA,IAAA,qBAAC,SAAD;IAAO,WAAU;IAAjB,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA4B,UAAA;IAAe,CAAA,GAC3D,oBAAC,OAAD;KACE,MAAK;KACL,OAAO,EAAE,QAAQ,OAAO,QAAQ,gBAAgB,EAAE,GAAG;KAC3C;KACV,YAAY;KACZ,cAAa;KACb,WAAW,MAAM;MACf,MAAM,OAAO,EAAE,GAAG,EAAE;MACpB,IAAI,EAAE,OAAO,OAAO,KAAK,OAAO,EAAE,OAAO;WACpC,OAAO,KAAK;MACjB,SAAS,IAAI;KACf;KACA,WAAU;KACV,cAAY,GAAG,MAAM;IACtB,CAAA,CACI;;EAEN;;AAET;;AAGA,SAAS,WAAW,OAAsD;CACxE,IAAI,CAAC,SAAS,OAAO,UAAU,UAAU,OAAO,KAAA;CAChD,MAAM,EAAE,OAAO,WAAW;CAC1B,OAAO,OAAO,UAAU,YAAY,OAAO,WAAW,YAAY,QAAQ,KAAK,SAAS,IAAI;EAAE,GAAG;EAAO,GAAG;CAAO,IAAI,KAAA;AACxH;;;;;;AAQA,SAAS,aAAa,EACpB,IACA,OACA,KACA,UACA,QACA,SACA,MACA,cAUC;CACD,MAAM,MAAM,MAAM,OAA0B,IAAI;CAChD,MAAM,CAAC,MAAM,WAAW,MAAM,SAAS,KAAK;CAE5C,MAAM,UAAU,MAAM,OAAO,KAAK;CAClC,MAAM,gBAAgB;EACpB,IAAI,QAAQ,WAAW,CAAC,YAAY,IAAI,SAAS,MAAM,EAAE,eAAe,KAAK,CAAC;EAC9E,QAAQ,UAAU;CACpB,GAAG,CAAC,UAAU,CAAC;CACf,MAAM,QAAQ,CAAC;CACf,MAAM,QAAQ,YAAY,QAAQ,CAAC;CACnC,MAAM,YAAY,SAAS,CAAC,SAAS,CAAC,CAAC;CAGvC,MAAM,SAAS,MAAM,WAAW,SAAS;CACzC,OACE,qBAAC,OAAD;EACE,WAAW,GACT,+FACA,6EACA,OAAO,0CAA0C,0BACjD,QAAQ,eAAe,0CACzB;EANF,UAAA,CAQA,oBAAC,SAAD;GAAS,SAAS;GAChB,UAAA,qBAAC,UAAD;IACE,KAAK;IACD;IACJ,MAAK;IACL,aAAU;IACV,UAAU;IACV,SAAS;IACT,cAAY,QAAQ,aAAa,UAAU,WAAW;IACtD,YAAY,aAAa,MAAM;KAAE,EAAE,eAAe;KAAG,QAAQ,IAAI;IAAG,IAAI,KAAA;IACxE,aAAa,kBAAkB,QAAQ,KAAK,IAAI,KAAA;IAChD,QAAQ,aAAa,MAAM;KAAE,EAAE,eAAe;KAAG,QAAQ,KAAK;KAAG,QAAQ,MAAM,KAAK,EAAE,aAAa,KAAK,CAAC;IAAG,IAAI,KAAA;IAChH,WAAU;IAXZ,UAAA;KAaE,oBAAC,QAAD;MACE,eAAA;MACA,WAAW,GACT,iFACA,QAAQ,2CAA2C,GAAG,uBAAuB,OAAO,CACtF;MAEC,UAAA,QAAQ,oBAAC,UAAD;OAAU,WAAU;OAAyB,QAAQ;MAAM,CAAA,IAAI,oBAAC,OAAD;OAAK,KAAK;OAAK,KAAI;OAAG,WAAU;MAA4B,CAAA;KAChI,CAAA;KACN,oBAAC,QAAD;MAAM,eAAA;MAAY,WAAW,GAAG,2BAA2B,QAAQ,kBAAkB,aAAa;MAC/F,UAAA,QAAS,OAAO,eAAe,aAAc;KAC1C,CAAA;KACL,QAAQ,OAAO,oBAAC,aAAD;MAAa,eAAA;MAAY,WAAU;MAAkC,QAAQ;KAAM,CAAA;IAC7F;;EACD,CAAA,GACN,SAAS,oBAAC,QAAD;GAAM,aAAU;GAAsB,WAAU;GAAwD,UAAA;EAAa,CAAA,IAAI,IAChI;;AAET;AAEA,SAAgB,aAAa,EAAE,OAAO,OAAO,UAAU,OAAO,UAAU,IAAI,QAAsB;CAChG,MAAM,EAAE,GAAG,UAAU,QAAQ,SAAS;CACtC,MAAM,MAAM,UAAU;CACtB,MAAM,UAAU,CAAC,CAAC,EAAE,iBAAiB,IAAI;CACzC,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE,eAAe,IAAI;CACnD,MAAM,eAAe,OAAO,UAAU,YAAY,MAAM,eAAe;CACvE,MAAM,IAAI,UAAU,KAAK;CACzB,MAAM,QAAQ,SAAS;EAAE,IAAI,GAAG;EAAI,KAAK,GAAG,OAAO;CAAG,CAAC;CAEvD,MAAM,SAAS,MAAM,UAAU,kBAAkB;CACjD,MAAM,QAA6B,MAAM,UAAU,CAAC,KAAK,IAAI,CAAC,SAAS,KAAK;CAO5E,MAAM,CAAC,QAAQ,aAAa,MAAM,SAA4D;CAC9F,MAAM,UAAU,UAAU,KAAK,OAAO,QAAQ,EAAE,MAAM;EAAE,GAAG,OAAO;EAAG,GAAG,OAAO;CAAE,IAAI,KAAA;CACrF,MAAM,eAAe,QAAiC;EACpD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,YAAY,CAAC,IAAI,gBAAgB,CAAC,IAAI,eAAe;EAC5E,MAAM,OAAO;GAAE,KAAK,EAAE;GAAK,GAAG,IAAI;GAAc,GAAG,IAAI;EAAc;EACrE,WAAW,SAAU,QAAQ,KAAK,QAAQ,KAAK,OAAO,KAAK,MAAM,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI,OAAO,IAAK;CAC7G;CAGA,MAAM,SAAS,WAAW,KAAK;CAC/B,MAAM,OAAO,OAAO,SAAS,MAAM,SAAS;EAAE,GAAG,MAAM;EAAO,GAAG,MAAM;CAAO,IAAI,UAAU;CAI5F,MAAM,YAAY,MAAyB;EACzC,IAAI,CAAC,GAAG,OAAO,MAAM,UAAU,KAAK,IAAI;EACxC,IAAI,SAAS,OAAO,MAAM,EAAE,GAAG;EAC/B,IAAI,gBAAgB,CAAC,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,EAAE,IAAI,OAAO,MAAM,EAAE,GAAG;EACzF,MAAM,CAAC;CACT;CACA,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,KAAK;CAClD,MAAM,KAAK,UAAU,QAAQ,UAAU,MAAM,EAAE,MAAM,SAAS,UAAU,EAAE,EAAE,CAAC,CAAC;CAC9E,MAAM,UAAU,EAAE,eAAe,CAAC,iBAAiB,UAAU,IAAI,IAAI,KAAA;CACrE,MAAM,SAAS,EAAE,gBAAgB,SAAA,CAAU;CAE3C,IAAI,YAAY,OAAO,KAAK,GAAG;EAE7B,MAAM,QAAQ,EAAE,eACZ,CACE,GAAI,IAAI,CAAC;GAAE,KAAK,EAAE;GAAK;GAAO,SAAS;EAAK,CAAC,IAAI,CAAC,GAClD,GAAG,MAAM,QAAQ,MAAM,EAAE,QAAQ,GAAG,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,OAAO,cAAc;GAAE;GAAK,OAAO;EAAO,EAAE,CACrI,IACA,KAAA;EACJ,MAAM,YAAY,WAAoB;GACpC,MAAM,IAAI,UAAU,MAAM;GAC1B,IAAI,GAAG,SAAS,UAAU;IAAE,IAAI,EAAE,MAAM;IAAI,KAAK,EAAE;IAAK,MAAM,EAAE;IAAM,KAAK,EAAE,QAAQ,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAA;IAAY,MAAM;GAAM,CAAC,CAAC;GAC3J,UAAU,KAAK;EACjB;EACA,OACE,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,oBAAC,cAAD;KACM;KACJ,OAAO,MAAM;KACb,KAAK,IAAI,IAAI,EAAE,GAAG,IAAI,KAAA;KACZ;KACV,QAAQ;KACR,SAAS,GAAG;KACZ,MAAM,GAAG,YAAY;KACrB,YAAY;IACb,CAAA;IACA,GAAG,QAAQ,oBAAC,QAAD,EAAA,UAAS,GAAG,MAAc,CAAA,IAAI;IACzC,CAAC,YAAY,CAAC,UAAU,oBAAC,QAAD;KAAQ,MAAK;KAAS,UAAA;IAAmB,CAAA,IAAI;IACtE,oBAAC,aAAD;KACE,MAAM;KACN,cAAc;KACd,QAAQ,CAAC,KAAK;KACd,OAAO,IAAI,iBAAiB;KAC5B,SAAS,MAAM,EAAE,MAAM,SAAS,UAAU,EAAE,EAAE,CAAC;KAC/C,UAAU,KAAK,CAAC,iBAAiB;MAAE,SAAS,IAAI;MAAG,UAAU,KAAK;KAAG,IAAI,KAAA;KAClE;KACP,YAAY,WAAW,KAAA,IAAY;IACpC,CAAA;GACE;;CAET;CAEA,IAAI,CAAC,GACH,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,UAAD;IACM;IACJ,OAAM;IACN,MAAK;IACG;IACR,MAAM,oBAAC,WAAD,EAAW,QAAQ,IAAM,CAAA;IAC/B,SAAS,GAAG;IACZ,WAAW;IACX,OAAO,WAAW,KAAA,KAAa,QAAQ,SAAS;KAAE;KAAK,MAAM,gBAAgB,GAAG,KAAK,KAAA;IAAU,CAAC;IAChG,QAAQ,GAAG;IACX,UAAU;IACV,UAAU,GAAG;GACd,CAAA;GACA,GAAG,QAAQ,oBAAC,QAAD,EAAA,UAAS,GAAG,MAAc,CAAA,IAAI;GAC1C,oBAAC,aAAD;IAAa,MAAM;IAAQ,cAAc;IAAW,QAAQ;IAAO,SAAS,MAAM,EAAE,MAAM,SAAS,UAAU,EAAE,EAAE,CAAC;GAAI,CAAA;EACnH;;CAGT,MAAM,MAAM,SAAS,IAAI;CAEzB,MAAM,SAAS,OAAO,SAAS,SAAS,CAAC,CAAC,MAAM,WAAW,mBAAmB,KAAK,EAAE,GAAG;CACxF,MAAM,MAAM,IAAI,SAAS,QAAQ,CAAC,SAAS,OAAO,KAAA;CAClD,MAAM,MAAM,UAAU,OAAO,MAAM,EAAE;CACrC,MAAM,OAAO,OAAO,QAAQ,EAAE,QAAQ,gBAAgB,EAAE,GAAG;CAC3D,MAAM,WAAW,MAAqB;EACpC,MAAM,OAAO,UAAU,CAAC;EACxB,IAAI,CAAC,KAAK,OAAO,EAAE,KAAK,KAAK,MAAM,EAAE;EACrC,IAAI,EAAE,OAAO,KAAK,QAAQ,EAAE;EAC5B,SAAS,IAAI;CACf;CACA,MAAM,oBAAoB,OAAO,iBAAiB,WAAW,IAAI,GAAG,CAAC;CACrE,OACE,qBAAC,SAAD;EAAS,MAAM;EAAS,cAAc;EAAtC,UAAA;GACE,qBAAC,eAAD;IACE,WAAW,GAAG,yBAAyB,IAAI,YAAY,cAAc,UAAU;IAC/E,UAAU,MAA4B;KACpC,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,KAAK;KAC9C,IAAI,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU;MACvC,EAAE,eAAe;MACjB,GAAG,IAAI,KAAK;KACd;IACF;IARF,UAAA;KAUE,qBAAC,OAAD;MACE,aAAU;MACV,oBAAkB,OAAO,IAAI,KAAK;MAClC,WAAW,GAAG,4EAA4E,OAAO;MACjG,OAAO,EAAE,aAAa,IAAI,MAAM;MAJlC,UAAA;OAME,oBAAC,UAAD;QACM;QACJ,MAAK;QACL,UAAU;QACV,eAAgB,UAAU,QAAQ,IAAI,YAAY;QAClD,cAAY,UAAU,WAAW,MAAM,UAAU,GAAG,MAAM,MAAM;QAChE,WAAU;QAEV,UAAA,oBAAC,OAAD;SACE,KAAK,IAAI,EAAE,GAAG;SACd,KAAK,OAAO;SACZ,KAAK;SACL,SAAS,MAAM,YAAY,EAAE,aAAa;SAC1C,aAAW,IAAI;SACf,oBAAkB,IAAI,SAAS,KAAA;SAC/B,YAAU,MAAM,GAAG,IAAI,EAAE,GAAG,IAAI,MAAM,KAAA;SACtC,WAAW,UAAU,IAAI;SACzB,OACE,IAAI,QACA;UAAE,aAAa,IAAI;UAAO,GAAI,MAAM;WAAE,UAAU,aAAa,IAAI,EAAE;WAAM,WAAW,aAAa,IAAI,EAAE;UAAK,IAAI,CAAC;SAAG,IACpH,KAAA;QAEP,CAAA;OACK,CAAA;OACP,WAAW,OACV,qBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACG,UACC,qBAAC,UAAD;SAAQ,MAAK;SAAS,SAAS;SAAS,WAAU;SAAlD,UAAA,CACE,oBAAC,aAAD;UAAa,WAAU;UAAW,QAAQ;UAAK,eAAA;SAAa,CAAA,GAAC,SAEvD;QACN,CAAA,IAAA,MACJ,oBAAC,SAAD;SAAS,SAAQ;SACf,UAAA,oBAAC,UAAD;UAAQ,MAAK;UAAS,cAAW;UAAe,eAAe,SAAS,IAAI;UAAG,WAAU;UACvF,UAAA,oBAAC,OAAD;WAAO,WAAU;WAAW,QAAQ;WAAK,eAAA;UAAa,CAAA;SAChD,CAAA;QACD,CAAA,CACN;;OAEN,GAAG,YAAY,OACd,oBAAC,OAAD;QAAK,WAAU;QACb,UAAA,oBAAC,UAAD;SAAU,OAAO,GAAG;SAAU,MAAK;SAAM,MAAK;SAAK,OAAM;QAAmB,CAAA;OACzE,CAAA,IACH;MACD;;KACL,qBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,qBAAC,QAAD;OAAM,aAAU;OAAoB,WAAU;OAA9C,UAAA;QACG;QACA,OACC,qBAAA,UAAA,EAAA,UAAA,CACG,OACD,qBAAC,QAAD;SAAM,WAAU;SAAhB,UAAA;UACG,KAAK;UAAE;UAAI,KAAK;SACb;QACN,CAAA,CAAA,EAAA,CAAA,IACA;QACH;QACA,MACC,oBAAC,QAAD;SAAM,WAAU;SAAgB,UAAA;QAAkB,CAAA,IAElD,qBAAC,QAAD;SAAM,WAAU;SAAhB,UAAA,CACE,oBAAC,mBAAD;UAAmB,WAAU;UAAS,QAAQ;UAAK,eAAA;SAAa,CAAA,GAAC,aAE7D;;OAEJ;MACN,CAAA,GAAA,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,aAAD;OACE,cAAW;OACX,WAAU;OAEV,UAAA,oBAAC,UAAD;QAAU,WAAU;QAAS,QAAQ;QAAK,eAAA;OAAa,CAAA;MAC5C,CAAA,GACb,qBAAC,aAAD;OAAa,OAAM;OAAM,WAAU;OAAnC,UAAA;QACE,oBAAC,UAAD;SAAU,MAAM,oBAAC,mBAAD,EAAmB,QAAQ,IAAM,CAAA;SAAG,SAAS;SAAa,UAAA;QAEhE,CAAA;QAEV,oBAAC,UAAD;SAAU,MAAM,oBAAC,aAAD,EAAa,QAAQ,IAAM,CAAA;SAAG,UAAU,CAAC;SAAS,SAAS;SAAS,UAAA;QAE1E,CAAA;QACV,oBAAC,UAAD;SAAU,MAAM,oBAAC,kBAAD,EAAkB,QAAQ,IAAM,CAAA;SAAG,eAAe,OAAO,KAAK,IAAI,EAAE,GAAG,GAAG,UAAU,UAAU;SAAG,UAAA;QAEvG,CAAA;QACV,oBAAC,eAAD,CAAgB,CAAA;QAChB,oBAAC,UAAD;SAAU,QAAA;SAAO,MAAM,oBAAC,WAAD,EAAW,QAAQ,IAAM,CAAA;SAAG,UAAU;SAAU,eAAe,CAAC,YAAY,SAAS,IAAI;SAAG,UAAA;QAEzG,CAAA;OACC;MACT,CAAA,CAAA,EAAA,CAAA,CACH;;KACJ,GAAG,QAAQ,oBAAC,QAAD,EAAA,UAAS,GAAG,MAAc,CAAA,IAAI;IAC7B;;GACf,oBAAC,gBAAD;IAAgB,WAAU;IAAY,OAAM;IAAQ,MAAK;IACvD,UAAA,oBAAC,cAAD;KAAiB;KAAa;KAAoB;KAAU,OAAO,MAAM;KAAgB;KAAkB;KAAe;KAAa;IAAQ,CAAA;GACjI,CAAA;GAChB,oBAAC,aAAD;IAAa,MAAM;IAAQ,cAAc;IAAW,QAAQ;IAAO,SAAS,MAAM,EAAE,MAAM,QAAQ,EAAE,EAAE;GAAI,CAAA;EACnG;;AAEb;AAKA,SAAS,MAAM,EACb,MACA,OACA,UACA,MACA,UACA,UAQC;CACD,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,SAAS,KAAK,OAAO,KAAK,GAAG;CACnC,OACE,qBAAC,OAAD;EACE,KAAK,KAAK,SAAS,KAAK,GAAG;EAC3B,MAAK;EACL,OAAO,KAAK,MAAM,KAAK,GAAG;EAE1B,WAAW,GACT,0IACA,SACA,KAAK,WAAW,KAAK,OAAO,2DAC9B;EATF,UAAA;GAWE,oBAAC,OAAD;IACE,GAAK,WAAW,CAAC,IAAI;IACrB,MAAM,KAAA;IACN,UAAU;IACV,cAAY,WAAW,QAAQ,GAAG,MAAM;IACxC,eAAe;IACf,YAAY,MAAM;KAChB,IAAI,CAAC,aAAa,EAAE,QAAQ,YAAY,EAAE,QAAQ,cAAc;MAC9D,EAAE,eAAe;MACjB,SAAS;MACT;KACF;KACA,IAAI,EAAE,QAAQ,SAAS;MACrB,EAAE,eAAe;MACjB,OAAO;MACP;KACF;KACA,IAAI,CAAC,UAAU,OAAO,UAAU,CAAC;IACnC;IACA,WAAU;IAGV,UAAA,oBAAC,OAAD;KAAK,KAAK,IAAI,KAAK,EAAE,GAAG;KAAG,KAAK,KAAK,EAAE,OAAO;KAAI,aAAU;KAAoB,WAAU;KAA2D,WAAW;IAAQ,CAAA;GACrK,CAAA;GACJ,CAAC,KAAK,EAAE,MAAM,oBAAC,QAAD;IAAM,MAAK;IAAM,WAAU;IAAwF,cAAW;GAAe,CAAA,IAAI;GAC/J,WAAW,OACV,oBAAC,UAAD;IACE,MAAK;IAEL,qBAAmB;KACjB,MAAM,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,QAAQ,gBAAgB,KAAK,EAAE,GAAG;KACpE,OAAO,OAAO,UAAU,SAAS;IACnC,EAAA,CAAG;IACH,gBAAgB,MAAM,EAAE,gBAAgB;IACxC,SAAS;IACT,WAAU;IAEV,UAAA,oBAAC,OAAD;KAAO,WAAU;KAAW,QAAQ;KAAK,eAAA;IAAa,CAAA;GAChD,CAAA;EAEP;;AAET;;AAGA,SAAgB,eAAe,EAAE,OAAO,UAAU,UAAU,OAAO,IAAI,QAAsB;CAC3F,MAAM,EAAE,GAAG,QAAQ,SAAS;CAC5B,MAAM,MAAM,UAAU;CACtB,MAAM,MAAM,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;CAE5C,MAAM,uBAAO,IAAI,IAAoB;CACrC,MAAM,QAAiB,IAAI,KAAK,MAAM;EACpC,MAAM,IAAI,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG;EACpC,MAAM,OAAO,EAAE,MAAM,EAAE;EACvB,MAAM,IAAI,KAAK,IAAI,IAAI,KAAK;EAC5B,KAAK,IAAI,MAAM,IAAI,CAAC;EACpB,OAAO;GAAE,KAAK,IAAI,GAAG,KAAK,GAAG,MAAM;GAAM;GAAG,KAAK;EAAE;CACrD,CAAC;CAED,MAAM,YAAY,IAAI,SAAS,KAAK,IAAI,OAAO,MAAM,OAAO,MAAM,QAAQ;CAC1E,MAAM,OAAO,MAAmB,aAAa,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM;CAC1E,MAAM,SAAS,SAAoB,SAAS,IAAI;CAChD,MAAM,OAAO,WAA4B,MAAM,CAAC,GAAG,KAAK,GAAG,OAAO,KAAK,MAAM,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;CAChG,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,KAAK,UAAU,WAAW,SAAS,GAAG;CAC5C,MAAM,OAAO,MAAM,KAAK,OAAO,GAAG,GAAG;CACrC,MAAM,OAAO,eACX,OACC,MAAM,OAAO;EACZ,MAAM,OAAO,CAAC,GAAG,GAAG;EACpB,MAAM,CAAC,SAAS,KAAK,OAAO,MAAM,CAAC;EACnC,KAAK,OAAO,IAAI,GAAG,KAAK;EACxB,MAAM,IAAI;CACZ,GACA;EAAE,MAAM;EAAQ,UAAU;CAAS,CACrC;CACA,MAAM,MAAM,MAAM,YAAY;CAC9B,MAAM,SAAS,CAAC,aAAa,OAAO,QAAQ,MAAM,SAAS,SAAS,EAAE,eAAe,GAAG;CACxF,MAAM,QAAQ,GAAW,OAAc,GAAG,EAAE,SAAS,gBAAgB,GAAG,EAAE,GAAG,KAAK,SAAS,IAAI;CAC/F,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,qBAAC,OAAD;IAAS;IAAI,MAAK;IAAO,cAAY,MAAM;IAAO,WAAU;IAA5D,UAAA,CACG,MAAM,KAAK,IAAI,MACd,oBAAC,OAAD;KAEE,MAAM;KACN,OAAO,KAAK,GAAG,EAAE;KACP;KACJ;KAEN,cAAe,EAAE,aAAa,CAAC,WAAW,EAAE,UAAU;MAAE,OAAO,IAAI;MAAO,MAAM,CAAC,GAAG,MAAM,CAAC;MAAG,OAAO,KAAK,GAAG,EAAE;KAAE,CAAC,IAAI,OAAO,KAAK,IAAI,GAAG,EAAE,GAAG,GAAG,UAAU,UAAU;KACrK,gBAAgB,MAAM,IAAI,QAAQ,GAAG,MAAM,MAAM,CAAC,CAAC;IACpD,GARM,GAAG,GAQT,CACF,GACA,SAGC,oBAAC,OAAD;KAAK,MAAK;KAAW,WAAU;KAC7B,UAAA,qBAAC,UAAD;MACE,MAAK;MACL,eAAgB,EAAE,cAAc,UAAU,IAAI,IAAI,GAAG,OAAO,SAAS,eAAe,GAAG,GAAG,OAAO,CAAC,EAAE,MAAM;MAC1G,UAAU,MAAM;OACd,MAAM,QAAQ,MAAM,KAAK,EAAE,cAAc,KAAK;OAC9C,IAAI,MAAM,UAAU,GAAG,KAAK;QAC1B,EAAE,eAAe;QACjB,GAAG,IAAI,KAAK;OACd;MACF;MACA,aAAa,MAAM,GAAG,OAAO,EAAE,eAAe;MAC9C,SAAS,MAAM;OACb,IAAI,CAAC,GAAG,KAAK;OACb,EAAE,eAAe;OACjB,GAAG,IAAI,MAAM,KAAK,EAAE,aAAa,KAAK,CAAC;MACzC;MACA,WAAU;MAhBZ,UAAA,CAkBE,oBAAC,UAAD;OAAU,WAAU;OAAS,QAAQ;OAAK,eAAA;MAAa,CAAA,GAAC,YAElD;;IACL,CAAA,IACH,IACD;;GACJ,KAAK;GACL,GAAG,OAAO,CAAC,EAAE,cACZ,oBAAC,SAAD;IACE,IAAI,GAAG,GAAG;IACV,MAAK;IACL,QAAA;IACA,UAAU;IACV,eAAA;IACA,QAAO;IACP,UAAA;IACA,WAAW,MAAM;KACf,GAAG,MAAM,MAAM,KAAK,EAAE,OAAO,SAAS,CAAC,CAAC,CAAC;KACzC,EAAE,OAAO,QAAQ;IACnB;GACD,CAAA,IACC;GACH,GAAG,YAAY,OAAO,oBAAC,UAAD;IAAU,OAAO,GAAG;IAAU,MAAK;IAAM,MAAK;IAAK,OAAM;GAAmB,CAAA,IAAI;GACtG,GAAG,QAAQ,oBAAC,QAAD,EAAA,UAAS,GAAG,MAAc,CAAA,IAAI;GACzC,CAAC,YAAY,CAAC,EAAE,eAAe,CAAC,GAAG,MAAM,oBAAC,QAAD;IAAQ,MAAK;IAAS,UAAA;GAAkB,CAAA,IAAI;GACtF,oBAAC,aAAD;IAAa,MAAM;IAAQ,cAAc;IAAW,UAAA;IAAS,QAAQ,CAAC,SAAS,KAAK;IAAG,SAAS,MAAM,EAAE,UAAU,IAAI,OAAO,OAAO,EAAE,MAAM,GAAG,KAAK,IAAI,GAAG,MAAM,MAAM,MAAM,CAAC,IAAI,CAAC;GAAI,CAAA;EACpL;;AAET;AAKA,IAAM,YAAY,MAAiC;CACjD,IAAI,OAAO,MAAM,UAAU,OAAO,IAAI,EAAE,KAAK,EAAE,IAAI;CACnD,OAAO,MAAM,CAAC,KAAK,OAAO,EAAE,QAAQ,YAAY,EAAE,MAAO,IAAkB;AAC7E;AACA,IAAM,iBAAiB,OAAiC;CAAE,KAAK,EAAE;CAAK,IAAI,EAAE;CAAI,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AAAG;AAEpH,SAAgB,YAAY,EAAE,OAAO,UAAU,UAAU,MAAoB;CAC3E,MAAM,EAAE,GAAG,UAAU,QAAQ,SAAS;CACtC,MAAM,IAAI,SAAS,KAAK;CACxB,MAAM,QAAQ,SAAS;EAAE,IAAI,GAAG;EAAI,KAAK,GAAG,OAAO;CAAG,CAAC;CACvD,MAAM,CAAC,QAAQ,aAAa,MAAM,SAAS,KAAK;CAChD,MAAM,KAAK,UAAU,KAAK,SAAS,MAAM,EAAE,MAAM,SAAS,cAAc,EAAE,EAAE,CAAC,CAAC;CAC9E,MAAM,UAAU,EAAE,eAAe,CAAC,iBAAiB,UAAU,IAAI,IAAI,KAAA;CACrE,MAAM,WAAW,oBAAC,aAAD;EAAa,MAAM;EAAQ,cAAc;EAAW,QAAQ,CAAC,MAAM;EAAG,SAAS,MAAM,EAAE,MAAM,SAAS,cAAc,EAAE,EAAE,CAAC;CAAI,CAAA;CAC9I,IAAI,CAAC,GACH,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,UAAD;IAAc;IAAI,OAAM;IAAa,MAAK;IAA4B,QAAO;IAAI,MAAM,oBAAC,cAAD,EAAc,QAAQ,IAAM,CAAA;IAAG,SAAS,GAAG;IAAK,WAAW;IAAS,QAAQ,GAAG;IAAU,UAAU;IAAU,UAAU,GAAG;GAAW,CAAA;GAC3N,GAAG,QAAQ,oBAAC,QAAD,EAAA,UAAS,GAAG,MAAc,CAAA,IAAI;GACzC;EACE;;CAET,MAAM,OAAO,OAAO,QAAQ,EAAE,QAAQ,gBAAgB,EAAE,GAAG;CAC3D,MAAM,OAAO,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,GAAA,EAAK,YAAY,KAAK;CAChF,MAAM,OAAO,CAAC,IAAI,YAAY,GAAG,OAAO,OAAO,YAAY,MAAM,IAAI,IAAI,IAAI,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,KAAK;CACzG,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,QAAD;IAAM,eAAA;IAAY,WAAU;IACzB,UAAA;GACG,CAAA;GACN,qBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,oBAAC,KAAD;KAAO;KAAI,MAAM,IAAI,EAAE,GAAG;KAAG,QAAO;KAAS,KAAI;KAAa,WAAU;KACrE,UAAA;IACA,CAAA,GACH,oBAAC,OAAD;KAAK,WAAU;KAA6B,UAAA;IAAU,CAAA,CACnD;;GACJ,UACC,oBAAC,QAAD;IAAQ,MAAK;IAAK,SAAQ;IAAQ,SAAS;IAAS,UAAA;GAE5C,CAAA,IACN;GACJ,qBAAC,MAAD,EAAA,UAAA,CACE,oBAAC,aAAD;IAAa,QAAQ,oBAAC,YAAD;KAAY,OAAM;KAAe,MAAK;IAAM,CAAA;IAC/D,UAAA,oBAAC,UAAD,EAAU,QAAQ,IAAM,CAAA;GACb,CAAA,GACb,qBAAC,aAAD;IAAa,OAAM;IAAnB,UAAA;KACE,oBAAC,UAAD;MAAU,MAAM,oBAAC,cAAD,EAAc,QAAQ,IAAM,CAAA;MAAG,eAAe,OAAO,KAAK,IAAI,EAAE,GAAG,GAAG,UAAU,UAAU;MAAG,UAAA;KAEnG,CAAA;KACV,oBAAC,eAAD,CAAgB,CAAA;KAChB,oBAAC,UAAD;MAAU,QAAA;MAAO,MAAM,oBAAC,WAAD,EAAW,QAAQ,IAAM,CAAA;MAAG,UAAU;MAAU,eAAe,CAAC,YAAY,SAAS,IAAI;MAAG,UAAA;KAEzG,CAAA;IACC;GACT,CAAA,CAAA,EAAA,CAAA;GACL;EACE;;AAET;AAGA,IAAa,iBAAiB,QAC5B,QAAQ,KAAK,GAAG,IAAI,YAAY,QAAQ,KAAK,GAAG,IAAI,UAAU,OAAO,KAAK,GAAG,IAAI,SAAS,0BAA0B,KAAK,GAAG,IAAI,QAAQ,MAAM,SAAS;AACzJ,IAAa,aAAa,QAAgB,IAAI,MAAM,gDAAgD,CAAC,GAAG;AACxG,IAAM,eAAe,QAAgB,0BAA0B,KAAK,GAAG;AAEvE,SAAgB,aAAa,EAAE,KAAK,QAAQ,SAA0D;CACpG,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,KAAK;CAClD,MAAM,gBAAgB,WAAW,KAAK,GAAG,CAAC,GAAG,CAAC;CAC9C,MAAM,KAAK,UAAU,GAAG;CACxB,MAAM,QAAQ,SAAS,IAAI,MAAM,IAAI,KAAK,0BAA0B,GAAG,kBAAkB,KAAA;CACzF,IAAI,WAAW,IACb,OAAO,oBAAC,UAAD;EAAe;EAAO,KAAK,0CAA0C,GAAG;EAAc,OAAM;EAA4B,WAAU;CAA6D,CAAA;CACxM,IAAI,WAAW,YAAY,GAAG,GAAG,OAAO,oBAAC,SAAD;EAAO,KAAK,IAAI,GAAG;EAAG,QAAQ;EAAO,UAAA;EAAS,UAAA;EAAS,WAAU;CAAmF,CAAA;CAC5L,MAAM,WAAW,CAAC,CAAC,MAAM,YAAY,GAAG;CACxC,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACG,QAAQ,oBAAC,OAAD;IAAK,KAAK;IAAO,KAAK,GAAG,MAAM;IAAU,WAAU;GAAqC,CAAA,IAAI;GACrG,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,WAAW,iBAAiB;IACxC,eAAgB,WAAW,WAAW,IAAI,IAAI,OAAO,KAAK,IAAI,GAAG,GAAG,UAAU,UAAU;IACxF,WAAU;IAET,UAAA,WAAW,oBAAC,gBAAD;KAAgB,WAAU;KAAS,QAAQ;KAAK,eAAA;IAAa,CAAA,IAAI,oBAAC,kBAAD;KAAkB,WAAU;KAAS,QAAQ;KAAK,eAAA;IAAa,CAAA;GACtI,CAAA;GACR,qBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACE,oBAAC,WAAD;KAAW,WAAU;KAAW,QAAQ;KAAK,eAAA;IAAa,CAAA,GACzD,cAAc,GAAG,CACd;;EACH;;AAET;;;;;;AAOA,SAAgB,aAAa,EAAE,OAAO,OAAO,UAAU,UAAU,IAAI,UAAwB;CAC3F,MAAM,MAAM,MAAM,KAAK,KAAK,OAAO,MAAM,QAAQ,WAAY,QAA6C;CAC1G,MAAM,SAAS,OAAO,UAAU,WAAW,QAAS,KAAK,OAAO;CAChE,MAAM,CAAC,OAAO,YAAY,MAAM,SAAS,MAAM;CAC/C,MAAM,CAAC,SAAS,cAAc,MAAM,SAAS,KAAK;CAClD,MAAM,gBAAgB,SAAS,MAAM,GAAG,CAAC,MAAM,CAAC;CAChD,MAAM,UAAU,QAAgB;EAC9B,MAAM,MAAM,IAAI,KAAK;EACrB,IAAI,QAAQ,UAAU,CAAC,WAAW,GAAG,GAAG;EACxC,IAAI,QAAQ,IAAI,OAAO,SAAS,MAAM,OAAO,EAAE;EAC/C,SAAS,MAAM;GAAE,GAAG;GAAK;EAAI,IAAI,GAAG;CACtC;CACA,MAAM,MAAM,MAAM,KAAK,MAAM,MAAM,CAAC,WAAW,KAAK;CACpD,MAAM,UAAU,GAAG,GAAG;CACtB,OACE,qBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,oBAAC,OAAD;IACM;IACJ,OAAO;IACG;IACV,gBAAc,OAAO,UAAU,OAAO,KAAA;IACtC,oBAAkB,OAAO,UAAU,UAAU,KAAA;IAC7C,cAAc;KACZ,WAAW,IAAI;KACf,SAAS;IACX;IACA,YAAY,MAAM;KAChB,IAAI,EAAE,QAAQ,YAAY,UAAU,QAAQ;MAC1C,EAAE,gBAAgB;MAClB,SAAS,MAAM;KACjB;IACF;IACA,aAAY;IACZ,SAAS,oBAAC,WAAD,EAAW,QAAQ,IAAM,CAAA;IAClC,WAAW,MAAM;KACf,SAAS,EAAE,OAAO,KAAK;KACvB,OAAO,EAAE,OAAO,KAAK;IACvB;GACD,CAAA;GACA,OAAO,UACN,oBAAC,KAAD;IAAG,IAAI;IAAS,MAAK;IAAQ,WAAU;IAAiC,UAAA;GAErE,CAAA,IACD;GAGH,SAAS,oBAAC,cAAD;IAAc,KAAK;IAAQ,QAAQ,KAAK;IAAQ,OAAO,MAAM;GAAQ,CAAA,IAAI,oBAAC,KAAD;IAAG,WAAU;IAA4B,UAAA;GAAuF,CAAA;EAChN;;AAET"}
@@ -5,9 +5,9 @@ import { fieldScale } from "../schema/scale.js";
5
5
  import { FallbackControl } from "../engine/kit-field.js";
6
6
  import { TEXT_FOCUS } from "./text.js";
7
7
  import * as React from "react";
8
- import { IconStarFilled } from "@tabler/icons-react";
9
8
  import { jsx, jsxs } from "react/jsx-runtime";
10
- //#region src/kit/controls/number.tsx
9
+ import { IconStarFilled } from "@tabler/icons-react";
10
+ //#region src/controls/number.tsx
11
11
  /**
12
12
  * NUMBER — a plain input, NO stepper (prod CPO-068), V2 HEAD 9829bf1 kit/controls/number.tsx, DESIGN §8.4.
13
13
  * ↑/↓ 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);
@@ -27,7 +27,8 @@ var NUMBER_TYPING = /^-?\d*\.?\d*$/;
27
27
  var decimals = (n) => (String(n).split(".")[1] ?? "").length;
28
28
  function NumberControl(p) {
29
29
  if (!fieldScale(p.field)) return /* @__PURE__ */ jsx(PlainNumber, { ...p });
30
- return /* @__PURE__ */ jsx(NUMBER_SCALE.control ?? FallbackControl, { ...p });
30
+ const Scale = NUMBER_SCALE.control ?? FallbackControl;
31
+ return /* @__PURE__ */ jsx(Scale, { ...p });
31
32
  }
32
33
  function PlainNumber({ field, value, onChange, readOnly, id, invalid, onBlur }) {
33
34
  const { variant } = useKitEnv();
@@ -54,7 +55,7 @@ function PlainNumber({ field, value, onChange, readOnly, id, invalid, onBlur })
54
55
  };
55
56
  return /* @__PURE__ */ jsxs("div", {
56
57
  "data-slot": "kit-number",
57
- className: cn("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", variant === "document" ? "h-9" : "h-8", invalid && "border-[var(--kit-field-invalid)] hover:border-[var(--kit-field-invalid)]", readOnly && "opacity-80"),
58
+ className: cn("flex w-full max-w-40 items-center rounded-kit-md border border-kit-line-strong bg-kit-field-bg transition-colors hover:border-kit-line-strong focus-within:border-kit-line-strong focus-within:bg-kit-field-bg", variant === "document" ? "h-9" : "h-8", invalid && "border-[var(--kit-field-invalid)]", readOnly && "opacity-80"),
58
59
  children: [/* @__PURE__ */ jsx("input", {
59
60
  id,
60
61
  inputMode: "decimal",
@@ -83,7 +84,7 @@ function PlainNumber({ field, value, onChange, readOnly, id, invalid, onBlur })
83
84
  onChange(clamp(base + d, base));
84
85
  }
85
86
  },
86
- 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")
87
+ className: cn(TEXT_FOCUS, "tabular-nums h-full min-w-0 flex-1 bg-transparent px-2.5 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3")
87
88
  }), unit ? /* @__PURE__ */ jsx(Tooltip, {
88
89
  content: readOnly ? void 0 : "Drag to adjust · Shift for ×10",
89
90
  children: /* @__PURE__ */ jsx("span", {
@@ -104,7 +105,7 @@ function PlainNumber({ field, value, onChange, readOnly, id, invalid, onBlur })
104
105
  },
105
106
  onPointerUp: () => start.current = null,
106
107
  onPointerCancel: () => start.current = null,
107
- 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"),
108
+ className: "flex h-full cursor-ew-resize select-none items-center pl-1 pr-2.5 text-kit-xs text-kit-fg-3 hover:text-kit-fg",
108
109
  children: unit
109
110
  })
110
111
  }) : null]
@@ -157,7 +158,7 @@ function RatingControl({ field, value, onChange, readOnly, id, invalid, onBlur }
157
158
  disabled: readOnly,
158
159
  onMouseEnter: () => setHover(i),
159
160
  onClick: () => onChange(pick),
160
- className: "relative flex size-7 items-center justify-center transition-transform hover:scale-110 disabled:hover:scale-100",
161
+ className: "relative flex size-7 items-center justify-center transition-transform hover:scale-110",
161
162
  children: [/* @__PURE__ */ jsx(IconStarFilled, { className: "size-[18px] text-kit-line-strong" }), /* @__PURE__ */ jsx("span", {
162
163
  className: "absolute inset-0 flex items-center justify-center overflow-hidden",
163
164
  style: { clipPath: `inset(0 ${100 - fill * 100}% 0 0)` },
@@ -180,7 +181,7 @@ function RatingControl({ field, value, onChange, readOnly, id, invalid, onBlur }
180
181
  onBlur?.();
181
182
  },
182
183
  onKeyDown: (e) => e.key === "Enter" && e.currentTarget.blur(),
183
- className: cn(TEXT_FOCUS, "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)]")
184
+ className: "tabular-nums h-7 w-12 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none hover:border-kit-line-strong focus:border-kit-line-strong focus:bg-kit-field-bg"
184
185
  }),
185
186
  /* @__PURE__ */ jsxs("span", {
186
187
  className: "text-kit-xs text-kit-fg-3",
@@ -190,6 +191,6 @@ function RatingControl({ field, value, onChange, readOnly, id, invalid, onBlur }
190
191
  });
191
192
  }
192
193
  //#endregion
193
- export { NUMBER_SCALE, NumberControl, RatingControl };
194
+ export { NUMBER_SCALE, NumberControl, PlainNumber, RatingControl, ratingScale, snapRating, toNum };
194
195
 
195
196
  //# sourceMappingURL=number.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"number.js","names":[],"sources":["../../src/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-line-strong bg-kit-field-bg transition-colors hover:border-kit-line-strong focus-within:border-kit-line-strong focus-within:bg-kit-field-bg\",\n variant === \"document\" ? \"h-9\" : \"h-8\",\n invalid && \"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, \"tabular-nums h-full min-w-0 flex-1 bg-transparent px-2.5 text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-3\")}\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=\"flex h-full cursor-ew-resize select-none items-center pl-1 pr-2.5 text-kit-xs text-kit-fg-3 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\"\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=\"tabular-nums h-7 w-12 rounded-kit-md border border-kit-line-strong bg-kit-field-bg px-2 text-kit-sm text-kit-fg outline-none hover:border-kit-line-strong focus:border-kit-line-strong focus:bg-kit-field-bg\"\n />\n <span className=\"text-kit-xs text-kit-fg-3\">out of {scale.max}</span>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { ARRAY_CONTROLS } from "../engine/array.js";
2
2
  import { CONTROLS } from "../engine/kit-field.js";
3
3
  import { ReferenceControl, ReferencesControl } from "./reference.js";
4
- //#region src/kit/controls/reference-register.ts
4
+ //#region src/controls/reference-register.ts
5
5
  /** Lane C4: the reference controls in the engine's dispatch tables (one line per type; merge with other lanes by line). */
6
6
  CONTROLS.reference = ReferenceControl;
7
7
  ARRAY_CONTROLS.references = ReferencesControl;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reference-register.js","names":[],"sources":["../../src/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"}
@@ -25,6 +25,10 @@ export interface KitReferenceOption {
25
25
  modelSlug?: string;
26
26
  /** a person's photo (an author entry's avatar), drawn as the row's round thumbnail; absent → the kind's icon */
27
27
  photo?: string | null;
28
+ /** a person (V2 RefOption.avatar): drawn as a round avatar, initials when there is no photo */
29
+ avatar?: boolean;
30
+ /** the record's cover image (V2 RefOption.cover): the row's square thumbnail when it is not a person */
31
+ cover?: string | null;
28
32
  }
29
33
  export interface KitReferenceQuery {
30
34
  /** the field's `reference.to`: entry model ids or slugs, and "page" / "form" / "collection" */
File without changes
@@ -3,7 +3,7 @@ import type { ControlProps } from "../types";
3
3
  /** The noun the picker uses (D48: "CMS item" where V2 says "entry"). */
4
4
  export declare function referenceNoun(to: string[]): string;
5
5
  export declare function RefThumb({ o, size }: {
6
- o: Pick<KitReferenceOption, "kind" | "title" | "photo"> | null;
6
+ o: Pick<KitReferenceOption, "kind" | "title" | "photo" | "avatar" | "cover"> | null;
7
7
  size?: number;
8
8
  }): import("react/jsx-runtime").JSX.Element;
9
9
  /**