@kerfjs/ui 5.0.0-beta.56 → 5.0.0-beta.58

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 (287) hide show
  1. package/README.md +81 -37
  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/component-catalog.json +211 -33
  7. package/ai/component-catalog.schema.json +2 -0
  8. package/ai/component-class-owners.cjs +83 -0
  9. package/ai/component-composition-extension.d.ts +7 -0
  10. package/ai/component-composition-extension.schema.json +7 -0
  11. package/ai/{component-catalog-v2-overrides.json → component-composition-rules.json} +2 -1
  12. package/ai/{component-catalog-v2.d.ts → component-composition.d.ts} +9 -5
  13. package/ai/{component-catalog-v2.json → component-composition.json} +155 -24
  14. package/ai/{component-catalog-v2.schema.json → component-composition.schema.json} +21 -5
  15. package/ai/components/README.md +170 -0
  16. package/ai/components/application-tabs.md +65 -0
  17. package/ai/components/badge.md +72 -0
  18. package/ai/components/collapsible-panel.md +102 -0
  19. package/ai/components/content-item.md +90 -0
  20. package/ai/components/disclosure-arrow.md +77 -0
  21. package/ai/components/document-baseline.md +75 -0
  22. package/ai/components/empty-state.md +80 -0
  23. package/ai/components/feedback.md +71 -0
  24. package/ai/components/floating-toolbar.md +80 -0
  25. package/ai/components/foundation.md +65 -0
  26. package/ai/components/grid.md +93 -0
  27. package/ai/components/headers.md +63 -0
  28. package/ai/components/layout.md +75 -0
  29. package/ai/components/list-action-row.md +91 -0
  30. package/ai/components/list-header.md +89 -0
  31. package/ai/components/list-inset-control.md +74 -0
  32. package/ai/components/list-inset-text.md +72 -0
  33. package/ai/components/list-item.md +88 -0
  34. package/ai/components/list.md +103 -0
  35. package/ai/components/loading-spinner.md +72 -0
  36. package/ai/components/lucide-icon.md +66 -0
  37. package/ai/components/nav-stack.md +103 -0
  38. package/ai/components/pane.md +100 -0
  39. package/ai/components/popup-menu.md +82 -0
  40. package/ai/components/recipe-app-shell.md +57 -0
  41. package/ai/components/recipe-collapsible-sidebar.md +57 -0
  42. package/ai/components/recipe-compact-toolbar.md +57 -0
  43. package/ai/components/recipe-composer-form.md +57 -0
  44. package/ai/components/recipe-list-detail-dialog.md +57 -0
  45. package/ai/components/recipe-list-workspace-states.md +57 -0
  46. package/ai/components/recipe-loading-inspector.md +57 -0
  47. package/ai/components/recipe-navigation-sidebar.md +57 -0
  48. package/ai/components/recipe-navigation-stack.md +57 -0
  49. package/ai/components/recipe-workspace-header.md +57 -0
  50. package/ai/components/resize.md +101 -0
  51. package/ai/components/row.md +96 -0
  52. package/ai/components/segmented-control.md +82 -0
  53. package/ai/components/select.md +107 -0
  54. package/ai/components/skeleton.md +84 -0
  55. package/ai/components/spacer.md +86 -0
  56. package/ai/components/split-view.md +102 -0
  57. package/ai/components/state-banner.md +92 -0
  58. package/ai/components/sunken-panel.md +79 -0
  59. package/ai/components/surface-scaffold.md +78 -0
  60. package/ai/components/tab-bar.md +112 -0
  61. package/ai/components/tab-scaffold.md +94 -0
  62. package/ai/components/tabs.md +90 -0
  63. package/ai/components/text.md +82 -0
  64. package/ai/components/token-search-field.md +101 -0
  65. package/ai/components/toolbar-control-group.md +102 -0
  66. package/ai/components/toolbar-text.md +76 -0
  67. package/ai/components/toolbar.md +95 -0
  68. package/ai/components/value-table.md +72 -0
  69. package/ai/components/wa-accordion-item.md +55 -0
  70. package/ai/components/wa-accordion.md +65 -0
  71. package/ai/components/wa-animated-image.md +55 -0
  72. package/ai/components/wa-animation.md +55 -0
  73. package/ai/components/wa-avatar.md +55 -0
  74. package/ai/components/wa-badge.md +55 -0
  75. package/ai/components/wa-breadcrumb-item.md +53 -0
  76. package/ai/components/wa-breadcrumb.md +55 -0
  77. package/ai/components/wa-button-group.md +59 -0
  78. package/ai/components/wa-button.md +55 -0
  79. package/ai/components/wa-callout.md +58 -0
  80. package/ai/components/wa-card.md +59 -0
  81. package/ai/components/wa-carousel-item.md +53 -0
  82. package/ai/components/wa-carousel.md +55 -0
  83. package/ai/components/wa-checkbox-group.md +55 -0
  84. package/ai/components/wa-checkbox.md +55 -0
  85. package/ai/components/wa-color-picker.md +55 -0
  86. package/ai/components/wa-comparison.md +55 -0
  87. package/ai/components/wa-copy-button.md +55 -0
  88. package/ai/components/wa-details.md +61 -0
  89. package/ai/components/wa-dialog.md +59 -0
  90. package/ai/components/wa-divider.md +53 -0
  91. package/ai/components/wa-drawer.md +55 -0
  92. package/ai/components/wa-dropdown-item.md +60 -0
  93. package/ai/components/wa-dropdown.md +60 -0
  94. package/ai/components/wa-format-bytes.md +53 -0
  95. package/ai/components/wa-format-date.md +53 -0
  96. package/ai/components/wa-format-number.md +53 -0
  97. package/ai/components/wa-icon.md +58 -0
  98. package/ai/components/wa-include.md +53 -0
  99. package/ai/components/wa-input.md +59 -0
  100. package/ai/components/wa-intersection-observer.md +53 -0
  101. package/ai/components/wa-known-date.md +53 -0
  102. package/ai/components/wa-markdown.md +53 -0
  103. package/ai/components/wa-mutation-observer.md +53 -0
  104. package/ai/components/wa-number-input.md +55 -0
  105. package/ai/components/wa-option.md +59 -0
  106. package/ai/components/wa-otp-input.md +53 -0
  107. package/ai/components/wa-page.md +53 -0
  108. package/ai/components/wa-pagination.md +55 -0
  109. package/ai/components/wa-popover.md +55 -0
  110. package/ai/components/wa-popup.md +53 -0
  111. package/ai/components/wa-progress-bar.md +53 -0
  112. package/ai/components/wa-progress-ring.md +53 -0
  113. package/ai/components/wa-qr-code.md +53 -0
  114. package/ai/components/wa-radio-group.md +59 -0
  115. package/ai/components/wa-radio.md +55 -0
  116. package/ai/components/wa-random-content.md +53 -0
  117. package/ai/components/wa-rating.md +55 -0
  118. package/ai/components/wa-relative-time.md +53 -0
  119. package/ai/components/wa-resize-observer.md +53 -0
  120. package/ai/components/wa-scroller.md +53 -0
  121. package/ai/components/wa-select.md +63 -0
  122. package/ai/components/wa-skeleton.md +53 -0
  123. package/ai/components/wa-slider.md +55 -0
  124. package/ai/components/wa-spinner.md +58 -0
  125. package/ai/components/wa-split-panel.md +58 -0
  126. package/ai/components/wa-switch.md +53 -0
  127. package/ai/components/wa-tab-group.md +69 -0
  128. package/ai/components/wa-tab-panel.md +60 -0
  129. package/ai/components/wa-tab.md +59 -0
  130. package/ai/components/wa-tag.md +59 -0
  131. package/ai/components/wa-textarea.md +53 -0
  132. package/ai/components/wa-time-input.md +55 -0
  133. package/ai/components/wa-toast-item.md +60 -0
  134. package/ai/components/wa-toast.md +60 -0
  135. package/ai/components/wa-tooltip.md +55 -0
  136. package/ai/components/wa-tree-item.md +55 -0
  137. package/ai/components/wa-tree.md +55 -0
  138. package/ai/components/wa-zoomable-frame.md +55 -0
  139. package/ai/components/workbench.md +114 -0
  140. package/ai/public-api-signatures-v1.md +174 -43
  141. package/ai/skill.md +100 -48
  142. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  143. package/analyzer/component-ownership.d.mts +56 -0
  144. package/analyzer/component-ownership.mjs +184 -0
  145. package/analyzer/index.d.mts +3 -0
  146. package/analyzer/index.mjs +274 -20
  147. package/analyzer/selectors.d.mts +21 -0
  148. package/analyzer/selectors.mjs +212 -0
  149. package/dist/browser/catalog.js +25 -0
  150. package/dist/browser/collapsible-panel.js +7 -0
  151. package/dist/browser/nav-stack.js +8 -0
  152. package/dist/browser/split-view.js +10 -0
  153. package/dist/browser/tab-scaffold.js +4 -0
  154. package/dist/browser/workbench.js +10 -0
  155. package/dist/catalog-resources.d.ts +2 -2
  156. package/dist/catalog.d.ts +3 -3
  157. package/dist/catalog.js +8 -7
  158. package/dist/catalog.js.map +1 -1
  159. package/dist/{chunk-QQOTQTDD.js → chunk-2CCMJTVY.js} +13 -10
  160. package/dist/chunk-2CCMJTVY.js.map +1 -0
  161. package/dist/{chunk-PK4N5QTO.js → chunk-553ASUK6.js} +2 -3
  162. package/dist/chunk-553ASUK6.js.map +1 -0
  163. package/dist/{chunk-G33XC2NB.js → chunk-6YFHCLHG.js} +2 -2
  164. package/dist/chunk-6YFHCLHG.js.map +1 -0
  165. package/dist/{chunk-ZIYOJFZD.js → chunk-7JUBXOIV.js} +17 -4
  166. package/dist/chunk-7JUBXOIV.js.map +1 -0
  167. package/dist/{chunk-T4UZTNZ4.js → chunk-EVYKTVBQ.js} +2 -11
  168. package/dist/chunk-EVYKTVBQ.js.map +1 -0
  169. package/dist/{chunk-AK67F6QN.js → chunk-EZVNC4J6.js} +4 -1
  170. package/dist/chunk-EZVNC4J6.js.map +1 -0
  171. package/dist/{chunk-MA6Z6EIM.js → chunk-F4QMLOXJ.js} +3 -2
  172. package/dist/chunk-F4QMLOXJ.js.map +1 -0
  173. package/dist/chunk-JCV4GXWB.js +249 -0
  174. package/dist/chunk-JCV4GXWB.js.map +1 -0
  175. package/dist/chunk-K47P7QZC.js +17 -0
  176. package/dist/chunk-K47P7QZC.js.map +1 -0
  177. package/dist/{chunk-MOBRFZH3.js → chunk-OUK6QRDR.js} +2 -12
  178. package/dist/chunk-OUK6QRDR.js.map +1 -0
  179. package/dist/{chunk-VNPQDCQZ.js → chunk-QOWG4ZCL.js} +3 -2
  180. package/dist/chunk-QOWG4ZCL.js.map +1 -0
  181. package/dist/{chunk-V65EOWNF.js → chunk-QPUPLNNB.js} +20 -8
  182. package/dist/chunk-QPUPLNNB.js.map +1 -0
  183. package/dist/{chunk-O3EXIBEZ.js → chunk-W4XKTST6.js} +8 -7
  184. package/dist/chunk-W4XKTST6.js.map +1 -0
  185. package/dist/{chunk-K6UNVKDK.js → chunk-XDKAYSVD.js} +3 -1
  186. package/dist/chunk-XDKAYSVD.js.map +1 -0
  187. package/dist/collapsible-panel.d.ts +9 -9
  188. package/dist/collapsible-panel.js +2 -2
  189. package/dist/collapsible-panel.js.map +1 -1
  190. package/dist/index.d.ts +2 -1
  191. package/dist/index.js +11 -9
  192. package/dist/list-action-row.js +2 -1
  193. package/dist/list-header.js +1 -1
  194. package/dist/list-item.js +2 -1
  195. package/dist/nav-stack.d.ts +13 -1
  196. package/dist/nav-stack.js +1 -1
  197. package/dist/pane.d.ts +20 -3
  198. package/dist/pane.js +1 -1
  199. package/dist/{panel-toolbar-C8sF-YZC.d.ts → panel-toolbar-DqwtBxQL.d.ts} +13 -13
  200. package/dist/select.js +1 -1
  201. package/dist/split-view.d.ts +3 -3
  202. package/dist/split-view.js +3 -2
  203. package/dist/split-view.js.map +1 -1
  204. package/dist/state-banner.js +1 -1
  205. package/dist/styles/app-tab.css +31 -0
  206. package/dist/styles/badge.css +19 -11
  207. package/dist/styles/collapsible-panel.css +13 -9
  208. package/dist/styles/floating-toolbar.css +25 -6
  209. package/dist/styles/list-header.css +0 -12
  210. package/dist/styles/list.css +4 -4
  211. package/dist/styles/nav-stack.css +46 -19
  212. package/dist/styles/pane.css +50 -0
  213. package/dist/styles/popup-menu.css +151 -0
  214. package/dist/styles/resizable-region.css +22 -10
  215. package/dist/styles/select.css +28 -14
  216. package/dist/styles/skeleton.css +30 -3
  217. package/dist/styles/split-view.css +10 -7
  218. package/dist/styles/state-banner.css +0 -19
  219. package/dist/styles/surface-scaffold.css +8 -3
  220. package/dist/styles/tab-bar.css +79 -28
  221. package/dist/styles/tab-scaffold.css +25 -1
  222. package/dist/styles/text.css +16 -0
  223. package/dist/styles/toolbar-control-group.css +121 -66
  224. package/dist/styles/toolbar-text.css +21 -0
  225. package/dist/styles/toolbar.css +8 -32
  226. package/dist/styles/workbench.css +18 -18
  227. package/dist/tab-scaffold.d.ts +11 -1
  228. package/dist/tab-scaffold.js +2 -0
  229. package/dist/tab-scaffold.js.map +1 -1
  230. package/dist/toolbar-control-group.d.ts +3 -1
  231. package/dist/toolbar-control-group.js +1 -1
  232. package/dist/toolbar-text.d.ts +7 -1
  233. package/dist/toolbar-text.js +1 -1
  234. package/dist/toolbar.d.ts +8 -1
  235. package/dist/toolbar.js +1 -1
  236. package/dist/{types-DXAGogOS.d.ts → types-BuHELdXR.d.ts} +1 -1
  237. package/dist/wire-catalog.d.ts +3 -1
  238. package/dist/wire-catalog.js +2 -0
  239. package/dist/wire-catalog.js.map +1 -1
  240. package/dist/wire-scroll-dividers.d.ts +69 -0
  241. package/dist/wire-scroll-dividers.js +3 -0
  242. package/dist/wire-scroll-dividers.js.map +1 -0
  243. package/dist/workbench.d.ts +17 -16
  244. package/dist/workbench.js +1 -1
  245. package/docs/app-layouts.md +9 -1
  246. package/docs/catalog.md +10 -5
  247. package/docs/collapsible-panel.md +22 -13
  248. package/docs/component-contract.md +147 -21
  249. package/docs/component-selection.md +21 -8
  250. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  251. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  252. package/docs/design/templates/tab-bar-dark.svg +1 -1
  253. package/docs/design/templates/tab-bar.svg +1 -1
  254. package/docs/design-philosophy.md +30 -3
  255. package/docs/examples/application-ui-profile.json +4 -4
  256. package/docs/examples/{component-catalog-extension-v2.json → component-composition-extension.json} +3 -3
  257. package/docs/layout.md +82 -3
  258. package/docs/nav-stack.md +33 -3
  259. package/docs/split-view.md +10 -5
  260. package/docs/tab-scaffold.md +23 -1
  261. package/docs/type-contracts.md +4 -3
  262. package/docs/ui-analyzer.md +99 -5
  263. package/docs/ui-doctor.md +10 -0
  264. package/docs/workbench.md +31 -20
  265. package/doctor/index.mjs +6 -1
  266. package/llms.txt +85 -20
  267. package/package.json +17 -5
  268. package/ux-demo/recipes/collapsible-sidebar.tsx +0 -1
  269. package/ux-demo/recipes/composer-form.tsx +0 -1
  270. package/ux-demo/recipes/list-detail-dialog.tsx +0 -2
  271. package/ux-demo/recipes/list-workspace-states.tsx +0 -1
  272. package/ux-demo/recipes/loading-inspector.tsx +0 -1
  273. package/ux-demo/recipes/workspace-header.tsx +0 -1
  274. package/ai/component-catalog-extension-v2.d.ts +0 -7
  275. package/ai/component-catalog-extension-v2.schema.json +0 -7
  276. package/dist/chunk-AK67F6QN.js.map +0 -1
  277. package/dist/chunk-G33XC2NB.js.map +0 -1
  278. package/dist/chunk-K6UNVKDK.js.map +0 -1
  279. package/dist/chunk-MA6Z6EIM.js.map +0 -1
  280. package/dist/chunk-MOBRFZH3.js.map +0 -1
  281. package/dist/chunk-O3EXIBEZ.js.map +0 -1
  282. package/dist/chunk-PK4N5QTO.js.map +0 -1
  283. package/dist/chunk-QQOTQTDD.js.map +0 -1
  284. package/dist/chunk-T4UZTNZ4.js.map +0 -1
  285. package/dist/chunk-V65EOWNF.js.map +0 -1
  286. package/dist/chunk-VNPQDCQZ.js.map +0 -1
  287. package/dist/chunk-ZIYOJFZD.js.map +0 -1
