@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
@@ -420,6 +420,9 @@
420
420
  "publicClasses": [
421
421
  "kui-app-root"
422
422
  ],
423
+ "placeableClasses": [
424
+ "kui-app-root"
425
+ ],
423
426
  "publicTokens": [],
424
427
  "links": {
425
428
  "catalogRoute": "?component=document-baseline",
@@ -482,6 +485,12 @@
482
485
  "kui-inline-metadata",
483
486
  "kui-scroll-owner"
484
487
  ],
488
+ "placeableClasses": [
489
+ "kui-content",
490
+ "kui-control-cluster",
491
+ "kui-inline-metadata",
492
+ "kui-scroll-owner"
493
+ ],
485
494
  "publicTokens": [
486
495
  "--kui-layout-control-gap",
487
496
  "--kui-layout-content-gap",
@@ -508,11 +517,13 @@
508
517
  "uses": [],
509
518
  "purpose": "Organize a sidebar, main area, inspector, or dialog column into fixed vertical header/footer chrome around one scrolling content owner.",
510
519
  "publicExports": [
511
- "Pane"
520
+ "Pane",
521
+ "wireScrollDividers"
512
522
  ],
513
523
  "useWhen": [
514
524
  "An application column needs shared header, content, and optional footer organization with exactly one scrolling content owner.",
515
- "A pane boundary needs an opt-in separator on any combination of logical sides."
525
+ "A pane boundary needs an opt-in separator on any combination of logical sides.",
526
+ "Pinned chrome needs a divider from the scrolling content only while content is scrolled beneath it (wireScrollDividers)."
516
527
  ],
517
528
  "avoidWhen": [
518
529
  "Do not use Pane as a padded card or add a competing scroll owner around its content slot.",
@@ -531,7 +542,8 @@
531
542
  "header, content, and footer children",
532
543
  "which logical boundaries show separators",
533
544
  "which sides may compensate for device safe areas in an app-owned arrangement (safeAreaEdges)",
534
- "responsive placement and visibility"
545
+ "responsive placement and visibility",
546
+ "whether the chrome dividers follow the scroll, always show, or never show (chromeDividers)"
535
547
  ],
536
548
  "variants": [
537
549
  "content only",
@@ -540,7 +552,9 @@
540
552
  "block-start separator",
541
553
  "block-end separator",
542
554
  "inline-start separator",
543
- "inline-end separator"
555
+ "inline-end separator",
556
+ "chrome dividers only while scrolled (default, wired by wireScrollDividers)",
557
+ "always or no chrome dividers"
544
558
  ],
545
559
  "accessibility": [
546
560
  "Choose semantic root and content elements that match the region and provide labels for landmark elements.",
@@ -562,7 +576,25 @@
562
576
  "browser-condition-css"
563
577
  ]
564
578
  },
565
- "wiring": [],
579
+ "wiring": [
580
+ {
581
+ "export": "wireScrollDividers",
582
+ "import": "@kerfjs/ui/wire-scroll-dividers",
583
+ "required": false,
584
+ "stateAttributes": [
585
+ {
586
+ "name": "data-scroll-overflow",
587
+ "on": "kui-pane__content",
588
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
589
+ },
590
+ {
591
+ "name": "data-scroll-divider",
592
+ "on": "kui-pane__header and kui-pane__footer",
593
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
594
+ }
595
+ ]
596
+ }
597
+ ],
566
598
  "publicClasses": [
567
599
  "kui-pane",
568
600
  "kui-pane__content",
@@ -630,7 +662,8 @@
630
662
  "preferred initial focus targets when DOM order is insufficient",
631
663
  "per-view bottom toolbar content or a persistent fallback",
632
664
  "per-view leading, center, and trailing top-toolbar groups",
633
- "top-toolbar configuration, title size, and heading level"
665
+ "top-toolbar configuration, title size, and heading level",
666
+ "whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers)"
634
667
  ],
635
668
  "variants": [
636
669
  "single root view",
@@ -639,7 +672,9 @@
639
672
  "configured top toolbar",
640
673
  "custom back icon or visible back text",
641
674
  "per-view bottom toolbar",
642
- "persistent bottom-toolbar fallback"
675
+ "persistent bottom-toolbar fallback",
676
+ "chrome and bottom-toolbar dividers only while the active view scrolls beneath them (wired by wireScrollDividers)",
677
+ "permanent or no chrome dividers (chromeDividers always or none)"
643
678
  ],
