@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":"overlay.js","names":[],"sources":["../../src/ui/overlay.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\";\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\";\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\";\nimport { PreviewCard as PreviewCardPrimitive } from \"@base-ui/react/preview-card\";\nimport { Separator } from \"@base-ui/react/separator\";\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { IconCheck, IconChevronRight, IconX } from \"@tabler/icons-react\";\nimport { AnimatePresence, motion } from \"framer-motion\";\nimport { cn } from \"../lib/cn\";\nimport { IconButton, TooltipScope } from \"./button\";\nimport { useShortcutHints } from \"./shortcut-hint\";\nimport { KIT_SCOPE } from \"./surfaces\";\nimport { MODAL_LAYER, TooltipLayer, TooltipRoot } from \"./tooltip-root\";\n\n/* Z-index scale: popover/menu 80 · modal overlay 60 / content 61 · sheet 55 · toast 100 · tooltip 90 */\n\n/** Base UI parts accept a className function; the kit takes plain strings so cn() can merge them. */\ntype Cls<P> = Omit<P, \"className\"> & { className?: string };\nconst layer = { [MODAL_LAYER]: \"\" };\n\n/* ── Dismiss guards (DESIGN.md §12) ──────────────────────────────────────────\n Every kit layer runs its close requests through keepOpen():\n - Escape owned by an inner list: an inner element that handles Escape calls event.preventDefault(); the layer\n keeps itself open. (Base UI's own nested layers already close innermost first.)\n - Floating layers portalled outside (an editor's selection toolbar, a slash menu) carry data-floating-layer:\n a press there counts as inside, so it never dismisses the layer underneath.\n - A press on a popover's anchor (the input a list hangs off) counts as inside. */\ntype CloseDetails = { reason: string; event: Event; cancel: () => void };\nexport const FLOATING_LAYER = \"[data-floating-layer]\";\nfunction keepOpen(details: CloseDetails, anchor?: Element | null) {\n const target = details.event?.target;\n const keep =\n (details.reason === \"escape-key\" && details.event.defaultPrevented) ||\n (details.reason === \"outside-press\" &&\n target instanceof Element &&\n (!!target.closest(FLOATING_LAYER) || !!anchor?.contains(target)));\n if (keep) details.cancel();\n return keep;\n}\nfunction guard<D extends CloseDetails>(onOpenChange: ((open: boolean, d: D) => void) | undefined, anchor?: () => Element | null) {\n return (open: boolean, details: D) => {\n if (!open && keepOpen(details, anchor?.())) return;\n onOpenChange?.(open, details);\n };\n}\n\n/* ── Tooltip ───────────────────────────────────────────────────────────── */\nexport const TooltipProvider = TooltipPrimitive.Provider;\nexport function Tooltip({\n content,\n children,\n side = \"top\",\n shortcut,\n delay = 350,\n disabled,\n}: {\n content: React.ReactNode;\n /** the trigger: one element that forwards its ref and spreads props */\n children: React.ReactElement;\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n /** a key hint (D44): shown only while keyboard hints are on */\n shortcut?: string;\n delay?: number;\n disabled?: boolean;\n}) {\n const hints = useShortcutHints();\n if (disabled || !content) return <TooltipScope.Provider value>{children}</TooltipScope.Provider>;\n return (\n <TooltipScope.Provider value>\n <TooltipRoot>\n <TooltipPrimitive.Trigger delay={delay} render={children} />\n {/* Fixed max width: long text (truncated titles, help) wraps into a calm block instead of a viewport-wide strip. */}\n <TooltipLayer side={side}>\n <span className=\"line-clamp-[8] min-w-0 whitespace-normal [overflow-wrap:anywhere]\">{content}</span>\n {shortcut && hints ? (\n <kbd data-hint=\"shortcuts\" className=\"mt-px shrink-0 rounded-kit-sm bg-kit-ink-active px-1 font-kit-sans text-kit-2xs\">\n {shortcut}\n </kbd>\n ) : null}\n </TooltipLayer>\n </TooltipRoot>\n </TooltipScope.Provider>\n );\n}\n\n/* ── Popover ───────────────────────────────────────────────────────────── */\nconst AnchorContext = React.createContext<React.RefObject<HTMLElement | null> | null>(null);\n\nexport function Popover({ onOpenChange, ...props }: PopoverPrimitive.Root.Props) {\n const anchor = React.useRef<HTMLElement | null>(null);\n return (\n <AnchorContext.Provider value={anchor}>\n <PopoverPrimitive.Root {...props} onOpenChange={guard(onOpenChange, () => anchor.current)} />\n </AnchorContext.Provider>\n );\n}\nexport const PopoverTrigger = PopoverPrimitive.Trigger;\nexport const PopoverClose = PopoverPrimitive.Close;\n\n/** Positions the popover against this element instead of the trigger; presses on it count as inside. */\nexport function PopoverAnchor({ render, ...props }: useRender.ComponentProps<\"div\">) {\n const anchor = React.useContext(AnchorContext);\n return useRender({ render: render ?? <div />, ref: anchor ?? undefined, props });\n}\n\nexport function PopoverContent({\n className,\n align = \"start\",\n side,\n sideOffset = 6,\n keepFocus,\n onMouseDown,\n collisionBoundary,\n collisionPadding = 12,\n collisionAvoidance,\n ...props\n}: Cls<PopoverPrimitive.Popup.Props> & {\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n sideOffset?: number;\n /** keep the popup inside this area (e.g. the scrolling panel under a sticky header) instead of the viewport */\n collisionBoundary?: PopoverPrimitive.Positioner.Props[\"collisionBoundary\"];\n collisionPadding?: PopoverPrimitive.Positioner.Props[\"collisionPadding\"];\n /** e.g. `{ align: \"shift\" }`: slide along the edge to fit instead of flipping start ↔ end (V2's Radix behaviour) */\n collisionAvoidance?: PopoverPrimitive.Positioner.Props[\"collisionAvoidance\"];\n /** §12 no-focus-steal: typing stays in the input the list hangs off. The popup takes no focus on open, gives none\n * back on close, and a mouse-down inside it never blurs the input (text fields inside the popup still focus). */\n keepFocus?: boolean;\n}) {\n const anchor = React.useContext(AnchorContext);\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Positioner\n align={align}\n side={side}\n sideOffset={sideOffset}\n collisionBoundary={collisionBoundary}\n collisionPadding={collisionPadding}\n collisionAvoidance={collisionAvoidance}\n anchor={anchor?.current ? anchor : undefined}\n className=\"z-[var(--kit-z-menu,80)]\"\n {...KIT_SCOPE}\n >\n <PopoverPrimitive.Popup\n initialFocus={keepFocus ? false : undefined}\n finalFocus={keepFocus ? false : undefined}\n onMouseDown={(e) => {\n onMouseDown?.(e);\n if (keepFocus && !(e.target as Element).closest(\"input, textarea, select, [contenteditable=true]\")) e.preventDefault();\n }}\n className={cn(\"glass w-72 rounded-kit-xl border p-3 text-kit-fg outline-none data-[open]:animate-kit-pop-in\", className)}\n {...props}\n />\n </PopoverPrimitive.Positioner>\n </PopoverPrimitive.Portal>\n );\n}\n\n/* ── Hover card ────────────────────────────────────────────────────────── */\nexport const HoverCard = PreviewCardPrimitive.Root;\nexport const HoverCardTrigger = PreviewCardPrimitive.Trigger;\nexport function HoverCardContent({ className, ...props }: Cls<PreviewCardPrimitive.Popup.Props>) {\n return (\n <PreviewCardPrimitive.Portal>\n <PreviewCardPrimitive.Positioner sideOffset={8} collisionPadding={12} className=\"z-[var(--kit-z-menu,80)]\" {...KIT_SCOPE}>\n <PreviewCardPrimitive.Popup\n className={cn(\"glass w-72 rounded-kit-xl border p-3 data-[open]:animate-kit-pop-in\", className)}\n {...props}\n />\n </PreviewCardPrimitive.Positioner>\n </PreviewCardPrimitive.Portal>\n );\n}\n\n/* ── Dropdown menu ─────────────────────────────────────────────────────── */\n/** Arrowing past the last item stays put (loopFocus false), like V2's Radix menus. */\nexport function Menu({ onOpenChange, loopFocus = false, ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root loopFocus={loopFocus} {...props} onOpenChange={guard(onOpenChange)} />;\n}\nexport const MenuTrigger = MenuPrimitive.Trigger;\nexport const MenuGroup = MenuPrimitive.Group;\nexport const MenuSub = MenuPrimitive.SubmenuRoot;\nexport const MenuRadioGroup = MenuPrimitive.RadioGroup;\n\nexport function MenuContent({\n className,\n align = \"start\",\n side,\n sideOffset = 6,\n positionerClassName,\n ...props\n}: Cls<MenuPrimitive.Popup.Props> & {\n align?: \"start\" | \"center\" | \"end\";\n side?: \"top\" | \"bottom\" | \"left\" | \"right\";\n sideOffset?: number;\n /** The layer: a menu opened from a dashboard dialog (z --z-modal) passes `z-[var(--z-dropdown)]`, or it opens behind it. */\n positionerClassName?: string;\n}) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner align={align} side={side} sideOffset={sideOffset} collisionPadding={12} className={cn(\"z-[var(--kit-z-menu,80)]\", positionerClassName)} {...KIT_SCOPE}>\n <MenuPrimitive.Popup\n {...layer}\n // capped to the room the positioner measured, so a tall menu scrolls instead of running off the window\n className={cn(\"glass max-h-[var(--available-height)] min-w-48 overflow-y-auto overflow-x-hidden rounded-kit-lg border p-1 text-kit-fg outline-none data-[open]:animate-kit-pop-in\", className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n );\n}\n\nconst itemCls =\n \"relative flex h-8 cursor-pointer select-none items-center gap-2 rounded-kit-md px-2 text-kit-sm text-kit-fg outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[highlighted]:bg-kit-hover [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-kit-fg-2\";\n\nexport function MenuItem({\n className,\n icon,\n shortcut,\n danger,\n children,\n ...props\n}: Cls<MenuPrimitive.Item.Props> & { icon?: React.ReactNode; shortcut?: string; danger?: boolean }) {\n return (\n <MenuPrimitive.Item\n className={cn(itemCls, danger && \"text-kit-danger-fg data-[highlighted]:bg-kit-danger-soft [&>svg]:text-kit-danger-fg\", className)}\n {...props}\n >\n {icon}\n <span className=\"min-w-0 flex-1 truncate\">{children}</span>\n {/* menu shortcut columns are not hints (D44): they always show */}\n {shortcut ? <span className=\"text-kit-xs text-kit-fg-3\">{shortcut}</span> : null}\n </MenuPrimitive.Item>\n );\n}\n\n/** Checking an item closes the menu, like V2's Radix items (pass closeOnClick={false} to keep it open). */\nexport function MenuCheckItem({ className, children, closeOnClick = true, ...props }: Cls<MenuPrimitive.CheckboxItem.Props>) {\n return (\n <MenuPrimitive.CheckboxItem className={cn(itemCls, \"pr-8\", className)} closeOnClick={closeOnClick} {...props}>\n {children}\n <MenuPrimitive.CheckboxItemIndicator className=\"absolute right-2\">\n <IconCheck className=\"size-4\" />\n </MenuPrimitive.CheckboxItemIndicator>\n </MenuPrimitive.CheckboxItem>\n );\n}\n\nexport function MenuRadioItem({ className, children, closeOnClick = true, ...props }: Cls<MenuPrimitive.RadioItem.Props>) {\n return (\n <MenuPrimitive.RadioItem className={cn(itemCls, \"pr-8\", className)} closeOnClick={closeOnClick} {...props}>\n {children}\n <MenuPrimitive.RadioItemIndicator className=\"absolute right-2\">\n <IconCheck className=\"size-4\" />\n </MenuPrimitive.RadioItemIndicator>\n </MenuPrimitive.RadioItem>\n );\n}\n\nexport function MenuSubTrigger({\n className,\n icon,\n children,\n ...props\n}: Cls<MenuPrimitive.SubmenuTrigger.Props> & { icon?: React.ReactNode }) {\n return (\n <MenuPrimitive.SubmenuTrigger className={cn(itemCls, \"data-[popup-open]:bg-kit-hover\", className)} {...props}>\n {icon}\n <span className=\"flex-1\">{children}</span>\n <IconChevronRight className=\"size-3.5 text-kit-fg-3\" />\n </MenuPrimitive.SubmenuTrigger>\n );\n}\nexport function MenuSubContent({ className, ...props }: Cls<MenuPrimitive.Popup.Props>) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner sideOffset={6} collisionPadding={12} className=\"z-[calc(var(--kit-z-menu,80)_+_1)]\" {...KIT_SCOPE}>\n <MenuPrimitive.Popup\n className={cn(\"glass min-w-44 rounded-kit-lg border p-1 data-[open]:animate-kit-pop-in\", className)}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n );\n}\nexport function MenuLabel({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"px-2 pb-1 pt-1.5 text-kit-xs font-medium text-kit-fg-3\", className)} {...props} />;\n}\nexport function MenuSeparator({ className }: { className?: string }) {\n return <Separator className={cn(\"-mx-1 my-1 h-px bg-kit-line\", className)} />;\n}\n\n/* ── Focus return (a11y) ───────────────────────────────────────────────────\n A dialog library remembers the focused element when the dialog opens and refocuses it on close. When a field\n inside autofocuses, that element is already the field, so focus fell to <body> on close. We keep the last few\n focused elements and hand focus back to the real trigger: the newest one that is outside the popup and still\n in the document. Without one, the library's default applies. */\nconst recent: HTMLElement[] = [];\nif (typeof document !== \"undefined\") {\n document.addEventListener(\n \"focusin\",\n (e) => {\n recent.unshift(e.target as HTMLElement);\n recent.length = Math.min(recent.length, 4);\n },\n true,\n );\n}\ntype FinalFocus = DialogPrimitive.Popup.Props[\"finalFocus\"];\nexport function useFocusReturn(finalFocus?: FinalFocus): {\n ref: (el: HTMLElement | null) => void;\n finalFocus: NonNullable<FinalFocus>;\n} {\n const ret = React.useRef<HTMLElement | null>(null);\n const popup = React.useRef<HTMLElement | null>(null);\n const ref = React.useCallback((el: HTMLElement | null) => {\n // Capture once per open (per popup element). A callback ref can be called again on a re-render while open, when\n // focus is already inside the popup and the trigger may have dropped out of `recent`.\n if (el === popup.current) return;\n popup.current = el;\n if (!el) return;\n const active = document.activeElement as HTMLElement | null;\n const outside = (n: HTMLElement | null): n is HTMLElement => !!n && n !== document.body && !el.contains(n);\n ret.current = outside(active) ? active : (recent.find(outside) ?? null);\n }, []);\n return {\n ref,\n finalFocus:\n finalFocus ??\n (() => {\n const t = ret.current;\n return t && t.isConnected ? t : true;\n }),\n };\n}\n\n/** One stable callback ref for both refs, so React does not detach and re-attach them on every render. */\nfunction useMergedRef<T>(a: React.Ref<T> | undefined, b: React.Ref<T> | undefined) {\n return React.useCallback(\n (el: T | null) => {\n for (const r of [a, b]) {\n if (typeof r === \"function\") r(el);\n else if (r) (r as React.RefObject<T | null>).current = el;\n }\n },\n [a, b],\n );\n}\n\n/* ── Modal (Dialog) ────────────────────────────────────────────────────── */\nexport function Modal({ onOpenChange, ...props }: DialogPrimitive.Root.Props) {\n return <DialogPrimitive.Root {...props} onOpenChange={guard(onOpenChange)} />;\n}\nexport const ModalTrigger = DialogPrimitive.Trigger;\nexport const ModalClose = DialogPrimitive.Close;\n\nconst sizes = {\n sm: \"max-w-[400px]\",\n md: \"max-w-[480px]\",\n lg: \"max-w-[640px]\",\n xl: \"max-w-[800px]\",\n full: \"max-w-[min(1280px,calc(100vw-48px))] h-[min(860px,calc(100vh-48px))]\",\n};\n\nexport function ModalContent({\n className,\n size = \"md\",\n children,\n hideClose,\n finalFocus,\n ref,\n ...props\n}: Cls<DialogPrimitive.Popup.Props> & { size?: keyof typeof sizes; hideClose?: boolean }) {\n const focusReturn = useFocusReturn(finalFocus);\n const merged = useMergedRef(ref, focusReturn.ref);\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Backdrop\n {...KIT_SCOPE}\n className=\"fixed inset-0 z-[var(--kit-z-modal,60)] bg-kit-overlay backdrop-blur-[2px] data-[open]:animate-kit-fade-in\"\n />\n <div {...KIT_SCOPE} className=\"pointer-events-none fixed inset-0 z-[calc(var(--kit-z-modal,60)_+_1)] flex items-center justify-center p-4 sm:p-6\">\n <DialogPrimitive.Popup\n {...layer}\n className={cn(\n \"pointer-events-auto relative flex max-h-[calc(100vh-32px)] w-full flex-col overflow-hidden rounded-kit-xl border border-kit-floating-line bg-kit-surface-raised text-kit-fg shadow-kit-xl outline-none data-[open]:animate-kit-pop-in\",\n sizes[size],\n className,\n )}\n {...props}\n ref={merged}\n finalFocus={focusReturn.finalFocus}\n >\n {children}\n {hideClose ? null : (\n <DialogPrimitive.Close render={<IconButton label=\"Close\" size=\"sm\" className=\"absolute right-3 top-3 z-10\" />}>\n <IconX />\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Popup>\n </div>\n </DialogPrimitive.Portal>\n );\n}\n\nexport function ModalHeader({\n title,\n description,\n className,\n children,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n /** D15: no icon tiles in dialog headers (accepted for compatibility, intentionally not rendered) */\n icon?: React.ReactNode;\n className?: string;\n children?: React.ReactNode;\n}) {\n return (\n <div className={cn(\"flex shrink-0 items-start gap-2.5 px-5 pb-1 pt-5 pr-12\", className)}>\n <div className=\"min-w-0 flex-1\">\n <DialogPrimitive.Title className=\"text-kit-md font-semibold tracking-[-0.01em] text-kit-fg\">{title}</DialogPrimitive.Title>\n {description ? (\n <DialogPrimitive.Description className=\"mt-1 text-kit-sm text-kit-fg-2\">{description}</DialogPrimitive.Description>\n ) : (\n <DialogPrimitive.Description className=\"sr-only\">{typeof title === \"string\" ? title : \"Dialog\"}</DialogPrimitive.Description>\n )}\n {children}\n </div>\n </div>\n );\n}\nexport function ModalBody({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return <div className={cn(\"min-h-0 flex-1 overflow-y-auto px-5 pb-5 pt-4\", className)} {...props} />;\n}\nexport function ModalFooter({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn(\"flex shrink-0 items-center justify-end gap-2 border-t border-kit-editor-tray-line bg-tray px-5 py-3\" /* action tray (Figma 61014:66265) */, className)}\n {...props}\n />\n );\n}\n\n/* ── Flow modal (V2 features/flows/parts/modal.tsx) ────────────────────────\n The shell every multi-step flow uses: a centered dialog on ≥sm, a full-screen sheet on mobile; it hugs its\n content (D15) and only caps the height. Not ModalContent: no fixed corner close, bg-kit-surface (not raised),\n a mobile sheet, `height` caps, and `locked` while a run is in progress. */\n// D15: md 480 · lg 640 · xl 800 (editors/previews) · 2xl 960 (side-by-side previews only)\nconst flowWidths = {\n md: \"sm:max-w-[480px]\",\n lg: \"sm:max-w-[640px]\",\n xl: \"sm:max-w-[800px]\",\n \"2xl\": \"sm:max-w-[960px]\",\n};\n\nexport function FlowModal({\n open,\n onOpenChange,\n size = \"lg\",\n height = \"fixed\",\n locked,\n children,\n className,\n}: {\n open: boolean;\n onOpenChange: (v: boolean) => void;\n size?: keyof typeof flowWidths;\n /** fixed = stable height for multi-step flows; auto = hug content */\n height?: \"fixed\" | \"auto\" | \"tall\";\n /** while true, outside-click / escape / the close button do nothing (a run is in progress) */\n locked?: boolean;\n children: React.ReactNode;\n className?: string;\n}) {\n // D15: dialogs hug their content — no tall empty canvases. \"fixed\"/\"tall\" only cap the height.\n const h =\n height === \"fixed\"\n ? \"sm:h-auto sm:max-h-[min(640px,calc(100dvh-48px))]\"\n : height === \"tall\"\n ? \"sm:h-auto sm:max-h-[min(760px,calc(100dvh-48px))]\"\n : \"sm:h-auto sm:max-h-[calc(100dvh-48px)]\";\n // Land focus on the dialog itself, not the close button (it showed as a bordered square on open).\n const popup = React.useRef<HTMLDivElement | null>(null);\n const focusReturn = useFocusReturn();\n const merged = useMergedRef(popup, focusReturn.ref);\n return (\n <DialogPrimitive.Root\n open={open}\n disablePointerDismissal={locked}\n onOpenChange={guard((v: boolean, details: DialogPrimitive.Root.ChangeEventDetails) => {\n if (!v && locked) return details.cancel();\n onOpenChange(v);\n })}\n >\n <DialogPrimitive.Portal>\n <DialogPrimitive.Backdrop\n {...KIT_SCOPE}\n className=\"fixed inset-0 z-[var(--kit-z-modal,60)] bg-kit-overlay backdrop-blur-[2px] data-[open]:animate-kit-fade-in\"\n />\n <div {...KIT_SCOPE} className=\"pointer-events-none fixed inset-0 z-[calc(var(--kit-z-modal,60)_+_1)] flex items-end justify-center sm:items-center sm:p-6\">\n <DialogPrimitive.Popup\n {...layer}\n ref={merged}\n tabIndex={-1}\n initialFocus={popup}\n finalFocus={focusReturn.finalFocus}\n className={cn(\n \"pointer-events-auto relative flex h-dvh w-full flex-col overflow-hidden bg-kit-surface text-kit-fg shadow-kit-xl outline-none\",\n \"max-sm:data-[open]:animate-kit-slide-up\",\n \"sm:rounded-kit-xl sm:border sm:border-kit-line sm:data-[open]:animate-kit-pop-in\",\n flowWidths[size],\n h,\n className,\n )}\n >\n {children}\n </DialogPrimitive.Popup>\n </div>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n );\n}\n\nexport function FlowClose({ disabled }: { disabled?: boolean }) {\n return (\n <DialogPrimitive.Close disabled={disabled} render={<IconButton label=\"Close\" size=\"sm\" className=\"shrink-0\" disabled={disabled} />}>\n <IconX />\n </DialogPrimitive.Close>\n );\n}\n\nexport function FlowHeader({\n title,\n description,\n icon,\n status,\n right,\n children,\n className,\n closeDisabled,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n status?: React.ReactNode;\n right?: React.ReactNode;\n children?: React.ReactNode;\n className?: string;\n closeDisabled?: boolean;\n}) {\n return (\n <div className={cn(\"relative shrink-0 border-b border-kit-line px-5 pb-3 pt-4\", className)}>\n {/* D15: no icon tile in dialog headers (icon prop kept for compatibility, intentionally not rendered) */}\n <div className=\"flex items-start gap-3\" data-icon={icon ? \"\" : undefined}>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1\">\n <DialogPrimitive.Title className=\"text-kit-md font-semibold tracking-[-0.01em] text-kit-fg\">{title}</DialogPrimitive.Title>\n {status}\n </div>\n {description ? (\n <DialogPrimitive.Description className=\"mt-0.5 text-kit-sm text-kit-fg-2\">{description}</DialogPrimitive.Description>\n ) : (\n <DialogPrimitive.Description className=\"sr-only\">{typeof title === \"string\" ? title : \"Dialog\"}</DialogPrimitive.Description>\n )}\n </div>\n <div className=\"flex shrink-0 items-center gap-1\">\n {right}\n <FlowClose disabled={closeDisabled} />\n </div>\n </div>\n {children}\n </div>\n );\n}\n\n/** Status chip used in flow headers (\"Ready to publish\" with a green dot). */\nexport function HeaderStatus({\n tone = \"success\",\n children,\n pulse,\n}: {\n tone?: \"success\" | \"warning\" | \"danger\" | \"info\" | \"accent\" | \"neutral\";\n children: React.ReactNode;\n pulse?: boolean;\n}) {\n const dot = { success: \"bg-kit-success\", warning: \"bg-kit-warning\", danger: \"bg-kit-danger\", info: \"bg-kit-info\", accent: \"bg-kit-accent\", neutral: \"bg-kit-fg-4\" }[tone];\n const fg = {\n success: \"text-kit-success-fg\",\n warning: \"text-kit-warning-fg\",\n danger: \"text-kit-danger-fg\",\n info: \"text-kit-info-fg\",\n accent: \"text-kit-accent-fg\",\n neutral: \"text-kit-fg-2\",\n }[tone];\n return (\n <span className={cn(\"inline-flex h-6 items-center gap-1.5 rounded-full border border-kit-line bg-kit-subtle px-2 text-kit-xs font-medium\", fg)}>\n <span className=\"relative inline-flex size-1.5\">\n {pulse ? <span className={cn(\"absolute inset-0 animate-ping rounded-full opacity-60\", dot)} /> : null}\n <span className={cn(\"relative inline-flex size-1.5 rounded-full\", dot)} />\n </span>\n {children}\n </span>\n );\n}\n\nexport function FlowBody({ className, children }: { className?: string; children: React.ReactNode }) {\n return <div className={cn(\"min-h-0 flex-1 overflow-y-auto overflow-x-hidden px-4 py-4 sm:px-5\", className)}>{children}</div>;\n}\n\nexport function FlowFooter({ left, children, className }: { left?: React.ReactNode; children?: React.ReactNode; className?: string }) {\n return (\n <div\n className={cn(\n \"flex shrink-0 flex-wrap items-center gap-2 border-t border-kit-editor-tray-line bg-tray px-4 py-3 pb-[max(12px,env(safe-area-inset-bottom))] sm:px-5\", // action tray (Figma 61014:66265)\n className,\n )}\n >\n {left ? <div className=\"min-w-0 flex-1 truncate text-kit-sm text-kit-fg-3 max-sm:basis-full\">{left}</div> : <div className=\"flex-1\" />}\n <div className=\"flex flex-wrap items-center justify-end gap-2 max-sm:w-full\">{children}</div>\n </div>\n );\n}\n\n/** Small uppercase-free section label used inside flow bodies. */\nexport function FlowLabel({ children, right, className }: { children: React.ReactNode; right?: React.ReactNode; className?: string }) {\n return (\n <div className={cn(\"mb-2 flex items-center justify-between gap-2\", className)}>\n <h3 className=\"text-kit-sm font-medium text-kit-fg-2\">{children}</h3>\n {right}\n </div>\n );\n}\n\n/** Radio-like option row (Figma \"Publish scope\" / \"When\" rows). */\nexport function OptionRow({\n selected,\n onSelect,\n title,\n description,\n right,\n disabled,\n children,\n className,\n}: {\n selected: boolean;\n onSelect: () => void;\n title: React.ReactNode;\n description?: React.ReactNode;\n right?: React.ReactNode;\n disabled?: boolean;\n children?: React.ReactNode;\n className?: string;\n}) {\n return (\n <div\n className={cn(\n \"rounded-kit-lg border bg-kit-surface transition-[border-color,box-shadow,background-color] duration-150\",\n selected ? \"border-kit-line-strong bg-kit-selected\" : \"border-kit-line hover:border-kit-line-strong hover:bg-kit-subtle-2\",\n disabled && \"pointer-events-none opacity-50\",\n className,\n )}\n >\n <button type=\"button\" onClick={onSelect} aria-pressed={selected} disabled={disabled} className=\"flex w-full items-center gap-3 px-3 py-2.5 text-left\">\n <span\n className={cn(\n \"flex size-4 shrink-0 items-center justify-center rounded-full border transition-colors\",\n selected ? \"border-kit-inverse bg-kit-inverse\" : \"border-kit-line-strong bg-kit-surface\",\n )}\n >\n {selected ? <span className=\"size-1.5 rounded-full bg-kit-surface\" /> : null}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-kit-sm font-medium text-kit-fg\">{title}</span>\n {description ? <span className=\"block text-kit-sm text-kit-fg-2\">{description}</span> : null}\n </span>\n {right}\n </button>\n <AnimatePresence initial={false}>\n {selected && children ? (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: 0.2, ease: [0.22, 1, 0.36, 1] }}\n className=\"overflow-hidden\"\n >\n <div className=\"px-3 pb-3 pl-[40px]\">{children}</div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/** Progressive disclosure: advanced choices tucked behind \"More options\" (CPO D6). */\nexport function MoreOptions({\n children,\n label = \"More options\",\n summary,\n defaultOpen = false,\n className,\n}: {\n children: React.ReactNode;\n label?: string;\n summary?: React.ReactNode;\n defaultOpen?: boolean;\n className?: string;\n}) {\n const [open, setOpen] = React.useState(defaultOpen);\n return (\n <div className={className}>\n <button\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n className=\"group flex w-full min-w-0 items-center gap-2 whitespace-nowrap rounded-kit-md py-1 text-left text-kit-sm font-medium text-kit-fg-2 hover:text-kit-fg\"\n >\n <span\n className={cn(\n \"flex size-5 items-center justify-center rounded-kit-md border border-kit-line bg-kit-surface text-kit-fg-3 transition-transform duration-200\",\n open && \"rotate-90\",\n )}\n >\n <svg viewBox=\"0 0 16 16\" className=\"size-3\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.75} aria-hidden>\n <path d=\"M6 4l4 4-4 4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n {label}\n {summary && !open ? <span className=\"ml-1 truncate text-kit-xs font-normal text-kit-fg-3\">{summary}</span> : null}\n </button>\n <AnimatePresence initial={false}>\n {open ? (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n transition={{ duration: 0.22, ease: [0.22, 1, 0.36, 1] }}\n className=\"overflow-hidden\"\n >\n <div className=\"pt-3\">{children}</div>\n </motion.div>\n ) : null}\n </AnimatePresence>\n </div>\n );\n}\n\n/* ── Sheet (side or bottom drawer) ─────────────────────────────────────── */\n/** A sheet is a dialog that slides in from an edge: open it with Sheet (= Modal) and its trigger. */\nexport const Sheet = Modal;\nexport const SheetTrigger = DialogPrimitive.Trigger;\nexport const SheetClose = DialogPrimitive.Close;\n/* V2 overlay.tsx:353-354. V2's cn() lets the side's later border-line win over border-floating-line: the sheet edge is\n --line in both themes. */\nconst sheetBase = \"fixed inset-y-0 z-[calc(var(--kit-z-sheet,55)_+_1)] flex flex-col bg-kit-surface-raised shadow-kit-xl outline-none transition-transform border-kit-floating-line\";\nconst sheetSides = {\n // V2: the sheet-in keyframe (24px slide + fade, 260ms ease-out-soft) on open; no exit motion\n right: \"right-0 border-l border-kit-line data-[open]:animate-[kit-sheet-in-r_260ms_var(--kit-ease-out-soft)]\",\n left: \"left-0 border-r border-kit-line data-[open]:animate-[kit-sheet-in-l_260ms_var(--kit-ease-out-soft)]\",\n // V2 TabletSheet / CommentsSheet / HistorySheet (editor.tsx:443-513): 52% tall, rounded-t-2xl, border-t, rises from\n // y 100% (V2's spring 420/42 settles in ~300ms with no overshoot; the drawer curve matches it without a motion import)\n bottom:\n \"inset-x-0 inset-y-auto bottom-0 h-[52%] overflow-hidden rounded-t-kit-2xl border-t border-kit-line data-[open]:animate-[kit-sheet-in-b_300ms_cubic-bezier(0.32,0.72,0,1)]\",\n} as const;\n/** How far a bottom sheet's grabber must be pulled down before letting go closes it (V2 editor.tsx). */\nconst SHEET_SWIPE_CLOSE_PX = 80;\n\n/**\n * A bottom sheet's grabber as a drag handle (V2 TabletSheet / CommentsSheet drag=\"y\"): pulled down past\n * SHEET_SWIPE_CLOSE_PX it closes the sheet, short of it the sheet eases back. The sheet follows the finger through a\n * transform written straight to the element (no re-render per move). Not a tab stop: Esc is the keyboard's way out.\n */\nfunction SheetGrabber({ sheet }: { sheet: React.RefObject<HTMLElement | null> }) {\n const close = React.useRef<HTMLButtonElement | null>(null);\n const drag = React.useRef<{ id: number; y: number; dy: number } | null>(null);\n const settle = (el: HTMLElement) => {\n const reduce = document.documentElement.hasAttribute(\"data-reduce-motion\") || !!window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n el.style.transition = reduce ? \"none\" : \"transform 200ms cubic-bezier(0.32, 0.72, 0, 1)\";\n el.style.transform = \"\";\n };\n return (\n <div className=\"flex shrink-0 justify-center pt-2\">\n <div\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Drag down to close\"\n data-sheet-handle=\"\"\n className=\"hit-area [--hit-size:24px] flex h-6 w-16 cursor-grab touch-none items-start justify-center active:cursor-grabbing\"\n onClick={(e) => {\n // a drag is not a tap: the click that follows the release must not close a sheet that eased back\n if (e.currentTarget.dataset.dragged !== undefined) delete e.currentTarget.dataset.dragged;\n else close.current?.click();\n }}\n onPointerDown={(e) => {\n if (e.button !== 0) return;\n drag.current = { id: e.pointerId, y: e.clientY, dy: 0 };\n e.currentTarget.setPointerCapture?.(e.pointerId);\n if (sheet.current) sheet.current.style.transition = \"none\";\n }}\n onPointerMove={(e) => {\n const d = drag.current;\n if (!d || d.id !== e.pointerId || !sheet.current) return;\n d.dy = Math.max(0, e.clientY - d.y);\n sheet.current.style.transform = `translateY(${d.dy}px)`;\n }}\n onPointerUp={(e) => {\n const d = drag.current;\n drag.current = null;\n if (!d || d.id !== e.pointerId) return;\n if (d.dy > SHEET_SWIPE_CLOSE_PX) close.current?.click();\n else if (sheet.current) settle(sheet.current);\n if (d.dy > 4) e.currentTarget.dataset.dragged = \"\";\n }}\n onPointerCancel={() => {\n drag.current = null;\n if (sheet.current) settle(sheet.current);\n }}\n >\n <span data-sheet-grabber className=\"h-1 w-10 rounded-full bg-kit-line-strong\" />\n </div>\n <DialogPrimitive.Close ref={close} hidden tabIndex={-1} aria-hidden />\n </div>\n );\n}\n\nexport function SheetContent({\n className,\n side = \"right\",\n children,\n width = 440,\n label = \"Panel\",\n noScrim = false,\n finalFocus,\n ref,\n style,\n backdropClassName,\n keepMounted = false,\n ...props\n}: Cls<DialogPrimitive.Popup.Props> & {\n side?: keyof typeof sheetSides;\n /** side sheets only: the panel width in px (a bottom sheet spans the viewport) */\n width?: number;\n /** the dialog's accessible name (V2's tablet inspector sheet is \"Inspector\") */\n label?: string;\n /** no backdrop: the page behind stays visible and, with <Sheet modal={false}>, live (V2's Comments and History sheets) */\n noScrim?: boolean;\n style?: React.CSSProperties;\n /** extra classes for the backdrop, a sibling portal: a host that themes its own scope (light/dark) passes the same class here */\n backdropClassName?: string;\n /** keep the content mounted (hidden) while closed: a host whose content holds live state, like the editor's inspector */\n keepMounted?: boolean;\n}) {\n const focusReturn = useFocusReturn(finalFocus);\n const popup = React.useRef<HTMLDivElement | null>(null);\n const merged = useMergedRef(useMergedRef(ref, focusReturn.ref), popup);\n const bottom = side === \"bottom\";\n return (\n <DialogPrimitive.Portal keepMounted={keepMounted}>\n {noScrim ? null : (\n <DialogPrimitive.Backdrop {...KIT_SCOPE} className={cn(\"fixed inset-0 z-[var(--kit-z-sheet,55)] bg-kit-overlay data-[open]:animate-kit-fade-in\", backdropClassName)} />\n )}\n <DialogPrimitive.Popup\n {...KIT_SCOPE}\n {...layer}\n style={bottom ? style : { width: `min(${width}px, 100vw)`, ...style }}\n className={cn(sheetBase, sheetSides[side], className)}\n {...props}\n ref={merged}\n finalFocus={focusReturn.finalFocus}\n >\n <DialogPrimitive.Title className=\"sr-only\">{label}</DialogPrimitive.Title>\n <DialogPrimitive.Description className=\"sr-only\">{bottom ? \"Bottom panel\" : \"Side panel\"}</DialogPrimitive.Description>\n {bottom ? <SheetGrabber sheet={popup} /> : null}\n {children}\n </DialogPrimitive.Popup>\n </DialogPrimitive.Portal>\n );\n}\n"],"mappings":"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"}
@@ -2,10 +2,10 @@ import { cn } from "../lib/cn.js";
2
2
  import { IconButton } from "./button.js";
