@kerfjs/ui 5.0.0-beta.55 → 5.0.0-beta.57

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 (418) hide show
  1. package/README.md +74 -41
  2. package/ai/application-ui-diagnostic-ids-v1.json +9 -1
  3. package/ai/application-ui-profile-sync.cjs +1 -1
  4. package/ai/application-ui-profile.defaults.json +63 -8
  5. package/ai/application-ui-profile.mjs +1 -1
  6. package/ai/compile-time-contracts-v1.json +2 -2
  7. package/ai/component-catalog.json +407 -80
  8. package/ai/component-catalog.schema.json +2 -0
  9. package/ai/component-class-owners.cjs +83 -0
  10. package/ai/component-composition-extension.d.ts +7 -0
  11. package/ai/component-composition-extension.schema.json +7 -0
  12. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  13. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  14. package/ai/{component-catalog-v2.json → component-composition.json} +302 -61
  15. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  16. package/ai/components/README.md +170 -0
  17. package/ai/components/application-tabs.md +65 -0
  18. package/ai/components/badge.md +72 -0
  19. package/ai/components/collapsible-panel.md +102 -0
  20. package/ai/components/content-item.md +90 -0
  21. package/ai/components/disclosure-arrow.md +77 -0
  22. package/ai/components/document-baseline.md +75 -0
  23. package/ai/components/empty-state.md +80 -0
  24. package/ai/components/feedback.md +71 -0
  25. package/ai/components/floating-toolbar.md +80 -0
  26. package/ai/components/foundation.md +65 -0
  27. package/ai/components/grid.md +93 -0
  28. package/ai/components/headers.md +63 -0
  29. package/ai/components/layout.md +75 -0
  30. package/ai/components/list-action-row.md +91 -0
  31. package/ai/components/list-header.md +89 -0
  32. package/ai/components/list-inset-control.md +74 -0
  33. package/ai/components/list-inset-text.md +72 -0
  34. package/ai/components/list-item.md +88 -0
  35. package/ai/components/list.md +103 -0
  36. package/ai/components/loading-spinner.md +72 -0
  37. package/ai/components/lucide-icon.md +66 -0
  38. package/ai/components/nav-stack.md +103 -0
  39. package/ai/components/pane.md +100 -0
  40. package/ai/components/popup-menu.md +82 -0
  41. package/ai/components/recipe-app-shell.md +57 -0
  42. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  43. package/ai/components/recipe-compact-toolbar.md +57 -0
  44. package/ai/components/recipe-composer-form.md +57 -0
  45. package/ai/components/recipe-list-detail-dialog.md +57 -0
  46. package/ai/components/recipe-list-workspace-states.md +57 -0
  47. package/ai/components/recipe-loading-inspector.md +57 -0
  48. package/ai/components/recipe-navigation-sidebar.md +57 -0
  49. package/ai/components/recipe-navigation-stack.md +57 -0
  50. package/ai/components/recipe-workspace-header.md +57 -0
  51. package/ai/components/resize.md +101 -0
  52. package/ai/components/row.md +96 -0
  53. package/ai/components/segmented-control.md +82 -0
  54. package/ai/components/select.md +107 -0
  55. package/ai/components/skeleton.md +84 -0
  56. package/ai/components/spacer.md +86 -0
  57. package/ai/components/split-view.md +102 -0
  58. package/ai/components/state-banner.md +92 -0
  59. package/ai/components/sunken-panel.md +79 -0
  60. package/ai/components/surface-scaffold.md +78 -0
  61. package/ai/components/tab-bar.md +112 -0
  62. package/ai/components/tab-scaffold.md +94 -0
  63. package/ai/components/tabs.md +90 -0
  64. package/ai/components/text.md +82 -0
  65. package/ai/components/token-search-field.md +101 -0
  66. package/ai/components/toolbar-control-group.md +100 -0
  67. package/ai/components/toolbar-text.md +76 -0
  68. package/ai/components/toolbar.md +95 -0
  69. package/ai/components/value-table.md +72 -0
  70. package/ai/components/wa-accordion-item.md +55 -0
  71. package/ai/components/wa-accordion.md +65 -0
  72. package/ai/components/wa-animated-image.md +55 -0
  73. package/ai/components/wa-animation.md +55 -0
  74. package/ai/components/wa-avatar.md +55 -0
  75. package/ai/components/wa-badge.md +55 -0
  76. package/ai/components/wa-breadcrumb-item.md +53 -0
  77. package/ai/components/wa-breadcrumb.md +55 -0
  78. package/ai/components/wa-button-group.md +59 -0
  79. package/ai/components/wa-button.md +55 -0
  80. package/ai/components/wa-callout.md +58 -0
  81. package/ai/components/wa-card.md +59 -0
  82. package/ai/components/wa-carousel-item.md +53 -0
  83. package/ai/components/wa-carousel.md +55 -0
  84. package/ai/components/wa-checkbox-group.md +55 -0
  85. package/ai/components/wa-checkbox.md +55 -0
  86. package/ai/components/wa-color-picker.md +55 -0
  87. package/ai/components/wa-comparison.md +55 -0
  88. package/ai/components/wa-copy-button.md +55 -0
  89. package/ai/components/wa-details.md +61 -0
  90. package/ai/components/wa-dialog.md +59 -0
  91. package/ai/components/wa-divider.md +53 -0
  92. package/ai/components/wa-drawer.md +55 -0
  93. package/ai/components/wa-dropdown-item.md +60 -0
  94. package/ai/components/wa-dropdown.md +60 -0
  95. package/ai/components/wa-format-bytes.md +53 -0
  96. package/ai/components/wa-format-date.md +53 -0
  97. package/ai/components/wa-format-number.md +53 -0
  98. package/ai/components/wa-icon.md +58 -0
  99. package/ai/components/wa-include.md +53 -0
  100. package/ai/components/wa-input.md +59 -0
  101. package/ai/components/wa-intersection-observer.md +53 -0
  102. package/ai/components/wa-known-date.md +53 -0
  103. package/ai/components/wa-markdown.md +53 -0
  104. package/ai/components/wa-mutation-observer.md +53 -0
  105. package/ai/components/wa-number-input.md +55 -0
  106. package/ai/components/wa-option.md +59 -0
  107. package/ai/components/wa-otp-input.md +53 -0
  108. package/ai/components/wa-page.md +53 -0
  109. package/ai/components/wa-pagination.md +55 -0
  110. package/ai/components/wa-popover.md +55 -0
  111. package/ai/components/wa-popup.md +53 -0
  112. package/ai/components/wa-progress-bar.md +53 -0
  113. package/ai/components/wa-progress-ring.md +53 -0
  114. package/ai/components/wa-qr-code.md +53 -0
  115. package/ai/components/wa-radio-group.md +59 -0
  116. package/ai/components/wa-radio.md +55 -0
  117. package/ai/components/wa-random-content.md +53 -0
  118. package/ai/components/wa-rating.md +55 -0
  119. package/ai/components/wa-relative-time.md +53 -0
  120. package/ai/components/wa-resize-observer.md +53 -0
  121. package/ai/components/wa-scroller.md +53 -0
  122. package/ai/components/wa-select.md +63 -0
  123. package/ai/components/wa-skeleton.md +53 -0
  124. package/ai/components/wa-slider.md +55 -0
  125. package/ai/components/wa-spinner.md +58 -0
  126. package/ai/components/wa-split-panel.md +58 -0
  127. package/ai/components/wa-switch.md +53 -0
  128. package/ai/components/wa-tab-group.md +69 -0
  129. package/ai/components/wa-tab-panel.md +60 -0
  130. package/ai/components/wa-tab.md +59 -0
  131. package/ai/components/wa-tag.md +59 -0
  132. package/ai/components/wa-textarea.md +53 -0
  133. package/ai/components/wa-time-input.md +55 -0
  134. package/ai/components/wa-toast-item.md +60 -0
  135. package/ai/components/wa-toast.md +60 -0
  136. package/ai/components/wa-tooltip.md +55 -0
  137. package/ai/components/wa-tree-item.md +55 -0
  138. package/ai/components/wa-tree.md +55 -0
  139. package/ai/components/wa-zoomable-frame.md +55 -0
  140. package/ai/components/workbench.md +114 -0
  141. package/ai/public-api-signatures-v1.md +572 -101
  142. package/ai/skill.md +107 -52
  143. package/ai/webawesome-jsx-signatures-v1.md +8 -2
  144. package/analyzer/component-ownership.d.mts +56 -0
  145. package/analyzer/component-ownership.mjs +184 -0
  146. package/analyzer/index.d.mts +3 -0
  147. package/analyzer/index.mjs +274 -20
  148. package/analyzer/selectors.d.mts +21 -0
  149. package/analyzer/selectors.mjs +212 -0
  150. package/dist/app-tab.js +1 -1
  151. package/dist/badge.d.ts +35 -7
  152. package/dist/badge.js +1 -1
  153. package/dist/browser/catalog.js +25 -0
  154. package/dist/browser/collapsible-panel.js +7 -0
  155. package/dist/browser/content-item.js +3 -0
  156. package/dist/browser/nav-stack.js +8 -0
  157. package/dist/browser/select.js +1 -0
  158. package/dist/browser/split-view.js +10 -0
  159. package/dist/browser/tab-scaffold.js +4 -0
  160. package/dist/browser/workbench.js +10 -0
  161. package/dist/catalog-resources.d.ts +12 -1
  162. package/dist/catalog.d.ts +14 -3
  163. package/dist/catalog.js +53 -43
  164. package/dist/catalog.js.map +1 -1
  165. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  166. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  167. package/dist/{chunk-R754MHXX.js → chunk-553ASUK6.js} +8 -8
  168. package/dist/chunk-553ASUK6.js.map +1 -0
  169. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  170. package/dist/chunk-5I7QGQVT.js.map +1 -0
  171. package/dist/{chunk-RNRUVPJ3.js → chunk-63ZWBGE3.js} +3 -2
  172. package/dist/chunk-63ZWBGE3.js.map +1 -0
  173. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  174. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  175. package/dist/{chunk-MTM43SJO.js → chunk-6YFHCLHG.js} +2 -2
  176. package/dist/chunk-6YFHCLHG.js.map +1 -0
  177. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  178. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  179. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  180. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  181. package/dist/chunk-BFPBS5Y4.js +250 -0
  182. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  183. package/dist/{chunk-5OLVUEND.js → chunk-DG6G5EPF.js} +4 -6
  184. package/dist/chunk-DG6G5EPF.js.map +1 -0
  185. package/dist/{chunk-LZXQVUGN.js → chunk-EVYKTVBQ.js} +5 -14
  186. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  187. package/dist/{chunk-7GUQYHKA.js → chunk-EZVNC4J6.js} +7 -1
  188. package/dist/chunk-EZVNC4J6.js.map +1 -0
  189. package/dist/{chunk-RNZAKSME.js → chunk-F4QMLOXJ.js} +5 -4
  190. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  191. package/dist/{chunk-EAX2GSS4.js → chunk-G2RKFVRB.js} +54 -20
  192. package/dist/chunk-G2RKFVRB.js.map +1 -0
  193. package/dist/chunk-JCV4GXWB.js +249 -0
  194. package/dist/chunk-JCV4GXWB.js.map +1 -0
  195. package/dist/chunk-K47P7QZC.js +17 -0
  196. package/dist/chunk-K47P7QZC.js.map +1 -0
  197. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  198. package/dist/chunk-KROD7KZK.js.map +1 -0
  199. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  200. package/dist/chunk-M7QV3IHH.js.map +1 -0
  201. package/dist/chunk-MA73TA6D.js +42 -0
  202. package/dist/chunk-MA73TA6D.js.map +1 -0
  203. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  204. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  205. package/dist/chunk-MP2GDBQZ.js +50 -0
  206. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  207. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  208. package/dist/chunk-NAPE7WUS.js.map +1 -0
  209. package/dist/{chunk-BSKEH3UC.js → chunk-NBYTIVHS.js} +2 -2
  210. package/dist/{chunk-BSKEH3UC.js.map → chunk-NBYTIVHS.js.map} +1 -1
  211. package/dist/{chunk-T22EM4ET.js → chunk-OUK6QRDR.js} +71 -31
  212. package/dist/chunk-OUK6QRDR.js.map +1 -0
  213. package/dist/chunk-PWXNJS2B.js +115 -0
  214. package/dist/chunk-PWXNJS2B.js.map +1 -0
  215. package/dist/{chunk-GUIHMIT2.js → chunk-QOWG4ZCL.js} +5 -4
  216. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  217. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  218. package/dist/chunk-VZOFZPSO.js.map +1 -0
  219. package/dist/{chunk-4BIMLITI.js → chunk-WLG6SSNT.js} +5 -3
  220. package/dist/chunk-WLG6SSNT.js.map +1 -0
  221. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  222. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  223. package/dist/{chunk-N7FHFNT6.js → chunk-XCO6YCYM.js} +34 -5
  224. package/dist/chunk-XCO6YCYM.js.map +1 -0
  225. package/dist/{chunk-TZ5IHWB2.js → chunk-XDKAYSVD.js} +5 -3
  226. package/dist/chunk-XDKAYSVD.js.map +1 -0
  227. package/dist/collapsible-panel.d.ts +14 -3
  228. package/dist/collapsible-panel.js +13 -16
  229. package/dist/collapsible-panel.js.map +1 -1
  230. package/dist/content-item.d.ts +46 -0
  231. package/dist/content-item.js +4 -0
  232. package/dist/content-item.js.map +1 -0
  233. package/dist/css-values.d.ts +5 -11
  234. package/dist/css-values.js +1 -1
  235. package/dist/disclosure-arrow.d.ts +4 -1
  236. package/dist/disclosure-arrow.js +1 -1
  237. package/dist/floating-toolbar.d.ts +17 -6
  238. package/dist/floating-toolbar.js +1 -1
  239. package/dist/grid.js +1 -1
  240. package/dist/help-tags-register.d.ts +13 -0
  241. package/dist/help-tags-register.js +9 -0
  242. package/dist/help-tags-register.js.map +1 -0
  243. package/dist/index.d.ts +7 -5
  244. package/dist/index.js +29 -26
  245. package/dist/list-action-row.js +2 -1
  246. package/dist/list-header.d.ts +14 -1
  247. package/dist/list-header.js +1 -1
  248. package/dist/list-inset-control.d.ts +1 -1
  249. package/dist/list-inset-control.js +1 -1
  250. package/dist/list-inset-text.d.ts +3 -10
  251. package/dist/list-inset-text.js +1 -1
  252. package/dist/list-item.js +2 -1
  253. package/dist/list.d.ts +10 -3
  254. package/dist/list.js +1 -1
  255. package/dist/nav-stack.d.ts +50 -5
  256. package/dist/nav-stack.js +4 -1
  257. package/dist/pane.d.ts +37 -2
  258. package/dist/pane.js +1 -1
  259. package/dist/{panel-toolbar-BFQxFITu.d.ts → panel-toolbar-BN4x0rth.d.ts} +13 -1
  260. package/dist/popup-menu-register.js +3 -2
  261. package/dist/popup-menu-register.js.map +1 -1
  262. package/dist/popup-menu.js +1 -1
  263. package/dist/row.d.ts +1 -1
  264. package/dist/row.js +1 -1
  265. package/dist/select-register.js +70 -3
  266. package/dist/select-register.js.map +1 -1
  267. package/dist/select.d.ts +46 -8
  268. package/dist/select.js +2 -1
  269. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  270. package/dist/skeleton.js +1 -1
  271. package/dist/spacer.js +1 -1
  272. package/dist/split-view.d.ts +31 -3
  273. package/dist/split-view.js +34 -5
  274. package/dist/split-view.js.map +1 -1
  275. package/dist/state-banner.js +1 -1
  276. package/dist/styles/app-tab.css +31 -0
  277. package/dist/styles/badge.css +32 -11
  278. package/dist/styles/catalog/components/catalog-example.css +1 -1
  279. package/dist/styles/catalog/components/catalog-stage.css +1 -1
  280. package/dist/styles/collapsible-panel.css +199 -42
  281. package/dist/styles/content-item.css +30 -0
  282. package/dist/styles/floating-toolbar.css +26 -2
  283. package/dist/styles/foundation.css +28 -19
  284. package/dist/styles/layout.css +1 -21
  285. package/dist/styles/list-action-row.css +13 -1
  286. package/dist/styles/list-header.css +0 -12
  287. package/dist/styles/list-inset-text.css +1 -2
  288. package/dist/styles/list-item.css +14 -1
  289. package/dist/styles/list.css +5 -5
  290. package/dist/styles/nav-stack.css +63 -71
  291. package/dist/styles/pane.css +83 -1
  292. package/dist/styles/popup-menu.css +229 -0
  293. package/dist/styles/resizable-region.css +70 -15
  294. package/dist/styles/select.css +60 -19
  295. package/dist/styles/skeleton.css +30 -3
  296. package/dist/styles/split-view.css +31 -32
  297. package/dist/styles/state-banner.css +0 -19
  298. package/dist/styles/surface-scaffold.css +8 -3
  299. package/dist/styles/tab-bar.css +79 -28
  300. package/dist/styles/tab-scaffold.css +60 -14
  301. package/dist/styles/text.css +17 -1
  302. package/dist/styles/token-search-field.css +4 -4
  303. package/dist/styles/toolbar-control-group.css +143 -69
  304. package/dist/styles/toolbar-text.css +21 -0
  305. package/dist/styles/toolbar.css +22 -37
  306. package/dist/styles/value-table.css +19 -2
  307. package/dist/styles/webawesome.css +3 -1
  308. package/dist/styles/workbench.css +145 -42
  309. package/dist/tab-scaffold.d.ts +46 -2
  310. package/dist/tab-scaffold.js +52 -16
  311. package/dist/tab-scaffold.js.map +1 -1
  312. package/dist/token-search-field.d.ts +4 -2
  313. package/dist/token-search-field.js +1 -1
  314. package/dist/toolbar-text.d.ts +7 -1
  315. package/dist/toolbar-text.js +1 -1
  316. package/dist/toolbar.d.ts +20 -5
  317. package/dist/toolbar.js +1 -1
  318. package/dist/{types-D6vzj-VT.d.ts → types-BuHELdXR.d.ts} +39 -6
  319. package/dist/value-table.js +1 -1
  320. package/dist/webawesome.d.ts +7 -1
  321. package/dist/wire-catalog.d.ts +15 -2
  322. package/dist/wire-catalog.js +12 -2
  323. package/dist/wire-catalog.js.map +1 -1
  324. package/dist/wire-scroll-dividers.d.ts +69 -0
  325. package/dist/wire-scroll-dividers.js +3 -0
  326. package/dist/wire-scroll-dividers.js.map +1 -0
  327. package/dist/wire-token-search-fields.js +1 -1
  328. package/dist/workbench.d.ts +60 -22
  329. package/dist/workbench.js +1 -1
  330. package/docs/accessibility.md +116 -7
  331. package/docs/app-layouts.md +18 -8
  332. package/docs/catalog.md +26 -7
  333. package/docs/collapsible-panel.md +32 -9
  334. package/docs/component-contract.md +182 -30
  335. package/docs/component-selection.md +59 -46
  336. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  337. package/docs/design/templates/empty-state/with-action.svg +1 -1
  338. package/docs/design/templates/empty-state-dark.svg +1 -1
  339. package/docs/design/templates/empty-state.svg +1 -1
  340. package/docs/design/templates/list/compact-dark.svg +1 -1
  341. package/docs/design/templates/list/compact.svg +1 -1
  342. package/docs/design/templates/list/stack-dark.svg +1 -1
  343. package/docs/design/templates/list/stack.svg +1 -1
  344. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  345. package/docs/design/templates/list-action-row/default.svg +1 -1
  346. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  347. package/docs/design/templates/list-action-row/selected.svg +1 -1
  348. package/docs/design/templates/list-action-row-dark.svg +1 -1
  349. package/docs/design/templates/list-action-row.svg +1 -1
  350. package/docs/design/templates/list-dark.svg +1 -1
  351. package/docs/design/templates/list-item/default-dark.svg +1 -1
  352. package/docs/design/templates/list-item/default.svg +1 -1
  353. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  354. package/docs/design/templates/list-item/selected.svg +1 -1
  355. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  356. package/docs/design/templates/list-item/trailing.svg +1 -1
  357. package/docs/design/templates/list-item-dark.svg +1 -1
  358. package/docs/design/templates/list-item.svg +1 -1
  359. package/docs/design/templates/list.svg +1 -1
  360. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  361. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  362. package/docs/design/templates/tab-bar-dark.svg +1 -1
  363. package/docs/design/templates/tab-bar.svg +1 -1
  364. package/docs/design/templates/value-table/details-dark.svg +1 -1
  365. package/docs/design/templates/value-table/details.svg +1 -1
  366. package/docs/design/templates/value-table-dark.svg +1 -1
  367. package/docs/design/templates/value-table.svg +1 -1
  368. package/docs/design-philosophy.md +31 -4
  369. package/docs/examples/application-ui-profile.json +4 -4
  370. package/docs/examples/command-palette-adapter.tsx +3 -2
  371. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  372. package/docs/layout.md +148 -29
  373. package/docs/nav-stack.md +77 -3
  374. package/docs/recipes.md +4 -3
  375. package/docs/split-view.md +54 -5
  376. package/docs/tab-scaffold.md +73 -2
  377. package/docs/type-contracts.md +21 -20
  378. package/docs/ui-analyzer.md +99 -5
  379. package/docs/ui-doctor.md +10 -0
  380. package/docs/ux-demo.md +2 -2
  381. package/docs/webawesome-theme.md +1 -2
  382. package/docs/workbench.md +57 -11
  383. package/doctor/index.mjs +6 -1
  384. package/llms.txt +117 -24
  385. package/package.json +29 -6
  386. package/ux-demo/recipes/collapsible-sidebar.tsx +3 -3
  387. package/ux-demo/recipes/composer-form.tsx +0 -1
  388. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  389. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  390. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  391. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  392. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  393. package/ux-demo/recipes/workspace-header.tsx +0 -1
  394. package/ai/component-catalog-extension-v2.d.ts +0 -7
  395. package/ai/component-catalog-extension-v2.schema.json +0 -7
  396. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  397. package/dist/chunk-4BIMLITI.js.map +0 -1
  398. package/dist/chunk-5I22LMCV.js.map +0 -1
  399. package/dist/chunk-5NDQABWK.js.map +0 -1
  400. package/dist/chunk-5OLVUEND.js.map +0 -1
  401. package/dist/chunk-7GUQYHKA.js.map +0 -1
  402. package/dist/chunk-D7GWXIAS.js.map +0 -1
  403. package/dist/chunk-DQA5FMOX.js +0 -85
  404. package/dist/chunk-DQA5FMOX.js.map +0 -1
  405. package/dist/chunk-EAX2GSS4.js.map +0 -1
  406. package/dist/chunk-GUIHMIT2.js.map +0 -1
  407. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  408. package/dist/chunk-LZXQVUGN.js.map +0 -1
  409. package/dist/chunk-MTM43SJO.js.map +0 -1
  410. package/dist/chunk-N7FHFNT6.js.map +0 -1
  411. package/dist/chunk-R754MHXX.js.map +0 -1
  412. package/dist/chunk-RNRUVPJ3.js.map +0 -1
  413. package/dist/chunk-RNZAKSME.js.map +0 -1
  414. package/dist/chunk-T22EM4ET.js.map +0 -1
  415. package/dist/chunk-TZ5IHWB2.js.map +0 -1
  416. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  417. package/dist/chunk-XD7DWYXG.js +0 -34
  418. package/dist/chunk-XD7DWYXG.js.map +0 -1