644
679
  "accessibility": [
645
680
  "Give the stack region an accessible label and every back control a stable action label; visible backText names the control itself.",
@@ -652,14 +687,16 @@
652
687
  "border": "conditional",
653
688
  "padding": "child",
654
689
  "notes": [
655
- "The stack owns its full-height chrome and viewport; each view owns its internal content padding and scrollable content."
690
+ "The stack owns its full-height chrome and viewport; each view owns its internal content padding and scrollable content.",
691
+ "The top chrome's bottom line and the bottom toolbar's top line are scroll state (wireScrollDividers), drawn as an overlaid 1px pseudo-element on the chrome and the bottom toolbar's always-present 1px top border, so neither moves the chrome or the content."
656
692
  ]
657
693
  },
658
694
  "delivery": {
659
695
  "moduleImport": "@kerfjs/ui/nav-stack",
696
+ "browserImport": "@kerfjs/ui/nav-stack",
660
697
  "manualCssImport": "@kerfjs/ui/nav-stack.css",
661
698
  "sideEffects": [
662
- "manual-css"
699
+ "browser-condition-css"
663
700
  ]
664
701
  },
665
702
  "wiring": [
@@ -684,6 +721,23 @@
684
721
  "meaning": "\"true\" on a popped view the helper briefly re-inserts to slide it out."
685
722
  }
686
723
  ]
724
+ },
725
+ {
726
+ "export": "wireScrollDividers",
727
+ "import": "@kerfjs/ui/wire-scroll-dividers",
728
+ "required": false,
729
+ "stateAttributes": [
730
+ {
731
+ "name": "data-scroll-overflow",
732
+ "on": "the active kui-nav-stack__view, or the kui-pane__content of a sole Pane in it",
733
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
734
+ },
735
+ {
736
+ "name": "data-scroll-divider",
737
+ "on": "kui-nav-stack__chrome and kui-nav-stack__bottom",
738
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
739
+ }
740
+ ]
687
741
  }
688
742
  ],
689
743
  "publicClasses": [
@@ -694,8 +748,6 @@
694
748
  "kui-nav-stack__chrome-copy",
695
749
  "kui-nav-stack__chrome-copy--bottom",
696
750
  "kui-nav-stack__chrome-copy--exiting",
697
- "kui-nav-stack__toolbar",
698
- "kui-nav-stack__title",
699
751
  "kui-nav-stack__viewport",
700
752
  "kui-nav-stack__view",
701
753
  "kui-nav-stack__view--entering",
@@ -755,7 +807,7 @@
755
807
  "list and detail content",
756
808
  "optional list width and persistence",
757
809
  "optional list collapse state and its restore control",
758
- "compact list and detail toolbar groups and toolbar configuration",
810
+ "compact list and detail toolbar groups, toolbar configuration, and chrome dividers",
759
811
  "back action"
760
812
  ],
761
813
  "variants": [
@@ -780,9 +832,10 @@
780
832
  },
781
833
  "delivery": {
782
834
  "moduleImport": "@kerfjs/ui/split-view",
835
+ "browserImport": "@kerfjs/ui/split-view",
783
836
  "manualCssImport": "@kerfjs/ui/split-view.css",
784
837
  "sideEffects": [
785
- "manual-css"
838
+ "browser-condition-css"
786
839
  ]
787
840
  },
788
841
  "wiring": [
@@ -882,13 +935,16 @@
882
935
  "tab labels, icons, and content",
883
936
  "tab badge counts or dots and their localized badgeLabel phrases",
884
937
  "routing and persistence",
885
- "responsive replacement on larger device classes"
938
+ "responsive replacement on larger device classes",
939
+ "whether the bar divider follows the scroll, always shows, or never shows (chromeDividers)"
886
940
  ],
887
941
  "variants": [
888
942
  "text-only tabs",
889
943
  "icon and text tabs",
890
944
  "badged tabs (count or text-free dot)",
891
- "one NavStack per tab"
945
+ "one NavStack per tab",
946
+ "bar divider only while the active scene continues below it (wired by wireScrollDividers)",
947
+ "permanent or no bar divider (chromeDividers always or none)"
892
948
  ],
893
949
  "accessibility": [
894
950
  "Give the tablist an accessible label and keep exactly the active tab in the sequential focus order.",
@@ -897,17 +953,19 @@
897
953
  ],
898
954
  "geometry": {
899
955
  "margin": "none",
900
- "border": "self",
956
+ "border": "conditional",
901
957
  "padding": "self",
902
958
  "notes": [
903
- "The scaffold owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry."
959
+ "The scaffold owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry.",
960
+ "The bar's top line is scroll state (wireScrollDividers): it shows only while the active scene's content continues below the bar, by coloring the bar's always-present 1px top border."
904
961
  ]
905
962
  },
906
963
  "delivery": {
907
964
  "moduleImport": "@kerfjs/ui/tab-scaffold",
965
+ "browserImport": "@kerfjs/ui/tab-scaffold",
908
966
  "manualCssImport": "@kerfjs/ui/tab-scaffold.css",
909
967
  "sideEffects": [
910
- "manual-css"
968
+ "browser-condition-css"
911
969
  ]
912
970
  },
913
971
  "wiring": [
@@ -915,6 +973,23 @@
915
973
  "export": "wireTabScaffold",
916
974
  "import": "@kerfjs/ui/wire-tab-scaffold",
917
975
  "required": true
976
+ },
977
+ {
978
+ "export": "wireScrollDividers",
979
+ "import": "@kerfjs/ui/wire-scroll-dividers",
980
+ "required": false,
981
+ "stateAttributes": [
982
+ {
983
+ "name": "data-scroll-overflow",
984
+ "on": "the active kui-tab-scaffold__scene, or what scrolls inside it (a sole NavStack's active view or a sole Pane's content)",
985
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
986
+ },
987
+ {
988
+ "name": "data-scroll-divider",
989
+ "on": "kui-tab-scaffold__bar",
990
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
991
+ }
992
+ ]
918
993
  }
919
994
  ],
920
995
  "publicClasses": [
@@ -995,7 +1070,8 @@
995
1070
  "clipped, scrolling, or popup-visible content",
996
1071
  "inline, overlay, or hidden responsive presentation",
997
1072
  "narrow or compact single-track responsive fill",
998
- "safe-area restore control"
1073
+ "safe-area restore control",
1074
+ "chrome dividers only while scrolled (wired by wireScrollDividers)"
999
1075
  ],
1000
1076
  "accessibility": [
1001
1077
  "Give the Workbench and each meaningful rail or drawer an accessible label.",
@@ -1014,9 +1090,10 @@
1014
1090
  },
1015
1091
  "delivery": {
1016
1092
  "moduleImport": "@kerfjs/ui/workbench",
1093
+ "browserImport": "@kerfjs/ui/workbench",
1017
1094
  "manualCssImport": "@kerfjs/ui/workbench.css",
1018
1095
  "sideEffects": [
1019
- "manual-css"
1096
+ "browser-condition-css"
1020
1097
  ]
1021
1098
  },
1022
1099
  "wiring": [
@@ -1036,6 +1113,23 @@
1036
1113
  "meaning": "Present on a resizable rail or the drawer while a pointer drag resizes it."
1037
1114
  }
1038
1115
  ]
1116
+ },
1117
+ {
1118
+ "export": "wireScrollDividers",
1119
+ "import": "@kerfjs/ui/wire-scroll-dividers",
1120
+ "required": false,
1121
+ "stateAttributes": [
1122
+ {
1123
+ "name": "data-scroll-overflow",
1124
+ "on": "kui-pane__content of each panel and work-area Pane",
1125
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1126
+ },
1127
+ {
1128
+ "name": "data-scroll-divider",
1129
+ "on": "kui-pane__header and kui-pane__footer of each panel and work-area Pane",
1130
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1131
+ }
1132
+ ]
1039
1133
  }
1040
1134
  ],
1041
1135
  "publicClasses": [
@@ -1128,7 +1222,8 @@
1128
1222
  "hidden separator",
1129
1223
  "slide, fade-slide, or instant content",
1130
1224
  "clipped, scrolling, or popup-visible content",
1131
- "safe-area restore control"
1225
+ "safe-area restore control",
1226
+ "chrome dividers only while scrolled (wired by wireScrollDividers)"
1132
1227
  ],
1133
1228
  "accessibility": [
1134
1229
  "Give the panel region and every collapse or restore control an accessible label.",
@@ -1144,9 +1239,10 @@
1144
1239
  },
1145
1240
  "delivery": {
1146
1241
  "moduleImport": "@kerfjs/ui/collapsible-panel",
1242
+ "browserImport": "@kerfjs/ui/collapsible-panel",
1147
1243
  "manualCssImport": "@kerfjs/ui/collapsible-panel.css",
1148
1244
  "sideEffects": [
1149
- "manual-css"
1245
+ "browser-condition-css"
1150
1246
  ]
1151
1247
  },
1152
1248
  "wiring": [
@@ -1171,6 +1267,23 @@
1171
1267
  "meaning": "Keeps the injected compact-overlay backdrop through the application's re-render; the helper creates and removes the backdrop itself."
1172
1268
  }
1173
1269
  ]
1270
+ },
1271
+ {
1272
+ "export": "wireScrollDividers",
1273
+ "import": "@kerfjs/ui/wire-scroll-dividers",
1274
+ "required": false,
1275
+ "stateAttributes": [
1276
+ {
1277
+ "name": "data-scroll-overflow",
1278
+ "on": "kui-pane__content of each panel and work-area Pane",
1279
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1280
+ },
1281
+ {
1282
+ "name": "data-scroll-divider",
1283
+ "on": "kui-pane__header and kui-pane__footer of each panel and work-area Pane",
1284
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1285
+ }
1286
+ ]
1174
1287
  }
1175
1288
  ],
1176
1289
  "publicClasses": [
@@ -1300,8 +1413,8 @@
1300
1413
  "which screen edges an app bar or bottom bar outside a Pane header or footer claims for device safe areas (safeAreaEdges)"
1301
1414
  ],
1302
1415
  "variants": [
1303
- "bottom divider (default)",
1304
- "no dividers",
1416
+ "no dividers (default)",
1417
+ "scroll dividers when named as wireScrollDividers targets chrome",
1305
1418
  "top/right/bottom/left divider combinations",
1306
1419
  "centered content",
1307
1420
  "stacked zones at compact or narrow widths",
@@ -1329,7 +1442,25 @@
1329
1442
  "browser-condition-css"
1330
1443
  ]
1331
1444
  },
1332
- "wiring": [],
1445
+ "wiring": [
1446
+ {
1447
+ "export": "wireScrollDividers",
1448
+ "import": "@kerfjs/ui/wire-scroll-dividers",
1449
+ "required": false,
1450
+ "stateAttributes": [
1451
+ {
1452
+ "name": "data-scroll-overflow",
1453
+ "on": "the targets scroller",
1454
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
1455
+ },
1456
+ {
1457
+ "name": "data-scroll-divider",
1458
+ "on": "a Toolbar named as targets chrome",
1459
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1460
+ }
1461
+ ]
1462
+ }
1463
+ ],
1333
1464
  "publicClasses": [
1334
1465
  "kui-toolbar",
1335
1466
  "kui-toolbar__center",
@@ -1366,8 +1497,9 @@
1366
1497
  "useWhen": [
1367
1498
  "Group related controls inside a toolbar with a supported visual treatment.",
1368
1499
  "Use ToolbarActionLink for navigation or external resources that must retain native anchor semantics inside a group.",
1369
- "Fill it with plain <button> controls (the group styles > button fully); use wa-button only for a Web Awesome feature such as a wa-dropdown popup trigger.",
1370
- "For an avatar control, set content=avatar and avatarImage instead of inserting an img; one button paints the group and multiple buttons paint only the pressed highlight."
1500
+ "Fill it with plain <button> controls (the group styles > button fully); use wa-button only for a Web Awesome feature. A popup menu is a PopupMenu in a single group with nestedDropdown; it renders its own trigger, so never hand-write wa-dropdown markup. Nothing wraps inside a group: an icon sits beside its label on one row and no trigger gets a fixed width.",
1501
+ "For an avatar control, set content=avatar and avatarImage instead of inserting an img; one button paints the group and multiple buttons paint only the pressed highlight.",
1502
+ "In a Workbench or CollapsiblePanel toolbar, mark a group relocateOnCollapse to keep it available in the work-area toolbar when the panel closes; place it directly or in an array in any toolbar zone."
1371
1503
  ],
1372
1504
  "avoidWhen": [
1373
1505
  "Do not use merely to align unrelated buttons or to imitate an exclusive choice.",
@@ -1404,6 +1536,7 @@
1404
1536
  "standard, compact, or list-zero dropdown menu inset",
1405
1537
  "visible or horizontally scrollable overflow",
1406
1538
  "always visible or compact-only responsive visibility",
1539
+ "relocate on panel collapse",
1407
1540
  "avatar scrim",
1408
1541
  "contained avatar background on a single group or selected multi-button highlight"
1409
1542
  ],
@@ -2496,7 +2629,8 @@
2496
2629
  "top/right/bottom/left divider combinations",
2497
2630
  "top/right/bottom/left text and control inset combinations",
2498
2631
  "fill: the layout root fills a definite-height parent",
2499
- "rootAttributes: safe data-* metadata on the root"
2632
+ "rootAttributes: safe data-* metadata on the root",
2633
+ "scroll dividers when named as wireScrollDividers targets chrome"
2500
2634
  ],
2501
2635
  "accessibility": [
2502
2636
  "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
@@ -2517,7 +2651,25 @@
2517
2651
  "browser-condition-css"
2518
2652
  ]
2519
2653
  },
2520
- "wiring": [],
2654
+ "wiring": [
2655
+ {
2656
+ "export": "wireScrollDividers",
2657
+ "import": "@kerfjs/ui/wire-scroll-dividers",
2658
+ "required": false,
2659
+ "stateAttributes": [
2660
+ {
2661
+ "name": "data-scroll-overflow",
2662
+ "on": "the targets scroller",
2663
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
2664
+ },
2665
+ {
2666
+ "name": "data-scroll-divider",
2667
+ "on": "a List named as targets chrome",
2668
+ "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
2669
+ }
2670
+ ]
2671
+ }
2672
+ ],
2521
2673
  "publicClasses": [
2522
2674
  "kui-list"
2523
2675
  ],
@@ -2605,14 +2757,12 @@
2605
2757
  "kui-list-header",
2606
2758
  "kui-list-header__action",
2607
2759
  "kui-list-header__action-layer",
2608
- "kui-list-header__label",
2609
2760
  "kui-list-header__title",
2610
2761
  "kui-list-header__toggle"
2611
2762
  ],
2612
2763
  "publicTokens": [
2613
2764
  "--kui-color-neutral-border-quiet",
2614
2765
  "--kui-focus-ring",
2615
- "--kui-font-xs",
2616
2766
  "--kui-list-header-action-icon-size",
2617
2767
  "--kui-list-header-color",
2618
2768
  "--kui-layout-inline-margin",
@@ -3062,6 +3212,12 @@
3062
3212
  "kui-content-item--pill",
3063
3213
  "kui-content-item--framed"
3064
3214
  ],
3215
+ "placeableClasses": [
3216
+ "kui-content-item",
3217
+ "kui-content-item--pill",
3218
+ "kui-content-item--framed"
3219
+ ],
3220
+ "rootElement": "div",
3065
3221
  "publicTokens": [
3066
3222
  "--kui-content-item-border",
3067
3223
  "--kui-content-item-radius",
@@ -3282,7 +3438,8 @@
3282
3438
  "rail, segmented, and inspector presentation",
3283
3439
  "intrinsic or fill allocation",
3284
3440
  "separate or adjacent trailing action",
3285
- "far-edge end action"
3441
+ "far-edge end action",
3442
+ "overflow dividers on each side with tabs scrolled out of view (wired by wireScrollDividers)"
3286
3443
  ],
3287
3444
  "accessibility": [
3288
3445
  "Keep exactly one selected tab at tabindex 0 and preserve the wiring keyboard model."
@@ -3329,6 +3486,23 @@
3329
3486
  "export": "reorderTabs",
3330
3487
  "import": "@kerfjs/ui/wire-tab-bars",
3331
3488
  "required": false
3489
+ },
3490
+ {
3491
+ "export": "wireScrollDividers",
3492
+ "import": "@kerfjs/ui/wire-scroll-dividers",
3493
+ "required": false,
3494
+ "stateAttributes": [
3495
+ {
3496
+ "name": "data-scroll-overflow",
3497
+ "on": "kui-tab-bar__tabs",
3498
+ "meaning": "The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it."
3499
+ },
3500
+ {
3501
+ "name": "data-scroll-divider",
3502
+ "on": "chrome named in wireScrollDividers targets (a TabBar strip has none)",
3503
+ "meaning": "The sides, in t/r/b/l order, on which that chrome currently draws its scroll divider. Re-applied if a re-render drops it."
3504
+ }
3505
+ ]
3332
3506
  }
3333
3507
  ],
3334
3508
  "publicClasses": [
@@ -3340,7 +3514,8 @@
3340
3514
  ],
3341
3515
  "publicTokens": [
3342
3516
  "--kui-tab-bar-background",
3343
- "--kui-tab-bar-border"
3517
+ "--kui-tab-bar-border",
3518
+ "--kui-tab-bar-divider-color"
3344
3519
  ],
3345
3520
  "links": {
3346
3521
  "catalogRoute": "?component=tab-bar",
@@ -5465,6 +5640,9 @@
5465
5640
  "publicClasses": [
5466
5641
  "hide-actions"
5467
5642
  ],
5643
+ "placeableClasses": [
5644
+ "hide-actions"
5645
+ ],
5468
5646
  "geometry": {
5469
5647
  "margin": "none",
5470
5648
  "border": "child",
@@ -39,6 +39,8 @@
39
39
  "variants": { "type": "array", "items": { "type": "string" } },
40
40
  "accessibility": { "type": "array", "items": { "type": "string" } },
41
41
  "publicClasses": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
42
+ "placeableClasses": { "description": "Public classes an application may place on its own elements (layout utilities, a document root, or item geometry on a non-div carrier). Every other public class is component anatomy: render the component instead.", "type": "array", "items": { "type": "string" }, "uniqueItems": true },
43
+ "rootElement": { "description": "The intrinsic element the component renders at its root. Required for a component whose placeableClasses it renders itself: a placeable class on a plain element of this tag is the component recreated, so render the component instead; another carrier element may keep the class.", "type": "string", "pattern": "^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$" },
42
44
  "publicTokens": { "type": "array", "items": { "type": "string" }, "uniqueItems": true },
43
45
  "cssValueProps": { "type": "array", "items": { "$ref": "#/$defs/cssValueProp" }, "uniqueItems": true },
44
46
  "geometry": { "$ref": "#/$defs/geometry" },
@@ -0,0 +1,83 @@
1
+ 'use strict';
2
+
3
+ // The one rule for which component export renders a cataloged public class —
4
+ // the KUI-L103 "render X instead" answer. `eslint-plugin-kerfjs`'s
5
+ // `ui-public-boundaries` rule loads this file from the installed
6
+ // `@kerfjs/ui/ai/` directory (beside `application-ui-profile-sync.cjs`), and
7
+ // `@kerfjs/ui`'s generated `ai/components/*.md` pages import it, so the lint
8
+ // message and the component reference cannot name different components. It
9
+ // applies to any composition catalog, `@kerfjs/ui`'s or a declared component
10
+ // package's (`acme-meter`), so it assumes no class prefix. CommonJS so the
11
+ // ESLint rule can load it synchronously.
12
+
13
+ // The component render exports among an entry's public exports: PascalCase
14
+ // names (JSX treats a lowercase tag as an intrinsic element) other than prop
15
+ // types, deduplicated in catalog order. Helpers such as `uiColor` or `px` are
16
+ // never a class's renderer.
17
+ function componentExportNames(exports) {
18
+ return [
19
+ ...new Set(
20
+ (exports ?? []).filter(
21
+ (name) =>
22
+ typeof name === 'string' &&
23
+ /^[A-Z]/.test(name) &&
24
+ !name.endsWith('Props'),
25
+ ),
26
+ ),
27
+ ];
28
+ }
29
+
30
+ // The export that renders `className`: the export named after the class's
31
+ // block, tried from the whole block down to its last word
32
+ // (`kui-toolbar-action-link` is ToolbarActionLink, `kui-pane__content` is
33
+ // Pane, `acme-meter__bar` is Meter), else the entry's own export, else every
34
+ // component export the entry lists.
35
+ function classRenderers(className, entryName, exports) {
36
+ const components = componentExportNames(exports);
37
+ const words = className.replace(/(?:__|--).*$/, '').split('-');
38
+ for (let start = 0; start < words.length; start += 1) {
39
+ const candidate = words
40
+ .slice(start)
41
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
42
+ .join('');
43
+ if (components.includes(candidate)) return [candidate];
44
+ }
45
+ if (components.includes(entryName)) return [entryName];
46
+ return components;
47
+ }
48
+
49
+ // The public classes of one catalog entry that are its component's rendered
50
+ // anatomy, each with the exports that render it. A class the entry lists in
51
+ // `placeableClasses` is the application's to place and is absent — unless the
52
+ // entry names the `rootElement` its component renders around those classes:
53
+ // then the class is listed with that `element`, because a plain
54
+ // `<div class="kui-content-item">` is exactly what ContentItem renders while
55
+ // a `<ul>` carrying the geometry stays the application's. An entry with no
56
+ // component export owns no classes.
57
+ function componentClassOwnership({
58
+ name,
59
+ exports,
60
+ publicClasses,
61
+ placeableClasses,
62
+ rootElement,
63
+ }) {
64
+ const components = componentExportNames(exports);
65
+ if (components.length === 0) return [];
66
+ const placeable = new Set(placeableClasses ?? []);
67
+ const owned = [];
68
+ for (const className of publicClasses ?? []) {
69
+ if (placeable.has(className) && !rootElement) continue;
70
+ owned.push({
71
+ className,
72
+ render: classRenderers(className, name, components),
73
+ ...(placeable.has(className) ? { element: rootElement } : {}),
74
+ });
75
+ }
76
+ return owned;
77
+ }
78
+
79
+ module.exports = {
80
+ classRenderers,
81
+ componentClassOwnership,
82
+ componentExportNames,
83
+ };
@@ -0,0 +1,7 @@
1
+ import type {
2
+ CatalogCompositionEntry,
3
+ ComponentComposition,
4
+ } from './component-composition.js';
5
+
6
+ export type ConsumerCompositionEntry = CatalogCompositionEntry;
7
+ export type ConsumerComponentComposition = ComponentComposition;
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/ai/component-composition-extension.schema.json",
4
+ "title": "Kerf UI consumer composition catalog extension",
5
+ "allOf": [{ "$ref": "./component-composition.schema.json" }],
6
+ "description": "Consumer composition catalogs use the composition entry contract with their own non-empty package identity; keys are always package:id."
7
+ }
@@ -180,7 +180,7 @@
180
180
  ],