3
3
  import { Menu as Menu$1, MenuContent, MenuTrigger, Tooltip } from "./overlay.js";
4
4
  import * as React from "react";
5
- import { IconArrowLeft, IconChevronDown, IconChevronRight } from "@tabler/icons-react";
6
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+ import { IconArrowLeft, IconChevronDown, IconChevronRight } from "@tabler/icons-react";
7
7
  import { Menu } from "@base-ui/react/menu";
8
- //#region src/kit/ui/path-crumbs.tsx
8
+ //#region src/ui/path-crumbs.tsx
9
9
  /**
10
10
  * PATH CRUMBS (CPO D38): the one breadcrumb for every drill-in path: Visuals inspector, Block Kit drill-in,
11
11
  * nested documents, media details, the workspace top bar.
@@ -526,7 +526,41 @@ function PathRow({ c, depth, current }) {
526
526
  }) : null
527
527
  ] });
528
528
  }
529
+ function PathCrumbSpecimen({ state, label, icon, group, size = "sm" }) {
530
+ const m = METRICS[size];
531
+ return /* @__PURE__ */ jsx("span", {
532
+ className: cn("inline-flex items-center", m.text),
533
+ children: /* @__PURE__ */ jsxs("span", {
534
+ className: cn(PILL, m.pill, "pointer-events-none", {
535
+ rest: "",
536
+ hover: "bg-kit-hover text-kit-fg",
537
+ pressed: "bg-kit-selected text-kit-fg",
538
+ focus: "shadow-[0_0_0_2px_var(--kit-surface),0_0_0_4px_var(--kit-focus-ring)]",
539
+ open: "bg-kit-selected text-kit-fg",
540
+ current: "font-semibold text-kit-fg hover:bg-transparent [&_[data-crumb-icon]]:text-kit-fg-2",
541
+ disabled: "text-kit-fg-4 hover:bg-transparent hover:text-kit-fg-4"
542
+ }[state]),
543
+ children: [
544
+ icon ? /* @__PURE__ */ jsx("span", {
545
+ "data-crumb-icon": true,
546
+ className: cn("flex shrink-0 items-center", m.icon),
547
+ "aria-hidden": true,
548
+ children: icon
549
+ }) : null,
550
+ /* @__PURE__ */ jsx("span", { children: label }),
551
+ group ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
552
+ className: "tabular-nums",
553
+ children: ["+", group]
554
+ }), /* @__PURE__ */ jsx(IconChevronDown, {
555
+ className: cn("-mx-0.5 shrink-0 text-kit-fg-4", m.sep),
556
+ stroke: 1.75,
557
+ "aria-hidden": true
558
+ })] }) : null
559
+ ]
560
+ })
561
+ });
562
+ }
529
563
  //#endregion
