@kerfjs/ui 5.0.0-beta.97 → 5.0.0-beta.99
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 +42 -1
- package/ai/application-ui-diagnostic-ids-v1.json +1 -0
- package/ai/component-catalog.json +487 -66
- package/ai/component-catalog.schema.json +1 -1
- package/ai/component-composition-rules.json +22 -2
- package/ai/component-composition.json +360 -33
- package/ai/component-composition.schema.json +1 -1
- package/ai/components/README.md +18 -17
- package/ai/components/anchored-surface.md +13 -0
- package/ai/components/application-tabs.md +1 -1
- package/ai/components/chip.md +9 -5
- package/ai/components/choice-chips.md +15 -8
- package/ai/components/collapsible-panel.md +3 -2
- package/ai/components/composer.md +83 -0
- package/ai/components/content-item.md +2 -2
- package/ai/components/corner-status.md +1 -1
- package/ai/components/document-baseline.md +3 -3
- package/ai/components/foundation.md +2 -2
- package/ai/components/layout.md +1 -1
- package/ai/components/list-action-row.md +5 -1
- package/ai/components/list-item.md +5 -1
- package/ai/components/list.md +19 -3
- package/ai/components/nav-stack.md +11 -2
- package/ai/components/pane.md +13 -4
- package/ai/components/popup-menu.md +4 -4
- package/ai/components/recipe-app-shell.md +3 -3
- package/ai/components/recipe-collapsible-sidebar.md +3 -3
- package/ai/components/recipe-compact-toolbar.md +1 -1
- package/ai/components/recipe-composer-form.md +3 -3
- package/ai/components/recipe-list-detail-dialog.md +2 -2
- package/ai/components/recipe-list-workspace-states.md +3 -3
- package/ai/components/recipe-loading-inspector.md +1 -1
- package/ai/components/recipe-navigation-sidebar.md +3 -3
- package/ai/components/recipe-navigation-stack.md +3 -3
- package/ai/components/recipe-workspace-header.md +3 -3
- package/ai/components/resize.md +2 -2
- package/ai/components/split-view.md +4 -2
- package/ai/components/sunken-panel.md +2 -2
- package/ai/components/surface-scaffold.md +15 -3
- package/ai/components/tab-bar.md +1 -0
- package/ai/components/tab-navigator.md +4 -0
- package/ai/components/toolbar-control-group.md +2 -0
- package/ai/components/toolbar-text.md +1 -0
- package/ai/components/toolbar.md +1 -0
- package/ai/components/workbench.md +1 -0
- package/ai/public-api-signatures-v1.md +504 -80
- package/ai/skill.md +41 -14
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/component-ownership.mjs +1 -1
- package/analyzer/index.mjs +41 -14
- package/dist/anchored-surface.d.ts +30 -2
- package/dist/anchored-surface.js +1 -1
- package/dist/app-tab.js +1 -1
- package/dist/browser/composer.js +4 -0
- package/dist/catalog-resources.d.ts +3 -2
- package/dist/catalog-resources.js +4 -4
- package/dist/catalog-resources.js.map +1 -1
- package/dist/catalog.d.ts +39 -8
- package/dist/catalog.js +55 -32
- package/dist/catalog.js.map +1 -1
- package/dist/chip.d.ts +41 -9
- package/dist/chip.js +1 -1
- package/dist/choice-chips.d.ts +40 -16
- package/dist/choice-chips.js +1 -1
- package/dist/chunk-34U4ANDJ.js +119 -0
- package/dist/chunk-34U4ANDJ.js.map +1 -0
- package/dist/{chunk-36TL6BCR.js → chunk-3GLYIIFR.js} +34 -6
- package/dist/chunk-3GLYIIFR.js.map +1 -0
- package/dist/{chunk-HWY4BSLS.js → chunk-3VXDSIBJ.js} +2 -2
- package/dist/{chunk-HWY4BSLS.js.map → chunk-3VXDSIBJ.js.map} +1 -1
- package/dist/chunk-3WYREXW4.js +120 -0
- package/dist/chunk-3WYREXW4.js.map +1 -0
- package/dist/chunk-AV7CPAPT.js +82 -0
- package/dist/chunk-AV7CPAPT.js.map +1 -0
- package/dist/{chunk-XK4E225T.js → chunk-B53PS2LE.js} +2 -2
- package/dist/{chunk-XK4E225T.js.map → chunk-B53PS2LE.js.map} +1 -1
- package/dist/{chunk-R42D2BAO.js → chunk-CA7LNX3J.js} +2 -2
- package/dist/{chunk-R42D2BAO.js.map → chunk-CA7LNX3J.js.map} +1 -1
- package/dist/{chunk-AYHC62OZ.js → chunk-CMETHPKR.js} +26 -29
- package/dist/chunk-CMETHPKR.js.map +1 -0
- package/dist/{chunk-Y43B6DS3.js → chunk-CVD5IZGB.js} +2 -2
- package/dist/{chunk-Y43B6DS3.js.map → chunk-CVD5IZGB.js.map} +1 -1
- package/dist/{chunk-6STQXRT4.js → chunk-CXZXHZTR.js} +121 -12
- package/dist/chunk-CXZXHZTR.js.map +1 -0
- package/dist/{chunk-GZE2XVKC.js → chunk-DZJ4GBSP.js} +3 -3
- package/dist/{chunk-GZE2XVKC.js.map → chunk-DZJ4GBSP.js.map} +1 -1
- package/dist/chunk-ELCMSQNJ.js +49 -0
- package/dist/chunk-ELCMSQNJ.js.map +1 -0
- package/dist/{chunk-P74VXMB6.js → chunk-EOO6PYGF.js} +7 -14
- package/dist/chunk-EOO6PYGF.js.map +1 -0
- package/dist/{chunk-PRG4CL3Q.js → chunk-FR76ZJQC.js} +21 -19
- package/dist/chunk-FR76ZJQC.js.map +1 -0
- package/dist/{chunk-QQ3TTWFH.js → chunk-G3J7JDP6.js} +1 -1
- package/dist/{chunk-QQ3TTWFH.js.map → chunk-G3J7JDP6.js.map} +1 -1
- package/dist/{chunk-IGTWXPTN.js → chunk-HGV7J4T6.js} +3 -3
- package/dist/{chunk-IGTWXPTN.js.map → chunk-HGV7J4T6.js.map} +1 -1
- package/dist/{chunk-YWQGSUF2.js → chunk-HLDRH23D.js} +3 -3
- package/dist/{chunk-YWQGSUF2.js.map → chunk-HLDRH23D.js.map} +1 -1
- package/dist/{chunk-PBT3CPPY.js → chunk-HQZYKJ56.js} +24 -4
- package/dist/chunk-HQZYKJ56.js.map +1 -0
- package/dist/{chunk-V6W56V3N.js → chunk-HZPHCSCS.js} +16 -3
- package/dist/chunk-HZPHCSCS.js.map +1 -0
- package/dist/{chunk-GJYQ27C2.js → chunk-INI4WDWC.js} +8 -1
- package/dist/chunk-INI4WDWC.js.map +1 -0
- package/dist/{chunk-U657IHFB.js → chunk-IQSRHXZR.js} +10 -4
- package/dist/chunk-IQSRHXZR.js.map +1 -0
- package/dist/{chunk-KQDU7Z7P.js → chunk-K4AT3V3J.js} +2 -1
- package/dist/chunk-K4AT3V3J.js.map +1 -0
- package/dist/{chunk-QIAPOWHH.js → chunk-KCS6NJ3O.js} +2 -2
- package/dist/{chunk-QIAPOWHH.js.map → chunk-KCS6NJ3O.js.map} +1 -1
- package/dist/{chunk-UKKRPP56.js → chunk-LOSRXZAH.js} +2 -2
- package/dist/{chunk-UKKRPP56.js.map → chunk-LOSRXZAH.js.map} +1 -1
- package/dist/{chunk-ROZLJULF.js → chunk-MF6ZUUJZ.js} +8 -3
- package/dist/chunk-MF6ZUUJZ.js.map +1 -0
- package/dist/{chunk-6IVNMC6R.js → chunk-MHMWQ7RB.js} +2 -2
- package/dist/{chunk-6IVNMC6R.js.map → chunk-MHMWQ7RB.js.map} +1 -1
- package/dist/{chunk-JYD7G4RG.js → chunk-PIVY32AE.js} +15 -5
- package/dist/chunk-PIVY32AE.js.map +1 -0
- package/dist/{chunk-BU23Z5HZ.js → chunk-PYBBYSZ3.js} +13 -18
- package/dist/chunk-PYBBYSZ3.js.map +1 -0
- package/dist/chunk-QDSZTQXL.js +28 -0
- package/dist/chunk-QDSZTQXL.js.map +1 -0
- package/dist/{chunk-YXOMI7ES.js → chunk-QIG4IGUP.js} +2 -2
- package/dist/{chunk-YXOMI7ES.js.map → chunk-QIG4IGUP.js.map} +1 -1
- package/dist/{chunk-6BRRUPJY.js → chunk-QROYYGWU.js} +3 -3
- package/dist/chunk-QROYYGWU.js.map +1 -0
- package/dist/{chunk-FOQK4F3L.js → chunk-RHD7RKGI.js} +28 -7
- package/dist/chunk-RHD7RKGI.js.map +1 -0
- package/dist/{chunk-BBU2SPRE.js → chunk-T4WJ5VGP.js} +4 -4
- package/dist/{chunk-BBU2SPRE.js.map → chunk-T4WJ5VGP.js.map} +1 -1
- package/dist/{chunk-6NOLL5KG.js → chunk-TGLUDQP2.js} +3 -3
- package/dist/{chunk-6NOLL5KG.js.map → chunk-TGLUDQP2.js.map} +1 -1
- package/dist/{chunk-HO6FU3G7.js → chunk-TLMMFQWM.js} +4 -4
- package/dist/{chunk-HO6FU3G7.js.map → chunk-TLMMFQWM.js.map} +1 -1
- package/dist/chunk-UMKV7YVQ.js +20 -0
- package/dist/chunk-UMKV7YVQ.js.map +1 -0
- package/dist/{chunk-M2NRCFRO.js → chunk-VFYO3UGZ.js} +2 -2
- package/dist/{chunk-M2NRCFRO.js.map → chunk-VFYO3UGZ.js.map} +1 -1
- package/dist/{chunk-YOKEL75M.js → chunk-WVS6CUCT.js} +2 -2
- package/dist/{chunk-YOKEL75M.js.map → chunk-WVS6CUCT.js.map} +1 -1
- package/dist/{chunk-MN3POJFN.js → chunk-YMUIQRWK.js} +2 -2
- package/dist/{chunk-MN3POJFN.js.map → chunk-YMUIQRWK.js.map} +1 -1
- package/dist/{chunk-Y3LC7JQO.js → chunk-YOA5W5ZH.js} +2 -2
- package/dist/{chunk-Y3LC7JQO.js.map → chunk-YOA5W5ZH.js.map} +1 -1
- package/dist/{chunk-44A6LP54.js → chunk-YQ2AC4E2.js} +2 -2
- package/dist/{chunk-44A6LP54.js.map → chunk-YQ2AC4E2.js.map} +1 -1
- package/dist/chunk-ZNROKDSZ.js +54 -0
- package/dist/chunk-ZNROKDSZ.js.map +1 -0
- package/dist/collapsible-panel.d.ts +3 -2
- package/dist/collapsible-panel.js +4 -3
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/composer.d.ts +62 -0
- package/dist/composer.js +5 -0
- package/dist/composer.js.map +1 -0
- package/dist/corner-status.d.ts +1 -1
- package/dist/corner-status.js +1 -1
- package/dist/css-values.d.ts +9 -1
- package/dist/css-values.js +1 -1
- package/dist/disclosure-arrow.js +1 -1
- package/dist/empty-state.js +1 -1
- package/dist/grid.js +1 -1
- package/dist/icon-button.js +1 -1
- package/dist/icon-toggle-button.js +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +40 -37
- package/dist/list-action-row.d.ts +10 -2
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-icon-tile-B8dr97OW.d.ts +18 -0
- package/dist/list-item.d.ts +10 -3
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +36 -4
- package/dist/list.js +1 -1
- package/dist/loading-spinner.js +1 -1
- package/dist/lucide-icon.js +1 -1
- package/dist/{nav-stack-BvSKY448.d.ts → nav-stack-VXTumzKa.d.ts} +53 -4
- package/dist/nav-stack.d.ts +3 -2
- package/dist/nav-stack.js +2 -1
- package/dist/pane.d.ts +40 -3
- package/dist/pane.js +1 -1
- package/dist/{panel-toolbar-CL9tYOkh.d.ts → panel-toolbar-vg6Ir5Dy.d.ts} +6 -1
- package/dist/popup-menu-register.d.ts +2 -1
- package/dist/popup-menu-register.js +97 -22
- package/dist/popup-menu-register.js.map +1 -1
- package/dist/popup-menu.js +1 -1
- package/dist/row.js +1 -1
- package/dist/scroll-clearance-BikHljTc.d.ts +14 -0
- package/dist/select-register.js +11 -0
- package/dist/select-register.js.map +1 -1
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-button.js +1 -1
- package/dist/split-view.d.ts +7 -5
- package/dist/split-view.js +6 -3
- package/dist/split-view.js.map +1 -1
- package/dist/state-banner.d.ts +6 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/anchored-surface.css +27 -1
- package/dist/styles/catalog/components/catalog-example-stack.css +5 -0
- package/dist/styles/catalog/components/catalog-example.css +33 -0
- package/dist/styles/catalog/components/catalog-stage.css +7 -0
- package/dist/styles/chip.css +70 -0
- package/dist/styles/components/actions/popup-menu/popup-menu.css +21 -4
- package/dist/styles/components/actions/toolbar/toolbar.css +19 -0
- package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +75 -1
- package/dist/styles/components/actions/toolbar-text/toolbar-text.css +75 -0
- package/dist/styles/components/collections/list/list.css +77 -7
- package/dist/styles/components/collections/list-action-row/list-action-row.css +177 -22
- package/dist/styles/components/collections/list-item/list-item.css +158 -11
- package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +27 -1
- package/dist/styles/components/feedback/chip/chip.css +70 -0
- package/dist/styles/components/feedback/state-banner/state-banner.css +24 -13
- package/dist/styles/components/forms/composer/composer.css +100 -0
- package/dist/styles/components/forms/select/select.css +1 -0
- package/dist/styles/components/forms/token-search-field/token-search-field.css +13 -2
- package/dist/styles/components/layout/pane/pane.css +81 -2
- package/dist/styles/components/navigation/nav-stack/nav-stack.css +84 -0
- package/dist/styles/components/navigation/tab-bar/tab-bar.css +15 -4
- package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +79 -4
- package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +195 -0
- package/dist/styles/composer.css +100 -0
- package/dist/styles/foundation.css +66 -0
- package/dist/styles/list-action-row.css +177 -22
- package/dist/styles/list-item.css +158 -11
- package/dist/styles/list.css +77 -7
- package/dist/styles/nav-stack.css +84 -0
- package/dist/styles/pane.css +81 -2
- package/dist/styles/popup-menu.css +21 -4
- package/dist/styles/select.css +1 -0
- package/dist/styles/state-banner.css +24 -13
- package/dist/styles/styles.css +1 -0
- package/dist/styles/surface-scaffold.css +195 -0
- package/dist/styles/tab-bar.css +15 -4
- package/dist/styles/tab-navigator.css +79 -4
- package/dist/styles/token-search-field.css +13 -2
- package/dist/styles/toolbar-control-group.css +75 -1
- package/dist/styles/toolbar-text.css +75 -0
- package/dist/styles/toolbar.css +19 -0
- package/dist/styles/webawesome.css +18 -0
- package/dist/surface-scaffold-register.d.ts +6 -1
- package/dist/surface-scaffold-register.js +89 -3
- package/dist/surface-scaffold-register.js.map +1 -1
- package/dist/surface-scaffold.d.ts +66 -7
- package/dist/surface-scaffold.js +1 -1
- package/dist/tab-navigator.d.ts +23 -2
- package/dist/tab-navigator.js +2 -0
- package/dist/tab-navigator.js.map +1 -1
- package/dist/token-search-field.d.ts +1 -1
- package/dist/token-search-field.js +1 -1
- package/dist/{token-search-model-DTcTXWMS.d.ts → token-search-model-aYR0YAei.d.ts} +32 -2
- package/dist/token-search-model.d.ts +1 -1
- package/dist/toolbar-control-group.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +1 -0
- package/dist/value-table.js +1 -1
- package/dist/wire-catalog.d.ts +3 -2
- package/dist/wire-catalog.js +2 -2
- package/dist/wire-composers.d.ts +16 -0
- package/dist/wire-composers.js +3 -0
- package/dist/wire-composers.js.map +1 -0
- package/dist/wire-list-focus-scroll.d.ts +16 -0
- package/dist/wire-list-focus-scroll.js +3 -0
- package/dist/wire-list-focus-scroll.js.map +1 -0
- package/dist/wire-nav-stack.js +135 -0
- package/dist/wire-nav-stack.js.map +1 -1
- package/dist/wire-scroll-dividers.d.ts +9 -0
- package/dist/wire-scroll-dividers.js +1 -1
- package/dist/wire-tab-bars.js +1 -1
- package/dist/wire-tab-navigator.d.ts +3 -1
- package/dist/wire-tab-navigator.js +133 -1
- package/dist/wire-tab-navigator.js.map +1 -1
- package/dist/wire-token-search-fields.d.ts +1 -1
- package/dist/wire-token-search-fields.js +1 -1
- package/dist/workbench.d.ts +8 -3
- package/dist/workbench.js +2 -1
- package/docs/accessibility.md +132 -3
- package/docs/anchored-surface.md +46 -4
- package/docs/app-layouts.md +23 -2
- package/docs/apple-hig.md +1 -0
- package/docs/catalog.md +61 -9
- package/docs/collapsible-panel.md +9 -6
- package/docs/component-contract.md +46 -13
- package/docs/component-selection.md +147 -20
- package/docs/composer.md +143 -0
- package/docs/design/templates/choice-chips/multiple-dark.svg +1 -0
- package/docs/design/templates/choice-chips/multiple.svg +1 -0
- package/docs/design/templates/choice-chips-dark.svg +1 -1
- package/docs/design/templates/choice-chips.svg +1 -1
- package/docs/design/templates/composer/chat-dark.svg +1 -0
- package/docs/design/templates/composer/chat.svg +1 -0
- package/docs/design/templates/composer/prompt-dark.svg +1 -0
- package/docs/design/templates/composer/prompt.svg +1 -0
- package/docs/design/templates/composer-dark.svg +1 -0
- package/docs/design/templates/composer.svg +1 -0
- package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
- package/docs/design/templates/empty-state/filtered.svg +1 -1
- package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
- package/docs/design/templates/empty-state/with-action.svg +1 -1
- package/docs/design/templates/empty-state-dark.svg +1 -1
- package/docs/design/templates/empty-state.svg +1 -1
- package/docs/design/templates/list/compact-dark.svg +1 -1
- package/docs/design/templates/list/compact.svg +1 -1
- package/docs/design/templates/list-action-row/default-dark.svg +1 -1
- package/docs/design/templates/list-action-row/default.svg +1 -1
- package/docs/design/templates/list-action-row/icon-tile-dark.svg +1 -0
- package/docs/design/templates/list-action-row/icon-tile.svg +1 -0
- package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
- package/docs/design/templates/list-action-row/selected.svg +1 -1
- package/docs/design/templates/list-action-row/trailing-menu-dark.svg +1 -1
- package/docs/design/templates/list-action-row/trailing-menu.svg +1 -1
- package/docs/design/templates/list-action-row-dark.svg +1 -1
- package/docs/design/templates/list-action-row.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-header/size-l-dark.svg +1 -1
- package/docs/design/templates/list-header/size-l.svg +1 -1
- package/docs/design/templates/list-header/size-m-dark.svg +1 -1
- package/docs/design/templates/list-header/size-m.svg +1 -1
- package/docs/design/templates/list-header/size-xl-dark.svg +1 -1
- package/docs/design/templates/list-header/size-xl.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/list-item/icon-tile-dark.svg +1 -0
- package/docs/design/templates/list-item/icon-tile.svg +1 -0
- package/docs/design/templates/list-item/selected-dark.svg +1 -1
- package/docs/design/templates/list-item/selected.svg +1 -1
- package/docs/design/templates/list-item-dark.svg +1 -1
- package/docs/design/templates/list-item.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design/templates/segmented-control-dark.svg +1 -1
- package/docs/design/templates/segmented-control.svg +1 -1
- package/docs/design/templates/skeleton-dark.svg +1 -1
- package/docs/design/templates/skeleton.svg +1 -1
- package/docs/design/templates/state-banner/danger-dark.svg +1 -1
- package/docs/design/templates/state-banner/danger.svg +1 -1
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
- package/docs/design/templates/state-banner/info-badge.svg +1 -1
- package/docs/design/templates/state-banner/info-dark.svg +1 -1
- package/docs/design/templates/state-banner/info.svg +1 -1
- package/docs/design/templates/state-banner/strip-dark.svg +1 -1
- package/docs/design/templates/state-banner/strip.svg +1 -1
- package/docs/design/templates/state-banner/success-dark.svg +1 -1
- package/docs/design/templates/state-banner/success.svg +1 -1
- package/docs/design/templates/state-banner/warning-dark.svg +1 -1
- package/docs/design/templates/state-banner/warning.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/tab-bar-dark.svg +1 -1
- package/docs/design/templates/tab-bar.svg +1 -1
- package/docs/design/templates/token-search-field-dark.svg +1 -1
- package/docs/design/templates/token-search-field.svg +1 -1
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default.svg +1 -1
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/large.svg +1 -1
- package/docs/design/templates/toolbar-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-text.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/design/templates/value-table/details-dark.svg +1 -1
- package/docs/design/templates/value-table/details.svg +1 -1
- package/docs/design/templates/value-table-dark.svg +1 -1
- package/docs/design/templates/value-table.svg +1 -1
- package/docs/design-philosophy.md +9 -1
- package/docs/examples/command-palette-adapter.tsx +3 -3
- package/docs/layout.md +147 -14
- package/docs/nav-stack.md +132 -8
- package/docs/recipes.md +9 -9
- package/docs/split-view.md +3 -3
- package/docs/sunken-panel.md +2 -2
- package/docs/surface-scaffold.md +138 -7
- package/docs/tab-navigator.md +38 -1
- package/docs/type-contracts.md +16 -16
- package/docs/ui-analyzer.md +3 -1
- package/docs/ui-doctor.md +71 -0
- package/docs/ux-demo.md +6 -6
- package/docs/webawesome-theme.md +7 -0
- package/docs/workbench.md +10 -6
- package/docs/writing.md +152 -0
- package/doctor/copy-capitalization-checks.mjs +591 -0
- package/doctor/index.mjs +17 -8
- package/llms.txt +105 -11
- package/package.json +15 -1
- package/ux-demo/recipes/app-shell.tsx +11 -11
- package/ux-demo/recipes/collapsible-sidebar.tsx +12 -11
- package/ux-demo/recipes/compact-toolbar.tsx +10 -10
- package/ux-demo/recipes/composer-form.tsx +8 -8
- package/ux-demo/recipes/list-detail-dialog.tsx +13 -13
- package/ux-demo/recipes/list-workspace-states.tsx +13 -13
- package/ux-demo/recipes/loading-inspector.tsx +10 -10
- package/ux-demo/recipes/navigation-sidebar.tsx +7 -7
- package/ux-demo/recipes/navigation-stack.tsx +5 -5
- package/ux-demo/recipes/workspace-header.tsx +5 -5
- package/dist/chunk-36TL6BCR.js.map +0 -1
- package/dist/chunk-4LOK4634.js +0 -21
- package/dist/chunk-4LOK4634.js.map +0 -1
- package/dist/chunk-6BRRUPJY.js.map +0 -1
- package/dist/chunk-6STQXRT4.js.map +0 -1
- package/dist/chunk-76PWEN5Y.js +0 -64
- package/dist/chunk-76PWEN5Y.js.map +0 -1
- package/dist/chunk-AYHC62OZ.js.map +0 -1
- package/dist/chunk-BU23Z5HZ.js.map +0 -1
- package/dist/chunk-DQDTZE4W.js +0 -70
- package/dist/chunk-DQDTZE4W.js.map +0 -1
- package/dist/chunk-FOQK4F3L.js.map +0 -1
- package/dist/chunk-GJYQ27C2.js.map +0 -1
- package/dist/chunk-JYD7G4RG.js.map +0 -1
- package/dist/chunk-KQDU7Z7P.js.map +0 -1
- package/dist/chunk-P74VXMB6.js.map +0 -1
- package/dist/chunk-PBT3CPPY.js.map +0 -1
- package/dist/chunk-PRG4CL3Q.js.map +0 -1
- package/dist/chunk-ROZLJULF.js.map +0 -1
- package/dist/chunk-U657IHFB.js.map +0 -1
- package/dist/chunk-V6W56V3N.js.map +0 -1
|
@@ -11,9 +11,24 @@ type DialogSurfaceHeight = CssLength | 'viewport';
|
|
|
11
11
|
/**
|
|
12
12
|
* How the dialog body lays out its children: `flow` (default) scrolls ordinary
|
|
13
13
|
* content in the body; `fill` gives one child the body's whole height and
|
|
14
|
-
* lets it own scrolling (a SplitView, a Pane, an editor)
|
|
14
|
+
* lets it own scrolling (a SplitView, a Pane, an editor); `fill-last` stacks
|
|
15
|
+
* the leading children at their natural height and gives the last child the
|
|
16
|
+
* remaining height to own its scrolling (a heading and notices above a
|
|
17
|
+
* scrolling transcript).
|
|
15
18
|
*/
|
|
16
|
-
type DialogSurfaceBodyLayout = 'flow' | 'fill';
|
|
19
|
+
type DialogSurfaceBodyLayout = 'flow' | 'fill' | 'fill-last';
|
|
20
|
+
/**
|
|
21
|
+
* Where the dialog footer sits: `docked` (default) below the body, or
|
|
22
|
+
* `floating` over the body's block end, inset from the panel's inline and
|
|
23
|
+
* block-end edges on a transparent background (a chat composer).
|
|
24
|
+
*/
|
|
25
|
+
type DialogSurfaceFooterPresentation = 'docked' | 'floating';
|
|
26
|
+
/**
|
|
27
|
+
* Where the dialog header sits: `docked` (default) above the body, or
|
|
28
|
+
* `floating` over the body's block-start edge on the translucent chrome
|
|
29
|
+
* material, so content scrolls visibly beneath the title bar.
|
|
30
|
+
*/
|
|
31
|
+
type DialogSurfaceHeaderPresentation = 'docked' | 'floating';
|
|
17
32
|
/**
|
|
18
33
|
* Application `data-*` identity on the DialogSurface root, such as
|
|
19
34
|
* `data-key`; the surface's own configuration attributes stay protected.
|
|
@@ -36,8 +51,43 @@ interface DialogSurfaceProps {
|
|
|
36
51
|
* height to fill. Takes precedence over `maxHeight`.
|
|
37
52
|
*/
|
|
38
53
|
height?: DialogSurfaceHeight;
|
|
39
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Body layout (default `flow`); `fill` lets one child own the body and
|
|
56
|
+
* `fill-last` stacks fixed rows above one filling last child.
|
|
57
|
+
*/
|
|
40
58
|
bodyLayout?: DialogSurfaceBodyLayout;
|
|
59
|
+
/**
|
|
60
|
+
* Header placement (default `docked`); `floating` lays the dialog's header
|
|
61
|
+
* (its title and close control) over the body's block-start edge on the
|
|
62
|
+
* translucent chrome material (`--kui-chrome-material-raised`, opaque under
|
|
63
|
+
* `prefers-reduced-transparency`, increased contrast, forced colors, or
|
|
64
|
+
* without `backdrop-filter`). The `/register` entry measures the header;
|
|
65
|
+
* the body reserves that height before its own inset, so its first content
|
|
66
|
+
* rests below the title bar. A `fill`/`fill-last` child that is the body's
|
|
67
|
+
* only child and opts into block-start `scrollClearance` (a `List` or
|
|
68
|
+
* `Pane`) takes the clearance inside its own scroll area instead, published
|
|
69
|
+
* as `--kui-scroll-clearance-block-start`, so its content scrolls visibly
|
|
70
|
+
* beneath the header. Unmeasured (without the register), the header stays
|
|
71
|
+
* docked. Keep header text in the normal text color: quiet text can fall
|
|
72
|
+
* below AA over the content passing beneath it.
|
|
73
|
+
*/
|
|
74
|
+
headerPresentation?: DialogSurfaceHeaderPresentation;
|
|
75
|
+
/**
|
|
76
|
+
* Footer placement (default `docked`); `floating` lays the footer over the
|
|
77
|
+
* body's block end. The body reserves the footer's measured height so its
|
|
78
|
+
* last content is never hidden beneath it. A `fill`/`fill-last` child that
|
|
79
|
+
* opts into block-end `scrollClearance` (a `List` or `Pane`) takes that
|
|
80
|
+
* clearance inside its own scroll area instead, published as
|
|
81
|
+
* `--kui-scroll-clearance-block-end`, so its content scrolls visibly beneath
|
|
82
|
+
* the transparent footer.
|
|
83
|
+
*/
|
|
84
|
+
footerPresentation?: DialogSurfaceFooterPresentation;
|
|
85
|
+
/**
|
|
86
|
+
* A floating footer's clearance from the panel's inline and block-end edges
|
|
87
|
+
* (default the 16px container inset). Choose a phone value such as
|
|
88
|
+
* `remify(8)` from `deviceClass()`; the scaffold adds no breakpoint.
|
|
89
|
+
*/
|
|
90
|
+
footerOffset?: CssLength;
|
|
41
91
|
/**
|
|
42
92
|
* Safe `data-*` identity on the root. Give sibling dialogs distinct
|
|
43
93
|
* `data-key`s so a re-render morphs each surface into itself instead of
|
|
@@ -50,7 +100,7 @@ interface DialogSurfaceProps {
|
|
|
50
100
|
slot?: string;
|
|
51
101
|
}
|
|
52
102
|
/** Configure recurring Web Awesome dialog geometry without consumer ::part() CSS. */
|
|
53
|
-
declare function DialogSurface({ children, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, bodyLayout, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
|
|
103
|
+
declare function DialogSurface({ children, size, presentation, preferredWidth, bodyInset, footerInset, viewportGutter, maxHeight, height, bodyLayout, headerPresentation, footerPresentation, footerOffset, rootAttributes, className, slot, }: DialogSurfaceProps): kerfjs.SafeHtml;
|
|
54
104
|
/** Where a PopoverDialogSurface appears: the top layer, or in flow. */
|
|
55
105
|
type PopoverDialogSurfacePresentation = 'overlay' | 'embedded';
|
|
56
106
|
/** Application `data-*` metadata on the surface root. */
|
|
@@ -65,6 +115,12 @@ type PopoverDialogSurfaceName = {
|
|
|
65
115
|
type PopoverDialogSurfaceProps = PopoverDialogSurfaceName & {
|
|
66
116
|
/** The root id: what an opening control's `popovertarget` names. */
|
|
67
117
|
id?: string;
|
|
118
|
+
/**
|
|
119
|
+
* Id of the element whose text is the dialog's accessible description,
|
|
120
|
+
* such as a title `ToolbarText`'s `descriptionId`; rendered as
|
|
121
|
+
* `aria-describedby` on the `role="dialog"` root.
|
|
122
|
+
*/
|
|
123
|
+
describedBy?: string;
|
|
68
124
|
children: KerfUiContent;
|
|
69
125
|
/**
|
|
70
126
|
* `overlay` (default) is a native `popover="auto"` in the top layer:
|
|
@@ -82,7 +138,10 @@ type PopoverDialogSurfaceProps = PopoverDialogSurfaceName & {
|
|
|
82
138
|
maxHeight?: DialogSurfaceMaxHeight;
|
|
83
139
|
/** Edge clearance on each side of the viewport (default 16px). */
|
|
84
140
|
viewportGutter?: CssLength;
|
|
85
|
-
/**
|
|
141
|
+
/**
|
|
142
|
+
* Body layout (default `flow`); `fill` lets one child own the surface and
|
|
143
|
+
* `fill-last` stacks fixed rows above one filling last child.
|
|
144
|
+
*/
|
|
86
145
|
bodyLayout?: DialogSurfaceBodyLayout;
|
|
87
146
|
rootAttributes?: PopoverDialogSurfaceDataAttributes;
|
|
88
147
|
className?: string;
|
|
@@ -96,7 +155,7 @@ type PopoverDialogSurfaceProps = PopoverDialogSurfaceName & {
|
|
|
96
155
|
* dismisses and leaves the page interactive. Use `DialogSurface` with
|
|
97
156
|
* `wa-dialog` when the task must block the page.
|
|
98
157
|
*/
|
|
99
|
-
declare function PopoverDialogSurface({ id, children, label, labelledBy, presentation, size, preferredWidth, height, maxHeight, viewportGutter, bodyLayout, rootAttributes, className, slot, }: PopoverDialogSurfaceProps): kerfjs.SafeHtml;
|
|
158
|
+
declare function PopoverDialogSurface({ id, children, label, labelledBy, describedBy, presentation, size, preferredWidth, height, maxHeight, viewportGutter, bodyLayout, rootAttributes, className, slot, }: PopoverDialogSurfaceProps): kerfjs.SafeHtml;
|
|
100
159
|
type PopupSurfaceInset = 'standard' | 'compact' | 'list-zero';
|
|
101
160
|
interface PopupSurfaceProps {
|
|
102
161
|
children: KerfUiContent;
|
|
@@ -108,4 +167,4 @@ interface PopupSurfaceProps {
|
|
|
108
167
|
/** Configure recurring Web Awesome dropdown-menu geometry without consumer ::part() CSS. */
|
|
109
168
|
declare function PopupSurface({ children, inset, className, slot, }: PopupSurfaceProps): kerfjs.SafeHtml;
|
|
110
169
|
|
|
111
|
-
export { DialogSurface, type DialogSurfaceBodyLayout, type DialogSurfaceHeight, type DialogSurfaceMaxHeight, type DialogSurfacePresentation, type DialogSurfaceProps, type DialogSurfaceRootAttributes, type DialogSurfaceSize, PopoverDialogSurface, type PopoverDialogSurfaceDataAttributes, type PopoverDialogSurfacePresentation, type PopoverDialogSurfaceProps, PopupSurface, type PopupSurfaceInset, type PopupSurfaceProps, type SurfaceInset };
|
|
170
|
+
export { DialogSurface, type DialogSurfaceBodyLayout, type DialogSurfaceFooterPresentation, type DialogSurfaceHeaderPresentation, type DialogSurfaceHeight, type DialogSurfaceMaxHeight, type DialogSurfacePresentation, type DialogSurfaceProps, type DialogSurfaceRootAttributes, type DialogSurfaceSize, PopoverDialogSurface, type PopoverDialogSurfaceDataAttributes, type PopoverDialogSurfacePresentation, type PopoverDialogSurfaceProps, PopupSurface, type PopupSurfaceInset, type PopupSurfaceProps, type SurfaceInset };
|
package/dist/surface-scaffold.js
CHANGED
package/dist/tab-navigator.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { SafeHtml } from 'kerfjs';
|
|
2
2
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
3
3
|
import { PaneAppearance } from './pane.js';
|
|
4
|
+
import './scroll-clearance-BikHljTc.js';
|
|
4
5
|
|
|
5
6
|
interface TabNavigatorTabBase<Id extends string> {
|
|
6
7
|
id: Id;
|
|
@@ -52,6 +53,12 @@ interface TabNavigatorTabDotBadge {
|
|
|
52
53
|
}
|
|
53
54
|
/** One bottom-bar destination: its label, optional icon and badge, and content. */
|
|
54
55
|
type TabNavigatorTab<Id extends string = string> = TabNavigatorTabBase<Id> & (TabNavigatorTabCountBadge | TabNavigatorTabDotBadge);
|
|
56
|
+
/**
|
|
57
|
+
* How a {@link TabNavigator}'s tab bar relates to the active scene: `docked`
|
|
58
|
+
* below it, or `overlay` laid over its bottom edge on the translucent chrome
|
|
59
|
+
* material, so the scene's content scrolls visibly beneath the bar.
|
|
60
|
+
*/
|
|
61
|
+
type TabNavigatorBarPresentation = 'docked' | 'overlay';
|
|
55
62
|
interface TabNavigatorProps<Id extends string = string> {
|
|
56
63
|
id: string;
|
|
57
64
|
/** Accessible name for the tab bar. */
|
|
@@ -76,6 +83,20 @@ interface TabNavigatorProps<Id extends string = string> {
|
|
|
76
83
|
* is the bar's own 1px top border, so no state moves the bar or a tab.
|
|
77
84
|
*/
|
|
78
85
|
chromeDividers?: 'scroll' | 'always' | 'none';
|
|
86
|
+
/**
|
|
87
|
+
* `docked` (default) gives the tab bar its own band below the scenes.
|
|
88
|
+
* `overlay` lays it over the active scene's bottom edge on the translucent
|
|
89
|
+
* chrome material (opaque under reduced transparency, increased contrast,
|
|
90
|
+
* or without `backdrop-filter`; `Canvas` in forced colors), so content
|
|
91
|
+
* scrolls visibly beneath it, as under an iOS tab bar. `wireTabNavigator`
|
|
92
|
+
* measures the live bar (bottom safe area included) and the scenes hand
|
|
93
|
+
* its height to their content as the block-end `--kui-edge-inset-*`
|
|
94
|
+
* context, so a plain scene, a sole `Pane`, or a `NavStack` (and its own
|
|
95
|
+
* bottom toolbar, which then sits above the bar) rests its last item clear
|
|
96
|
+
* of it. Until then it stays docked. Unselected tab labels lift halfway
|
|
97
|
+
* toward the normal text color to keep AA over the content beneath.
|
|
98
|
+
*/
|
|
99
|
+
barPresentation?: TabNavigatorBarPresentation;
|
|
79
100
|
className?: string;
|
|
80
101
|
/** Native named-slot assignment when composed inside a web component. */
|
|
81
102
|
slot?: string;
|
|
@@ -88,6 +109,6 @@ interface TabNavigatorProps<Id extends string = string> {
|
|
|
88
109
|
* On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
|
|
89
110
|
* a bottom bar. See `docs/23-app-layouts.md` §3.4.
|
|
90
111
|
*/
|
|
91
|
-
declare function TabNavigator<Id extends string>({ id, label, tabs, active, separator, chromeDividers, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
|
|
112
|
+
declare function TabNavigator<Id extends string>({ id, label, tabs, active, separator, chromeDividers, barPresentation, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
|
|
92
113
|
|
|
93
|
-
export { TabNavigator, type TabNavigatorProps, type TabNavigatorTab };
|
|
114
|
+
export { TabNavigator, type TabNavigatorBarPresentation, type TabNavigatorProps, type TabNavigatorTab };
|
package/dist/tab-navigator.js
CHANGED
|
@@ -10,6 +10,7 @@ function TabNavigator({
|
|
|
10
10
|
active,
|
|
11
11
|
separator = "auto",
|
|
12
12
|
chromeDividers = "scroll",
|
|
13
|
+
barPresentation = "docked",
|
|
13
14
|
className = "",
|
|
14
15
|
slot
|
|
15
16
|
}) {
|
|
@@ -23,6 +24,7 @@ function TabNavigator({
|
|
|
23
24
|
"data-tab-scaffold-id": id,
|
|
24
25
|
"data-separator": separator,
|
|
25
26
|
"data-chrome-dividers": chromeDividers === "always" || chromeDividers === "none" ? chromeDividers : void 0,
|
|
27
|
+
"data-bar-presentation": barPresentation === "overlay" ? "overlay" : void 0,
|
|
26
28
|
slot,
|
|
27
29
|
children: [
|
|
28
30
|
/* @__PURE__ */ jsx("div", { class: "kui-tab-scaffold__scenes", children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/navigation/tab-navigator/tab-navigator.tsx"],"names":[],"mappings":"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","file":"tab-navigator.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { ensureSunkenTexture } from '../../../shared/styles/sunken-texture.js';\nimport { Badge } from '../../feedback/badge/badge.js';\nimport type { PaneAppearance } from '../../layout/pane/pane.js';\n\ninterface TabNavigatorTabBase<Id extends string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: KerfUiContent;\n /** Background of this scene's scrolling work surface. */\n appearance?: PaneAppearance;\n /** Add 8px to every side of a plain scene's scrolling content. */\n deepInset?: boolean;\n /** Opt into keyboard (`0`) or programmatic (`-1`) focus on this scene. */\n tabIndex?: 0 | -1;\n /** Keep the standard focus outline visible while this scene is active. */\n outlined?: boolean;\n}\n\n/** A tab with an optional count or short-status badge. */\ninterface TabNavigatorTabCountBadge {\n /**\n * Optional count or short status shown as a solid danger `Badge` at the\n * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,\n * or non-finite numbers render no badge. The visual badge is `aria-hidden`;\n * its meaning reaches assistive technology through `badgeLabel`.\n *\n * Pass `true` instead for the text-free dot (new content without a count).\n */\n badge?: string | number;\n /**\n * Localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"3 unread\"` → `\"Inbox, 3 unread\"`).\n * Defaults to the badge text itself. Ignored when no badge renders.\n */\n badgeLabel?: string;\n}\n\n/** A tab with the text-free dot badge (new content without a count). */\ninterface TabNavigatorTabDotBadge {\n /**\n * `true` shows a solid danger dot `Badge` at the top-trailing corner of the\n * tab icon — the iOS tab-bar dot for new content without a count.\n */\n badge: true;\n /**\n * Required localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"New activity\"` →\n * `\"Feed, New activity\"`). A dot has no text, so this is its only meaning.\n */\n badgeLabel: string;\n}\n\n/** One bottom-bar destination: its label, optional icon and badge, and content. */\nexport type TabNavigatorTab<Id extends string = string> =\n TabNavigatorTabBase<Id> &\n (TabNavigatorTabCountBadge | TabNavigatorTabDotBadge);\n\nexport interface TabNavigatorProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabNavigatorTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n /**\n * The bar's top separator. `auto` (default) draws it against a sunken active\n * work surface and otherwise follows `chromeDividers`; `hidden` suppresses\n * the line, including a scroll divider.\n */\n separator?: 'auto' | 'hidden';\n /**\n * The line over the tab bar, where it meets the active scene. `scroll`\n * (default) shows it only while more of the scene's content lies below —\n * never at the scroll end or when the content fits — once\n * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above\n * the scaffold; unwired, it does not show. `always` shows it without the\n * wiring; `none` suppresses that scroll divider. A sunken active work\n * surface still draws the separator unless `separator=\"hidden\"`. The line\n * is the bar's own 1px top border, so no state moves the bar or a tab.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab navigator: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-navigator`'s `wireTabNavigator`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabNavigator<Id extends string>({\n id,\n label,\n tabs,\n active,\n separator = 'auto',\n chromeDividers = 'scroll',\n className = '',\n slot,\n}: TabNavigatorProps<Id>) {\n if (tabs.some((tab) => tab.appearance === 'sunken')) ensureSunkenTexture();\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n data-separator={separator}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n slot={slot}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n data-appearance={tab.appearance === 'sunken' ? 'sunken' : undefined}\n data-deep-inset={tab.deepInset ? 'true' : undefined}\n data-outlined={\n tab.id === active && tab.outlined ? 'true' : undefined\n }\n role={tab.tabIndex === undefined ? undefined : 'tabpanel'}\n aria-label={tab.tabIndex === undefined ? undefined : tab.label}\n aria-hidden={String(tab.id !== active)}\n tabindex={\n tab.id === active\n ? tab.tabIndex\n : tab.tabIndex === undefined\n ? undefined\n : -1\n }\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => {\n const dot = tab.badge === true;\n const badgeText = dot ? undefined : normalizeBadge(tab.badge);\n const hasBadge = dot || badgeText !== undefined;\n const badge = hasBadge && (\n <span\n class=\"kui-tab-scaffold__tab-badge\"\n data-badge-kind={dot ? 'dot' : 'text'}\n >\n {badgeText === undefined ? (\n <Badge tone=\"danger\" size=\"dot\" ariaHidden />\n ) : (\n <Badge\n tone=\"danger\"\n appearance=\"solid\"\n size=\"compact\"\n ariaHidden\n >\n {badgeText}\n </Badge>\n )}\n </span>\n );\n // A dot has no text fallback: without a usable badgeLabel (reachable\n // only from untyped callers) the tab keeps its plain accessible name.\n const badgeLabel = hasBadge\n ? tab.badgeLabel?.trim() || badgeText\n : undefined;\n return (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n aria-label={\n badgeLabel === undefined\n ? undefined\n : `${tab.label}, ${badgeLabel}`\n }\n data-has-badge={hasBadge ? 'true' : undefined}\n >\n {tab.icon ? (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n {badge}\n </span>\n ) : (\n badge\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </section>\n );\n}\n\nfunction normalizeBadge(\n badge: string | number | undefined,\n): string | undefined {\n if (typeof badge === 'number')\n return Number.isFinite(badge) ? String(badge) : undefined;\n if (typeof badge === 'string' && badge.trim()) return badge.trim();\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/navigation/tab-navigator/tab-navigator.tsx"],"names":[],"mappings":"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","file":"tab-navigator.js","sourcesContent":["import type { SafeHtml } from 'kerfjs';\n\nimport type { KerfUiContent } from '../../../shared/content/semantic-content.js';\nimport { ensureSunkenTexture } from '../../../shared/styles/sunken-texture.js';\nimport { Badge } from '../../feedback/badge/badge.js';\nimport type { PaneAppearance } from '../../layout/pane/pane.js';\n\ninterface TabNavigatorTabBase<Id extends string> {\n id: Id;\n label: string;\n /** Decorative icon shown above the label in the bottom bar. */\n icon?: SafeHtml;\n /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */\n content: KerfUiContent;\n /** Background of this scene's scrolling work surface. */\n appearance?: PaneAppearance;\n /** Add 8px to every side of a plain scene's scrolling content. */\n deepInset?: boolean;\n /** Opt into keyboard (`0`) or programmatic (`-1`) focus on this scene. */\n tabIndex?: 0 | -1;\n /** Keep the standard focus outline visible while this scene is active. */\n outlined?: boolean;\n}\n\n/** A tab with an optional count or short-status badge. */\ninterface TabNavigatorTabCountBadge {\n /**\n * Optional count or short status shown as a solid danger `Badge` at the\n * top-trailing corner of the tab icon (the iOS tab-bar badge). Omitted, `''`,\n * or non-finite numbers render no badge. The visual badge is `aria-hidden`;\n * its meaning reaches assistive technology through `badgeLabel`.\n *\n * Pass `true` instead for the text-free dot (new content without a count).\n */\n badge?: string | number;\n /**\n * Localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"3 unread\"` → `\"Inbox, 3 unread\"`).\n * Defaults to the badge text itself. Ignored when no badge renders.\n */\n badgeLabel?: string;\n}\n\n/** A tab with the text-free dot badge (new content without a count). */\ninterface TabNavigatorTabDotBadge {\n /**\n * `true` shows a solid danger dot `Badge` at the top-trailing corner of the\n * tab icon — the iOS tab-bar dot for new content without a count.\n */\n badge: true;\n /**\n * Required localized phrase folded into the tab's accessible name as\n * `\"<label>, <badgeLabel>\"` (for example `\"New activity\"` →\n * `\"Feed, New activity\"`). A dot has no text, so this is its only meaning.\n */\n badgeLabel: string;\n}\n\n/** One bottom-bar destination: its label, optional icon and badge, and content. */\nexport type TabNavigatorTab<Id extends string = string> =\n TabNavigatorTabBase<Id> &\n (TabNavigatorTabCountBadge | TabNavigatorTabDotBadge);\n\n/**\n * How a {@link TabNavigator}'s tab bar relates to the active scene: `docked`\n * below it, or `overlay` laid over its bottom edge on the translucent chrome\n * material, so the scene's content scrolls visibly beneath the bar.\n */\nexport type TabNavigatorBarPresentation = 'docked' | 'overlay';\n\nexport interface TabNavigatorProps<Id extends string = string> {\n id: string;\n /** Accessible name for the tab bar. */\n label: string;\n tabs: readonly TabNavigatorTab<Id>[];\n /** The controlled active tab id (the app owns selection). */\n active: NoInfer<Id>;\n /**\n * The bar's top separator. `auto` (default) draws it against a sunken active\n * work surface and otherwise follows `chromeDividers`; `hidden` suppresses\n * the line, including a scroll divider.\n */\n separator?: 'auto' | 'hidden';\n /**\n * The line over the tab bar, where it meets the active scene. `scroll`\n * (default) shows it only while more of the scene's content lies below —\n * never at the scroll end or when the content fits — once\n * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above\n * the scaffold; unwired, it does not show. `always` shows it without the\n * wiring; `none` suppresses that scroll divider. A sunken active work\n * surface still draws the separator unless `separator=\"hidden\"`. The line\n * is the bar's own 1px top border, so no state moves the bar or a tab.\n */\n chromeDividers?: 'scroll' | 'always' | 'none';\n /**\n * `docked` (default) gives the tab bar its own band below the scenes.\n * `overlay` lays it over the active scene's bottom edge on the translucent\n * chrome material (opaque under reduced transparency, increased contrast,\n * or without `backdrop-filter`; `Canvas` in forced colors), so content\n * scrolls visibly beneath it, as under an iOS tab bar. `wireTabNavigator`\n * measures the live bar (bottom safe area included) and the scenes hand\n * its height to their content as the block-end `--kui-edge-inset-*`\n * context, so a plain scene, a sole `Pane`, or a `NavStack` (and its own\n * bottom toolbar, which then sits above the bar) rests its last item clear\n * of it. Until then it stays docked. Unselected tab labels lift halfway\n * toward the normal text color to keep AA over the content beneath.\n */\n barPresentation?: TabNavigatorBarPresentation;\n className?: string;\n /** Native named-slot assignment when composed inside a web component. */\n slot?: string;\n}\n\n/**\n * A mobile-first, iOS-like bottom tab navigator: a bottom tab bar that switches\n * between major sections, each tab keeping its own content (usually a `NavStack`)\n * mounted so its stack and scroll survive a switch. Controlled — the app owns\n * `active`; wire selection with `@kerfjs/ui/wire-tab-navigator`'s `wireTabNavigator`.\n * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of\n * a bottom bar. See `docs/23-app-layouts.md` §3.4.\n */\nexport function TabNavigator<Id extends string>({\n id,\n label,\n tabs,\n active,\n separator = 'auto',\n chromeDividers = 'scroll',\n barPresentation = 'docked',\n className = '',\n slot,\n}: TabNavigatorProps<Id>) {\n if (tabs.some((tab) => tab.appearance === 'sunken')) ensureSunkenTexture();\n return (\n <section\n class={`kui-tab-scaffold ${className}`.trim()}\n id={id}\n data-component=\"tab-scaffold\"\n data-tab-scaffold-id={id}\n data-separator={separator}\n data-chrome-dividers={\n chromeDividers === 'always' || chromeDividers === 'none'\n ? chromeDividers\n : undefined\n }\n data-bar-presentation={\n barPresentation === 'overlay' ? 'overlay' : undefined\n }\n slot={slot}\n >\n <div class=\"kui-tab-scaffold__scenes\">\n {tabs.map((tab) => (\n <div\n class=\"kui-tab-scaffold__scene\"\n data-tab-scaffold-scene={tab.id}\n data-active={String(tab.id === active)}\n data-appearance={tab.appearance === 'sunken' ? 'sunken' : undefined}\n data-deep-inset={tab.deepInset ? 'true' : undefined}\n data-outlined={\n tab.id === active && tab.outlined ? 'true' : undefined\n }\n role={tab.tabIndex === undefined ? undefined : 'tabpanel'}\n aria-label={tab.tabIndex === undefined ? undefined : tab.label}\n aria-hidden={String(tab.id !== active)}\n tabindex={\n tab.id === active\n ? tab.tabIndex\n : tab.tabIndex === undefined\n ? undefined\n : -1\n }\n >\n {tab.content}\n </div>\n ))}\n </div>\n <nav class=\"kui-tab-scaffold__bar\" role=\"tablist\" aria-label={label}>\n {tabs.map((tab) => {\n const dot = tab.badge === true;\n const badgeText = dot ? undefined : normalizeBadge(tab.badge);\n const hasBadge = dot || badgeText !== undefined;\n const badge = hasBadge && (\n <span\n class=\"kui-tab-scaffold__tab-badge\"\n data-badge-kind={dot ? 'dot' : 'text'}\n >\n {badgeText === undefined ? (\n <Badge tone=\"danger\" size=\"dot\" ariaHidden />\n ) : (\n <Badge\n tone=\"danger\"\n appearance=\"solid\"\n size=\"compact\"\n ariaHidden\n >\n {badgeText}\n </Badge>\n )}\n </span>\n );\n // A dot has no text fallback: without a usable badgeLabel (reachable\n // only from untyped callers) the tab keeps its plain accessible name.\n const badgeLabel = hasBadge\n ? tab.badgeLabel?.trim() || badgeText\n : undefined;\n return (\n <button\n type=\"button\"\n class=\"kui-tab-scaffold__tab\"\n role=\"tab\"\n data-tab-scaffold-tab={tab.id}\n aria-selected={String(tab.id === active)}\n tabindex={tab.id === active ? '0' : '-1'}\n aria-label={\n badgeLabel === undefined\n ? undefined\n : `${tab.label}, ${badgeLabel}`\n }\n data-has-badge={hasBadge ? 'true' : undefined}\n >\n {tab.icon ? (\n <span class=\"kui-tab-scaffold__tab-icon\" aria-hidden=\"true\">\n {tab.icon}\n {badge}\n </span>\n ) : (\n badge\n )}\n <span class=\"kui-tab-scaffold__tab-label\">{tab.label}</span>\n </button>\n );\n })}\n </nav>\n </section>\n );\n}\n\nfunction normalizeBadge(\n badge: string | number | undefined,\n): string | undefined {\n if (typeof badge === 'number')\n return Number.isFinite(badge) ? String(badge) : undefined;\n if (typeof badge === 'string' && badge.trim()) return badge.trim();\n return undefined;\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, k as TokenSearchTrailingAction, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-model-
|
|
1
|
+
export { T as TokenSearchEditorAttributes, a as TokenSearchField, b as TokenSearchFieldProps, c as TokenSearchFieldValue, j as TokenSearchToken, k as TokenSearchTrailingAction, l as TokenSearchTrailingActionAttributes, p as placeTokenSearchCaret, r as readTokenSearchField } from './token-search-model-aYR0YAei.js';
|
|
2
2
|
import 'kerfjs';
|
|
3
3
|
import './semantic-content-BbzjvSu9.js';
|
|
@@ -7,12 +7,42 @@ interface TokenSearchToken {
|
|
|
7
7
|
offset?: number;
|
|
8
8
|
accessibleLabel?: string;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Domain `data-*` metadata for a trailing action button. The component owns
|
|
12
|
+
* `data-action` (pass `action`) and its state attributes.
|
|
13
|
+
*/
|
|
14
|
+
type TokenSearchTrailingActionAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
15
|
+
'data-action'?: never;
|
|
16
|
+
'data-component'?: never;
|
|
17
|
+
'data-key'?: never;
|
|
18
|
+
}>;
|
|
19
|
+
interface TokenSearchTrailingActionBase {
|
|
20
|
+
/** Decorative glyph, such as a `LucideIcon`. */
|
|
11
21
|
icon: SafeHtml;
|
|
22
|
+
/** Accessible name and tooltip, in title style ("Search Help"). */
|
|
12
23
|
label: string;
|
|
24
|
+
/** Delegated `data-action` value. */
|
|
13
25
|
action: string;
|
|
14
26
|
id?: string;
|
|
27
|
+
/** `aria-controls`: the id of the surface this button opens or toggles. */
|
|
28
|
+
controls?: string;
|
|
29
|
+
/** `aria-haspopup` for a button that opens a dialog, menu, or listbox. */
|
|
30
|
+
haspopup?: 'dialog' | 'menu' | 'listbox' | 'true';
|
|
31
|
+
/** Domain `data-*` metadata for the app's delegated handler. */
|
|
32
|
+
attributes?: TokenSearchTrailingActionAttributes;
|
|
15
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* A compact icon button in the field's trailing slot, sized and styled like
|
|
36
|
+
* the clear button. Pass `expanded` for a disclosure (a help surface it opens)
|
|
37
|
+
* or `pressed` for a toggle; the button shows the state with its hover fill.
|
|
38
|
+
*/
|
|
39
|
+
type TokenSearchTrailingAction = TokenSearchTrailingActionBase & ({
|
|
40
|
+
expanded?: boolean;
|
|
41
|
+
pressed?: never;
|
|
42
|
+
} | {
|
|
43
|
+
expanded?: never;
|
|
44
|
+
pressed?: boolean;
|
|
45
|
+
});
|
|
16
46
|
type TokenSearchEditorAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
|
|
17
47
|
'data-component'?: never;
|
|
18
48
|
'data-key'?: never;
|
|
@@ -151,4 +181,4 @@ interface TokenSearchModelOptions<Result> {
|
|
|
151
181
|
/** Opt-in state, token parsing, suggestions, and evaluation for TokenSearchField. */
|
|
152
182
|
declare function createTokenSearchModel<Result = unknown>({ rules, initial, evaluate, onSubmit, }?: TokenSearchModelOptions<Result>): TokenSearchModel<Result>;
|
|
153
183
|
|
|
154
|
-
export { type TokenSearchEditorAttributes as T, TokenSearchField as a, type TokenSearchFieldProps as b, type TokenSearchFieldValue as c, type TokenSearchModel as d, type TokenSearchModelOptions as e, type TokenSearchResolvedToken as f, type TokenSearchRule as g, type TokenSearchState as h, type TokenSearchSuggestion as i, type TokenSearchToken as j, type TokenSearchTrailingAction as k,
|
|
184
|
+
export { type TokenSearchEditorAttributes as T, TokenSearchField as a, type TokenSearchFieldProps as b, type TokenSearchFieldValue as c, type TokenSearchModel as d, type TokenSearchModelOptions as e, type TokenSearchResolvedToken as f, type TokenSearchRule as g, type TokenSearchState as h, type TokenSearchSuggestion as i, type TokenSearchToken as j, type TokenSearchTrailingAction as k, type TokenSearchTrailingActionAttributes as l, createTokenSearchModel as m, placeTokenSearchCaret as p, readTokenSearchField as r };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion,
|
|
1
|
+
export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchResolvedToken, g as TokenSearchRule, h as TokenSearchState, i as TokenSearchSuggestion, m as createTokenSearchModel } from './token-search-model-aYR0YAei.js';
|
|
2
2
|
import 'kerfjs';
|
|
3
3
|
import './semantic-content-BbzjvSu9.js';
|
package/dist/toolbar-text.js
CHANGED
package/dist/toolbar.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as kerfjs from 'kerfjs';
|
|
|
2
2
|
import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
|
|
3
3
|
import { S as Sides } from './sides-BPSWde0A.js';
|
|
4
4
|
import { PaneSeparatorSide } from './pane.js';
|
|
5
|
+
import './scroll-clearance-BikHljTc.js';
|
|
5
6
|
|
|
6
7
|
type ToolbarPosition = 'header' | 'footer';
|
|
7
8
|
/** Control-band density: `default` (60px with 44px groups) or `compact`. */
|
package/dist/value-table.js
CHANGED
package/dist/wire-catalog.d.ts
CHANGED
|
@@ -4,13 +4,14 @@ import './toolbar.js';
|
|
|
4
4
|
import './semantic-content-BbzjvSu9.js';
|
|
5
5
|
import './sides-BPSWde0A.js';
|
|
6
6
|
import './pane.js';
|
|
7
|
+
import './scroll-clearance-BikHljTc.js';
|
|
7
8
|
import './workbench.js';
|
|
8
|
-
import './nav-stack-
|
|
9
|
+
import './nav-stack-VXTumzKa.js';
|
|
9
10
|
import './list.js';
|
|
10
11
|
import './extension-attributes-mu8MFUl0.js';
|
|
11
12
|
import './flex-alignment-4ms8ZbV8.js';
|
|
12
13
|
import './css-values.js';
|
|
13
|
-
import './panel-toolbar-
|
|
14
|
+
import './panel-toolbar-vg6Ir5Dy.js';
|
|
14
15
|
import './lucide-icon.js';
|
|
15
16
|
import 'lucide';
|
|
16
17
|
import './toolbar-text.js';
|
package/dist/wire-catalog.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { wireWorkbench } from './chunk-QLA25V2K.js';
|
|
2
|
+
import { wireScrollDividers } from './chunk-CXZXHZTR.js';
|
|
2
3
|
|
|
3
|
-
import { wireScrollDividers } from './chunk-6STQXRT4.js';
|
|
4
4
|
import { loadUxReviewProject } from './chunk-6C6DLP3W.js';
|
|
5
5
|
|
|
6
|
-
import { readTokenSearchField } from './chunk-
|
|
6
|
+
import { readTokenSearchField } from './chunk-MF6ZUUJZ.js';
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type Root = HTMLElement | Document;
|
|
2
|
+
/**
|
|
3
|
+
* Enter-to-send for every `Composer` rendered with `submitOnEnter` below
|
|
4
|
+
* root. In its field, Enter (alone or with Cmd or Ctrl) activates the
|
|
5
|
+
* composer's first trailing action, so a keyboard send runs the same
|
|
6
|
+
* delegated handler as a click. Shift+Enter and Alt+Enter insert a newline.
|
|
7
|
+
* Nothing is sent, and no newline is inserted, when the message is empty or
|
|
8
|
+
* whitespace-only, the key is auto-repeating, or the first action is
|
|
9
|
+
* disabled, loading, or `aria-disabled`. An Enter that commits an IME
|
|
10
|
+
* composition (`isComposing`, keyCode 229, or between `compositionstart` and
|
|
11
|
+
* `compositionend`) is left to the input method. Dispose with the owning
|
|
12
|
+
* application.
|
|
13
|
+
*/
|
|
14
|
+
declare function wireComposers(root: Root): () => void;
|
|
15
|
+
|
|
16
|
+
export { wireComposers };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"wire-composers.js"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type Root = HTMLElement | Document;
|
|
2
|
+
/**
|
|
3
|
+
* Bring a keyboard-focused row of a `scrollable` List below `root` fully into
|
|
4
|
+
* view, focus ring included. Engines differ on how `focus()` scrolls a partly
|
|
5
|
+
* hidden row: Chromium scrolls it to the nearest edge plus scroll padding,
|
|
6
|
+
* Firefox waits until about half of it is hidden and then centers it, and
|
|
7
|
+
* WebKit leaves it where it is. On `focusin`, when the newly focused element
|
|
8
|
+
* matches `:focus-visible` and its ring crosses the nearest scrollable List's
|
|
9
|
+
* clip, this calls `scrollIntoView({ block: 'nearest', inline: 'nearest' })`,
|
|
10
|
+
* which honors the List's ring-room scroll padding in every engine. Pointer
|
|
11
|
+
* focus is left alone, so a click never scrolls the row out from under the
|
|
12
|
+
* pointer. Returns a disposer.
|
|
13
|
+
*/
|
|
14
|
+
declare function wireListFocusScroll(root: Root): () => void;
|
|
15
|
+
|
|
16
|
+
export { wireListFocusScroll };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"wire-list-focus-scroll.js"}
|
package/dist/wire-nav-stack.js
CHANGED
|
@@ -2,6 +2,27 @@ import { delegate } from 'kerfjs';
|
|
|
2
2
|
|
|
3
3
|
// src/components/navigation/nav-stack/wiring/wire-nav-stack.ts
|
|
4
4
|
var DEFAULT_DURATION = 200;
|
|
5
|
+
var CHROME_OVERLAY = "data-chrome-overlay";
|
|
6
|
+
var BOTTOM_TOOLBAR_OVERLAY = "data-bottom-toolbar-overlay";
|
|
7
|
+
var OVERLAY_EDGES = [
|
|
8
|
+
{
|
|
9
|
+
presentation: "data-chrome-presentation",
|
|
10
|
+
element: ":scope > [data-nav-stack-chrome]:not([data-nav-chrome-copy])",
|
|
11
|
+
blockSize: "--_kui-nav-stack-chrome-block-size",
|
|
12
|
+
scrollbarInlineSize: "--_kui-nav-stack-scrollbar-inline-size",
|
|
13
|
+
// A Pane header lies beneath the chrome and starts its content below it.
|
|
14
|
+
paneChrome: ":scope > :is(.kui-pane__header, .kui-pane__toolbar)"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
presentation: "data-bottom-toolbar-presentation",
|
|
18
|
+
element: ":scope > [data-nav-stack-bottom]:not([data-nav-chrome-copy])",
|
|
19
|
+
blockSize: "--_kui-nav-stack-bottom-block-size",
|
|
20
|
+
scrollbarInlineSize: "--_kui-nav-stack-bottom-scrollbar-inline-size",
|
|
21
|
+
// A Pane footer lies beneath the toolbar and ends its content above it.
|
|
22
|
+
paneChrome: ":scope > .kui-pane__footer"
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
var NESTED_LAYOUT = ["nav-stack", "split-view", "workbench", "tab-scaffold"].map((name) => `[data-component="${name}"]`).join(", ");
|
|
5
26
|
var FOCUSABLE_SELECTOR = [
|
|
6
27
|
"a[href]",
|
|
7
28
|
"button:not([disabled])",
|
|
@@ -144,6 +165,109 @@ function wireNavStack(root, options = {}) {
|
|
|
144
165
|
}
|
|
145
166
|
targetView.focus({ preventScroll: true });
|
|
146
167
|
};
|
|
168
|
+
const edges = OVERLAY_EDGES.map((edge) => [
|
|
169
|
+
edge,
|
|
170
|
+
{ covers: false }
|
|
171
|
+
]);
|
|
172
|
+
const measuredEdge = (state) => state.element !== void 0 && state.size !== void 0;
|
|
173
|
+
let measuredScroller;
|
|
174
|
+
let scrollbarSize = 0;
|
|
175
|
+
const writeProperty = (name, value) => {
|
|
176
|
+
if (section.style.getPropertyValue(name) === value) return;
|
|
177
|
+
if (value) section.style.setProperty(name, value);
|
|
178
|
+
else section.style.removeProperty(name);
|
|
179
|
+
};
|
|
180
|
+
const publishOverlay = () => {
|
|
181
|
+
for (const [edge, state] of edges) {
|
|
182
|
+
const measured = measuredEdge(state);
|
|
183
|
+
writeProperty(edge.blockSize, measured ? `${state.size}px` : "");
|
|
184
|
+
writeProperty(
|
|
185
|
+
edge.scrollbarInlineSize,
|
|
186
|
+
measured && state.covers && scrollbarSize > 0 ? `${scrollbarSize}px` : ""
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
if (section.getAttribute("style") === "") section.removeAttribute("style");
|
|
190
|
+
const [top, bottom] = edges.map(([, state]) => measuredEdge(state));
|
|
191
|
+
if (top && section.getAttribute(CHROME_OVERLAY) !== "measured")
|
|
192
|
+
section.setAttribute(CHROME_OVERLAY, "measured");
|
|
193
|
+
else if (!top && section.hasAttribute(CHROME_OVERLAY))
|
|
194
|
+
section.removeAttribute(CHROME_OVERLAY);
|
|
195
|
+
if (bottom && section.getAttribute(BOTTOM_TOOLBAR_OVERLAY) !== "measured")
|
|
196
|
+
section.setAttribute(BOTTOM_TOOLBAR_OVERLAY, "measured");
|
|
197
|
+
else if (!bottom && section.hasAttribute(BOTTOM_TOOLBAR_OVERLAY))
|
|
198
|
+
section.removeAttribute(BOTTOM_TOOLBAR_OVERLAY);
|
|
199
|
+
};
|
|
200
|
+
const activeScroller = () => {
|
|
201
|
+
const top = topView(viewport);
|
|
202
|
+
const only = top?.children.length === 1 ? top.children[0] : void 0;
|
|
203
|
+
if (!only) return { scroller: top };
|
|
204
|
+
if (only.matches(".kui-pane"))
|
|
205
|
+
return {
|
|
206
|
+
scroller: only.querySelector(":scope > .kui-pane__content") ?? void 0,
|
|
207
|
+
pane: only
|
|
208
|
+
};
|
|
209
|
+
return { scroller: only.matches(NESTED_LAYOUT) ? void 0 : top };
|
|
210
|
+
};
|
|
211
|
+
const measureScrollbar = () => {
|
|
212
|
+
const scroller = measuredScroller;
|
|
213
|
+
if (!scroller) {
|
|
214
|
+
scrollbarSize = 0;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const style = view.getComputedStyle(scroller);
|
|
218
|
+
scrollbarSize = Math.max(
|
|
219
|
+
0,
|
|
220
|
+
scroller.offsetWidth - scroller.clientWidth - (Number.parseFloat(style.borderLeftWidth) || 0) - (Number.parseFloat(style.borderRightWidth) || 0)
|
|
221
|
+
);
|
|
222
|
+
};
|
|
223
|
+
const chromeObserver = view.ResizeObserver ? new view.ResizeObserver((entries) => {
|
|
224
|
+
for (const entry of entries) {
|
|
225
|
+
const state = edges.find(
|
|
226
|
+
([, edgeState]) => edgeState.element === entry.target
|
|
227
|
+
)?.[1];
|
|
228
|
+
if (state)
|
|
229
|
+
state.size = entry.borderBoxSize?.[0]?.blockSize ?? entry.target.getBoundingClientRect().height;
|
|
230
|
+
else if (entry.target === measuredScroller) measureScrollbar();
|
|
231
|
+
}
|
|
232
|
+
publishOverlay();
|
|
233
|
+
}) : void 0;
|
|
234
|
+
const syncOverlay = () => {
|
|
235
|
+
for (const [edge, state] of edges) {
|
|
236
|
+
const element = section.getAttribute(edge.presentation) === "overlay" ? section.querySelector(edge.element) ?? void 0 : void 0;
|
|
237
|
+
if (element === state.element) continue;
|
|
238
|
+
if (state.element) chromeObserver?.unobserve(state.element);
|
|
239
|
+
state.element = element;
|
|
240
|
+
if (!element) state.size = void 0;
|
|
241
|
+
else {
|
|
242
|
+
if (state.size === void 0 || !chromeObserver)
|
|
243
|
+
state.size = element.getBoundingClientRect().height;
|
|
244
|
+
chromeObserver?.observe(element, { box: "border-box" });
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const { scroller, pane } = activeScroller();
|
|
248
|
+
for (const [edge, state] of edges)
|
|
249
|
+
state.covers = state.element !== void 0 && scroller !== void 0 && !pane?.querySelector(edge.paneChrome);
|
|
250
|
+
const covered = edges.some(([, state]) => state.covers) ? scroller : void 0;
|
|
251
|
+
if (covered !== measuredScroller) {
|
|
252
|
+
if (measuredScroller) chromeObserver?.unobserve(measuredScroller);
|
|
253
|
+
measuredScroller = covered;
|
|
254
|
+
measureScrollbar();
|
|
255
|
+
if (measuredScroller) chromeObserver?.observe(measuredScroller);
|
|
256
|
+
}
|
|
257
|
+
publishOverlay();
|
|
258
|
+
};
|
|
259
|
+
const overlayObserver = new MutationObserver(syncOverlay);
|
|
260
|
+
overlayObserver.observe(section, {
|
|
261
|
+
childList: true,
|
|
262
|
+
attributes: true,
|
|
263
|
+
attributeFilter: [
|
|
264
|
+
...OVERLAY_EDGES.map((edge) => edge.presentation),
|
|
265
|
+
CHROME_OVERLAY,
|
|
266
|
+
BOTTOM_TOOLBAR_OVERLAY,
|
|
267
|
+
"style"
|
|
268
|
+
]
|
|
269
|
+
});
|
|
270
|
+
syncOverlay();
|
|
147
271
|
const onFocusIn = (event) => rememberFocusedView(event.target);
|
|
148
272
|
section.addEventListener("focusin", onFocusIn);
|
|
149
273
|
rememberFocusedView(section.ownerDocument.activeElement);
|
|
@@ -231,6 +355,7 @@ function wireNavStack(root, options = {}) {
|
|
|
231
355
|
focusInto(top);
|
|
232
356
|
}
|
|
233
357
|
activeKey = currentKey;
|
|
358
|
+
syncOverlay();
|
|
234
359
|
});
|
|
235
360
|
observer.observe(viewport, {
|
|
236
361
|
childList: true,
|
|
@@ -242,6 +367,16 @@ function wireNavStack(root, options = {}) {
|
|
|
242
367
|
disposeBack();
|
|
243
368
|
section.removeEventListener("focusin", onFocusIn);
|
|
244
369
|
observer.disconnect();
|
|
370
|
+
overlayObserver.disconnect();
|
|
371
|
+
chromeObserver?.disconnect();
|
|
372
|
+
for (const [, state] of edges) {
|
|
373
|
+
state.element = void 0;
|
|
374
|
+
state.size = void 0;
|
|
375
|
+
state.covers = false;
|
|
376
|
+
}
|
|
377
|
+
measuredScroller = void 0;
|
|
378
|
+
scrollbarSize = 0;
|
|
379
|
+
publishOverlay();
|
|
245
380
|
finishTransition();
|
|
246
381
|
for (const [element, previousTabIndex] of generatedFallbacks) {
|
|
247
382
|
if (!element.isConnected || element.tabIndex !== -1) continue;
|