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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (619) hide show
  1. package/README.md +33 -0
  2. package/dist/adapters/dock-values.d.ts +28 -0
  3. package/dist/adapters/dock-values.js +41 -0
  4. package/dist/adapters/dock-values.js.map +1 -0
  5. package/{adapters → dist/adapters}/icons.js +2 -2
  6. package/dist/adapters/icons.js.map +1 -0
  7. package/{adapters → dist/adapters}/lossy.d.ts +94 -31
  8. package/dist/adapters/lossy.js +419 -0
  9. package/dist/adapters/lossy.js.map +1 -0
  10. package/{adapters → dist/adapters}/prod-types.d.ts +91 -26
  11. package/{adapters → dist/adapters}/prod-types.js +82 -13
  12. package/dist/adapters/prod-types.js.map +1 -0
  13. package/{adapters → dist/adapters}/schema.d.ts +40 -1
  14. package/{adapters → dist/adapters}/schema.js +1038 -204
  15. package/dist/adapters/schema.js.map +1 -0
  16. package/{adapters → dist/adapters}/values.d.ts +26 -5
  17. package/{adapters → dist/adapters}/values.js +87 -17
  18. package/dist/adapters/values.js.map +1 -0
  19. package/dist/brand/logo.js +96 -0
  20. package/dist/brand/logo.js.map +1 -0
  21. package/{context.d.ts → dist/context.d.ts} +131 -2
  22. package/{context.js → dist/context.js} +44 -2
  23. package/dist/context.js.map +1 -0
  24. package/{controls → dist/controls}/button.d.ts +19 -5
  25. package/{controls → dist/controls}/button.js +125 -54
  26. package/dist/controls/button.js.map +1 -0
  27. package/{controls → dist/controls}/c1.js +1 -1
  28. package/dist/controls/c1.js.map +1 -0
  29. package/{controls → dist/controls}/c2.js +1 -1
  30. package/dist/controls/c2.js.map +1 -0
  31. package/{controls → dist/controls}/choice.d.ts +7 -2
  32. package/{controls → dist/controls}/choice.js +71 -18
  33. package/dist/controls/choice.js.map +1 -0
  34. package/{controls → dist/controls}/code-register.js +1 -1
  35. package/dist/controls/code-register.js.map +1 -0
  36. package/{controls → dist/controls}/code.js +10 -9
  37. package/dist/controls/code.js.map +1 -0
  38. package/{controls → dist/controls}/color.js +8 -8
  39. package/dist/controls/color.js.map +1 -0
  40. package/{controls → dist/controls}/component-services.d.ts +42 -0
  41. package/dist/controls/component-services.js +7 -0
  42. package/dist/controls/component-services.js.map +1 -0
  43. package/{controls → dist/controls}/date-register.js +1 -1
  44. package/dist/controls/date-register.js.map +1 -0
  45. package/{controls → dist/controls}/date-zone.js +8 -2
  46. package/dist/controls/date-zone.js.map +1 -0
  47. package/{controls → dist/controls}/date.js +32 -24
  48. package/dist/controls/date.js.map +1 -0
  49. package/dist/controls/form-picker-register.d.ts +7 -0
  50. package/{controls → dist/controls}/form-picker-register.js +2 -6
  51. package/dist/controls/form-picker-register.js.map +1 -0
  52. package/{controls → dist/controls}/form-picker.js +11 -9
  53. package/dist/controls/form-picker.js.map +1 -0
  54. package/{controls → dist/controls}/icon-register.js +1 -1
  55. package/dist/controls/icon-register.js.map +1 -0
  56. package/{controls → dist/controls}/icon.d.ts +4 -2
  57. package/{controls → dist/controls}/icon.js +32 -27
  58. package/dist/controls/icon.js.map +1 -0
  59. package/{controls → dist/controls}/index.d.ts +1 -1
  60. package/{controls → dist/controls}/index.js +4 -3
  61. package/dist/controls/index.js.map +1 -0
  62. package/{controls → dist/controls}/json-register.js +1 -1
  63. package/dist/controls/json-register.js.map +1 -0
  64. package/{controls → dist/controls}/json.js +13 -3
  65. package/dist/controls/json.js.map +1 -0
  66. package/{controls → dist/controls}/link.js +116 -200
  67. package/dist/controls/link.js.map +1 -0
  68. package/{controls → dist/controls}/location-register.js +1 -1
  69. package/dist/controls/location-register.js.map +1 -0
  70. package/{controls → dist/controls}/location.js +59 -40
  71. package/dist/controls/location.js.map +1 -0
  72. package/{controls → dist/controls}/media-register.js +1 -1
  73. package/dist/controls/media-register.js.map +1 -0
  74. package/{controls → dist/controls}/media-services.d.ts +6 -0
  75. package/dist/controls/media-services.js +0 -0
  76. package/{controls → dist/controls}/media.d.ts +21 -4
  77. package/{controls → dist/controls}/media.js +407 -130
  78. package/dist/controls/media.js.map +1 -0
  79. package/{controls → dist/controls}/number.js +10 -9
  80. package/dist/controls/number.js.map +1 -0
  81. package/{controls → dist/controls}/reference-register.js +1 -1
  82. package/dist/controls/reference-register.js.map +1 -0
  83. package/{controls → dist/controls}/reference-services.d.ts +4 -0
  84. package/dist/controls/reference-services.js +0 -0
  85. package/{controls → dist/controls}/reference.d.ts +1 -1
  86. package/{controls → dist/controls}/reference.js +93 -77
  87. package/dist/controls/reference.js.map +1 -0
  88. package/dist/controls/rich-text/article-shell.d.ts +145 -0
  89. package/dist/controls/rich-text/article-shell.js +510 -0
  90. package/dist/controls/rich-text/article-shell.js.map +1 -0
  91. package/dist/controls/rich-text/author.d.ts +25 -0
  92. package/dist/controls/rich-text/author.js +104 -0
  93. package/dist/controls/rich-text/author.js.map +1 -0
  94. package/dist/controls/rich-text/blocks.d.ts +60 -0
  95. package/{controls → dist/controls}/rich-text/blocks.js +164 -389
  96. package/dist/controls/rich-text/blocks.js.map +1 -0
  97. package/dist/controls/rich-text/button.d.ts +23 -0
  98. package/dist/controls/rich-text/button.js +85 -0
  99. package/dist/controls/rich-text/button.js.map +1 -0
  100. package/{controls → dist/controls}/rich-text/catalog.d.ts +7 -4
  101. package/{controls → dist/controls}/rich-text/catalog.js +94 -68
  102. package/dist/controls/rich-text/catalog.js.map +1 -0
  103. package/dist/controls/rich-text/checklist.d.ts +24 -0
  104. package/dist/controls/rich-text/checklist.js +115 -0
  105. package/dist/controls/rich-text/checklist.js.map +1 -0
  106. package/{controls → dist/controls}/rich-text/codec.d.ts +9 -1
  107. package/{controls → dist/controls}/rich-text/codec.js +7 -2
  108. package/dist/controls/rich-text/codec.js.map +1 -0
  109. package/dist/controls/rich-text/columns.d.ts +41 -0
  110. package/dist/controls/rich-text/columns.js +181 -0
  111. package/dist/controls/rich-text/columns.js.map +1 -0
  112. package/{controls → dist/controls}/rich-text/component-card.d.ts +1 -1
  113. package/{controls → dist/controls}/rich-text/component-card.js +417 -99
  114. package/dist/controls/rich-text/component-card.js.map +1 -0
  115. package/dist/controls/rich-text/component-panel.d.ts +47 -0
  116. package/dist/controls/rich-text/component-panel.js +141 -0
  117. package/dist/controls/rich-text/component-panel.js.map +1 -0
  118. package/{controls → dist/controls}/rich-text/control.d.ts +1 -2
  119. package/{controls → dist/controls}/rich-text/control.js +84 -42
  120. package/dist/controls/rich-text/control.js.map +1 -0
  121. package/{controls → dist/controls}/rich-text/dom.d.ts +53 -9
  122. package/{controls → dist/controls}/rich-text/dom.js +388 -50
  123. package/dist/controls/rich-text/dom.js.map +1 -0
  124. package/{controls → dist/controls}/rich-text/editor.d.ts +7 -0
  125. package/{controls → dist/controls}/rich-text/editor.js +226 -44
  126. package/dist/controls/rich-text/editor.js.map +1 -0
  127. package/dist/controls/rich-text/embed.d.ts +28 -0
  128. package/dist/controls/rich-text/embed.js +210 -0
  129. package/dist/controls/rich-text/embed.js.map +1 -0
  130. package/{controls → dist/controls}/rich-text/floating.d.ts +6 -1
  131. package/{controls → dist/controls}/rich-text/floating.js +35 -18
  132. package/dist/controls/rich-text/floating.js.map +1 -0
  133. package/dist/controls/rich-text/footnote.d.ts +41 -0
  134. package/dist/controls/rich-text/footnote.js +185 -0
  135. package/dist/controls/rich-text/footnote.js.map +1 -0
  136. package/dist/controls/rich-text/gallery.d.ts +28 -0
  137. package/dist/controls/rich-text/gallery.js +167 -0
  138. package/dist/controls/rich-text/gallery.js.map +1 -0
  139. package/{controls → dist/controls}/rich-text/index.js +1 -1
  140. package/dist/controls/rich-text/index.js.map +1 -0
  141. package/{controls → dist/controls}/rich-text/link-form.d.ts +3 -1
  142. package/dist/controls/rich-text/link-form.js +147 -0
  143. package/dist/controls/rich-text/link-form.js.map +1 -0
  144. package/{controls → dist/controls}/rich-text/markdown.js +4 -2
  145. package/dist/controls/rich-text/markdown.js.map +1 -0
  146. package/{controls → dist/controls}/rich-text/ops.js +17 -15
  147. package/dist/controls/rich-text/ops.js.map +1 -0
  148. package/dist/controls/rich-text/plain.d.ts +17 -0
  149. package/dist/controls/rich-text/plain.js +44 -0
  150. package/dist/controls/rich-text/plain.js.map +1 -0
  151. package/dist/controls/rich-text/related.d.ts +36 -0
  152. package/dist/controls/rich-text/related.js +213 -0
  153. package/dist/controls/rich-text/related.js.map +1 -0
  154. package/dist/controls/rich-text/toc.d.ts +46 -0
  155. package/dist/controls/rich-text/toc.js +161 -0
  156. package/dist/controls/rich-text/toc.js.map +1 -0
  157. package/{controls → dist/controls}/rich-text/toolbar.d.ts +6 -2
  158. package/{controls → dist/controls}/rich-text/toolbar.js +12 -7
  159. package/dist/controls/rich-text/toolbar.js.map +1 -0
  160. package/{controls → dist/controls}/scale.js +5 -5
  161. package/dist/controls/scale.js.map +1 -0
  162. package/dist/controls/slot-register.d.ts +6 -0
  163. package/{controls → dist/controls}/slot-register.js +2 -5
  164. package/dist/controls/slot-register.js.map +1 -0
  165. package/{controls → dist/controls}/slot-services.d.ts +25 -0
  166. package/dist/controls/slot-services.js +155 -0
  167. package/dist/controls/slot-services.js.map +1 -0
  168. package/{controls → dist/controls}/slot.js +42 -24
  169. package/dist/controls/slot.js.map +1 -0
  170. package/{controls → dist/controls}/table/index.js +1 -1
  171. package/dist/controls/table/index.js.map +1 -0
  172. package/{controls → dist/controls}/table/prod.js +3 -3
  173. package/dist/controls/table/prod.js.map +1 -0
  174. package/{controls → dist/controls}/table/refs.js +13 -2
  175. package/dist/controls/table/refs.js.map +1 -0
  176. package/{controls → dist/controls}/table/stored.js +1 -1
  177. package/dist/controls/table/stored.js.map +1 -0
  178. package/{controls → dist/controls}/table/table-editor.js +51 -48
  179. package/dist/controls/table/table-editor.js.map +1 -0
  180. package/{controls → dist/controls}/table/table-link.js +3 -3
  181. package/dist/controls/table/table-link.js.map +1 -0
  182. package/{controls → dist/controls}/table/table.js +3 -3
  183. package/dist/controls/table/table.js.map +1 -0
  184. package/{controls → dist/controls}/text.d.ts +2 -2
  185. package/{controls → dist/controls}/text.js +78 -43
  186. package/dist/controls/text.js.map +1 -0
  187. package/dist/controls/unknown-value.d.ts +17 -0
  188. package/dist/controls/unknown-value.js +66 -0
  189. package/dist/controls/unknown-value.js.map +1 -0
  190. package/dist/core/core.d.ts +70 -0
  191. package/dist/core/core.js +187 -0
  192. package/dist/core/core.js.map +1 -0
  193. package/dist/core/facets.d.ts +355 -0
  194. package/dist/core/facets.js +342 -0
  195. package/dist/core/facets.js.map +1 -0
  196. package/dist/core/index.d.ts +3 -0
  197. package/dist/core/index.js +3 -0
  198. package/{engine → dist/engine}/array.js +34 -21
  199. package/dist/engine/array.js.map +1 -0
  200. package/{engine → dist/engine}/bits.js +1 -1
  201. package/dist/engine/bits.js.map +1 -0
  202. package/{engine → dist/engine}/breadcrumb.d.ts +3 -3
  203. package/{engine → dist/engine}/breadcrumb.js +12 -36
  204. package/dist/engine/breadcrumb.js.map +1 -0
  205. package/{engine → dist/engine}/expand.d.ts +2 -4
  206. package/{engine → dist/engine}/expand.js +5 -22
  207. package/dist/engine/expand.js.map +1 -0
  208. package/{engine → dist/engine}/field-list.js +1 -1
  209. package/dist/engine/field-list.js.map +1 -0
  210. package/{engine → dist/engine}/field-shell.js +249 -121
  211. package/dist/engine/field-shell.js.map +1 -0
  212. package/{engine → dist/engine}/frame.d.ts +3 -1
  213. package/{engine → dist/engine}/frame.js +16 -14
  214. package/dist/engine/frame.js.map +1 -0
  215. package/{engine → dist/engine}/group-summary.d.ts +2 -1
  216. package/{engine → dist/engine}/group-summary.js +7 -3
  217. package/dist/engine/group-summary.js.map +1 -0
  218. package/{engine → dist/engine}/grouping.d.ts +19 -5
  219. package/{engine → dist/engine}/grouping.js +193 -21
  220. package/dist/engine/grouping.js.map +1 -0
  221. package/{engine → dist/engine}/item-list.d.ts +11 -1
  222. package/{engine → dist/engine}/item-list.js +35 -13
  223. package/dist/engine/item-list.js.map +1 -0
  224. package/{engine → dist/engine}/kit-field.js +45 -10
  225. package/dist/engine/kit-field.js.map +1 -0
  226. package/{engine → dist/engine}/schema-form.d.ts +27 -2
  227. package/{engine → dist/engine}/schema-form.js +182 -40
  228. package/dist/engine/schema-form.js.map +1 -0
  229. package/{engine → dist/engine}/slot.js +5 -15
  230. package/dist/engine/slot.js.map +1 -0
  231. package/dist/index.js +58 -0
  232. package/dist/index.js.map +1 -0
  233. package/{kit.css → dist/kit.css} +19 -0
  234. package/{lib → dist/lib}/cn.js +7 -4
  235. package/dist/lib/cn.js.map +1 -0
  236. package/{lib → dist/lib}/columns.js +4 -1
  237. package/dist/lib/columns.js.map +1 -0
  238. package/{lib → dist/lib}/frames.js +2 -2
  239. package/dist/lib/frames.js.map +1 -0
  240. package/dist/lib/icon-image.d.ts +10 -0
  241. package/dist/lib/icon-image.js +8 -0
  242. package/dist/lib/icon-image.js.map +1 -0
  243. package/{lib → dist/lib}/icons.js +4 -3
  244. package/dist/lib/icons.js.map +1 -0
  245. package/dist/lib/input-modality.d.ts +11 -0
  246. package/dist/lib/input-modality.js +47 -0
  247. package/dist/lib/input-modality.js.map +1 -0
  248. package/dist/lib/key-event.d.ts +11 -0
  249. package/dist/lib/key-event.js +16 -0
  250. package/dist/lib/key-event.js.map +1 -0
  251. package/{lib → dist/lib}/path.js +4 -2
  252. package/dist/lib/path.js.map +1 -0
  253. package/{lib → dist/lib}/schema.d.ts +34 -3
  254. package/{lib → dist/lib}/schema.js +110 -13
  255. package/dist/lib/schema.js.map +1 -0
  256. package/{lib → dist/lib}/utils.js +1 -1
  257. package/dist/lib/utils.js.map +1 -0
  258. package/{lib → dist/lib}/validate.d.ts +11 -1
  259. package/{lib → dist/lib}/validate.js +85 -11
  260. package/dist/lib/validate.js.map +1 -0
  261. package/dist/library/analysis.d.ts +23 -0
  262. package/dist/library/analysis.js +160 -0
  263. package/dist/library/analysis.js.map +1 -0
  264. package/dist/library/catalog.d.ts +57 -0
  265. package/dist/library/catalog.js +307 -0
  266. package/dist/library/catalog.js.map +1 -0
  267. package/dist/library/coreNotes.d.ts +8 -0
  268. package/dist/library/coreNotes.js +111 -0
  269. package/dist/library/coreNotes.js.map +1 -0
  270. package/dist/library/coverage.d.ts +40 -0
  271. package/dist/library/coverage.js +59 -0
  272. package/dist/library/coverage.js.map +1 -0
  273. package/dist/library/entries/advanced.entries.d.ts +2 -0
  274. package/dist/library/entries/advanced.entries.js +6579 -0
  275. package/dist/library/entries/advanced.entries.js.map +1 -0
  276. package/dist/library/entries/commerce.entries.d.ts +2 -0
  277. package/dist/library/entries/commerce.entries.js +4140 -0
  278. package/dist/library/entries/commerce.entries.js.map +1 -0
  279. package/dist/library/entries/company.entries.d.ts +2 -0
  280. package/dist/library/entries/company.entries.js +2731 -0
  281. package/dist/library/entries/company.entries.js.map +1 -0
  282. package/dist/library/entries/conversion.entries.d.ts +2 -0
  283. package/dist/library/entries/conversion.entries.js +3707 -0
  284. package/dist/library/entries/conversion.entries.js.map +1 -0
  285. package/dist/library/entries/data.entries.d.ts +7 -0
  286. package/dist/library/entries/data.entries.js +4613 -0
  287. package/dist/library/entries/data.entries.js.map +1 -0
  288. package/dist/library/entries/events.entries.d.ts +2 -0
  289. package/dist/library/entries/events.entries.js +3428 -0
  290. package/dist/library/entries/events.entries.js.map +1 -0
  291. package/dist/library/entries/features.entries.d.ts +2 -0
  292. package/dist/library/entries/features.entries.js +3157 -0
  293. package/dist/library/entries/features.entries.js.map +1 -0
  294. package/dist/library/entries/heroes.entries.d.ts +2 -0
  295. package/dist/library/entries/heroes.entries.js +3401 -0
  296. package/dist/library/entries/heroes.entries.js.map +1 -0
  297. package/dist/library/entries/index.d.ts +3 -0
  298. package/dist/library/entries/index.js +35 -0
  299. package/dist/library/entries/index.js.map +1 -0
  300. package/dist/library/entries/listings.entries.d.ts +2 -0
  301. package/dist/library/entries/listings.entries.js +2976 -0
  302. package/dist/library/entries/listings.entries.js.map +1 -0
  303. package/dist/library/entries/longform.entries.d.ts +2 -0
  304. package/dist/library/entries/longform.entries.js +4227 -0
  305. package/dist/library/entries/longform.entries.js.map +1 -0
  306. package/dist/library/entries/media.entries.d.ts +2 -0
  307. package/dist/library/entries/media.entries.js +2781 -0
  308. package/dist/library/entries/media.entries.js.map +1 -0
  309. package/dist/library/entries/navigation.entries.d.ts +2 -0
  310. package/dist/library/entries/navigation.entries.js +4011 -0
  311. package/dist/library/entries/navigation.entries.js.map +1 -0
  312. package/dist/library/entries/pricing.entries.d.ts +2 -0
  313. package/dist/library/entries/pricing.entries.js +2383 -0
  314. package/dist/library/entries/pricing.entries.js.map +1 -0
  315. package/dist/library/entries/social-proof.entries.d.ts +2 -0
  316. package/dist/library/entries/social-proof.entries.js +2297 -0
  317. package/dist/library/entries/social-proof.entries.js.map +1 -0
  318. package/dist/library/examples/bento.d.ts +92 -0
  319. package/dist/library/examples/bento.js +201 -0
  320. package/dist/library/examples/bento.js.map +1 -0
  321. package/dist/library/examples/blocks.d.ts +14 -0
  322. package/dist/library/examples/blocks.js +313 -0
  323. package/dist/library/examples/blocks.js.map +1 -0
  324. package/dist/library/examples/faq.d.ts +28 -0
  325. package/dist/library/examples/faq.js +230 -0
  326. package/dist/library/examples/faq.js.map +1 -0
  327. package/dist/library/examples/hero.d.ts +43 -0
  328. package/dist/library/examples/hero.js +222 -0
  329. package/dist/library/examples/hero.js.map +1 -0
  330. package/dist/library/examples/index.d.ts +36 -0
  331. package/dist/library/examples/index.js +109 -0
  332. package/dist/library/examples/index.js.map +1 -0
  333. package/dist/library/examples/journalStory.d.ts +93 -0
  334. package/dist/library/examples/journalStory.js +338 -0
  335. package/dist/library/examples/journalStory.js.map +1 -0
  336. package/dist/library/examples/megaMenu.d.ts +134 -0
  337. package/dist/library/examples/megaMenu.js +442 -0
  338. package/dist/library/examples/megaMenu.js.map +1 -0
  339. package/dist/library/examples/pricing.d.ts +103 -0
  340. package/dist/library/examples/pricing.js +479 -0
  341. package/dist/library/examples/pricing.js.map +1 -0
  342. package/dist/library/examples/tabs.d.ts +87 -0
  343. package/dist/library/examples/tabs.js +180 -0
  344. package/dist/library/examples/tabs.js.map +1 -0
  345. package/dist/library/export.d.ts +42 -0
  346. package/dist/library/export.js +80 -0
  347. package/dist/library/export.js.map +1 -0
  348. package/dist/library/index.d.ts +13 -0
  349. package/dist/library/index.js +6 -0
  350. package/dist/library/kit-catalog.json +1511 -0
  351. package/dist/library/types.d.ts +42 -0
  352. package/dist/library/types.js +0 -0
  353. package/{schema → dist/schema}/adapters.js +1 -2
  354. package/dist/schema/adapters.js.map +1 -0
  355. package/{schema → dist/schema}/help.d.ts +2 -0
  356. package/{schema → dist/schema}/help.js +6 -4
  357. package/dist/schema/help.js.map +1 -0
  358. package/{schema → dist/schema}/scale.js +1 -1
  359. package/dist/schema/scale.js.map +1 -0
  360. package/{schema → dist/schema}/sources.js +1 -1
  361. package/dist/schema/sources.js.map +1 -0
  362. package/{schema → dist/schema}/table.js +11 -10
  363. package/dist/schema/table.js.map +1 -0
  364. package/{schema → dist/schema}/types.d.ts +36 -1
  365. package/{schema → dist/schema}/types.js +1 -1
  366. package/dist/schema/types.js.map +1 -0
  367. package/dist/styles.css +2 -0
  368. package/dist/table/table-view.d.ts +14 -0
  369. package/dist/table/table-view.js +140 -0
  370. package/dist/table/table-view.js.map +1 -0
  371. package/dist/table/table.css +73 -0
  372. package/dist/testing/corpus.d.ts +63 -0
  373. package/dist/testing/corpus.js +129 -0
  374. package/dist/testing/corpus.js.map +1 -0
  375. package/dist/testing/test-form.d.ts +11 -0
  376. package/dist/testing/test-form.js +38 -0
  377. package/dist/testing/test-form.js.map +1 -0
  378. package/dist/theme.css +345 -0
  379. package/dist/theme.d.ts +22 -0
  380. package/dist/theme.js +43 -0
  381. package/dist/theme.js.map +1 -0
  382. package/dist/tokens.css +542 -0
  383. package/dist/types.js +0 -0
  384. package/{ui → dist/ui}/action-tray.d.ts +1 -1
  385. package/{ui → dist/ui}/action-tray.js +20 -19
  386. package/dist/ui/action-tray.js.map +1 -0
  387. package/dist/ui/autocomplete.d.ts +58 -0
  388. package/dist/ui/autocomplete.js +194 -0
  389. package/dist/ui/autocomplete.js.map +1 -0
  390. package/{ui → dist/ui}/button.d.ts +3 -3
  391. package/{ui → dist/ui}/button.js +8 -11
  392. package/dist/ui/button.js.map +1 -0
  393. package/{ui → dist/ui}/choice-switch.js +1 -1
  394. package/dist/ui/choice-switch.js.map +1 -0
  395. package/{ui → dist/ui}/controls.js +51 -39
  396. package/dist/ui/controls.js.map +1 -0
  397. package/{ui → dist/ui}/display.d.ts +10 -3
  398. package/{ui → dist/ui}/display.js +57 -46
  399. package/dist/ui/display.js.map +1 -0
  400. package/{ui → dist/ui}/expanded-editor-modal.d.ts +2 -2
  401. package/{ui → dist/ui}/expanded-editor-modal.js +6 -6
  402. package/dist/ui/expanded-editor-modal.js.map +1 -0
  403. package/{ui → dist/ui}/field-context.js +1 -1
  404. package/dist/ui/field-context.js.map +1 -0
  405. package/{ui → dist/ui}/floating-panel.d.ts +1 -1
  406. package/{ui → dist/ui}/floating-panel.js +28 -12
  407. package/dist/ui/floating-panel.js.map +1 -0
  408. package/{ui → dist/ui}/index.d.ts +4 -0
  409. package/dist/ui/index.js +18 -0
  410. package/{ui → dist/ui}/input.d.ts +1 -1
  411. package/{ui → dist/ui}/input.js +9 -9
  412. package/dist/ui/input.js.map +1 -0
  413. package/{ui → dist/ui}/mode-bar.js +3 -3
  414. package/dist/ui/mode-bar.js.map +1 -0
  415. package/{ui → dist/ui}/overlay.d.ts +77 -5
  416. package/dist/ui/overlay.js +697 -0
  417. package/dist/ui/overlay.js.map +1 -0
  418. package/{ui → dist/ui}/path-crumbs.js +37 -3
  419. package/dist/ui/path-crumbs.js.map +1 -0
  420. package/{ui → dist/ui}/presence.js +2 -2
  421. package/dist/ui/presence.js.map +1 -0
  422. package/{ui → dist/ui}/select.js +89 -87
  423. package/dist/ui/select.js.map +1 -0
  424. package/{ui → dist/ui}/shortcut-hint.js +1 -1
  425. package/dist/ui/shortcut-hint.js.map +1 -0
  426. package/dist/ui/spinner.d.ts +24 -0
  427. package/dist/ui/spinner.js +42 -0
  428. package/dist/ui/spinner.js.map +1 -0
  429. package/dist/ui/split-button.d.ts +32 -0
  430. package/dist/ui/split-button.js +60 -0
  431. package/dist/ui/split-button.js.map +1 -0
  432. package/{ui → dist/ui}/surfaces.js +1 -1
  433. package/dist/ui/surfaces.js.map +1 -0
  434. package/dist/ui/tab.d.ts +38 -0
  435. package/dist/ui/tab.js +87 -0
  436. package/dist/ui/tab.js.map +1 -0
  437. package/dist/ui/toast.d.ts +20 -0
  438. package/dist/ui/toast.js +115 -0
  439. package/dist/ui/toast.js.map +1 -0
  440. package/{ui → dist/ui}/tooltip-root.d.ts +4 -3
  441. package/{ui → dist/ui}/tooltip-root.js +9 -8
  442. package/dist/ui/tooltip-root.js.map +1 -0
  443. package/{ui → dist/ui}/variants.js +1 -1
  444. package/dist/ui/variants.js.map +1 -0
  445. package/package.json +83 -23
  446. package/adapters/icons.js.map +0 -1
  447. package/adapters/lossy.js +0 -233
  448. package/adapters/lossy.js.map +0 -1
  449. package/adapters/prod-types.js.map +0 -1
  450. package/adapters/schema.js.map +0 -1
  451. package/adapters/values.js.map +0 -1
  452. package/brand/logo.js +0 -9
  453. package/brand/logo.js.map +0 -1
  454. package/context.js.map +0 -1
  455. package/controls/button.js.map +0 -1
  456. package/controls/c1.js.map +0 -1
  457. package/controls/c2.js.map +0 -1
  458. package/controls/choice.js.map +0 -1
  459. package/controls/code-register.js.map +0 -1
  460. package/controls/code.js.map +0 -1
  461. package/controls/color.js.map +0 -1
  462. package/controls/date-register.js.map +0 -1
  463. package/controls/date-zone.js.map +0 -1
  464. package/controls/date.js.map +0 -1
  465. package/controls/form-picker-register.d.ts +0 -1
  466. package/controls/form-picker-register.js.map +0 -1
  467. package/controls/form-picker.js.map +0 -1
  468. package/controls/icon-register.js.map +0 -1
  469. package/controls/icon.js.map +0 -1
  470. package/controls/index.js.map +0 -1
  471. package/controls/json-register.js.map +0 -1
  472. package/controls/json.js.map +0 -1
  473. package/controls/link.js.map +0 -1
  474. package/controls/location-register.js.map +0 -1
  475. package/controls/location.js.map +0 -1
  476. package/controls/media-register.js.map +0 -1
  477. package/controls/media.js.map +0 -1
  478. package/controls/number.js.map +0 -1
  479. package/controls/reference-register.js.map +0 -1
  480. package/controls/reference.js.map +0 -1
  481. package/controls/rich-text/blocks.d.ts +0 -28
  482. package/controls/rich-text/blocks.js.map +0 -1
  483. package/controls/rich-text/catalog.js.map +0 -1
  484. package/controls/rich-text/codec.js.map +0 -1
  485. package/controls/rich-text/component-card.js.map +0 -1
  486. package/controls/rich-text/control.js.map +0 -1
  487. package/controls/rich-text/dom.js.map +0 -1
  488. package/controls/rich-text/editor.js.map +0 -1
  489. package/controls/rich-text/floating.js.map +0 -1
  490. package/controls/rich-text/index.js.map +0 -1
  491. package/controls/rich-text/link-form.js +0 -111
  492. package/controls/rich-text/link-form.js.map +0 -1
  493. package/controls/rich-text/markdown.js.map +0 -1
  494. package/controls/rich-text/ops.js.map +0 -1
  495. package/controls/rich-text/toolbar.js.map +0 -1
  496. package/controls/scale.js.map +0 -1
  497. package/controls/slot-register.d.ts +0 -1
  498. package/controls/slot-register.js.map +0 -1
  499. package/controls/slot-services.js +0 -38
  500. package/controls/slot-services.js.map +0 -1
  501. package/controls/slot.js.map +0 -1
  502. package/controls/table/index.js.map +0 -1
  503. package/controls/table/prod.js.map +0 -1
  504. package/controls/table/refs.js.map +0 -1
  505. package/controls/table/stored.js.map +0 -1
  506. package/controls/table/table-editor.js.map +0 -1
  507. package/controls/table/table-link.js.map +0 -1
  508. package/controls/table/table.js.map +0 -1
  509. package/controls/text.js.map +0 -1
  510. package/engine/array.js.map +0 -1
  511. package/engine/bits.js.map +0 -1
  512. package/engine/breadcrumb.js.map +0 -1
  513. package/engine/expand.js.map +0 -1
  514. package/engine/field-list.js.map +0 -1
  515. package/engine/field-shell.js.map +0 -1
  516. package/engine/frame.js.map +0 -1
  517. package/engine/group-summary.js.map +0 -1
  518. package/engine/grouping.js.map +0 -1
  519. package/engine/item-list.js.map +0 -1
  520. package/engine/kit-field.js.map +0 -1
  521. package/engine/schema-form.js.map +0 -1
  522. package/engine/slot.js.map +0 -1
  523. package/index.js +0 -55
  524. package/index.js.map +0 -1
  525. package/lib/cn.js.map +0 -1
  526. package/lib/columns.js.map +0 -1
  527. package/lib/frames.js.map +0 -1
  528. package/lib/icons.js.map +0 -1
  529. package/lib/path.js.map +0 -1
  530. package/lib/schema.js.map +0 -1
  531. package/lib/utils.js.map +0 -1
  532. package/lib/validate.js.map +0 -1
  533. package/schema/adapters.js.map +0 -1
  534. package/schema/help.js.map +0 -1
  535. package/schema/scale.js.map +0 -1
  536. package/schema/sources.js.map +0 -1
  537. package/schema/table.js.map +0 -1
  538. package/schema/types.js.map +0 -1
  539. package/ui/action-tray.js.map +0 -1
  540. package/ui/button.js.map +0 -1
  541. package/ui/choice-switch.js.map +0 -1
  542. package/ui/controls.js.map +0 -1
  543. package/ui/display.js.map +0 -1
  544. package/ui/expanded-editor-modal.js.map +0 -1
  545. package/ui/field-context.js.map +0 -1
  546. package/ui/floating-panel.js.map +0 -1
  547. package/ui/index.js +0 -13
  548. package/ui/input.js.map +0 -1
  549. package/ui/mode-bar.js.map +0 -1
  550. package/ui/overlay.js +0 -378
  551. package/ui/overlay.js.map +0 -1
  552. package/ui/path-crumbs.js.map +0 -1
  553. package/ui/presence.js.map +0 -1
  554. package/ui/select.js.map +0 -1
  555. package/ui/shortcut-hint.js.map +0 -1
  556. package/ui/surfaces.js.map +0 -1
  557. package/ui/tooltip-root.js.map +0 -1
  558. package/ui/variants.js.map +0 -1
  559. /package/{_virtual → dist/_virtual}/_rolldown/runtime.js +0 -0
  560. /package/{adapters → dist/adapters}/icons.d.ts +0 -0
  561. /package/{brand → dist/brand}/logo.d.ts +0 -0
  562. /package/{controls → dist/controls}/c1.d.ts +0 -0
  563. /package/{controls → dist/controls}/c2.d.ts +0 -0
  564. /package/{controls → dist/controls}/code-register.d.ts +0 -0
  565. /package/{controls → dist/controls}/code.d.ts +0 -0
  566. /package/{controls → dist/controls}/color.d.ts +0 -0
  567. /package/{controls → dist/controls}/date-register.d.ts +0 -0
  568. /package/{controls → dist/controls}/date-zone.d.ts +0 -0
  569. /package/{controls → dist/controls}/date.d.ts +0 -0
  570. /package/{controls → dist/controls}/form-picker.d.ts +0 -0
  571. /package/{controls → dist/controls}/icon-register.d.ts +0 -0
  572. /package/{controls → dist/controls}/json-register.d.ts +0 -0
  573. /package/{controls → dist/controls}/json.d.ts +0 -0
  574. /package/{controls → dist/controls}/link.d.ts +0 -0
  575. /package/{controls → dist/controls}/location-register.d.ts +0 -0
  576. /package/{controls → dist/controls}/location.d.ts +0 -0
  577. /package/{controls → dist/controls}/media-register.d.ts +0 -0
  578. /package/{controls → dist/controls}/number.d.ts +0 -0
  579. /package/{controls → dist/controls}/reference-register.d.ts +0 -0
  580. /package/{controls → dist/controls}/rich-text/index.d.ts +0 -0
  581. /package/{controls → dist/controls}/rich-text/markdown.d.ts +0 -0
  582. /package/{controls → dist/controls}/rich-text/ops.d.ts +0 -0
  583. /package/{controls → dist/controls}/scale.d.ts +0 -0
  584. /package/{controls → dist/controls}/slot.d.ts +0 -0
  585. /package/{controls → dist/controls}/table/index.d.ts +0 -0
  586. /package/{controls → dist/controls}/table/prod.d.ts +0 -0
  587. /package/{controls → dist/controls}/table/refs.d.ts +0 -0
  588. /package/{controls → dist/controls}/table/stored.d.ts +0 -0
  589. /package/{controls → dist/controls}/table/table-editor.d.ts +0 -0
  590. /package/{controls → dist/controls}/table/table-link.d.ts +0 -0
  591. /package/{controls → dist/controls}/table/table.d.ts +0 -0
  592. /package/{engine → dist/engine}/array.d.ts +0 -0
  593. /package/{engine → dist/engine}/bits.d.ts +0 -0
  594. /package/{engine → dist/engine}/field-list.d.ts +0 -0
  595. /package/{engine → dist/engine}/field-shell.d.ts +0 -0
  596. /package/{engine → dist/engine}/kit-field.d.ts +0 -0
  597. /package/{engine → dist/engine}/slot.d.ts +0 -0
  598. /package/{index.d.ts → dist/index.d.ts} +0 -0
  599. /package/{lib → dist/lib}/cn.d.ts +0 -0
  600. /package/{lib → dist/lib}/columns.d.ts +0 -0
  601. /package/{lib → dist/lib}/frames.d.ts +0 -0
  602. /package/{lib → dist/lib}/icons.d.ts +0 -0
  603. /package/{lib → dist/lib}/path.d.ts +0 -0
  604. /package/{lib → dist/lib}/utils.d.ts +0 -0
  605. /package/{schema → dist/schema}/adapters.d.ts +0 -0
  606. /package/{schema → dist/schema}/scale.d.ts +0 -0
  607. /package/{schema → dist/schema}/sources.d.ts +0 -0
  608. /package/{schema → dist/schema}/table.d.ts +0 -0
  609. /package/{types.d.ts → dist/types.d.ts} +0 -0
  610. /package/{ui → dist/ui}/choice-switch.d.ts +0 -0
  611. /package/{ui → dist/ui}/controls.d.ts +0 -0
  612. /package/{ui → dist/ui}/field-context.d.ts +0 -0
  613. /package/{ui → dist/ui}/mode-bar.d.ts +0 -0
  614. /package/{ui → dist/ui}/path-crumbs.d.ts +0 -0
  615. /package/{ui → dist/ui}/presence.d.ts +0 -0
  616. /package/{ui → dist/ui}/select.d.ts +0 -0
  617. /package/{ui → dist/ui}/shortcut-hint.d.ts +0 -0
  618. /package/{ui → dist/ui}/surfaces.d.ts +0 -0
  619. /package/{ui → dist/ui}/variants.d.ts +0 -0