530
- export { PathCrumbs };
564
+ export { PathCrumbSpecimen, PathCrumbs, clipWords, middleEllipsis, plansFor };
531
565
 
532
566
  //# sourceMappingURL=path-crumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path-crumbs.js","names":[],"sources":["../../src/ui/path-crumbs.tsx"],"sourcesContent":["/**\n * PATH CRUMBS (CPO D38): the one breadcrumb for every drill-in path: Visuals inspector, Block Kit drill-in,\n * nested documents, media details, the workspace top bar.\n *\n * <PathCrumbs items={[{ id, label, icon, onSelect }, …, current]} />\n *\n * Look (D38 v3): ancestors fg-3 with an invisible 4px-radius pill that appears on hover (bg-hover) and darkens while\n * pressed (bg-selected); the current item is fg/semibold with its icon, NO box; thin fg-4 chevrons flush between pills (6px from text);\n * the fold chip is a ghost crumb (\"Columns… +2 ⌄\") whose open state is bg-selected; keyboard-only neutral focus ring.\n *\n * Back (←) and current never collapse, and every visible crumb keeps READABLE TEXT (no icon-only crumbs). The trail\n * adapts to the width it ACTUALLY has (ResizeObserver on the nav + document.fonts.ready, not viewport breakpoints),\n * using space greedily; the first plan that fits wins:\n *\n * stage 0 everything at full length\n * stage 1 long labels shorten to their first words (~16ch, word boundary: \"Seasoning & care…\", \"Columns…\"):\n * middle items root side first, then the parent, then the root\n * stage 2 the middle folds, root side first, into ONE readable chip \"[▦] Columns… +2\" (its first folded level +\n * the count) that opens the Pathway popover; the immediate parent stays out of the fold\n * stage 3 the root joins the fold, then (last) the parent\n * last the current item middle-truncates (\"Seasoning…ail kit\"), full name in a tooltip\n *\n * Every variant is measured once in a hidden mirror and the stage is picked in a layout effect, so the first paint\n * is already right (no flicker, no layout jump). The Pathway popover lists the whole path as an indented tree\n * (↑↓ · Enter · Esc, focus returns to the chip). Siblings menus on crumbs were considered and left out (D6 calm).\n *\n * Links: a crumb with `to` renders through `linkAs` (default: a plain <a href>), so a host can pass its router's Link.\n */\nimport * as React from \"react\";\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\";\nimport { IconArrowLeft, IconChevronDown, IconChevronRight } from \"@tabler/icons-react\";\nimport { cn } from \"../lib/cn\";\nimport { IconButton } from \"./button\";\nimport { Menu, MenuContent, MenuTrigger, Tooltip } from \"./overlay\";\n\n/* ── Metrics: one 2/4/6/8 scale, two densities ─────────────────────────────────────────────\n * row text pill (h · px) icon gap separator back\n * sm 28 13/20 24 · 6 14 6 12 chevron (6 to text) 28\n * md 32 14/20 28 · 8 16 6 14 chevron (8 to text) 32\n * The chevron sits flush between pills, so the text-to-chevron distance IS the pill padding (one number to tune).\n * The pill is invisible at rest; hover = bg-hover, pressed = bg-selected, radius 4. Hit areas ≥ 24px. */\nconst METRICS = {\n sm: { row: \"h-7\", text: \"text-[13px] leading-5\", pill: \"h-6 px-1.5\", cur: \"pr-0.5\", gap: \"gap-1.5\", icon: \"[&_svg]:size-3.5\", sep: \"size-3\", back: \"sm\" as const },\n md: { row: \"h-8\", text: \"text-[14px] leading-5\", pill: \"h-7 px-2\", cur: \"pr-0.5\", gap: \"gap-1.5\", icon: \"[&_svg]:size-4\", sep: \"size-3.5\", back: \"md\" as const },\n};\n/** Ancestor / group pill: fg-3 at rest, a quiet pill on hover, darker while pressed, fg-4 + inert when it can't navigate. */\nconst PILL =\n \"inline-flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-kit-sm text-kit-fg-3 transition-colors duration-100 hover:bg-kit-hover hover:text-kit-fg active:bg-kit-selected disabled:pointer-events-none disabled:text-kit-fg-4\";\n\nexport interface PathCrumb {\n /** stable key */\n id: string;\n label: string;\n /** type icon (16px glyph; sized by the crumb) */\n icon?: React.ReactNode;\n /** navigate here (ignored on the current item) */\n onSelect?: () => void;\n /** …or a link (rendered through PathCrumbs `linkAs`) */\n to?: string;\n /** a meaningful container (a block, a folder): may name the collapsed group (\"Columns +2\") */\n container?: boolean;\n /** red dot: something under this level has errors */\n errors?: number;\n}\n\nexport type PathCrumbLinkProps = React.AnchorHTMLAttributes<HTMLAnchorElement> & { to: string; ref?: React.Ref<HTMLAnchorElement> };\n\nfunction DefaultLink({ to, ...props }: PathCrumbLinkProps) {\n return <a href={to} {...props} />;\n}\n\nexport interface PathCrumbsProps {\n /** root → current; the last item is the current one */\n items: PathCrumb[];\n /** ← goes up one level. Default: the parent's onSelect/to. `false` hides it (top-bar style). */\n onBack?: (() => void) | false;\n /** tooltip/aria for ←, default \"Back to {parent}\" */\n backLabel?: string;\n /** a key hint in the ← tooltip, shown only while keyboard hints are on (D44) */\n backShortcut?: string;\n /** @deprecated (D38 v3): the current item is always text: weight + colour, never a box. Kept for call-site compat. */\n current?: \"chip\" | \"text\";\n /** nav aria-label */\n label?: string;\n size?: \"sm\" | \"md\";\n /** renders crumbs that have `to` (a router Link); must forward its ref and spread props. Default: <a href> */\n linkAs?: React.ComponentType<PathCrumbLinkProps>;\n className?: string;\n}\n\n/** Word-boundary shortening: the first 2–3 words that fit ~16ch (\"Seasoning & care kit\" → \"Seasoning & care…\",\n * \"Columns / Bento\" → \"Columns…\"). Never mid-word unless a single word is itself too long. */\nconst isJoiner = (w: string) => /^[/&·\\-–—|:,+]+$/.test(w);\nexport function clipWords(s: string, max = 16): string {\n const words = s.trim().split(/\\s+/);\n if (s.length <= 12 && words.length <= 2) return s;\n const out: string[] = [];\n for (let i = 0; i < words.length - 1; i++) {\n const next = [...out, words[i]].join(\" \");\n if (next.length > max) break;\n out.push(words[i]);\n }\n while (out.length && isJoiner(out[out.length - 1])) out.pop();\n if (!out.length) return words[0].length > max ? `${words[0].slice(0, max - 2)}…` : `${words[0]}…`;\n return `${out.join(\" \")}…`;\n}\nconst long = (s: string) => clipWords(s) !== s;\nconst clip = (s: string) => clipWords(s);\n\ntype Form = \"full\" | \"trunc\";\ntype Group = { start: number; end: number };\ntype Plan = { forms: Form[]; group: Group | null };\n\n/** Degradation order: the first plan that fits wins. Every visible crumb keeps readable text (no icon-only crumbs). */\nexport function plansFor(items: PathCrumb[]): Plan[] {\n const n = items.length;\n const plans: Plan[] = [];\n const forms: Form[] = items.map(() => \"full\");\n const push = (group: Group | null = null) => plans.push({ forms: [...forms], group: group ? { ...group } : null });\n push();\n if (n < 2) return plans;\n const parent = n - 2;\n const middle = Array.from({ length: Math.max(0, n - 2) }, (_, k) => k + 1); // 1 … n-2, root side first\n // 1 · long labels shorten to their first words: middle items root side first, then the parent, then the root\n for (const i of middle) if (i !== parent && long(items[i].label)) { forms[i] = \"trunc\"; push(); }\n if (parent >= 1 && long(items[parent].label)) { forms[parent] = \"trunc\"; push(); }\n if (long(items[0].label)) { forms[0] = \"trunc\"; push(); }\n // 2 · the middle folds, root side first, into ONE readable chip (\"Columns… +2\"); the parent stays out of it\n for (let end = 1; end <= parent - 1; end++) push({ start: 1, end });\n // 3 · the root joins the fold, then (last) the parent\n if (parent >= 1) push({ start: 0, end: parent - 1 });\n push({ start: 0, end: parent });\n return plans;\n}\n\n/** Keep the head and the tail: \"Seasoning wax & chainmail kit\" → \"Seasoning…mail kit\". */\nexport function middleEllipsis(text: string, maxPx: number, measure: (s: string) => number) {\n if (measure(text) <= maxPx) return text;\n let lo = 2;\n let hi = text.length - 1;\n let best = \"\";\n while (lo <= hi) {\n const keep = (lo + hi) >> 1;\n const head = Math.ceil(keep * 0.6);\n const s = `${text.slice(0, head).trimEnd()}…${text.slice(text.length - (keep - head)).trimStart()}`;\n if (measure(s) <= maxPx) { best = s; lo = keep + 1; } else hi = keep - 1;\n }\n return best || null;\n}\n\nlet canvas: HTMLCanvasElement | null = null;\nfunction textMeasurer(el: Element | null) {\n if (!el) return null;\n canvas ??= document.createElement(\"canvas\");\n let ctx: CanvasRenderingContext2D | null = null;\n try {\n ctx = canvas.getContext(\"2d\");\n } catch {\n return null; // no canvas (test DOM): skip the last-resort truncation\n }\n if (!ctx) return null;\n const cs = getComputedStyle(el);\n ctx.font = `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`;\n return (s: string) => ctx.measureText(s).width;\n}\n\nexport function PathCrumbs({ items, onBack, backLabel, backShortcut, label = \"Breadcrumb\", size = \"sm\", linkAs: Link = DefaultLink, className }: PathCrumbsProps) {\n const n = items.length;\n const parent = n > 1 ? items[n - 2] : undefined;\n const back = onBack === false ? undefined : onBack ?? (parent ? () => go(parent) : undefined);\n const sig = items.map((i) => `${i.id}\\u0001${i.label}\\u0001${i.icon ? 1 : 0}\\u0001${i.errors ? 1 : 0}\\u0001${i.container ? 1 : 0}`).join(\"\\u0002\");\n const plans = React.useMemo(() => plansFor(items), [sig]); // eslint-disable-line react-hooks/exhaustive-deps\n const navRef = React.useRef<HTMLElement>(null);\n const mirrorRef = React.useRef<HTMLDivElement>(null);\n const backRef = React.useRef<HTMLDivElement>(null);\n const [fit, setFit] = React.useState<{ plan: number; currentText: string | null }>({ plan: 0, currentText: null });\n\n const measure = React.useCallback(() => {\n const nav = navRef.current;\n const mirror = mirrorRef.current;\n if (!nav || !mirror) return;\n // layout widths, not painted ones: an ancestor mid-animation (scale / pop-in) must not skew the fit\n const rect = nav.getBoundingClientRect().width;\n const scale = nav.offsetWidth && rect ? rect / nav.offsetWidth : 1;\n const w = (key: string) => (mirror.querySelector<HTMLElement>(`[data-m=\"${key}\"]`)?.getBoundingClientRect().width ?? 0) / scale;\n const avail = nav.clientWidth - (backRef.current ? backRef.current.getBoundingClientRect().width / scale : 0) - 0.5;\n const sep = w(\"sep\");\n const cur = w(\"cur\");\n const widthOf = (p: Plan) => {\n const parts: number[] = [];\n if (n > 1) {\n const gk = (g: Group) => `g:${g.start}:${g.end}`;\n if (p.group?.start === 0) parts.push(w(gk(p.group)));\n else {\n parts.push(w(`0:${p.forms[0]}`));\n if (p.group) parts.push(w(gk(p.group)));\n }\n for (let i = 1; i < n - 1; i++) if (!p.group || i > p.group.end) parts.push(w(`${i}:${p.forms[i]}`));\n }\n parts.push(cur);\n return parts.reduce((a, b) => a + b, 0) + sep * (parts.length - 1);\n };\n let pick = plans.length - 1;\n let total = 0;\n for (let k = 0; k < plans.length; k++) {\n total = widthOf(plans[k]);\n if (total <= avail) { pick = k; break; }\n }\n let currentText: string | null = null;\n if (pick === plans.length - 1 && (total = widthOf(plans[pick])) > avail) {\n // last resort: middle-truncate the current item to the room that's left\n const textEl = mirror.querySelector('[data-m=\"curtext\"]');\n const textW = textEl?.getBoundingClientRect().width ?? 0;\n const room = cur - (total - avail) - (cur - textW);\n const m = textMeasurer(textEl);\n if (m && room > 24) currentText = middleEllipsis(items[n - 1].label, room, m);\n }\n setFit((f) => (f.plan === pick && f.currentText === currentText ? f : { plan: pick, currentText }));\n }, [plans, n]); // eslint-disable-line react-hooks/exhaustive-deps\n\n React.useLayoutEffect(() => {\n measure();\n }, [measure, sig]);\n React.useLayoutEffect(() => {\n const nav = navRef.current;\n if (!nav || typeof ResizeObserver === \"undefined\") return;\n const ro = new ResizeObserver(() => measure());\n ro.observe(nav);\n let alive = true;\n document.fonts?.ready.then(() => alive && measure());\n return () => {\n alive = false;\n ro.disconnect();\n };\n }, [measure]);\n\n if (!n) return null;\n const plan = plans[Math.min(fit.plan, plans.length - 1)];\n const m = METRICS[size];\n const curItem = items[n - 1];\n\n /* ── pieces (shared by the mirror and the real trail so the widths match) ── */\n const icon = (c: PathCrumb) => (c.icon ? <span className={cn(\"flex shrink-0 items-center\", m.icon)} aria-hidden>{c.icon}</span> : null);\n /* V2: the dot itself carries the name (role=\"img\" so assistive tech reads it; no hidden text in the crumb) */\n const dot = (c: PathCrumb) => (c.errors ? <span role=\"img\" aria-label=\"Has errors\" className=\"size-1.5 shrink-0 rounded-full bg-kit-danger\" /> : null);\n const crumbCls = cn(PILL, m.pill);\n const body = (c: PathCrumb, form: Form) => (\n <>\n {icon(c)}\n <span>{form === \"trunc\" ? clip(c.label) : c.label}</span>\n {dot(c)}\n </>\n );\n /** The fold chip names its first folded level (the root only when nothing else is folded): \"[▦] Columns… +2\". */\n const groupBody = (g: Group) => {\n const count = g.end - g.start + 1;\n const lead = items[g.start === 0 && g.end > 0 ? 1 : g.start];\n return (\n <>\n {icon(lead)}\n <span>{clipWords(lead.label, 12)}</span>\n {count > 1 ? <span className=\"tabular-nums\">+{count - 1}</span> : null}\n <IconChevronDown className={cn(\"-mx-0.5 shrink-0 text-kit-fg-4\", m.sep)} stroke={1.75} aria-hidden />\n </>\n );\n };\n // current = emphasis by weight + colour, never a box (D38 v3); same box metrics as a crumb so nothing shifts\n // it has no pill, so no trailing padding: only the leading inset that lines it up with the chevron rhythm\n const currentCls = cn(\"inline-flex min-w-0 max-w-full items-center whitespace-nowrap rounded-kit-sm font-semibold text-kit-fg\", m.pill, m.cur, m.gap, \"[&_[data-crumb-icon]]:text-kit-fg-2\");\n const sepEl = <IconChevronRight className={cn(\"shrink-0 text-kit-fg-4\", m.sep)} stroke={1.75} aria-hidden />;\n\n function go(c: PathCrumb) {\n c.onSelect?.();\n }\n\n const crumb = (c: PathCrumb, i: number, form: Form) => {\n const tip = form !== \"full\" || undefined;\n const inner = body(c, form);\n const aria = form === \"trunc\" ? (c.errors ? `${c.label}, has errors` : c.label) : undefined;\n const el = c.to ? (\n <Link to={c.to} className={crumbCls} aria-label={aria} onClick={c.onSelect}>{inner}</Link>\n ) : (\n <button type=\"button\" className={crumbCls} aria-label={aria} onClick={() => go(c)} disabled={!c.onSelect}>{inner}</button>\n );\n return (\n <li key={c.id} className=\"flex shrink-0 items-center\">\n {i > 0 ? sepEl : null}\n {tip ? <Tooltip content={c.label} side=\"bottom\">{el}</Tooltip> : el}\n </li>\n );\n };\n\n const shown: React.ReactNode[] = [];\n if (n > 1) {\n const g = plan.group;\n const group = (first?: boolean) => (\n <GroupLi key=\"grp\" items={items} group={g!} first={first} trigger={groupBody(g!)} sep={sepEl} navRef={navRef} label={label} cls={crumbCls} link={Link} />\n );\n if (g?.start === 0) shown.push(group(true));\n else {\n shown.push(crumb(items[0], 0, plan.forms[0]));\n if (g) shown.push(group());\n }\n for (let i = 1; i < n - 1; i++) if (!g || i > g.end) shown.push(crumb(items[i], i, plan.forms[i]));\n }\n const curLabel = fit.currentText ?? curItem.label;\n const curNode = (\n <span aria-current=\"page\" className={currentCls}>\n {curItem.icon ? <span data-crumb-icon className={cn(\"flex shrink-0 items-center\", m.icon)} aria-hidden>{curItem.icon}</span> : null}\n <span className=\"min-w-0 truncate\" aria-label={curLabel !== curItem.label ? curItem.label : undefined}>{curLabel}</span>\n {dot(curItem)}\n </span>\n );\n const backText = backLabel ?? (parent ? `Back to ${parent.label}` : \"Back\");\n\n return (\n <nav ref={navRef} aria-label={label} data-size={size} className={cn(\"relative flex min-w-0 flex-1 items-center\", m.row, m.text, className)}>\n {back ? (\n <div ref={backRef} className=\"flex shrink-0 items-center\">\n <Tooltip content={backText} shortcut={backShortcut}>\n <IconButton label={backText} size={m.back} onClick={back} className=\"shrink-0 rounded-kit-sm\">\n <IconArrowLeft stroke={1.75} />\n </IconButton>\n </Tooltip>\n </div>\n ) : null}\n <ol className=\"flex min-w-0 flex-1 items-center overflow-hidden\">\n {shown}\n <li className=\"flex min-w-0 shrink items-center\">\n {n > 1 ? sepEl : null}\n {fit.currentText || (fit.plan === plans.length - 1 && long(curItem.label)) ? (\n <Tooltip content={curItem.label} side=\"bottom\">\n <span tabIndex={0} className=\"flex min-w-0 rounded-kit-sm\">{curNode}</span>\n </Tooltip>\n ) : (\n curNode\n )}\n </li>\n </ol>\n\n {/* hidden mirror: every variant measured once (never painted, never announced) */}\n <div ref={mirrorRef} aria-hidden className=\"pointer-events-none invisible absolute left-0 top-0 h-0 w-0 overflow-hidden\">\n <div className=\"flex w-max flex-col items-start\">\n <span data-m=\"sep\" className=\"flex\">{sepEl}</span>\n {items.slice(0, -1).map((c, i) => (\n <React.Fragment key={c.id}>\n <span data-m={`${i}:full`} className={crumbCls}>{body(c, \"full\")}</span>\n <span data-m={`${i}:trunc`} className={crumbCls}>{body(c, \"trunc\")}</span>\n </React.Fragment>\n ))}\n {[0, 1].flatMap((start) =>\n items.slice(0, -1).map((_, end) =>\n end < start ? null : <span key={`g${start}:${end}`} data-m={`g:${start}:${end}`} className={crumbCls}>{groupBody({ start, end })}</span>,\n ),\n )}\n <span data-m=\"cur\" className={currentCls}>\n {curItem.icon ? <span data-crumb-icon className={cn(\"flex shrink-0 items-center\", m.icon)}>{curItem.icon}</span> : null}\n <span data-m=\"curtext\">{curItem.label}</span>\n {dot(curItem)}\n </span>\n </div>\n </div>\n </nav>\n );\n}\n\n/* ── The folded middle + its Pathway popover ───────────────────────────────────── */\nfunction GroupLi({\n items,\n group,\n trigger,\n sep,\n first,\n navRef,\n label,\n cls,\n link: Link,\n}: {\n items: PathCrumb[];\n group: Group;\n trigger: React.ReactNode;\n sep: React.ReactNode;\n first?: boolean;\n navRef: React.RefObject<HTMLElement | null>;\n label: string;\n cls: string;\n link: React.ComponentType<PathCrumbLinkProps>;\n}) {\n const count = group.end - group.start + 1;\n const last = items.length - 1;\n return (\n <li className=\"flex shrink-0 items-center\">\n {first ? null : sep}\n <Menu>\n <Tooltip content=\"Show the full path\" side=\"bottom\">\n <MenuTrigger\n data-crumb-group=\"\"\n className={cn(cls, \"aria-expanded:bg-kit-selected aria-expanded:text-kit-fg\")} /* = crumbCls: the mirror measures it */\n aria-label={`Show ${count} more ${count === 1 ? \"level\" : \"levels\"}`}\n >\n {trigger}\n </MenuTrigger>\n </Tooltip>\n {/* the kit MenuContent: §12 dismiss guards and the modal-layer marker (an open tooltip closes) */}\n <MenuContent\n align=\"start\"\n finalFocus={() => {\n // a jump re-lays the trail (or remounts the host) and the chip may be gone: land on the trail's chip,\n // ← or current item instead of <body>\n requestAnimationFrame(() => {\n const nav = navRef.current?.isConnected ? navRef.current : document.querySelector<HTMLElement>(`nav[aria-label=\"${CSS.escape(label)}\"]`);\n if (!nav) return;\n const chip = nav.querySelector<HTMLElement>(\"[data-crumb-group]\");\n (chip ?? nav.querySelector<HTMLElement>(\"button, [aria-current], [tabindex='0']\"))?.focus({ preventScroll: true });\n });\n return false;\n }}\n className=\"w-64 max-w-[calc(100vw-24px)] text-[13px] leading-5\"\n >\n <div className=\"px-2 pb-1 pt-1 text-kit-xs font-medium text-kit-fg-3\">Pathway</div>\n {/* role=none: the menu owns its menuitems directly (no list or listitem in between) */}\n <ol role=\"none\" className=\"flex flex-col\">\n {items.map((c, i) => {\n const isCurrent = i === last;\n const hidden = i >= group.start && i <= group.end;\n const rowCls = cn(\n \"relative flex h-7 select-none items-center gap-1.5 rounded-kit-sm pr-2 outline-none transition-colors\",\n isCurrent\n ? \"cursor-default font-semibold text-kit-fg data-[highlighted]:bg-kit-hover\"\n : cn(\"cursor-pointer data-[highlighted]:bg-kit-hover data-[highlighted]:text-kit-fg active:bg-kit-selected\", hidden ? \"text-kit-fg\" : \"text-kit-fg-3\"),\n );\n const style = { paddingLeft: 8 + Math.min(i, 8) * 12 };\n return (\n <li key={c.id} role=\"none\">\n {c.to && !isCurrent ? (\n <MenuPrimitive.LinkItem\n closeOnClick\n render={<Link to={c.to} />}\n onClick={() => c.onSelect?.()}\n className={rowCls}\n style={style}\n >\n <PathRow c={c} depth={i} />\n </MenuPrimitive.LinkItem>\n ) : (\n <MenuPrimitive.Item\n onClick={() => (isCurrent ? undefined : c.onSelect?.())}\n aria-current={isCurrent ? \"page\" : undefined}\n className={rowCls}\n style={style}\n >\n <PathRow c={c} depth={i} current={isCurrent} />\n </MenuPrimitive.Item>\n )}\n </li>\n );\n })}\n </ol>\n </MenuContent>\n </Menu>\n </li>\n );\n}\n\nfunction PathRow({ c, depth, current }: { c: PathCrumb; depth: number; current?: boolean }) {\n return (\n <>\n {depth > 0 ? <span aria-hidden className=\"-mt-2 h-3 w-2 shrink-0 rounded-bl-[3px] border-b border-l border-kit-line-strong\" /> : null}\n {c.icon ? <span aria-hidden className=\"flex shrink-0 items-center text-kit-fg-3 [&_svg]:size-3.5\">{c.icon}</span> : null}\n {c.label.length > 28 ? (\n <Tooltip content={c.label} side=\"right\">\n <span className=\"min-w-0 flex-1 truncate\">{c.label}</span>\n </Tooltip>\n ) : (\n <span className=\"min-w-0 flex-1 truncate\">{c.label}</span>\n )}\n {c.errors ? <span role=\"img\" aria-label=\"Has errors\" className=\"size-1.5 shrink-0 rounded-full bg-kit-danger\" /> : null}\n {current ? <span aria-hidden className=\"size-1.5 shrink-0 rounded-full bg-kit-accent\" /> : null}\n </>\n );\n}\n\n/* ── Specimen (design system): one crumb frozen in a state, built from the SAME constants ─── */\nexport type PathCrumbState = \"rest\" | \"hover\" | \"pressed\" | \"focus\" | \"open\" | \"current\" | \"disabled\";\nexport function PathCrumbSpecimen({ state, label, icon, group, size = \"sm\" }: { state: PathCrumbState; label: string; icon?: React.ReactNode; group?: number; size?: \"sm\" | \"md\" }) {\n const m = METRICS[size];\n const forced: Record<PathCrumbState, string> = {\n rest: \"\",\n hover: \"bg-kit-hover text-kit-fg\",\n pressed: \"bg-kit-selected text-kit-fg\",\n focus: \"shadow-[0_0_0_2px_var(--kit-surface),0_0_0_4px_var(--kit-focus-ring)]\",\n open: \"bg-kit-selected text-kit-fg\",\n current: \"font-semibold text-kit-fg hover:bg-transparent [&_[data-crumb-icon]]:text-kit-fg-2\",\n disabled: \"text-kit-fg-4 hover:bg-transparent hover:text-kit-fg-4\",\n };\n return (\n <span className={cn(\"inline-flex items-center\", m.text)}>\n <span className={cn(PILL, m.pill, \"pointer-events-none\", forced[state])}>\n {icon ? <span data-crumb-icon className={cn(\"flex shrink-0 items-center\", m.icon)} aria-hidden>{icon}</span> : null}\n <span>{label}</span>\n {group ? (\n <>\n <span className=\"tabular-nums\">+{group}</span>\n <IconChevronDown className={cn(\"-mx-0.5 shrink-0 text-kit-fg-4\", m.sep)} stroke={1.75} aria-hidden />\n </>\n ) : null}\n </span>\n </span>\n );\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- //#region src/kit/ui/presence.ts