package/README.md CHANGED
@@ -39,13 +39,15 @@ npm install kerfjs @kerfjs/ui
39
39
  ```
40
40
 
41
41
  ```tsx
42
+ import { mount } from "kerfjs";
42
43
  import { ListItem } from "@kerfjs/ui/list-item";
43
44
  import { ListHeader } from "@kerfjs/ui/list-header";
44
45
  import { ListActionRow } from "@kerfjs/ui/list-action-row";
45
46
  import { Toolbar } from "@kerfjs/ui/toolbar";
46
- import { ToolbarControlGroup } from "@kerfjs/ui/toolbar-control-group";
47
47
  import { ToolbarText } from "@kerfjs/ui/toolbar-text";
48
48
 
49
+ const root = document.getElementById("app")!;
50
+
49
51
  mount(root, () => (
50
52
  <>
51
53
  <Toolbar
@@ -80,7 +82,7 @@ mount(root, () => (
80
82
  label="src/main.ts"
81
83
  trailingAction="open-file-actions"
82
84
  trailingActionLabel="Actions for src/main.ts"
83
- trailingActionIcon={moreIcon}
85
+ trailingActionIcon={<span aria-hidden="true">⋯</span>}
84
86
  />
85
87
  <div id="workspace-actions" popover="auto">
86
88
  Application-owned actions
@@ -97,7 +99,7 @@ primary region, while semantic positions and replacement content use explicit
97
99
  named `SafeHtml` props such as `header`, `footer`, `leading`, `trailing`,
98
100
  `icon`, and `action`. These named `SafeHtml` prop slots are ordinary typed
99
101
  function-component props—not native `<slot>` elements, wrapper slot
100
- components, or a generic `slots` object. The v2 composition catalog publishes
102
+ components, or a generic `slots` object. The composition catalog publishes
101
103
  sound prop bindings as `zone.jsx.prop`, allowing ESLint to validate statically
102
104
  visible content and cardinality without guessing from zone names.
103
105
 
@@ -214,6 +216,7 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
214
216
  | `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
215
217
  | `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
216
218
  | `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | — |
219
+ | `wireScrollDividers` | `@kerfjs/ui/wire-scroll-dividers` | — |
217
220
  | `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
218
221
  | `Skeleton` | `@kerfjs/ui/skeleton` | `@kerfjs/ui/skeleton.css` |
219
222
  | `SunkenPanel` | `@kerfjs/ui/sunken-panel` | `@kerfjs/ui/sunken-panel.css` |
@@ -225,13 +228,24 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
225
228
  | `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
226
229
  | `ValueTable`, `ValueTableRow` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
227
230
 
228
- Opt-in application layouts keep JavaScript and CSS explicit. Import each
229
- layout from its component subpath, load the matching manual CSS export, and
230
- add its wire subpath when the layout has interactive behavior. The catalog
231
+ Application layouts are separate component subpaths. Browser-condition imports
232
+ include their reachable CSS; use the matching manual CSS export when your
233
+ bundler does not select the browser condition. Add a wire subpath when the
234
+ layout has interactive behavior. The catalog
231
235
  entries for `nav-stack`, `split-view`, `tab-scaffold`, `workbench`, and
232
236
  `collapsible-panel` document their selection rules, ownership boundaries,
233
237
  public classes, tokens, and focused demos. See
234
238
  [`docs/app-layouts.md`](./docs/app-layouts.md) for the layout decision matrix.
239
+ `NavStack` and `TabScaffold` expose `chromeDividers="scroll" | "always" |
240
+ "none"` for their chrome lines; `SplitView` forwards the setting to its
241
+ compact stack. A sole `Pane` in a view or scene fills it, keeping the Pane's
242
+ header in place while its own content scrolls.
243
+
244
+ For a `Workbench` or `CollapsiblePanel`, place panel toolbar groups in its
245
+ `leading`, `center`, and `trailing` zones. Add `relocateOnCollapse` to each
246
+ `ToolbarControlGroup` that should remain available in the work-area toolbar
247
+ while the panel is closed. The panel collects marked groups in zone order;
248
+ its toggle follows them. See [Workbench panel toolbars](./docs/workbench.md#panel-toolbars).
235
249
 
236
250
  Compose panel, dialog, and page headings directly with `Toolbar`: put an optional
237
251
  icon in a `ToolbarControlGroup`, use a direct extra-large `ToolbarText` for the
@@ -271,7 +285,19 @@ action at the logical end. Its visible action glyph defaults to 18px through
271
285
 
272
286
  ## Machine-readable catalog
273
287
 
274
- AI tools can retrieve the shipped [`ai/component-catalog.json`](./ai/component-catalog.json)
288
+ AI assistants should start from the generated markdown reference,
289
+ [`ai/components/README.md`](./ai/components/README.md): a one-line index of
290
+ every entry grouped like the catalog, plus one short page per entry
291
+ (`ai/components/<id>.md`) covering when to use and avoid it, imports and
292
+ CSS/registration side effects, where its exact props live, legal parents,
293
+ zones with their JSX props and child counts, app- and wiring-owned state,
294
+ geometry ownership, accessibility obligations, the styling boundary
295
+ (configure through props; never override internals), and its composition
296
+ diagnostics. The pages are projected from the two JSON catalogs by
297
+ `scripts/sync-component-docs.mjs` (`npm run catalog:sync`), and
298
+ `npm run check:catalog` fails when any page drifts.
299
+
300
+ Tools can retrieve the shipped [`ai/component-catalog.json`](./ai/component-catalog.json)
275
301
  for the exhaustive component and composition inventory. It is the canonical
276
302
  source for ids, public exports, purpose and selection guidance, relationships,
277
303
  delivery and side effects, companion wiring, application-owned policy,
@@ -291,14 +317,16 @@ Keeping this as a companion artifact prevents per-entry selection facts from
291
317
  duplicating presentation rules.
292
318
 
293
319
  Tools that evaluate composition may additionally load
294
- [`component-catalog-v2.json`](./ai/component-catalog-v2.json). It is a
295
- deterministic, package-qualified projection of every v1 entry with formal
296
- parent/context, zone/cardinality, child, state ownership, wiring, responsive,
297
- layout, accessibility, public-boundary, and stable-diagnostic fields. V1
298
- remains the selection and delivery compatibility surface. V2 defaults are
320
+ [`component-composition.json`](./ai/component-composition.json). It is a
321
+ generated composition layer beside `component-catalog.json`, not a newer
322
+ version of it: a deterministic, package-qualified projection of every
323
+ component-catalog entry with formal parent/context, zone/cardinality, child,
324
+ state ownership, wiring, responsive, layout, accessibility, public-boundary,
325
+ and stable-diagnostic fields. `component-catalog.json` remains the selection
326
+ and delivery surface. Composition defaults are
299
327
  deliberately permissive; only documented objective rules receive an
300
328
  authoritative override and enforceable diagnostic. The adjacent schema and
301
- [`component-catalog-v2.d.ts`](./ai/component-catalog-v2.d.ts) types describe
329
+ [`component-composition.d.ts`](./ai/component-composition.d.ts) types describe
302
330
  the same contract.
303
331
 
304
332
  Applications and downstream design systems should publish the same facts for
@@ -314,9 +342,9 @@ tool reason about both sides of a composition using one vocabulary without
314
342
  pretending app-local components are `@kerfjs/ui` exports.
315
343
 
316
344
  Composition-aware consumers use
317
- [`component-catalog-extension-v2.schema.json`](./ai/component-catalog-extension-v2.schema.json),
345
+ [`component-composition-extension.schema.json`](./ai/component-composition-extension.schema.json),
318
346
  its shipped TypeScript types, and the checked
319
- [`component-catalog-extension-v2.json`](./docs/examples/component-catalog-extension-v2.json)
347
+ [`component-composition-extension.json`](./docs/examples/component-composition-extension.json)
320
348
  example. Preserve each catalog's package and qualify every identity and
321
349
  cross-catalog reference as `package:id`; never merge entries by bare id.
322
350
 
@@ -327,7 +355,7 @@ rejects. The package gate compiles one positive/negative consumer fixture agains
327
355
  both source and declarations extracted from the real packed tarball. The
328
356
  [compile-time contract guide](./docs/type-contracts.md) documents migrations and
329
357
  the dynamic DOM/children relationships that remain runtime or catalog checks.
330
- Packages scaffolded by `create-kerf-component` maintain this v2 input from
358
+ Packages scaffolded by `create-kerf-component` maintain this composition input from
331
359
  `kerf.components.json`: `npm run catalog:generate` emits the catalog and
332
360
  `npm run catalog:check` verifies source files, named public exports, explicit
333
361
  author decisions, and byte-for-byte drift. Tools index the generated consumer
@@ -350,9 +378,9 @@ token overrides, layout/responsive conventions, and narrow rule exceptions.
350
378
  Profiles contain policy only—never product records, user data, or broad styling
351
379
  waivers.
352
380
 
353
- Catalog declarations always provide a v2 `composition` location. Consumer
381
+ Catalog declarations always provide a `composition` location. Consumer
354
382
  packages generated with composition-only metadata omit `selection`;
355
- `@kerfjs/ui` continues to require its v1 selection catalog.
383
+ `@kerfjs/ui` continues to require its `component-catalog.json` selection catalog.
356
384
 
357
385
  Node-based AI and static-analysis tools may import the shipped discovery API
358
386
  from `@kerfjs/ui/ai/application-ui-profile.mjs`. It discovers package defaults,
@@ -376,9 +404,12 @@ Run `kerf-ui-analyze --root . src` (or import
376
404
  composition catalogs and application profile. It catches provable private
377
405
  selector reach-through, unknown tokens, competing geometry owners, nested
378
406
  scroll owners, and cataloged CSS-value violations in JavaScript/TypeScript
379
- component calls and JSX. It reports forced dimensions, repeated insets,
380
- exceptional spacing shorthands, and dynamic classes separately as review
381
- findings. Text, versioned JSON,
407
+ component calls and JSX, plus component-ownership overrides: CSS that makes
408
+ another package's component its subject, touches its private variables,
409
+ overrides a token its typed prop sets, or styles it through a hook class on
410
+ its root (`KUI-L019`–`KUI-L022`; forcing a component's dimensions is one such
411
+ restyle). It reports repeated insets, exceptional spacing shorthands, and
412
+ dynamic classes separately as review findings. Text, versioned JSON,
382
413
  and SARIF outputs carry stable `KUI-L###` ids, repository-relative locations,
383
414
  evidence, and ownership chains. See the [analyzer guide](./docs/ui-analyzer.md).
384
415
 
@@ -435,7 +466,10 @@ file.
435
466
 
436
467
  `npm run check:css-ownership` keeps that boundary honest: application CSS may
437
468
  style only application-owned structure, never package component classes or
438
- Web Awesome descendants. The UX catalog's `style.css` contains document-shell
469
+ Web Awesome descendants, and a package component's stylesheet styles only
470
+ itself (in a composing parent's context when needed) — never another kerf
471
+ component's root, the `wa-*` tags it renders, its variables, or a hook class on
472
+ its root. The UX catalog's `style.css` contains document-shell
439
473
  mechanics only, recipes ship no stylesheets (`npm run check:recipes` rejects
440
474
  route stylesheets, inline styles, and styling-only classes), and `catalog.css`
441
475
  remains a
@@ -461,23 +495,29 @@ component browser imports. See [Document baseline](./docs/document-baseline.md).
461
495
 
462
496
  ## Pane and content geometry
463
497
 
464
- Import `@kerfjs/ui/layout.css` and use the same structural vocabulary for a
465
- sidebar, main area, inspector, or dialog. `.kui-pane` is unpadded and contains
466
- an optional toolbar, one scrolling `.kui-pane__content`, and an optional footer.
467
- Add `.kui-content` to make its major children a vertical stack with 24px gaps.
498
+ Render `Pane` (`@kerfjs/ui/pane`) for a sidebar, main area, inspector, or
499
+ dialog: the same structural vocabulary everywhere. Its `.kui-pane` root is
500
+ unpadded and contains an optional header, one scrolling `.kui-pane__content`,
501
+ and an optional footer; the content slot already carries `.kui-content`, which
502
+ makes its major children a vertical stack with 24px gaps. Choose landmark
503
+ semantics with `element` / `contentElement` rather than writing the pane
504
+ classes onto your own elements — `eslint-plugin-kerfjs` reports a component's
505
+ anatomy class on an application-owned element as `KUI-L103`.
468
506
 
469
507
  ```tsx
470
- <aside class="kui-pane">
471
- <div class="kui-pane__toolbar"><Toolbar label="Workspace" ... /></div>
472
- <nav class="kui-pane__content kui-content">
473
- <section>
474
- <ListHeader label="Workspace" count={3} countLabel="3 workspaces" />
475
- <ListItem action="open" label="Inbox" icon={inboxIcon} />
476
- <ListItem action="open" label="Drafts" />
477
- </section>
478
- <ContentItem>Workspace details</ContentItem>
479
- </nav>
480
- </aside>
508
+ <Pane
509
+ element="aside"
510
+ label="Workspace"
511
+ contentElement="nav"
512
+ header={<Toolbar label="Workspace" ... />}
513
+ >
514
+ <section>
515
+ <ListHeader label="Workspace" count={3} countLabel="3 workspaces" />
516
+ <ListItem action="open" label="Inbox" icon={inboxIcon} />
517
+ <ListItem action="open" label="Drafts" />
518
+ </section>
519
+ <ContentItem>Workspace details</ContentItem>
520
+ </Pane>
481
521
  ```
482
522
 
483
523
  Ordinary children use `ContentItem` (`@kerfjs/ui/content-item`): 8px inline
@@ -553,6 +593,10 @@ arrays support diagnostics, tooling, browser assertions, and package-owned
553
593
  composition; they are not an application styling API. Application-owned CSS may
554
594
  style new structure rendered by its own component, but it must not select a
555
595
  nested Kerf or Web Awesome component. Add missing configuration to the owner.
596
+ Markup follows the same rule: write only an entry's `placeableClasses` (layout
597
+ utilities, `kui-app-root`, `kui-content-item` on a non-div carrier) onto your
598
+ own elements; any other public class recreates a component by class, which
599
+ `eslint-plugin-kerfjs` reports as `KUI-L103` with the component to render.
556
600
 
557
601
  `StateBanner` has opinionated `neutral`, `info`, `pop`, `success`, `warning`,
558
602
  and `danger` palettes. Override an individual banner with
@@ -47,9 +47,14 @@
47
47
  "KUI-L016",
48
48
  "KUI-L017",
49
49
  "KUI-L018",
50
+ "KUI-L019",
51
+ "KUI-L020",
52
+ "KUI-L021",
53
+ "KUI-L022",
50
54
  "KUI-L090",
51
55
  "KUI-L101",
52
56
  "KUI-L102",
57
+ "KUI-L103",
53
58
  "KUI-L201",
54
59
  "KUI-L202",
55
60
  "KUI-L203",
@@ -97,5 +102,8 @@
97
102
  "KUI-T009",
98
103
  "KUI-T010",
99
104
  "KUI-T011"
100
- ]
105
+ ],
106
+ "retired": {
107
+ "KUI-L005": "Folded into KUI-L019: any application rule whose subject is a cataloged component, forced dimensions included. Kept in ids so existing profile exceptions that name it still load."
108
+ }
101
109
  }
@@ -202,7 +202,7 @@ function validateApplicationUiProfile(profile, options = {}) {
202
202
  add(
203
203
  'KUI-P005',
204
204
  `${path}.selection`,
205
- 'The @kerfjs/ui catalog requires its v1 selection location.',
205
+ 'The @kerfjs/ui catalog requires its component-catalog.json selection location.',
206
206
  );
207
207
  for (const kind of ['selection', 'composition']) {
208
208
  if (kind === 'selection' && !catalog[kind]) continue;
@@ -5,22 +5,77 @@
5
5
  "catalogs": [
6
6
  {
7
7
  "package": "@kerfjs/ui",
8
- "selection": { "path": "./component-catalog.json", "schemaVersion": 1 },
8
+ "selection": {
9
+ "path": "./component-catalog.json",
10
+ "schemaVersion": 1
11
+ },
9
12
  "composition": {
10
- "path": "./component-catalog-v2.json",
11
- "schemaVersion": 2
13
+ "path": "./component-composition.json",
14
+ "schemaVersion": 1
12
15
  }
13
16
  }
14
17
  ],
15
18
  "preferences": {
16
- "application-shell": { "preferred": "@kerfjs/ui:recipe-app-shell" },
19
+ "application-shell": {
20
+ "preferred": "@kerfjs/ui:recipe-app-shell"
21
+ },
22
+ "application-tabs": {
23
+ "preferred": "@kerfjs/ui:tab-bar",
24
+ "avoid": [
25
+ "@kerfjs/ui:wa-tab-group",
26
+ "@kerfjs/ui:wa-tab",
27
+ "@kerfjs/ui:wa-tab-panel"
28
+ ],
29
+ "rationale": "Render TabBar (or SegmentedControl for a view switch) instead of composing Web Awesome tabs directly."
30
+ },
31
+ "command-menu": {
32
+ "preferred": "@kerfjs/ui:popup-menu",
33
+ "avoid": ["@kerfjs/ui:wa-dropdown", "@kerfjs/ui:wa-dropdown-item"],
34
+ "rationale": "Render PopupMenu, which wraps wa-dropdown with the shared popup contract; use Select when choosing a value."
35
+ },
36
+ "embedded-media": {
37
+ "preferred": "@kerfjs/ui:content-item",
38
+ "avoid": [
39
+ "@kerfjs/ui:wa-animated-image",
40
+ "@kerfjs/ui:wa-comparison",
41
+ "@kerfjs/ui:wa-zoomable-frame"
42
+ ],
43
+ "rationale": "Keep media behavior application-owned: place a native img, video, or iframe in a ContentItem. Record a narrow KUI-L301 profile exception only when a concrete product requirement needs this Web Awesome element."
44
+ },
17
45
  "exclusive-choice": {
18
46
  "preferred": "@kerfjs/ui:segmented-control",
19
- "avoid": ["@kerfjs/ui:wa-button-group"]
47
+ "avoid": ["@kerfjs/ui:wa-button-group"],
48
+ "rationale": "Render SegmentedControl for one-of-N choices instead of a Web Awesome button group."
49
+ },
50
+ "hierarchy-navigation": {
51
+ "preferred": "@kerfjs/ui:list",
52
+ "avoid": ["@kerfjs/ui:wa-tree", "@kerfjs/ui:wa-tree-item"],
53
+ "rationale": "Present hierarchy as List rows (or NavStack drill-in levels). Record a narrow KUI-L301 profile exception only when the product requires tree behavior."
54
+ },
55
+ "icon": {
56
+ "preferred": "@kerfjs/ui:lucide-icon",
57
+ "avoid": ["@kerfjs/ui:wa-icon"],
58
+ "rationale": "Render LucideIcon; Web Awesome icons are not part of the Kerf icon contract."
20
59
  },
21
- "navigation-row": { "preferred": "@kerfjs/ui:list-item" },
22
- "panel-heading": { "preferred": "@kerfjs/ui:toolbar" },
23
- "structured-search": { "preferred": "@kerfjs/ui:token-search-field" }
60
+ "navigation-row": {
61
+ "preferred": "@kerfjs/ui:list-item"
62
+ },
63
+ "panel-heading": {
64
+ "preferred": "@kerfjs/ui:toolbar"
65
+ },
66
+ "resizable-pane": {
67
+ "preferred": "@kerfjs/ui:resize",
68
+ "avoid": ["@kerfjs/ui:wa-split-panel"],
69
+ "rationale": "Render ResizableRegion for application panes instead of a Web Awesome split panel."
70
+ },
71
+ "structured-search": {
72
+ "preferred": "@kerfjs/ui:token-search-field"
73
+ },
74
+ "value-selection": {
75
+ "preferred": "@kerfjs/ui:select",
76
+ "avoid": ["@kerfjs/ui:wa-select", "@kerfjs/ui:wa-option"],
77
+ "rationale": "Render Select, which wraps wa-select and wa-option with Kerf's popup and spacing contract."
78
+ }
24
79
  },
25
80
  "theme": {
26
81
  "colorScheme": "light",
@@ -289,7 +289,7 @@ export function validateApplicationUiProfile(
289
289
  add(
290
290
  'KUI-P005',
291
291
  `${path}.selection`,
292
- 'The @kerfjs/ui catalog requires its v1 selection location.',
292
+ 'The @kerfjs/ui catalog requires its component-catalog.json selection location.',
293
293
  );
294
294
  for (const kind of ['selection', 'composition']) {
295
295
  if (kind === 'selection' && !catalog?.selection) continue;