@@ -1,15 +1,19 @@
1
+ import { cropPreset, cropRect, isCropRect } from "../adapters/values.js";
1
2
  import { cn } from "../lib/cn.js";
2
- import { isObj } from "../lib/path.js";
3
3
  import { useKitEnv, useKitServices } from "../context.js";
4
- import { Button } from "../ui/button.js";
4
+ import { isObj } from "../lib/path.js";
5
+ import { Button, IconButton } from "../ui/button.js";
5
6
  import { Progress } from "../ui/controls.js";
6
7
  import { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger, Popover, PopoverAnchor, PopoverContent, Tooltip } from "../ui/overlay.js";
8
+ import { RowChrome } from "../engine/bits.js";
9
+ import { isIconImage } from "../lib/icon-image.js";
7
10
  import { Input, Textarea } from "../ui/input.js";
11
+ import { Select } from "../ui/select.js";
8
12
  import { useDragReorder } from "../engine/item-list.js";
9
13
  import * as React from "react";
10
- import { IconAlertTriangle, IconDots, IconDownload, IconExternalLink, IconFileText, IconFocusCentered, IconLink, IconPhoto, IconPlayerPlay, IconPlus, IconReplace, IconTrash, IconUpload, IconVideo, IconWorld, IconX } from "@tabler/icons-react";
11
14
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
- //#region src/kit/controls/media.tsx
15
+ import { IconAlertTriangle, IconCrop, IconDots, IconDownload, IconExternalLink, IconFileText, IconFocusCentered, IconLink, IconPhoto, IconPlayerPlay, IconPlus, IconRefresh, IconReplace, IconTrash, IconUpload, IconVideo, IconWorld, IconX } from "@tabler/icons-react";
16
+ //#region src/controls/media.tsx
13
17
  /**
14
18
  * MEDIA — image · gallery · file · video (V2 HEAD 9829bf1 kit/controls/media.tsx, DESIGN.md 8.15).
15
19
  *
@@ -19,8 +23,9 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
19
23
  * (media-services.ts): the kit never imports a feature, and a missing service is named in words, never faked.
20
24
  *
21
25
  * Kit deviations from V2, each because of what the backend stores (adapters/values.ts):
22
- * - no "Crop for this placement" dropdown: `imageToProd` cannot store a crop preset (it becomes a pixel rect only with
23
- * the asset's size, and never reads back as the preset), so the dock would refuse every write that carried one;
26
+ * - "Crop for this placement" is V2's five-crop dropdown, stored as the rect prod keeps (cut from the picture's own size,
27
+ * centred on the focal point); a stored rect reads back as its preset when the size is known, and is kept as it is
28
+ * otherwise. With no size yet, the dropdown waits, and says why;
24
29
  * - a picked asset's width / height / size are read for the caption, never written into the value (prod rebuilds the
25
30
  * value from url, id, name, altText and focal; the rest would be refused);
26
31
  * - where the host stores the URL string only (`imageStoresUrl`, the dock's top-level image props) the value stays a
@@ -31,11 +36,15 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
31
36
  * refuses a half-typed address.
32
37
  */
33
38
  var fileNameFromUrl = (url) => {
34
- const last = url.split("?")[0].split("#")[0].split("/").filter(Boolean).pop() ?? "";
39
+ const inline = /^data:image\/([a-z0-9.+-]+)/i.exec(url.trim());
40
+ if (inline) return `Embedded ${inline[1].replace(/\+xml$/i, "").replace(/^jpeg$/i, "jpg").toUpperCase()} image`;
35
41
  try {
36
- return decodeURIComponent(last);
42
+ const u = new URL(url, typeof window === "undefined" ? "https://x.invalid" : window.location.href);
43
+ if (u.protocol === "data:" || u.protocol === "blob:") return "Image";
44
+ const file = u.pathname.split("/").filter(Boolean).reverse().find((x) => /\.[a-z0-9]{2,5}$/i.test(x));
45
+ return file ? decodeURIComponent(file) : `Image from ${u.hostname.replace(/^www\./, "")}`;
37
46
  } catch {
38
- return last;
47
+ return "Image";
39
48
  }
40
49
  };
41
50
  var normImage = (v) => {
@@ -44,10 +53,10 @@ var normImage = (v) => {
44
53
  };
45
54
  /** What an asset becomes in a value: the keys prod keeps (url, id, name, alt), nothing measured. */
46
55
  var fromAsset = (a) => {
47
- const out = {
56
+ const out = a.id ? {
48
57
  url: a.url,
49
58
  id: a.id
50
- };
59
+ } : { url: a.url };
51
60
  if (a.name) out.name = a.name;
52
61
  if (a.alt) out.alt = a.alt;
53
62
  return out;
@@ -57,6 +66,7 @@ var HTTP = /^https?:\/\/\S+$/i;
57
66
  /** An http(s) URL or a site path: what prod's video value takes (video-value.ts isVideoUrl). */
58
67
  var isVideoUrl = (s) => s === "" || HTTP.test(s.trim()) || /^\/(?!\/)\S*$/.test(s.trim());
59
68
  var NO_ASSET = () => void 0;
69
+ var NO_ICONS = () => [];
60
70
  var NO_SRC = (u) => u;
61
71
  /** The services the media controls read, each hook stable across renders. */
62
72
  function useMedia() {
@@ -183,8 +193,8 @@ function DropWell({ id, title, hint, accept, multiple, icon, disabled, onFiles,
183
193
  className: "text-kit-xs text-kit-fg-3",
184
194
  children: hint
185
195
  }) : null] }),