1
+ //#region src/ui/presence.ts
2
2
  /**
3
3
  * Presence colour: ONE slot per person, the same everywhere they appear (field border, avatar ring, canvas pill, caret flag,
4
4
  * History change bars). Slots are the `--kit-presence-1…8` tokens (D56); text on a presence fill is `--kit-presence-on`.
@@ -53,7 +53,7 @@ function presenceSlot(person) {
53
53
  if (hit) return hit;
54
54
  let h = 0;
55
55
  for (let i = 0; i < key.length; i++) h = h * 31 + key.charCodeAt(i) >>> 0;
56
- return 4 + h % (SLOTS - 3);
56
+ return 4 + h % 5;
57
57
  }
58
58
  /** `var(--kit-presence-n)` for that person: use as a CSS colour (border, ring, background with presence-on text). */
59
59
  function presenceColor(person) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.js","names":[],"sources":["../../src/ui/presence.ts"],"sourcesContent":["/**\n * Presence colour: ONE slot per person, the same everywhere they appear (field border, avatar ring, canvas pill, caret flag,\n * History change bars). Slots are the `--kit-presence-1…8` tokens (D56); text on a presence fill is `--kit-presence-on`.\n * Known people keep their earlier colours: priya → 1, daniel → 2, sujay → 3.\n *\n * D61: everyone else gets a slot at join, in join order, from the slots still free (all 8, not 5), so a real team rarely\n * shares a colour; once all 8 are taken the least recently assigned slot is reused. Register the workspace roster with\n * `registerPresenceRoster`. Someone not on the roster hashes stably into 4…8.\n * AI agents never take a person's slot: they use `--kit-presence-agent` (`AGENT_PRESENCE`).\n *\n * src/index.css declares the tokens app-wide (light and dark), so presenceColor() needs no fallback.\n */\nconst KNOWN: Record<string, number> = { priya: 1, daniel: 2, sujay: 3 };\nconst SLOTS = 8;\n\n/** D63: AI agents in History (change bars, outlines, tags): neutral violet-grey, never a person's slot. */\nexport const AGENT_PRESENCE = \"var(--kit-presence-agent)\";\n\nconst keyOf = (person: string) => person.trim().toLowerCase().replace(/^u_/, \"\").split(/[\\s@._-]+/)[0] ?? \"\";\n/** roster assignments: key (first name, id or email head) → slot */\nconst assigned = new Map<string, number>();\n\n/**\n * Assign slots to a workspace's members in join order (stable: the same roster always gives the same colours).\n * Each member is then found by id, full name or email.\n */\nexport function registerPresenceRoster(members: { id: string; name: string; email?: string; joinedAt?: string }[]) {\n assigned.clear();\n const order = [...members].sort((a, b) => (a.joinedAt && b.joinedAt ? a.joinedAt.localeCompare(b.joinedAt) : 0));\n const lastUse = new Map<number, number>(); // slot → assignment tick\n Object.values(KNOWN).forEach((s, i) => lastUse.set(s, i));\n let tick = 10;\n for (const m of order) {\n const keys = [m.id.toLowerCase(), keyOf(m.name), m.email ? keyOf(m.email) : \"\"].filter(Boolean);\n const known = keys.map((k) => KNOWN[k]).find(Boolean);\n let slot = known;\n if (!slot) {\n const free = Array.from({ length: SLOTS }, (_, i) => i + 1).filter((s) => !lastUse.has(s));\n // all 8 taken: reuse the least recently assigned slot\n slot = free[0] ?? [...lastUse.entries()].sort((a, b) => a[1] - b[1])[0][0];\n }\n lastUse.set(slot, tick++);\n for (const k of keys) assigned.set(k, slot);\n }\n}\n\n/** Accepts a person id (\"u_priya\", \"priya\"), a full name (\"Priya Nair\") or an email; returns the slot 1…8. */\nexport function presenceSlot(person: string): number {\n const whole = person.trim().toLowerCase();\n const key = keyOf(person);\n if (KNOWN[key]) return KNOWN[key];\n const hit = assigned.get(whole) ?? assigned.get(key);\n if (hit) return hit;\n let h = 0;\n for (let i = 0; i < key.length; i++) h = (h * 31 + key.charCodeAt(i)) >>> 0;\n return 4 + (h % (SLOTS - 3));\n}\n\n/** `var(--kit-presence-n)` for that person: use as a CSS colour (border, ring, background with presence-on text). */\nexport function presenceColor(person: string): string {\n const n = presenceSlot(person);\n return `var(--kit-presence-${n})`;\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAM,QAAgC;CAAE,OAAO;CAAG,QAAQ;CAAG,OAAO;AAAE;AACtE,IAAM,QAAQ;;AAGd,IAAa,iBAAiB;AAE9B,IAAM,SAAS,WAAmB,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,OAAO,EAAE,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC,MAAM;;AAE1G,IAAM,2BAAW,IAAI,IAAoB;;;;;AAMzC,SAAgB,uBAAuB,SAA4E;CACjH,SAAS,MAAM;CACf,MAAM,QAAQ,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,GAAG,MAAO,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,cAAc,EAAE,QAAQ,IAAI,CAAE;CAC/G,MAAM,0BAAU,IAAI,IAAoB;CACxC,OAAO,OAAO,KAAK,CAAC,CAAC,SAAS,GAAG,MAAM,QAAQ,IAAI,GAAG,CAAC,CAAC;CACxD,IAAI,OAAO;CACX,KAAK,MAAM,KAAK,OAAO;EACrB,MAAM,OAAO;GAAC,EAAE,GAAG,YAAY;GAAG,MAAM,EAAE,IAAI;GAAG,EAAE,QAAQ,MAAM,EAAE,KAAK,IAAI;EAAE,CAAC,CAAC,OAAO,OAAO;EAE9F,IAAI,OADU,KAAK,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC,KAAK,OAClC;EACX,IAAI,CAAC,MAGH,OAFa,MAAM,KAAK,EAAE,QAAQ,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,QAAQ,IAAI,CAAC,CAEjF,CAAA,CAAK,MAAM,CAAC,GAAG,QAAQ,QAAQ,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;EAE1E,QAAQ,IAAI,MAAM,MAAM;EACxB,KAAK,MAAM,KAAK,MAAM,SAAS,IAAI,GAAG,IAAI;CAC5C;AACF;;AAGA,SAAgB,aAAa,QAAwB;CACnD,MAAM,QAAQ,OAAO,KAAK,CAAC,CAAC,YAAY;CACxC,MAAM,MAAM,MAAM,MAAM;CACxB,IAAI,MAAM,MAAM,OAAO,MAAM;CAC7B,MAAM,MAAM,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG;CACnD,IAAI,KAAK,OAAO;CAChB,IAAI,IAAI;CACR,KAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,IAAK,IAAI,KAAK,IAAI,WAAW,CAAC,MAAO;CAC1E,OAAO,IAAK,IAAK;AACnB;;AAGA,SAAgB,cAAc,QAAwB;CAEpD,OAAO,sBADG,aAAa,MACM,EAAE;AACjC"}