@@ -1,31 +1,36 @@
1
- import { Skeleton } from './chunk-ATHXW6RP.js';
2
- import { em } from './chunk-WZ2GLEY4.js';
1
+ import { Skeleton } from './chunk-AHEG27M7.js';
2
+ import { Badge } from './chunk-MP2GDBQZ.js';
3
3
  import { LucideIcon } from './chunk-4R777DUZ.js';
4
+ import { em } from './chunk-2G2ZJQYK.js';
4
5
  import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
5
6
 
6
7
  function SelectChevron() {
7
8
  return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 448 512", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M201.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 338.7 54.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z" }) });
8
9
  }
9
- function Select({
10
- name,
11
- value,
12
- label,
13
- ariaLabel,
14
- choices,
15
- className = "",
16
- placeholderText,
17
- hint,
18
- disabled = false,
19
- fitMenu = false,
20
- renderSelected,
21
- placeholder = false,
22
- presentation = "form",
23
- size = "default",
24
- selectedPresentation = "label",
25
- focusRingOwner = "select",
26
- labelMaxWidth,
27
- slot
28
- }) {
10
+ function Select(props) {
11
+ const {
12
+ name,
13
+ label,
14
+ ariaLabel,
15
+ choices,
16
+ className = "",
17
+ placeholderText,
18
+ hint,
19
+ disabled = false,
20
+ fitMenu = false,
21
+ placeholder = false,
22
+ presentation = "form",
23
+ size = "default",
24
+ focusRingOwner = "select",
25
+ labelMaxWidth,
26
+ slot
27
+ } = props;
28
+ const multiple = props.multiple === true;
29
+ const values = props.multiple ? props.value : [props.value];
30
+ const renderSelected = props.multiple ? void 0 : props.renderSelected;
31
+ const selectedPresentation = props.selectedPresentation ?? "label";
32
+ const iconTrigger = props.multiple && props.selectedPresentation === "icon-only";
33
+ const triggerIcon = iconTrigger ? props.triggerIcon : void 0;
29
34
  if (placeholder) {
30
35
  return /* @__PURE__ */ jsxs(
31
36
  "div",
@@ -59,7 +64,8 @@ function Select({
59
64
  }
60
65
  );
61
66
  }
62
- const selected = choices.find((choice) => choice.value === value);
67
+ const selected = multiple ? void 0 : choices.find((choice) => choice.value === values[0]);
68
+ const chosenCount = iconTrigger ? choices.filter((choice) => values.includes(choice.value)).length : 0;
63
69
  const icon = (choice, selectedIcon = false) => /* @__PURE__ */ jsx(
64
70
  "span",
65
71
  {
@@ -78,11 +84,25 @@ function Select({
78
84
  }
79
85
  );
80
86
  const option = (choice, index) => /* @__PURE__ */ jsxs(Fragment, { children: [
81
- choice.separatorBefore && index > 0 && /* @__PURE__ */ jsx("wa-divider", {}),
82
- /* @__PURE__ */ jsxs("wa-option", { value: choice.value, children: [
83
- choice.icon ? icon(choice) : null,
84
- choice.label
85
- ] })
87
+ choice.separatorBefore && index > 0 && /* @__PURE__ */ jsx(
88
+ "wa-divider",
89
+ {
90
+ orientation: "horizontal",
91
+ role: "separator",
92
+ "aria-orientation": "horizontal"
93
+ }
94
+ ),
95
+ /* @__PURE__ */ jsxs(
96
+ "wa-option",
97
+ {
98
+ value: choice.value,
99
+ selected: multiple && values.includes(choice.value),
100
+ children: [
101
+ choice.icon ? icon(choice) : null,
102
+ choice.label
103
+ ]
104
+ }
105
+ )
86
106
  ] });
87
107
  const groups = [
88
108
  ...new Set(
@@ -93,6 +113,9 @@ function Select({
93
113
  return /* @__PURE__ */ jsxs(
94
114
  "wa-select",
95
115
  {
116
+ size: "m",
117
+ appearance: "outlined",
118
+ placement: "bottom",
96
119
  class: `kui-select${renderSelected ? " kui-select--custom-selected" : ""}${fitMenu ? " kui-select--fit-menu" : ""}${!label ? " kui-select--label-hidden" : ""} ${className}`.trim(),
97
120
  "data-component": "select",
98
121
  "data-presentation": presentation,
@@ -102,17 +125,34 @@ function Select({
102
125
  name,
103
126
  label: label || ariaLabel,
104
127
  "aria-label": ariaLabel,
105
- value,
128
+ multiple,
129
+ value: multiple ? void 0 : values[0],
106
130
  placeholder: placeholderText,
107
131
  hint,
108
132
  disabled,
109
133
  style: labelMaxWidth === void 0 ? void 0 : `--kui-select-label-max-width:${labelMaxWidth}px`,
110
134
  slot,
111
135
  children: [
136
+ iconTrigger && /* @__PURE__ */ jsxs(Fragment, { children: [
137
+ /* @__PURE__ */ jsxs("span", { slot: "label", "data-key": `${name}:trigger-label`, children: [
138
+ label || ariaLabel,
139
+ /* @__PURE__ */ jsx("span", { class: "kui-select__name-summary", "data-morph-skip": true })
140
+ ] }),
141
+ /* @__PURE__ */ jsx(
142
+ "span",
143
+ {
144
+ "data-key": `${name}:trigger-icon`,
145
+ slot: "start",
146
+ class: "kui-select__icon kui-select__icon--selected kui-select__trigger-icon",
147
+ children: triggerIcon
148
+ }
149
+ ),
150
+ chosenCount > 0 && /* @__PURE__ */ jsx(Badge, { slot: "end", tone: "brand", size: "compact", ariaHidden: true, children: chosenCount })
151
+ ] }),
112
152
  selected && (renderSelected ? /* @__PURE__ */ jsx(
113
153
  "span",
114
154
  {
115
- "data-key": `${name}:${value}:custom-selected`,
155
+ "data-key": `${name}:${values[0]}:custom-selected`,
116
156
  slot: "start",
117
157
  class: "kui-select__custom-selected",
118
158
  children: renderSelected(selected)
@@ -138,4 +178,4 @@ function Select({
138
178
 
139
179
  export { Select };
140
180
 
141
- //# sourceMappingURL=chunk-T22EM4ET.js.map
181
+ //# sourceMappingURL=chunk-OUK6QRDR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/select.tsx"],"names":[],"mappings":"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","file":"chunk-OUK6QRDR.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { Badge } from './badge.js';\nimport { type CssForegroundColor, em } from './css-values.js';\nimport { LucideIcon, type LucideNode } from './lucide-icon.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Skeleton } from './skeleton.js';\n\nexport interface SelectChoice<Value extends string = string> {\n value: Value;\n label: string;\n icon?: LucideNode;\n iconName?: string;\n /**\n * Foreground color for the optional icon: a semantic foreground token such\n * as `uiColor('success-on-quiet')`, or an application-owned\n * `foregroundColorVar('--app-icon-color')`. Fill tokens such as\n * `uiColor('success-fill-quiet')` are pale background tints and do not\n * type-check.\n */\n color?: CssForegroundColor;\n group?: string;\n /**\n * Draw a divider between this choice and the previous choice in the same\n * list. A group boundary is already a separator, so the first choice of a\n * group (or of the whole menu) never draws a second one.\n */\n separatorBefore?: boolean;\n}\n\ntype SelectAccessibleName =\n { label: string; ariaLabel?: string } | { label?: never; ariaLabel: string };\n\nexport type SelectPresentation = 'form' | 'toolbar-borderless' | 'navigation';\nexport type SelectSize = 'default' | 'compact';\nexport type SelectSelectedPresentation = 'label' | 'icon-only';\nexport type SelectFocusRingOwner = 'select' | 'group';\n\ninterface SelectBaseProps<Value extends string = string> {\n name: string;\n choices: readonly SelectChoice<Value>[];\n className?: string;\n /** Empty-value hint text shown in the closed control (the native select placeholder). */\n placeholderText?: string;\n /** Supporting text shown below the control and associated with its combobox. */\n hint?: string;\n disabled?: boolean;\n fitMenu?: boolean;\n /** Render as an unanimated loading skeleton: the label above a static, empty control box. */\n placeholder?: boolean;\n /** Form (default), borderless toolbar, or intrinsic navigation chrome. */\n presentation?: SelectPresentation;\n size?: SelectSize;\n /** Let an enclosing ToolbarControlGroup paint the composed focus ring. */\n focusRingOwner?: SelectFocusRingOwner;\n /** Maximum closed-control label width in CSS pixels before ellipsis. */\n labelMaxWidth?: number;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** One chosen value (the default). */\nexport interface SelectSingleValueProps<Value extends string = string> {\n multiple?: false;\n value: NoInfer<Value>;\n renderSelected?: (choice: SelectChoice<Value>) => SafeHtml;\n /** Show only the selected choice icon while retaining the Select's accessible name. */\n selectedPresentation?: SelectSelectedPresentation;\n triggerIcon?: never;\n}\n\n/**\n * Any number of chosen values. The popup stays open while the person toggles\n * choices and closes on an outside click, Escape, or focus leaving; the closed\n * control summarizes the chosen labels in choice order.\n */\nexport interface SelectMultipleLabelProps<Value extends string = string> {\n multiple: true;\n value: readonly NoInfer<Value>[];\n renderSelected?: never;\n selectedPresentation?: 'label';\n triggerIcon?: never;\n}\n\n/**\n * A multiple Select drawn as an icon-only toolbar trigger, such as a\n * \"Filter by label\" funnel. No single choice is selected, so the trigger shows\n * a fixed `triggerIcon` naming the menu's purpose; while any choice is chosen\n * a count badge sits beside it, and the combobox's accessible name ends with\n * the chosen labels in choice order.\n */\nexport interface SelectMultipleIconProps<Value extends string = string> {\n multiple: true;\n value: readonly NoInfer<Value>[];\n renderSelected?: never;\n selectedPresentation: 'icon-only';\n /**\n * The trigger's fixed icon, typically a `LucideIcon` naming the menu's\n * purpose (a funnel for a filter), independent of the selection.\n */\n triggerIcon: KerfUiContent;\n}\n\nexport type SelectMultipleValueProps<Value extends string = string> =\n SelectMultipleLabelProps<Value> | SelectMultipleIconProps<Value>;\n\nexport type SelectProps<Value extends string = string> =\n SelectBaseProps<Value> &\n SelectAccessibleName &\n (SelectSingleValueProps<Value> | SelectMultipleValueProps<Value>);\n\n// The closed wa-select's disclosure glyph: Web Awesome's system `chevron-down`,\n// Font Awesome Free 7.0.0 by @fontawesome (https://fontawesome.com), licensed\n// CC BY 4.0 (https://fontawesome.com/license/free). The placeholder draws the\n// same path so the loading box matches the live control without registering\n// Web Awesome.\nfunction SelectChevron() {\n return (\n <svg viewBox=\"0 0 448 512\" aria-hidden=\"true\">\n <path d=\"M201.4 406.6c12.5 12.5 32.8 12.5 45.3 0l192-192c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 338.7 54.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l192 192z\"></path>\n </svg>\n );\n}\n\nexport function Select<Value extends string>(props: SelectProps<Value>) {\n const {\n name,\n label,\n ariaLabel,\n choices,\n className = '',\n placeholderText,\n hint,\n disabled = false,\n fitMenu = false,\n placeholder = false,\n presentation = 'form',\n size = 'default',\n focusRingOwner = 'select',\n labelMaxWidth,\n slot,\n } = props;\n const multiple = props.multiple === true;\n const values: readonly Value[] = props.multiple ? props.value : [props.value];\n const renderSelected = props.multiple ? undefined : props.renderSelected;\n const selectedPresentation: SelectSelectedPresentation =\n props.selectedPresentation ?? 'label';\n // A multiple icon-only trigger shows a fixed icon naming the menu's\n // purpose instead of a selected choice's icon.\n const iconTrigger =\n props.multiple && props.selectedPresentation === 'icon-only';\n const triggerIcon = iconTrigger ? props.triggerIcon : undefined;\n if (placeholder) {\n return (\n <div\n class={`kui-select kui-select--placeholder ${className}`.trim()}\n data-component=\"select\"\n data-placeholder=\"true\"\n data-presentation={presentation}\n data-size={size}\n data-selected-presentation={selectedPresentation}\n data-focus-ring-owner={focusRingOwner}\n aria-busy=\"true\"\n style={\n labelMaxWidth === undefined\n ? undefined\n : `--kui-select-label-max-width:${labelMaxWidth}px`\n }\n slot={slot}\n >\n {label && <span class=\"kui-select__placeholder-label\">{label}</span>}\n <span\n class=\"kui-select__placeholder-box\"\n aria-label={ariaLabel}\n role=\"img\"\n >\n <Skeleton width={em(10)} />\n <span class=\"kui-select__placeholder-chevron\" aria-hidden=\"true\">\n <SelectChevron />\n </span>\n </span>\n {hint && <span class=\"kui-select__placeholder-hint\">{hint}</span>}\n </div>\n );\n }\n // A multiple Select summarizes its choices in the display text instead of\n // leading with one selected icon.\n const selected = multiple\n ? undefined\n : choices.find((choice) => choice.value === values[0]);\n const chosenCount = iconTrigger\n ? choices.filter((choice) => values.includes(choice.value)).length\n : 0;\n const icon = (choice: SelectChoice<Value>, selectedIcon = false) => (\n <span\n data-key={`${name}:${choice.value}:${selectedIcon ? 'selected' : 'option'}`}\n data-morph-skip\n slot=\"start\"\n class={`kui-select__icon${selectedIcon ? ' kui-select__icon--selected' : ''}`}\n style={choice.color ? `color:${choice.color}` : undefined}\n >\n {choice.icon ? (\n <LucideIcon\n icon={choice.icon}\n name={\n choice.iconName ?? choice.label.toLowerCase().replaceAll(' ', '-')\n }\n />\n ) : null}\n </span>\n );\n const option = (choice: SelectChoice<Value>, index: number) => (\n <>\n {/* Web Awesome sets the divider's role and aria-orientation on its\n host once, so a template that omits them would lose them to the\n next kerf re-render's morph for good. Render them explicitly, with\n the orientation it reflects (see the wa-select note below). */}\n {choice.separatorBefore && index > 0 && (\n <wa-divider\n orientation=\"horizontal\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n ></wa-divider>\n )}\n <wa-option\n value={choice.value}\n selected={multiple && values.includes(choice.value)}\n >\n {choice.icon ? icon(choice) : null}\n {choice.label}\n </wa-option>\n </>\n );\n const groups = [\n ...new Set(\n choices\n .map((choice) => choice.group)\n .filter((group): group is string => Boolean(group)),\n ),\n ];\n const ungrouped = choices.filter((choice) => !choice.group);\n // Web Awesome names its shadow combobox from the label, not the host's\n // aria-label. Keep ariaLabel-only names available without visible chrome.\n // A multiple Select's value is its selected options (the value attribute\n // holds only one string), kept in sync by @kerfjs/ui/select/register.\n // size/appearance/placement are Web Awesome's defaults, which it reflects\n // onto the host; rendering them keeps a re-render's morph from stripping\n // them and forcing a Lit update to put them back.\n return (\n <wa-select\n size=\"m\"\n appearance=\"outlined\"\n placement=\"bottom\"\n class={`kui-select${renderSelected ? ' kui-select--custom-selected' : ''}${fitMenu ? ' kui-select--fit-menu' : ''}${!label ? ' kui-select--label-hidden' : ''} ${className}`.trim()}\n data-component=\"select\"\n data-presentation={presentation}\n data-size={size}\n data-selected-presentation={selectedPresentation}\n data-focus-ring-owner={focusRingOwner}\n name={name}\n label={label || ariaLabel}\n aria-label={ariaLabel}\n multiple={multiple}\n value={multiple ? undefined : values[0]}\n placeholder={placeholderText}\n hint={hint}\n disabled={disabled}\n style={\n labelMaxWidth === undefined\n ? undefined\n : `--kui-select-label-max-width:${labelMaxWidth}px`\n }\n slot={slot}\n >\n {iconTrigger && (\n <>\n {/* The accessible name ends with the chosen labels, which\n @kerfjs/ui/select/register writes into the summary. */}\n <span slot=\"label\" data-key={`${name}:trigger-label`}>\n {label || ariaLabel}\n <span class=\"kui-select__name-summary\" data-morph-skip></span>\n </span>\n <span\n data-key={`${name}:trigger-icon`}\n slot=\"start\"\n class=\"kui-select__icon kui-select__icon--selected kui-select__trigger-icon\"\n >\n {triggerIcon}\n </span>\n {chosenCount > 0 && (\n <Badge slot=\"end\" tone=\"brand\" size=\"compact\" ariaHidden>\n {chosenCount}\n </Badge>\n )}\n </>\n )}\n {selected &&\n (renderSelected ? (\n <span\n data-key={`${name}:${values[0]}:custom-selected`}\n slot=\"start\"\n class=\"kui-select__custom-selected\"\n >\n {renderSelected(selected)}\n </span>\n ) : selected.icon ? (\n icon(selected, true)\n ) : null)}\n {ungrouped.map(option)}\n {groups.map((group, index) => (\n <div\n class={`kui-select__group${index > 0 || ungrouped.length > 0 ? ' kui-select__group--separated' : ''}`}\n role=\"group\"\n aria-label={group}\n >\n <span class=\"kui-select__group-title\">{group}</span>\n {choices.filter((choice) => choice.group === group).map(option)}\n </div>\n ))}\n </wa-select>\n );\n}\n"]}
@@ -0,0 +1,115 @@
1
+ import { ToolbarText } from './chunk-XDKAYSVD.js';
2
+ import { ToolbarControlGroup } from './chunk-ZIYOJFZD.js';
3
+ import { Toolbar } from './chunk-6YFHCLHG.js';
4
+ import { LucideIcon } from './chunk-4R777DUZ.js';
5
+ import { ChevronLeft } from 'lucide';
6
+ import { jsxs, jsx, Fragment } from 'kerfjs/jsx-runtime';
7
+
8
+ var DEFAULT_SAFE_AREA_EDGES = [
9
+ "block-start",
10
+ "inline-start",
11
+ "inline-end"
12
+ ];
13
+ function NavStack({
14
+ id,
15
+ label,
16
+ views,
17
+ backLabel = "Back",
18
+ backIcon,
19
+ backText,
20
+ toolbarConfig = {},
21
+ hideToolbar = false,
22
+ bottomToolbar,
23
+ chromeDividers = "scroll",
24
+ className = "",
25
+ slot
26
+ }) {
27
+ const topIndex = views.length - 1;
28
+ const top = views[topIndex];
29
+ const canPop = views.length > 1;
30
+ return /* @__PURE__ */ jsxs(
31
+ "section",
32
+ {
33
+ class: `kui-nav-stack ${className}`.trim(),
34
+ id,
35
+ "data-component": "nav-stack",
36
+ "data-nav-stack-id": id,
37
+ "data-depth": String(views.length),
38
+ "data-chrome-dividers": chromeDividers === "always" || chromeDividers === "none" ? chromeDividers : void 0,
39
+ "aria-label": label,
40
+ slot,
41
+ children: [
42
+ !hideToolbar && /* @__PURE__ */ jsx("div", { class: "kui-nav-stack__chrome", "data-nav-stack-chrome": true, children: /* @__PURE__ */ jsx(
43
+ Toolbar,
44
+ {
45
+ label: toolbarConfig.label,
46
+ dividerSides: toolbarConfig.dividerSides,
47
+ centerAlign: toolbarConfig.centerAlign,
48
+ responsive: toolbarConfig.responsive,
49
+ responsiveAt: toolbarConfig.responsiveAt,
50
+ safeAreaEdges: toolbarConfig.safeAreaEdges ?? DEFAULT_SAFE_AREA_EDGES,
51
+ leading: /* @__PURE__ */ jsxs(Fragment, { children: [
52
+ canPop && /* @__PURE__ */ jsx(
53
+ ToolbarControlGroup,
54
+ {
55
+ appearance: "borderless",
56
+ shape: "rounded",
57
+ content: backText ? "mixed" : "icon",
58
+ single: true,
59
+ children: /* @__PURE__ */ jsxs(
60
+ "button",
61
+ {
62
+ type: "button",
63
+ class: "kui-nav-stack__back",
64
+ "data-nav-back": true,
65
+ "aria-label": backText ? void 0 : backLabel,
66
+ children: [
67
+ backIcon ?? /* @__PURE__ */ jsx(
68
+ LucideIcon,
69
+ {
70
+ icon: ChevronLeft,
71
+ name: "chevron-left",
72
+ className: "kui-nav-stack__back-icon"
73
+ }
74
+ ),
75
+ backText ? /* @__PURE__ */ jsx("span", { children: backText }) : null
76
+ ]
77
+ }
78
+ )
79
+ }
80
+ ),
81
+ top?.leading,
82
+ /* @__PURE__ */ jsx(
83
+ ToolbarText,
84
+ {
85
+ text: top?.title ?? "",
86
+ size: toolbarConfig.titleSize ?? "large",
87
+ headingLevel: toolbarConfig.headingLevel,
88
+ fill: true
89
+ }
90
+ )
91
+ ] }),
92
+ center: top?.center,
93
+ trailing: top?.toolbar
94
+ }
95
+ ) }),
96
+ /* @__PURE__ */ jsx("div", { class: "kui-nav-stack__viewport", "data-nav-stack-viewport": true, children: views.map((view, index) => /* @__PURE__ */ jsx(
97
+ "article",
98
+ {
99
+ class: "kui-nav-stack__view",
100
+ "data-key": view.key,
101
+ "data-nav-key": view.key,
102
+ "data-nav-active": String(index === topIndex),
103
+ "aria-hidden": String(index !== topIndex),
104
+ children: view.content
105
+ }
106
+ )) }),
107
+ (top?.bottomToolbar ?? bottomToolbar) && /* @__PURE__ */ jsx("footer", { class: "kui-nav-stack__bottom", "data-nav-stack-bottom": true, children: top?.bottomToolbar ?? bottomToolbar })
108
+ ]
109
+ }
110
+ );
111
+ }
112
+
113
+ export { NavStack };
114
+
115
+ //# sourceMappingURL=chunk-PWXNJS2B.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nav-stack.tsx"],"names":[],"mappings":"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","file":"chunk-PWXNJS2B.js","sourcesContent":["import { ChevronLeft } from 'lucide';\n\nimport { LucideIcon } from './lucide-icon.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Toolbar, type ToolbarConfig } from './toolbar.js';\nimport { ToolbarControlGroup } from './toolbar-control-group.js';\nimport {\n type HeadingLevel,\n ToolbarText,\n type ToolbarTextSize,\n} from './toolbar-text.js';\n\n/**\n * One entry in a {@link NavStack}. The app owns the stack as an array (usually a\n * signal); `NavStack` renders it and `wireNavStack` animates the transitions.\n */\nexport interface NavStackView {\n /** Stable identity for keyed reconcile and transition direction. */\n key: string;\n content: KerfUiContent;\n /** Title shown in the top toolbar for this view. */\n title?: string;\n /** Leading groups for this view's top toolbar, after the back control and before the title. */\n leading?: KerfUiContent;\n /** Center content for this view's top toolbar (placed per `toolbarConfig.centerAlign`). */\n center?: KerfUiContent;\n /** Trailing actions for this view's top toolbar. */\n toolbar?: KerfUiContent;\n /** Bottom toolbar for this view. Cross-fades with the top chrome on navigation. */\n bottomToolbar?: KerfUiContent;\n}\n\n/**\n * The top toolbar's configuration. Its `ToolbarConfig` forwards to the real\n * `Toolbar` the stack renders; by default that toolbar draws no divider and\n * claims the top and side safe-area edges the stack still touches.\n */\nexport interface NavStackToolbarConfig extends ToolbarConfig {\n /** Accessible name of the top toolbar (default: none). */\n label?: string;\n /** Size of the view title's `ToolbarText` (default `large`). */\n titleSize?: ToolbarTextSize;\n /** Expose the view title as a heading at this level (default: a plain span). */\n headingLevel?: HeadingLevel;\n}\n\nexport interface NavStackProps {\n id: string;\n /** Accessible name for the stack region. */\n label: string;\n /** The stack, root first; the last entry is the active top view. */\n views: NavStackView[];\n /** Accessible label for the icon-only back control (default \"Back\"). */\n backLabel?: string;\n /** The back control's icon (default a chevron-left `LucideIcon`). */\n backIcon?: KerfUiContent;\n /**\n * Visible text beside the back icon, such as the previous view's title\n * (default: icon only). When set, the text names the control and\n * `backLabel` is not used.\n */\n backText?: string;\n /** The top toolbar's configuration, forwarded to its `Toolbar`. */\n toolbarConfig?: NavStackToolbarConfig;\n /** Hide the top toolbar entirely (rare — a fully custom-chrome view). */\n hideToolbar?: boolean;\n /** Optional persistent bottom toolbar used when the active view does not provide one. */\n bottomToolbar?: KerfUiContent;\n /**\n * The line under the top chrome and over the bottom toolbar, where they\n * meet the active view. `scroll` (default) shows the chrome's line only\n * while the view's content is scrolled beneath it, and the bottom\n * toolbar's only while more content lies below — never when the content\n * fits — once `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is\n * wired above the stack; unwired, neither shows. `always` shows both\n * without the wiring; `none` neither, even when wired. The line is drawn\n * inside the chrome, so no state moves the chrome or the content. A\n * `toolbarConfig.dividerSides` edge is the Toolbar's own and is unaffected.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nconst DEFAULT_SAFE_AREA_EDGES = [\n 'block-start',\n 'inline-start',\n 'inline-end',\n] as const;\n\n/**\n * A navigation stack (iOS-style push/pop). Renders every entry stacked, the last\n * one active; `@kerfjs/ui/wire-nav-stack`'s `wireNavStack` slides the content and\n * cross-fades the chrome across a change. Its top chrome is a real `Toolbar`: the\n * back control and title lead, the active view's `leading` / `center` / `toolbar`\n * content fills the zones, and `toolbarConfig` configures it. A single-pane\n * layout is a `NavStack` with one entry. See `docs/23-app-layouts.md` §3.1.\n */\nexport function NavStack({\n id,\n label,\n views,\n backLabel = 'Back',\n backIcon,\n backText,\n toolbarConfig = {},\n hideToolbar = false,\n bottomToolbar,\n chromeDividers = 'scroll',\n className = '',\n slot,\n}: NavStackProps) {\n const topIndex = views.length - 1;\n const top = views[topIndex];\n const canPop = views.length > 1;\n return (\n <section\n class={`kui-nav-stack ${className}`.trim()}\n id={id}\n data-component=\"nav-stack\"\n data-nav-stack-id={id}\n data-depth={String(views.length)}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n aria-label={label}\n slot={slot}\n >\n {!hideToolbar && (\n <div class=\"kui-nav-stack__chrome\" data-nav-stack-chrome>\n <Toolbar\n label={toolbarConfig.label}\n dividerSides={toolbarConfig.dividerSides}\n centerAlign={toolbarConfig.centerAlign}\n responsive={toolbarConfig.responsive}\n responsiveAt={toolbarConfig.responsiveAt}\n safeAreaEdges={\n toolbarConfig.safeAreaEdges ?? DEFAULT_SAFE_AREA_EDGES\n }\n leading={\n <>\n {canPop && (\n <ToolbarControlGroup\n appearance=\"borderless\"\n shape=\"rounded\"\n content={backText ? 'mixed' : 'icon'}\n single\n >\n <button\n type=\"button\"\n class=\"kui-nav-stack__back\"\n data-nav-back\n aria-label={backText ? undefined : backLabel}\n >\n {backIcon ?? (\n <LucideIcon\n icon={ChevronLeft}\n name=\"chevron-left\"\n className=\"kui-nav-stack__back-icon\"\n />\n )}\n {backText ? <span>{backText}</span> : null}\n </button>\n </ToolbarControlGroup>\n )}\n {top?.leading}\n <ToolbarText\n text={top?.title ?? ''}\n size={toolbarConfig.titleSize ?? 'large'}\n headingLevel={toolbarConfig.headingLevel}\n fill\n />\n </>\n }\n center={top?.center}\n trailing={top?.toolbar}\n />\n </div>\n )}\n <div class=\"kui-nav-stack__viewport\" data-nav-stack-viewport>\n {views.map((view, index) => (\n <article\n class=\"kui-nav-stack__view\"\n data-key={view.key}\n data-nav-key={view.key}\n data-nav-active={String(index === topIndex)}\n aria-hidden={String(index !== topIndex)}\n >\n {view.content}\n </article>\n ))}\n </div>\n {(top?.bottomToolbar ?? bottomToolbar) && (\n <footer class=\"kui-nav-stack__bottom\" data-nav-stack-bottom>\n {top?.bottomToolbar ?? bottomToolbar}\n </footer>\n )}\n </section>\n );\n}\n"]}
@@ -1,7 +1,8 @@
1
+ import { withWordBreaks } from './chunk-K47P7QZC.js';
1
2
  import { LoadingSpinner } from './chunk-ZLWQZUGF.js';
2
- import { Skeleton } from './chunk-ATHXW6RP.js';
3
+ import { Skeleton } from './chunk-AHEG27M7.js';
3
4
  import { filterDataAttributes } from './chunk-SRSJO5QE.js';
4
- import { remify, em } from './chunk-WZ2GLEY4.js';
5
+ import { remify, em } from './chunk-2G2ZJQYK.js';
5
6
  import { jsxs, jsx } from 'kerfjs/jsx-runtime';
6
7
 
7
8
  var PROTECTED_ROOT_DATA_ATTRIBUTES = /* @__PURE__ */ new Set([
@@ -74,7 +75,7 @@ function ListItem({
74
75
  children: [
75
76
  icon && /* @__PURE__ */ jsx("span", { class: "kui-list-item__icon", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { block: true, width: remify(18), height: remify(18) }) : icon }),
76
77
  /* @__PURE__ */ jsxs("span", { class: "kui-list-item__label", children: [
77
- /* @__PURE__ */ jsx("span", { class: "kui-list-item__primary-label", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: em(9) }) : label }),
78
+ /* @__PURE__ */ jsx("span", { class: "kui-list-item__primary-label", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: em(9) }) : multiline ? withWordBreaks(label) : label }),
78
79
  description && /* @__PURE__ */ jsx("span", { class: "kui-list-item__description", children: placeholder ? /* @__PURE__ */ jsx(Skeleton, { width: em(11) }) : description })
79
80
  ] }),
80
81
  (busy || status || trailing) && /* @__PURE__ */ jsxs("span", { class: "kui-list-item__trailing", children: [
@@ -89,4 +90,4 @@ function ListItem({
89
90
 
90
91
  export { ListItem };
91
92
 
92
- //# sourceMappingURL=chunk-GUIHMIT2.js.map
93
+ //# sourceMappingURL=chunk-QOWG4ZCL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/list-item.tsx"],"names":[],"mappings":"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","file":"chunk-QOWG4ZCL.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { em, remify } from './css-values.js';\nimport { filterDataAttributes } from './extension-attributes.js';\nimport { LoadingSpinner } from './loading-spinner.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Skeleton } from './skeleton.js';\nimport { withWordBreaks } from './word-breaks.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-item-id',\n 'data-has-icon',\n 'data-has-description',\n 'data-multiline',\n 'data-density',\n 'data-divider',\n 'data-busy',\n 'data-state',\n 'data-kui-disabled',\n]);\n\ntype ListItemRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-item-id'?: never;\n 'data-has-icon'?: never;\n 'data-has-description'?: never;\n 'data-multiline'?: never;\n 'data-density'?: never;\n 'data-divider'?: never;\n 'data-busy'?: never;\n 'data-state'?: never;\n 'data-kui-disabled'?: never;\n }\n>;\n\nexport interface ListItemProps {\n label: string | SafeHtml;\n /** App-owned supporting text rendered in the component's stable label stack. */\n description?: string | SafeHtml;\n icon?: SafeHtml;\n /** Dormant author content at the row's end; a placeholder renders it as a skeleton. */\n trailing?: KerfUiContent;\n /** Dormant status metadata rendered before trailing content; a placeholder renders it as a skeleton. */\n status?: string | SafeHtml;\n /** Show a progress indicator and expose the row as busy without replacing its content; a placeholder keeps the indicator. */\n busy?: boolean;\n density?: 'standard' | 'compact';\n divider?: 'none' | 'before' | 'after' | 'both';\n selected?: boolean;\n action: string;\n itemId?: string;\n className?: string;\n pressed?: boolean;\n accessibleLabel?: string;\n title?: string;\n multiline?: boolean;\n state?: string;\n disabled?: boolean;\n tabIndex?: number;\n /** Render the row as an unanimated loading skeleton, disabling its action: label, description, icon, status, and trailing content become skeletons; the `busy` indicator stays live. */\n placeholder?: boolean;\n rootAttributes?: ListItemRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nexport function ListItem({\n label,\n description,\n icon,\n trailing,\n status,\n busy = false,\n density = 'standard',\n divider = 'none',\n selected = false,\n action,\n itemId,\n className = '',\n pressed,\n accessibleLabel,\n title,\n multiline = false,\n state,\n disabled = false,\n tabIndex,\n placeholder = false,\n rootAttributes = {},\n slot,\n}: ListItemProps) {\n const extensionAttributes = filterDataAttributes(\n rootAttributes,\n PROTECTED_ROOT_DATA_ATTRIBUTES,\n );\n return (\n <button\n {...extensionAttributes}\n type=\"button\"\n class={`kui-list-item ${className}`.trim()}\n title={placeholder ? undefined : title}\n disabled={disabled || placeholder}\n tabindex={placeholder ? -1 : tabIndex}\n data-component=\"list-item\"\n data-action={placeholder ? undefined : action}\n data-item-id={itemId}\n data-has-icon={String(Boolean(icon))}\n data-has-description={String(Boolean(description))}\n data-multiline={multiline ? 'true' : undefined}\n data-density={density}\n data-divider={divider}\n data-busy={busy ? 'true' : undefined}\n data-state={state}\n data-kui-disabled={disabled ? 'true' : undefined}\n data-placeholder={placeholder ? 'true' : undefined}\n aria-label={accessibleLabel}\n aria-current={selected ? 'page' : undefined}\n aria-pressed={pressed === undefined ? undefined : String(pressed)}\n aria-busy={placeholder || busy ? 'true' : undefined}\n slot={slot}\n >\n {icon && (\n <span class=\"kui-list-item__icon\">\n {placeholder ? (\n <Skeleton block width={remify(18)} height={remify(18)} />\n ) : (\n icon\n )}\n </span>\n )}\n <span class=\"kui-list-item__label\">\n <span class=\"kui-list-item__primary-label\">\n {placeholder ? (\n <Skeleton width={em(9)} />\n ) : multiline ? (\n withWordBreaks(label)\n ) : (\n label\n )}\n </span>\n {description && (\n <span class=\"kui-list-item__description\">\n {placeholder ? <Skeleton width={em(11)} /> : description}\n </span>\n )}\n </span>\n {(busy || status || trailing) && (\n <span class=\"kui-list-item__trailing\">\n {/* The busy spinner is component-owned chrome drawn from a known\n prop, so a placeholder keeps it live. Status text and\n author-supplied trailing content are values: skeletons. */}\n {busy && <LoadingSpinner />}\n {status && (\n <span class=\"kui-list-item__status\">\n {placeholder ? <Skeleton width={em(3.5)} /> : status}\n </span>\n )}\n {trailing && (placeholder ? <Skeleton width={em(1.5)} /> : trailing)}\n </span>\n )}\n </button>\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { verticalAlignment, horizontalAlignment } from './chunk-AYUHMAI6.js';
2
2
  import { filterDataAttributes } from './chunk-SRSJO5QE.js';
3
- import { space } from './chunk-WZ2GLEY4.js';
3
+ import { space } from './chunk-2G2ZJQYK.js';
4
4
  import { jsx } from 'kerfjs/jsx-runtime';
5
5
 
6
6
  var rowProtectedAttributes = /* @__PURE__ */ new Set([
@@ -68,4 +68,4 @@ function Row({
68
68
 
69
69
  export { Row };
70
70
 
71
- //# sourceMappingURL=chunk-5I22LMCV.js.map
71
+ //# sourceMappingURL=chunk-VZOFZPSO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/row.tsx"],"names":[],"mappings":";;;;;AAiBA,IAAM,sBAAA,uBAA6B,GAAA,CAAI;AAAA,EACrC,gBAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,kBAAA;AAAA,EACA;AACF,CAAC,CAAA;AAeD,IAAM,UAAA,GAAqC;AAAA,EACzC,MAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA,GAAA;AAAA,EACA;AACF,CAAA;AAgCO,SAAS,GAAA,CAAI;AAAA,EAClB,QAAA;AAAA,EACA,MAAA,GAAS,MAAA;AAAA,EACT,MAAA,GAAS,MAAA;AAAA,EACT,GAAA,GAAM,IAAA;AAAA,EACN,IAAA,GAAO,KAAA;AAAA,EACP,IAAA,GAAO,KAAA;AAAA,EACP,IAAA,GAAO,KAAA;AAAA,EACP,UAAA,GAAa,EAAA;AAAA,EACb,aAAA,GAAgB,EAAA;AAAA,EAChB,SAAA,GAAY,EAAA;AAAA,EACZ,iBAAiB,EAAC;AAAA,EAClB;AACF,CAAA,EAAa;AACX,EAAA,MAAM,kBAAA,GAAqB,oBAAA;AAAA,IACzB,cAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAW,UAAA,CAAW,QAAA,CAAS,GAAkB,CAAA,GACnD,KAAA,CAAM,GAAkB,CAAA,GACxB,GAAA;AACJ,EAAA,MAAM,SAAA,GAAY,IAAA,KAAS,IAAA,GAAO,UAAA,GAAa,IAAA,IAAQ,MAAA;AACvD,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,kBAAkB,QAAQ,CAAA,CAAA;AAAA,IAC1B,SAAA,GAAY,CAAA,gBAAA,EAAmB,SAAS,CAAA,CAAA,GAAK;AAAA,GAC/C,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,GAAG,CAAA;AAEX,EAAA,uBACE,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACE,GAAG,kBAAA;AAAA,MACJ,KAAA,EAAO,CAAA,QAAA,EAAW,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MACnC,gBAAA,EAAe,KAAA;AAAA,MACf,cAAA,EAAc,oBAAoB,MAAM,CAAA;AAAA,MACxC,cAAA,EAAc,kBAAkB,MAAM,CAAA;AAAA,MACtC,WAAA,EAAW,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAC,CAAA;AAAA,MAC/B,WAAA,EAAW,OAAO,MAAA,GAAS,MAAA;AAAA,MAC3B,WAAA,EAAW,OAAO,IAAI,CAAA;AAAA,MACtB,oBAAkB,UAAA,IAAc,MAAA;AAAA,MAChC,uBAAqB,aAAA,IAAiB,MAAA;AAAA,MACtC,KAAA;AAAA,MACA,IAAA;AAAA,MAEC;AAAA;AAAA,GACH;AAEJ","file":"chunk-VZOFZPSO.js","sourcesContent":["import {\n type CssFlex,\n type CssFlexKeyword,\n type CssLength,\n space,\n type UiSpaceName,\n} from './css-values.js';\nimport { filterDataAttributes } from './extension-attributes.js';\nimport {\n type HorizontalAlignment,\n horizontalAlignment,\n type VerticalAlignment,\n verticalAlignment,\n} from './flex-alignment.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport type { Sides } from './sides.js';\n\nconst rowProtectedAttributes = new Set([\n 'data-component',\n 'data-h-align',\n 'data-v-align',\n 'data-flex',\n 'data-fill',\n 'data-wrap',\n 'data-text-insets',\n 'data-control-insets',\n]);\n\ntype RowRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-h-align'?: never;\n 'data-v-align'?: never;\n 'data-flex'?: never;\n 'data-fill'?: never;\n 'data-wrap'?: never;\n 'data-text-insets'?: never;\n 'data-control-insets'?: never;\n }\n>;\n\nconst spaceNames: readonly UiSpaceName[] = [\n 'none',\n '2xs',\n 'xs',\n 's',\n 'm',\n 'l',\n 'xl',\n];\n\nexport interface RowProps {\n children?: KerfUiContent;\n /** Horizontal distribution. Defaults to left. */\n hAlign?: HorizontalAlignment;\n /** Vertical alignment and wrapped-line distribution. Defaults to full. */\n vAlign?: VerticalAlignment;\n /** A named UI spacing token or typed CSS length. Defaults to xs. */\n gap?: UiSpaceName | CssLength;\n /** Allow this row to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */\n flex?: boolean | CssFlexKeyword | CssFlex;\n /**\n * Fill the height of a parent with a definite height, such as an app root or\n * a fixed-height frame, when this row is that parent's layout root. Inside a\n * flex layout use `flex` instead. Defaults to false.\n */\n fill?: boolean;\n /** Allow children to wrap onto additional lines. */\n wrap?: boolean;\n /** Physical sides that receive the standard 17px text inset. */\n textInsets?: Sides;\n /** Physical sides that receive the standard 8px control inset. Text insets win on overlap. */\n controlInsets?: Sides;\n className?: string;\n /** Safe `data-*` metadata; Row-owned structural attributes remain protected. */\n rootAttributes?: RowRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/** A horizontal flex row with explicit physical-axis alignment and spacing. */\nexport function Row({\n children,\n hAlign = 'left',\n vAlign = 'full',\n gap = 'xs',\n flex = false,\n fill = false,\n wrap = false,\n textInsets = '',\n controlInsets = '',\n className = '',\n rootAttributes = {},\n slot,\n}: RowProps) {\n const safeRootAttributes = filterDataAttributes(\n rootAttributes,\n rowProtectedAttributes,\n );\n const gapValue = spaceNames.includes(gap as UiSpaceName)\n ? space(gap as UiSpaceName)\n : gap;\n const flexValue = flex === true ? '1 1 auto' : flex || undefined;\n const style = [\n `--_kui-row-gap:${gapValue}`,\n flexValue ? `--_kui-row-flex:${flexValue}` : '',\n ]\n .filter(Boolean)\n .join(';');\n\n return (\n <div\n {...safeRootAttributes}\n class={`kui-row ${className}`.trim()}\n data-component=\"row\"\n data-h-align={horizontalAlignment(hAlign)}\n data-v-align={verticalAlignment(vAlign)}\n data-flex={String(Boolean(flex))}\n data-fill={fill ? 'true' : undefined}\n data-wrap={String(wrap)}\n data-text-insets={textInsets || undefined}\n data-control-insets={controlInsets || undefined}\n style={style}\n slot={slot}\n >\n {children}\n </div>\n );\n}\n\nexport type {\n CssFlex,\n CssFlexKeyword,\n CssLength,\n UiSpaceName,\n} from './css-values.js';\nexport type {\n HorizontalAlignment,\n VerticalAlignment,\n} from './flex-alignment.js';\nexport type { Sides } from './sides.js';\n"]}
@@ -23,7 +23,8 @@ function entryKey(entry) {
23
23
  }
24
24
  function renderEntry(entry) {
25
25
  if (entry.kind === "divider") return /* @__PURE__ */ jsx("wa-divider", {});
26
- if (entry.kind === "heading") return /* @__PURE__ */ jsx("h3", { children: entry.label });
26
+ if (entry.kind === "heading")
27
+ return /* @__PURE__ */ jsx("div", { class: "kui-popup-menu__heading", children: entry.label });
27
28
  return /* @__PURE__ */ jsxs(
28
29
  "wa-dropdown-item",
29
30
  {
@@ -32,7 +33,7 @@ function renderEntry(entry) {
32
33
  value: entry.value,
33
34
  disabled: entry.disabled,
34
35
  children: [
35
- entry.icon ? /* @__PURE__ */ jsx("span", { slot: "icon", children: entry.icon }) : null,
36
+ entry.icon ? /* @__PURE__ */ jsx("span", { slot: "icon", class: "kui-popup-menu__icon", children: entry.icon }) : null,
36
37
  entry.label
37
38
  ]
38
39
  }
@@ -60,6 +61,7 @@ function PopupMenu({
60
61
  return /* @__PURE__ */ jsxs(
61
62
  "wa-dropdown",
62
63
  {
64
+ size: "m",
63
65
  ...rootAttributes,
64
66
  class: "kui-popup-menu",
65
67
  "data-component": "popup-menu",
@@ -89,4 +91,4 @@ function PopupMenu({
89
91
 
90
92
  export { PopupMenu };
91
93
 
92
- //# sourceMappingURL=chunk-4BIMLITI.js.map
94
+ //# sourceMappingURL=chunk-WLG6SSNT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/popup-menu.tsx"],"names":[],"mappings":"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","file":"chunk-WLG6SSNT.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type { KerfUiContent } from './semantic-content.js';\n\nexport type PopupMenuPlacement =\n 'bottom-start' | 'bottom' | 'bottom-end' | 'top-start' | 'top' | 'top-end';\n\ntype PopupMenuDataAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-action'?: never;\n 'data-component'?: never;\n 'data-key'?: never;\n 'data-morph-skip-children'?: never;\n }\n>;\n\n/** One command in the menu. */\nexport interface PopupMenuItem {\n kind?: 'item';\n label: string;\n /** Delegated `data-action` the app handles when the item is chosen. */\n action?: string;\n /** Native `wa-dropdown-item` value, reported by its `wa-select` event. */\n value?: string;\n /** Leading icon, typically a `LucideIcon`; it is placed in the item's icon slot. */\n icon?: SafeHtml;\n disabled?: boolean;\n /** Application `data-*` metadata such as a record id. */\n attributes?: PopupMenuDataAttributes;\n}\n\n/** A labeled group heading; items that follow it belong to the group. */\nexport interface PopupMenuHeading {\n kind: 'heading';\n label: string;\n}\n\n/** A separator between groups of items. */\nexport interface PopupMenuDivider {\n kind: 'divider';\n}\n\nexport type PopupMenuEntry =\n PopupMenuItem | PopupMenuHeading | PopupMenuDivider;\n\ntype PopupMenuTriggerName =\n | {\n /** Visible trigger text, which is also its accessible name. */\n text: string;\n label?: never;\n }\n | {\n text?: never;\n /**\n * Accessible name of an icon-only trigger, rendered as visually hidden\n * slotted text (a Web Awesome button takes its name from its content).\n */\n label: string;\n };\n\nexport type PopupMenuProps = PopupMenuTriggerName & {\n /** Trigger icon, typically a `LucideIcon`, before any visible text. */\n icon?: KerfUiContent;\n items: readonly PopupMenuEntry[];\n /** Where the menu opens relative to its trigger. Defaults to `bottom-start`. */\n placement?: PopupMenuPlacement;\n /** Show the disclosure caret after the trigger content. Defaults to true. */\n caret?: boolean;\n disabled?: boolean;\n /** Application `data-*` metadata on the menu root. */\n rootAttributes?: PopupMenuDataAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n};\n\n/** A short, stable FNV-1a digest of the trigger and item structure. */\nfunction contentKey(parts: readonly string[]): string {\n let hash = 0x811c9dc5;\n for (const character of parts.join('\\u0000')) {\n hash ^= character.codePointAt(0)!;\n hash = Math.imul(hash, 0x01000193);\n }\n return (hash >>> 0).toString(36);\n}\n\nfunction entryKey(entry: PopupMenuEntry): string {\n if (entry.kind === 'divider') return '-';\n if (entry.kind === 'heading') return `#${entry.label}`;\n return [\n entry.label,\n entry.action ?? '',\n entry.value ?? '',\n entry.disabled ? '1' : '0',\n String(entry.icon ?? ''),\n JSON.stringify(entry.attributes ?? {}),\n ].join('\\u0001');\n}\n\nfunction renderEntry(entry: PopupMenuEntry) {\n if (entry.kind === 'divider') return <wa-divider></wa-divider>;\n // A group title styled like the Select's group title. It is not a slotted\n // h1-h6, whose Web Awesome group-label metrics are !important.\n if (entry.kind === 'heading')\n return <div class=\"kui-popup-menu__heading\">{entry.label}</div>;\n return (\n <wa-dropdown-item\n {...(entry.attributes ?? {})}\n data-action={entry.action}\n value={entry.value}\n disabled={entry.disabled}\n >\n {entry.icon ? (\n <span slot=\"icon\" class=\"kui-popup-menu__icon\">\n {entry.icon}\n </span>\n ) : null}\n {entry.label}\n </wa-dropdown-item>\n );\n}\n\n/**\n * An action menu: a trigger button that opens a list of commands. Renders the\n * `wa-dropdown` root directly, so a `single` `ToolbarControlGroup` (with\n * `nestedDropdown`) or a `PopupSurface` sizes and insets it as usual. Items\n * dispatch through delegated `data-action`s; the app owns the commands and any\n * open-state reaction. Import `@kerfjs/ui/popup-menu/register` once to register\n * the Web Awesome elements.\n */\nexport function PopupMenu({\n text,\n label,\n icon,\n items,\n placement = 'bottom-start',\n caret = true,\n disabled = false,\n rootAttributes = {},\n slot,\n}: PopupMenuProps) {\n // Web Awesome owns the trigger and item DOM once upgraded, so the morph\n // skips the children; the content key rebuilds the menu when they change.\n const key = `kui-popup-menu-${contentKey([\n text ?? '',\n label ?? '',\n String(icon ?? ''),\n String(caret),\n String(disabled),\n ...items.map(entryKey),\n ])}`;\n // size=\"m\" is Web Awesome's reflected default; rendering it keeps a\n // re-render's morph from stripping it and forcing a Lit update.\n return (\n <wa-dropdown\n size=\"m\"\n {...rootAttributes}\n class=\"kui-popup-menu\"\n data-component=\"popup-menu\"\n data-key={key}\n data-morph-skip-children\n placement={placement}\n slot={slot}\n >\n <wa-button\n slot=\"trigger\"\n appearance=\"plain\"\n with-caret={caret}\n disabled={disabled}\n >\n {icon}\n {text ? (\n <span>{text}</span>\n ) : (\n <span class=\"kui-popup-menu__label\">{label}</span>\n )}\n </wa-button>\n {items.map(renderEntry)}\n </wa-dropdown>\n );\n}\n"]}
@@ -1,6 +1,6 @@
1
- import { Skeleton } from './chunk-ATHXW6RP.js';
1
+ import { Skeleton } from './chunk-AHEG27M7.js';
2
2
  import { filterDataAttributes } from './chunk-SRSJO5QE.js';
3
- import { em } from './chunk-WZ2GLEY4.js';
3
+ import { em } from './chunk-2G2ZJQYK.js';
4
4
  import { jsxs, jsx } from 'kerfjs/jsx-runtime';
5
5
 
6
6
  var PROTECTED_ROOT_DATA_ATTRIBUTES = /* @__PURE__ */ new Set([
@@ -123,4 +123,4 @@ function AppTab({
123
123
 
124
124
  export { AppTab };
125
125
 
126
- //# sourceMappingURL=chunk-NE5JAOQS.js.map
126
+ //# sourceMappingURL=chunk-WOUF7YXM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/app-tab.tsx"],"names":[],"mappings":"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","file":"chunk-NE5JAOQS.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { em } from './css-values.js';\nimport { filterDataAttributes } from './extension-attributes.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Skeleton } from './skeleton.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-tab-id',\n 'data-selected',\n 'data-tab-dragging',\n 'data-tab-drop-position',\n]);\n\ntype AppTabRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-tab-id'?: never;\n 'data-selected'?: never;\n 'data-tab-dragging'?: never;\n 'data-tab-drop-position'?: never;\n }\n>;\n\nexport type AppTabPresentation = 'pill' | 'segmented' | 'icon-only';\nexport type AppTabSize = 'default' | 'compact';\n\nexport interface AppTabProps {\n id: string;\n name: string;\n selected?: boolean;\n closable?: boolean;\n draggable?: boolean;\n leading?: KerfUiContent;\n trailing?: KerfUiContent;\n /** Visual treatment within a TabBar. Icon-only tabs retain `name` as their accessible name. */\n presentation?: AppTabPresentation;\n /** Compact tabs use the 32px application-rail height. */\n size?: AppTabSize;\n /** Maximum visible label width in CSS pixels before ellipsis. */\n labelMaxWidth?: number;\n /** Decorative dormant content for the close button. Must not contain interactive descendants. */\n closeIcon?: SafeHtml;\n selectAction?: string;\n closeAction?: string;\n className?: string;\n /** Render as an unanimated loading skeleton, disabling select/close and dragging. */\n placeholder?: boolean;\n /**\n * Named and still opening: the tab is known but its content is loading.\n * Keeps `name` visible in the quiet text color and as the tab's accessible\n * name, shows `trailing` (for example a `LoadingSpinner`), and marks the\n * tab `aria-busy`. Unlike `placeholder` it stays selectable — the\n * application shows placeholder content in its panel until loading\n * completes — while close and dragging stay disabled. Same pill geometry\n * as the live tab, so swapping it in place does not shift the bar.\n * `placeholder` wins when both are set.\n */\n pending?: boolean;\n rootAttributes?: AppTabRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nfunction CloseIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.25\"\n stroke-linecap=\"round\"\n >\n <path d=\"m7 7 10 10\"></path>\n <path d=\"M17 7 7 17\"></path>\n </svg>\n );\n}\n\nexport function AppTab({\n id,\n name,\n selected = false,\n closable = true,\n draggable = false,\n leading,\n trailing,\n presentation = 'pill',\n size = 'default',\n labelMaxWidth,\n closeIcon,\n selectAction = 'select-tab',\n closeAction = 'close-tab',\n className = '',\n placeholder = false,\n pending = false,\n rootAttributes = {},\n slot,\n}: AppTabProps) {\n // Both loading states disable close and dragging; a `placeholder` (unknown\n // tab) is also unselectable and hides its name, while a `pending` (known,\n // still opening) tab stays selectable so its panel can show placeholders.\n const dormant = placeholder || pending;\n const named = pending && !placeholder;\n const keyshortcuts = [\n closable && !dormant ? 'Delete Backspace' : '',\n draggable && !dormant ? 'Alt+Shift+ArrowLeft Alt+Shift+ArrowRight' : '',\n ]\n .filter(Boolean)\n .join(' ');\n const extensionAttributes = filterDataAttributes(\n rootAttributes,\n PROTECTED_ROOT_DATA_ATTRIBUTES,\n );\n return (\n <div\n {...extensionAttributes}\n class={`kui-app-tab ${className}`.trim()}\n data-component=\"app-tab\"\n data-tab-id={id}\n data-selected={String(selected)}\n data-presentation={presentation}\n data-size={size}\n data-placeholder={placeholder ? 'true' : undefined}\n data-pending={named ? 'true' : undefined}\n draggable={dormant ? 'false' : draggable ? 'true' : 'false'}\n aria-busy={dormant ? 'true' : undefined}\n style={\n labelMaxWidth === undefined\n ? undefined\n : `--kui-app-tab-label-max-width:${labelMaxWidth}px`\n }\n slot={slot}\n >\n {closable && (\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"kui-app-tab__close\"\n data-action={dormant ? undefined : closeAction}\n data-tab-id={id}\n disabled={dormant || undefined}\n aria-label={`Close ${name}`}\n title={`Close ${name}`}\n >\n <span class=\"kui-app-tab__close-icon\" aria-hidden=\"true\">\n {closeIcon ?? <CloseIcon />}\n </span>\n </button>\n )}\n <button\n type=\"button\"\n class=\"kui-app-tab__select\"\n role=\"tab\"\n aria-selected={String(selected)}\n aria-label={presentation === 'icon-only' || named ? name : undefined}\n aria-keyshortcuts={keyshortcuts || undefined}\n data-action={placeholder ? undefined : selectAction}\n data-tab-id={id}\n disabled={placeholder || undefined}\n tabindex={!placeholder && selected ? '0' : '-1'}\n >\n {leading}\n <span\n class=\"kui-app-tab__name\"\n aria-hidden={presentation === 'icon-only' ? 'true' : undefined}\n >\n {placeholder ? <Skeleton width={em(7)} /> : name}\n </span>\n {closable || trailing ? (\n <span class=\"kui-app-tab__trailing\">{trailing}</span>\n ) : undefined}\n </button>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/app-tab.tsx"],"names":[],"mappings":"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","file":"chunk-WOUF7YXM.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { em } from './css-values.js';\nimport { filterDataAttributes } from './extension-attributes.js';\nimport type { KerfUiContent } from './semantic-content.js';\nimport { Skeleton } from './skeleton.js';\n\nconst PROTECTED_ROOT_DATA_ATTRIBUTES = new Set([\n 'data-component',\n 'data-action',\n 'data-tab-id',\n 'data-selected',\n 'data-tab-dragging',\n 'data-tab-drop-position',\n]);\n\ntype AppTabRootAttributes = Readonly<\n Record<`data-${string}`, string | undefined> & {\n 'data-component'?: never;\n 'data-action'?: never;\n 'data-tab-id'?: never;\n 'data-selected'?: never;\n 'data-tab-dragging'?: never;\n 'data-tab-drop-position'?: never;\n }\n>;\n\nexport type AppTabPresentation = 'pill' | 'segmented' | 'icon-only';\nexport type AppTabSize = 'default' | 'compact';\n\nexport interface AppTabProps {\n id: string;\n name: string;\n selected?: boolean;\n closable?: boolean;\n draggable?: boolean;\n leading?: KerfUiContent;\n trailing?: KerfUiContent;\n /** Visual treatment within a TabBar. Icon-only tabs retain `name` as their accessible name. */\n presentation?: AppTabPresentation;\n /** Compact tabs use the 32px application-rail height. */\n size?: AppTabSize;\n /** Maximum visible label width in CSS pixels before ellipsis. */\n labelMaxWidth?: number;\n /** Decorative dormant content for the close button. Must not contain interactive descendants. */\n closeIcon?: SafeHtml;\n selectAction?: string;\n closeAction?: string;\n className?: string;\n /** Render as an unanimated loading skeleton, disabling select/close and dragging. */\n placeholder?: boolean;\n /**\n * Named and still opening: the tab is known but its content is loading.\n * Keeps `name` visible in the quiet text color and as the tab's accessible\n * name, shows `trailing` (for example a `LoadingSpinner`), and marks the\n * tab `aria-busy`. Unlike `placeholder` it stays selectable — the\n * application shows placeholder content in its panel until loading\n * completes — while close and dragging stay disabled. Same pill geometry\n * as the live tab, so swapping it in place does not shift the bar.\n * `placeholder` wins when both are set.\n */\n pending?: boolean;\n rootAttributes?: AppTabRootAttributes;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\nfunction CloseIcon() {\n return (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2.25\"\n stroke-linecap=\"round\"\n >\n <path d=\"m7 7 10 10\"></path>\n <path d=\"M17 7 7 17\"></path>\n </svg>\n );\n}\n\nexport function AppTab({\n id,\n name,\n selected = false,\n closable = true,\n draggable = false,\n leading,\n trailing,\n presentation = 'pill',\n size = 'default',\n labelMaxWidth,\n closeIcon,\n selectAction = 'select-tab',\n closeAction = 'close-tab',\n className = '',\n placeholder = false,\n pending = false,\n rootAttributes = {},\n slot,\n}: AppTabProps) {\n // Both loading states disable close and dragging; a `placeholder` (unknown\n // tab) is also unselectable and hides its name, while a `pending` (known,\n // still opening) tab stays selectable so its panel can show placeholders.\n const dormant = placeholder || pending;\n const named = pending && !placeholder;\n const keyshortcuts = [\n closable && !dormant ? 'Delete Backspace' : '',\n draggable && !dormant ? 'Alt+Shift+ArrowLeft Alt+Shift+ArrowRight' : '',\n ]\n .filter(Boolean)\n .join(' ');\n const extensionAttributes = filterDataAttributes(\n rootAttributes,\n PROTECTED_ROOT_DATA_ATTRIBUTES,\n );\n return (\n <div\n {...extensionAttributes}\n class={`kui-app-tab ${className}`.trim()}\n data-component=\"app-tab\"\n data-tab-id={id}\n data-selected={String(selected)}\n data-presentation={presentation}\n data-size={size}\n data-placeholder={placeholder ? 'true' : undefined}\n data-pending={named ? 'true' : undefined}\n draggable={dormant ? 'false' : draggable ? 'true' : 'false'}\n aria-busy={dormant ? 'true' : undefined}\n style={\n labelMaxWidth === undefined\n ? undefined\n : `--kui-app-tab-label-max-width:${labelMaxWidth}px`\n }\n slot={slot}\n >\n {closable && (\n <button\n type=\"button\"\n tabindex=\"-1\"\n class=\"kui-app-tab__close\"\n data-action={dormant ? undefined : closeAction}\n data-tab-id={id}\n disabled={dormant || undefined}\n aria-label={`Close ${name}`}\n title={`Close ${name}`}\n >\n <span class=\"kui-app-tab__close-icon\" aria-hidden=\"true\">\n {closeIcon ?? <CloseIcon />}\n </span>\n </button>\n )}\n <button\n type=\"button\"\n class=\"kui-app-tab__select\"\n role=\"tab\"\n aria-selected={String(selected)}\n aria-label={presentation === 'icon-only' || named ? name : undefined}\n aria-keyshortcuts={keyshortcuts || undefined}\n data-action={placeholder ? undefined : selectAction}\n data-tab-id={id}\n disabled={placeholder || undefined}\n tabindex={!placeholder && selected ? '0' : '-1'}\n >\n {leading}\n <span\n class=\"kui-app-tab__name\"\n aria-hidden={presentation === 'icon-only' ? 'true' : undefined}\n >\n {placeholder ? <Skeleton width={em(7)} /> : name}\n </span>\n {closable || trailing ? (\n <span class=\"kui-app-tab__trailing\">{trailing}</span>\n ) : undefined}\n </button>\n </div>\n );\n}\n"]}
@@ -1,5 +1,6 @@
1
- import { Toolbar } from './chunk-MTM43SJO.js';
2
1
  import { ToolbarControlGroup } from './chunk-ZIYOJFZD.js';
2
+ import { Toolbar } from './chunk-6YFHCLHG.js';
3
+ import { Pane } from './chunk-EZVNC4J6.js';
3
4
  import { LucideIcon } from './chunk-4R777DUZ.js';
4
5
  import { PanelLeftOpen, PanelLeftClose, PanelRightOpen, PanelRightClose, PanelBottomOpen, PanelBottomClose } from 'lucide';
5
6
  import { jsx, jsxs, Fragment } from 'kerfjs/jsx-runtime';
@@ -20,7 +21,7 @@ function panelToggleGroup(side, toggle, collapsed, attributes) {
20
21
  ...attributes,
21
22
  "data-action": toggle.action,
22
23
  "aria-expanded": String(!collapsed),
23
- "aria-label": `${collapsed ? "Show" : "Hide"} ${toggle.name}`,
24
+ "aria-label": collapsed ? toggle.showLabel ?? `Show ${toggle.name}` : toggle.hideLabel ?? `Hide ${toggle.name}`,
24
25
  children: /* @__PURE__ */ jsx(LucideIcon, { icon: glyph.icon, name: glyph.name })
25
26
  }
26
27
  ) });
@@ -30,7 +31,12 @@ function composedPanelToolbar(toolbar, side, collapsed, attributes) {
30
31
  Toolbar,
31
32
  {
32
33
  label: toolbar.label,
33
- dividerSides: "b",
34
+ dividerSides: toolbar.dividerSides,
35
+ centerAlign: toolbar.centerAlign,
36
+ responsive: toolbar.responsive,
37
+ responsiveAt: toolbar.responsiveAt,
38
+ safeAreaEdges: toolbar.safeAreaEdges,
39
+ center: toolbar.center,
34
40
  leading: /* @__PURE__ */ jsxs(Fragment, { children: [
35
41
  toolbar.title,
36
42
  toolbar.panelOnly
@@ -42,6 +48,29 @@ function composedPanelToolbar(toolbar, side, collapsed, attributes) {
42
48
  }
43
49
  );
44
50
  }
51
+ function composedPanelBody({
52
+ toolbar,
53
+ side,
54
+ collapsed,
55
+ attributes,
56
+ pane,
57
+ footer,
58
+ content
59
+ }) {
60
+ return /* @__PURE__ */ jsx(
61
+ Pane,
62
+ {
63
+ header: composedPanelToolbar(toolbar, side, collapsed, attributes),
64
+ footer,
65
+ contentElement: pane?.contentElement,
66
+ contentLabel: pane?.contentLabel,
67
+ separators: pane?.separators,
68
+ safeAreaEdges: pane?.safeAreaEdges,
69
+ chromeDividers: pane?.chromeDividers,
70
+ children: content
71
+ }
72
+ );
73
+ }
45
74
  function relocatedPanelGroups(toolbar, side, collapsed, attributes) {
46
75
  if (!collapsed || !toolbar) return [];
47
76
  return [
@@ -50,6 +79,6 @@ function relocatedPanelGroups(toolbar, side, collapsed, attributes) {
50
79
  ].filter((group) => group !== void 0 && group !== null && group !== false);
51
80
  }
52
81
 
53
- export { collapsiblePanelToggleIcon, composedPanelToolbar, relocatedPanelGroups };
82
+ export { collapsiblePanelToggleIcon, composedPanelBody, relocatedPanelGroups };
54
83
 
55
- //# sourceMappingURL=chunk-N7FHFNT6.js.map
84
+ //# sourceMappingURL=chunk-XCO6YCYM.js.map