@entifix/react-controls 0.1.0-0
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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/i18n/catalog/en.d.ts +10 -0
- package/dist/i18n/catalog/en.d.ts.map +1 -0
- package/dist/i18n/catalog/en.js +211 -0
- package/dist/i18n/catalog/en.js.map +1 -0
- package/dist/i18n/catalog/es.d.ts +275 -0
- package/dist/i18n/catalog/es.d.ts.map +1 -0
- package/dist/i18n/catalog/es.js +261 -0
- package/dist/i18n/catalog/es.js.map +1 -0
- package/dist/i18n/catalog/index.d.ts +403 -0
- package/dist/i18n/catalog/index.d.ts.map +1 -0
- package/dist/i18n/catalog/index.js +23 -0
- package/dist/i18n/catalog/index.js.map +1 -0
- package/dist/i18n/entity-labels.d.ts +29 -0
- package/dist/i18n/entity-labels.d.ts.map +1 -0
- package/dist/i18n/entity-labels.js +49 -0
- package/dist/i18n/entity-labels.js.map +1 -0
- package/dist/i18n/fallback-catalogs.d.ts +5 -0
- package/dist/i18n/fallback-catalogs.d.ts.map +1 -0
- package/dist/i18n/fallback-catalogs.js +34 -0
- package/dist/i18n/fallback-catalogs.js.map +1 -0
- package/dist/i18n/i18n-context.d.ts +62 -0
- package/dist/i18n/i18n-context.d.ts.map +1 -0
- package/dist/i18n/i18n-context.js +128 -0
- package/dist/i18n/i18n-context.js.map +1 -0
- package/dist/i18n/index.d.ts +5 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +6 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/i18n/spec-support/catalogs.d.ts +2 -0
- package/dist/i18n/spec-support/catalogs.d.ts.map +1 -0
- package/dist/i18n/spec-support/catalogs.js +142 -0
- package/dist/i18n/spec-support/catalogs.js.map +1 -0
- package/dist/i18next/index.d.ts +20 -0
- package/dist/i18next/index.d.ts.map +1 -0
- package/dist/i18next/index.js +60 -0
- package/dist/i18next/index.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/preferences/index.d.ts +7 -0
- package/dist/preferences/index.d.ts.map +1 -0
- package/dist/preferences/index.js +8 -0
- package/dist/preferences/index.js.map +1 -0
- package/dist/preferences/indexeddb-ui-preferences-state.d.ts +16 -0
- package/dist/preferences/indexeddb-ui-preferences-state.d.ts.map +1 -0
- package/dist/preferences/indexeddb-ui-preferences-state.js +50 -0
- package/dist/preferences/indexeddb-ui-preferences-state.js.map +1 -0
- package/dist/preferences/local-storage-ui-preferences-state.d.ts +16 -0
- package/dist/preferences/local-storage-ui-preferences-state.d.ts.map +1 -0
- package/dist/preferences/local-storage-ui-preferences-state.js +51 -0
- package/dist/preferences/local-storage-ui-preferences-state.js.map +1 -0
- package/dist/preferences/ui-preferences-context.d.ts +16 -0
- package/dist/preferences/ui-preferences-context.d.ts.map +1 -0
- package/dist/preferences/ui-preferences-context.js +31 -0
- package/dist/preferences/ui-preferences-context.js.map +1 -0
- package/dist/preferences/ui-preferences-state.d.ts +23 -0
- package/dist/preferences/ui-preferences-state.d.ts.map +1 -0
- package/dist/preferences/ui-preferences-state.js +5 -0
- package/dist/preferences/ui-preferences-state.js.map +1 -0
- package/dist/preferences/use-ui-preference.d.ts +20 -0
- package/dist/preferences/use-ui-preference.d.ts.map +1 -0
- package/dist/preferences/use-ui-preference.js +72 -0
- package/dist/preferences/use-ui-preference.js.map +1 -0
- package/dist/preferences/use-viewport-mode.d.ts +33 -0
- package/dist/preferences/use-viewport-mode.d.ts.map +1 -0
- package/dist/preferences/use-viewport-mode.js +53 -0
- package/dist/preferences/use-viewport-mode.js.map +1 -0
- package/dist/primitives.d.ts +25 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +54 -0
- package/dist/primitives.js.map +1 -0
- package/dist/theme/index.d.ts +3 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +4 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/theme-context.d.ts +26 -0
- package/dist/theme/theme-context.d.ts.map +1 -0
- package/dist/theme/theme-context.js +79 -0
- package/dist/theme/theme-context.js.map +1 -0
- package/dist/theme/types.d.ts +22 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +6 -0
- package/dist/theme/types.js.map +1 -0
- package/dist/ui/actions/action-surfaces.d.ts +59 -0
- package/dist/ui/actions/action-surfaces.d.ts.map +1 -0
- package/dist/ui/actions/action-surfaces.js +109 -0
- package/dist/ui/actions/action-surfaces.js.map +1 -0
- package/dist/ui/actions/index.d.ts +2 -0
- package/dist/ui/actions/index.d.ts.map +1 -0
- package/dist/ui/actions/index.js +3 -0
- package/dist/ui/actions/index.js.map +1 -0
- package/dist/ui/atoms/button/button-link.d.ts +27 -0
- package/dist/ui/atoms/button/button-link.d.ts.map +1 -0
- package/dist/ui/atoms/button/button-link.js +23 -0
- package/dist/ui/atoms/button/button-link.js.map +1 -0
- package/dist/ui/atoms/button/button-recipe.d.ts +19 -0
- package/dist/ui/atoms/button/button-recipe.d.ts.map +1 -0
- package/dist/ui/atoms/button/button-recipe.js +42 -0
- package/dist/ui/atoms/button/button-recipe.js.map +1 -0
- package/dist/ui/atoms/button/button.d.ts +7 -0
- package/dist/ui/atoms/button/button.d.ts.map +1 -0
- package/dist/ui/atoms/button/button.js +22 -0
- package/dist/ui/atoms/button/button.js.map +1 -0
- package/dist/ui/atoms/button/index.d.ts +4 -0
- package/dist/ui/atoms/button/index.d.ts.map +1 -0
- package/dist/ui/atoms/button/index.js +5 -0
- package/dist/ui/atoms/button/index.js.map +1 -0
- package/dist/ui/atoms/cell-value/cell-value.d.ts +12 -0
- package/dist/ui/atoms/cell-value/cell-value.d.ts.map +1 -0
- package/dist/ui/atoms/cell-value/cell-value.js +101 -0
- package/dist/ui/atoms/cell-value/cell-value.js.map +1 -0
- package/dist/ui/atoms/cell-value/index.d.ts +2 -0
- package/dist/ui/atoms/cell-value/index.d.ts.map +1 -0
- package/dist/ui/atoms/cell-value/index.js +3 -0
- package/dist/ui/atoms/cell-value/index.js.map +1 -0
- package/dist/ui/atoms/field/checkbox.d.ts +35 -0
- package/dist/ui/atoms/field/checkbox.d.ts.map +1 -0
- package/dist/ui/atoms/field/checkbox.js +46 -0
- package/dist/ui/atoms/field/checkbox.js.map +1 -0
- package/dist/ui/atoms/field/field.d.ts +4 -0
- package/dist/ui/atoms/field/field.d.ts.map +1 -0
- package/dist/ui/atoms/field/field.js +29 -0
- package/dist/ui/atoms/field/field.js.map +1 -0
- package/dist/ui/atoms/field/index.d.ts +3 -0
- package/dist/ui/atoms/field/index.d.ts.map +1 -0
- package/dist/ui/atoms/field/index.js +4 -0
- package/dist/ui/atoms/field/index.js.map +1 -0
- package/dist/ui/atoms/field-control/field-control.d.ts +50 -0
- package/dist/ui/atoms/field-control/field-control.d.ts.map +1 -0
- package/dist/ui/atoms/field-control/field-control.js +82 -0
- package/dist/ui/atoms/field-control/field-control.js.map +1 -0
- package/dist/ui/atoms/field-control/index.d.ts +2 -0
- package/dist/ui/atoms/field-control/index.d.ts.map +1 -0
- package/dist/ui/atoms/field-control/index.js +3 -0
- package/dist/ui/atoms/field-control/index.js.map +1 -0
- package/dist/ui/atoms/skeleton/index.d.ts +2 -0
- package/dist/ui/atoms/skeleton/index.d.ts.map +1 -0
- package/dist/ui/atoms/skeleton/index.js +3 -0
- package/dist/ui/atoms/skeleton/index.js.map +1 -0
- package/dist/ui/atoms/skeleton/skeleton.d.ts +21 -0
- package/dist/ui/atoms/skeleton/skeleton.d.ts.map +1 -0
- package/dist/ui/atoms/skeleton/skeleton.js +33 -0
- package/dist/ui/atoms/skeleton/skeleton.js.map +1 -0
- package/dist/ui/atoms/table/index.d.ts +2 -0
- package/dist/ui/atoms/table/index.d.ts.map +1 -0
- package/dist/ui/atoms/table/index.js +3 -0
- package/dist/ui/atoms/table/index.js.map +1 -0
- package/dist/ui/atoms/table/table.d.ts +30 -0
- package/dist/ui/atoms/table/table.d.ts.map +1 -0
- package/dist/ui/atoms/table/table.js +84 -0
- package/dist/ui/atoms/table/table.js.map +1 -0
- package/dist/ui/atoms/text/index.d.ts +2 -0
- package/dist/ui/atoms/text/index.d.ts.map +1 -0
- package/dist/ui/atoms/text/index.js +3 -0
- package/dist/ui/atoms/text/index.js.map +1 -0
- package/dist/ui/atoms/text/text.d.ts +86 -0
- package/dist/ui/atoms/text/text.d.ts.map +1 -0
- package/dist/ui/atoms/text/text.js +221 -0
- package/dist/ui/atoms/text/text.js.map +1 -0
- package/dist/ui/layout/_demo.d.ts +6 -0
- package/dist/ui/layout/_demo.d.ts.map +1 -0
- package/dist/ui/layout/_demo.js +11 -0
- package/dist/ui/layout/_demo.js.map +1 -0
- package/dist/ui/layout/_shared.d.ts +9 -0
- package/dist/ui/layout/_shared.d.ts.map +1 -0
- package/dist/ui/layout/_shared.js +30 -0
- package/dist/ui/layout/_shared.js.map +1 -0
- package/dist/ui/layout/box/box.d.ts +10 -0
- package/dist/ui/layout/box/box.d.ts.map +1 -0
- package/dist/ui/layout/box/box.js +28 -0
- package/dist/ui/layout/box/box.js.map +1 -0
- package/dist/ui/layout/box/index.d.ts +2 -0
- package/dist/ui/layout/box/index.d.ts.map +1 -0
- package/dist/ui/layout/box/index.js +3 -0
- package/dist/ui/layout/box/index.js.map +1 -0
- package/dist/ui/layout/center/center.d.ts +13 -0
- package/dist/ui/layout/center/center.d.ts.map +1 -0
- package/dist/ui/layout/center/center.js +22 -0
- package/dist/ui/layout/center/center.js.map +1 -0
- package/dist/ui/layout/center/index.d.ts +2 -0
- package/dist/ui/layout/center/index.d.ts.map +1 -0
- package/dist/ui/layout/center/index.js +3 -0
- package/dist/ui/layout/center/index.js.map +1 -0
- package/dist/ui/layout/cluster/cluster.d.ts +11 -0
- package/dist/ui/layout/cluster/cluster.d.ts.map +1 -0
- package/dist/ui/layout/cluster/cluster.js +19 -0
- package/dist/ui/layout/cluster/cluster.js.map +1 -0
- package/dist/ui/layout/cluster/index.d.ts +2 -0
- package/dist/ui/layout/cluster/index.d.ts.map +1 -0
- package/dist/ui/layout/cluster/index.js +3 -0
- package/dist/ui/layout/cluster/index.js.map +1 -0
- package/dist/ui/layout/cover/cover.d.ts +26 -0
- package/dist/ui/layout/cover/cover.d.ts.map +1 -0
- package/dist/ui/layout/cover/cover.js +57 -0
- package/dist/ui/layout/cover/cover.js.map +1 -0
- package/dist/ui/layout/cover/index.d.ts +2 -0
- package/dist/ui/layout/cover/index.d.ts.map +1 -0
- package/dist/ui/layout/cover/index.js +3 -0
- package/dist/ui/layout/cover/index.js.map +1 -0
- package/dist/ui/layout/grid/grid.d.ts +14 -0
- package/dist/ui/layout/grid/grid.d.ts.map +1 -0
- package/dist/ui/layout/grid/grid.js +25 -0
- package/dist/ui/layout/grid/grid.js.map +1 -0
- package/dist/ui/layout/grid/index.d.ts +2 -0
- package/dist/ui/layout/grid/index.d.ts.map +1 -0
- package/dist/ui/layout/grid/index.js +3 -0
- package/dist/ui/layout/grid/index.js.map +1 -0
- package/dist/ui/layout/sidebar/index.d.ts +2 -0
- package/dist/ui/layout/sidebar/index.d.ts.map +1 -0
- package/dist/ui/layout/sidebar/index.js +3 -0
- package/dist/ui/layout/sidebar/index.js.map +1 -0
- package/dist/ui/layout/sidebar/sidebar.d.ts +33 -0
- package/dist/ui/layout/sidebar/sidebar.d.ts.map +1 -0
- package/dist/ui/layout/sidebar/sidebar.js +54 -0
- package/dist/ui/layout/sidebar/sidebar.js.map +1 -0
- package/dist/ui/layout/switcher/index.d.ts +2 -0
- package/dist/ui/layout/switcher/index.d.ts.map +1 -0
- package/dist/ui/layout/switcher/index.js +3 -0
- package/dist/ui/layout/switcher/index.js.map +1 -0
- package/dist/ui/layout/switcher/switcher.d.ts +15 -0
- package/dist/ui/layout/switcher/switcher.d.ts.map +1 -0
- package/dist/ui/layout/switcher/switcher.js +26 -0
- package/dist/ui/layout/switcher/switcher.js.map +1 -0
- package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts +27 -0
- package/dist/ui/molecules/breadcrumbs/breadcrumbs.d.ts.map +1 -0
- package/dist/ui/molecules/breadcrumbs/breadcrumbs.js +50 -0
- package/dist/ui/molecules/breadcrumbs/breadcrumbs.js.map +1 -0
- package/dist/ui/molecules/breadcrumbs/index.d.ts +2 -0
- package/dist/ui/molecules/breadcrumbs/index.d.ts.map +1 -0
- package/dist/ui/molecules/breadcrumbs/index.js +3 -0
- package/dist/ui/molecules/breadcrumbs/index.js.map +1 -0
- package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.d.ts +47 -0
- package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.d.ts.map +1 -0
- package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js +63 -0
- package/dist/ui/molecules/bulk-action-bar/bulk-action-bar.js.map +1 -0
- package/dist/ui/molecules/bulk-action-bar/index.d.ts +2 -0
- package/dist/ui/molecules/bulk-action-bar/index.d.ts.map +1 -0
- package/dist/ui/molecules/bulk-action-bar/index.js +3 -0
- package/dist/ui/molecules/bulk-action-bar/index.js.map +1 -0
- package/dist/ui/molecules/bulk-result/bulk-result.d.ts +31 -0
- package/dist/ui/molecules/bulk-result/bulk-result.d.ts.map +1 -0
- package/dist/ui/molecules/bulk-result/bulk-result.js +86 -0
- package/dist/ui/molecules/bulk-result/bulk-result.js.map +1 -0
- package/dist/ui/molecules/bulk-result/index.d.ts +2 -0
- package/dist/ui/molecules/bulk-result/index.d.ts.map +1 -0
- package/dist/ui/molecules/bulk-result/index.js +3 -0
- package/dist/ui/molecules/bulk-result/index.js.map +1 -0
- package/dist/ui/molecules/card/card.d.ts +5 -0
- package/dist/ui/molecules/card/card.d.ts.map +1 -0
- package/dist/ui/molecules/card/card.js +14 -0
- package/dist/ui/molecules/card/card.js.map +1 -0
- package/dist/ui/molecules/card/index.d.ts +2 -0
- package/dist/ui/molecules/card/index.d.ts.map +1 -0
- package/dist/ui/molecules/card/index.js +3 -0
- package/dist/ui/molecules/card/index.js.map +1 -0
- package/dist/ui/molecules/column-settings/column-settings.d.ts +29 -0
- package/dist/ui/molecules/column-settings/column-settings.d.ts.map +1 -0
- package/dist/ui/molecules/column-settings/column-settings.js +117 -0
- package/dist/ui/molecules/column-settings/column-settings.js.map +1 -0
- package/dist/ui/molecules/column-settings/index.d.ts +2 -0
- package/dist/ui/molecules/column-settings/index.d.ts.map +1 -0
- package/dist/ui/molecules/column-settings/index.js +3 -0
- package/dist/ui/molecules/column-settings/index.js.map +1 -0
- package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts +31 -0
- package/dist/ui/molecules/confirm-dialog/confirm-dialog.d.ts.map +1 -0
- package/dist/ui/molecules/confirm-dialog/confirm-dialog.js +68 -0
- package/dist/ui/molecules/confirm-dialog/confirm-dialog.js.map +1 -0
- package/dist/ui/molecules/confirm-dialog/index.d.ts +2 -0
- package/dist/ui/molecules/confirm-dialog/index.d.ts.map +1 -0
- package/dist/ui/molecules/confirm-dialog/index.js +3 -0
- package/dist/ui/molecules/confirm-dialog/index.js.map +1 -0
- package/dist/ui/molecules/drawer/drawer.d.ts +25 -0
- package/dist/ui/molecules/drawer/drawer.d.ts.map +1 -0
- package/dist/ui/molecules/drawer/drawer.js +60 -0
- package/dist/ui/molecules/drawer/drawer.js.map +1 -0
- package/dist/ui/molecules/drawer/index.d.ts +2 -0
- package/dist/ui/molecules/drawer/index.d.ts.map +1 -0
- package/dist/ui/molecules/drawer/index.js +3 -0
- package/dist/ui/molecules/drawer/index.js.map +1 -0
- package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts +36 -0
- package/dist/ui/molecules/entity-link-input/entity-link-input.d.ts.map +1 -0
- package/dist/ui/molecules/entity-link-input/entity-link-input.js +191 -0
- package/dist/ui/molecules/entity-link-input/entity-link-input.js.map +1 -0
- package/dist/ui/molecules/entity-link-input/index.d.ts +2 -0
- package/dist/ui/molecules/entity-link-input/index.d.ts.map +1 -0
- package/dist/ui/molecules/entity-link-input/index.js +3 -0
- package/dist/ui/molecules/entity-link-input/index.js.map +1 -0
- package/dist/ui/molecules/entity-link-picker/entity-link-picker.d.ts +19 -0
- package/dist/ui/molecules/entity-link-picker/entity-link-picker.d.ts.map +1 -0
- package/dist/ui/molecules/entity-link-picker/entity-link-picker.js +78 -0
- package/dist/ui/molecules/entity-link-picker/entity-link-picker.js.map +1 -0
- package/dist/ui/molecules/entity-link-picker/index.d.ts +2 -0
- package/dist/ui/molecules/entity-link-picker/index.d.ts.map +1 -0
- package/dist/ui/molecules/entity-link-picker/index.js +3 -0
- package/dist/ui/molecules/entity-link-picker/index.js.map +1 -0
- package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts +30 -0
- package/dist/ui/molecules/entity-record-card/entity-record-card.d.ts.map +1 -0
- package/dist/ui/molecules/entity-record-card/entity-record-card.js +39 -0
- package/dist/ui/molecules/entity-record-card/entity-record-card.js.map +1 -0
- package/dist/ui/molecules/entity-record-card/index.d.ts +2 -0
- package/dist/ui/molecules/entity-record-card/index.d.ts.map +1 -0
- package/dist/ui/molecules/entity-record-card/index.js +3 -0
- package/dist/ui/molecules/entity-record-card/index.js.map +1 -0
- package/dist/ui/molecules/filter-builder/filter-builder.d.ts +19 -0
- package/dist/ui/molecules/filter-builder/filter-builder.d.ts.map +1 -0
- package/dist/ui/molecules/filter-builder/filter-builder.js +333 -0
- package/dist/ui/molecules/filter-builder/filter-builder.js.map +1 -0
- package/dist/ui/molecules/filter-builder/filter-operators.d.ts +20 -0
- package/dist/ui/molecules/filter-builder/filter-operators.d.ts.map +1 -0
- package/dist/ui/molecules/filter-builder/filter-operators.js +56 -0
- package/dist/ui/molecules/filter-builder/filter-operators.js.map +1 -0
- package/dist/ui/molecules/filter-builder/index.d.ts +3 -0
- package/dist/ui/molecules/filter-builder/index.d.ts.map +1 -0
- package/dist/ui/molecules/filter-builder/index.js +4 -0
- package/dist/ui/molecules/filter-builder/index.js.map +1 -0
- package/dist/ui/molecules/loading-boundary/index.d.ts +2 -0
- package/dist/ui/molecules/loading-boundary/index.d.ts.map +1 -0
- package/dist/ui/molecules/loading-boundary/index.js +3 -0
- package/dist/ui/molecules/loading-boundary/index.js.map +1 -0
- package/dist/ui/molecules/loading-boundary/loading-boundary.d.ts +27 -0
- package/dist/ui/molecules/loading-boundary/loading-boundary.d.ts.map +1 -0
- package/dist/ui/molecules/loading-boundary/loading-boundary.js +42 -0
- package/dist/ui/molecules/loading-boundary/loading-boundary.js.map +1 -0
- package/dist/ui/molecules/menu/index.d.ts +2 -0
- package/dist/ui/molecules/menu/index.d.ts.map +1 -0
- package/dist/ui/molecules/menu/index.js +3 -0
- package/dist/ui/molecules/menu/index.js.map +1 -0
- package/dist/ui/molecules/menu/menu.d.ts +37 -0
- package/dist/ui/molecules/menu/menu.d.ts.map +1 -0
- package/dist/ui/molecules/menu/menu.js +71 -0
- package/dist/ui/molecules/menu/menu.js.map +1 -0
- package/dist/ui/molecules/pagination/index.d.ts +2 -0
- package/dist/ui/molecules/pagination/index.d.ts.map +1 -0
- package/dist/ui/molecules/pagination/index.js +3 -0
- package/dist/ui/molecules/pagination/index.js.map +1 -0
- package/dist/ui/molecules/pagination/pagination.d.ts +13 -0
- package/dist/ui/molecules/pagination/pagination.d.ts.map +1 -0
- package/dist/ui/molecules/pagination/pagination.js +68 -0
- package/dist/ui/molecules/pagination/pagination.js.map +1 -0
- package/dist/ui/molecules/sort-builder/index.d.ts +2 -0
- package/dist/ui/molecules/sort-builder/index.d.ts.map +1 -0
- package/dist/ui/molecules/sort-builder/index.js +3 -0
- package/dist/ui/molecules/sort-builder/index.js.map +1 -0
- package/dist/ui/molecules/sort-builder/sort-builder.d.ts +18 -0
- package/dist/ui/molecules/sort-builder/sort-builder.d.ts.map +1 -0
- package/dist/ui/molecules/sort-builder/sort-builder.js +185 -0
- package/dist/ui/molecules/sort-builder/sort-builder.js.map +1 -0
- package/dist/ui/molecules/stack/index.d.ts +2 -0
- package/dist/ui/molecules/stack/index.d.ts.map +1 -0
- package/dist/ui/molecules/stack/index.js +3 -0
- package/dist/ui/molecules/stack/index.js.map +1 -0
- package/dist/ui/molecules/stack/stack.d.ts +12 -0
- package/dist/ui/molecules/stack/stack.d.ts.map +1 -0
- package/dist/ui/molecules/stack/stack.js +36 -0
- package/dist/ui/molecules/stack/stack.js.map +1 -0
- package/dist/ui/molecules/tab-strip/index.d.ts +2 -0
- package/dist/ui/molecules/tab-strip/index.d.ts.map +1 -0
- package/dist/ui/molecules/tab-strip/index.js +3 -0
- package/dist/ui/molecules/tab-strip/index.js.map +1 -0
- package/dist/ui/molecules/tab-strip/tab-strip.d.ts +29 -0
- package/dist/ui/molecules/tab-strip/tab-strip.d.ts.map +1 -0
- package/dist/ui/molecules/tab-strip/tab-strip.js +82 -0
- package/dist/ui/molecules/tab-strip/tab-strip.js.map +1 -0
- package/dist/ui/molecules/table-toolbar/index.d.ts +2 -0
- package/dist/ui/molecules/table-toolbar/index.d.ts.map +1 -0
- package/dist/ui/molecules/table-toolbar/index.js +3 -0
- package/dist/ui/molecules/table-toolbar/index.js.map +1 -0
- package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts +13 -0
- package/dist/ui/molecules/table-toolbar/table-toolbar.d.ts.map +1 -0
- package/dist/ui/molecules/table-toolbar/table-toolbar.js +28 -0
- package/dist/ui/molecules/table-toolbar/table-toolbar.js.map +1 -0
- package/dist/ui/molecules/theme-switcher/index.d.ts +2 -0
- package/dist/ui/molecules/theme-switcher/index.d.ts.map +1 -0
- package/dist/ui/molecules/theme-switcher/index.js +3 -0
- package/dist/ui/molecules/theme-switcher/index.js.map +1 -0
- package/dist/ui/molecules/theme-switcher/theme-switcher.d.ts +6 -0
- package/dist/ui/molecules/theme-switcher/theme-switcher.d.ts.map +1 -0
- package/dist/ui/molecules/theme-switcher/theme-switcher.js +24 -0
- package/dist/ui/molecules/theme-switcher/theme-switcher.js.map +1 -0
- package/dist/ui/organisms/command-palette/command-palette.d.ts +67 -0
- package/dist/ui/organisms/command-palette/command-palette.d.ts.map +1 -0
- package/dist/ui/organisms/command-palette/command-palette.js +226 -0
- package/dist/ui/organisms/command-palette/command-palette.js.map +1 -0
- package/dist/ui/organisms/command-palette/index.d.ts +2 -0
- package/dist/ui/organisms/command-palette/index.d.ts.map +1 -0
- package/dist/ui/organisms/command-palette/index.js +3 -0
- package/dist/ui/organisms/command-palette/index.js.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts +43 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.d.ts.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js +281 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.js.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.d.ts +49 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.d.ts.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.js +3 -0
- package/dist/ui/organisms/entity-detail-grid/entity-detail-grid.types.js.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/index.d.ts +3 -0
- package/dist/ui/organisms/entity-detail-grid/index.d.ts.map +1 -0
- package/dist/ui/organisms/entity-detail-grid/index.js +4 -0
- package/dist/ui/organisms/entity-detail-grid/index.js.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form-slots.d.ts +53 -0
- package/dist/ui/organisms/entity-form/entity-form-slots.d.ts.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form-slots.js +44 -0
- package/dist/ui/organisms/entity-form/entity-form-slots.js.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form.d.ts +4 -0
- package/dist/ui/organisms/entity-form/entity-form.d.ts.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form.js +494 -0
- package/dist/ui/organisms/entity-form/entity-form.js.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form.types.d.ts +151 -0
- package/dist/ui/organisms/entity-form/entity-form.types.d.ts.map +1 -0
- package/dist/ui/organisms/entity-form/entity-form.types.js +3 -0
- package/dist/ui/organisms/entity-form/entity-form.types.js.map +1 -0
- package/dist/ui/organisms/entity-form/index.d.ts +5 -0
- package/dist/ui/organisms/entity-form/index.d.ts.map +1 -0
- package/dist/ui/organisms/entity-form/index.js +6 -0
- package/dist/ui/organisms/entity-form/index.js.map +1 -0
- package/dist/ui/organisms/entity-form/use-entity-form-fields.d.ts +13 -0
- package/dist/ui/organisms/entity-form/use-entity-form-fields.d.ts.map +1 -0
- package/dist/ui/organisms/entity-form/use-entity-form-fields.js +50 -0
- package/dist/ui/organisms/entity-form/use-entity-form-fields.js.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table-slots.d.ts +55 -0
- package/dist/ui/organisms/entity-table/entity-table-slots.d.ts.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table-slots.js +50 -0
- package/dist/ui/organisms/entity-table/entity-table-slots.js.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table.d.ts +4 -0
- package/dist/ui/organisms/entity-table/entity-table.d.ts.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table.js +529 -0
- package/dist/ui/organisms/entity-table/entity-table.js.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table.types.d.ts +126 -0
- package/dist/ui/organisms/entity-table/entity-table.types.d.ts.map +1 -0
- package/dist/ui/organisms/entity-table/entity-table.types.js +3 -0
- package/dist/ui/organisms/entity-table/entity-table.types.js.map +1 -0
- package/dist/ui/organisms/entity-table/index.d.ts +5 -0
- package/dist/ui/organisms/entity-table/index.d.ts.map +1 -0
- package/dist/ui/organisms/entity-table/index.js +6 -0
- package/dist/ui/organisms/entity-table/index.js.map +1 -0
- package/dist/ui/organisms/entity-table/use-entity-table-columns.d.ts +29 -0
- package/dist/ui/organisms/entity-table/use-entity-table-columns.d.ts.map +1 -0
- package/dist/ui/organisms/entity-table/use-entity-table-columns.js +103 -0
- package/dist/ui/organisms/entity-table/use-entity-table-columns.js.map +1 -0
- package/dist/ui/organisms/top-bar/index.d.ts +2 -0
- package/dist/ui/organisms/top-bar/index.d.ts.map +1 -0
- package/dist/ui/organisms/top-bar/index.js +3 -0
- package/dist/ui/organisms/top-bar/index.js.map +1 -0
- package/dist/ui/organisms/top-bar/top-bar.d.ts +20 -0
- package/dist/ui/organisms/top-bar/top-bar.d.ts.map +1 -0
- package/dist/ui/organisms/top-bar/top-bar.js +43 -0
- package/dist/ui/organisms/top-bar/top-bar.js.map +1 -0
- package/dist/ui/organisms/wizard/index.d.ts +3 -0
- package/dist/ui/organisms/wizard/index.d.ts.map +1 -0
- package/dist/ui/organisms/wizard/index.js +4 -0
- package/dist/ui/organisms/wizard/index.js.map +1 -0
- package/dist/ui/organisms/wizard/wizard.d.ts +21 -0
- package/dist/ui/organisms/wizard/wizard.d.ts.map +1 -0
- package/dist/ui/organisms/wizard/wizard.js +260 -0
- package/dist/ui/organisms/wizard/wizard.js.map +1 -0
- package/dist/ui/organisms/wizard/wizard.types.d.ts +83 -0
- package/dist/ui/organisms/wizard/wizard.types.d.ts.map +1 -0
- package/dist/ui/organisms/wizard/wizard.types.js +3 -0
- package/dist/ui/organisms/wizard/wizard.types.js.map +1 -0
- package/dist/ui/utils/cn.d.ts +4 -0
- package/dist/ui/utils/cn.d.ts.map +1 -0
- package/dist/ui/utils/cn.js +5 -0
- package/dist/ui/utils/cn.js.map +1 -0
- package/dist/ui/utils/use-hotkey.d.ts +31 -0
- package/dist/ui/utils/use-hotkey.d.ts.map +1 -0
- package/dist/ui/utils/use-hotkey.js +69 -0
- package/dist/ui/utils/use-hotkey.js.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { useT } from '../../../i18n/index.js';
|
|
5
|
+
import { Button } from '../../atoms/button/index.js';
|
|
6
|
+
import { Skeleton } from '../../atoms/skeleton/index.js';
|
|
7
|
+
import { Text } from '../../atoms/text/index.js';
|
|
8
|
+
import { Cluster } from '../../layout/cluster/index.js';
|
|
9
|
+
import { Card } from '../../molecules/card/index.js';
|
|
10
|
+
import { Stack } from '../../molecules/stack/index.js';
|
|
11
|
+
import { cn } from '../../utils/cn.js';
|
|
12
|
+
/** How many placeholder steps stand in when the caller has none yet. */ const SKELETON_STEP_COUNT = 4;
|
|
13
|
+
/**
|
|
14
|
+
* The status catalog keys, written out rather than composed.
|
|
15
|
+
*
|
|
16
|
+
* `t(\`wizard.status.${status}\`)` would work and would be untyped — the
|
|
17
|
+
* augmentation cannot see a template literal, so the only thing left checking
|
|
18
|
+
* it would be `@r10c/i18n-check`, which does not read `.tsx`. Four literals
|
|
19
|
+
* cost nothing and stay compile-checked.
|
|
20
|
+
*/ const STATUS_KEY = {
|
|
21
|
+
pending: 'wizard.status.pending',
|
|
22
|
+
active: 'wizard.status.active',
|
|
23
|
+
complete: 'wizard.status.complete',
|
|
24
|
+
error: 'wizard.status.error'
|
|
25
|
+
};
|
|
26
|
+
const MARKER_CLASS = {
|
|
27
|
+
pending: 'border-border bg-surface text-content-muted',
|
|
28
|
+
active: 'border-accent bg-accent text-primary-content',
|
|
29
|
+
complete: 'border-accent bg-surface text-accent',
|
|
30
|
+
error: 'border-danger bg-danger-subtle text-danger'
|
|
31
|
+
};
|
|
32
|
+
const LABEL_CLASS = {
|
|
33
|
+
pending: 'text-content-muted',
|
|
34
|
+
active: 'font-medium text-content',
|
|
35
|
+
complete: 'text-content',
|
|
36
|
+
error: 'font-medium text-danger'
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A guided multi-step flow: the stepper, the active step's body, and the
|
|
40
|
+
* controls that move between them.
|
|
41
|
+
*
|
|
42
|
+
* **Presentational, and controlled from above.** It holds no step state, no
|
|
43
|
+
* draft and no router — `activeStep` is a prop and `onStepChange` reports a
|
|
44
|
+
* click, the same rule that made `hrefFor` a prop, so URL synchronisation stays
|
|
45
|
+
* the shell's job and this control can be told to render step four by a route,
|
|
46
|
+
* a workspace tab, or a Storybook arg without knowing which
|
|
47
|
+
* ([ADR 0045](../../../../../../../docs/adr/0045-the-wizard-a-step-graph-and-a-submit-that-hands-off.md)).
|
|
48
|
+
*
|
|
49
|
+
* ⚠️ **The stepper is an ordered list, not a tablist.** `TabStrip` is the
|
|
50
|
+
* nearest-looking thing in this package and is the wrong precedent: a
|
|
51
|
+
* `role="tablist"` tells assistive technology that the panels are siblings the
|
|
52
|
+
* user may choose between, and a wizard's steps are ordered and gated. So this
|
|
53
|
+
* is `<ol>`/`<li>` with `aria-current="step"`, and each step's status is
|
|
54
|
+
* announced rather than carried by colour alone.
|
|
55
|
+
*/ export function Wizard({ steps, activeStep, title, children, onNext, onFinish, onPrevious, onStepChange, canFinish = false, canAdvance = true, isSubmitting = false, recap, onDismissRecap, isLoading = false, skeleton = true, className }) {
|
|
56
|
+
const t = useT();
|
|
57
|
+
const heading = useRef(null);
|
|
58
|
+
const focused = useRef(activeStep);
|
|
59
|
+
// Focus moves to the new step's heading, and **only on a change**: doing it on
|
|
60
|
+
// mount would take focus from whatever opened the wizard, which on a route is
|
|
61
|
+
// the link the operator just used.
|
|
62
|
+
useEffect(()=>{
|
|
63
|
+
var _heading_current;
|
|
64
|
+
if (focused.current === activeStep) return;
|
|
65
|
+
focused.current = activeStep;
|
|
66
|
+
(_heading_current = heading.current) == null ? void 0 : _heading_current.focus();
|
|
67
|
+
}, [
|
|
68
|
+
activeStep
|
|
69
|
+
]);
|
|
70
|
+
if (isLoading && skeleton !== false) {
|
|
71
|
+
return /*#__PURE__*/ _jsx(WizardSkeleton, {
|
|
72
|
+
stepCount: steps.length > 0 ? steps.length : SKELETON_STEP_COUNT,
|
|
73
|
+
placeholder: skeleton === true ? undefined : skeleton,
|
|
74
|
+
className: className
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
const position = steps.findIndex((step)=>step.id === activeStep) + 1;
|
|
78
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
79
|
+
gap: "m",
|
|
80
|
+
className: className,
|
|
81
|
+
children: [
|
|
82
|
+
/*#__PURE__*/ _jsx(Stepper, {
|
|
83
|
+
steps: steps,
|
|
84
|
+
activeStep: activeStep,
|
|
85
|
+
onStepChange: onStepChange
|
|
86
|
+
}),
|
|
87
|
+
recap && /*#__PURE__*/ _jsx(Card, {
|
|
88
|
+
"data-testid": "wizard-recap",
|
|
89
|
+
className: "border-l-4 border-l-accent",
|
|
90
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
91
|
+
gap: "2xs",
|
|
92
|
+
children: [
|
|
93
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
94
|
+
as: "h3",
|
|
95
|
+
step: 0,
|
|
96
|
+
weight: "semibold",
|
|
97
|
+
children: t('wizard.resume.title')
|
|
98
|
+
}),
|
|
99
|
+
recap,
|
|
100
|
+
onDismissRecap && /*#__PURE__*/ _jsx(Cluster, {
|
|
101
|
+
justify: "end",
|
|
102
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
103
|
+
variant: "ghost",
|
|
104
|
+
size: "sm",
|
|
105
|
+
onClick: onDismissRecap,
|
|
106
|
+
children: t('wizard.resume.dismiss')
|
|
107
|
+
})
|
|
108
|
+
})
|
|
109
|
+
]
|
|
110
|
+
})
|
|
111
|
+
}),
|
|
112
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
113
|
+
gap: "s",
|
|
114
|
+
children: [
|
|
115
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
116
|
+
gap: "3xs",
|
|
117
|
+
children: [
|
|
118
|
+
/*#__PURE__*/ _jsx("h2", {
|
|
119
|
+
ref: heading,
|
|
120
|
+
tabIndex: -1,
|
|
121
|
+
className: "rounded-sm text-step-1 font-semibold text-content focus-ring outline-none",
|
|
122
|
+
children: title
|
|
123
|
+
}),
|
|
124
|
+
position > 0 && /*#__PURE__*/ _jsx(Text, {
|
|
125
|
+
step: -1,
|
|
126
|
+
tone: "muted",
|
|
127
|
+
children: t('wizard.stepOf', {
|
|
128
|
+
current: position,
|
|
129
|
+
total: steps.length
|
|
130
|
+
})
|
|
131
|
+
})
|
|
132
|
+
]
|
|
133
|
+
}),
|
|
134
|
+
children
|
|
135
|
+
]
|
|
136
|
+
}),
|
|
137
|
+
/*#__PURE__*/ _jsxs(Cluster, {
|
|
138
|
+
justify: "between",
|
|
139
|
+
children: [
|
|
140
|
+
/*#__PURE__*/ _jsx("div", {
|
|
141
|
+
children: onPrevious && /*#__PURE__*/ _jsx(Button, {
|
|
142
|
+
type: "button",
|
|
143
|
+
variant: "secondary",
|
|
144
|
+
"data-testid": "wizard-previous",
|
|
145
|
+
onClick: onPrevious,
|
|
146
|
+
disabled: isSubmitting,
|
|
147
|
+
children: t('wizard.previous')
|
|
148
|
+
})
|
|
149
|
+
}),
|
|
150
|
+
/*#__PURE__*/ _jsxs(Button, {
|
|
151
|
+
type: "button",
|
|
152
|
+
"data-testid": "wizard-next",
|
|
153
|
+
onClick: canFinish ? onFinish : onNext,
|
|
154
|
+
disabled: isSubmitting || !canAdvance,
|
|
155
|
+
children: [
|
|
156
|
+
isSubmitting && t('wizard.submitting'),
|
|
157
|
+
!isSubmitting && canFinish && t('wizard.finish'),
|
|
158
|
+
!isSubmitting && !canFinish && t('wizard.next')
|
|
159
|
+
]
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
})
|
|
163
|
+
]
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function Stepper({ steps, activeStep, onStepChange }) {
|
|
167
|
+
const t = useT();
|
|
168
|
+
return /*#__PURE__*/ _jsx("ol", {
|
|
169
|
+
"aria-label": t('wizard.steps'),
|
|
170
|
+
className: "flex flex-wrap items-center gap-x-s gap-y-2xs",
|
|
171
|
+
children: steps.map((step, index)=>/*#__PURE__*/ _jsxs("li", {
|
|
172
|
+
"aria-current": step.id === activeStep ? 'step' : undefined,
|
|
173
|
+
className: "flex items-center gap-2xs",
|
|
174
|
+
children: [
|
|
175
|
+
/*#__PURE__*/ _jsx(StepMarker, {
|
|
176
|
+
step: step,
|
|
177
|
+
index: index,
|
|
178
|
+
onStepChange: onStepChange
|
|
179
|
+
}),
|
|
180
|
+
index < steps.length - 1 && /*#__PURE__*/ _jsx("span", {
|
|
181
|
+
"aria-hidden": "true",
|
|
182
|
+
className: "h-px w-s shrink-0 bg-border"
|
|
183
|
+
})
|
|
184
|
+
]
|
|
185
|
+
}, step.id))
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* One step's dot and label.
|
|
190
|
+
*
|
|
191
|
+
* A completed step is a `<button>` and every other step is not, rather than a
|
|
192
|
+
* disabled button throughout: a disabled control is still announced as a
|
|
193
|
+
* control, so a pending step would read as something the operator may activate
|
|
194
|
+
* and cannot, when in truth there is nothing there to activate yet.
|
|
195
|
+
*/ function StepMarker({ step, index, onStepChange }) {
|
|
196
|
+
const t = useT();
|
|
197
|
+
const clickable = onStepChange !== undefined && step.status === 'complete';
|
|
198
|
+
const body = /*#__PURE__*/ _jsxs(_Fragment, {
|
|
199
|
+
children: [
|
|
200
|
+
/*#__PURE__*/ _jsx("span", {
|
|
201
|
+
"aria-hidden": "true",
|
|
202
|
+
className: cn('size-6 flex shrink-0 items-center justify-center rounded-full border', 'text-step-xs font-medium transition duration-200 ease-smooth', MARKER_CLASS[step.status]),
|
|
203
|
+
children: index + 1
|
|
204
|
+
}),
|
|
205
|
+
/*#__PURE__*/ _jsx("span", {
|
|
206
|
+
className: cn('text-step-sm', LABEL_CLASS[step.status]),
|
|
207
|
+
children: step.label
|
|
208
|
+
}),
|
|
209
|
+
/*#__PURE__*/ _jsx("span", {
|
|
210
|
+
className: "sr-only",
|
|
211
|
+
children: t(STATUS_KEY[step.status])
|
|
212
|
+
})
|
|
213
|
+
]
|
|
214
|
+
});
|
|
215
|
+
if (!clickable) {
|
|
216
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
217
|
+
className: "flex items-center gap-3xs",
|
|
218
|
+
children: body
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return /*#__PURE__*/ _jsx("button", {
|
|
222
|
+
type: "button",
|
|
223
|
+
onClick: ()=>onStepChange(step.id),
|
|
224
|
+
"aria-label": t('wizard.goToStep', {
|
|
225
|
+
label: step.label
|
|
226
|
+
}),
|
|
227
|
+
className: "flex items-center gap-3xs rounded-md p-3xs focus-ring hover:bg-surface-elevated",
|
|
228
|
+
children: body
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The wizard's shape while it is in flight.
|
|
233
|
+
*
|
|
234
|
+
* Sized from the step count it was handed, so the swap to the real stepper
|
|
235
|
+
* shifts nothing — the geometry rule every skeleton in this package follows.
|
|
236
|
+
*/ function WizardSkeleton({ stepCount, placeholder, className }) {
|
|
237
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
238
|
+
gap: "m",
|
|
239
|
+
className: className,
|
|
240
|
+
role: "status",
|
|
241
|
+
"aria-busy": "true",
|
|
242
|
+
"data-testid": "wizard-skeleton",
|
|
243
|
+
children: [
|
|
244
|
+
/*#__PURE__*/ _jsx(Cluster, {
|
|
245
|
+
gap: "s",
|
|
246
|
+
children: Array.from({
|
|
247
|
+
length: stepCount
|
|
248
|
+
}, (_, index)=>/*#__PURE__*/ _jsx(Skeleton, {
|
|
249
|
+
shape: "line",
|
|
250
|
+
className: "h-6 w-24"
|
|
251
|
+
}, index))
|
|
252
|
+
}),
|
|
253
|
+
placeholder != null ? placeholder : /*#__PURE__*/ _jsx(Skeleton, {
|
|
254
|
+
className: "h-40 w-full"
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
//# sourceMappingURL=wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/ui/organisms/wizard/wizard.tsx"],"sourcesContent":["'use client';\n\nimport type { WizardStepStatus } from '@entifix/core';\nimport { type ReactNode, useEffect, useRef } from 'react';\n\nimport { useT } from '../../../i18n/index.js';\nimport { Button } from '../../atoms/button/index.js';\nimport { Skeleton } from '../../atoms/skeleton/index.js';\nimport { Text } from '../../atoms/text/index.js';\nimport { Cluster } from '../../layout/cluster/index.js';\nimport { Card } from '../../molecules/card/index.js';\nimport { Stack } from '../../molecules/stack/index.js';\nimport { cn } from '../../utils/cn.js';\nimport type { WizardProps, WizardStepView } from './wizard.types.js';\n\n/** How many placeholder steps stand in when the caller has none yet. */\nconst SKELETON_STEP_COUNT = 4;\n\n/**\n * The status catalog keys, written out rather than composed.\n *\n * `t(\\`wizard.status.${status}\\`)` would work and would be untyped — the\n * augmentation cannot see a template literal, so the only thing left checking\n * it would be `@r10c/i18n-check`, which does not read `.tsx`. Four literals\n * cost nothing and stay compile-checked.\n */\nconst STATUS_KEY = {\n pending: 'wizard.status.pending',\n active: 'wizard.status.active',\n complete: 'wizard.status.complete',\n error: 'wizard.status.error',\n} as const satisfies Record<WizardStepStatus, string>;\n\nconst MARKER_CLASS: Record<WizardStepStatus, string> = {\n pending: 'border-border bg-surface text-content-muted',\n active: 'border-accent bg-accent text-primary-content',\n complete: 'border-accent bg-surface text-accent',\n error: 'border-danger bg-danger-subtle text-danger',\n};\n\nconst LABEL_CLASS: Record<WizardStepStatus, string> = {\n pending: 'text-content-muted',\n active: 'font-medium text-content',\n complete: 'text-content',\n error: 'font-medium text-danger',\n};\n\n/**\n * A guided multi-step flow: the stepper, the active step's body, and the\n * controls that move between them.\n *\n * **Presentational, and controlled from above.** It holds no step state, no\n * draft and no router — `activeStep` is a prop and `onStepChange` reports a\n * click, the same rule that made `hrefFor` a prop, so URL synchronisation stays\n * the shell's job and this control can be told to render step four by a route,\n * a workspace tab, or a Storybook arg without knowing which\n * ([ADR 0045](../../../../../../../docs/adr/0045-the-wizard-a-step-graph-and-a-submit-that-hands-off.md)).\n *\n * ⚠️ **The stepper is an ordered list, not a tablist.** `TabStrip` is the\n * nearest-looking thing in this package and is the wrong precedent: a\n * `role=\"tablist\"` tells assistive technology that the panels are siblings the\n * user may choose between, and a wizard's steps are ordered and gated. So this\n * is `<ol>`/`<li>` with `aria-current=\"step\"`, and each step's status is\n * announced rather than carried by colour alone.\n */\nexport function Wizard({\n steps,\n activeStep,\n title,\n children,\n onNext,\n onFinish,\n onPrevious,\n onStepChange,\n canFinish = false,\n canAdvance = true,\n isSubmitting = false,\n recap,\n onDismissRecap,\n isLoading = false,\n skeleton = true,\n className,\n}: WizardProps) {\n const t = useT();\n const heading = useRef<HTMLHeadingElement>(null);\n const focused = useRef(activeStep);\n\n // Focus moves to the new step's heading, and **only on a change**: doing it on\n // mount would take focus from whatever opened the wizard, which on a route is\n // the link the operator just used.\n useEffect(() => {\n if (focused.current === activeStep) return;\n focused.current = activeStep;\n heading.current?.focus();\n }, [activeStep]);\n\n if (isLoading && skeleton !== false) {\n return (\n <WizardSkeleton\n stepCount={steps.length > 0 ? steps.length : SKELETON_STEP_COUNT}\n placeholder={skeleton === true ? undefined : skeleton}\n className={className}\n />\n );\n }\n\n const position = steps.findIndex(step => step.id === activeStep) + 1;\n\n return (\n <Stack gap=\"m\" className={className}>\n <Stepper\n steps={steps}\n activeStep={activeStep}\n onStepChange={onStepChange}\n />\n\n {recap && (\n <Card data-testid=\"wizard-recap\" className=\"border-l-4 border-l-accent\">\n <Stack gap=\"2xs\">\n <Text as=\"h3\" step={0} weight=\"semibold\">\n {t('wizard.resume.title')}\n </Text>\n {recap}\n {onDismissRecap && (\n <Cluster justify=\"end\">\n <Button variant=\"ghost\" size=\"sm\" onClick={onDismissRecap}>\n {t('wizard.resume.dismiss')}\n </Button>\n </Cluster>\n )}\n </Stack>\n </Card>\n )}\n\n {/* No `Card` around the body: a step brings its own surface — an embedded\n `EntityForm` is already a card — and nesting one inside another reads\n as two panels for one step. */}\n <Stack gap=\"s\">\n <Stack gap=\"3xs\">\n {/*\n A plain heading with a real ref, and `tabIndex={-1}` so script can\n focus it without putting it in the tab order — the target of the\n advance above.\n */}\n <h2\n ref={heading}\n tabIndex={-1}\n className=\"rounded-sm text-step-1 font-semibold text-content focus-ring outline-none\"\n >\n {title}\n </h2>\n {position > 0 && (\n <Text step={-1} tone=\"muted\">\n {t('wizard.stepOf', {\n current: position,\n total: steps.length,\n })}\n </Text>\n )}\n </Stack>\n\n {children}\n </Stack>\n\n <Cluster justify=\"between\">\n <div>\n {onPrevious && (\n <Button\n type=\"button\"\n variant=\"secondary\"\n data-testid=\"wizard-previous\"\n onClick={onPrevious}\n disabled={isSubmitting}\n >\n {t('wizard.previous')}\n </Button>\n )}\n </div>\n {/* Named for the tests and the e2e, because a step may bring controls\n of its own — a table step's pager sits in the same view. */}\n <Button\n type=\"button\"\n data-testid=\"wizard-next\"\n onClick={canFinish ? onFinish : onNext}\n disabled={isSubmitting || !canAdvance}\n >\n {isSubmitting && t('wizard.submitting')}\n {!isSubmitting && canFinish && t('wizard.finish')}\n {!isSubmitting && !canFinish && t('wizard.next')}\n </Button>\n </Cluster>\n </Stack>\n );\n}\n\ninterface StepperProps {\n steps: readonly WizardStepView[];\n activeStep: string;\n onStepChange?: (stepId: string) => void;\n}\n\nfunction Stepper({ steps, activeStep, onStepChange }: StepperProps) {\n const t = useT();\n\n return (\n <ol\n aria-label={t('wizard.steps')}\n className=\"flex flex-wrap items-center gap-x-s gap-y-2xs\"\n >\n {steps.map((step, index) => (\n <li\n key={step.id}\n aria-current={step.id === activeStep ? 'step' : undefined}\n className=\"flex items-center gap-2xs\"\n >\n <StepMarker step={step} index={index} onStepChange={onStepChange} />\n {index < steps.length - 1 && (\n <span aria-hidden=\"true\" className=\"h-px w-s shrink-0 bg-border\" />\n )}\n </li>\n ))}\n </ol>\n );\n}\n\ninterface StepMarkerProps {\n step: WizardStepView;\n index: number;\n onStepChange?: (stepId: string) => void;\n}\n\n/**\n * One step's dot and label.\n *\n * A completed step is a `<button>` and every other step is not, rather than a\n * disabled button throughout: a disabled control is still announced as a\n * control, so a pending step would read as something the operator may activate\n * and cannot, when in truth there is nothing there to activate yet.\n */\nfunction StepMarker({ step, index, onStepChange }: StepMarkerProps) {\n const t = useT();\n const clickable = onStepChange !== undefined && step.status === 'complete';\n\n const body = (\n <>\n <span\n aria-hidden=\"true\"\n className={cn(\n 'size-6 flex shrink-0 items-center justify-center rounded-full border',\n 'text-step-xs font-medium transition duration-200 ease-smooth',\n MARKER_CLASS[step.status],\n )}\n >\n {index + 1}\n </span>\n <span className={cn('text-step-sm', LABEL_CLASS[step.status])}>\n {step.label}\n </span>\n {/*\n Status is announced as well as coloured. A screen reader walks this list\n without seeing the ring, and \"completed\" is the whole point of a stepper.\n */}\n <span className=\"sr-only\">{t(STATUS_KEY[step.status])}</span>\n </>\n );\n\n if (!clickable) {\n return <span className=\"flex items-center gap-3xs\">{body}</span>;\n }\n\n return (\n <button\n type=\"button\"\n onClick={() => onStepChange(step.id)}\n aria-label={t('wizard.goToStep', { label: step.label })}\n className=\"flex items-center gap-3xs rounded-md p-3xs focus-ring hover:bg-surface-elevated\"\n >\n {body}\n </button>\n );\n}\n\ninterface WizardSkeletonProps {\n stepCount: number;\n placeholder?: ReactNode;\n className?: string;\n}\n\n/**\n * The wizard's shape while it is in flight.\n *\n * Sized from the step count it was handed, so the swap to the real stepper\n * shifts nothing — the geometry rule every skeleton in this package follows.\n */\nfunction WizardSkeleton({\n stepCount,\n placeholder,\n className,\n}: WizardSkeletonProps) {\n return (\n <Stack\n gap=\"m\"\n className={className}\n role=\"status\"\n aria-busy=\"true\"\n data-testid=\"wizard-skeleton\"\n >\n <Cluster gap=\"s\">\n {Array.from({ length: stepCount }, (_, index) => (\n <Skeleton key={index} shape=\"line\" className=\"h-6 w-24\" />\n ))}\n </Cluster>\n {placeholder ?? <Skeleton className=\"h-40 w-full\" />}\n </Stack>\n );\n}\n"],"names":["useEffect","useRef","useT","Button","Skeleton","Text","Cluster","Card","Stack","cn","SKELETON_STEP_COUNT","STATUS_KEY","pending","active","complete","error","MARKER_CLASS","LABEL_CLASS","Wizard","steps","activeStep","title","children","onNext","onFinish","onPrevious","onStepChange","canFinish","canAdvance","isSubmitting","recap","onDismissRecap","isLoading","skeleton","className","t","heading","focused","current","focus","WizardSkeleton","stepCount","length","placeholder","undefined","position","findIndex","step","id","gap","Stepper","data-testid","as","weight","justify","variant","size","onClick","h2","ref","tabIndex","tone","total","div","type","disabled","ol","aria-label","map","index","li","aria-current","StepMarker","span","aria-hidden","clickable","status","body","label","button","role","aria-busy","Array","from","_","shape"],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { WizardStepStatus } from '@entifix/core';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* One step as the stepper shows it.
|
|
5
|
+
*
|
|
6
|
+
* `label` is **already-resolved copy**, not a catalog key, which is the rule
|
|
7
|
+
* `ConfirmDialog`'s `title`/`message` already follow: a step's name belongs to
|
|
8
|
+
* the domain that declared the wizard, so its copy is `shell:`-namespaced and
|
|
9
|
+
* this package cannot type-check the key.
|
|
10
|
+
*/
|
|
11
|
+
export interface WizardStepView {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly status: WizardStepStatus;
|
|
15
|
+
}
|
|
16
|
+
export interface WizardProps {
|
|
17
|
+
/**
|
|
18
|
+
* The steps on the path this flow is taking, in order — the projection
|
|
19
|
+
* `stepStatuses` returns, not the definition's whole step list.
|
|
20
|
+
*
|
|
21
|
+
* A graph's declared steps include branches not taken, so rendering all of
|
|
22
|
+
* them promises an operator who chose to start blank a step they will never
|
|
23
|
+
* see.
|
|
24
|
+
*/
|
|
25
|
+
steps: readonly WizardStepView[];
|
|
26
|
+
/** Which step's body `children` is. Controlled; the shell owns the URL. */
|
|
27
|
+
activeStep: string;
|
|
28
|
+
/**
|
|
29
|
+
* The active step's heading.
|
|
30
|
+
*
|
|
31
|
+
* It is also the **focus target on advance**: moving focus to the top of the
|
|
32
|
+
* new step is what makes a keyboard or screen-reader user land somewhere
|
|
33
|
+
* meaningful instead of wherever the previous step's Next button was.
|
|
34
|
+
*/
|
|
35
|
+
title: string;
|
|
36
|
+
/** The active step's body. */
|
|
37
|
+
children: ReactNode;
|
|
38
|
+
onNext: () => void;
|
|
39
|
+
onFinish: () => void;
|
|
40
|
+
/** Absent at the entry step, where there is nowhere to go back to. */
|
|
41
|
+
onPrevious?: () => void;
|
|
42
|
+
/**
|
|
43
|
+
* A completed step was clicked. Omit and the stepper is read-only.
|
|
44
|
+
*
|
|
45
|
+
* Only `complete` steps are clickable; a `pending` one would skip the per-step
|
|
46
|
+
* submit that validates everything in between.
|
|
47
|
+
*/
|
|
48
|
+
onStepChange?: (stepId: string) => void;
|
|
49
|
+
/** The active step ends the flow, so the primary button reads Finalizar. */
|
|
50
|
+
canFinish?: boolean;
|
|
51
|
+
/** Advancing is blocked — a required answer is missing on this step. */
|
|
52
|
+
canAdvance?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* The submit is in flight.
|
|
55
|
+
*
|
|
56
|
+
* It stays in flight: `onFinish` hands off and returns before the write is
|
|
57
|
+
* terminal ([ADR 0043](../../../../../../../docs/adr/0043-the-optimistic-mutation-contract.md)),
|
|
58
|
+
* so what this disables is a second submit — it is not a spinner waiting for
|
|
59
|
+
* a resolution the caller never gets.
|
|
60
|
+
*/
|
|
61
|
+
isSubmitting?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* What was already decided, shown when a half-finished wizard is resumed.
|
|
64
|
+
*
|
|
65
|
+
* Persistence gives "continue" for free; what it does not give is remembering
|
|
66
|
+
* what you had answered, which is the known failure of a long flow restored
|
|
67
|
+
* mid-way ([#111](https://github.com/r10c-technologies/r10c/issues/111)).
|
|
68
|
+
*/
|
|
69
|
+
recap?: ReactNode;
|
|
70
|
+
/** Dismiss the recap. Omit and it has no dismiss control. */
|
|
71
|
+
onDismissRecap?: () => void;
|
|
72
|
+
isLoading?: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* What holds the wizard's shape while it is in flight.
|
|
75
|
+
*
|
|
76
|
+
* `true` (the default) renders the built-in placeholder, sized from the step
|
|
77
|
+
* count it was given so the swap to the real stepper shifts nothing. A node
|
|
78
|
+
* replaces that default; `false` renders no placeholder at all.
|
|
79
|
+
*/
|
|
80
|
+
skeleton?: boolean | ReactNode;
|
|
81
|
+
className?: string;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=wizard.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.types.d.ts","sourceRoot":"","sources":["../../../../src/ui/organisms/wizard/wizard.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CACnC;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;;;OAOG;IACH,KAAK,EAAE,SAAS,cAAc,EAAE,CAAC;IAEjC,2EAA2E;IAC3E,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd,8BAA8B;IAC9B,QAAQ,EAAE,SAAS,CAAC;IAEpB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,sEAAsE;IACtE,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAExC,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IAEvB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAE5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/ui/organisms/wizard/wizard.types.ts"],"sourcesContent":["import type { WizardStepStatus } from '@entifix/core';\nimport type { ReactNode } from 'react';\n\n/**\n * One step as the stepper shows it.\n *\n * `label` is **already-resolved copy**, not a catalog key, which is the rule\n * `ConfirmDialog`'s `title`/`message` already follow: a step's name belongs to\n * the domain that declared the wizard, so its copy is `shell:`-namespaced and\n * this package cannot type-check the key.\n */\nexport interface WizardStepView {\n readonly id: string;\n readonly label: string;\n readonly status: WizardStepStatus;\n}\n\nexport interface WizardProps {\n /**\n * The steps on the path this flow is taking, in order — the projection\n * `stepStatuses` returns, not the definition's whole step list.\n *\n * A graph's declared steps include branches not taken, so rendering all of\n * them promises an operator who chose to start blank a step they will never\n * see.\n */\n steps: readonly WizardStepView[];\n\n /** Which step's body `children` is. Controlled; the shell owns the URL. */\n activeStep: string;\n\n /**\n * The active step's heading.\n *\n * It is also the **focus target on advance**: moving focus to the top of the\n * new step is what makes a keyboard or screen-reader user land somewhere\n * meaningful instead of wherever the previous step's Next button was.\n */\n title: string;\n\n /** The active step's body. */\n children: ReactNode;\n\n onNext: () => void;\n onFinish: () => void;\n /** Absent at the entry step, where there is nowhere to go back to. */\n onPrevious?: () => void;\n /**\n * A completed step was clicked. Omit and the stepper is read-only.\n *\n * Only `complete` steps are clickable; a `pending` one would skip the per-step\n * submit that validates everything in between.\n */\n onStepChange?: (stepId: string) => void;\n\n /** The active step ends the flow, so the primary button reads Finalizar. */\n canFinish?: boolean;\n /** Advancing is blocked — a required answer is missing on this step. */\n canAdvance?: boolean;\n\n /**\n * The submit is in flight.\n *\n * It stays in flight: `onFinish` hands off and returns before the write is\n * terminal ([ADR 0043](../../../../../../../docs/adr/0043-the-optimistic-mutation-contract.md)),\n * so what this disables is a second submit — it is not a spinner waiting for\n * a resolution the caller never gets.\n */\n isSubmitting?: boolean;\n\n /**\n * What was already decided, shown when a half-finished wizard is resumed.\n *\n * Persistence gives \"continue\" for free; what it does not give is remembering\n * what you had answered, which is the known failure of a long flow restored\n * mid-way ([#111](https://github.com/r10c-technologies/r10c/issues/111)).\n */\n recap?: ReactNode;\n /** Dismiss the recap. Omit and it has no dismiss control. */\n onDismissRecap?: () => void;\n\n isLoading?: boolean;\n /**\n * What holds the wizard's shape while it is in flight.\n *\n * `true` (the default) renders the built-in placeholder, sized from the step\n * count it was given so the swap to the real stepper shifts nothing. A node\n * replaces that default; `false` renders no placeholder at all.\n */\n skeleton?: boolean | ReactNode;\n\n className?: string;\n}\n"],"names":[],"mappings":"AAiBA,WA2EC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/cn.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,CAAC;AAE3D,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAElD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/utils/cn.ts"],"sourcesContent":["/** Tiny class-name joiner. Filters falsy values; no external dependency. */\nexport type ClassValue = string | false | null | undefined;\n\nexport function cn(...values: ClassValue[]): string {\n return values.filter(Boolean).join(' ');\n}\n"],"names":["cn","values","filter","Boolean","join"],"mappings":"AAAA,0EAA0E,GAG1E,OAAO,SAASA,GAAG,GAAGC,MAAoB;IACxC,OAAOA,OAAOC,MAAM,CAACC,SAASC,IAAI,CAAC;AACrC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** One chord, described the way a person would say it. */
|
|
2
|
+
export interface Hotkey {
|
|
3
|
+
/** The `KeyboardEvent.key`, compared case-insensitively. */
|
|
4
|
+
readonly key: string;
|
|
5
|
+
/** ⌘ on a Mac, Ctrl elsewhere. Either satisfies it. */
|
|
6
|
+
readonly mod?: boolean;
|
|
7
|
+
readonly shift?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Fire `handler` when any of `hotkeys` is pressed, anywhere on the page.
|
|
11
|
+
*
|
|
12
|
+
* The repo's first global shortcut, so two things are decided here rather than
|
|
13
|
+
* at each future call site.
|
|
14
|
+
*
|
|
15
|
+
* **It skips while focus is in an editable element**, because a page-wide
|
|
16
|
+
* listener that does not would eat the chord a person meant for the field they
|
|
17
|
+
* are typing in. The palette's own input is exempt in practice: the palette
|
|
18
|
+
* unmounts its trigger's listener behaviour by simply not being open.
|
|
19
|
+
*
|
|
20
|
+
* **It calls `preventDefault`**, which is what stops the browser acting on a
|
|
21
|
+
* chord it also claims. ⚠️ That is not guaranteed to work: Chrome, Safari and
|
|
22
|
+
* Edge dispatch these to the page and honour it, Firefox reserves some chords
|
|
23
|
+
* and ignores `defaultPrevented` for them. So no single binding may be
|
|
24
|
+
* load-bearing — bind more than one, and always leave a visible control that
|
|
25
|
+
* does the same thing.
|
|
26
|
+
*
|
|
27
|
+
* `handler` is held in a ref so a caller may pass an inline closure without
|
|
28
|
+
* re-subscribing the listener on every render.
|
|
29
|
+
*/
|
|
30
|
+
export declare function useHotkey(hotkeys: readonly Hotkey[], handler: (event: KeyboardEvent) => void): void;
|
|
31
|
+
//# sourceMappingURL=use-hotkey.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-hotkey.d.ts","sourceRoot":"","sources":["../../../src/ui/utils/use-hotkey.ts"],"names":[],"mappings":"AAIA,0DAA0D;AAC1D,MAAM,WAAW,MAAM;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AA2BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,GACtC,IAAI,CAwBN"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
const isEditable = (target)=>{
|
|
4
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
5
|
+
const tag = target.tagName;
|
|
6
|
+
if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;
|
|
7
|
+
// `closest`, not `isContentEditable`: the property is true for a *descendant*
|
|
8
|
+
// of an editable host but is not implemented in jsdom, so the branch that
|
|
9
|
+
// matters most for a rich editor would be the one no test could reach. The
|
|
10
|
+
// selector covers the host and everything inside it, and the `:not` arm is
|
|
11
|
+
// what keeps `contenteditable="false"` — the way a widget opts a subtree back
|
|
12
|
+
// out — from reading as editable.
|
|
13
|
+
return target.closest('[contenteditable]:not([contenteditable="false"])') !== null;
|
|
14
|
+
};
|
|
15
|
+
const matches = (event, hotkey)=>{
|
|
16
|
+
var _hotkey_mod, _hotkey_shift;
|
|
17
|
+
if (event.key.toLowerCase() !== hotkey.key.toLowerCase()) return false;
|
|
18
|
+
// ⌘ and Ctrl are the same intent on different platforms, so either satisfies
|
|
19
|
+
// `mod` rather than the hook asking the caller to sniff the platform. Nothing
|
|
20
|
+
// in the fleet binds a chord that means one thing with ⌘ and another with Ctrl.
|
|
21
|
+
const mod = event.metaKey || event.ctrlKey;
|
|
22
|
+
if (((_hotkey_mod = hotkey.mod) != null ? _hotkey_mod : false) !== mod) return false;
|
|
23
|
+
return ((_hotkey_shift = hotkey.shift) != null ? _hotkey_shift : false) === event.shiftKey;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Fire `handler` when any of `hotkeys` is pressed, anywhere on the page.
|
|
27
|
+
*
|
|
28
|
+
* The repo's first global shortcut, so two things are decided here rather than
|
|
29
|
+
* at each future call site.
|
|
30
|
+
*
|
|
31
|
+
* **It skips while focus is in an editable element**, because a page-wide
|
|
32
|
+
* listener that does not would eat the chord a person meant for the field they
|
|
33
|
+
* are typing in. The palette's own input is exempt in practice: the palette
|
|
34
|
+
* unmounts its trigger's listener behaviour by simply not being open.
|
|
35
|
+
*
|
|
36
|
+
* **It calls `preventDefault`**, which is what stops the browser acting on a
|
|
37
|
+
* chord it also claims. ⚠️ That is not guaranteed to work: Chrome, Safari and
|
|
38
|
+
* Edge dispatch these to the page and honour it, Firefox reserves some chords
|
|
39
|
+
* and ignores `defaultPrevented` for them. So no single binding may be
|
|
40
|
+
* load-bearing — bind more than one, and always leave a visible control that
|
|
41
|
+
* does the same thing.
|
|
42
|
+
*
|
|
43
|
+
* `handler` is held in a ref so a caller may pass an inline closure without
|
|
44
|
+
* re-subscribing the listener on every render.
|
|
45
|
+
*/ export function useHotkey(hotkeys, handler) {
|
|
46
|
+
const handlerRef = useRef(handler);
|
|
47
|
+
useEffect(()=>{
|
|
48
|
+
handlerRef.current = handler;
|
|
49
|
+
});
|
|
50
|
+
// Serialized rather than passed by identity: callers build the array inline,
|
|
51
|
+
// so the array itself is a new object every render and would re-subscribe the
|
|
52
|
+
// listener on each one.
|
|
53
|
+
const signature = JSON.stringify(hotkeys);
|
|
54
|
+
useEffect(()=>{
|
|
55
|
+
const bindings = JSON.parse(signature);
|
|
56
|
+
const onKeyDown = (event)=>{
|
|
57
|
+
if (isEditable(event.target)) return;
|
|
58
|
+
if (!bindings.some((hotkey)=>matches(event, hotkey))) return;
|
|
59
|
+
event.preventDefault();
|
|
60
|
+
handlerRef.current(event);
|
|
61
|
+
};
|
|
62
|
+
document.addEventListener('keydown', onKeyDown);
|
|
63
|
+
return ()=>document.removeEventListener('keydown', onKeyDown);
|
|
64
|
+
}, [
|
|
65
|
+
signature
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=use-hotkey.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/ui/utils/use-hotkey.ts"],"sourcesContent":["'use client';\n\nimport { useEffect, useRef } from 'react';\n\n/** One chord, described the way a person would say it. */\nexport interface Hotkey {\n /** The `KeyboardEvent.key`, compared case-insensitively. */\n readonly key: string;\n /** ⌘ on a Mac, Ctrl elsewhere. Either satisfies it. */\n readonly mod?: boolean;\n readonly shift?: boolean;\n}\n\nconst isEditable = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;\n // `closest`, not `isContentEditable`: the property is true for a *descendant*\n // of an editable host but is not implemented in jsdom, so the branch that\n // matters most for a rich editor would be the one no test could reach. The\n // selector covers the host and everything inside it, and the `:not` arm is\n // what keeps `contenteditable=\"false\"` — the way a widget opts a subtree back\n // out — from reading as editable.\n return (\n target.closest('[contenteditable]:not([contenteditable=\"false\"])') !== null\n );\n};\n\nconst matches = (event: KeyboardEvent, hotkey: Hotkey): boolean => {\n if (event.key.toLowerCase() !== hotkey.key.toLowerCase()) return false;\n // ⌘ and Ctrl are the same intent on different platforms, so either satisfies\n // `mod` rather than the hook asking the caller to sniff the platform. Nothing\n // in the fleet binds a chord that means one thing with ⌘ and another with Ctrl.\n const mod = event.metaKey || event.ctrlKey;\n if ((hotkey.mod ?? false) !== mod) return false;\n return (hotkey.shift ?? false) === event.shiftKey;\n};\n\n/**\n * Fire `handler` when any of `hotkeys` is pressed, anywhere on the page.\n *\n * The repo's first global shortcut, so two things are decided here rather than\n * at each future call site.\n *\n * **It skips while focus is in an editable element**, because a page-wide\n * listener that does not would eat the chord a person meant for the field they\n * are typing in. The palette's own input is exempt in practice: the palette\n * unmounts its trigger's listener behaviour by simply not being open.\n *\n * **It calls `preventDefault`**, which is what stops the browser acting on a\n * chord it also claims. ⚠️ That is not guaranteed to work: Chrome, Safari and\n * Edge dispatch these to the page and honour it, Firefox reserves some chords\n * and ignores `defaultPrevented` for them. So no single binding may be\n * load-bearing — bind more than one, and always leave a visible control that\n * does the same thing.\n *\n * `handler` is held in a ref so a caller may pass an inline closure without\n * re-subscribing the listener on every render.\n */\nexport function useHotkey(\n hotkeys: readonly Hotkey[],\n handler: (event: KeyboardEvent) => void,\n): void {\n const handlerRef = useRef(handler);\n useEffect(() => {\n handlerRef.current = handler;\n });\n\n // Serialized rather than passed by identity: callers build the array inline,\n // so the array itself is a new object every render and would re-subscribe the\n // listener on each one.\n const signature = JSON.stringify(hotkeys);\n\n useEffect(() => {\n const bindings = JSON.parse(signature) as Hotkey[];\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (isEditable(event.target)) return;\n if (!bindings.some(hotkey => matches(event, hotkey))) return;\n event.preventDefault();\n handlerRef.current(event);\n };\n\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [signature]);\n}\n"],"names":["useEffect","useRef","isEditable","target","HTMLElement","tag","tagName","closest","matches","event","hotkey","key","toLowerCase","mod","metaKey","ctrlKey","shift","shiftKey","useHotkey","hotkeys","handler","handlerRef","current","signature","JSON","stringify","bindings","parse","onKeyDown","some","preventDefault","document","addEventListener","removeEventListener"],"mappings":"AAAA;AAEA,SAASA,SAAS,EAAEC,MAAM,QAAQ,QAAQ;AAW1C,MAAMC,aAAa,CAACC;IAClB,IAAI,CAAEA,CAAAA,kBAAkBC,WAAU,GAAI,OAAO;IAC7C,MAAMC,MAAMF,OAAOG,OAAO;IAC1B,IAAID,QAAQ,WAAWA,QAAQ,cAAcA,QAAQ,UAAU,OAAO;IACtE,8EAA8E;IAC9E,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,8EAA8E;IAC9E,kCAAkC;IAClC,OACEF,OAAOI,OAAO,CAAC,wDAAwD;AAE3E;AAEA,MAAMC,UAAU,CAACC,OAAsBC;QAMhCA,aACGA;IANR,IAAID,MAAME,GAAG,CAACC,WAAW,OAAOF,OAAOC,GAAG,CAACC,WAAW,IAAI,OAAO;IACjE,6EAA6E;IAC7E,8EAA8E;IAC9E,gFAAgF;IAChF,MAAMC,MAAMJ,MAAMK,OAAO,IAAIL,MAAMM,OAAO;IAC1C,IAAI,EAACL,cAAAA,OAAOG,GAAG,YAAVH,cAAc,WAAWG,KAAK,OAAO;IAC1C,OAAO,EAACH,gBAAAA,OAAOM,KAAK,YAAZN,gBAAgB,WAAWD,MAAMQ,QAAQ;AACnD;AAEA;;;;;;;;;;;;;;;;;;;;CAoBC,GACD,OAAO,SAASC,UACdC,OAA0B,EAC1BC,OAAuC;IAEvC,MAAMC,aAAapB,OAAOmB;IAC1BpB,UAAU;QACRqB,WAAWC,OAAO,GAAGF;IACvB;IAEA,6EAA6E;IAC7E,8EAA8E;IAC9E,wBAAwB;IACxB,MAAMG,YAAYC,KAAKC,SAAS,CAACN;IAEjCnB,UAAU;QACR,MAAM0B,WAAWF,KAAKG,KAAK,CAACJ;QAE5B,MAAMK,YAAY,CAACnB;YACjB,IAAIP,WAAWO,MAAMN,MAAM,GAAG;YAC9B,IAAI,CAACuB,SAASG,IAAI,CAACnB,CAAAA,SAAUF,QAAQC,OAAOC,UAAU;YACtDD,MAAMqB,cAAc;YACpBT,WAAWC,OAAO,CAACb;QACrB;QAEAsB,SAASC,gBAAgB,CAAC,WAAWJ;QACrC,OAAO,IAAMG,SAASE,mBAAmB,CAAC,WAAWL;IACvD,GAAG;QAACL;KAAU;AAChB"}
|