@kerfjs/ui 4.4.1 → 4.5.0-beta.1
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 +425 -42
- package/ai/application-ui-diagnostic-ids-v1.json +92 -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 +102 -0
- package/ai/compile-time-contracts-v1.schema.json +49 -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 +319 -0
- package/ai/component-catalog-v2.d.ts +67 -0
- package/ai/component-catalog-v2.json +4675 -0
- package/ai/component-catalog-v2.schema.json +246 -0
- package/ai/component-catalog.json +5826 -0
- package/ai/component-catalog.schema.json +95 -0
- package/ai/public-api-signatures-v1.md +1719 -0
- package/ai/skill.md +129 -21
- package/ai/webawesome-jsx-signatures-v1.md +106 -0
- package/analyzer/cli.mjs +46 -0
- package/analyzer/index.d.mts +45 -0
- package/analyzer/index.mjs +737 -0
- package/analyzer/report.schema.json +66 -0
- package/dist/app-tab.d.ts +14 -2
- package/dist/app-tab.js +3 -1
- package/dist/browser/app-tab.js +3 -2
- package/dist/browser/disclosure-arrow.js +4 -0
- package/dist/browser/empty-state.js +3 -3
- package/dist/browser/floating-toolbar.js +3 -0
- package/dist/browser/list-action-row.js +4 -0
- package/dist/browser/list-header.js +6 -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 +4 -0
- package/dist/browser/list.js +3 -0
- package/dist/browser/loading-spinner.js +2 -2
- package/dist/browser/lucide-icon.js +2 -2
- package/dist/browser/pane.js +3 -0
- package/dist/browser/panel-header.js +7 -0
- package/dist/browser/resizable-region.js +2 -2
- package/dist/browser/segmented-control.js +3 -2
- package/dist/browser/select.js +4 -3
- package/dist/browser/skeleton.js +3 -0
- package/dist/browser/state-banner.js +3 -2
- package/dist/browser/sunken-panel.js +3 -0
- package/dist/browser/tab-bar.js +2 -2
- package/dist/browser/token-search-field.js +4 -0
- package/dist/browser/toolbar-control-group.js +2 -2
- package/dist/browser/toolbar-text.js +3 -2
- package/dist/browser/toolbar.js +2 -2
- package/dist/browser/value-table.js +3 -2
- package/dist/catalog-resources.d.ts +34 -0
- package/dist/catalog-resources.js +22 -0
- package/dist/catalog-resources.js.map +1 -0
- package/dist/catalog.d.ts +150 -0
- package/dist/catalog.js +377 -0
- package/dist/catalog.js.map +1 -0
- package/dist/chunk-5VTB2BKP.js +35 -0
- package/dist/chunk-5VTB2BKP.js.map +1 -0
- package/dist/chunk-6WTETUZ6.js +21 -0
- package/dist/chunk-6WTETUZ6.js.map +1 -0
- package/dist/chunk-7KEUJIIC.js +218 -0
- package/dist/chunk-7KEUJIIC.js.map +1 -0
- package/dist/chunk-7XRDUG4Y.js +58 -0
- package/dist/chunk-7XRDUG4Y.js.map +1 -0
- package/dist/chunk-B3A3IVO5.js +83 -0
- package/dist/chunk-B3A3IVO5.js.map +1 -0
- package/dist/chunk-DPDBVKNA.js +113 -0
- package/dist/chunk-DPDBVKNA.js.map +1 -0
- package/dist/chunk-FEAMR7S4.js +68 -0
- package/dist/chunk-FEAMR7S4.js.map +1 -0
- package/dist/chunk-FEY65TBV.js +15 -0
- package/dist/chunk-FEY65TBV.js.map +1 -0
- package/dist/{chunk-TRNBHPNW.js → chunk-IJBSZ4NX.js} +11 -8
- package/dist/chunk-IJBSZ4NX.js.map +1 -0
- package/dist/chunk-J5BFYY7Q.js +35 -0
- package/dist/chunk-J5BFYY7Q.js.map +1 -0
- package/dist/chunk-JRKSK2HX.js +79 -0
- package/dist/chunk-JRKSK2HX.js.map +1 -0
- package/dist/chunk-KWWR5VMS.js +45 -0
- package/dist/chunk-KWWR5VMS.js.map +1 -0
- package/dist/chunk-LPOMRC4C.js +25 -0
- package/dist/chunk-LPOMRC4C.js.map +1 -0
- package/dist/chunk-M7JBER5U.js +41 -0
- package/dist/chunk-M7JBER5U.js.map +1 -0
- package/dist/chunk-NENBUYX5.js +79 -0
- package/dist/chunk-NENBUYX5.js.map +1 -0
- package/dist/chunk-NWSEP5RT.js +117 -0
- package/dist/chunk-NWSEP5RT.js.map +1 -0
- package/dist/chunk-OJWWHFH3.js +426 -0
- package/dist/chunk-OJWWHFH3.js.map +1 -0
- package/dist/chunk-PSKN344N.js +114 -0
- package/dist/chunk-PSKN344N.js.map +1 -0
- package/dist/chunk-PX3YSS5C.js +32 -0
- package/dist/chunk-PX3YSS5C.js.map +1 -0
- package/dist/chunk-QO55FN2Y.js +20 -0
- package/dist/chunk-QO55FN2Y.js.map +1 -0
- package/dist/chunk-R7ZWUN64.js +38 -0
- package/dist/chunk-R7ZWUN64.js.map +1 -0
- package/dist/chunk-RKVQEH4J.js +61 -0
- package/dist/chunk-RKVQEH4J.js.map +1 -0
- package/dist/chunk-SRSJO5QE.js +40 -0
- package/dist/chunk-SRSJO5QE.js.map +1 -0
- package/dist/chunk-SYDMYBPG.js +31 -0
- package/dist/chunk-SYDMYBPG.js.map +1 -0
- package/dist/chunk-TB6DY7H5.js +25 -0
- package/dist/chunk-TB6DY7H5.js.map +1 -0
- package/dist/chunk-UFZKLBCF.js +108 -0
- package/dist/chunk-UFZKLBCF.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-W5L2JSBY.js +40 -0
- package/dist/chunk-W5L2JSBY.js.map +1 -0
- package/dist/chunk-Y45PPBDV.js +105 -0
- package/dist/chunk-Y45PPBDV.js.map +1 -0
- package/dist/chunk-Y6LYKFXY.js +43 -0
- package/dist/chunk-Y6LYKFXY.js.map +1 -0
- package/dist/collapsible-panel.d.ts +66 -0
- package/dist/collapsible-panel.js +63 -0
- package/dist/collapsible-panel.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.d.ts +14 -0
- package/dist/disclosure-arrow.js +4 -0
- package/dist/disclosure-arrow.js.map +1 -0
- package/dist/divider-sides-267FA7sY.d.ts +4 -0
- package/dist/empty-state.d.ts +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/floating-toolbar.d.ts +28 -0
- package/dist/floating-toolbar.js +3 -0
- package/dist/floating-toolbar.js.map +1 -0
- package/dist/index.d.ts +20 -9
- package/dist/index.js +29 -18
- package/dist/list-action-row.d.ts +52 -0
- package/dist/list-action-row.js +5 -0
- package/dist/list-action-row.js.map +1 -0
- package/dist/list-header.d.ts +64 -0
- package/dist/list-header.js +7 -0
- package/dist/list-header.js.map +1 -0
- package/dist/list-inset-control.d.ts +16 -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 +25 -0
- package/dist/list-inset-text.js +3 -0
- package/dist/list-inset-text.js.map +1 -0
- package/dist/list-item.d.ts +33 -0
- package/dist/list-item.js +5 -0
- package/dist/list-item.js.map +1 -0
- package/dist/list.d.ts +19 -0
- package/dist/list.js +3 -0
- package/dist/list.js.map +1 -0
- package/dist/loading-spinner.js +1 -1
- package/dist/nav-stack.d.ts +38 -0
- package/dist/nav-stack.js +5 -0
- package/dist/nav-stack.js.map +1 -0
- package/dist/pane.d.ts +49 -0
- package/dist/pane.js +4 -0
- package/dist/pane.js.map +1 -0
- package/dist/panel-header.d.ts +42 -0
- package/dist/panel-header.js +7 -0
- package/dist/panel-header.js.map +1 -0
- package/dist/resizable-region.d.ts +3 -1
- package/dist/resizable-region.js +1 -1
- package/dist/segmented-control.d.ts +8 -6
- package/dist/segmented-control.js +2 -1
- package/dist/select-register.d.ts +5 -1
- package/dist/select-register.js +3 -0
- package/dist/select-register.js.map +1 -1
- package/dist/select.d.ts +15 -6
- package/dist/select.js +2 -1
- package/dist/skeleton.d.ts +24 -0
- package/dist/skeleton.js +3 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/split-view.d.ts +42 -0
- package/dist/split-view.js +81 -0
- package/dist/split-view.js.map +1 -0
- package/dist/state-banner.d.ts +8 -3
- package/dist/state-banner.js +2 -1
- package/dist/styles/app-tab.css +152 -0
- package/dist/styles/catalog.css +575 -0
- package/dist/styles/collapsible-panel.css +146 -0
- package/dist/styles/disclosure-arrow.css +23 -0
- package/dist/styles/empty-state.css +47 -0
- package/dist/styles/floating-toolbar.css +38 -0
- package/dist/styles/foundation.css +362 -0
- package/dist/styles/layout.css +55 -0
- package/dist/styles/list-action-row.css +160 -0
- package/dist/styles/list-header.css +160 -0
- package/dist/styles/list-inset-control.css +7 -0
- package/dist/styles/list-inset-text.css +14 -0
- package/dist/styles/list-item.css +123 -0
- package/dist/styles/list.css +43 -0
- package/dist/styles/loading-spinner.css +21 -0
- package/dist/styles/lucide-icon.css +6 -0
- package/dist/styles/nav-stack.css +111 -0
- package/dist/styles/pane.css +62 -0
- package/dist/styles/panel-header.css +64 -0
- package/dist/styles/resizable-region.css +111 -0
- package/{src → dist/styles}/segmented-control.css +58 -31
- package/dist/styles/select.css +140 -0
- package/dist/styles/skeleton.css +31 -0
- package/dist/styles/split-view.css +35 -0
- package/dist/styles/state-banner.css +198 -0
- package/dist/styles/styles.css +24 -0
- package/dist/styles/sunken-panel.css +22 -0
- package/dist/styles/tab-bar.css +45 -0
- package/dist/styles/tab-scaffold.css +84 -0
- package/dist/styles/token-search-field.css +289 -0
- package/dist/styles/toolbar-control-group.css +225 -0
- package/dist/styles/toolbar-text.css +92 -0
- package/dist/styles/toolbar.css +97 -0
- package/dist/styles/value-table.css +75 -0
- package/dist/styles/webawesome.css +399 -0
- package/dist/styles/workbench.css +94 -0
- package/dist/sunken-panel.d.ts +19 -0
- package/dist/sunken-panel.js +3 -0
- package/dist/sunken-panel.js.map +1 -0
- package/dist/tab-bar.d.ts +10 -2
- package/dist/tab-bar.js +1 -1
- package/dist/tab-scaffold.d.ts +30 -0
- package/dist/tab-scaffold.js +51 -0
- package/dist/tab-scaffold.js.map +1 -0
- package/dist/token-search-field.d.ts +59 -0
- package/dist/token-search-field.js +4 -0
- package/dist/token-search-field.js.map +1 -0
- package/dist/toolbar-control-group.d.ts +11 -5
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.d.ts +31 -4
- package/dist/toolbar-text.js +2 -1
- package/dist/toolbar.d.ts +5 -3
- package/dist/toolbar.js +1 -1
- package/dist/value-table.d.ts +13 -3
- package/dist/value-table.js +2 -1
- package/dist/webawesome.d.ts +100 -0
- package/dist/webawesome.js +3 -0
- package/dist/webawesome.js.map +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 +15 -0
- package/dist/wire-nav-stack.js +103 -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 +43 -0
- package/dist/wire-sidebar.js +128 -0
- package/dist/wire-sidebar.js.map +1 -0
- package/dist/wire-tab-bars.d.ts +18 -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 +111 -0
- package/dist/wire-token-search-fields.js +5 -0
- package/dist/wire-token-search-fields.js.map +1 -0
- package/dist/workbench.d.ts +33 -0
- package/dist/workbench.js +64 -0
- package/dist/workbench.js.map +1 -0
- package/docs/accessibility.md +124 -4
- package/docs/app-layouts.md +61 -0
- package/docs/catalog.md +364 -0
- package/docs/collapsible-panel.md +129 -0
- package/docs/component-contract.md +312 -5
- package/docs/component-selection.md +219 -0
- 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/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/panel-header/icon-actions-dark.svg +1 -0
- package/docs/design/templates/panel-header/icon-actions.svg +1 -0
- package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +1 -0
- package/docs/design/templates/panel-header/icon-summary-actions.svg +1 -0
- package/docs/design/templates/panel-header/no-icon-dark.svg +1 -0
- package/docs/design/templates/panel-header/no-icon.svg +1 -0
- package/docs/design/templates/panel-header/page-heading-dark.svg +1 -0
- package/docs/design/templates/panel-header/page-heading.svg +1 -0
- package/docs/design/templates/panel-header/title-only-dark.svg +1 -0
- package/docs/design/templates/panel-header/title-only.svg +1 -0
- package/docs/design/templates/panel-header-dark.svg +1 -0
- package/docs/design/templates/panel-header.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 +130 -0
- package/docs/design-philosophy.md +59 -1
- package/docs/device-class.md +54 -0
- package/docs/examples/application-ui-profile.json +60 -0
- package/docs/examples/command-palette-adapter.tsx +120 -0
- package/docs/examples/component-catalog-extension-v2.json +81 -0
- package/docs/examples/component-catalog-extension.json +45 -0
- package/docs/layout.md +150 -0
- package/docs/nav-stack.md +56 -0
- package/docs/recipes.md +167 -0
- package/docs/split-view.md +49 -0
- package/docs/sunken-panel.md +53 -0
- package/docs/tab-scaffold.md +50 -0
- package/docs/type-contracts.md +102 -0
- package/docs/ui-analyzer.md +86 -0
- package/docs/ui-doctor.md +84 -0
- package/docs/ui-evaluator.md +122 -0
- package/docs/ux-demo.md +23 -9
- package/docs/webawesome-theme.md +87 -7
- package/docs/workbench.md +73 -0
- package/doctor/cli.mjs +115 -0
- package/doctor/config.schema.json +68 -0
- package/doctor/eslint-diagnostics.d.mts +8 -0
- package/doctor/eslint-diagnostics.mjs +7 -0
- package/doctor/index.d.mts +116 -0
- package/doctor/index.mjs +1257 -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 +197 -14
- package/package.json +228 -46
- package/traversal-exclusions.mjs +27 -0
- package/ux-demo/recipes/app-shell.tsx +228 -0
- package/ux-demo/recipes/collapsible-sidebar.tsx +223 -0
- package/ux-demo/recipes/compact-toolbar.tsx +145 -0
- package/ux-demo/recipes/composer-form.tsx +151 -0
- package/ux-demo/recipes/list-detail-dialog.tsx +181 -0
- package/ux-demo/recipes/list-workspace-states.tsx +183 -0
- package/ux-demo/recipes/loaders.ts +36 -0
- package/ux-demo/recipes/loading-inspector.tsx +164 -0
- package/ux-demo/recipes/mount-recipe.ts +64 -0
- package/ux-demo/recipes/navigation-sidebar.tsx +137 -0
- package/ux-demo/recipes/navigation-stack.tsx +118 -0
- package/ux-demo/recipes/recipes.css +448 -0
- package/ux-demo/recipes/types.ts +19 -0
- package/ux-demo/recipes/workspace-header.tsx +67 -0
- package/dist/browser/dialog-header.js +0 -3
- package/dist/browser/menu-header.js +0 -3
- 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-3O7ZEUW2.js +0 -27
- package/dist/chunk-3O7ZEUW2.js.map +0 -1
- package/dist/chunk-4HHCYSGT.js +0 -79
- package/dist/chunk-4HHCYSGT.js.map +0 -1
- package/dist/chunk-55DATV3A.js +0 -10
- package/dist/chunk-55DATV3A.js.map +0 -1
- package/dist/chunk-723YNJBH.js +0 -17
- package/dist/chunk-723YNJBH.js.map +0 -1
- package/dist/chunk-DAFFDO33.js +0 -14
- package/dist/chunk-DAFFDO33.js.map +0 -1
- package/dist/chunk-GY5WH7TO.js +0 -10
- package/dist/chunk-GY5WH7TO.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-NHXX4JI5.js +0 -28
- package/dist/chunk-NHXX4JI5.js.map +0 -1
- package/dist/chunk-OPCJRCYO.js +0 -19
- package/dist/chunk-OPCJRCYO.js.map +0 -1
- package/dist/chunk-T5XNMVOI.js +0 -24
- package/dist/chunk-T5XNMVOI.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-VKH2JLDZ.js +0 -10
- package/dist/chunk-VKH2JLDZ.js.map +0 -1
- package/dist/chunk-WVPYVDXY.js +0 -15
- package/dist/chunk-WVPYVDXY.js.map +0 -1
- package/dist/chunk-WY4CAEPG.js +0 -14
- package/dist/chunk-WY4CAEPG.js.map +0 -1
- package/dist/dialog-header.d.ts +0 -14
- package/dist/dialog-header.js +0 -3
- package/dist/dialog-header.js.map +0 -1
- package/dist/menu-header.d.ts +0 -15
- package/dist/menu-header.js +0 -3
- package/dist/menu-header.js.map +0 -1
- package/dist/menu-item.d.ts +0 -22
- package/dist/menu-item.js +0 -3
- 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/src/app-tab.css +0 -20
- package/src/dialog-header.css +0 -9
- package/src/empty-state.css +0 -6
- package/src/foundation.css +0 -106
- package/src/loading-spinner.css +0 -4
- package/src/lucide-icon.css +0 -1
- package/src/menu-header.css +0 -13
- package/src/menu-item.css +0 -12
- package/src/page-header.css +0 -3
- package/src/resizable-region.css +0 -19
- package/src/select.css +0 -18
- package/src/state-banner.css +0 -31
- package/src/styles.css +0 -18
- package/src/tab-bar.css +0 -4
- package/src/toolbar-control-group.css +0 -25
- package/src/toolbar-text.css +0 -4
- package/src/toolbar.css +0 -9
- package/src/value-table.css +0 -5
- package/src/webawesome.css +0 -178
package/README.md
CHANGED
|
@@ -2,46 +2,328 @@
|
|
|
2
2
|
|
|
3
3
|
Accessible, composable UI primitives for [kerf](https://github.com/brianwestphal/kerf). The package ships production components, component-reachable CSS, accessibility and keyboard contracts, an AI-readable guide, and a production-backed UX catalog.
|
|
4
4
|
|
|
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
|
+
|
|
7
|
+
When authoring a component gallery, follow the single
|
|
8
|
+
[Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract)
|
|
9
|
+
for focused-versus-composition modes, helper nesting, specimen selection,
|
|
10
|
+
geometry inspection, and metadata ownership. AI tools can discover that
|
|
11
|
+
contract and its public imports through the shipped
|
|
12
|
+
[`catalog-authoring.json`](./ai/catalog-authoring.json) artifact.
|
|
13
|
+
|
|
14
|
+
For connective application patterns, use the seven [production composition
|
|
15
|
+
recipes](./docs/recipes.md). Each has a stable catalog route, runnable state,
|
|
16
|
+
public-subpath source, semantic layout ownership, and explicit application
|
|
17
|
+
customization boundaries. The composer recipe demonstrates one coherent form
|
|
18
|
+
surface with `PanelHeader` hierarchy and field/action controls aligned to the
|
|
19
|
+
shared 8px gutter; only persistent feedback adds a nested semantic
|
|
20
|
+
`StateBanner` surface.
|
|
21
|
+
|
|
22
|
+
When no primitive matches, keep policy application-owned while reusing the
|
|
23
|
+
layout vocabulary. The typed
|
|
24
|
+
[`command-palette-adapter.tsx`](./docs/examples/command-palette-adapter.tsx)
|
|
25
|
+
shows that application boundary explicitly; it is reference source, not a package
|
|
26
|
+
runtime export.
|
|
27
|
+
|
|
5
28
|
```bash
|
|
6
29
|
npm install kerfjs @kerfjs/ui
|
|
7
30
|
```
|
|
8
31
|
|
|
9
32
|
```tsx
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
33
|
+
import { ListItem } from "@kerfjs/ui/list-item";
|
|
34
|
+
import { ListHeader } from "@kerfjs/ui/list-header";
|
|
35
|
+
import { ListActionRow } from "@kerfjs/ui/list-action-row";
|
|
36
|
+
import { Toolbar } from "@kerfjs/ui/toolbar";
|
|
37
|
+
import { ToolbarControlGroup } from "@kerfjs/ui/toolbar-control-group";
|
|
38
|
+
import { ToolbarText } from "@kerfjs/ui/toolbar-text";
|
|
39
|
+
|
|
40
|
+
mount(root, () => (
|
|
41
|
+
<>
|
|
42
|
+
<Toolbar
|
|
43
|
+
label="Document"
|
|
44
|
+
leading={
|
|
45
|
+
<ToolbarControlGroup appearance="borderless" single>
|
|
46
|
+
<ToolbarText text="Notes" />
|
|
47
|
+
</ToolbarControlGroup>
|
|
48
|
+
}
|
|
49
|
+
/>
|
|
50
|
+
<section>
|
|
51
|
+
<ListHeader
|
|
52
|
+
label="Workspace"
|
|
53
|
+
action="show-workspace-actions"
|
|
54
|
+
actionLabel="Workspace actions"
|
|
55
|
+
rootAttributes={{ "data-section-id": "workspace" }}
|
|
56
|
+
triggerAttributes={{
|
|
57
|
+
popoverTarget: "workspace-actions",
|
|
58
|
+
popoverTargetAction: "toggle",
|
|
59
|
+
"aria-controls": "workspace-actions",
|
|
60
|
+
"aria-haspopup": "dialog",
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
<ListItem
|
|
64
|
+
action="open-notes"
|
|
65
|
+
label="Notes"
|
|
66
|
+
selected
|
|
67
|
+
rootAttributes={{
|
|
68
|
+
"data-command-color": "blue",
|
|
69
|
+
"data-drop-status": "ready",
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
<ListActionRow
|
|
73
|
+
action="open-file"
|
|
74
|
+
itemId="src/main.ts"
|
|
75
|
+
label="src/main.ts"
|
|
76
|
+
trailingAction="open-file-actions"
|
|
77
|
+
trailingActionLabel="Actions for src/main.ts"
|
|
78
|
+
trailingActionIcon={moreIcon}
|
|
79
|
+
/>
|
|
80
|
+
<div id="workspace-actions" popover="auto">
|
|
81
|
+
Application-owned actions
|
|
82
|
+
</div>
|
|
83
|
+
</section>
|
|
84
|
+
</>
|
|
85
|
+
));
|
|
18
86
|
```
|
|
19
87
|
|
|
20
88
|
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.
|
|
21
89
|
|
|
90
|
+
`ListItem.rootAttributes`, `ListHeader.rootAttributes`,
|
|
91
|
+
`ListActionRow.rootAttributes`, `AppTab.rootAttributes`,
|
|
92
|
+
`CatalogExample.rootAttributes`, and `CatalogExampleStack.rootAttributes` carry typed
|
|
93
|
+
application `data-*` metadata without
|
|
94
|
+
teaching the package domain fields. `ListHeader.triggerAttributes` and
|
|
95
|
+
`ListActionRow.trailingActionAttributes` additionally support native popover
|
|
96
|
+
target and relationship attributes. Roles and component-owned action, selection,
|
|
97
|
+
disclosure, naming, disabled, icon, and catalog-structure semantics remain protected props; an
|
|
98
|
+
isolated `role="menuitem"` is not an extension shortcut.
|
|
99
|
+
The slots are also filtered at runtime, so structurally widened objects and
|
|
100
|
+
JavaScript callers cannot bypass those protections with case-variant names.
|
|
101
|
+
`ListItem.trailing` is dormant metadata. Use `ListActionRow` when a row needs
|
|
102
|
+
sibling primary and trailing native-button actions with independent names,
|
|
103
|
+
disabled states, focus, and click ownership. Its `label`, `icon`, and
|
|
104
|
+
`trailingActionIcon` slots are dormant content and must not contain controls.
|
|
105
|
+
In either component's multiline mode, the leading icon remains aligned with
|
|
106
|
+
the first text line as the label wraps below it.
|
|
107
|
+
For section quantities, pass a non-negative safe-integer `count` together with
|
|
108
|
+
the localized full spoken phrase in `countLabel`, for example
|
|
109
|
+
`count={3} countLabel="3 notes"`. This renders the standard neutral count pill
|
|
110
|
+
and includes the count in the heading or disclosure button's accessible name.
|
|
111
|
+
Do not concatenate a count into `label` or pass a numeric `badge`; the mutually
|
|
112
|
+
exclusive legacy `badge` slot remains available for non-count `SafeHtml` such
|
|
113
|
+
as a `New` marker.
|
|
114
|
+
|
|
22
115
|
## Component subpaths
|
|
23
116
|
|
|
24
|
-
| Component
|
|
25
|
-
|
|
|
26
|
-
| `LucideIcon`
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `
|
|
35
|
-
| `
|
|
36
|
-
| `
|
|
37
|
-
| `
|
|
38
|
-
| `
|
|
39
|
-
|
|
|
40
|
-
| `
|
|
41
|
-
| `
|
|
42
|
-
| `
|
|
43
|
-
| `
|
|
44
|
-
| `
|
|
117
|
+
| Component | Browser import (includes reachable CSS) | Manual CSS export |
|
|
118
|
+
| ------------------------------------------------------------------- | --------------------------------------- | -------------------------------------- |
|
|
119
|
+
| `LucideIcon` | `@kerfjs/ui/lucide-icon` | `@kerfjs/ui/lucide-icon.css` |
|
|
120
|
+
| `DisclosureArrow` | `@kerfjs/ui/disclosure-arrow` | `@kerfjs/ui/disclosure-arrow.css` |
|
|
121
|
+
| `Toolbar` | `@kerfjs/ui/toolbar` | `@kerfjs/ui/toolbar.css` |
|
|
122
|
+
| `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
|
|
123
|
+
| `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
|
|
124
|
+
| `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
|
|
125
|
+
| `List` | `@kerfjs/ui/list` | `@kerfjs/ui/list.css` |
|
|
126
|
+
| `ListActionRow` | `@kerfjs/ui/list-action-row` | `@kerfjs/ui/list-action-row.css` |
|
|
127
|
+
| `ListItem` | `@kerfjs/ui/list-item` | `@kerfjs/ui/list-item.css` |
|
|
128
|
+
| `ListHeader` | `@kerfjs/ui/list-header` | `@kerfjs/ui/list-header.css` |
|
|
129
|
+
| `ListInsetControl` | `@kerfjs/ui/list-inset-control` | `@kerfjs/ui/list-inset-control.css` |
|
|
130
|
+
| `ListInsetText` | `@kerfjs/ui/list-inset-text` | `@kerfjs/ui/list-inset-text.css` |
|
|
131
|
+
| `Pane` | `@kerfjs/ui/pane` | `@kerfjs/ui/pane.css` |
|
|
132
|
+
| Content and navigation composition | — | `@kerfjs/ui/layout.css` |
|
|
133
|
+
| `ResizableRegion` | `@kerfjs/ui/resizable-region` | `@kerfjs/ui/resizable-region.css` |
|
|
134
|
+
| `wireResizableRegions` | `@kerfjs/ui/wire-resizable-regions` | — |
|
|
135
|
+
| `AppTab` | `@kerfjs/ui/app-tab` | `@kerfjs/ui/app-tab.css` |
|
|
136
|
+
| `TabBar` | `@kerfjs/ui/tab-bar` | `@kerfjs/ui/tab-bar.css` |
|
|
137
|
+
| `wireTabBars`, `reorderTabs` | `@kerfjs/ui/wire-tab-bars` | — |
|
|
138
|
+
| `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
|
|
139
|
+
| `Skeleton` | `@kerfjs/ui/skeleton` | `@kerfjs/ui/skeleton.css` |
|
|
140
|
+
| `SunkenPanel` | `@kerfjs/ui/sunken-panel` | `@kerfjs/ui/sunken-panel.css` |
|
|
141
|
+
| `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
|
|
142
|
+
| `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
|
|
143
|
+
| `TokenSearchField`, `readTokenSearchField`, `placeTokenSearchCaret` | `@kerfjs/ui/token-search-field` | `@kerfjs/ui/token-search-field.css` |
|
|
144
|
+
| `wireTokenSearchFields` | `@kerfjs/ui/wire-token-search-fields` | — |
|
|
145
|
+
| `StateBanner` | `@kerfjs/ui/state-banner` | `@kerfjs/ui/state-banner.css` |
|
|
146
|
+
| `EmptyState` | `@kerfjs/ui/empty-state` | `@kerfjs/ui/empty-state.css` |
|
|
147
|
+
| `PanelHeader` | `@kerfjs/ui/panel-header` | `@kerfjs/ui/panel-header.css` |
|
|
148
|
+
| `ValueTable`, `ValueTableRow` | `@kerfjs/ui/value-table` | `@kerfjs/ui/value-table.css` |
|
|
149
|
+
|
|
150
|
+
Opt-in application layouts keep JavaScript and CSS explicit. For the
|
|
151
|
+
desktop-class multi-panel shell, import `Workbench` from
|
|
152
|
+
`@kerfjs/ui/workbench` and load `@kerfjs/ui/workbench.css`; its supported
|
|
153
|
+
classes and size tokens are cataloged under the `workbench` entry. See
|
|
154
|
+
[`docs/workbench.md`](./docs/workbench.md) for panel ownership and responsive
|
|
155
|
+
replacement guidance.
|
|
156
|
+
|
|
157
|
+
`PanelHeader` is a plain `Toolbar` used as a panel, dialog, or page heading: an
|
|
158
|
+
optional icon control group (given a brand fill with a matching border), the
|
|
159
|
+
title as extra-large `ToolbarText`, the app's trailing action controls, and an
|
|
160
|
+
optional subtitle on a separate row below the title. It overrides no toolbar
|
|
161
|
+
styles — the app passes its own trailing controls (typically a
|
|
162
|
+
`ToolbarControlGroup`).
|
|
163
|
+
|
|
164
|
+
`DisclosureArrow` defaults to an 18px root-scaled decorative visual. Override
|
|
165
|
+
`--kui-disclosure-arrow-size` at the narrowest useful scope when a consumer
|
|
166
|
+
needs another size; the owning control still supplies interaction, naming, and
|
|
167
|
+
expanded state. Kerf `Select` retains its independent Web Awesome expand-glyph
|
|
168
|
+
scale of `.5` through `--kui-disclosure-icon-scale`. Author replacement
|
|
169
|
+
`DisclosureArrow` icon content facing right before its configured direction
|
|
170
|
+
transform is applied. Direction changes take the shortest rotation path; a
|
|
171
|
+
180-degree closed-to-open tie uses counterclockwise rotation.
|
|
172
|
+
|
|
173
|
+
`ListHeader` supplies that production `DisclosureArrow` automatically when
|
|
174
|
+
`toggle` is true and `actionIcon` is omitted. Keep `expanded` synchronized with
|
|
175
|
+
real controlled content and preserve the button's stable label; ordinary
|
|
176
|
+
navigation must not display a disclosure arrow. A custom `actionIcon` remains
|
|
177
|
+
an escape hatch and replaces the default arrow entirely. The header fills its
|
|
178
|
+
available inline width, keeping a separate action at the logical end in a 44px
|
|
179
|
+
target. Its visible action glyph defaults to 18px through
|
|
180
|
+
`--kui-list-header-action-icon-size`.
|
|
181
|
+
|
|
182
|
+
## Machine-readable catalog
|
|
183
|
+
|
|
184
|
+
AI tools can retrieve the shipped [`ai/component-catalog.json`](./ai/component-catalog.json)
|
|
185
|
+
for the exhaustive component and composition inventory. It is the canonical
|
|
186
|
+
source for ids, public exports, purpose and selection guidance, relationships,
|
|
187
|
+
delivery and side effects, companion wiring, application-owned policy,
|
|
188
|
+
variants, accessibility obligations, public CSS hooks, routes, and current
|
|
189
|
+
documentation/recipe links. The adjacent
|
|
190
|
+
[`component-catalog.schema.json`](./ai/component-catalog.schema.json) describes
|
|
191
|
+
the versioned format. Every visual entry also declares who owns its margin,
|
|
192
|
+
border, and padding, so a generator can fit it into Kerf's alignment model
|
|
193
|
+
without guessing from a screenshot or private CSS.
|
|
194
|
+
|
|
195
|
+
Catalog demo authoring is deliberately separate from the entry inventory. Load
|
|
196
|
+
[`catalog-authoring.json`](./ai/catalog-authoring.json) to discover the
|
|
197
|
+
authoritative [Catalog demo authoring contract](./docs/catalog.md#catalog-demo-authoring-contract),
|
|
198
|
+
the exact API-signature context, public imports/helpers, and sanctioned metadata
|
|
199
|
+
slot. Keeping this as a companion artifact prevents per-entry selection facts
|
|
200
|
+
from duplicating presentation rules.
|
|
201
|
+
|
|
202
|
+
Tools that evaluate composition may additionally load
|
|
203
|
+
[`component-catalog-v2.json`](./ai/component-catalog-v2.json). It is a
|
|
204
|
+
deterministic, package-qualified projection of every v1 entry with formal
|
|
205
|
+
parent/context, zone/cardinality, child, state ownership, wiring, responsive,
|
|
206
|
+
layout, accessibility, public-boundary, and stable-diagnostic fields. V1
|
|
207
|
+
remains the selection and delivery compatibility surface. V2 defaults are
|
|
208
|
+
deliberately permissive; only documented objective rules receive an
|
|
209
|
+
authoritative override and enforceable diagnostic. The adjacent schema and
|
|
210
|
+
[`component-catalog-v2.d.ts`](./ai/component-catalog-v2.d.ts) types describe
|
|
211
|
+
the same contract.
|
|
212
|
+
|
|
213
|
+
Applications and downstream design systems should publish the same facts for
|
|
214
|
+
their own components. Start from the reusable
|
|
215
|
+
[`component-catalog-extension.schema.json`](./ai/component-catalog-extension.schema.json)
|
|
216
|
+
and the checked
|
|
217
|
+
[`component-catalog-extension.json`](./docs/examples/component-catalog-extension.json)
|
|
218
|
+
example. Give each app-owned component or composition a stable id, selection
|
|
219
|
+
guidance, public hooks, and explicit geometry ownership; then concatenate its
|
|
220
|
+
`entries` with Kerf's shipped `entries` in the AI context. Keep package/source
|
|
221
|
+
identity alongside each input when ids could collide. This makes a combined
|
|
222
|
+
tool reason about both sides of a composition using one vocabulary without
|
|
223
|
+
pretending app-local components are `@kerfjs/ui` exports.
|
|
224
|
+
|
|
225
|
+
Composition-aware consumers use
|
|
226
|
+
[`component-catalog-extension-v2.schema.json`](./ai/component-catalog-extension-v2.schema.json),
|
|
227
|
+
its shipped TypeScript types, and the checked
|
|
228
|
+
[`component-catalog-extension-v2.json`](./docs/examples/component-catalog-extension-v2.json)
|
|
229
|
+
example. Preserve each catalog's package and qualify every identity and
|
|
230
|
+
cross-catalog reference as `package:id`; never merge entries by bare id.
|
|
231
|
+
|
|
232
|
+
[`compile-time-contracts-v1.json`](./ai/compile-time-contracts-v1.json) is the
|
|
233
|
+
matching declaration contract: stable `KUI-T###` ids identify the invalid prop,
|
|
234
|
+
state, identity, accessibility, and protected-attribute combinations TypeScript
|
|
235
|
+
rejects. The package gate compiles one positive/negative consumer fixture against
|
|
236
|
+
both source and declarations extracted from the real packed tarball. The
|
|
237
|
+
[compile-time contract guide](./docs/type-contracts.md) documents migrations and
|
|
238
|
+
the dynamic DOM/children relationships that remain runtime or catalog checks.
|
|
239
|
+
Packages scaffolded by `create-kerf-component` maintain this v2 input from
|
|
240
|
+
`kerf.components.json`: `npm run catalog:generate` emits the catalog and
|
|
241
|
+
`npm run catalog:check` verifies source files, named public exports, explicit
|
|
242
|
+
author decisions, and byte-for-byte drift. Tools index the generated consumer
|
|
243
|
+
entries and this catalog by full key, reject duplicate full keys, search the
|
|
244
|
+
consumer package first, and retain package identity across every reference.
|
|
245
|
+
They must not infer missing semantics or geometry from rendered appearance.
|
|
246
|
+
|
|
247
|
+
### Application UI profile
|
|
248
|
+
|
|
249
|
+
Applications can check in `.kerf-ui-profile.json` so tools do not have to infer
|
|
250
|
+
project-wide UI policy. Start from the shipped
|
|
251
|
+
[`application-ui-profile.defaults.json`](./ai/application-ui-profile.defaults.json)
|
|
252
|
+
and the checked
|
|
253
|
+
[`application-ui-profile.json`](./docs/examples/application-ui-profile.json)
|
|
254
|
+
workspace example. The versioned
|
|
255
|
+
[`application-ui-profile.schema.json`](./ai/application-ui-profile.schema.json)
|
|
256
|
+
and [`application-ui-profile.d.ts`](./ai/application-ui-profile.d.ts) cover
|
|
257
|
+
catalog locations, concept preferences, allowed theme/density choices, semantic
|
|
258
|
+
token overrides, layout/responsive conventions, and narrow rule exceptions.
|
|
259
|
+
Profiles contain policy only—never product records, user data, or broad styling
|
|
260
|
+
waivers.
|
|
261
|
+
|
|
262
|
+
Catalog declarations always provide a v2 `composition` location. Consumer
|
|
263
|
+
packages generated with composition-only metadata omit `selection`;
|
|
264
|
+
`@kerfjs/ui` continues to require its v1 selection catalog.
|
|
265
|
+
|
|
266
|
+
Node-based AI and static-analysis tools may import the shipped discovery API
|
|
267
|
+
from `@kerfjs/ui/ai/application-ui-profile.mjs`. It discovers package defaults,
|
|
268
|
+
then the workspace profile, then directory profiles from parent to child;
|
|
269
|
+
`mergeApplicationUiProfiles()` applies later scalar/map values, replaces a
|
|
270
|
+
catalog by package and an exception by id, and preserves source provenance.
|
|
271
|
+
`loadApplicationUiProfile()` resolves catalogs and returns diagnostics with the
|
|
272
|
+
originating file plus JSON path. Unknown/stale components, tokens, rules, and
|
|
273
|
+
catalog locations are errors. Every layer is checked against its then-effective
|
|
274
|
+
catalogs, including parent references and catalog paths later overridden by a
|
|
275
|
+
child profile. Synchronous integrations can require the shipped
|
|
276
|
+
`application-ui-profile-sync.cjs` projection and call
|
|
277
|
+
`loadApplicationUiProfileSync()` with already-discovered layers. Consumers that define additional stable
|
|
278
|
+
diagnostics pass their ids through the additive `knownRules` option; those ids
|
|
279
|
+
are merged with catalog diagnostics before exception validation.
|
|
280
|
+
|
|
281
|
+
### Static CSS and layout ownership analysis
|
|
282
|
+
|
|
283
|
+
Run `kerf-ui-analyze --root . src` (or import
|
|
284
|
+
`@kerfjs/ui/analyzer`) to evaluate cross-file integration facts against the
|
|
285
|
+
composition catalogs and application profile. It catches provable private
|
|
286
|
+
selector reach-through, unknown tokens, competing geometry owners, and nested
|
|
287
|
+
scroll owners; it reports forced dimensions, repeated insets, off-scale literal
|
|
288
|
+
spacing, and dynamic classes separately as review findings. Text, versioned JSON,
|
|
289
|
+
and SARIF outputs carry stable `KUI-L###` ids, repository-relative locations,
|
|
290
|
+
evidence, and ownership chains. See the [analyzer guide](./docs/ui-analyzer.md).
|
|
291
|
+
|
|
292
|
+
### Browser-backed integration evaluation
|
|
293
|
+
|
|
294
|
+
Run `kerf-ui-evaluate --url <running-app>` (or import
|
|
295
|
+
`@kerfjs/ui/evaluator`) after the static analyzer. Its Playwright-backed
|
|
296
|
+
wide/intermediate/narrow/200%-zoom, light/dark, and reduced-motion matrix checks
|
|
297
|
+
rendered overflow, clipping, reachability, focus/keyboard behavior, accessible
|
|
298
|
+
names, contrast, hit targets, scrolling, alignment, and cataloged runtime
|
|
299
|
+
geometry. The versioned report carries stable `KUI-B###` diagnostics, focused
|
|
300
|
+
DOM/computed-style evidence, hashed screenshot artifacts, explicit timeout and
|
|
301
|
+
retention policy, and a separate unscored human-visual rubric. See the
|
|
302
|
+
[browser evaluator guide](./docs/ui-evaluator.md).
|
|
303
|
+
|
|
304
|
+
### Unified repair-loop doctor
|
|
305
|
+
|
|
306
|
+
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. 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).
|
|
307
|
+
|
|
308
|
+
For code generation, pair catalog selection guidance with the checked-in
|
|
309
|
+
[`public-api-signatures-v1.md`](./ai/public-api-signatures-v1.md) declaration
|
|
310
|
+
snapshot. It is generated from the emitted `@kerfjs/ui` declarations and the
|
|
311
|
+
installed `kerfjs/actions` declaration, so callback names, props, return values,
|
|
312
|
+
and accepted import paths do not have to be inferred from examples. Direct
|
|
313
|
+
Web Awesome JSX has its own generated
|
|
314
|
+
[`webawesome-jsx-signatures-v1.md`](./ai/webawesome-jsx-signatures-v1.md)
|
|
315
|
+
context so adding the declaration boundary does not mutate a frozen measured
|
|
316
|
+
regression suite.
|
|
317
|
+
|
|
318
|
+
`npm run catalog:sync` deterministically projects the fields used by the UX
|
|
319
|
+
catalog into `ux-demo/catalog.generated.ts`, including the existing guidance
|
|
320
|
+
path and the first-party source path for each main, recipe, or Web Awesome
|
|
321
|
+
specimen. First-party component entries also derive their implementation path
|
|
322
|
+
from the canonical browser import. Do not edit that generated file.
|
|
323
|
+
`npm run check:catalog` rejects stale generated output, exports and package
|
|
324
|
+
paths, Web Awesome manifest/declaration drift, invalid relationships, broken
|
|
325
|
+
links, or a missing AI-guidance entry. Prose remains authored where design
|
|
326
|
+
nuance matters.
|
|
45
327
|
|
|
46
328
|
Import components from their explicit JavaScript subpaths. CSS-aware browser
|
|
47
329
|
bundlers such as Vite, webpack, and esbuild follow each subpath's `browser`
|
|
@@ -57,9 +339,48 @@ that convenience import, also import `@kerfjs/ui/styles.css`, which deliberately
|
|
|
57
339
|
contains the complete layer. Non-browser/SSR tools resolve the pure `import`
|
|
58
340
|
condition automatically; `@kerfjs/ui/unstyled` is the explicit CSS-free root
|
|
59
341
|
entry for a browser build with a custom styling pipeline. The exported
|
|
60
|
-
|
|
61
|
-
delivery.
|
|
62
|
-
|
|
342
|
+
`@kerfjs/ui/foundation.css` and component CSS paths remain available for fully
|
|
343
|
+
manual delivery. Its complete supported `--kui-*` token surface is cataloged
|
|
344
|
+
under the `foundation` entry. Load application overrides after package styles,
|
|
345
|
+
or scope variables directly on a component instance.
|
|
346
|
+
|
|
347
|
+
## Pane and content geometry
|
|
348
|
+
|
|
349
|
+
Import `@kerfjs/ui/layout.css` and use the same structural vocabulary for a
|
|
350
|
+
sidebar, main area, inspector, or dialog. `.kui-pane` is unpadded and contains
|
|
351
|
+
an optional toolbar, one scrolling `.kui-pane__content`, and an optional footer.
|
|
352
|
+
Add `.kui-content` to make its major children a vertical stack with 24px gaps.
|
|
353
|
+
|
|
354
|
+
```tsx
|
|
355
|
+
<aside class="kui-pane">
|
|
356
|
+
<div class="kui-pane__toolbar"><Toolbar label="Workspace" ... /></div>
|
|
357
|
+
<nav class="kui-pane__content kui-content">
|
|
358
|
+
<section>
|
|
359
|
+
<ListHeader label="Workspace" count={3} countLabel="3 workspaces" />
|
|
360
|
+
<ListItem action="open" label="Inbox" icon={inboxIcon} />
|
|
361
|
+
<ListItem action="open" label="Drafts" />
|
|
362
|
+
</section>
|
|
363
|
+
<div class="kui-content-item">Workspace details</div>
|
|
364
|
+
</nav>
|
|
365
|
+
</aside>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
Ordinary children use `.kui-content-item`: 8px inline margin, a real 1px border
|
|
369
|
+
(transparent by default), 8px padding, and 12px rounded corners. The pill
|
|
370
|
+
modifier uses a 22px radius. A component can expose a transparent border or
|
|
371
|
+
background without changing layout. `ListHeader` follows the same rule while
|
|
372
|
+
keeping its dormant title and count-or-badge cluster separate from its optional
|
|
373
|
+
44px action.
|
|
374
|
+
|
|
375
|
+
## Spacing and application layout
|
|
376
|
+
|
|
377
|
+
Use 24px only for major vertical separation; use 8px inside content items and
|
|
378
|
+
between toolbar groups. Toolbar groups are 44px outside (`2px + 42px`) and keep
|
|
379
|
+
that geometry when their border/background are transparent. Wrap text and other
|
|
380
|
+
dormant toolbar content in a `ToolbarControlGroup` too. Do not pad the pane
|
|
381
|
+
itself, add competing wrapper insets, or give it more than one scroll owner.
|
|
382
|
+
Reading width and responsive pane placement remain application decisions. See
|
|
383
|
+
the complete [layout contract](./docs/layout.md).
|
|
63
384
|
|
|
64
385
|
## Web Awesome theme
|
|
65
386
|
|
|
@@ -67,11 +388,17 @@ Apps using Web Awesome's free components can opt into the same visual universe
|
|
|
67
388
|
with one CSS import:
|
|
68
389
|
|
|
69
390
|
```ts
|
|
70
|
-
import
|
|
71
|
-
import
|
|
72
|
-
import
|
|
391
|
+
import type {} from "@kerfjs/ui/webawesome";
|
|
392
|
+
import "@kerfjs/ui/webawesome.css";
|
|
393
|
+
import "@awesome.me/webawesome/dist/components/button/button.js";
|
|
394
|
+
import "@awesome.me/webawesome/dist/components/input/input.js";
|
|
73
395
|
```
|
|
74
396
|
|
|
397
|
+
The type-only `@kerfjs/ui/webawesome` import adds Kerf JSX intrinsic-element
|
|
398
|
+
declarations for the same 70 elements tracked by the catalog. It emits no
|
|
399
|
+
runtime code and registers nothing; keep importing only the individual Web
|
|
400
|
+
Awesome modules the application renders.
|
|
401
|
+
|
|
75
402
|
`webawesome.css` includes Web Awesome's native/base theme and then applies the
|
|
76
403
|
Hot Sheet 2 palette, surfaces, status colors, focus treatment, form geometry,
|
|
77
404
|
radii, tooltips, and shadows through Web Awesome's public `--wa-*` contract.
|
|
@@ -90,7 +417,7 @@ classes for explicit appearance boundaries:
|
|
|
90
417
|
```css
|
|
91
418
|
:root {
|
|
92
419
|
--wa-color-brand-fill-loud: #7540a8;
|
|
93
|
-
--wa-form-control-border-radius: .5rem;
|
|
420
|
+
--wa-form-control-border-radius: 0.5rem;
|
|
94
421
|
}
|
|
95
422
|
```
|
|
96
423
|
|
|
@@ -100,6 +427,10 @@ foreground roles through `--kui-color-*`; stateful components also expose
|
|
|
100
427
|
component variables such as `--kui-state-banner-background`. Override the
|
|
101
428
|
foundation for an application theme, a tone variable for one semantic state, or
|
|
102
429
|
a component variable on one instance without replacing component selectors.
|
|
430
|
+
Prefer an equivalent prop or token. When composition-specific layout still
|
|
431
|
+
needs a selector, the component catalog's `publicClasses` arrays define the
|
|
432
|
+
exact stable anatomy: public-class-to-public-class selectors are supported;
|
|
433
|
+
descendant tag, id, attribute-only, and unlisted-class selectors are not.
|
|
103
434
|
|
|
104
435
|
`StateBanner` has opinionated `neutral`, `info`, `success`, `warning`, and
|
|
105
436
|
`danger` palettes. Override an individual banner with
|
|
@@ -126,8 +457,8 @@ standalone `filled`/`outlined` appearance with `shape="rounded"` or
|
|
|
126
457
|
appearance="toolbar"
|
|
127
458
|
shape="pill"
|
|
128
459
|
choices={[
|
|
129
|
-
{ value:
|
|
130
|
-
{ value:
|
|
460
|
+
{ value: "list", label: "List" },
|
|
461
|
+
{ value: "columns", label: "Columns" },
|
|
131
462
|
]}
|
|
132
463
|
/>
|
|
133
464
|
```
|
|
@@ -137,40 +468,92 @@ value through `data-segment-value`. Override an instance through
|
|
|
137
468
|
`--kui-segmented-{background|border|foreground|hover-background}` and
|
|
138
469
|
`--kui-segmented-selected-{background|foreground|border|shadow}`.
|
|
139
470
|
|
|
471
|
+
`TokenSearchField` is a token-controlled contenteditable searchbox that keeps
|
|
472
|
+
free text and ordered filter chips in one field. Its editable text stays
|
|
473
|
+
DOM-owned between token changes so typing does not replace the caret. Tokens
|
|
474
|
+
expose stable edit/remove actions and remain atomic during editing; the app owns
|
|
475
|
+
parsing, suggestions, query execution, and state. Use `readTokenSearchField()`
|
|
476
|
+
after browser input to recover text plus token offsets, and
|
|
477
|
+
`placeTokenSearchCaret()` when restoring focus after a controlled update.
|
|
478
|
+
Call `wireTokenSearchFields()` once at a stable root to make Enter submit through
|
|
479
|
+
`onSubmit` without inserting a contenteditable line break and to preserve focus
|
|
480
|
+
plus the text-relative caret when keyboard deletion of a chip causes controlled
|
|
481
|
+
rendering to replace the editor. A select-all deletion is normalized to a truly
|
|
482
|
+
empty editor even when the browser leaves an atomic chip or line break behind.
|
|
483
|
+
Text still wraps visually when it reaches the field edge.
|
|
484
|
+
Clear actions should empty the editor's `textContent` before clearing app state.
|
|
485
|
+
The leading icon, first text line, clear action, and trailing slot share one
|
|
486
|
+
fixed alignment row; when text wraps, those controls stay pinned to that first
|
|
487
|
+
row instead of recentering against the taller editor.
|
|
488
|
+
Set `collapsible` for the first-class compact presentation: an empty closed
|
|
489
|
+
field renders as one iconic search action, `expanded` reveals the complete
|
|
490
|
+
field, and text or tokens keep it expanded. Width changes animate by default
|
|
491
|
+
and respect reduced-motion preferences. The field works standalone or inside a
|
|
492
|
+
`ToolbarControlGroup`; the application owns the transient focused/open signal,
|
|
493
|
+
focus transfer, and focusout policy. The catalog's Toolbar route demonstrates
|
|
494
|
+
that composition at wide and narrow sizes.
|
|
495
|
+
Override its surface through `--kui-token-search-{background|border}` and its
|
|
496
|
+
chips through `--kui-token-search-token-{background|foreground}`. Override
|
|
497
|
+
`--kui-token-search-line-size` only when the complete first-line geometry must
|
|
498
|
+
change together.
|
|
499
|
+
|
|
140
500
|
`TabBar` is controlled: pass ordered `AppTab` children, then wire its keyboard
|
|
141
501
|
and same-bar drag behavior with `wireTabBars(root, { onReorder })`. During a
|
|
142
502
|
drag, the scroll strip automatically moves toward either edge with speed based
|
|
143
503
|
on pointer proximity, exposing earlier or later drop targets. Apply the reported
|
|
144
504
|
change with `reorderTabs()` or application-specific state logic. The application
|
|
145
505
|
still owns selection, closing, routing, and persistence.
|
|
506
|
+
Use `AppTab.rootAttributes` for domain `data-*` metadata and `closeIcon` for a
|
|
507
|
+
decorative replacement glyph. The runtime rejects roles and case variants of
|
|
508
|
+
the component- or wiring-owned action, tab identity, selection, drag, drop, and
|
|
509
|
+
component markers. Keep the icon free of interactive descendants; the named
|
|
510
|
+
close button retains all close interaction.
|
|
146
511
|
|
|
147
512
|
`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:
|
|
148
513
|
|
|
149
514
|
```ts
|
|
150
|
-
import
|
|
151
|
-
import
|
|
515
|
+
import "@kerfjs/ui/webawesome.css";
|
|
516
|
+
import "@kerfjs/ui/select/register";
|
|
152
517
|
```
|
|
153
518
|
|
|
154
519
|
That boundary keeps Web Awesome and its custom-element side effects out of bundles that use unrelated components. Automated consumer-bundle tests enforce it.
|
|
520
|
+
`Select` also owns the Kerf/Web Awesome reconciliation boundary: option icons
|
|
521
|
+
keep stable slotted elements across rerenders, and `renderSelected` content is
|
|
522
|
+
replaced when the controlled value changes. Consumers do not need to add
|
|
523
|
+
`data-key` or `data-morph-skip` workarounds around choice icons.
|
|
155
524
|
|
|
156
525
|
For application choices and panes, prefer Kerf's purpose-built primitives:
|
|
157
526
|
`Select` over direct Web Awesome selection/dropdown composition,
|
|
158
527
|
`SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web
|
|
159
528
|
Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over
|
|
160
529
|
Split Panel. `ResizableRegion` includes Hot Sheet 2's 1px separator and
|
|
161
|
-
hover/focus grip.
|
|
530
|
+
hover/focus grip. Its optional `handleIcon` replaces only the decorative glyph;
|
|
531
|
+
the component and `wireResizableRegions()` retain separator semantics and
|
|
532
|
+
pointer/keyboard behavior. Consider Web Awesome Popup when its anchored-positioning
|
|
162
533
|
engine removes custom placement code; treat Tree, Animated Image, Comparison,
|
|
163
534
|
Zoomable Frame, and the displaced alternatives above as exceptional rather
|
|
164
535
|
than default patterns. The detailed rationale lives in the theme contract.
|
|
165
536
|
|
|
166
537
|
## Design and tool guidance
|
|
167
538
|
|
|
539
|
+
- [Component selection and composition](./docs/component-selection.md)
|
|
168
540
|
- [Design philosophy](./docs/design-philosophy.md)
|
|
169
541
|
- [Apple HIG translation](./docs/apple-hig.md)
|
|
170
542
|
- [Accessibility and keyboard contracts](./docs/accessibility.md)
|
|
171
543
|
- [Component and integration contract](./docs/component-contract.md)
|
|
544
|
+
- [Spacing and application layout](./docs/layout.md)
|
|
172
545
|
- [Web Awesome theme contract](./docs/webawesome-theme.md)
|
|
173
546
|
- [UX catalog contract](./docs/ux-demo.md)
|
|
174
547
|
- [AI guide](./ai/skill.md)
|
|
175
548
|
|
|
176
|
-
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. 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.
|
|
549
|
+
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.
|
|
550
|
+
|
|
551
|
+
Run `npm run format` after editing source or structured content. The narrower
|
|
552
|
+
`npm run format:css` command remains available for style-only work. The normal
|
|
553
|
+
`npm run lint` and `npm run check` gates use Prettier to reject formatting drift.
|
|
554
|
+
|
|
555
|
+
For dimensions that should scale with the root font size, author pixels with
|
|
556
|
+
`remify()`: `gap: remify(17px)` builds to `gap: 1.0625rem` using a fixed 16px
|
|
557
|
+
baseline. Keep intentional 1px borders in pixels and contextual `em` values
|
|
558
|
+
explicit. `npm run build` emits standard CSS to `dist/styles`; `npm run dev`
|
|
559
|
+
applies the same transform directly to source styles and hot-reloads edits.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"ids": [
|
|
4
|
+
"KUI-B001",
|
|
5
|
+
"KUI-B010",
|
|
6
|
+
"KUI-B011",
|
|
7
|
+
"KUI-B012",
|
|
8
|
+
"KUI-B020",
|
|
9
|
+
"KUI-B021",
|
|
10
|
+
"KUI-B022",
|
|
11
|
+
"KUI-B023",
|
|
12
|
+
"KUI-B030",
|
|
13
|
+
"KUI-B040",
|
|
14
|
+
"KUI-B050",
|
|
15
|
+
"KUI-B060",
|
|
16
|
+
"KUI-B070",
|
|
17
|
+
"KUI-B080",
|
|
18
|
+
"KUI-C101",
|
|
19
|
+
"KUI-C102",
|
|
20
|
+
"KUI-C103",
|
|
21
|
+
"KUI-C104",
|
|
22
|
+
"KUI-C105",
|
|
23
|
+
"KUI-C106",
|
|
24
|
+
"KUI-C107",
|
|
25
|
+
"KUI-C108",
|
|
26
|
+
"KUI-D001",
|
|
27
|
+
"KUI-D002",
|
|
28
|
+
"KUI-D003",
|
|
29
|
+
"KUI-D010",
|
|
30
|
+
"KUI-D011",
|
|
31
|
+
"KUI-D020",
|
|
32
|
+
"KUI-L001",
|
|
33
|
+
"KUI-L002",
|
|
34
|
+
"KUI-L003",
|
|
35
|
+
"KUI-L004",
|
|
36
|
+
"KUI-L005",
|
|
37
|
+
"KUI-L006",
|
|
38
|
+
"KUI-L007",
|
|
39
|
+
"KUI-L008",
|
|
40
|
+
"KUI-L009",
|
|
41
|
+
"KUI-L090",
|
|
42
|
+
"KUI-L101",
|
|
43
|
+
"KUI-L102",
|
|
44
|
+
"KUI-L201",
|
|
45
|
+
"KUI-L202",
|
|
46
|
+
"KUI-L203",
|
|
47
|
+
"KUI-L301",
|
|
48
|
+
"KUI-L401",
|
|
49
|
+
"KUI-L402",
|
|
50
|
+
"KUI-P001",
|
|
51
|
+
"KUI-P002",
|
|
52
|
+
"KUI-P003",
|
|
53
|
+
"KUI-P004",
|
|
54
|
+
"KUI-P005",
|
|
55
|
+
"KUI-P006",
|
|
56
|
+
"KUI-P007",
|
|
57
|
+
"KUI-P008",
|
|
58
|
+
"KUI-P009",
|
|
59
|
+
"KUI-P010",
|
|
60
|
+
"KUI-P011",
|
|
61
|
+
"KUI-P012",
|
|
62
|
+
"KUI-P013",
|
|
63
|
+
"KUI-P014",
|
|
64
|
+
"KUI-P015",
|
|
65
|
+
"KUI-P016",
|
|
66
|
+
"KUI-P017",
|
|
67
|
+
"KUI-P018",
|
|
68
|
+
"KUI-P019",
|
|
69
|
+
"KUI-P020",
|
|
70
|
+
"KUI-P021",
|
|
71
|
+
"KUI-P022",
|
|
72
|
+
"KUI-P023",
|
|
73
|
+
"KUI-P024",
|
|
74
|
+
"KUI-P025",
|
|
75
|
+
"KUI-P026",
|
|
76
|
+
"KUI-P027",
|
|
77
|
+
"KUI-P028",
|
|
78
|
+
"KUI-P029",
|
|
79
|
+
"KUI-P030",
|
|
80
|
+
"KUI-T001",
|
|
81
|
+
"KUI-T002",
|
|
82
|
+
"KUI-T003",
|
|
83
|
+
"KUI-T004",
|
|
84
|
+
"KUI-T005",
|
|
85
|
+
"KUI-T006",
|
|
86
|
+
"KUI-T007",
|
|
87
|
+
"KUI-T008",
|
|
88
|
+
"KUI-T009",
|
|
89
|
+
"KUI-T010",
|
|
90
|
+
"KUI-T011"
|
|
91
|
+
]
|
|
92
|
+
}
|