@kerfjs/ui 5.0.0-beta.16 → 5.0.0-beta.18

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 (218) hide show
  1. package/README.md +111 -81
  2. package/ai/component-catalog-extension.schema.json +79 -0
  3. package/ai/component-catalog.json +499 -0
  4. package/ai/component-catalog.schema.json +15 -0
  5. package/ai/public-api-signatures-v1.md +86 -32
  6. package/ai/skill.md +60 -51
  7. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  8. package/dist/app-tab.d.ts +1 -1
  9. package/dist/app-tab.js +1 -1
  10. package/dist/catalog.d.ts +12 -3
  11. package/dist/catalog.js +283 -90
  12. package/dist/catalog.js.map +1 -1
  13. package/dist/chunk-43FUQH35.js +83 -0
  14. package/dist/chunk-43FUQH35.js.map +1 -0
  15. package/dist/{chunk-YGN7OMLT.js → chunk-4TRDV6RL.js} +2 -2
  16. package/dist/chunk-4TRDV6RL.js.map +1 -0
  17. package/dist/chunk-6ETZKKAE.js +38 -0
  18. package/dist/chunk-6ETZKKAE.js.map +1 -0
  19. package/dist/chunk-6WTETUZ6.js +21 -0
  20. package/dist/chunk-6WTETUZ6.js.map +1 -0
  21. package/dist/chunk-7L6EHUMV.js +31 -0
  22. package/dist/chunk-7L6EHUMV.js.map +1 -0
  23. package/dist/chunk-BBRXX6PF.js +108 -0
  24. package/dist/chunk-BBRXX6PF.js.map +1 -0
  25. package/dist/chunk-DPDBVKNA.js +113 -0
  26. package/dist/chunk-DPDBVKNA.js.map +1 -0
  27. package/dist/chunk-ELSJX4W7.js +68 -0
  28. package/dist/chunk-ELSJX4W7.js.map +1 -0
  29. package/dist/{chunk-LCOBDOCC.js → chunk-ENVTNLYC.js} +153 -67
  30. package/dist/chunk-ENVTNLYC.js.map +1 -0
  31. package/dist/{chunk-AHQI52QO.js → chunk-FEY65TBV.js} +6 -2
  32. package/dist/chunk-FEY65TBV.js.map +1 -0
  33. package/dist/chunk-JTHUXDN2.js +58 -0
  34. package/dist/chunk-JTHUXDN2.js.map +1 -0
  35. package/dist/chunk-LPOMRC4C.js +25 -0
  36. package/dist/chunk-LPOMRC4C.js.map +1 -0
  37. package/dist/chunk-NENBUYX5.js +79 -0
  38. package/dist/chunk-NENBUYX5.js.map +1 -0
  39. package/dist/{chunk-XXMOARTH.js → chunk-NVWXKU37.js} +57 -16
  40. package/dist/chunk-NVWXKU37.js.map +1 -0
  41. package/dist/chunk-PIDTEQ3U.js +105 -0
  42. package/dist/chunk-PIDTEQ3U.js.map +1 -0
  43. package/dist/chunk-PX3YSS5C.js +32 -0
  44. package/dist/chunk-PX3YSS5C.js.map +1 -0
  45. package/dist/chunk-PZQVSDLH.js +61 -0
  46. package/dist/chunk-PZQVSDLH.js.map +1 -0
  47. package/dist/chunk-QIRXYKCE.js +113 -0
  48. package/dist/chunk-QIRXYKCE.js.map +1 -0
  49. package/dist/chunk-QO55FN2Y.js +20 -0
  50. package/dist/chunk-QO55FN2Y.js.map +1 -0
  51. package/dist/chunk-QQFJMRIB.js +45 -0
  52. package/dist/chunk-QQFJMRIB.js.map +1 -0
  53. package/dist/chunk-S3HKPI7I.js +218 -0
  54. package/dist/chunk-S3HKPI7I.js.map +1 -0
  55. package/dist/chunk-S3PCZ7NV.js +38 -0
  56. package/dist/chunk-S3PCZ7NV.js.map +1 -0
  57. package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
  58. package/dist/chunk-SRSJO5QE.js.map +1 -0
  59. package/dist/chunk-U5IFGQCD.js +117 -0
  60. package/dist/chunk-U5IFGQCD.js.map +1 -0
  61. package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
  62. package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
  63. package/dist/chunk-ZK2G3VR5.js +35 -0
  64. package/dist/chunk-ZK2G3VR5.js.map +1 -0
  65. package/dist/chunk-ZVI5YST2.js +41 -0
  66. package/dist/chunk-ZVI5YST2.js.map +1 -0
  67. package/dist/collapsible-panel.d.ts +2 -2
  68. package/dist/collapsible-panel.js +47 -6
  69. package/dist/collapsible-panel.js.map +1 -1
  70. package/dist/device-class.js +33 -5
  71. package/dist/device-class.js.map +1 -1
  72. package/dist/disclosure-arrow.js +1 -1
  73. package/dist/empty-state.d.ts +1 -1
  74. package/dist/empty-state.js +1 -1
  75. package/dist/floating-toolbar.d.ts +1 -1
  76. package/dist/floating-toolbar.js +1 -1
  77. package/dist/index.js +25 -25
  78. package/dist/list-action-row.d.ts +1 -1
  79. package/dist/list-action-row.js +1 -1
  80. package/dist/list-header.d.ts +1 -1
  81. package/dist/list-header.js +1 -1
  82. package/dist/list-inset-control.d.ts +1 -1
  83. package/dist/list-inset-control.js +1 -1
  84. package/dist/list-inset-text.d.ts +1 -1
  85. package/dist/list-inset-text.js +1 -1
  86. package/dist/list-item.d.ts +1 -1
  87. package/dist/list-item.js +1 -1
  88. package/dist/loading-spinner.js +1 -1
  89. package/dist/nav-stack.d.ts +1 -1
  90. package/dist/nav-stack.js +1 -1
  91. package/dist/panel-header.d.ts +1 -1
  92. package/dist/panel-header.js +1 -1
  93. package/dist/resizable-region.d.ts +1 -1
  94. package/dist/resizable-region.js +1 -1
  95. package/dist/segmented-control.js +1 -1
  96. package/dist/select.d.ts +1 -1
  97. package/dist/select.js +1 -1
  98. package/dist/skeleton.d.ts +1 -1
  99. package/dist/skeleton.js +1 -1
  100. package/dist/split-view.d.ts +1 -1
  101. package/dist/split-view.js +70 -10
  102. package/dist/split-view.js.map +1 -1
  103. package/dist/state-banner.d.ts +1 -1
  104. package/dist/state-banner.js +1 -1
  105. package/dist/styles/catalog.css +48 -1
  106. package/dist/styles/toolbar-text.css +54 -2
  107. package/dist/styles/webawesome.css +131 -0
  108. package/dist/tab-bar.d.ts +1 -1
  109. package/dist/tab-bar.js +1 -1
  110. package/dist/tab-scaffold.d.ts +1 -1
  111. package/dist/tab-scaffold.js +43 -8
  112. package/dist/tab-scaffold.js.map +1 -1
  113. package/dist/token-search-field.js +1 -1
  114. package/dist/toolbar-control-group.d.ts +1 -1
  115. package/dist/toolbar-control-group.js +1 -1
  116. package/dist/toolbar-text.d.ts +17 -1
  117. package/dist/toolbar-text.js +1 -1
  118. package/dist/toolbar.d.ts +1 -1
  119. package/dist/toolbar.js +1 -1
  120. package/dist/value-table.d.ts +2 -2
  121. package/dist/value-table.js +1 -1
  122. package/dist/wire-catalog.d.ts +31 -2
  123. package/dist/wire-catalog.js +203 -8
  124. package/dist/wire-catalog.js.map +1 -1
  125. package/dist/wire-nav-stack.js +22 -7
  126. package/dist/wire-nav-stack.js.map +1 -1
  127. package/dist/wire-resizable-regions.d.ts +1 -1
  128. package/dist/wire-resizable-regions.js +1 -1
  129. package/dist/wire-sidebar.js +52 -41
  130. package/dist/wire-sidebar.js.map +1 -1
  131. package/dist/wire-tab-bars.js +1 -1
  132. package/dist/wire-tab-scaffold.js +9 -4
  133. package/dist/wire-tab-scaffold.js.map +1 -1
  134. package/dist/wire-token-search-fields.d.ts +1 -1
  135. package/dist/wire-token-search-fields.js +1 -1
  136. package/dist/workbench.d.ts +1 -1
  137. package/dist/workbench.js +56 -9
  138. package/dist/workbench.js.map +1 -1
  139. package/docs/app-layouts.md +7 -7
  140. package/docs/catalog.md +110 -25
  141. package/docs/collapsible-panel.md +38 -11
  142. package/docs/component-contract.md +30 -2
  143. package/docs/component-selection.md +76 -65
  144. package/docs/design/templates.md +1 -1
  145. package/docs/design-philosophy.md +5 -5
  146. package/docs/device-class.md +8 -8
  147. package/docs/examples/command-palette-adapter.tsx +67 -17
  148. package/docs/examples/component-catalog-extension.json +45 -0
  149. package/docs/layout.md +19 -19
  150. package/docs/nav-stack.md +15 -6
  151. package/docs/recipes.md +4 -4
  152. package/docs/split-view.md +3 -3
  153. package/docs/tab-scaffold.md +16 -7
  154. package/docs/ux-demo.md +2 -2
  155. package/docs/webawesome-theme.md +73 -8
  156. package/docs/workbench.md +18 -5
  157. package/llms.txt +36 -15
  158. package/package.json +6 -4
  159. package/ux-demo/recipes/app-shell.tsx +206 -10
  160. package/ux-demo/recipes/collapsible-sidebar.tsx +167 -44
  161. package/ux-demo/recipes/compact-toolbar.tsx +114 -12
  162. package/ux-demo/recipes/composer-form.tsx +106 -18
  163. package/ux-demo/recipes/list-detail-dialog.tsx +144 -8
  164. package/ux-demo/recipes/list-workspace-states.tsx +165 -8
  165. package/ux-demo/recipes/loaders.ts +5 -2
  166. package/ux-demo/recipes/loading-inspector.tsx +124 -41
  167. package/ux-demo/recipes/mount-recipe.ts +27 -6
  168. package/ux-demo/recipes/navigation-sidebar.tsx +120 -9
  169. package/ux-demo/recipes/navigation-stack.tsx +61 -19
  170. package/ux-demo/recipes/types.ts +3 -1
  171. package/ux-demo/recipes/workspace-header.tsx +57 -2
  172. package/dist/chunk-2Z5TWHKQ.js +0 -34
  173. package/dist/chunk-2Z5TWHKQ.js.map +0 -1
  174. package/dist/chunk-37T3VNIZ.js +0 -19
  175. package/dist/chunk-37T3VNIZ.js.map +0 -1
  176. package/dist/chunk-55DATV3A.js +0 -10
  177. package/dist/chunk-55DATV3A.js.map +0 -1
  178. package/dist/chunk-5ATCDSQS.js +0 -42
  179. package/dist/chunk-5ATCDSQS.js.map +0 -1
  180. package/dist/chunk-5E2HVJ33.js +0 -10
  181. package/dist/chunk-5E2HVJ33.js.map +0 -1
  182. package/dist/chunk-7BR3DO2A.js.map +0 -1
  183. package/dist/chunk-7JB7VPRI.js +0 -34
  184. package/dist/chunk-7JB7VPRI.js.map +0 -1
  185. package/dist/chunk-7LDCTU7D.js +0 -134
  186. package/dist/chunk-7LDCTU7D.js.map +0 -1
  187. package/dist/chunk-AHQI52QO.js.map +0 -1
  188. package/dist/chunk-AQNKJRFH.js +0 -79
  189. package/dist/chunk-AQNKJRFH.js.map +0 -1
  190. package/dist/chunk-AVZHJN6C.js +0 -14
  191. package/dist/chunk-AVZHJN6C.js.map +0 -1
  192. package/dist/chunk-B24C4A6T.js +0 -22
  193. package/dist/chunk-B24C4A6T.js.map +0 -1
  194. package/dist/chunk-BLK3UEEI.js +0 -23
  195. package/dist/chunk-BLK3UEEI.js.map +0 -1
  196. package/dist/chunk-CH4SQ6H5.js +0 -39
  197. package/dist/chunk-CH4SQ6H5.js.map +0 -1
  198. package/dist/chunk-DAFFDO33.js +0 -14
  199. package/dist/chunk-DAFFDO33.js.map +0 -1
  200. package/dist/chunk-I7INRJO4.js +0 -17
  201. package/dist/chunk-I7INRJO4.js.map +0 -1
  202. package/dist/chunk-L4OKFDJY.js +0 -24
  203. package/dist/chunk-L4OKFDJY.js.map +0 -1
  204. package/dist/chunk-LCOBDOCC.js.map +0 -1
  205. package/dist/chunk-M5JRI6MN.js +0 -27
  206. package/dist/chunk-M5JRI6MN.js.map +0 -1
  207. package/dist/chunk-RNPGFQ33.js +0 -10
  208. package/dist/chunk-RNPGFQ33.js.map +0 -1
  209. package/dist/chunk-RUNWEPR4.js +0 -10
  210. package/dist/chunk-RUNWEPR4.js.map +0 -1
  211. package/dist/chunk-VPCTCUED.js +0 -10
  212. package/dist/chunk-VPCTCUED.js.map +0 -1
  213. package/dist/chunk-WVPYVDXY.js +0 -15
  214. package/dist/chunk-WVPYVDXY.js.map +0 -1
  215. package/dist/chunk-XE5ZLPCC.js +0 -20
  216. package/dist/chunk-XE5ZLPCC.js.map +0 -1
  217. package/dist/chunk-XXMOARTH.js.map +0 -1
  218. package/dist/chunk-YGN7OMLT.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":";;;;;;AA4CO,SAAS,UAAU,EAAE,EAAA,EAAI,OAAO,IAAA,EAAM,MAAA,EAAQ,UAAU,KAAA,EAAO,YAAA,GAAe,OAAO,SAAA,GAAY,EAAA,EAAI,cAAc,EAAA,EAAI,SAAA,GAAY,QAAQ,SAAA,EAAW,SAAA,GAAY,IAAG,EAAmB;AAC7L,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,KAAA,GAAQ,YAAA,GACV,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAK,EAAG,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,WAAA,EAAa,OAAA,EAAS,MAAA,EAAQ,CAAA,GACzG,CAAC,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,CAAA;AACrD,IAAA,uBAAO,GAAA,CAAC,SAAI,KAAA,EAAO,CAAA,uCAAA,EAA0C,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,mBAAgB,SAAA,EACnI,QAAA,kBAAA,GAAA,CAAC,YAAS,EAAA,EAAI,CAAA,EAAG,EAAE,CAAA,MAAA,CAAA,EAAU,KAAA,EAAc,KAAA,EAAc,SAAA,EAAsB,CAAA,EACjF,CAAA;AAAA,EACF;AACA,EAAA,MAAM,QAAA,GAAW,SAAA,mBACb,GAAA,CAAC,eAAA,EAAA,EAAgB,IAAI,CAAA,EAAG,EAAE,CAAA,KAAA,CAAA,EAAS,KAAA,EAAO,aAAa,MAAA,EAAQ,IAAA,EAAM,SAAA,CAAU,IAAA,EAAM,KAAK,SAAA,CAAU,GAAA,EAAK,GAAA,EAAK,SAAA,CAAU,KACtH,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,mBAAe,IAAA,EAAE,QAAA,EAAA,IAAA,EAAK,CAAA,EACnE,CAAA,uBACC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,iBAAA,EAAe,MAAE,QAAA,EAAA,IAAA,EAAK,CAAA;AACrE,EAAA,uBAAO,IAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAO,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,YAAA,EAAa,iBAAA,EAAgB,OAAA,EAAQ,cAAY,KAAA,EAC9H,QAAA,EAAA;AAAA,IAAA,QAAA;AAAA,oBACD,GAAA,CAAC,SAAI,KAAA,EAAM,iCAAA,EAAkC,qBAAiB,IAAA,EAAC,YAAA,EAAY,WAAA,IAAe,MAAA,EAAY,QAAA,EAAA,MAAA,EAAO;AAAA,GAAA,EAC/G,CAAA;AACF","file":"split-view.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { NavStack } from './nav-stack.js';\nimport { ResizableRegion } from './resizable-region.js';\n\nexport interface SplitViewResizable {\n size: number;\n min: number;\n max: number;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: SafeHtml;\n /** The detail (secondary) pane. */\n detail: SafeHtml;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({ id, label, list, detail, compact = false, detailActive = false, listTitle = '', detailTitle = '', backLabel = 'Back', resizable, className = '' }: SplitViewProps) {\n if (compact) {\n const views = detailActive\n ? [{ key: 'list', title: listTitle, content: list }, { key: 'detail', title: detailTitle, content: detail }]\n : [{ key: 'list', title: listTitle, content: list }];\n return <div class={`kui-split-view kui-split-view--compact ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"compact\">\n <NavStack id={`${id}-stack`} label={label} views={views} backLabel={backLabel} />\n </div>;\n }\n const listPane = resizable\n ? <ResizableRegion id={`${id}-list`} label={listTitle || 'List'} size={resizable.size} min={resizable.min} max={resizable.max}>\n <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>\n </ResizableRegion>\n : <div class=\"kui-split-view__list kui-pane\" data-split-list>{list}</div>;\n return <div class={`kui-split-view ${className}`.trim()} id={id} data-component=\"split-view\" data-split-mode=\"split\" aria-label={label}>\n {listPane}\n <div class=\"kui-split-view__detail kui-pane\" data-split-detail aria-label={detailTitle || undefined}>{detail}</div>\n </div>;\n}\n"]}
1
+ {"version":3,"sources":["../src/split-view.tsx"],"names":[],"mappings":";;;;;;AA4CO,SAAS,SAAA,CAAU;AAAA,EACxB,EAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA,GAAU,KAAA;AAAA,EACV,YAAA,GAAe,KAAA;AAAA,EACf,SAAA,GAAY,EAAA;AAAA,EACZ,WAAA,GAAc,EAAA;AAAA,EACd,SAAA,GAAY,MAAA;AAAA,EACZ,SAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAAmB;AACjB,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,QAAQ,YAAA,GACV;AAAA,MACE,EAAE,GAAA,EAAK,MAAA,EAAQ,KAAA,EAAO,SAAA,EAAW,SAAS,IAAA,EAAK;AAAA,MAC/C,EAAE,GAAA,EAAK,QAAA,EAAU,KAAA,EAAO,WAAA,EAAa,SAAS,MAAA;AAAO,KACvD,GACA,CAAC,EAAE,GAAA,EAAK,QAAQ,KAAA,EAAO,SAAA,EAAW,OAAA,EAAS,IAAA,EAAM,CAAA;AACrD,IAAA,uBACE,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,CAAA,uCAAA,EAA0C,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,QAClE,EAAA;AAAA,QACA,gBAAA,EAAe,YAAA;AAAA,QACf,iBAAA,EAAgB,SAAA;AAAA,QAEhB,QAAA,kBAAA,GAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,EAAA,EAAI,GAAG,EAAE,CAAA,MAAA,CAAA;AAAA,YACT,KAAA;AAAA,YACA,KAAA;AAAA,YACA;AAAA;AAAA;AACF;AAAA,KACF;AAAA,EAEJ;AACA,EAAA,MAAM,WAAW,SAAA,mBACf,GAAA;AAAA,IAAC,eAAA;AAAA,IAAA;AAAA,MACC,EAAA,EAAI,GAAG,EAAE,CAAA,KAAA,CAAA;AAAA,MACT,OAAO,SAAA,IAAa,MAAA;AAAA,MACpB,MAAM,SAAA,CAAU,IAAA;AAAA,MAChB,KAAK,SAAA,CAAU,GAAA;AAAA,MACf,KAAK,SAAA,CAAU,GAAA;AAAA,MAEf,8BAAC,KAAA,EAAA,EAAI,KAAA,EAAM,+BAAA,EAAgC,iBAAA,EAAe,MACvD,QAAA,EAAA,IAAA,EACH;AAAA;AAAA,sBAGF,GAAA,CAAC,KAAA,EAAA,EAAI,OAAM,+BAAA,EAAgC,iBAAA,EAAe,MACvD,QAAA,EAAA,IAAA,EACH,CAAA;AAEF,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,eAAA,EAAkB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC1C,EAAA;AAAA,MACA,gBAAA,EAAe,YAAA;AAAA,MACf,iBAAA,EAAgB,OAAA;AAAA,MAChB,YAAA,EAAY,KAAA;AAAA,MAEX,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,wBACD,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,iCAAA;AAAA,YACN,mBAAA,EAAiB,IAAA;AAAA,YACjB,cAAY,WAAA,IAAe,MAAA;AAAA,YAE1B,QAAA,EAAA;AAAA;AAAA;AACH;AAAA;AAAA,GACF;AAEJ","file":"split-view.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport { NavStack } from './nav-stack.js';\nimport { ResizableRegion } from './resizable-region.js';\n\nexport interface SplitViewResizable {\n size: number;\n min: number;\n max: number;\n}\n\nexport interface SplitViewProps {\n id: string;\n label: string;\n /** The list (primary) pane. */\n list: SafeHtml;\n /** The detail (secondary) pane. */\n detail: SafeHtml;\n /**\n * Compact (\"one pane at a time\") classes — a handset or portrait tablet.\n * Derive from `deviceClass().value.compact`. When true the split collapses to\n * a `NavStack`: the list is the root and the detail is pushed over it.\n */\n compact?: boolean;\n /** In compact mode, whether the detail is currently pushed over the list. */\n detailActive?: boolean;\n /** Title/label for the list (compact NavStack root + region label). */\n listTitle?: string;\n /** Title/label for the detail (compact NavStack pushed view + region label). */\n detailTitle?: string;\n /** Back label for the compact NavStack (default \"Back\"). */\n backLabel?: string;\n /** A resizable separator on roomy classes (min/max px). Omit for a fixed split. */\n resizable?: SplitViewResizable;\n className?: string;\n}\n\n/**\n * A list-detail split. On roomy classes it shows both panes side\n * by side with an optional resizable separator; on compact classes it collapses\n * to a `NavStack` (list → detail). See `docs/23-app-layouts.md` §3.2. Compose the\n * resizable wiring with `wireResizableRegions` and the compact back with\n * `wireNavStack`.\n */\nexport function SplitView({\n id,\n label,\n list,\n detail,\n compact = false,\n detailActive = false,\n listTitle = '',\n detailTitle = '',\n backLabel = 'Back',\n resizable,\n className = '',\n}: SplitViewProps) {\n if (compact) {\n const views = detailActive\n ? [\n { key: 'list', title: listTitle, content: list },\n { key: 'detail', title: detailTitle, content: detail },\n ]\n : [{ key: 'list', title: listTitle, content: list }];\n return (\n <div\n class={`kui-split-view kui-split-view--compact ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"compact\"\n >\n <NavStack\n id={`${id}-stack`}\n label={label}\n views={views}\n backLabel={backLabel}\n />\n </div>\n );\n }\n const listPane = resizable ? (\n <ResizableRegion\n id={`${id}-list`}\n label={listTitle || 'List'}\n size={resizable.size}\n min={resizable.min}\n max={resizable.max}\n >\n <div class=\"kui-split-view__list kui-pane\" data-split-list>\n {list}\n </div>\n </ResizableRegion>\n ) : (\n <div class=\"kui-split-view__list kui-pane\" data-split-list>\n {list}\n </div>\n );\n return (\n <div\n class={`kui-split-view ${className}`.trim()}\n id={id}\n data-component=\"split-view\"\n data-split-mode=\"split\"\n aria-label={label}\n >\n {listPane}\n <div\n class=\"kui-split-view__detail kui-pane\"\n data-split-detail\n aria-label={detailTitle || undefined}\n >\n {detail}\n </div>\n </div>\n );\n}\n"]}
@@ -12,6 +12,6 @@ interface StateBannerProps {
12
12
  /** Render the title and detail as unanimated loading skeletons, keeping the icon and tone. */
13
13
  placeholder?: boolean;
14
14
  }
15
- declare function StateBanner({ title, detail, icon, action, tone, urgency, className, placeholder }: StateBannerProps): SafeHtml;
15
+ declare function StateBanner({ title, detail, icon, action, tone, urgency, className, placeholder, }: StateBannerProps): SafeHtml;
16
16
 
17
17
  export { StateBanner, type StateBannerProps, type StateBannerTone };
@@ -1,4 +1,4 @@
1
- export { StateBanner } from './chunk-I7INRJO4.js';
1
+ export { StateBanner } from './chunk-6ETZKKAE.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=state-banner.js.map
@@ -104,7 +104,28 @@
104
104
  }
105
105
 
106
106
  .kui-catalog__items .kui-list-item {
107
- grid-template-columns: minmax(0, 1fr);
107
+ grid-template-columns: minmax(0, 1fr) auto;
108
+ }
109
+
110
+ .kui-catalog__tags {
111
+ display: inline-flex;
112
+ min-width: 0;
113
+ flex-wrap: wrap;
114
+ justify-content: flex-end;
115
+ gap: var(--kui-space-2xs);
116
+ }
117
+
118
+ .kui-catalog__tag {
119
+ display: inline-flex;
120
+ padding: 0.125rem 0.375rem;
121
+ border: 1px solid var(--kui-color-warning-border-quiet);
122
+ border-radius: 999px;
123
+ color: var(--kui-color-warning-text);
124
+ background: var(--kui-color-warning);
125
+ font-size: var(--kui-font-2xs);
126
+ font-weight: 650;
127
+ line-height: 1.2;
128
+ white-space: nowrap;
108
129
  }
109
130
 
110
131
  .kui-catalog__group--secondary {
@@ -304,6 +325,32 @@
304
325
  place-items: center;
305
326
  }
306
327
 
328
+ /* Optional devtools-style geometry overlay. `wireCatalogGeometryOverlay` draws
329
+ a quiet dashed outer bound for transparent specimens and orange bands for
330
+ non-zero margins. */
331
+ .kui-catalog__geometry-overlay {
332
+ position: absolute;
333
+ z-index: 3;
334
+ pointer-events: none;
335
+ inset: 0;
336
+ }
337
+
338
+ .kui-catalog__geometry-bound,
339
+ .kui-catalog__geometry-margin {
340
+ position: absolute;
341
+ top: 0;
342
+ left: 0;
343
+ box-sizing: border-box;
344
+ }
345
+
346
+ .kui-catalog__geometry-bound {
347
+ border: 1px dashed color-mix(in srgb, var(--kui-color-text) 40%, transparent);
348
+ }
349
+
350
+ .kui-catalog__geometry-margin {
351
+ background: color-mix(in srgb, #f6a94c 55%, transparent);
352
+ }
353
+
307
354
  .kui-catalog__footer {
308
355
  --kui-toolbar-gap: 0.25rem;
309
356
  --kui-toolbar-group-size: 2rem;
@@ -9,11 +9,19 @@
9
9
  color: var(--kui-color-neutral-on-quiet);
10
10
  font-weight: 650;
11
11
  line-height: 1;
12
- text-overflow: ellipsis;
13
- white-space: nowrap;
14
12
  align-items: center;
15
13
  }
16
14
 
15
+ /* The text lives in a block child, not directly in the flex box, so
16
+ `text-overflow: ellipsis` actually applies (it is a no-op on a flex item). */
17
+ .kui-toolbar-text__text {
18
+ min-width: 0;
19
+ max-width: 100%;
20
+ overflow: hidden;
21
+ white-space: nowrap;
22
+ text-overflow: ellipsis;
23
+ }
24
+
17
25
  .kui-toolbar-text[data-size="xlarge"] {
18
26
  /* Matches the page/panel title: the same responsive clamp so a PanelHeader
19
27
  title reads at the page-title scale without a bespoke override. Height grows
@@ -38,3 +46,47 @@
38
46
  font-family: var(--kui-font-mono);
39
47
  font-size: var(--kui-font-xs);
40
48
  }
49
+
50
+ /* Single line, no ellipsis: hard-clip the overflow instead of showing …. */
51
+ .kui-toolbar-text[data-ellipsis="false"] .kui-toolbar-text__text {
52
+ text-overflow: clip;
53
+ }
54
+
55
+ /* Wrap onto multiple lines. The box grows to fit and switches from the centered
56
+ single-line row to a top-aligned block with readable leading; a min-height keeps
57
+ a one-line label at the toolbar row height. */
58
+ .kui-toolbar-text[data-wrap="true"] {
59
+ align-items: flex-start;
60
+ height: auto;
61
+ min-height: 2.5rem;
62
+ }
63
+
64
+ .kui-toolbar-text[data-size="xlarge"][data-wrap="true"] {
65
+ min-height: 2.75rem;
66
+ }
67
+
68
+ .kui-toolbar-text[data-wrap="true"] .kui-toolbar-text__text {
69
+ white-space: normal;
70
+ line-height: 1.25;
71
+ }
72
+
73
+ /* Wrap capped to N lines with an ellipsis at the cut. `-webkit-line-clamp` needs
74
+ the box display and emits the … itself; the unprefixed `line-clamp` follows for
75
+ engines that ship it. */
76
+ .kui-toolbar-text[data-wrap="true"][data-max-lines] .kui-toolbar-text__text {
77
+ display: -webkit-box;
78
+ -webkit-box-orient: vertical;
79
+ -webkit-line-clamp: var(--kui-toolbar-text-max-lines);
80
+ line-clamp: var(--kui-toolbar-text-max-lines);
81
+ overflow: hidden;
82
+ }
83
+
84
+ /* Wrap capped to N lines without an ellipsis: clip at a max-height instead of
85
+ line-clamp (which always ellipsizes). */
86
+ .kui-toolbar-text[data-wrap="true"][data-max-lines][data-ellipsis="false"]
87
+ .kui-toolbar-text__text {
88
+ display: block;
89
+ -webkit-line-clamp: none;
90
+ line-clamp: none;
91
+ max-height: calc(var(--kui-toolbar-text-max-lines) * 1.25em);
92
+ }
@@ -175,6 +175,19 @@
175
175
  --wa-form-control-border-color: var(--wa-color-neutral-border-normal);
176
176
  --wa-form-control-border-radius: var(--wa-border-radius-m);
177
177
  --wa-form-control-activated-color: var(--wa-color-brand-fill-loud);
178
+ /* Field inset: a 1px border with 8px inside it, the same content-item
179
+ geometry the Kerf primitives use (docs/layout.md). WA's defaults are a
180
+ larger 0.75em/1em pad; this brings every form field onto our 8px rhythm
181
+ (and a ~40px single-line control height). */
182
+ --wa-form-control-border-width: var(--kui-layout-item-border-width, 1px);
183
+ --wa-form-control-padding-block: var(
184
+ --kui-layout-item-padding,
185
+ 0.5rem
186
+ );
187
+ --wa-form-control-padding-inline: var(
188
+ --kui-layout-item-padding,
189
+ 0.5rem
190
+ );
178
191
  --wa-panel-border-radius: var(--wa-border-radius-l);
179
192
  --wa-tooltip-background-color: var(--wa-color-neutral-fill-loud);
180
193
  --wa-tooltip-content-color: var(--wa-color-neutral-on-loud);
@@ -184,6 +197,13 @@
184
197
  --kui-wa-carousel-dot-hit-size: 20px;
185
198
  --kui-wa-carousel-control-size: 28px;
186
199
  --kui-wa-carousel-icon-size: 16px;
200
+ /* Non-field chrome uses Kerf's control, surface, and container spacing:
201
+ 8px inside controls/surfaces, 8px around bordered surfaces, and 16px
202
+ inside the remaining content containers. */
203
+ --kui-wa-control-inset: var(--kui-layout-item-padding, 0.5rem);
204
+ --kui-wa-surface-inset: var(--kui-layout-item-padding, 0.5rem);
205
+ --kui-wa-surface-margin: var(--kui-layout-inline-margin, 0.5rem);
206
+ --kui-wa-container-inset: var(--kui-space-m, 1rem);
187
207
  --kui-disclosure-icon-scale: 0.5;
188
208
  --wa-shadow-s: 0 1px 3px rgb(0 0 0 / 0.14);
189
209
  --wa-shadow-m: 0 0.35rem 1rem rgb(0 0 0 / 0.11);
@@ -248,9 +268,120 @@
248
268
  transform: scale(var(--kui-disclosure-icon-scale));
249
269
  }
250
270
 
271
+ /* Bordered/fill surfaces follow the same 8px outer margin + 8px inner
272
+ padding contract as a Kerf content item. Accordion owns one outer margin
273
+ for the group; its items retain connected borders. */
274
+ :is(wa-accordion, wa-card, wa-details, wa-callout, wa-include) {
275
+ margin-inline: var(--kui-wa-surface-margin);
276
+ }
277
+
278
+ wa-card,
279
+ wa-details,
280
+ wa-accordion-item {
281
+ /* WA declares this custom property on :host inside each shadow root. The
282
+ important flag is required for a public host override to cross that
283
+ encapsulation boundary. */
284
+ --spacing: var(--kui-wa-surface-inset) !important;
285
+ }
286
+
287
+ /* Card halves --spacing for its header block padding upstream, so pin the
288
+ public part to the same full surface inset as its body and footer. */
289
+ wa-card::part(header) {
290
+ padding: var(--kui-wa-surface-inset);
291
+ }
292
+
293
+ wa-callout {
294
+ padding: var(--kui-wa-surface-inset) !important;
295
+ }
296
+
297
+ wa-include {
298
+ padding: var(--kui-wa-surface-inset);
299
+ }
300
+
301
+ /* Interactive and item chrome follows the content-item 8px inset. */
302
+ wa-tab::part(tab) {
303
+ padding: var(--kui-wa-control-inset);
304
+ }
305
+
306
+ wa-tab-panel {
307
+ --padding: var(--kui-wa-container-inset) 0 !important;
308
+ }
309
+
310
+ wa-tree-item::part(item) {
311
+ margin-inline: var(--kui-layout-inline-margin, 0.5rem);
312
+ padding-inline-end: var(--kui-wa-control-inset);
313
+ border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
314
+ }
315
+
316
+ wa-tag {
317
+ padding-inline: var(--kui-wa-control-inset) !important;
318
+ }
319
+
320
+ wa-dropdown-item {
321
+ padding-inline: var(--kui-wa-control-inset) !important;
322
+ }
323
+
251
324
  wa-popover {
252
325
  --arrow-size: var(--kui-wa-popover-arrow-size);
253
326
  }
327
+
328
+ /* A form field's top label is inset by the field's own border + inline padding
329
+ (1px + 8px = 9px) so the label text lines up with the value inside the field,
330
+ and it is styled exactly like a ListHeader label: uppercase, xs, quiet. */
331
+ :is(
332
+ wa-checkbox-group,
333
+ wa-color-picker,
334
+ wa-input,
335
+ wa-known-date,
336
+ wa-number-input,
337
+ wa-radio-group,
338
+ wa-select,
339
+ wa-textarea,
340
+ wa-time-input
341
+ )::part(form-control-label),
342
+ wa-otp-input::part(label),
343
+ wa-slider::part(label) {
344
+ padding-inline: calc(
345
+ var(--wa-form-control-border-width) +
346
+ var(--wa-form-control-padding-inline)
347
+ );
348
+ color: var(--kui-color-neutral-on-quiet, var(--wa-color-text-quiet));
349
+ font-size: var(--kui-font-xs, var(--wa-font-size-xs));
350
+ font-weight: 650;
351
+ letter-spacing: 0.04em;
352
+ line-height: var(--wa-line-height-condensed);
353
+ text-transform: uppercase;
354
+ }
355
+
356
+ /* Checkbox/radio groups and the color picker have no bordered field shell,
357
+ so their control regions need the content-item's 8px inline outer inset. */
358
+ :is(wa-checkbox-group, wa-color-picker, wa-radio-group)::part(
359
+ form-control-input
360
+ ) {
361
+ margin-inline: var(--kui-layout-inline-margin, 0.5rem);
362
+ }
363
+
364
+ wa-slider::part(slider) {
365
+ margin-inline: var(--kui-layout-inline-margin, 0.5rem);
366
+ }
367
+
368
+ /* Secondary captions and hints align with the value inside bordered fields:
369
+ 1px border + 8px field padding = a 9px logical inset. */
370
+ wa-known-date::part(field-label),
371
+ :is(
372
+ wa-input,
373
+ wa-known-date,
374
+ wa-number-input,
375
+ wa-otp-input,
376
+ wa-select,
377
+ wa-textarea,
378
+ wa-time-input
379
+ )::part(hint) {
380
+ padding-inline: calc(
381
+ var(--wa-form-control-border-width) +
382
+ var(--wa-form-control-padding-inline)
383
+ );
384
+ }
254
385
  }
255
386
 
256
387
  @media (prefers-contrast: more) {
package/dist/tab-bar.d.ts CHANGED
@@ -16,6 +16,6 @@ interface TabBarProps {
16
16
  activation?: 'automatic' | 'manual';
17
17
  }
18
18
  /** Render a controlled tab strip. The application owns selection, order, and persistence. */
19
- declare function TabBar({ id, label, children, leading, trailing, className, activation }: TabBarProps): SafeHtml;
19
+ declare function TabBar({ id, label, children, leading, trailing, className, activation, }: TabBarProps): SafeHtml;
20
20
 
21
21
  export { TabBar, type TabBarProps };
package/dist/tab-bar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { TabBar } from './chunk-AVZHJN6C.js';
1
+ export { TabBar } from './chunk-ZVI5YST2.js';
2
2
 
3
3
  //# sourceMappingURL=tab-bar.js.map
@@ -25,6 +25,6 @@ interface TabScaffoldProps {
25
25
  * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
26
26
  * a bottom bar. See `docs/23-app-layouts.md` §3.4.
27
27
  */
28
- declare function TabScaffold({ id, label, tabs, active, className }: TabScaffoldProps): SafeHtml;
28
+ declare function TabScaffold({ id, label, tabs, active, className, }: TabScaffoldProps): SafeHtml;
29
29
 
30
30
  export { TabScaffold, type TabScaffoldProps, type TabScaffoldTab };
@@ -1,14 +1,49 @@
1
1
  import { jsxs, jsx } from 'kerfjs/jsx-runtime';
2
2
 
3
3
  // src/tab-scaffold.tsx
4
- function TabScaffold({ id, label, tabs, active, className = "" }) {
5
- return /* @__PURE__ */ jsxs("section", { class: `kui-tab-scaffold ${className}`.trim(), id, "data-component": "tab-scaffold", "data-tab-scaffold-id": id, children: [
6
- /* @__PURE__ */ jsx("div", { class: "kui-tab-scaffold__scenes", children: tabs.map((tab) => /* @__PURE__ */ jsx("div", { class: "kui-tab-scaffold__scene", "data-tab-scaffold-scene": tab.id, "data-active": String(tab.id === active), "aria-hidden": String(tab.id !== active), children: tab.content })) }),
7
- /* @__PURE__ */ jsx("nav", { class: "kui-tab-scaffold__bar", role: "tablist", "aria-label": label, children: tabs.map((tab) => /* @__PURE__ */ jsxs("button", { type: "button", class: "kui-tab-scaffold__tab", role: "tab", "data-tab-scaffold-tab": tab.id, "aria-selected": String(tab.id === active), tabindex: tab.id === active ? "0" : "-1", children: [
8
- tab.icon && /* @__PURE__ */ jsx("span", { class: "kui-tab-scaffold__tab-icon", "aria-hidden": "true", children: tab.icon }),
9
- /* @__PURE__ */ jsx("span", { class: "kui-tab-scaffold__tab-label", children: tab.label })
10
- ] })) })
11
- ] });
4
+ function TabScaffold({
5
+ id,
6
+ label,
7
+ tabs,
8
+ active,
9
+ className = ""
10
+ }) {
11
+ return /* @__PURE__ */ jsxs(
12
+ "section",
13
+ {
14
+ class: `kui-tab-scaffold ${className}`.trim(),
15
+ id,
16
+ "data-component": "tab-scaffold",
17
+ "data-tab-scaffold-id": id,
18
+ children: [
19
+ /* @__PURE__ */ jsx("div", { class: "kui-tab-scaffold__scenes", children: tabs.map((tab) => /* @__PURE__ */ jsx(
20
+ "div",
21
+ {
22
+ class: "kui-tab-scaffold__scene",
23
+ "data-tab-scaffold-scene": tab.id,
24
+ "data-active": String(tab.id === active),
25
+ "aria-hidden": String(tab.id !== active),
26
+ children: tab.content
27
+ }
28
+ )) }),
29
+ /* @__PURE__ */ jsx("nav", { class: "kui-tab-scaffold__bar", role: "tablist", "aria-label": label, children: tabs.map((tab) => /* @__PURE__ */ jsxs(
30
+ "button",
31
+ {
32
+ type: "button",
33
+ class: "kui-tab-scaffold__tab",
34
+ role: "tab",
35
+ "data-tab-scaffold-tab": tab.id,
36
+ "aria-selected": String(tab.id === active),
37
+ tabindex: tab.id === active ? "0" : "-1",
38
+ children: [
39
+ tab.icon && /* @__PURE__ */ jsx("span", { class: "kui-tab-scaffold__tab-icon", "aria-hidden": "true", children: tab.icon }),
40
+ /* @__PURE__ */ jsx("span", { class: "kui-tab-scaffold__tab-label", children: tab.label })
41
+ ]
42
+ }
43
+ )) })
44
+ ]
45
+ }
46
+ );
12
47
  }
13
48
 
14
49
  export { TabScaffold };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":";;;AA6BO,SAAS,WAAA,CAAY,EAAE,EAAA,EAAI,KAAA,EAAO,MAAM,MAAA,EAAQ,SAAA,GAAY,IAAG,EAAqB;AACzF,EAAA,uBAAO,IAAA,CAAC,SAAA,EAAA,EAAQ,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK,EAAG,EAAA,EAAQ,gBAAA,EAAe,cAAA,EAAe,sBAAA,EAAsB,EAAA,EACzH,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,0BAAA,EACR,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBAAQ,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,yBAAA,EAA0B,yBAAA,EAAyB,GAAA,CAAI,EAAA,EAAI,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA,EAAG,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA,EAAI,QAAA,EAAA,GAAA,CAAI,OAAA,EAAQ,CAAM,CAAA,EAC9L,CAAA;AAAA,oBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAwB,MAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAC3D,QAAA,EAAA,IAAA,CAAK,IAAI,CAAC,GAAA,qBAAQ,IAAA,CAAC,QAAA,EAAA,EAAO,MAAK,QAAA,EAAS,KAAA,EAAM,uBAAA,EAAwB,IAAA,EAAK,KAAA,EAAM,uBAAA,EAAuB,GAAA,CAAI,EAAA,EAAI,iBAAe,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,GAAG,QAAA,EAAU,GAAA,CAAI,EAAA,KAAO,MAAA,GAAS,MAAM,IAAA,EAC5L,QAAA,EAAA;AAAA,MAAA,GAAA,CAAI,IAAA,wBAAS,MAAA,EAAA,EAAK,KAAA,EAAM,8BAA6B,aAAA,EAAY,MAAA,EAAQ,cAAI,IAAA,EAAK,CAAA;AAAA,sBACnF,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,6BAAA,EAA+B,cAAI,KAAA,EAAM;AAAA,KAAA,EACvD,CAAS,CAAA,EACX;AAAA,GAAA,EACF,CAAA;AACF","file":"tab-scaffold.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface TabScaffoldTab {\n id: string;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: SafeHtml;\n}\n\nexport interface TabScaffoldProps {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: TabScaffoldTab[];\n /** The controlled active tab id (the app owns selection). */\n active: string;\n className?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab scaffold: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-scaffold`'s `wireTabScaffold`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabScaffold({ id, label, tabs, active, className = '' }: TabScaffoldProps) {\n return <section class={`kui-tab-scaffold ${className}`.trim()} id={id} data-component=\"tab-scaffold\" data-tab-scaffold-id={id}>\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => <div class=\"kui-tab-scaffold__scene\" data-tab-scaffold-scene={tab.id} data-active={String(tab.id === active)} aria-hidden={String(tab.id !== active)}>{tab.content}</div>)}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => <button type=\"button\" class=\"kui-tab-scaffold__tab\" role=\"tab\" data-tab-scaffold-tab={tab.id} aria-selected={String(tab.id === active)} tabindex={tab.id === active ? '0' : '-1'}>\n {tab.icon && <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">{tab.icon}</span>}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>)}\n </nav>\n </section>;\n}\n"]}
1
+ {"version":3,"sources":["../src/tab-scaffold.tsx"],"names":[],"mappings":";;;AA6BO,SAAS,WAAA,CAAY;AAAA,EAC1B,EAAA;AAAA,EACA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,MAAA;AAAA,EACA,SAAA,GAAY;AACd,CAAA,EAAqB;AACnB,EAAA,uBACE,IAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,CAAA,iBAAA,EAAoB,SAAS,CAAA,CAAA,CAAG,IAAA,EAAK;AAAA,MAC5C,EAAA;AAAA,MACA,gBAAA,EAAe,cAAA;AAAA,MACf,sBAAA,EAAsB,EAAA;AAAA,MAEtB,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,SAAI,KAAA,EAAM,0BAAA,EACR,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,GAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAM,yBAAA;AAAA,YACN,2BAAyB,GAAA,CAAI,EAAA;AAAA,YAC7B,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACrC,aAAA,EAAa,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YAEpC,QAAA,EAAA,GAAA,CAAI;AAAA;AAAA,SAER,CAAA,EACH,CAAA;AAAA,wBACA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,uBAAA,EAAwB,IAAA,EAAK,SAAA,EAAU,YAAA,EAAY,KAAA,EAC3D,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,qBACT,IAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,KAAA,EAAM,uBAAA;AAAA,YACN,IAAA,EAAK,KAAA;AAAA,YACL,yBAAuB,GAAA,CAAI,EAAA;AAAA,YAC3B,eAAA,EAAe,MAAA,CAAO,GAAA,CAAI,EAAA,KAAO,MAAM,CAAA;AAAA,YACvC,QAAA,EAAU,GAAA,CAAI,EAAA,KAAO,MAAA,GAAS,GAAA,GAAM,IAAA;AAAA,YAEnC,QAAA,EAAA;AAAA,cAAA,GAAA,CAAI,IAAA,wBACF,MAAA,EAAA,EAAK,KAAA,EAAM,8BAA6B,aAAA,EAAY,MAAA,EAClD,cAAI,IAAA,EACP,CAAA;AAAA,8BAEF,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,6BAAA,EAA+B,cAAI,KAAA,EAAM;AAAA;AAAA;AAAA,SAExD,CAAA,EACH;AAAA;AAAA;AAAA,GACF;AAEJ","file":"tab-scaffold.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nexport interface TabScaffoldTab {\n id: string;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: SafeHtml;\n}\n\nexport interface TabScaffoldProps {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: TabScaffoldTab[];\n /** The controlled active tab id (the app owns selection). */\n active: string;\n className?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab scaffold: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-scaffold`'s `wireTabScaffold`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabScaffold({\n id,\n label,\n tabs,\n active,\n className = '',\n}: TabScaffoldProps) {\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n aria-hidden={String(tab.id !== active)}\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n >\n {tab.icon && (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n </span>\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n ))}\n </nav>\n </section>\n );\n}\n"]}
@@ -1,4 +1,4 @@
1
- export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-7LDCTU7D.js';
1
+ export { TokenSearchField, placeTokenSearchCaret, readTokenSearchField } from './chunk-S3HKPI7I.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=token-search-field.js.map
@@ -12,6 +12,6 @@ interface ToolbarControlGroupProps {
12
12
  /** Corner shape: fully round `pill` (default) or a softer `rounded` rectangle. */
13
13
  shape?: 'pill' | 'rounded';
14
14
  }
15
- declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape }: ToolbarControlGroupProps): SafeHtml;
15
+ declare function ToolbarControlGroup({ children, label, className, expanded, single, appearance, tone, buttonAppearance, shape, }: ToolbarControlGroupProps): SafeHtml;
16
16
 
17
17
  export { ToolbarControlGroup, type ToolbarControlGroupProps };
@@ -1,3 +1,3 @@
1
- export { ToolbarControlGroup } from './chunk-RNPGFQ33.js';
1
+ export { ToolbarControlGroup } from './chunk-ZK2G3VR5.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar-control-group.js.map
@@ -17,7 +17,23 @@ interface ToolbarTextProps {
17
17
  headingLevel?: HeadingLevel;
18
18
  /** Render the text as an unanimated loading skeleton instead of its value. */
19
19
  placeholder?: boolean;
20
+ /**
21
+ * Wrap onto multiple lines when the text does not fit, instead of the default
22
+ * single line. Combine with `maxLines` to cap the number of lines. Default false.
23
+ */
24
+ wrap?: boolean;
25
+ /**
26
+ * Show a trailing ellipsis (…) where the text is truncated — on the single line
27
+ * (default), or at the `maxLines` boundary when wrapping. Set false to hard-clip
28
+ * instead. Default true.
29
+ */
30
+ ellipsis?: boolean;
31
+ /**
32
+ * Cap wrapped text to this many lines, truncating past it. Only takes effect with
33
+ * `wrap`; ignored on a single line. `null`/omitted wraps without a line cap. Default null.
34
+ */
35
+ maxLines?: number | null;
20
36
  }
21
- declare function ToolbarText({ text, size, className, id, headingLevel, placeholder }: ToolbarTextProps): kerfjs.SafeHtml;
37
+ declare function ToolbarText({ text, size, className, id, headingLevel, placeholder, wrap, ellipsis, maxLines, }: ToolbarTextProps): kerfjs.SafeHtml;
22
38
 
23
39
  export { type HeadingLevel, ToolbarText, type ToolbarTextProps, type ToolbarTextSize };
@@ -1,4 +1,4 @@
1
- export { ToolbarText } from './chunk-RUNWEPR4.js';
1
+ export { ToolbarText } from './chunk-S3PCZ7NV.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=toolbar-text.js.map
package/dist/toolbar.d.ts CHANGED
@@ -8,6 +8,6 @@ interface ToolbarProps {
8
8
  divider?: boolean;
9
9
  className?: string;
10
10
  }
11
- declare function Toolbar({ leading, center, trailing, label, divider, className }: ToolbarProps): SafeHtml;
11
+ declare function Toolbar({ leading, center, trailing, label, divider, className, }: ToolbarProps): SafeHtml;
12
12
 
13
13
  export { Toolbar, type ToolbarProps };
package/dist/toolbar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Toolbar } from './chunk-DAFFDO33.js';
1
+ export { Toolbar } from './chunk-7L6EHUMV.js';
2
2
 
3
3
  //# sourceMappingURL=toolbar.js.map
@@ -8,13 +8,13 @@ interface ValueTableRowProps {
8
8
  /** Render the value as an unanimated loading skeleton, keeping the field label. */
9
9
  placeholder?: boolean;
10
10
  }
11
- declare function ValueTableRow({ label, value, icon, className, placeholder }: ValueTableRowProps): SafeHtml;
11
+ declare function ValueTableRow({ label, value, icon, className, placeholder, }: ValueTableRowProps): SafeHtml;
12
12
 
13
13
  interface ValueTableProps {
14
14
  label: string;
15
15
  className?: string;
16
16
  children: SafeHtml | readonly SafeHtml[];
17
17
  }
18
- declare function ValueTable({ label, className, children }: ValueTableProps): SafeHtml;
18
+ declare function ValueTable({ label, className, children, }: ValueTableProps): SafeHtml;
19
19
 
20
20
  export { ValueTable, type ValueTableProps, ValueTableRow, type ValueTableRowProps };
@@ -1,4 +1,4 @@
1
- export { ValueTable, ValueTableRow } from './chunk-37T3VNIZ.js';
1
+ export { ValueTable, ValueTableRow } from './chunk-QQFJMRIB.js';
2
2
 
3
3
 
4
4
  //# sourceMappingURL=value-table.js.map
@@ -9,11 +9,40 @@ interface WireCatalogOptions {
9
9
  onToggleSecondary?: () => void;
10
10
  /** When set, `?<urlParam>=<id>` is written on select via `history.replaceState`. */
11
11
  urlParam?: string;
12
+ /**
13
+ * Reveal the chosen sidebar row after selection. `true` uses desktop-safe
14
+ * defaults; pass options to customize scroll alignment or the media guard.
15
+ */
16
+ revealSelection?: boolean | CatalogRevealOptions;
12
17
  selectAction?: string;
13
18
  toggleSidebarAction?: string;
14
19
  toggleThemeAction?: string;
15
20
  toggleSecondaryAction?: string;
16
21
  }
22
+ interface CatalogRevealOptions {
23
+ /** Scroll alignment within the sidebar. Default `'nearest'`. */
24
+ block?: ScrollLogicalPosition;
25
+ /** Cross-axis alignment. Default `'nearest'`. */
26
+ inline?: ScrollLogicalPosition;
27
+ /** Scroll behavior. Default `'auto'`. */
28
+ behavior?: ScrollBehavior;
29
+ /**
30
+ * Only reveal when this media query matches. Defaults to the Catalog's
31
+ * desktop layout; pass `false` to reveal at every viewport size.
32
+ */
33
+ media?: string | false;
34
+ }
35
+ /**
36
+ * Reveal one Catalog sidebar entry after the controlled render settles without
37
+ * moving focus. Returns a cancellation function for rapid selection changes.
38
+ */
39
+ declare function revealCatalogEntry(root: HTMLElement, id: string, { block, inline, behavior, media, }?: CatalogRevealOptions): () => void;
40
+ /**
41
+ * Keep a Catalog's opt-in geometry overlay synchronized with its preview.
42
+ * Transparent specimens receive a dashed outer bound and positive margins use
43
+ * devtools-style orange bands. Returns a disposer.
44
+ */
45
+ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
17
46
  /**
18
47
  * Wire a {@link Catalog}'s interactions with one delegated listener set: sidebar
19
48
  * item selection (and the related-entry popup menu), the sidebar collapse toggle, and
@@ -21,6 +50,6 @@ interface WireCatalogOptions {
21
50
  * them in the callbacks; optionally mirror the active id into the URL via `urlParam`.
22
51
  * Returns a disposer.
23
52
  */
24
- declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, }: WireCatalogOptions): () => void;
53
+ declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, }: WireCatalogOptions): () => void;
25
54
 
26
- export { type WireCatalogOptions, wireCatalog };
55
+ export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };