@kerfjs/ui 5.0.0-beta.4 → 5.0.0-beta.41
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.
- package/README.md +342 -108
- package/ai/application-ui-diagnostic-ids-v1.json +100 -0
- package/ai/application-ui-profile-sync.cjs +529 -0
- package/ai/application-ui-profile.d.mts +1 -0
- package/ai/application-ui-profile.d.ts +102 -0
- package/ai/application-ui-profile.defaults.json +41 -0
- package/ai/application-ui-profile.mjs +626 -0
- package/ai/application-ui-profile.schema.json +130 -0
- package/ai/catalog-authoring.json +25 -0
- package/ai/catalog-authoring.schema.json +61 -0
- package/ai/compile-time-contracts-v1.json +132 -0
- package/ai/compile-time-contracts-v1.schema.json +51 -0
- package/ai/component-catalog-extension-v2.d.ts +7 -0
- package/ai/component-catalog-extension-v2.schema.json +7 -0
- package/ai/component-catalog-extension.schema.json +79 -0
- package/ai/component-catalog-v2-overrides.json +496 -0
- package/ai/component-catalog-v2.d.ts +90 -0
- package/ai/component-catalog-v2.json +5678 -0
- package/ai/component-catalog-v2.schema.json +298 -0
- package/ai/component-catalog.json +2694 -417
- package/ai/component-catalog.schema.json +39 -0
- package/ai/public-api-signatures-v1.md +1591 -126
- package/ai/skill.md +140 -54
- package/ai/webawesome-jsx-signatures-v1.md +2 -1
- package/analyzer/cli.mjs +49 -0
- package/analyzer/index.d.mts +46 -0
- package/analyzer/index.mjs +1086 -0
- package/analyzer/report.schema.json +66 -0
- package/dist/app-tab.d.ts +15 -4
- package/dist/app-tab.js +3 -1
- package/dist/browser/app-tab.js +1 -0
- package/dist/browser/floating-toolbar.js +3 -0
- package/dist/browser/list-action-row.js +5 -0
- package/dist/browser/list-header.js +7 -0
- package/dist/browser/list-inset-control.js +3 -0
- package/dist/browser/list-inset-text.js +3 -0
- package/dist/browser/list-item.js +5 -0
- package/dist/browser/list.js +3 -0
- package/dist/browser/pane.js +3 -0
- package/dist/browser/row.js +3 -0
- package/dist/browser/segmented-control.js +1 -0
- package/dist/browser/select.js +1 -0
- package/dist/browser/skeleton.js +3 -0
- package/dist/browser/spacer.js +3 -0
- package/dist/browser/state-banner.js +1 -0
- package/dist/browser/sunken-panel.js +3 -0
- package/dist/browser/surface-scaffold.js +3 -0
- package/dist/browser/text.js +3 -0
- package/dist/browser/toolbar-text.js +1 -0
- package/dist/browser/value-table.js +1 -0
- package/dist/catalog-resources.d.ts +35 -0
- package/dist/catalog-resources.js +22 -0
- package/dist/catalog-resources.js.map +1 -0
- package/dist/catalog.d.ts +151 -0
- package/dist/catalog.js +396 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chunk-2TYUFZUC.js +22 -0
- package/dist/chunk-2TYUFZUC.js.map +1 -0
- package/dist/chunk-6NDBE2OK.js +32 -0
- package/dist/chunk-6NDBE2OK.js.map +1 -0
- package/dist/chunk-6WTETUZ6.js +21 -0
- package/dist/chunk-6WTETUZ6.js.map +1 -0
- package/dist/chunk-AQFWBG23.js +83 -0
- package/dist/chunk-AQFWBG23.js.map +1 -0
- package/dist/chunk-B6JYRX3P.js +51 -0
- package/dist/chunk-B6JYRX3P.js.map +1 -0
- package/dist/chunk-C34NZOLJ.js +53 -0
- package/dist/chunk-C34NZOLJ.js.map +1 -0
- package/dist/chunk-CAB6NQ2T.js +102 -0
- package/dist/chunk-CAB6NQ2T.js.map +1 -0
- package/dist/chunk-CK6P5AUK.js +136 -0
- package/dist/chunk-CK6P5AUK.js.map +1 -0
- package/dist/chunk-DAO2VFTT.js +129 -0
- package/dist/chunk-DAO2VFTT.js.map +1 -0
- package/dist/chunk-DEYOGDE7.js +141 -0
- package/dist/chunk-DEYOGDE7.js.map +1 -0
- package/dist/chunk-DYBPI5O2.js +25 -0
- package/dist/chunk-DYBPI5O2.js.map +1 -0
- package/dist/{chunk-TRNBHPNW.js → chunk-E34TE2ZI.js} +12 -8
- package/dist/chunk-E34TE2ZI.js.map +1 -0
- package/dist/chunk-EYALJQQD.js +25 -0
- package/dist/chunk-EYALJQQD.js.map +1 -0
- package/dist/chunk-I45QO2IZ.js +88 -0
- package/dist/chunk-I45QO2IZ.js.map +1 -0
- package/dist/chunk-I4V3UDSA.js +79 -0
- package/dist/chunk-I4V3UDSA.js.map +1 -0
- package/dist/chunk-OGTJNHRG.js +42 -0
- package/dist/chunk-OGTJNHRG.js.map +1 -0
- package/dist/chunk-OL4TC3U2.js +156 -0
- package/dist/chunk-OL4TC3U2.js.map +1 -0
- package/dist/chunk-OMSRSL3B.js +120 -0
- package/dist/chunk-OMSRSL3B.js.map +1 -0
- package/dist/chunk-R3EBGEAW.js +46 -0
- package/dist/chunk-R3EBGEAW.js.map +1 -0
- package/dist/chunk-SOK5EUF7.js +25 -0
- package/dist/chunk-SOK5EUF7.js.map +1 -0
- package/dist/{chunk-7BR3DO2A.js → chunk-SRSJO5QE.js} +13 -4
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-T7DOWS6T.js +61 -0
- package/dist/chunk-T7DOWS6T.js.map +1 -0
- package/dist/chunk-TIGSG6BX.js +218 -0
- package/dist/chunk-TIGSG6BX.js.map +1 -0
- package/dist/chunk-UDHHKZWO.js +41 -0
- package/dist/chunk-UDHHKZWO.js.map +1 -0
- package/dist/{chunk-MQIZAD4A.js → chunk-UKKSMZYT.js} +76 -22
- package/dist/chunk-UKKSMZYT.js.map +1 -0
- package/dist/chunk-V6GQKOX2.js +39 -0
- package/dist/chunk-V6GQKOX2.js.map +1 -0
- package/dist/chunk-V6HCTCVD.js +46 -0
- package/dist/chunk-V6HCTCVD.js.map +1 -0
- package/dist/chunk-VDUJZF5G.js +515 -0
- package/dist/chunk-VDUJZF5G.js.map +1 -0
- package/dist/chunk-VXFGMDA7.js +31 -0
- package/dist/chunk-VXFGMDA7.js.map +1 -0
- package/dist/chunk-WN52USHV.js +115 -0
- package/dist/chunk-WN52USHV.js.map +1 -0
- package/dist/chunk-WSXUPSID.js +43 -0
- package/dist/chunk-WSXUPSID.js.map +1 -0
- package/dist/chunk-X5GRDQ7V.js +50 -0
- package/dist/chunk-X5GRDQ7V.js.map +1 -0
- package/dist/{chunk-56RJXPHG.js → chunk-Y6LYKFXY.js} +1 -1
- package/dist/{chunk-56RJXPHG.js.map → chunk-Y6LYKFXY.js.map} +1 -1
- package/dist/chunk-ZASJJMGV.js +17 -0
- package/dist/chunk-ZASJJMGV.js.map +1 -0
- package/dist/chunk-ZPWZIVI6.js +47 -0
- package/dist/chunk-ZPWZIVI6.js.map +1 -0
- package/dist/collapsible-panel.d.ts +77 -0
- package/dist/collapsible-panel.js +84 -0
- package/dist/collapsible-panel.js.map +1 -0
- package/dist/css-values.d.ts +75 -0
- package/dist/css-values.js +3 -0
- package/dist/css-values.js.map +1 -0
- package/dist/device-class.d.ts +62 -0
- package/dist/device-class.js +103 -0
- package/dist/device-class.js.map +1 -0
- package/dist/disclosure-arrow.js +1 -1
- package/dist/divider-sides-BzB6rphT.d.ts +6 -0
- package/dist/empty-state.d.ts +3 -2
- package/dist/empty-state.js +1 -1
- package/dist/flex-alignment-CF8NLj7i.d.ts +4 -0
- package/dist/floating-toolbar.d.ts +29 -0
- package/dist/floating-toolbar.js +3 -0
- package/dist/floating-toolbar.js.map +1 -0
- package/dist/index.d.ts +28 -14
- package/dist/index.js +34 -23
- package/dist/{menu-action-row.d.ts → list-action-row.d.ts} +19 -8
- package/dist/list-action-row.js +7 -0
- package/dist/list-action-row.js.map +1 -0
- package/dist/list-header.d.ts +80 -0
- package/dist/list-header.js +9 -0
- package/dist/list-header.js.map +1 -0
- package/dist/list-inset-control.d.ts +20 -0
- package/dist/list-inset-control.js +3 -0
- package/dist/list-inset-control.js.map +1 -0
- package/dist/list-inset-text.d.ts +29 -0
- package/dist/list-inset-text.js +3 -0
- package/dist/list-inset-text.js.map +1 -0
- package/dist/list-item.d.ts +45 -0
- package/dist/list-item.js +7 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list.d.ts +30 -0
- package/dist/list.js +5 -0
- package/dist/list.js.map +1 -0
- package/dist/loading-spinner.js +1 -1
- package/dist/nav-stack.d.ts +41 -0
- package/dist/nav-stack.js +6 -0
- package/dist/nav-stack.js.map +1 -0
- package/dist/pane.d.ts +50 -0
- package/dist/pane.js +4 -0
- package/dist/pane.js.map +1 -0
- package/dist/resizable-region.d.ts +21 -3
- package/dist/resizable-region.js +1 -1
- package/dist/row.d.ts +28 -0
- package/dist/row.js +5 -0
- package/dist/row.js.map +1 -0
- package/dist/segmented-control.d.ts +11 -8
- package/dist/segmented-control.js +3 -1
- package/dist/select-register.d.ts +5 -1
- package/dist/select-register.js +129 -1
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +34 -8
- package/dist/select.js +3 -1
- package/dist/semantic-content-BbzjvSu9.d.ts +14 -0
- package/dist/skeleton.d.ts +25 -0
- package/dist/skeleton.js +4 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/spacer.d.ts +16 -0
- package/dist/spacer.js +4 -0
- package/dist/spacer.js.map +1 -0
- package/dist/split-view.d.ts +43 -0
- package/dist/split-view.js +82 -0
- package/dist/split-view.js.map +1 -0
- package/dist/state-banner.d.ts +11 -5
- package/dist/state-banner.js +3 -1
- package/dist/styles/app-tab.css +26 -0
- package/dist/styles/catalog.css +582 -0
- package/dist/styles/collapsible-panel.css +212 -0
- package/dist/styles/floating-toolbar.css +38 -0
- package/dist/styles/foundation.css +80 -0
- package/dist/styles/layout.css +2 -20
- package/dist/styles/list-action-row.css +224 -0
- package/dist/styles/list-header.css +224 -0
- package/dist/styles/list-inset-control.css +23 -0
- package/dist/styles/list-inset-text.css +30 -0
- package/dist/styles/list-item.css +171 -0
- package/dist/styles/list.css +118 -0
- package/dist/styles/nav-stack.css +141 -0
- package/dist/styles/pane.css +62 -0
- package/dist/styles/resizable-region.css +158 -0
- package/dist/styles/row.css +92 -0
- package/dist/styles/segmented-control.css +10 -7
- package/dist/styles/select.css +115 -2
- package/dist/styles/skeleton.css +31 -0
- package/dist/styles/spacer.css +11 -0
- package/dist/styles/split-view.css +35 -0
- package/dist/styles/state-banner.css +49 -10
- package/dist/styles/styles.css +10 -5
- package/dist/styles/sunken-panel.css +22 -0
- package/dist/styles/surface-scaffold.css +51 -0
- package/dist/styles/tab-bar.css +24 -0
- package/dist/styles/tab-scaffold.css +85 -0
- package/dist/styles/text.css +6 -0
- package/dist/styles/token-search-field.css +14 -2
- package/dist/styles/toolbar-control-group.css +235 -8
- package/dist/styles/toolbar-text.css +65 -2
- package/dist/styles/toolbar.css +47 -2
- package/dist/styles/webawesome.css +171 -0
- package/dist/styles/workbench.css +187 -0
- package/dist/sunken-panel.d.ts +20 -0
- package/dist/sunken-panel.js +3 -0
- package/dist/sunken-panel.js.map +1 -0
- package/dist/surface-scaffold.d.ts +26 -0
- package/dist/surface-scaffold.js +3 -0
- package/dist/surface-scaffold.js.map +1 -0
- package/dist/tab-bar.d.ts +24 -6
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +31 -0
- package/dist/tab-scaffold.js +51 -0
- package/dist/tab-scaffold.js.map +1 -0
- package/dist/text.d.ts +20 -0
- package/dist/text.js +3 -0
- package/dist/text.js.map +1 -0
- package/dist/token-search-field.d.ts +30 -13
- package/dist/token-search-field.js +1 -1
- package/dist/toolbar-control-group.d.ts +33 -7
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +31 -4
- package/dist/toolbar-text.js +3 -1
- package/dist/toolbar.d.ts +10 -7
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +7 -3
- package/dist/value-table.js +3 -1
- package/dist/webawesome.d.ts +1 -0
- package/dist/wire-catalog.d.ts +57 -0
- package/dist/wire-catalog.js +302 -0
- package/dist/wire-catalog.js.map +1 -0
- package/dist/wire-nav-stack.d.ts +18 -0
- package/dist/wire-nav-stack.js +228 -0
- package/dist/wire-nav-stack.js.map +1 -0
- package/dist/wire-resizable-regions.d.ts +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +48 -0
- package/dist/wire-sidebar.js +147 -0
- package/dist/wire-sidebar.js.map +1 -0
- package/dist/wire-tab-bars.d.ts +19 -2
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-scaffold.d.ts +11 -0
- package/dist/wire-tab-scaffold.js +21 -0
- package/dist/wire-tab-scaffold.js.map +1 -0
- package/dist/wire-token-search-fields.d.ts +104 -4
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +44 -0
- package/dist/workbench.js +106 -0
- package/dist/workbench.js.map +1 -0
- package/docs/accessibility.md +155 -20
- package/docs/app-layouts.md +61 -0
- package/docs/catalog.md +364 -0
- package/docs/collapsible-panel.md +142 -0
- package/docs/component-contract.md +258 -28
- package/docs/component-integration.md +63 -0
- package/docs/component-selection.md +219 -57
- package/docs/design/templates/empty-state/filtered-dark.svg +1 -0
- package/docs/design/templates/empty-state/filtered.svg +1 -0
- package/docs/design/templates/empty-state/with-action-dark.svg +1 -0
- package/docs/design/templates/empty-state/with-action.svg +1 -0
- package/docs/design/templates/empty-state-dark.svg +1 -0
- package/docs/design/templates/empty-state.svg +1 -0
- package/docs/design/templates/list/compact-dark.svg +1 -0
- package/docs/design/templates/list/compact.svg +1 -0
- package/docs/design/templates/list/stack-dark.svg +1 -0
- package/docs/design/templates/list/stack.svg +1 -0
- package/docs/design/templates/list-action-row/default-dark.svg +1 -0
- package/docs/design/templates/list-action-row/default.svg +1 -0
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -0
- package/docs/design/templates/list-action-row/selected.svg +1 -0
- package/docs/design/templates/list-action-row-dark.svg +1 -0
- package/docs/design/templates/list-action-row.svg +1 -0
- package/docs/design/templates/list-dark.svg +1 -0
- package/docs/design/templates/list-header/action-dark.svg +1 -0
- package/docs/design/templates/list-header/action.svg +1 -0
- package/docs/design/templates/list-header/count-dark.svg +1 -0
- package/docs/design/templates/list-header/count.svg +1 -0
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -0
- package/docs/design/templates/list-header/inline-action.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-collapsed.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -0
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -0
- package/docs/design/templates/list-header-dark.svg +1 -0
- package/docs/design/templates/list-header.svg +1 -0
- package/docs/design/templates/list-item/default-dark.svg +1 -0
- package/docs/design/templates/list-item/default.svg +1 -0
- package/docs/design/templates/list-item/multiline-dark.svg +1 -0
- package/docs/design/templates/list-item/multiline.svg +1 -0
- package/docs/design/templates/list-item/selected-dark.svg +1 -0
- package/docs/design/templates/list-item/selected.svg +1 -0
- package/docs/design/templates/list-item/trailing-dark.svg +1 -0
- package/docs/design/templates/list-item/trailing.svg +1 -0
- package/docs/design/templates/list-item-dark.svg +1 -0
- package/docs/design/templates/list-item.svg +1 -0
- package/docs/design/templates/list.svg +1 -0
- package/docs/design/templates/segmented-control/equal-dark.svg +1 -0
- package/docs/design/templates/segmented-control/equal.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -0
- package/docs/design/templates/segmented-control/pill-small.svg +1 -0
- package/docs/design/templates/segmented-control-dark.svg +1 -0
- package/docs/design/templates/segmented-control.svg +1 -0
- package/docs/design/templates/skeleton/avatar-dark.svg +1 -0
- package/docs/design/templates/skeleton/avatar.svg +1 -0
- package/docs/design/templates/skeleton/block-dark.svg +1 -0
- package/docs/design/templates/skeleton/block.svg +1 -0
- package/docs/design/templates/skeleton/lines-dark.svg +1 -0
- package/docs/design/templates/skeleton/lines.svg +1 -0
- package/docs/design/templates/skeleton-dark.svg +1 -0
- package/docs/design/templates/skeleton.svg +1 -0
- package/docs/design/templates/state-banner/danger-dark.svg +1 -0
- package/docs/design/templates/state-banner/danger.svg +1 -0
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
- package/docs/design/templates/state-banner/info-badge.svg +1 -0
- package/docs/design/templates/state-banner/info-dark.svg +1 -0
- package/docs/design/templates/state-banner/info.svg +1 -0
- package/docs/design/templates/state-banner/success-dark.svg +1 -0
- package/docs/design/templates/state-banner/success.svg +1 -0
- package/docs/design/templates/state-banner/warning-dark.svg +1 -0
- package/docs/design/templates/state-banner/warning.svg +1 -0
- package/docs/design/templates/state-banner-dark.svg +1 -0
- package/docs/design/templates/state-banner.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -0
- package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -0
- package/docs/design/templates/tab-bar-dark.svg +1 -0
- package/docs/design/templates/tab-bar.svg +1 -0
- package/docs/design/templates/token-search-field/empty-dark.svg +1 -0
- package/docs/design/templates/token-search-field/empty.svg +1 -0
- package/docs/design/templates/token-search-field/tokens-dark.svg +1 -0
- package/docs/design/templates/token-search-field/tokens.svg +1 -0
- package/docs/design/templates/token-search-field-dark.svg +1 -0
- package/docs/design/templates/token-search-field.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -0
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -0
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -0
- package/docs/design/templates/toolbar-control-group.svg +1 -0
- package/docs/design/templates/toolbar-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/default.svg +1 -0
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/large.svg +1 -0
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -0
- package/docs/design/templates/toolbar-text/small.svg +1 -0
- package/docs/design/templates/toolbar-text-dark.svg +1 -0
- package/docs/design/templates/toolbar-text.svg +1 -0
- package/docs/design/templates/toolbar.svg +1 -0
- package/docs/design/templates/value-table/details-dark.svg +1 -0
- package/docs/design/templates/value-table/details.svg +1 -0
- package/docs/design/templates/value-table-dark.svg +1 -0
- package/docs/design/templates/value-table.svg +1 -0
- package/docs/design/templates.md +128 -0
- package/docs/design-philosophy.md +33 -11
- package/docs/device-class.md +54 -0
- package/docs/examples/application-ui-profile.json +60 -0
- package/docs/examples/command-palette-adapter.tsx +68 -17
- package/docs/examples/component-catalog-extension-v2.json +80 -0
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/layout.md +169 -38
- package/docs/nav-stack.md +77 -0
- package/docs/recipes.md +64 -16
- package/docs/split-view.md +55 -0
- package/docs/sunken-panel.md +53 -0
- package/docs/surface-scaffold.md +25 -0
- package/docs/tab-scaffold.md +52 -0
- package/docs/type-contracts.md +127 -0
- package/docs/ui-analyzer.md +118 -0
- package/docs/ui-doctor.md +91 -0
- package/docs/ui-evaluator.md +122 -0
- package/docs/ux-demo.md +29 -10
- package/docs/webawesome-theme.md +82 -8
- package/docs/workbench.md +123 -0
- package/doctor/cli.mjs +115 -0
- package/doctor/config.schema.json +68 -0
- package/doctor/eslint-diagnostics.d.mts +24 -0
- package/doctor/eslint-diagnostics.mjs +24 -0
- package/doctor/index.d.mts +116 -0
- package/doctor/index.mjs +1272 -0
- package/doctor/report.schema.json +118 -0
- package/evaluator/cli.mjs +89 -0
- package/evaluator/index.d.mts +90 -0
- package/evaluator/index.mjs +1138 -0
- package/evaluator/report.schema.json +152 -0
- package/llms.txt +260 -32
- package/package.json +205 -38
- package/traversal-exclusions.mjs +27 -0
- package/ux-demo/recipes/app-shell.tsx +223 -13
- package/ux-demo/recipes/collapsible-sidebar.tsx +230 -0
- package/ux-demo/recipes/compact-toolbar.tsx +116 -12
- package/ux-demo/recipes/composer-form.tsx +120 -19
- package/ux-demo/recipes/list-detail-dialog.tsx +205 -0
- package/ux-demo/recipes/list-workspace-states.tsx +176 -9
- package/ux-demo/recipes/loaders.ts +13 -4
- package/ux-demo/recipes/loading-inspector.tsx +191 -0
- package/ux-demo/recipes/mount-recipe.ts +31 -5
- package/ux-demo/recipes/navigation-sidebar.tsx +123 -11
- package/ux-demo/recipes/navigation-stack.tsx +121 -0
- package/ux-demo/recipes/recipes.css +125 -16
- package/ux-demo/recipes/types.ts +9 -1
- package/ux-demo/recipes/workspace-header.tsx +72 -3
- package/dist/browser/dialog-header.js +0 -5
- package/dist/browser/menu-action-row.js +0 -3
- package/dist/browser/menu-header.js +0 -5
- package/dist/browser/menu-item.js +0 -3
- package/dist/browser/page-header.js +0 -3
- package/dist/chunk-2PES33HS.js +0 -13
- package/dist/chunk-2PES33HS.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-7BR3DO2A.js.map +0 -1
- package/dist/chunk-7LDCTU7D.js +0 -134
- package/dist/chunk-7LDCTU7D.js.map +0 -1
- package/dist/chunk-AQNKJRFH.js +0 -79
- package/dist/chunk-AQNKJRFH.js.map +0 -1
- package/dist/chunk-CTQKI2XL.js +0 -28
- package/dist/chunk-CTQKI2XL.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-EGHL5S4P.js +0 -33
- package/dist/chunk-EGHL5S4P.js.map +0 -1
- package/dist/chunk-GY5WH7TO.js +0 -10
- package/dist/chunk-GY5WH7TO.js.map +0 -1
- package/dist/chunk-H5AGGVU5.js +0 -75
- package/dist/chunk-H5AGGVU5.js.map +0 -1
- package/dist/chunk-K3G72I6D.js +0 -24
- package/dist/chunk-K3G72I6D.js.map +0 -1
- package/dist/chunk-M5JRI6MN.js +0 -27
- package/dist/chunk-M5JRI6MN.js.map +0 -1
- package/dist/chunk-MBR3TYNL.js +0 -14
- package/dist/chunk-MBR3TYNL.js.map +0 -1
- package/dist/chunk-MFKMHK5W.js +0 -10
- package/dist/chunk-MFKMHK5W.js.map +0 -1
- package/dist/chunk-MQIZAD4A.js.map +0 -1
- package/dist/chunk-NPPD2A6O.js +0 -40
- package/dist/chunk-NPPD2A6O.js.map +0 -1
- package/dist/chunk-R6JHHBKQ.js +0 -19
- package/dist/chunk-R6JHHBKQ.js.map +0 -1
- package/dist/chunk-S3TPM2LP.js +0 -23
- package/dist/chunk-S3TPM2LP.js.map +0 -1
- package/dist/chunk-TRNBHPNW.js.map +0 -1
- package/dist/chunk-VHW5YNIB.js +0 -17
- package/dist/chunk-VHW5YNIB.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-XZXRLY5Q.js +0 -33
- package/dist/chunk-XZXRLY5Q.js.map +0 -1
- package/dist/dialog-header.d.ts +0 -15
- package/dist/dialog-header.js +0 -5
- package/dist/dialog-header.js.map +0 -1
- package/dist/menu-action-row.js +0 -4
- package/dist/menu-action-row.js.map +0 -1
- package/dist/menu-header.d.ts +0 -41
- package/dist/menu-header.js +0 -6
- package/dist/menu-header.js.map +0 -1
- package/dist/menu-item.d.ts +0 -31
- package/dist/menu-item.js +0 -4
- package/dist/menu-item.js.map +0 -1
- package/dist/page-header.d.ts +0 -9
- package/dist/page-header.js +0 -3
- package/dist/page-header.js.map +0 -1
- package/dist/styles/dialog-header.css +0 -87
- package/dist/styles/menu-action-row.css +0 -160
- package/dist/styles/menu-header.css +0 -143
- package/dist/styles/menu-item.css +0 -123
- package/dist/styles/page-header.css +0 -33
- package/ux-demo/recipes/master-detail-dialog.tsx +0 -45
package/README.md
CHANGED
|
@@ -4,11 +4,27 @@ Accessible, composable UI primitives for [kerf](https://github.com/brianwestphal
|
|
|
4
4
|
|
|
5
5
|
Start interface work with the [need-first component selection matrix](./docs/component-selection.md). It distinguishes direct reuse, composition, thin application adapters, and genuinely custom semantics, with imports, required wiring, application ownership, alternatives, and recipes for every public primitive.
|
|
6
6
|
|
|
7
|
+
When adding a first-party public component, follow the
|
|
8
|
+
[component integration workflow](./docs/component-integration.md). The catalog
|
|
9
|
+
entry drives one validator across package, build, barrel, CSS, demo, route, and
|
|
10
|
+
AI signature projections, with a non-mutating dry-run report.
|
|
11
|
+
|
|
12
|
+
Browser verification always builds current source: both `npm run test:e2e`
|
|
13
|
+
and direct focused Playwright commands run the catalog/conformance preflights
|
|
14
|
+
and production build before preview. See the [UX catalog contract](./docs/ux-demo.md).
|
|
15
|
+
|
|
16
|
+
When authoring a component gallery, follow the single
|
|
17
|
+
[Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
|
|
18
|
+
for focused-versus-composition modes, helper nesting, specimen selection,
|
|
19
|
+
geometry inspection, and metadata ownership. AI tools can discover that
|
|
20
|
+
contract and its public imports through the shipped
|
|
21
|
+
[`catalog-authoring.json`](./ai/catalog-authoring.json) artifact.
|
|
22
|
+
|
|
7
23
|
For connective application patterns, use the seven [production composition
|
|
8
24
|
recipes](./docs/recipes.md). Each has a stable catalog route, runnable state,
|
|
9
25
|
public-subpath source, semantic layout ownership, and explicit application
|
|
10
26
|
customization boundaries. The composer recipe demonstrates one coherent form
|
|
11
|
-
surface with `
|
|
27
|
+
surface with a `Toolbar`/`ToolbarText` heading and field/action controls aligned to the
|
|
12
28
|
shared 8px gutter; only persistent feedback adds a nested semantic
|
|
13
29
|
`StateBanner` surface.
|
|
14
30
|
|
|
@@ -23,60 +39,80 @@ npm install kerfjs @kerfjs/ui
|
|
|
23
39
|
```
|
|
24
40
|
|
|
25
41
|
```tsx
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import { Toolbar } from
|
|
30
|
-
import { ToolbarControlGroup } from
|
|
31
|
-
import { ToolbarText } from
|
|
32
|
-
|
|
33
|
-
mount(root, () =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
action="show-workspace-actions"
|
|
39
|
-
actionLabel="Workspace actions"
|
|
40
|
-
rootAttributes={{ 'data-section-id': 'workspace' }}
|
|
41
|
-
triggerAttributes={{
|
|
42
|
-
popoverTarget: 'workspace-actions',
|
|
43
|
-
popoverTargetAction: 'toggle',
|
|
44
|
-
'aria-controls': 'workspace-actions',
|
|
45
|
-
'aria-haspopup': 'dialog',
|
|
46
|
-
}}
|
|
47
|
-
/>
|
|
48
|
-
<MenuItem
|
|
49
|
-
action="open-notes"
|
|
50
|
-
label="Notes"
|
|
51
|
-
selected
|
|
52
|
-
rootAttributes={{ 'data-command-color': 'blue', 'data-drop-status': 'ready' }}
|
|
42
|
+
import { ListItem } from "@kerfjs/ui/list-item";
|
|
43
|
+
import { ListHeader } from "@kerfjs/ui/list-header";
|
|
44
|
+
import { ListActionRow } from "@kerfjs/ui/list-action-row";
|
|
45
|
+
import { Toolbar } from "@kerfjs/ui/toolbar";
|
|
46
|
+
import { ToolbarControlGroup } from "@kerfjs/ui/toolbar-control-group";
|
|
47
|
+
import { ToolbarText } from "@kerfjs/ui/toolbar-text";
|
|
48
|
+
|
|
49
|
+
mount(root, () => (
|
|
50
|
+
<>
|
|
51
|
+
<Toolbar
|
|
52
|
+
label="Document"
|
|
53
|
+
leading={<ToolbarText text="Notes" />}
|
|
53
54
|
/>
|
|
54
|
-
<
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
<section>
|
|
56
|
+
<ListHeader
|
|
57
|
+
label="Workspace"
|
|
58
|
+
action="show-workspace-actions"
|
|
59
|
+
actionLabel="Workspace actions"
|
|
60
|
+
rootAttributes={{ "data-section-id": "workspace" }}
|
|
61
|
+
triggerAttributes={{
|
|
62
|
+
popoverTarget: "workspace-actions",
|
|
63
|
+
popoverTargetAction: "toggle",
|
|
64
|
+
"aria-controls": "workspace-actions",
|
|
65
|
+
"aria-haspopup": "dialog",
|
|
66
|
+
}}
|
|
67
|
+
/>
|
|
68
|
+
<ListItem
|
|
69
|
+
action="open-notes"
|
|
70
|
+
label="Notes"
|
|
71
|
+
selected
|
|
72
|
+
rootAttributes={{
|
|
73
|
+
"data-command-color": "blue",
|
|
74
|
+
"data-drop-status": "ready",
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
<ListActionRow
|
|
78
|
+
action="open-file"
|
|
79
|
+
itemId="src/main.ts"
|
|
80
|
+
label="src/main.ts"
|
|
81
|
+
trailingAction="open-file-actions"
|
|
82
|
+
trailingActionLabel="Actions for src/main.ts"
|
|
83
|
+
trailingActionIcon={moreIcon}
|
|
84
|
+
/>
|
|
85
|
+
<div id="workspace-actions" popover="auto">
|
|
86
|
+
Application-owned actions
|
|
87
|
+
</div>
|
|
88
|
+
</section>
|
|
89
|
+
</>
|
|
90
|
+
));
|
|
65
91
|
```
|
|
66
92
|
|
|
67
93
|
Components return Kerf `SafeHtml`. They do not own application state or attach transient listeners. Actions are stable `data-action` hooks; the application wires them once with `delegate()` or `delegateActions()` and retains the disposer.
|
|
68
94
|
|
|
69
|
-
`
|
|
70
|
-
|
|
95
|
+
Component content positions use one convention: `children` is the homogeneous
|
|
96
|
+
primary region, while semantic positions and replacement content use explicit
|
|
97
|
+
named `SafeHtml` props such as `header`, `footer`, `leading`, `trailing`,
|
|
98
|
+
`icon`, and `action`. These named `SafeHtml` prop slots are ordinary typed
|
|
99
|
+
function-component props—not native `<slot>` elements, wrapper slot
|
|
100
|
+
components, or a generic `slots` object. The v2 composition catalog publishes
|
|
101
|
+
sound prop bindings as `zone.jsx.prop`, allowing ESLint to validate statically
|
|
102
|
+
visible content and cardinality without guessing from zone names.
|
|
103
|
+
|
|
104
|
+
`ListItem.rootAttributes`, `ListHeader.rootAttributes`,
|
|
105
|
+
`ListActionRow.rootAttributes`, `AppTab.rootAttributes`,
|
|
106
|
+
`CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` carry typed
|
|
71
107
|
application `data-*` metadata without
|
|
72
|
-
teaching the package domain fields. `
|
|
73
|
-
`
|
|
108
|
+
teaching the package domain fields. `ListHeader.triggerAttributes` and
|
|
109
|
+
`ListActionRow.trailingActionAttributes` additionally support native popover
|
|
74
110
|
target and relationship attributes. Roles and component-owned action, selection,
|
|
75
|
-
disclosure, naming, disabled, and
|
|
111
|
+
disclosure, naming, disabled, icon, and catalog-structure semantics remain protected props; an
|
|
76
112
|
isolated `role="menuitem"` is not an extension shortcut.
|
|
77
113
|
The slots are also filtered at runtime, so structurally widened objects and
|
|
78
114
|
JavaScript callers cannot bypass those protections with case-variant names.
|
|
79
|
-
`
|
|
115
|
+
`ListItem.trailing` is dormant metadata. Use `ListActionRow` when a row needs
|
|
80
116
|
sibling primary and trailing native-button actions with independent names,
|
|
81
117
|
disabled states, focus, and click ownership. Its `label`, `icon`, and
|
|
82
118
|
`trailingActionIcon` slots are dormant content and must not contain controls.
|
|
@@ -90,40 +126,93 @@ Do not concatenate a count into `label` or pass a numeric `badge`; the mutually
|
|
|
90
126
|
exclusive legacy `badge` slot remains available for non-count `SafeHtml` such
|
|
91
127
|
as a `New` marker.
|
|
92
128
|
|
|
129
|
+
`Row.gap`, `List.gap`, and `Spacer` dimensions accept a direct spacing name such as
|
|
130
|
+
`gap="xs"` or `gap="m"`, or a branded `CssLength`. Import `space`, `rem`, `em`,
|
|
131
|
+
`px`, `pct`, `lengthVar`, `plus`, and `calc` from the CSS-free
|
|
132
|
+
`@kerfjs/ui/css-values` subpath when a named step is not enough. `plus` returns
|
|
133
|
+
an incomplete expression, so wrap it with `calc` before passing it to a prop.
|
|
134
|
+
Raw CSS strings are deliberately rejected; the opaque brands catch authoring
|
|
135
|
+
mistakes but are not sanitizers.
|
|
136
|
+
|
|
137
|
+
Use `Row` for horizontal flex composition and `List` for vertical composition.
|
|
138
|
+
Both accept `hAlign` (`left`, `center`, `right`, `full`) and `vAlign` (`top`,
|
|
139
|
+
`middle`, `bottom`, `full`), plus their documented short/CSS aliases. `Row`
|
|
140
|
+
defaults to left/full alignment, the `xs` gap, and `wrap={false}`; List keeps
|
|
141
|
+
its existing full/top alignment and zero-gap defaults. Set `textInsets` or
|
|
142
|
+
`controlInsets` with canonical physical sides in `t`/`r`/`b`/`l` order (for
|
|
143
|
+
example, `textInsets="tbl"` or `controlInsets="r"`). Text geometry takes
|
|
144
|
+
precedence where both select the same side. `ListInsetText` and
|
|
145
|
+
`ListInsetControl` inset all four sides by default and accept the same `sides`
|
|
146
|
+
grammar for selective insets.
|
|
147
|
+
|
|
148
|
+
The same property-specific boundary applies beyond spacing: use `flex()` (or a
|
|
149
|
+
finite keyword) for `Row.flex` and `List.flex`; length builders and intrinsic-size keywords for
|
|
150
|
+
`Skeleton.width`/`height`; length builders for `Skeleton.radius`; and
|
|
151
|
+
`uiColor()` or `colorVar()` for `SelectChoice.color`. These grammars are not
|
|
152
|
+
interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
|
|
153
|
+
`style` declarations; use `className`, public tokens, and component props.
|
|
154
|
+
|
|
93
155
|
## Component subpaths
|
|
94
156
|
|
|
95
|
-
| Component
|
|
96
|
-
|
|
|
97
|
-
| `LucideIcon`
|
|
98
|
-
| `DisclosureArrow`
|
|
99
|
-
| `Toolbar`
|
|
100
|
-
| `ToolbarControlGroup`
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
|
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
|
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
112
|
-
| `
|
|
113
|
-
| `
|
|
114
|
-
| `
|
|
115
|
-
| `
|
|
116
|
-
| `
|
|
117
|
-
| `
|
|
118
|
-
| `
|
|
119
|
-
| `
|
|
120
|
-
| `
|
|
121
|
-
|
|
122
|
-
`
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
157
|
+
| Component | Browser import (includes reachable CSS) | Manual CSS export |
|
|
158
|
+
| ------------------------------------------------------------------- | --------------------------------------- | -------------------------------------- |
|
|
159
|
+
| `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
|
|
160
|
+
| `DisclosureArrow` | `@kerfjs/ui/disclosure-arrow` | `@kerfjs/ui/disclosure-arrow.css` |
|
|
161
|
+
| `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
|
|
162
|
+
| `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
|
|
163
|
+
| `DialogSurface`, `PopupSurface` | `@kerfjs/ui/surface-scaffold` | `@kerfjs/ui/surface-scaffold.css` |
|
|
164
|
+
| `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
|
|
165
|
+
| `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
|
|
166
|
+
| `Text` | `@kerfjs/ui/text` | `@kerfjs/ui/text.css` |
|
|
167
|
+
| `List` | `@kerfjs/ui/list` | `@kerfjs/ui/list.css` |
|
|
168
|
+
| `Row` | `@kerfjs/ui/row` | `@kerfjs/ui/row.css` |
|
|
169
|
+
| `Spacer` | `@kerfjs/ui/spacer` | `@kerfjs/ui/spacer.css` |
|
|
170
|
+
| Typed CSS dimension builders | `@kerfjs/ui/css-values` | — |
|
|
171
|
+
| `ListActionRow` | `@kerfjs/ui/list-action-row` | `@kerfjs/ui/list-action-row.css` |
|
|
172
|
+
| `ListItem` | `@kerfjs/ui/list-item` | `@kerfjs/ui/list-item.css` |
|
|
173
|
+
| `ListHeader` | `@kerfjs/ui/list-header` | `@kerfjs/ui/list-header.css` |
|
|
174
|
+
| `ListInsetControl` | `@kerfjs/ui/list-inset-control` | `@kerfjs/ui/list-inset-control.css` |
|
|
175
|
+
| `ListInsetText` | `@kerfjs/ui/list-inset-text` | `@kerfjs/ui/list-inset-text.css` |
|
|
176
|
+
| `Pane` | `@kerfjs/ui/pane` | `@kerfjs/ui/pane.css` |
|
|
177
|
+
| `NavStack` | `@kerfjs/ui/nav-stack` | `@kerfjs/ui/nav-stack.css` |
|
|
178
|
+
| `wireNavStack` | `@kerfjs/ui/wire-nav-stack` | — |
|
|
179
|
+
| `SplitView` | `@kerfjs/ui/split-view` | `@kerfjs/ui/split-view.css` |
|
|
180
|
+
| `TabScaffold` | `@kerfjs/ui/tab-scaffold` | `@kerfjs/ui/tab-scaffold.css` |
|
|
181
|
+
| `wireTabScaffold` | `@kerfjs/ui/wire-tab-scaffold` | — |
|
|
182
|
+
| `Workbench` | `@kerfjs/ui/workbench` | `@kerfjs/ui/workbench.css` |
|
|
183
|
+
| `CollapsiblePanel`, `CollapsiblePanelToggle` | `@kerfjs/ui/collapsible-panel` | `@kerfjs/ui/collapsible-panel.css` |
|
|
184
|
+
| `wireSidebar` | `@kerfjs/ui/wire-sidebar` | — |
|
|
185
|
+
| Content and navigation composition | — | `@kerfjs/ui/layout.css` |
|
|
186
|
+
| `ResizableRegion` | `@kerfjs/ui/resizable-region` | `@kerfjs/ui/resizable-region.css` |
|
|
187
|
+
| `wireResizableRegions` | `@kerfjs/ui/wire-resizable-regions` | — |
|
|
188
|
+
| `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
|
|
189
|
+
| `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
|
|
190
|
+
| `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | — |
|
|
191
|
+
| `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
|
|
192
|
+
| `Skeleton` | `@kerfjs/ui/skeleton` | `@kerfjs/ui/skeleton.css` |
|
|
193
|
+
| `SunkenPanel` | `@kerfjs/ui/sunken-panel` | `@kerfjs/ui/sunken-panel.css` |
|
|
194
|
+
| `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
|
|
195
|
+
| `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
|
|
196
|
+
| `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret` | `@kerfjs/ui/token-search-field` | `@kerfjs/ui/token-search-field.css` |
|
|
197
|
+
| `wireTokenSearchFields` | `@kerfjs/ui/wire-token-search-fields` | — |
|
|
198
|
+
| `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
|
|
199
|
+
| `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
|
|
200
|
+
| `ValueTable`, `ValueTableRow` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
|
|
201
|
+
|
|
202
|
+
Opt-in application layouts keep JavaScript and CSS explicit. Import each
|
|
203
|
+
layout from its component subpath, load the matching manual CSS export, and
|
|
204
|
+
add its wire subpath when the layout has interactive behavior. The catalog
|
|
205
|
+
entries for `nav-stack`, `split-view`, `tab-scaffold`, `workbench`, and
|
|
206
|
+
`collapsible-panel` document their selection rules, ownership boundaries,
|
|
207
|
+
public classes, tokens, and focused demos. See
|
|
208
|
+
[`docs/app-layouts.md`](./docs/app-layouts.md) for the layout decision matrix.
|
|
209
|
+
|
|
210
|
+
Compose panel, dialog, and page headings directly with `Toolbar`: put an optional
|
|
211
|
+
icon in a `ToolbarControlGroup`, use a direct extra-large `ToolbarText` for the
|
|
212
|
+
title, and put actions in the trailing zone inside their own control group. Set
|
|
213
|
+
`headingLevel` for page or section headings. Supporting copy is app-owned content
|
|
214
|
+
below the toolbar and should be connected to its host with `aria-describedby`
|
|
215
|
+
when it adds useful context.
|
|
127
216
|
|
|
128
217
|
`DisclosureArrow` defaults to an 18px root-scaled decorative visual. Override
|
|
129
218
|
`--kui-disclosure-arrow-size` at the narrowest useful scope when a consumer
|
|
@@ -134,14 +223,15 @@ scale of `.5` through `--kui-disclosure-icon-scale`. Author replacement
|
|
|
134
223
|
transform is applied. Direction changes take the shortest rotation path; a
|
|
135
224
|
180-degree closed-to-open tie uses counterclockwise rotation.
|
|
136
225
|
|
|
137
|
-
`
|
|
226
|
+
`ListHeader` supplies that production `DisclosureArrow` automatically when
|
|
138
227
|
`toggle` is true and `actionIcon` is omitted. Keep `expanded` synchronized with
|
|
139
228
|
real controlled content and preserve the button's stable label; ordinary
|
|
140
229
|
navigation must not display a disclosure arrow. A custom `actionIcon` remains
|
|
141
230
|
an escape hatch and replaces the default arrow entirely. The header fills its
|
|
142
|
-
available inline width
|
|
143
|
-
|
|
144
|
-
|
|
231
|
+
available inline width by default; set `inline` to shrink-wrap it beside other
|
|
232
|
+
content and remove its root margin, border, and padding. It keeps a separate
|
|
233
|
+
action at the logical end. Its visible action glyph defaults to 18px through
|
|
234
|
+
`--kui-list-header-action-icon-size`.
|
|
145
235
|
|
|
146
236
|
## Machine-readable catalog
|
|
147
237
|
|
|
@@ -152,7 +242,124 @@ delivery and side effects, companion wiring, application-owned policy,
|
|
|
152
242
|
variants, accessibility obligations, public CSS hooks, routes, and current
|
|
153
243
|
documentation/recipe links. The adjacent
|
|
154
244
|
[`component-catalog.schema.json`](./ai/component-catalog.schema.json) describes
|
|
155
|
-
the versioned format.
|
|
245
|
+
the versioned format. Every visual entry also declares who owns its margin,
|
|
246
|
+
border, and padding, so a generator can fit it into Kerf's alignment model
|
|
247
|
+
without guessing from a screenshot or private CSS.
|
|
248
|
+
|
|
249
|
+
Catalog demo authoring is deliberately separate from the entry inventory. Load
|
|
250
|
+
[`catalog-authoring.json`](./ai/catalog-authoring.json) to discover the
|
|
251
|
+
authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract),
|
|
252
|
+
the exact API-signature context, public imports/helpers, and sanctioned metadata
|
|
253
|
+
slot. Keeping this as a companion artifact prevents per-entry selection facts
|
|
254
|
+
from duplicating presentation rules.
|
|
255
|
+
|
|
256
|
+
Tools that evaluate composition may additionally load
|
|
257
|
+
[`component-catalog-v2.json`](./ai/component-catalog-v2.json). It is a
|
|
258
|
+
deterministic, package-qualified projection of every v1 entry with formal
|
|
259
|
+
parent/context, zone/cardinality, child, state ownership, wiring, responsive,
|
|
260
|
+
layout, accessibility, public-boundary, and stable-diagnostic fields. V1
|
|
261
|
+
remains the selection and delivery compatibility surface. V2 defaults are
|
|
262
|
+
deliberately permissive; only documented objective rules receive an
|
|
263
|
+
authoritative override and enforceable diagnostic. The adjacent schema and
|
|
264
|
+
[`component-catalog-v2.d.ts`](./ai/component-catalog-v2.d.ts) types describe
|
|
265
|
+
the same contract.
|
|
266
|
+
|
|
267
|
+
Applications and downstream design systems should publish the same facts for
|
|
268
|
+
their own components. Start from the reusable
|
|
269
|
+
[`component-catalog-extension.schema.json`](./ai/component-catalog-extension.schema.json)
|
|
270
|
+
and the checked
|
|
271
|
+
[`component-catalog-extension.json`](./docs/examples/component-catalog-extension.json)
|
|
272
|
+
example. Give each app-owned component or composition a stable id, selection
|
|
273
|
+
guidance, public hooks, and explicit geometry ownership; then concatenate its
|
|
274
|
+
`entries` with Kerf's shipped `entries` in the AI context. Keep package/source
|
|
275
|
+
identity alongside each input when ids could collide. This makes a combined
|
|
276
|
+
tool reason about both sides of a composition using one vocabulary without
|
|
277
|
+
pretending app-local components are `@kerfjs/ui` exports.
|
|
278
|
+
|
|
279
|
+
Composition-aware consumers use
|
|
280
|
+
[`component-catalog-extension-v2.schema.json`](./ai/component-catalog-extension-v2.schema.json),
|
|
281
|
+
its shipped TypeScript types, and the checked
|
|
282
|
+
[`component-catalog-extension-v2.json`](./docs/examples/component-catalog-extension-v2.json)
|
|
283
|
+
example. Preserve each catalog's package and qualify every identity and
|
|
284
|
+
cross-catalog reference as `package:id`; never merge entries by bare id.
|
|
285
|
+
|
|
286
|
+
[`compile-time-contracts-v1.json`](./ai/compile-time-contracts-v1.json) is the
|
|
287
|
+
matching declaration contract: stable `KUI-T###` ids identify the invalid prop,
|
|
288
|
+
state, identity, accessibility, and protected-attribute combinations TypeScript
|
|
289
|
+
rejects. The package gate compiles one positive/negative consumer fixture against
|
|
290
|
+
both source and declarations extracted from the real packed tarball. The
|
|
291
|
+
[compile-time contract guide](./docs/type-contracts.md) documents migrations and
|
|
292
|
+
the dynamic DOM/children relationships that remain runtime or catalog checks.
|
|
293
|
+
Packages scaffolded by `create-kerf-component` maintain this v2 input from
|
|
294
|
+
`kerf.components.json`: `npm run catalog:generate` emits the catalog and
|
|
295
|
+
`npm run catalog:check` verifies source files, named public exports, explicit
|
|
296
|
+
author decisions, and byte-for-byte drift. Tools index the generated consumer
|
|
297
|
+
entries and this catalog by full key, reject duplicate full keys, search the
|
|
298
|
+
consumer package first, and retain package identity across every reference.
|
|
299
|
+
They must not infer missing semantics or geometry from rendered appearance.
|
|
300
|
+
|
|
301
|
+
### Application UI profile
|
|
302
|
+
|
|
303
|
+
Applications can check in `.kerf-ui-profile.json` so tools do not have to infer
|
|
304
|
+
project-wide UI policy. Start from the shipped
|
|
305
|
+
[`application-ui-profile.defaults.json`](./ai/application-ui-profile.defaults.json)
|
|
306
|
+
and the checked
|
|
307
|
+
[`application-ui-profile.json`](./docs/examples/application-ui-profile.json)
|
|
308
|
+
workspace example. The versioned
|
|
309
|
+
[`application-ui-profile.schema.json`](./ai/application-ui-profile.schema.json)
|
|
310
|
+
and [`application-ui-profile.d.ts`](./ai/application-ui-profile.d.ts) cover
|
|
311
|
+
catalog locations, concept preferences, allowed theme/density choices, semantic
|
|
312
|
+
token overrides, layout/responsive conventions, and narrow rule exceptions.
|
|
313
|
+
Profiles contain policy only—never product records, user data, or broad styling
|
|
314
|
+
waivers.
|
|
315
|
+
|
|
316
|
+
Catalog declarations always provide a v2 `composition` location. Consumer
|
|
317
|
+
packages generated with composition-only metadata omit `selection`;
|
|
318
|
+
`@kerfjs/ui` continues to require its v1 selection catalog.
|
|
319
|
+
|
|
320
|
+
Node-based AI and static-analysis tools may import the shipped discovery API
|
|
321
|
+
from `@kerfjs/ui/ai/application-ui-profile.mjs`. It discovers package defaults,
|
|
322
|
+
then the workspace profile, then directory profiles from parent to child;
|
|
323
|
+
`mergeApplicationUiProfiles()` applies later scalar/map values, replaces a
|
|
324
|
+
catalog by package and an exception by id, and preserves source provenance.
|
|
325
|
+
`loadApplicationUiProfile()` resolves catalogs and returns diagnostics with the
|
|
326
|
+
originating file plus JSON path. Unknown/stale components, tokens, rules, and
|
|
327
|
+
catalog locations are errors. Every layer is checked against its then-effective
|
|
328
|
+
catalogs, including parent references and catalog paths later overridden by a
|
|
329
|
+
child profile. Synchronous integrations can require the shipped
|
|
330
|
+
`application-ui-profile-sync.cjs` projection and call
|
|
331
|
+
`loadApplicationUiProfileSync()` with already-discovered layers. Consumers that define additional stable
|
|
332
|
+
diagnostics pass their ids through the additive `knownRules` option; those ids
|
|
333
|
+
are merged with catalog diagnostics before exception validation.
|
|
334
|
+
|
|
335
|
+
### Static CSS and layout ownership analysis
|
|
336
|
+
|
|
337
|
+
Run `kerf-ui-analyze --root . src` (or import
|
|
338
|
+
`@kerfjs/ui/analyzer`) to evaluate cross-file integration facts against the
|
|
339
|
+
composition catalogs and application profile. It catches provable private
|
|
340
|
+
selector reach-through, unknown tokens, competing geometry owners, nested
|
|
341
|
+
scroll owners, and cataloged CSS-value violations in JavaScript/TypeScript
|
|
342
|
+
component calls and JSX. It reports forced dimensions, repeated insets,
|
|
343
|
+
exceptional spacing shorthands, and dynamic classes separately as review
|
|
344
|
+
findings. Text, versioned JSON,
|
|
345
|
+
and SARIF outputs carry stable `KUI-L###` ids, repository-relative locations,
|
|
346
|
+
evidence, and ownership chains. See the [analyzer guide](./docs/ui-analyzer.md).
|
|
347
|
+
|
|
348
|
+
### Browser-backed integration evaluation
|
|
349
|
+
|
|
350
|
+
Run `kerf-ui-evaluate --url <running-app>` (or import
|
|
351
|
+
`@kerfjs/ui/evaluator`) after the static analyzer. Its Playwright-backed
|
|
352
|
+
wide/intermediate/narrow/200%-zoom, light/dark, and reduced-motion matrix checks
|
|
353
|
+
rendered overflow, clipping, reachability, focus/keyboard behavior, accessible
|
|
354
|
+
names, contrast, hit targets, scrolling, alignment, and cataloged runtime
|
|
355
|
+
geometry. The versioned report carries stable `KUI-B###` diagnostics, focused
|
|
356
|
+
DOM/computed-style evidence, hashed screenshot artifacts, explicit timeout and
|
|
357
|
+
retention policy, and a separate unscored human-visual rubric. See the
|
|
358
|
+
[browser evaluator guide](./docs/ui-evaluator.md).
|
|
359
|
+
|
|
360
|
+
### Unified repair-loop doctor
|
|
361
|
+
|
|
362
|
+
Use `kerf-ui-doctor` for the supported application repair loop across profile/catalog validation, TypeScript, the Kerf UI ESLint preset, static layout analysis, and an optional explicitly authorized browser evaluation. Its isolated Kerf lint pass preserves each file's applicable core-rule and suppression settings without executing consumer plugin rules. It emits one portable versioned JSON report with deterministic exit codes, exact suppressions, monorepo package selection, changed/full modes, caching, and local-path redaction. See the [UI doctor guide](./docs/ui-doctor.md).
|
|
156
363
|
|
|
157
364
|
For code generation, pair catalog selection guidance with the checked-in
|
|
158
365
|
[`public-api-signatures-v1.md`](./ai/public-api-signatures-v1.md) declaration
|
|
@@ -188,9 +395,10 @@ that convenience import, also import `@kerfjs/ui/styles.css`, which deliberately
|
|
|
188
395
|
contains the complete layer. Non-browser/SSR tools resolve the pure `import`
|
|
189
396
|
condition automatically; `@kerfjs/ui/unstyled` is the explicit CSS-free root
|
|
190
397
|
entry for a browser build with a custom styling pipeline. The exported
|
|
191
|
-
|
|
192
|
-
delivery.
|
|
193
|
-
|
|
398
|
+
`@kerfjs/ui/foundation.css` and component CSS paths remain available for fully
|
|
399
|
+
manual delivery. Its complete supported `--kui-*` token surface is cataloged
|
|
400
|
+
under the `foundation` entry. Load application overrides after package styles,
|
|
401
|
+
or scope variables directly on a component instance.
|
|
194
402
|
|
|
195
403
|
## Pane and content geometry
|
|
196
404
|
|
|
@@ -204,9 +412,9 @@ Add `.kui-content` to make its major children a vertical stack with 24px gaps.
|
|
|
204
412
|
<div class="kui-pane__toolbar"><Toolbar label="Workspace" ... /></div>
|
|
205
413
|
<nav class="kui-pane__content kui-content">
|
|
206
414
|
<section>
|
|
207
|
-
<
|
|
208
|
-
<
|
|
209
|
-
<
|
|
415
|
+
<ListHeader label="Workspace" count={3} countLabel="3 workspaces" />
|
|
416
|
+
<ListItem action="open" label="Inbox" icon={inboxIcon} />
|
|
417
|
+
<ListItem action="open" label="Drafts" />
|
|
210
418
|
</section>
|
|
211
419
|
<div class="kui-content-item">Workspace details</div>
|
|
212
420
|
</nav>
|
|
@@ -216,7 +424,7 @@ Add `.kui-content` to make its major children a vertical stack with 24px gaps.
|
|
|
216
424
|
Ordinary children use `.kui-content-item`: 8px inline margin, a real 1px border
|
|
217
425
|
(transparent by default), 8px padding, and 12px rounded corners. The pill
|
|
218
426
|
modifier uses a 22px radius. A component can expose a transparent border or
|
|
219
|
-
background without changing layout. `
|
|
427
|
+
background without changing layout. `ListHeader` follows the same rule while
|
|
220
428
|
keeping its dormant title and count-or-badge cluster separate from its optional
|
|
221
429
|
44px action.
|
|
222
430
|
|
|
@@ -236,10 +444,10 @@ Apps using Web Awesome's free components can opt into the same visual universe
|
|
|
236
444
|
with one CSS import:
|
|
237
445
|
|
|
238
446
|
```ts
|
|
239
|
-
import type {} from
|
|
240
|
-
import
|
|
241
|
-
import
|
|
242
|
-
import
|
|
447
|
+
import type {} from "@kerfjs/ui/webawesome";
|
|
448
|
+
import "@kerfjs/ui/webawesome.css";
|
|
449
|
+
import "@awesome.me/webawesome/dist/components/button/button.js";
|
|
450
|
+
import "@awesome.me/webawesome/dist/components/input/input.js";
|
|
243
451
|
```
|
|
244
452
|
|
|
245
453
|
The type-only `@kerfjs/ui/webawesome` import adds Kerf JSX intrinsic-element
|
|
@@ -250,6 +458,9 @@ Awesome modules the application renders.
|
|
|
250
458
|
`webawesome.css` includes Web Awesome's native/base theme and then applies the
|
|
251
459
|
Hot Sheet 2 palette, surfaces, status colors, focus treatment, form geometry,
|
|
252
460
|
radii, tooltips, and shadows through Web Awesome's public `--wa-*` contract.
|
|
461
|
+
On `wa-dialog`, the optional `hide-actions` class hides the exported
|
|
462
|
+
`header-actions` shadow part for compositions that provide another dismissal
|
|
463
|
+
affordance.
|
|
253
464
|
Those tokens flow into all free component families. Every free Web Awesome 3.12
|
|
254
465
|
component has an individual UX-catalog route under the collapsible ecosystem
|
|
255
466
|
section, but the theme entry does not import or register component JavaScript,
|
|
@@ -265,13 +476,15 @@ classes for explicit appearance boundaries:
|
|
|
265
476
|
```css
|
|
266
477
|
:root {
|
|
267
478
|
--wa-color-brand-fill-loud: #7540a8;
|
|
268
|
-
--wa-form-control-border-radius: .5rem;
|
|
479
|
+
--wa-form-control-border-radius: 0.5rem;
|
|
269
480
|
}
|
|
270
481
|
```
|
|
271
482
|
|
|
272
483
|
`foundation.css` follows Hot Sheet 2's Web Awesome-compatible semantic palette.
|
|
273
|
-
Brand, neutral, success, warning, and danger each expose fill, border, and
|
|
274
|
-
foreground roles through `--kui-color
|
|
484
|
+
Brand, pop, neutral, success, warning, and danger each expose fill, border, and
|
|
485
|
+
foreground roles through `--kui-color-*`. Pop is attractive, non-status emphasis
|
|
486
|
+
for featured, novel, or celebratory content; it never substitutes for success,
|
|
487
|
+
warning, or danger. Stateful components also expose
|
|
275
488
|
component variables such as `--kui-state-banner-background`. Override the
|
|
276
489
|
foundation for an application theme, a tone variable for one semantic state, or
|
|
277
490
|
a component variable on one instance without replacing component selectors.
|
|
@@ -280,8 +493,8 @@ needs a selector, the component catalog's `publicClasses` arrays define the
|
|
|
280
493
|
exact stable anatomy: public-class-to-public-class selectors are supported;
|
|
281
494
|
descendant tag, id, attribute-only, and unlisted-class selectors are not.
|
|
282
495
|
|
|
283
|
-
`StateBanner` has opinionated `neutral`, `info`, `success`, `warning`,
|
|
284
|
-
`danger` palettes. Override an individual banner with
|
|
496
|
+
`StateBanner` has opinionated `neutral`, `info`, `pop`, `success`, `warning`,
|
|
497
|
+
and `danger` palettes. Override an individual banner with
|
|
285
498
|
`--kui-state-banner-background`, `--kui-state-banner-border`,
|
|
286
499
|
`--kui-state-banner-foreground`, `--kui-state-banner-detail`,
|
|
287
500
|
`--kui-state-banner-action-background`, and
|
|
@@ -305,8 +518,8 @@ standalone `filled`/`outlined` appearance with `shape="rounded"` or
|
|
|
305
518
|
appearance="toolbar"
|
|
306
519
|
shape="pill"
|
|
307
520
|
choices={[
|
|
308
|
-
{ value:
|
|
309
|
-
{ value:
|
|
521
|
+
{ value: "list", label: "List" },
|
|
522
|
+
{ value: "columns", label: "Columns" },
|
|
310
523
|
]}
|
|
311
524
|
/>
|
|
312
525
|
```
|
|
@@ -326,8 +539,14 @@ after browser input to recover text plus token offsets, and
|
|
|
326
539
|
Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
|
|
327
540
|
`onSubmit` without inserting a contenteditable line break and to preserve focus
|
|
328
541
|
plus the text-relative caret when keyboard deletion of a chip causes controlled
|
|
329
|
-
rendering to replace the editor.
|
|
330
|
-
|
|
542
|
+
rendering to replace the editor. A select-all deletion is normalized to a truly
|
|
543
|
+
empty editor even when the browser leaves an atomic chip or line break behind;
|
|
544
|
+
replacement typing consumes that intent so a later Backspace/Delete remains an
|
|
545
|
+
ordinary character edit.
|
|
546
|
+
Managed deletion keeps a collapsible replacement editor open and focused before
|
|
547
|
+
the next keystroke; applications must persist both query and tokens from the DOM
|
|
548
|
+
read. Genuine outside focus and Escape still collapse an empty field.
|
|
549
|
+
Text still wraps visually when it reaches the field edge.
|
|
331
550
|
Clear actions should empty the editor's `textContent` before clearing app state.
|
|
332
551
|
The leading icon, first text line, clear action, and trailing slot share one
|
|
333
552
|
fixed alignment row; when text wraps, those controls stay pinned to that first
|
|
@@ -359,15 +578,25 @@ close button retains all close interaction.
|
|
|
359
578
|
`Select` uses Web Awesome but does not register anything by itself. Install the optional peer, import the shared theme if desired, and explicitly import the registration entry in the application:
|
|
360
579
|
|
|
361
580
|
```ts
|
|
362
|
-
import
|
|
363
|
-
import
|
|
581
|
+
import "@kerfjs/ui/webawesome.css";
|
|
582
|
+
import "@kerfjs/ui/select/register";
|
|
364
583
|
```
|
|
365
584
|
|
|
366
585
|
That boundary keeps Web Awesome and its custom-element side effects out of bundles that use unrelated components. Automated consumer-bundle tests enforce it.
|
|
586
|
+
Use `label` for a visible label or `ariaLabel` for a visually hidden name. A
|
|
587
|
+
nonempty visible label takes precedence when both are supplied. Kerf names the
|
|
588
|
+
actual shadow combobox without adding visible label spacing; this also works
|
|
589
|
+
with `renderSelected`, and needs no application shadow-DOM patch. Use `hint`
|
|
590
|
+
for persistent supporting text below the control and `placeholderText` for the
|
|
591
|
+
empty value inside the closed control. Loading placeholders preserve the hint.
|
|
592
|
+
|
|
367
593
|
`Select` also owns the Kerf/Web Awesome reconciliation boundary: option icons
|
|
368
594
|
keep stable slotted elements across rerenders, and `renderSelected` content is
|
|
369
595
|
replaced when the controlled value changes. Consumers do not need to add
|
|
370
|
-
`data-key` or `data-morph-skip` workarounds around choice icons.
|
|
596
|
+
`data-key` or `data-morph-skip` workarounds around choice icons. Icon-bearing
|
|
597
|
+
options retain the standard icon-to-label gap. When a compact Select is wrapped
|
|
598
|
+
in a `ToolbarControlGroup`, use `focusRingOwner="group"`; the group paints the
|
|
599
|
+
focus ring with its configured pill or rounded geometry.
|
|
371
600
|
|
|
372
601
|
For application choices and panes, prefer Kerf's purpose-built primitives:
|
|
373
602
|
`Select` over direct Web Awesome selection/dropdown composition,
|
|
@@ -376,7 +605,11 @@ Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over
|
|
|
376
605
|
Split Panel. `ResizableRegion` includes Hot Sheet 2's 1px separator and
|
|
377
606
|
hover/focus grip. Its optional `handleIcon` replaces only the decorative glyph;
|
|
378
607
|
the component and `wireResizableRegions()` retain separator semantics and
|
|
379
|
-
pointer/keyboard behavior.
|
|
608
|
+
pointer/keyboard behavior. Typed policies cover separator visibility,
|
|
609
|
+
instant-track/composited-content collapse, popup-safe overflow,
|
|
610
|
+
inline/overlay/hidden responsive presentation, and safe-area restore controls;
|
|
611
|
+
the same policies are available on `Workbench` and `CollapsiblePanel`. Consider
|
|
612
|
+
Web Awesome Popup when its anchored-positioning
|
|
380
613
|
engine removes custom placement code; treat Tree, Animated Image, Comparison,
|
|
381
614
|
Zoomable Frame, and the displaced alternatives above as exceptional rather
|
|
382
615
|
than default patterns. The detailed rationale lives in the theme contract.
|
|
@@ -395,8 +628,9 @@ than default patterns. The detailed rationale lives in the theme contract.
|
|
|
395
628
|
|
|
396
629
|
Run `npm run dev` from this directory for the category-grouped master/detail catalog. Every public visual component has a focused route; all 70 free Web Awesome 3.12 components have focused routes under the collapsible ecosystem section. Every detail visibly links its first-party demo source and existing guidance while showing the repository-relative paths; first-party components also link their implementation source, and Web Awesome entries label local guidance as Kerf integration guidance. One grouped `Related components` selector contains derived `Uses` / `Used by` navigation across both sets. Run `npm run check` for static/unit/bundle gates and `npm run test:e2e` for the real-browser suite.
|
|
397
630
|
|
|
398
|
-
Run `npm run format
|
|
399
|
-
|
|
631
|
+
Run `npm run format` after editing source or structured content. The narrower
|
|
632
|
+
`npm run format:css` command remains available for style-only work. The normal
|
|
633
|
+
`npm run lint` and `npm run check` gates use Prettier to reject formatting drift.
|
|
400
634
|
|
|
401
635
|
For dimensions that should scale with the root font size, author pixels with
|
|
402
636
|
`remify()`: `gap: remify(17px)` builds to `gap: 1.0625rem` using a fixed 16px
|