181
181
  "wiring": {
182
182
  "required": true,
183
- "helpers": ["wireTabBars"],
183
+ "helpers": ["wireTabBars", "wireScrollDividers"],
184
184
  "obligations": [
185
185
  "Retain and invoke the disposer.",
186
186
  "Apply onReorder to application-owned order."
@@ -435,6 +435,7 @@
435
435
  "boundaries": {
436
436
  "rootClass": null,
437
437
  "publicClasses": ["hide-actions"],
438
+ "placeableClasses": ["hide-actions"],
438
439
  "publicTokens": []
439
440
  }
440
441
  },
@@ -39,7 +39,7 @@ export type CatalogCssValueProp = {
39
39
  unsafeHelper?: string;
40
40
  examples: string[];
41
41
  };
42
- export interface CatalogCompositionEntryV2 {
42
+ export interface CatalogCompositionEntry {
43
43
  key: CatalogQualifiedKey;
44
44
  package: string;
45
45
  id: string;
@@ -95,6 +95,10 @@ export interface CatalogCompositionEntryV2 {
95
95
  boundaries: {
96
96
  rootClass: string | null;
97
97
  publicClasses: string[];
98
+ /** Public classes an application may place on its own elements; absent means none. */
99
+ placeableClasses?: string[];
100
+ /** The intrinsic element the component renders at its root; a placeable class on a plain element of this tag recreates the component. */
101
+ rootElement?: string;
98
102
  publicTokens: string[];
99
103
  publicParts?: string[];
100
104
  };
@@ -102,10 +106,10 @@ export interface CatalogCompositionEntryV2 {
102
106
  diagnostics: CatalogDiagnostic[];
103
107
  provenance: { selection: string; composition: string };
104
108
  }
105
- export interface ComponentCatalogV2 {
109
+ export interface ComponentComposition {
106
110
  $schema?: string;
107
- schemaVersion: 2;
111
+ schemaVersion: 1;
108
112
  package: string;
109
- compatibility: { v1Catalog: string; identity: 'package:id' };
110
- entries: CatalogCompositionEntryV2[];
113
+ compatibility: { componentCatalog: string; identity: 'package:id' };
114
+ entries: CatalogCompositionEntry[];
111
115
  }