186
- urlMode && onUrl ? /* @__PURE__ */ jsxs("form", {
187
- className: "flex w-full max-w-sm flex-col gap-1.5",
196
+ urlMode && onUrl ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("form", {
197
+ className: "flex w-full max-w-sm items-center gap-1.5",
188
198
  onSubmit: (e) => {
189
199
  e.preventDefault();
190
200
  e.stopPropagation();
@@ -203,26 +213,22 @@ function DropWell({ id, title, hint, accept, multiple, icon, disabled, onFiles,
203
213
  setUrlError(null);
204
214
  }
205
215
  },
206
- children: [/* @__PURE__ */ jsxs("div", {
207
- className: "flex items-center gap-1.5",
208
- children: [/* @__PURE__ */ jsx(Input, {
209
- autoFocus: true,
210
- size: "sm",
211
- value: url,
212
- "aria-label": "Image URL",
213
- "aria-invalid": urlError ? true : void 0,
214
- onChange: (e) => setUrl(e.target.value),
215
- placeholder: "https://…/photo.jpg",
216
- leading: /* @__PURE__ */ jsx(IconLink, { stroke: 1.5 }),
217
- className: "flex-1"
218
- }), /* @__PURE__ */ jsx(Button, {
219
- size: "sm",
220
- type: "submit",
221
- variant: "primary",
222
- children: "Add"
223
- })]
224
- }), urlError ? /* @__PURE__ */ jsx(Reason, { children: urlError }) : null]
225
- }) : /* @__PURE__ */ jsxs("div", {
216
+ children: [/* @__PURE__ */ jsx(Input, {
217
+ autoFocus: true,
218
+ size: "sm",
219
+ value: url,
220
+ "aria-label": "Image URL",
221
+ "aria-invalid": urlError ? true : void 0,
222
+ onChange: (e) => setUrl(e.target.value),
223
+ placeholder: "https://…/photo.jpg",
224
+ leading: /* @__PURE__ */ jsx(IconLink, { stroke: 1.5 })
225
+ }), /* @__PURE__ */ jsx(Button, {
226
+ size: "sm",
227
+ type: "submit",
228
+ variant: "primary",
229
+ children: "Add"
230
+ })]
231
+ }), urlError ? /* @__PURE__ */ jsx(Reason, { children: urlError }) : null] }) : /* @__PURE__ */ jsxs("div", {
226
232
  className: "flex flex-wrap justify-center gap-1.5",
227
233
  children: [
228
234
  onLibrary || refuse ? /* @__PURE__ */ jsx(Button, {
@@ -289,19 +295,83 @@ function DropWell({ id, title, hint, accept, multiple, icon, disabled, onFiles,
289
295
  var NO_SOURCE = "No media library or upload is connected to this editor, so nothing can be chosen here.";
290
296
  var NO_LIBRARY = "No media library is connected to this editor, so nothing can be picked from it here.";
291
297
  var NO_UPLOAD = "No upload is connected to this editor, so files can't be uploaded here.";
292
- function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
298
+ /** Transparency checker on the kit tokens (white in light, dimmed in dark), as the media grid draws it. */
299
+ var CHECKER = "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]";
300
+ /** V2's five crops (kit media.tsx CROPS, D46). */
301
+ var CROPS = [
302
+ {
303
+ value: "original",
304
+ label: "Original",
305
+ ratio: "auto",
306
+ description: "Keep the uploaded shape"
307
+ },
308
+ {
309
+ value: "16:9",
310
+ label: "16:9",
311
+ ratio: "16/9",
312
+ description: "Widescreen"
313
+ },
314
+ {
315
+ value: "4:3",
316
+ label: "4:3",
317
+ ratio: "4/3",
318
+ description: "Landscape"
319
+ },
320
+ {
321
+ value: "1:1",
322
+ label: "1:1",
323
+ ratio: "1/1",
324
+ description: "Square"
325
+ },
326
+ {
327
+ value: "4:5",
328
+ label: "4:5",
329
+ ratio: "4/5",
330
+ description: "Portrait"
331
+ }
332
+ ];
333
+ var CUSTOM_CROP = "custom";
334
+ /** The crop a value shows: its preset, a stored rect read against the picture's size, or a rect that is none of them. */
335
+ function cropChoice(crop, size) {
336
+ if (!crop) return "original";
337
+ if (typeof crop === "string") return crop;
338
+ if (!isCropRect(crop)) return "original";
339
+ return size && cropPreset(crop, size.w, size.h) || CUSTOM_CROP;
340
+ }
341
+ /** A custom rect's own shape (its fractions of the picture, in pixels), when the picture's size is known. */
342
+ function customRatio(crop, size) {
343
+ if (!size || !crop || typeof crop === "string" || !isCropRect(crop)) return void 0;
344
+ const w = (1 - crop.left - crop.right) * size.w;
345
+ const h = (1 - crop.top - crop.bottom) * size.h;
346
+ return w > 0 && h > 0 ? String(w / h) : void 0;
347
+ }
348
+ /** The value with `choice` cut from the picture (centred on its focal point), or with no crop for Original. */
349
+ function withCrop(v, choice, size) {
350
+ const next = { ...v };
351
+ delete next.crop;
352
+ const rect = choice === "original" ? void 0 : cropRect(choice, size.w, size.h, v.focal);
353
+ if (rect) next.crop = rect;
354
+ return next;
355
+ }
356
+ function ImageDetails({ v, onChange, readOnly, label, urlOnly, altOnly = false, size, asset }) {
293
357
  const { src } = useMedia();
294
358
  const focal = v.focal ?? {
295
359
  x: 50,
296
360
  y: 50
297
361
  };
298
- const setFocal = (x, y) => onChange({
299
- ...v,
300
- focal: {
301
- x: Math.round(Math.min(100, Math.max(0, x))),
302
- y: Math.round(Math.min(100, Math.max(0, y)))
303
- }
304
- });
362
+ const choice = cropChoice(v.crop, size);
363
+ const crop = CROPS.find((c) => c.value === choice);
364
+ const padRatio = crop && crop.ratio !== "auto" ? crop.ratio : customRatio(v.crop, size) ?? "3/2";
365
+ const setFocal = (x, y) => {
366
+ const next = {
367
+ ...v,
368
+ focal: {
369
+ x: Math.round(Math.min(100, Math.max(0, x))),
370
+ y: Math.round(Math.min(100, Math.max(0, y)))
371
+ }
372
+ };
373
+ onChange(crop && crop.value !== "original" && size ? withCrop(next, crop.value, size) : next);
374
+ };
305
375
  const fromPointer = (e) => {
306
376
  const r = e.currentTarget.getBoundingClientRect();
307
377
  if (!r.width || !r.height) return;
@@ -356,21 +426,29 @@ function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
356
426
  className: "min-h-14 text-kit-sm",
357
427
  "aria-label": `${label} alt text`
358
428
  })]
359
- }), /* @__PURE__ */ jsxs("div", {
429
+ }), altOnly ? /* @__PURE__ */ jsx(Reason, {
430
+ tone: "muted",
431
+ children: "This image block keeps its address and alt text. A crop or focal point isn't stored with it."
432
+ }) : /* @__PURE__ */ jsxs("div", {
360
433
  className: "flex flex-col gap-1.5",
361
434
  children: [
362
435
  /* @__PURE__ */ jsxs("div", {
363
436
  className: "flex items-center justify-between",
364
437
  children: [/* @__PURE__ */ jsxs("span", {
365
438
  className: "flex items-center gap-1 text-kit-xs text-kit-fg-3",
366
- children: [/* @__PURE__ */ jsx(IconFocusCentered, {
439
+ children: [/* @__PURE__ */ jsx(IconCrop, {
367
440
  className: "size-3.5",
368
441
  stroke: 1.5,
369
442
  "aria-hidden": true
370
- }), "Focal point"]
443
+ }), "Crop for this placement"]
371
444
  }), /* @__PURE__ */ jsxs("span", {
372
- className: "tabular-nums text-kit-2xs text-kit-fg-3",
445
+ className: "flex items-center gap-1 text-kit-2xs text-kit-fg-3",
373
446
  children: [
447
+ /* @__PURE__ */ jsx(IconFocusCentered, {
448
+ className: "size-3",
449
+ stroke: 1.5,
450
+ "aria-hidden": true
451
+ }),
374
452
  "Focal ",
375
453
  focal.x,
376
454
  "%, ",
@@ -379,6 +457,28 @@ function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
379
457
  ]
380
458
  })]
381
459
  }),
460
+ /* @__PURE__ */ jsx(Select, {
461
+ size: "sm",
462
+ "aria-label": `${label} crop`,
463
+ disabled: readOnly || !size,
464
+ triggerClassName: "w-full",
465
+ value: choice,
466
+ onValueChange: (c) => size && c !== CUSTOM_CROP && onChange(withCrop(v, c, size)),
467
+ options: [...CROPS.map((c) => ({
468
+ value: c.value,
469
+ label: c.label,
470
+ meta: c.description
471
+ })), ...choice === CUSTOM_CROP ? [{
472
+ value: CUSTOM_CROP,
473
+ label: "Custom",
474
+ meta: "Cut elsewhere",
475
+ disabled: true
476
+ }] : []]
477
+ }),
478
+ !size && !readOnly ? /* @__PURE__ */ jsx("span", {
479
+ className: "text-kit-2xs text-kit-fg-3",
480
+ children: "The crop is cut from the picture's size, which is still loading."
481
+ }) : null,
382
482
  /* @__PURE__ */ jsxs("div", {
383
483
  role: "slider",
384
484
  "aria-label": "Focal point. Click the subject.",
@@ -401,16 +501,18 @@ function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
401
501
  e.preventDefault();
402
502
  setFocal(focal.x + step[0], focal.y + step[1]);
403
503
  },
404
- className: "relative mt-1 aspect-[3/2] cursor-crosshair overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted",
504
+ "data-pad-ratio": padRatio,
505
+ className: "relative mt-1 cursor-crosshair overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted",
506
+ style: { aspectRatio: padRatio },
405
507
  children: [/* @__PURE__ */ jsx("img", {
406
508
  src: src(v.url),
407
509
  alt: "",
408
510
  draggable: false,
409
- className: "pointer-events-none size-full select-none object-cover transition-[object-position] duration-200 motion-reduce:transition-none",
511
+ className: "pointer-events-none size-full select-none object-cover transition-[object-position] duration-200",
410
512
  style: { objectPosition: `${focal.x}% ${focal.y}%` }
411
513
  }), /* @__PURE__ */ jsx("span", {
412
514
  "aria-hidden": true,
413
- className: "pointer-events-none absolute size-5 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-kit-fg-inverse bg-kit-inverse/30 shadow-kit-md transition-[left,top] duration-150 motion-reduce:transition-none",
515
+ 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",
414
516
  style: {
415
517
  left: `${focal.x}%`,
416
518
  top: `${focal.y}%`
@@ -423,7 +525,7 @@ function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
423
525
  })
424
526
  ]
425
527
  })] }),
426
- /* @__PURE__ */ jsxs("div", {
528
+ urlOnly || altOnly ? /* @__PURE__ */ jsxs("div", {
427
529
  className: "flex flex-col gap-1.5",
428
530
  children: [/* @__PURE__ */ jsx("span", {
429
531
  className: "text-kit-xs text-kit-fg-3",
@@ -432,6 +534,26 @@ function ImageDetails({ v, onChange, readOnly, label, urlOnly, size, asset }) {
432
534
  className: "truncate font-kit-mono text-kit-xs text-kit-fg",
433
535
  children: asset?.name ?? v.name ?? fileNameFromUrl(v.url)
434
536
  })]
537
+ }) : /* @__PURE__ */ jsxs("label", {
538
+ className: "flex flex-col gap-1.5",
539
+ children: [/* @__PURE__ */ jsx("span", {
540
+ className: "text-kit-xs text-kit-fg-3",
541
+ children: "File name"
542
+ }), /* @__PURE__ */ jsx(Input, {
543
+ size: "sm",
544
+ value: v.name ?? asset?.name ?? fileNameFromUrl(v.url),
545
+ readOnly,
546
+ spellCheck: false,
547
+ autoComplete: "off",
548
+ onChange: (e) => {
549
+ const next = { ...v };
550
+ if (e.target.value) next.name = e.target.value;
551
+ else delete next.name;
552
+ onChange(next);
553
+ },
554
+ className: "font-kit-mono [&_input]:font-kit-mono",
555
+ "aria-label": `${label} file name`
556
+ })]
435
557
  })
436
558
  ]
437
559
  });
@@ -445,19 +567,105 @@ function storedSize(value) {
445
567
  h: height
446
568
  } : void 0;
447
569
  }
448
- var PILL = "flex h-7 items-center gap-1 rounded-full border border-kit-swatch-ring bg-kit-control-bg px-2.5 text-kit-xs font-medium text-kit-fg shadow-kit-sm";
570
+ /**
571
+ * V2's icon control shape (controls/icon.tsx): ONE button — a 24px glyph tile, the field's name, a quiet replace cue —
572
+ * that opens the library. No Replace pill, no ×, no alt text, crop or details: an icon's alt text is "" (aria-hidden on
573
+ * the page) and Remove sits in the picker's footer. Empty: a dashed tile, "Add icon", and an SVG dropped on it uploads.
574
+ */
575
+ function IconImageRow({ id, title, url, readOnly, onOpen, onFiles, busy, pickerOpen }) {
576
+ const row = React.useRef(null);
577
+ const [over, setOver] = React.useState(false);
578
+ const wasOpen = React.useRef(false);
579
+ React.useEffect(() => {
580
+ if (wasOpen.current && !pickerOpen) row.current?.focus({ preventScroll: true });
581
+ wasOpen.current = pickerOpen;
582
+ }, [pickerOpen]);
583
+ const empty = !url;
584
+ const inert = readOnly || busy || !onOpen;
585
+ const droppable = empty && !inert && !!onFiles;
586
+ const chrome = React.useContext(RowChrome);
587
+ return /* @__PURE__ */ jsxs("div", {
588
+ className: cn("flex h-8 min-w-0 items-center rounded-kit-md border bg-kit-field-bg pointer-coarse:min-h-11", "transition-colors duration-[120ms] ease-out motion-reduce:transition-none", over ? "border-kit-emphasis-line bg-kit-hover" : "border-kit-line-strong", inert ? "opacity-60" : "[@media(hover:hover)]:hover:bg-kit-hover"),
589
+ children: [/* @__PURE__ */ jsx(Tooltip, {
590
+ content: title,
591
+ children: /* @__PURE__ */ jsxs("button", {
592
+ ref: row,
593
+ id,
594
+ type: "button",
595
+ "data-slot": "kit-icon-row",
596
+ disabled: inert,
597
+ onClick: onOpen,
598
+ "aria-label": empty ? `Add icon, ${title}` : `Replace ${title}`,
599
+ onDragOver: droppable ? (e) => {
600
+ e.preventDefault();
601
+ setOver(true);
602
+ } : void 0,
603
+ onDragLeave: droppable ? () => setOver(false) : void 0,
604
+ onDrop: droppable ? (e) => {
605
+ e.preventDefault();
606
+ setOver(false);
607
+ onFiles(Array.from(e.dataTransfer.files));
608
+ } : void 0,
609
+ 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",
610
+ children: [
611
+ /* @__PURE__ */ jsx("span", {
612
+ "aria-hidden": true,
613
+ className: cn("grid size-6 shrink-0 place-items-center overflow-hidden rounded-kit-sm border", empty ? "border-dashed border-kit-emphasis-line" : cn("border-kit-line p-1", CHECKER)),
614
+ children: empty ? /* @__PURE__ */ jsx(IconPlus, {
615
+ className: "size-3.5 text-kit-fg-3",
616
+ stroke: 1.5
617
+ }) : /* @__PURE__ */ jsx("img", {
618
+ src: url,
619
+ alt: "",
620
+ className: "size-full object-contain"
621
+ })
622
+ }),
623
+ /* @__PURE__ */ jsx("span", {
624
+ "aria-hidden": true,
625
+ className: cn("min-w-0 flex-1 truncate", empty ? "text-kit-fg-3" : "text-kit-fg"),
626
+ children: empty ? busy ? "Uploading…" : "Add icon" : title
627
+ }),
628
+ empty ? null : /* @__PURE__ */ jsx(IconRefresh, {
629
+ "aria-hidden": true,
630
+ className: "size-3.5 shrink-0 text-kit-fg-3",
631
+ stroke: 1.5
632
+ })
633
+ ]
634
+ })
635
+ }), chrome ? /* @__PURE__ */ jsx("span", {
636
+ "data-slot": "kit-icon-row-chrome",
637
+ className: "flex shrink-0 items-center gap-0.5 pr-1 empty:hidden",
638
+ children: chrome
639
+ }) : null]
640
+ });
641
+ }
449
642
  function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
450
643
  const { s, useAsset, src } = useMedia();
451
644
  const env = useKitEnv();
452
645
  const urlOnly = !!s.imageStoresUrl?.(path);
646
+ const altOnly = !urlOnly && !!s.imageAltOnly?.(path);
453
647
  const legacyString = typeof value === "string" || field.valueShape === "string";
454
648
  const v = normImage(value);
455
649
  const asset = useAsset({
456
650
  id: v?.id,
457
651
  url: v?.url ?? ""
458
652
  });
459
- const [natural, setNatural] = React.useState();
460
- React.useEffect(() => setNatural(void 0), [v?.url]);
653
+ const accept = field.svgOnly ? "image/svg+xml" : "image/*";
654
+ const kinds = field.svgOnly ? ["svg"] : ["image", "svg"];
655
+ const [loaded, setLoaded] = React.useState();
656
+ const natural = loaded && v && loaded.url === v.url ? {
657
+ w: loaded.w,
658
+ h: loaded.h
659
+ } : void 0;
660
+ const readNatural = (img) => {
661
+ if (!img || !v || !img.complete || !img.naturalWidth || !img.naturalHeight) return;
662
+ const next = {
663
+ url: v.url,
664
+ w: img.naturalWidth,
665
+ h: img.naturalHeight
666
+ };
667
+ setLoaded((prev) => prev && prev.url === next.url && prev.w === next.w && prev.h === next.h ? prev : next);
668
+ };
461
669
  const stored = storedSize(value);
462
670
  const size = asset?.width && asset.height ? {
463
671
  w: asset.width,
@@ -466,13 +674,68 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
466
674
  const onChange = (n) => {
467
675
  if (!n) return write(urlOnly ? "" : null);
468
676
  if (urlOnly) return write(n.url);
469
- if (legacyString && !n.alt && !n.focal) return write(n.url);
677
+ if (legacyString && !n.alt && !n.focal && !n.crop && !n.name && !n.id) return write(n.url);
470
678
  write(n);
471
679
  };
472
680
  const [picker, setPicker] = React.useState(false);
473
681
  const [details, setDetails] = React.useState(false);
474
- const up = useUpload("image/*", "image", (a) => a[0] && onChange(fromAsset(a[0])));
682
+ const up = useUpload(accept, "image", (a) => a[0] && onChange(fromAsset(a[0])));
475
683
  const library = s.MediaPicker && !readOnly ? () => setPicker(true) : void 0;
684
+ const known = (s.useSiteIcons ?? NO_ICONS)();
685
+ if (isIconImage(field, value)) {
686
+ const icons = s.useSiteIcons ? [...v ? [{
687
+ url: v.url,
688
+ value,
689
+ current: true
690
+ }] : [], ...known.filter((i) => i.url !== v?.url && !(v?.id && i.assetId === v.id)).map(({ url, value: stored }) => ({
691
+ url,
692
+ value: stored
693
+ }))] : void 0;
694
+ const pickIcon = (stored) => {
695
+ const n = normImage(stored);
696
+ if (n) onChange(fromAsset({
697
+ id: n.id ?? "",
698
+ url: n.url,
699
+ name: n.name,
700
+ alt: n.alt ?? (typeof n.altText === "string" ? n.altText : void 0),
701
+ kind: "svg"
702
+ }));
703
+ setPicker(false);
704
+ };
705
+ return /* @__PURE__ */ jsxs("div", {
706
+ className: "flex flex-col gap-1.5",
707
+ children: [
708
+ /* @__PURE__ */ jsx(IconImageRow, {
709
+ id,
710
+ title: field.title,
711
+ url: v ? src(v.url) : void 0,
712
+ readOnly,
713
+ onOpen: library,
714
+ onFiles: up.run,
715
+ busy: up.progress != null,
716
+ pickerOpen: picker
717
+ }),
718
+ up.error ? /* @__PURE__ */ jsx(Reason, { children: up.error }) : null,
719
+ !readOnly && !library ? /* @__PURE__ */ jsx(Reason, {
720
+ tone: "muted",
721
+ children: NO_LIBRARY
722
+ }) : null,
723
+ /* @__PURE__ */ jsx(MediaPicker, {
724
+ open: picker,
725
+ onOpenChange: setPicker,
726
+ accept: ["svg"],
727
+ title: v ? "Replace icon" : "Select an icon",
728
+ onPick: (a) => a[0] && onChange(fromAsset(a[0])),
729
+ onRemove: v && !readOnly ? () => {
730
+ onChange(null);
731
+ setPicker(false);
732
+ } : void 0,
733
+ icons,
734
+ onPickIcon: readOnly ? void 0 : pickIcon
735
+ })
736
+ ]
737
+ });
738
+ }
476
739
  if (!v) return /* @__PURE__ */ jsxs("div", {
477
740
  className: "flex flex-col gap-1.5",
478
741
  children: [
@@ -480,7 +743,7 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
480
743
  id,
481
744
  title: "Add an image",
482
745
  hint: "Or drop or paste one here",
483
- accept: "image/*",
746
+ accept,
484
747
  icon: /* @__PURE__ */ jsx(IconPhoto, { stroke: 1.5 }),
485
748
  onFiles: up.run,
486
749
  onLibrary: library,
@@ -496,11 +759,12 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
496
759
  /* @__PURE__ */ jsx(MediaPicker, {
497
760
  open: picker,
498
761
  onOpenChange: setPicker,
499
- accept: ["image", "svg"],
762
+ accept: kinds,
500
763
  onPick: (a) => a[0] && onChange(fromAsset(a[0]))
501
764
  })
502
765
  ]
503
766
  });
767
+ const frameRatio = CROPS.find((c) => c.value === cropChoice(v.crop, size))?.ratio;
504
768
  const focal = v.focal ?? {
505
769
  x: 50,
506
770
  y: 50
@@ -529,7 +793,9 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
529
793
  },
530
794
  children: [
531
795
  /* @__PURE__ */ jsxs("div", {
532
- className: "group/img relative aspect-video overflow-hidden rounded-kit-lg border border-kit-line bg-kit-muted",
796
+ "data-slot": "kit-image-frame",
797
+ className: "group/img relative overflow-hidden rounded-kit-lg border border-kit-line bg-kit-muted",
798
+ style: { aspectRatio: frameRatio && frameRatio !== "auto" ? frameRatio : "16/9" },
533
799
  children: [
534
800
  /* @__PURE__ */ jsx("button", {
535
801
  id,
@@ -537,17 +803,12 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
537
803
  disabled: readOnly,
538
804
  onClick: () => library ? library() : openDetails(),
539
805
  "aria-label": library ? `Replace ${field.title}` : `${field.title} details`,
540
- className: "block size-full outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none",
806
+ 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",
541
807
  children: /* @__PURE__ */ jsx("img", {
542
808
  src: src(v.url),
543
809
  alt: alt ?? "",
544
- onLoad: (e) => {
545
- const img = e.currentTarget;
546
- if (img.naturalWidth && img.naturalHeight) setNatural({
547
- w: img.naturalWidth,
548
- h: img.naturalHeight
549
- });
550
- },
810
+ ref: readNatural,
811
+ onLoad: (e) => readNatural(e.currentTarget),
551
812
  className: "size-full object-cover",
552
813
  style: { objectPosition: `${focal.x}% ${focal.y}%` }
553
814
  })
@@ -557,7 +818,7 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
557
818
  children: [library ? /* @__PURE__ */ jsxs("button", {
558
819
  type: "button",
559
820
  onClick: library,
560
- className: PILL,
821
+ 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",
561
822
  children: [/* @__PURE__ */ jsx(IconReplace, {
562
823
  className: "size-3.5",
563
824
  stroke: 1.5,
@@ -569,7 +830,7 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
569
830
  type: "button",
570
831
  "aria-label": "Remove image",
571
832
  onClick: () => onChange(null),
572
- className: cn(PILL, "size-7 justify-center px-0"),
833
+ 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",
573
834
  children: /* @__PURE__ */ jsx(IconX, {
574
835
  className: "size-3.5",
575
836
  stroke: 1.5,
@@ -634,22 +895,25 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
634
895
  onClick: openDetails,
635
896
  children: "Alt text and details"
636
897
  }),
637
- library ? /* @__PURE__ */ jsx(MenuItem, {
898
+ /* @__PURE__ */ jsx(MenuItem, {
638
899
  icon: /* @__PURE__ */ jsx(IconReplace, { stroke: 1.5 }),
900
+ disabled: !library,
639
901
  onClick: library,
640
902
  children: "Replace"
641
- }) : null,
903
+ }),
642
904
  /* @__PURE__ */ jsx(MenuItem, {
643
905
  icon: /* @__PURE__ */ jsx(IconExternalLink, { stroke: 1.5 }),
644
906
  onClick: () => window.open(src(v.url), "_blank", "noopener"),
645
907
  children: "Open original"
646
908
  }),
647
- readOnly ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MenuSeparator, {}), /* @__PURE__ */ jsx(MenuItem, {
909
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
910
+ /* @__PURE__ */ jsx(MenuItem, {
648
911
  danger: true,
649
912
  icon: /* @__PURE__ */ jsx(IconTrash, { stroke: 1.5 }),
650
- onClick: () => onChange(null),
913
+ disabled: readOnly,
914
+ onClick: () => !readOnly && onChange(null),
651
915
  children: "Remove"
652
- })] })
916
+ })
653
917
  ]
654
918
  })] })]
655
919
  }),
@@ -666,6 +930,7 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
666
930
  readOnly,
667
931
  label: field.title,
668
932
  urlOnly,
933
+ altOnly,
669
934
  size,
670
935
  asset
671
936
  })
@@ -673,7 +938,7 @@ function ImageControl({ field, value, onChange: write, readOnly, id, path }) {
673
938
  /* @__PURE__ */ jsx(MediaPicker, {
674
939
  open: picker,
675
940
  onOpenChange: setPicker,
676
- accept: ["image", "svg"],
941
+ accept: kinds,
677
942
  onPick: (a) => a[0] && replace(a[0])
678
943
  })
679
944
  ]
@@ -686,10 +951,11 @@ function Thumb({ item, label, readOnly, sort, onRemove, onOpen }) {
686
951
  ref: sort.register(item.key),
687
952
  role: "listitem",
688
953
  style: sort.style(item.key),
689
- className: cn("group/thumb relative aspect-square overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted", sort.active === item.key && "z-10 shadow-kit-lg ring-2 ring-kit-line-strong"),
954
+ className: cn("group/thumb relative aspect-square cursor-grab touch-none overflow-hidden rounded-kit-md border border-kit-line bg-kit-muted active:cursor-grabbing", sort.active === item.key && "z-10 opacity-90 shadow-kit-lg ring-2 ring-kit-line-strong"),
690
955
  children: [
691
956
  /* @__PURE__ */ jsx("div", {
692
957
  ...readOnly ? {} : handle,
958
+ role: void 0,
693
959
  tabIndex: 0,
694
960
  "aria-label": readOnly ? label : `${label}, drag to reorder`,
695
961
  onDoubleClick: onOpen,
@@ -706,10 +972,11 @@ function Thumb({ item, label, readOnly, sort, onRemove, onOpen }) {
706
972
  }
707
973
  if (!readOnly) handle.onKeyDown(e);
708
974
  },
709
- className: cn("size-full touch-none outline-none focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-kit-focus-ring focus-visible:[outline-style:solid] [html[data-input-modality=pointer]_&]:focus-visible:outline-none", !readOnly && "cursor-grab active:cursor-grabbing"),
975
+ 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",
710
976
  children: /* @__PURE__ */ jsx("img", {
711
977
  src: src(item.v.url),
712
978
  alt: item.v.alt ?? "",
979
+ "data-slot": "kit-gallery-thumb",
713
980
  className: "pointer-events-none size-full select-none object-cover",
714
981
  draggable: false
715
982
  })
@@ -721,10 +988,13 @@ function Thumb({ item, label, readOnly, sort, onRemove, onOpen }) {
721
988
  }) : null,
722
989
  readOnly ? null : /* @__PURE__ */ jsx("button", {
723
990
  type: "button",
724
- "aria-label": `Remove ${label}`,
991
+ "aria-label": (() => {
992
+ const what = item.v.alt || item.v.name || fileNameFromUrl(item.v.url);
993
+ return what ? `Remove ${what}` : "Remove image";
994
+ })(),
725
995
  onPointerDown: (e) => e.stopPropagation(),
726
996
  onClick: onRemove,
727
- className: "absolute right-1 top-1 flex size-6 items-center justify-center rounded-kit-md bg-kit-inverse/80 text-kit-fg-inverse opacity-0 transition-opacity focus-visible:opacity-100 group-hover/thumb:opacity-100 [@media(pointer:coarse)]:opacity-100",
997
+ 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",
728
998
  children: /* @__PURE__ */ jsx(IconX, {
729
999
  className: "size-3.5",
730
1000
  stroke: 1.5,
@@ -735,8 +1005,9 @@ function Thumb({ item, label, readOnly, sort, onRemove, onOpen }) {
735
1005
  });
736
1006
  }
737
1007
  /** An array of images: a sortable grid of tiles with a dashed "Add images" tile last (hidden at `max`). */
738
- function GalleryControl({ value, onChange, readOnly, field, id }) {
1008
+ function GalleryControl({ value, onChange, readOnly, field, id, path }) {
739
1009
  const { s, src } = useMedia();
1010
+ const env = useKitEnv();
740
1011
  const raw = Array.isArray(value) ? value : [];
741
1012
  const seen = /* @__PURE__ */ new Map();
742
1013
  const items = raw.map((x) => {
@@ -756,7 +1027,8 @@ function GalleryControl({ value, onChange, readOnly, field, id }) {
756
1027
  const add = (assets) => write([...raw, ...assets.map((a) => out(fromAsset(a)))]);
757
1028
  const [picker, setPicker] = React.useState(false);
758
1029
  const up = useUpload("image/*", "image", add);
759
- const sort = useDragReorder(items.map((it) => it.key), (from, to) => {
1030
+ const keys = items.map((it) => it.key);
1031
+ const sort = useDragReorder(keys, (from, to) => {
760
1032
  const next = [...raw];
761
1033
  const [moved] = next.splice(from, 1);
762
1034
  next.splice(to, 0, moved);
@@ -781,7 +1053,11 @@ function GalleryControl({ value, onChange, readOnly, field, id }) {
781
1053
  label: noun(i, it),
782
1054
  readOnly,
783
1055
  sort,
784
- onOpen: () => window.open(src(it.v.url), "_blank", "noopener"),
1056
+ onOpen: () => s.editImage && !readOnly ? s.editImage({
1057
+ docId: env.docId,
1058
+ path: [...path, i],
1059
+ title: noun(i, it)
1060
+ }) : window.open(src(it.v.url), "_blank", "noopener"),
785
1061
  onRemove: () => write(raw.filter((_, j) => j !== i))
786
1062
  }, it.key)), canAdd ? /* @__PURE__ */ jsx("div", {
787
1063
  role: "listitem",
@@ -894,58 +1170,59 @@ function FileControl({ value, onChange, readOnly, id }) {
894
1170
  const ext = (name.includes(".") ? name.split(".").pop() : "")?.toUpperCase() || "FILE";
895
1171
  const meta = [ext.toLowerCase(), asset?.size ? formatBytes(asset.size) : null].filter(Boolean).join(" · ");
896
1172
  return /* @__PURE__ */ jsxs("div", {
897
- className: "flex flex-col gap-1.5",
898
- children: [/* @__PURE__ */ jsxs("div", {
899
- className: "flex items-center gap-3 rounded-kit-lg border border-kit-line bg-kit-control-bg p-2",
900
- children: [
901
- /* @__PURE__ */ jsx("span", {
902
- "aria-hidden": true,
903
- 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",
904
- children: ext
905
- }),
906
- /* @__PURE__ */ jsxs("div", {
907
- className: "min-w-0 flex-1",
908
- children: [/* @__PURE__ */ jsx("a", {
909
- id,
910
- href: src(v.url),
911
- target: "_blank",
912
- rel: "noreferrer",
913
- className: "block truncate text-kit-sm font-medium text-kit-accent-fg hover:underline",
914
- children: name
915
- }), /* @__PURE__ */ jsx("div", {
916
- className: "text-kit-xs text-kit-fg-3",
917
- children: meta
918
- })]
1173
+ className: "flex items-center gap-3 rounded-kit-lg border border-kit-line bg-kit-control-bg p-2",
1174
+ children: [
1175
+ /* @__PURE__ */ jsx("span", {
1176
+ "aria-hidden": true,
1177
+ 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",
1178
+ children: ext
1179
+ }),
1180
+ /* @__PURE__ */ jsxs("div", {
1181
+ className: "min-w-0 flex-1",
1182
+ children: [/* @__PURE__ */ jsx("a", {
1183
+ id,
1184
+ href: src(v.url),
1185
+ target: "_blank",
1186
+ rel: "noreferrer",
1187
+ className: "block truncate text-kit-sm font-medium text-kit-accent-fg hover:underline",
1188
+ children: name
1189
+ }), /* @__PURE__ */ jsx("div", {
1190
+ className: "text-kit-xs text-kit-fg-3",
1191
+ children: meta
1192
+ })]
1193
+ }),
1194
+ library ? /* @__PURE__ */ jsx(Button, {
1195
+ size: "sm",
1196
+ variant: "ghost",
1197
+ onClick: library,
1198
+ children: "Replace"
1199
+ }) : null,
1200
+ /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
1201
+ render: /* @__PURE__ */ jsx(IconButton, {
1202
+ label: "File actions",
1203
+ size: "sm"
919
1204
  }),
920
- library ? /* @__PURE__ */ jsx(Button, {
921
- size: "sm",
922
- variant: "ghost",
923
- onClick: library,
924
- children: "Replace"
925
- }) : null,
926
- /* @__PURE__ */ jsxs(Menu, { children: [/* @__PURE__ */ jsx(MenuTrigger, {
927
- "aria-label": "File actions",
928
- className: "flex size-7 shrink-0 items-center justify-center rounded-kit-md text-kit-fg-3 hover:bg-kit-hover hover:text-kit-fg data-[popup-open]:bg-kit-hover",
929
- children: /* @__PURE__ */ jsx(IconDots, {
930
- className: "size-4",
931
- stroke: 1.5,
932
- "aria-hidden": true
933
- })
934
- }), /* @__PURE__ */ jsxs(MenuContent, {
935
- align: "end",
936
- children: [/* @__PURE__ */ jsx(MenuItem, {
1205
+ children: /* @__PURE__ */ jsx(IconDots, { stroke: 1.5 })
1206
+ }), /* @__PURE__ */ jsxs(MenuContent, {
1207
+ align: "end",
1208
+ children: [
1209
+ /* @__PURE__ */ jsx(MenuItem, {
937
1210
  icon: /* @__PURE__ */ jsx(IconDownload, { stroke: 1.5 }),
938
1211
  onClick: () => window.open(src(v.url), "_blank", "noopener"),
939
1212
  children: "Open"
940
- }), readOnly ? null : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MenuSeparator, {}), /* @__PURE__ */ jsx(MenuItem, {
1213
+ }),
1214
+ /* @__PURE__ */ jsx(MenuSeparator, {}),
1215
+ /* @__PURE__ */ jsx(MenuItem, {
941
1216
  danger: true,
942
1217
  icon: /* @__PURE__ */ jsx(IconTrash, { stroke: 1.5 }),
943
- onClick: () => onChange(null),
1218
+ disabled: readOnly,
1219
+ onClick: () => !readOnly && onChange(null),
944
1220
  children: "Remove"
945
- })] })]
946
- })] })
947
- ]
948
- }), pickerEl]
1221
+ })
1222
+ ]
1223
+ })] }),
1224
+ pickerEl
1225
+ ]
949
1226
  });
950
1227
  }
951
1228
  var videoProvider = (url) => /youtu/.test(url) ? "YouTube" : /vimeo/.test(url) ? "Vimeo" : /loom/.test(url) ? "Loom" : /\.(mp4|webm|mov)(\?|$)/i.test(url) ? "MP4" : url ? "Link" : "";
@@ -968,11 +1245,11 @@ function VideoPreview({ url, poster, title }) {
968
1245
  poster: thumb,
969
1246
  controls: true,
970
1247
  autoPlay: true,
971
- className: "aspect-video w-full rounded-kit-lg border border-kit-line bg-kit-inverse"
1248
+ className: "aspect-video w-full rounded-kit-lg border border-kit-line bg-kit-media-backdrop"
972
1249
  });
973
1250
  const playable = !!yt || isFileVideo(url);
974
1251
  return /* @__PURE__ */ jsxs("div", {
975
- className: "relative aspect-video overflow-hidden rounded-kit-lg border border-kit-line bg-kit-inverse",
1252
+ className: "relative aspect-video overflow-hidden rounded-kit-lg border border-kit-line bg-kit-media-backdrop",
976
1253
  children: [
977
1254
  thumb ? /* @__PURE__ */ jsx("img", {
978
1255
  src: thumb,
@@ -983,7 +1260,7 @@ function VideoPreview({ url, poster, title }) {
983
1260
  type: "button",
984
1261
  "aria-label": playable ? "Play preview" : "Open video link",
985
1262
  onClick: () => playable ? setPlaying(true) : window.open(src(url), "_blank", "noopener"),
986
- className: "absolute inset-0 m-auto flex size-12 items-center justify-center rounded-full bg-kit-control-bg text-kit-fg shadow-kit-lg transition-transform hover:scale-105",
1263
+ 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",
987
1264
  children: playable ? /* @__PURE__ */ jsx(IconPlayerPlay, {
988
1265
  className: "size-5",
989
1266
  stroke: 1.5,
@@ -995,7 +1272,7 @@ function VideoPreview({ url, poster, title }) {
995
1272
  })
996
1273
  }),
997
1274
  /* @__PURE__ */ jsxs("span", {
998
- className: "absolute left-2 top-2 inline-flex items-center gap-1 rounded-kit-md bg-kit-inverse/70 px-1.5 py-0.5 text-kit-xs text-kit-fg-inverse",
1275
+ 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",
999
1276
  children: [/* @__PURE__ */ jsx(IconVideo, {
1000
1277
  className: "size-3.5",
1001
1278
  stroke: 1.5,
@@ -1071,6 +1348,6 @@ function VideoControl({ field, value, onChange, readOnly, id, onBlur }) {
1071
1348
  });
1072
1349
  }
1073
1350
  //#endregion
1074
- export { FileControl, GalleryControl, ImageControl, VideoControl };
1351
+ export { FileControl, GalleryControl, ImageControl, MediaPicker, VideoControl, VideoPreview, acceptsFile, cropChoice, fileNameFromUrl, formatBytes, fromAsset, isVideoUrl, normImage, useUpload, videoProvider, withCrop, youTubeId };
1075
1352
 
1076
1353
  //# sourceMappingURL=media.js.map