@@ -1,13 +1,13 @@
1
1
  import { cn } from "../lib/cn.js";
2
2
  import { useFieldId, useFieldLabelledBy, useLabelFor } from "./field-context.js";
3
- import { GLASS, KIT_SCOPE } from "./surfaces.js";
3
+ import { KIT_SCOPE } from "./surfaces.js";
4
4
  import { Avatar } from "./display.js";
5
5
  import * as React from "react";
6
- import { IconCheck, IconChevronDown, IconSearch } from "@tabler/icons-react";
7
6
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
- import { Select } from "@base-ui/react/select";
7
+ import { IconCheck, IconChevronDown, IconSearch } from "@tabler/icons-react";
8
+ import { Select as Select$1 } from "@base-ui/react/select";
9
9
  import { Combobox } from "@base-ui/react/combobox";
10
- //#region src/kit/ui/select.tsx
10
+ //#region src/ui/select.tsx
11
11
  var SEARCH_THRESHOLD = 7;
12
12
  /** Plain text of a React node — lets `label` stay a ReactNode while still being searchable. */
13
13
  function nodeText(node) {
@@ -131,8 +131,7 @@ function triggerClass(variant, size) {
131
131
  }
132
132
  /** The Select trigger look, for controls that open their own picker but must read as a Select (D57: one look per job). */
133
133
  var selectTriggerClass = triggerClass;
134
- var floatingClass = cn("rounded-kit-lg border text-kit-fg outline-none data-[open]:animate-kit-pop-in", GLASS);
135
- var itemClass = "relative flex cursor-pointer select-none items-center gap-2 rounded-kit-md py-1.5 pl-2 pr-8 text-kit-sm text-kit-fg outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[highlighted]:bg-kit-hover [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-kit-fg-2";
134
+ var itemClass = cn("relative flex cursor-pointer select-none items-center gap-2 rounded-kit-md py-1.5 pl-2 pr-8 text-kit-sm text-kit-fg outline-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-kit-fg-2", "data-[disabled]:pointer-events-none data-[disabled]:opacity-40 data-[highlighted]:bg-kit-hover");
136
135
  var groupHeading = "px-2 pb-1 pt-2 text-kit-xs font-medium text-kit-fg-3";
137
136
  function Lead({ o }) {
138
137
  if (o.avatar) return /* @__PURE__ */ jsx(Avatar, {
@@ -143,7 +142,7 @@ function Lead({ o }) {
143
142
  });
144
143
  return o.icon ? /* @__PURE__ */ jsx(Fragment, { children: o.icon }) : null;
145
144
  }
146
- function Select$1(props) {
145
+ function Select(props) {
147
146
  const { searchable = "auto", options } = props;
148
147
  return searchable === true || searchable === "auto" && options.length > 7 ? /* @__PURE__ */ jsx(SearchSelect, { ...props }) : /* @__PURE__ */ jsx(PlainSelect, { ...props });
149
148
  }
@@ -176,7 +175,7 @@ function PlainSelect({ value, defaultValue, onValueChange, options, placeholder
176
175
  value: o.value,
177
176
  label: o.label
178
177
  })), [options]);
179
- const renderItem = (o) => /* @__PURE__ */ jsxs(Select.Item, {
178
+ const renderItem = (o) => /* @__PURE__ */ jsxs(Select$1.Item, {
180
179
  value: o.value,
181
180
  disabled: o.disabled,
182
181
  className: itemClass,
@@ -184,7 +183,7 @@ function PlainSelect({ value, defaultValue, onValueChange, options, placeholder
184
183
  /* @__PURE__ */ jsx(Lead, { o }),
185
184
  /* @__PURE__ */ jsxs("div", {
186
185
  className: "min-w-0 flex-1",
187
- children: [/* @__PURE__ */ jsx(Select.ItemText, { children: o.label }), o.description ? /* @__PURE__ */ jsx("div", {
186
+ children: [/* @__PURE__ */ jsx(Select$1.ItemText, { children: o.label }), o.description ? /* @__PURE__ */ jsx("div", {
188
187
  className: "text-kit-xs text-kit-fg-3",
189
188
  children: o.description
190
189
  }) : null]
@@ -193,36 +192,36 @@ function PlainSelect({ value, defaultValue, onValueChange, options, placeholder
193
192
  className: "shrink-0 text-kit-xs tabular-nums text-kit-fg-3",
194
193
  children: o.meta
195
194
  }) : null,
196
- /* @__PURE__ */ jsx(Select.ItemIndicator, {
195
+ /* @__PURE__ */ jsx(Select$1.ItemIndicator, {
197
196
  className: "absolute right-2",
198
- children: /* @__PURE__ */ jsx(IconCheck, { className: "size-4 !text-kit-fg" })
197
+ children: /* @__PURE__ */ jsx(IconCheck, { className: "size-4 text-kit-fg" })
199
198
  })
200
199
  ]
201
200
  }, o.value);
202
- return /* @__PURE__ */ jsxs(Select.Root, {
201
+ return /* @__PURE__ */ jsxs(Select$1.Root, {
203
202
  items,
204
203
  value: current ?? null,
205
204
  onValueChange: (v) => v != null && setCurrent(v),
206
205
  onOpenChange: setOpen,
207
206
  disabled,
208
- children: [/* @__PURE__ */ jsxs(Select.Trigger, {
207
+ children: [/* @__PURE__ */ jsxs(Select$1.Trigger, {
209
208
  ...a11y,
210
209
  "data-state": open ? "open" : "closed",
211
210
  className: cn(triggerClass(variant, size), triggerClassName, className),
212
211
  children: [/* @__PURE__ */ jsx("span", {
213
212
  className: "flex min-w-0 items-center gap-2 truncate [&_svg]:size-4 [&_svg]:text-kit-fg-3",
214
- children: /* @__PURE__ */ jsx(Select.Value, { placeholder })
215
- }), /* @__PURE__ */ jsx(Select.Icon, { children: /* @__PURE__ */ jsx(IconChevronDown, { className: "size-3.5 text-kit-fg-3 transition-transform group-data-[popup-open]:rotate-180" }) })]
216
- }), /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, {
213
+ children: /* @__PURE__ */ jsx(Select$1.Value, { placeholder })
214
+ }), /* @__PURE__ */ jsx(Select$1.Icon, { children: /* @__PURE__ */ jsx(IconChevronDown, { className: "size-3.5 text-kit-fg-3 transition-transform group-data-[popup-open]:rotate-180" }) })]
215
+ }), /* @__PURE__ */ jsx(Select$1.Portal, { children: /* @__PURE__ */ jsx(Select$1.Positioner, {
217
216
  align,
218
217
  sideOffset: 6,
219
218
  alignItemWithTrigger: false,
220
- className: "z-[80]",
219
+ className: "z-[var(--kit-z-menu,80)]",
221
220
  "data-floating-layer": "",
222
221
  ...KIT_SCOPE,
223
- children: /* @__PURE__ */ jsx(Select.Popup, {
224
- className: cn(floatingClass, "max-h-[min(360px,var(--available-height))] min-w-[var(--anchor-width)] overflow-y-auto p-1"),
225
- children: /* @__PURE__ */ jsx(Select.List, { children: grouped(options).map((g, gi) => g.group ? /* @__PURE__ */ jsxs(Select.Group, { children: [/* @__PURE__ */ jsx(Select.GroupLabel, {
222
+ children: /* @__PURE__ */ jsx(Select$1.Popup, {
223
+ className: "glass max-h-[min(360px,var(--available-height))] min-w-[var(--anchor-width)] overflow-y-auto rounded-kit-lg border p-1 data-[open]:animate-kit-pop-in",
224
+ children: /* @__PURE__ */ jsx(Select$1.List, { children: grouped(options).map((g, gi) => g.group ? /* @__PURE__ */ jsxs(Select$1.Group, { children: [/* @__PURE__ */ jsx(Select$1.GroupLabel, {
226
225
  className: groupHeading,
227
226
  children: g.group
228
227
  }), g.items.map(renderItem)] }, g.group + gi) : g.items.map(renderItem)) })
@@ -326,80 +325,83 @@ function SearchSelect({ value, defaultValue, onValueChange, options, placeholder
326
325
  align,
327
326
  sideOffset: 6,
328
327
  collisionPadding: 12,
329
- className: "z-[80]",
328
+ className: "z-[var(--kit-z-menu,80)]",
330
329
  "data-floating-layer": "",
331
330
  ...KIT_SCOPE,
332
- children: /* @__PURE__ */ jsxs(Combobox.Popup, {
333
- className: cn(floatingClass, "flex max-h-[min(400px,var(--available-height))] w-[max(var(--anchor-width),240px)] max-w-[min(400px,calc(100vw-24px))] flex-col overflow-hidden", menuClassName),
334
- children: [
335
- /* @__PURE__ */ jsxs("div", {
336
- className: "flex h-9 shrink-0 items-center gap-2 border-b border-kit-line-subtle px-2.5 text-kit-fg-3",
337
- children: [/* @__PURE__ */ jsx(IconSearch, {
338
- "aria-hidden": true,
339
- className: "size-4 shrink-0"
340
- }), /* @__PURE__ */ jsx(Combobox.Input, {
341
- "aria-label": typeof a11y["aria-label"] === "string" ? a11y["aria-label"] : "Options",
342
- placeholder: searchPlaceholder,
343
- className: "h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-4"
344
- })]
345
- }),
346
- shown.length === 0 ? /* @__PURE__ */ jsx("div", {
347
- className: "px-2 py-6 text-center text-kit-sm text-kit-fg-3",
348
- children: "No matches"
349
- }) : null,
350
- /* @__PURE__ */ jsx(Combobox.List, {
351
- ref: listRef,
352
- className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-1 empty:hidden",
353
- children: grouped(shown).map((g, gi) => {
354
- const items = g.items.map((o) => {
355
- const text = nodeText(o.label);
356
- const checked = o.value === current;
357
- return /* @__PURE__ */ jsxs(Combobox.Item, {
358
- value: o.value,
359
- disabled: o.disabled,
360
- "data-checked": checked,
361
- className: itemClass,
362
- children: [
363
- /* @__PURE__ */ jsx(Lead, { o }),
364
- /* @__PURE__ */ jsxs("div", {
365
- className: "min-w-0 flex-1",
366
- children: [/* @__PURE__ */ jsx("div", {
367
- className: "truncate",
368
- children: typeof o.label === "string" ? /* @__PURE__ */ jsx(Highlight, {
369
- text,
370
- query
371
- }) : o.label
372
- }), o.description ? /* @__PURE__ */ jsx("div", {
373
- className: "truncate text-kit-xs text-kit-fg-3",
374
- children: /* @__PURE__ */ jsx(Highlight, {
375
- text: o.description,
376
- query
377
- })
378
- }) : null]
379
- }),
380
- o.meta ? /* @__PURE__ */ jsx("span", {
381
- className: "shrink-0 text-kit-xs tabular-nums text-kit-fg-3",
382
- children: o.meta
383
- }) : null,
384
- checked ? /* @__PURE__ */ jsx(IconCheck, {
385
- "aria-hidden": true,
386
- className: "absolute right-2 size-4 !text-kit-fg"
387
- }) : null
388
- ]
389
- }, o.value);
390
- });
391
- return g.group ? /* @__PURE__ */ jsxs(Combobox.Group, { children: [/* @__PURE__ */ jsx(Combobox.GroupLabel, {
392
- className: groupHeading,
393
- children: g.group
394
- }), items] }, g.group + gi) : /* @__PURE__ */ jsx(React.Fragment, { children: items }, "g" + gi);
331
+ children: /* @__PURE__ */ jsx(Combobox.Popup, {
332
+ className: cn("glass flex max-h-[min(400px,var(--available-height))] w-[max(var(--anchor-width),240px)] max-w-[min(400px,calc(100vw-24px))] flex-col overflow-hidden rounded-kit-lg border text-kit-fg outline-none data-[open]:animate-kit-pop-in", menuClassName),
333
+ children: /* @__PURE__ */ jsxs("div", {
334
+ className: "flex min-h-0 flex-1 flex-col",
335
+ children: [
336
+ /* @__PURE__ */ jsxs("div", {
337
+ className: "flex h-9 shrink-0 items-center gap-2 border-b border-kit-line-subtle px-2.5 text-kit-fg-3",
338
+ children: [/* @__PURE__ */ jsx(IconSearch, {
339
+ "aria-hidden": true,
340
+ className: "size-4 shrink-0"
341
+ }), /* @__PURE__ */ jsx(Combobox.Input, {
342
+ "aria-label": typeof a11y["aria-label"] === "string" ? a11y["aria-label"] : "Options",
343
+ placeholder: searchPlaceholder,
344
+ className: "h-full min-w-0 flex-1 bg-transparent text-kit-sm text-kit-fg outline-none placeholder:text-kit-fg-4"
345
+ })]
346
+ }),
347
+ shown.length === 0 ? /* @__PURE__ */ jsx("div", {
348
+ className: "px-2 py-6 text-center text-kit-sm text-kit-fg-3",
349
+ children: "No matches"
350
+ }) : null,
351
+ /* @__PURE__ */ jsx(Combobox.List, {
352
+ ref: listRef,
353
+ className: "min-h-0 flex-1 overflow-y-auto overscroll-contain p-1 empty:hidden",
354
+ children: grouped(shown).map((g, gi) => {
355
+ const items = g.items.map((o) => {
356
+ const text = nodeText(o.label);
357
+ const checked = o.value === current;
358
+ return /* @__PURE__ */ jsxs(Combobox.Item, {
359
+ value: o.value,
360
+ disabled: o.disabled,
361
+ "data-checked": checked,
362
+ className: itemClass,
363
+ children: [
364
+ /* @__PURE__ */ jsx(Lead, { o }),
365
+ /* @__PURE__ */ jsxs("div", {
366
+ className: "min-w-0 flex-1",
367
+ children: [/* @__PURE__ */ jsx("div", {
368
+ className: "truncate",
369
+ children: typeof o.label === "string" ? /* @__PURE__ */ jsx(Highlight, {
370
+ text,
371
+ query
372
+ }) : o.label
373
+ }), o.description ? /* @__PURE__ */ jsx("div", {
374
+ className: "truncate text-kit-xs text-kit-fg-3",
375
+ children: /* @__PURE__ */ jsx(Highlight, {
376
+ text: o.description,
377
+ query
378
+ })
379
+ }) : null]
380
+ }),
381
+ o.meta ? /* @__PURE__ */ jsx("span", {
382
+ className: "shrink-0 text-kit-xs tabular-nums text-kit-fg-3",
383
+ children: o.meta
384
+ }) : null,
385
+ checked ? /* @__PURE__ */ jsx(IconCheck, {
386
+ "aria-hidden": true,
387
+ className: "absolute right-2 size-4 !text-kit-fg"
388
+ }) : null
389
+ ]
390
+ }, o.value);
391
+ });
392
+ return g.group ? /* @__PURE__ */ jsxs(Combobox.Group, { children: [/* @__PURE__ */ jsx(Combobox.GroupLabel, {
393
+ className: groupHeading,
394
+ children: g.group
395
+ }), items] }, g.group + gi) : /* @__PURE__ */ jsx(React.Fragment, { children: items }, "g" + gi);
396
+ })
395
397
  })
396
- })
397
- ]
398
+ ]
399
+ })
398
400
  })
399
401
  }) })]
400
402
  });
401
403
  }
402
404
  //#endregion
403
- export { Highlight, SEARCH_THRESHOLD, Select$1 as Select, filterOptions, matchPositions, matchScore, nodeText, selectTriggerClass };
405
+ export { Highlight, SEARCH_THRESHOLD, Select, filterOptions, matchPositions, matchScore, nodeText, selectTriggerClass };
404
406
 
405
407
  //# sourceMappingURL=select.js.map