@eifi1/ui-kit 0.4.1 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +32 -0
- package/README.md +498 -57
- package/dist/chart.d.ts +10 -0
- package/dist/chart.js +10 -0
- package/dist/chart.js.map +1 -0
- package/dist/components/account-settings.d.ts +11 -0
- package/dist/components/account-settings.js +19 -12
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/alert-banner.d.ts +10 -6
- package/dist/components/alert-banner.js +20 -16
- package/dist/components/alert-banner.js.map +1 -1
- package/dist/components/amount-input.d.ts +30 -4
- package/dist/components/amount-input.js +36 -14
- package/dist/components/amount-input.js.map +1 -1
- package/dist/components/calculator.d.ts +24 -7
- package/dist/components/calculator.js +37 -20
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/chart-zoom.d.ts +156 -0
- package/dist/components/chart-zoom.js +262 -0
- package/dist/components/chart-zoom.js.map +1 -0
- package/dist/components/chart.d.ts +28 -3
- package/dist/components/chart.js +71 -32
- package/dist/components/chart.js.map +1 -1
- package/dist/components/checkbox.d.ts +51 -0
- package/dist/components/checkbox.js +123 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/chip.d.ts +142 -0
- package/dist/components/chip.js +357 -0
- package/dist/components/chip.js.map +1 -0
- package/dist/components/choice-parts.d.ts +24 -0
- package/dist/components/choice-parts.js +18 -0
- package/dist/components/choice-parts.js.map +1 -0
- package/dist/components/combobox-core.d.ts +52 -9
- package/dist/components/combobox-core.js +89 -19
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.d.ts +43 -33
- package/dist/components/combobox.js +409 -340
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/currency-select.d.ts +48 -8
- package/dist/components/currency-select.js +115 -65
- package/dist/components/currency-select.js.map +1 -1
- package/dist/components/data-table-filter-popover.d.ts +15 -3
- package/dist/components/data-table-filter-popover.js +23 -17
- package/dist/components/data-table-filter-popover.js.map +1 -1
- package/dist/components/data-table-filters.d.ts +1 -1
- package/dist/components/data-table-filters.js +3 -2
- package/dist/components/data-table-filters.js.map +1 -1
- package/dist/components/data-table-labels.d.ts +53 -2
- package/dist/components/data-table-labels.js +31 -2
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-pagination.d.ts +3 -1
- package/dist/components/data-table-pagination.js +16 -10
- package/dist/components/data-table-pagination.js.map +1 -1
- package/dist/components/data-table-sort.js +1 -0
- package/dist/components/data-table-sort.js.map +1 -1
- package/dist/components/data-table.d.ts +1 -1
- package/dist/components/data-table.js +201 -85
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.d.ts +25 -9
- package/dist/components/date-picker.js +244 -94
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/dropdown.d.ts +74 -19
- package/dist/components/dropdown.js +72 -22
- package/dist/components/dropdown.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +5 -4
- package/dist/components/entity-combobox.js +107 -76
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +36 -0
- package/dist/components/facing-pair.js +40 -0
- package/dist/components/facing-pair.js.map +1 -0
- package/dist/components/field-sync.d.ts +164 -0
- package/dist/components/field-sync.js +264 -0
- package/dist/components/field-sync.js.map +1 -0
- package/dist/components/file-dropzone.d.ts +21 -7
- package/dist/components/file-dropzone.js +28 -7
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/full-bleed-dialog.d.ts +37 -26
- package/dist/components/full-bleed-dialog.js +20 -5
- package/dist/components/full-bleed-dialog.js.map +1 -1
- package/dist/components/grouped-picker.d.ts +21 -10
- package/dist/components/grouped-picker.js +66 -52
- package/dist/components/grouped-picker.js.map +1 -1
- package/dist/components/hover-menu.d.ts +20 -4
- package/dist/components/hover-menu.js +15 -4
- package/dist/components/hover-menu.js.map +1 -1
- package/dist/components/mini-calendar.d.ts +102 -14
- package/dist/components/mini-calendar.js +256 -70
- package/dist/components/mini-calendar.js.map +1 -1
- package/dist/components/modal.d.ts +9 -3
- package/dist/components/modal.js +34 -45
- package/dist/components/modal.js.map +1 -1
- package/dist/components/month-picker.d.ts +79 -0
- package/dist/components/month-picker.js +353 -0
- package/dist/components/month-picker.js.map +1 -0
- package/dist/components/multi-entity-combobox.d.ts +7 -6
- package/dist/components/multi-entity-combobox.js +112 -72
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/multi-select.d.ts +13 -11
- package/dist/components/multi-select.js +161 -84
- package/dist/components/multi-select.js.map +1 -1
- package/dist/components/number-field.d.ts +92 -0
- package/dist/components/number-field.js +111 -0
- package/dist/components/number-field.js.map +1 -0
- package/dist/components/number-input.d.ts +21 -2
- package/dist/components/number-input.js +2 -1
- package/dist/components/number-input.js.map +1 -1
- package/dist/components/numpad-sheet.d.ts +25 -4
- package/dist/components/numpad-sheet.js +30 -13
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/page-contents.d.ts +90 -0
- package/dist/components/page-contents.js +170 -0
- package/dist/components/page-contents.js.map +1 -0
- package/dist/components/password-strength.d.ts +106 -0
- package/dist/components/password-strength.js +132 -0
- package/dist/components/password-strength.js.map +1 -0
- package/dist/components/picker-sheet.d.ts +23 -15
- package/dist/components/picker-sheet.js +34 -14
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/popover.d.ts +62 -4
- package/dist/components/popover.js +55 -2
- package/dist/components/popover.js.map +1 -1
- package/dist/components/search-field.d.ts +25 -7
- package/dist/components/search-field.js +7 -5
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/series-chart-labels.d.ts +14 -0
- package/dist/components/series-chart-labels.js +11 -0
- package/dist/components/series-chart-labels.js.map +1 -0
- package/dist/components/series-chart.d.ts +207 -0
- package/dist/components/series-chart.js +223 -0
- package/dist/components/series-chart.js.map +1 -0
- package/dist/components/settings-fields.d.ts +14 -4
- package/dist/components/settings-fields.js +19 -8
- package/dist/components/settings-fields.js.map +1 -1
- package/dist/components/signature-pad.d.ts +119 -0
- package/dist/components/signature-pad.js +405 -0
- package/dist/components/signature-pad.js.map +1 -0
- package/dist/components/slider.d.ts +80 -0
- package/dist/components/slider.js +155 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/sparkline.d.ts +93 -0
- package/dist/components/sparkline.js +205 -0
- package/dist/components/sparkline.js.map +1 -0
- package/dist/components/stat-tile.d.ts +151 -0
- package/dist/components/stat-tile.js +236 -0
- package/dist/components/stat-tile.js.map +1 -0
- package/dist/components/swipeable-row.d.ts +25 -2
- package/dist/components/swipeable-row.js +31 -0
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +60 -0
- package/dist/components/switch.js +81 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/time-input.d.ts +58 -0
- package/dist/components/time-input.js +50 -0
- package/dist/components/time-input.js.map +1 -0
- package/dist/components/toggle-group.d.ts +18 -3
- package/dist/components/toggle-group.js +10 -6
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/toggle-legend.d.ts +115 -0
- package/dist/components/toggle-legend.js +114 -0
- package/dist/components/toggle-legend.js.map +1 -0
- package/dist/components/tooltip.d.ts +40 -11
- package/dist/components/tooltip.js +77 -20
- package/dist/components/tooltip.js.map +1 -1
- package/dist/components/treemap.d.ts +132 -0
- package/dist/components/treemap.js +179 -0
- package/dist/components/treemap.js.map +1 -0
- package/dist/components/trigger-aria.d.ts +18 -0
- package/dist/components/trigger-aria.js +25 -0
- package/dist/components/trigger-aria.js.map +1 -0
- package/dist/components/ui.d.ts +167 -46
- package/dist/components/ui.js +225 -121
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-mobile-reveal.js +1 -0
- package/dist/components/use-mobile-reveal.js.map +1 -1
- package/dist/components/use-table-state.d.ts +1 -1
- package/dist/components/use-table-state.js +38 -17
- package/dist/components/use-table-state.js.map +1 -1
- package/dist/components/user-avatar.d.ts +5 -3
- package/dist/components/user-avatar.js +4 -2
- package/dist/components/user-avatar.js.map +1 -1
- package/dist/components/wizard-stepper.js +3 -2
- package/dist/components/wizard-stepper.js.map +1 -1
- package/dist/{data-table-filters-aXyf0Xub.d.ts → data-table-filters-DM1auUfH.d.ts} +27 -5
- package/dist/data-table.d.ts +7 -0
- package/dist/data-table.js +12 -0
- package/dist/data-table.js.map +1 -0
- package/dist/feedback/feedback-attachment.js +12 -11
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-dialog.js +2 -1
- package/dist/feedback/feedback-dialog.js.map +1 -1
- package/dist/feedback/feedback-inbox.d.ts +33 -7
- package/dist/feedback/feedback-inbox.js +49 -37
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback.d.ts +5 -0
- package/dist/feedback.js +5 -0
- package/dist/feedback.js.map +1 -0
- package/dist/hooks/use-anchored-panel.js +1 -0
- package/dist/hooks/use-anchored-panel.js.map +1 -1
- package/dist/hooks/use-anchored-rect.js +1 -0
- package/dist/hooks/use-anchored-rect.js.map +1 -1
- package/dist/hooks/use-announce.d.ts +46 -0
- package/dist/hooks/use-announce.js +37 -0
- package/dist/hooks/use-announce.js.map +1 -0
- package/dist/hooks/use-body-scroll-lock.js +1 -0
- package/dist/hooks/use-body-scroll-lock.js.map +1 -1
- package/dist/hooks/use-close-transition.js +1 -0
- package/dist/hooks/use-close-transition.js.map +1 -1
- package/dist/hooks/use-dismiss.js +1 -0
- package/dist/hooks/use-dismiss.js.map +1 -1
- package/dist/hooks/use-focus-trap.d.ts +16 -0
- package/dist/hooks/use-focus-trap.js +67 -0
- package/dist/hooks/use-focus-trap.js.map +1 -0
- package/dist/hooks/use-media-query.js +1 -0
- package/dist/hooks/use-media-query.js.map +1 -1
- package/dist/hooks/use-overlay-history.js +27 -1
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/hooks/use-row-swipe.js +1 -0
- package/dist/hooks/use-row-swipe.js.map +1 -1
- package/dist/i18n/defaults.d.ts +31 -0
- package/dist/i18n/defaults.js +63 -0
- package/dist/i18n/defaults.js.map +1 -0
- package/dist/i18n/kit-labels.d.ts +250 -0
- package/dist/i18n/kit-labels.js +184 -0
- package/dist/i18n/kit-labels.js.map +1 -0
- package/dist/index.d.ts +47 -22
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/calc.js +1 -0
- package/dist/lib/calc.js.map +1 -1
- package/dist/lib/cn.js +1 -0
- package/dist/lib/cn.js.map +1 -1
- package/dist/lib/dates.js +1 -0
- package/dist/lib/dates.js.map +1 -1
- package/dist/lib/logger.js +1 -0
- package/dist/lib/logger.js.map +1 -1
- package/dist/lib/safe-storage.js +1 -0
- package/dist/lib/safe-storage.js.map +1 -1
- package/dist/search/command-palette.d.ts +11 -1
- package/dist/search/command-palette.js +21 -15
- package/dist/search/command-palette.js.map +1 -1
- package/dist/search.d.ts +2 -0
- package/dist/search.js +3 -0
- package/dist/search.js.map +1 -0
- package/dist/shell/app-shell.d.ts +33 -4
- package/dist/shell/app-shell.js +275 -78
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/option-switcher-menu.js +3 -2
- package/dist/shell/option-switcher-menu.js.map +1 -1
- package/dist/shell/role-switcher.d.ts +6 -0
- package/dist/shell/role-switcher.js +7 -4
- package/dist/shell/role-switcher.js.map +1 -1
- package/dist/shell/top-bar.d.ts +15 -7
- package/dist/shell/top-bar.js +3 -5
- package/dist/shell/top-bar.js.map +1 -1
- package/dist/shell/topbar-action-menu.js +3 -2
- package/dist/shell/topbar-action-menu.js.map +1 -1
- package/dist/shell/topbar-controls.d.ts +5 -2
- package/dist/shell/topbar-controls.js +20 -15
- package/dist/shell/topbar-controls.js.map +1 -1
- package/dist/shell.d.ts +13 -0
- package/dist/shell.js +8 -0
- package/dist/shell.js.map +1 -0
- package/dist/theme/chart-palette.d.ts +19 -12
- package/dist/theme/chart-palette.js +24 -30
- package/dist/theme/chart-palette.js.map +1 -1
- package/dist/theme/color.d.ts +78 -0
- package/dist/theme/color.js +148 -0
- package/dist/theme/color.js.map +1 -0
- package/dist/theme/palette-derive.d.ts +140 -0
- package/dist/theme/palette-derive.js +376 -0
- package/dist/theme/palette-derive.js.map +1 -0
- package/dist/theme/palette-presets.d.ts +14 -1
- package/dist/theme/palette-presets.js +231 -3
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/theme/palette-store.js +1 -0
- package/dist/theme/palette-store.js.map +1 -1
- package/dist/theme/theme-store.js +1 -0
- package/dist/theme/theme-store.js.map +1 -1
- package/dist/tour/tour.d.ts +2 -1
- package/dist/tour/tour.js +15 -9
- package/dist/tour/tour.js.map +1 -1
- package/dist/tour.d.ts +2 -0
- package/dist/tour.js +3 -0
- package/dist/tour.js.map +1 -0
- package/dist/wizard/stepper-nav.js +10 -8
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard/types.d.ts +18 -2
- package/dist/wizard/types.js +4 -1
- package/dist/wizard/types.js.map +1 -1
- package/dist/wizard/use-wizard.js +12 -4
- package/dist/wizard/use-wizard.js.map +1 -1
- package/dist/wizard/validation.js +1 -0
- package/dist/wizard/validation.js.map +1 -1
- package/dist/wizard/wizard-context.js +1 -0
- package/dist/wizard/wizard-context.js.map +1 -1
- package/dist/wizard/wizard-step.js +1 -0
- package/dist/wizard/wizard-step.js.map +1 -1
- package/dist/wizard/wizard-summary.js +5 -3
- package/dist/wizard/wizard-summary.js.map +1 -1
- package/dist/wizard.d.ts +8 -0
- package/dist/wizard.js +9 -0
- package/dist/wizard.js.map +1 -0
- package/package.json +66 -13
- package/src/chart.ts +22 -0
- package/src/components/account-settings.tsx +275 -0
- package/src/components/alert-banner.tsx +75 -0
- package/src/components/amount-input.tsx +471 -0
- package/src/components/calculator.tsx +252 -0
- package/src/components/chart-zoom.tsx +499 -0
- package/src/components/chart.tsx +363 -0
- package/src/components/checkbox.tsx +222 -0
- package/src/components/chip.tsx +584 -0
- package/src/components/choice-parts.ts +33 -0
- package/src/components/combobox-core.tsx +540 -0
- package/src/components/combobox.tsx +1026 -0
- package/src/components/currency-select.tsx +283 -0
- package/src/components/data-table-filter-popover.tsx +252 -0
- package/src/components/data-table-filters.ts +176 -0
- package/src/components/data-table-labels.ts +190 -0
- package/src/components/data-table-pagination.tsx +126 -0
- package/src/components/data-table-sort.ts +70 -0
- package/src/components/data-table.tsx +1740 -0
- package/src/components/date-picker.tsx +656 -0
- package/src/components/dropdown.tsx +341 -0
- package/src/components/entity-combobox.tsx +215 -0
- package/src/components/facing-pair.ts +86 -0
- package/src/components/field-sync.tsx +472 -0
- package/src/components/file-dropzone.tsx +181 -0
- package/src/components/full-bleed-dialog.tsx +179 -0
- package/src/components/grouped-picker.tsx +157 -0
- package/src/components/hover-menu.tsx +183 -0
- package/src/components/mini-calendar.tsx +554 -0
- package/src/components/modal.tsx +287 -0
- package/src/components/month-picker.tsx +567 -0
- package/src/components/multi-entity-combobox.tsx +226 -0
- package/src/components/multi-select.tsx +303 -0
- package/src/components/number-field.tsx +225 -0
- package/src/components/number-input.tsx +211 -0
- package/src/components/numpad-sheet.tsx +264 -0
- package/src/components/page-contents.tsx +289 -0
- package/src/components/password-strength.tsx +258 -0
- package/src/components/picker-sheet.tsx +251 -0
- package/src/components/popover.tsx +198 -0
- package/src/components/search-field.tsx +146 -0
- package/src/components/series-chart-labels.ts +26 -0
- package/src/components/series-chart.tsx +481 -0
- package/src/components/settings-fields.tsx +68 -0
- package/src/components/signature-pad.tsx +630 -0
- package/src/components/slider.tsx +313 -0
- package/src/components/sparkline.tsx +329 -0
- package/src/components/stat-tile.tsx +448 -0
- package/src/components/swipeable-row.tsx +271 -0
- package/src/components/switch.tsx +170 -0
- package/src/components/time-input.tsx +107 -0
- package/src/components/toggle-group.tsx +153 -0
- package/src/components/toggle-legend.tsx +229 -0
- package/src/components/tooltip.tsx +477 -0
- package/src/components/treemap.tsx +390 -0
- package/src/components/trigger-aria.ts +42 -0
- package/src/components/ui.tsx +1295 -0
- package/src/components/use-mobile-reveal.ts +54 -0
- package/src/components/use-table-state.ts +295 -0
- package/src/components/user-avatar.tsx +61 -0
- package/src/components/wizard-stepper.tsx +37 -0
- package/src/data-table.ts +19 -0
- package/src/feedback/feedback-attachment.tsx +246 -0
- package/src/feedback/feedback-dialog.tsx +209 -0
- package/src/feedback/feedback-inbox.tsx +615 -0
- package/src/feedback.ts +8 -0
- package/src/hooks/use-anchored-panel.ts +169 -0
- package/src/hooks/use-anchored-rect.ts +78 -0
- package/src/hooks/use-announce.ts +85 -0
- package/src/hooks/use-body-scroll-lock.ts +94 -0
- package/src/hooks/use-close-transition.ts +99 -0
- package/src/hooks/use-dismiss.ts +77 -0
- package/src/hooks/use-focus-trap.ts +160 -0
- package/src/hooks/use-media-query.ts +23 -0
- package/src/hooks/use-overlay-history.ts +345 -0
- package/src/hooks/use-row-swipe.ts +212 -0
- package/src/i18n/defaults.ts +68 -0
- package/src/i18n/kit-labels.tsx +447 -0
- package/src/index.ts +169 -0
- package/src/lib/calc.ts +309 -0
- package/src/lib/cn.ts +5 -0
- package/src/lib/dates.ts +187 -0
- package/src/lib/logger.ts +73 -0
- package/src/lib/safe-storage.ts +37 -0
- package/src/search/command-palette.tsx +342 -0
- package/src/search.ts +3 -0
- package/src/shell/app-shell.tsx +772 -0
- package/src/shell/option-switcher-menu.tsx +72 -0
- package/src/shell/role-switcher.tsx +46 -0
- package/src/shell/top-bar.tsx +39 -0
- package/src/shell/topbar-action-menu.tsx +91 -0
- package/src/shell/topbar-controls.tsx +229 -0
- package/src/shell.ts +10 -0
- package/src/theme/chart-palette.ts +145 -0
- package/src/theme/color.ts +266 -0
- package/src/theme/palette-derive.ts +681 -0
- package/src/theme/palette-presets.ts +760 -0
- package/src/theme/palette-store.ts +94 -0
- package/src/theme/theme-store.ts +145 -0
- package/src/tour/tour.tsx +586 -0
- package/src/tour.ts +3 -0
- package/src/vite-env.d.ts +26 -0
- package/src/wizard/stepper-nav.tsx +221 -0
- package/src/wizard/types.ts +178 -0
- package/src/wizard/use-wizard.ts +345 -0
- package/src/wizard/validation.ts +37 -0
- package/src/wizard/wizard-context.tsx +29 -0
- package/src/wizard/wizard-step.tsx +14 -0
- package/src/wizard/wizard-summary.tsx +69 -0
- package/src/wizard.ts +14 -0
- package/tokens.css +222 -20
package/LICENSE
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marcel Eifert
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
THIRD-PARTY NOTICES
|
|
26
|
+
|
|
27
|
+
src/components/chart.tsx is adapted from the shadcn/ui chart kit
|
|
28
|
+
(https://ui.shadcn.com), Copyright (c) 2023 shadcn, MIT licensed. The structure
|
|
29
|
+
— config-driven series colours injected as CSS custom properties, the muted
|
|
30
|
+
axis/grid treatment, and the tooltip/legend content components — is retained;
|
|
31
|
+
it has been ported to Recharts 3 and re-skinned onto this package's own tokens
|
|
32
|
+
rather than shadcn's.
|
package/README.md
CHANGED
|
@@ -25,6 +25,25 @@ module so consumers can still tree-shake it (see the `sideEffects` note in
|
|
|
25
25
|
entry chunk). Tailwind classes are emitted as-is; each app still compiles them
|
|
26
26
|
with its own Tailwind config.
|
|
27
27
|
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
| | |
|
|
31
|
+
|---|---|
|
|
32
|
+
| [ADOPTING.md](https://github.com/Eifi1/ui-kit/blob/main/ADOPTING.md) | The brief for a new consuming app — hand it to that repo's agent |
|
|
33
|
+
| [MIGRATING.md](https://github.com/Eifi1/ui-kit/blob/main/MIGRATING.md) | Moving an app off the old `@hb/ui` submodule onto the npm package |
|
|
34
|
+
| [CHANGELOG.md](https://github.com/Eifi1/ui-kit/blob/main/CHANGELOG.md) | Every release, and the semver contract this package keeps below 1.0 |
|
|
35
|
+
| [CONTRIBUTING.md](https://github.com/Eifi1/ui-kit/blob/main/CONTRIBUTING.md) | Repo layout, the house rules, the gates, how to cut a release |
|
|
36
|
+
| [Issues](https://github.com/Eifi1/ui-kit/issues) | Bugs and requests |
|
|
37
|
+
|
|
38
|
+
The links are absolute because only this README is in the npm tarball — `files` ships
|
|
39
|
+
`dist`, `src`, `tokens.css` and `LICENSE`, so a reader who arrived from npmjs.com has none
|
|
40
|
+
of the others on disk and a relative link would be a 404.
|
|
41
|
+
|
|
42
|
+
A rendered catalogue of every component, with the theme, palette and language switchers
|
|
43
|
+
live, deploys to <https://eifi1.github.io/ui-kit/> on every push to `main`. It needs one
|
|
44
|
+
manual repo setting to go live, named at the top of `.github/workflows/pages.yml`; until
|
|
45
|
+
then, `npm run dev:showcase` from a checkout is the same page.
|
|
46
|
+
|
|
28
47
|
## Install
|
|
29
48
|
|
|
30
49
|
```bash
|
|
@@ -35,10 +54,43 @@ Versions are pinned in your lockfile like any dependency, so each app upgrades
|
|
|
35
54
|
when it chooses. To work on the design system and an app together, use
|
|
36
55
|
`npm link` or a workspace override rather than a `file:` path.
|
|
37
56
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
57
|
+
### What you install alongside it
|
|
58
|
+
|
|
59
|
+
| Package | Declared as | Why |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `react`, `react-dom` | peer, `>=19` | The kit is components and hooks; two copies of React break hooks and context. |
|
|
62
|
+
| `react-router` | peer, `>=7` | Imported unconditionally by `DataTable`, `useTableState`, `AppShell` and `useWizard`. A Router has to be mounted even with `urlSync` off. |
|
|
63
|
+
| `recharts` | peer, `>=3` | `@eifi1/ui-kit/chart` imports it statically. Only that subpath needs it — the main barrel no longer reaches it. |
|
|
64
|
+
| `lucide-react` | peer, `>=0.400.0 <2` | Icons, in 33 modules. **Yours to version.** |
|
|
65
|
+
| `sonner` | peer, `>=2`, **optional** | `FileDropzone` and the wizard's "fill in the required fields" toast, reached only through `await import()`. Pass `onValidationFailed` to route it elsewhere. |
|
|
66
|
+
| `clsx`, `tailwind-merge`, `zustand` | dependency | Small, imported directly, and the kit owns the version. Add `zustand` to Vite's `dedupe` (below) — the theme and palette stores are singletons. |
|
|
67
|
+
| `flag-icons` | **nothing — you supply the stylesheet** | See below. |
|
|
68
|
+
|
|
69
|
+
**`lucide-react` is a peer from 0.5.0, not a dependency.** All three consumers already
|
|
70
|
+
declared it themselves, so a hard dependency here bought each of them a second copy of the
|
|
71
|
+
icon set — and `^0.511.0` on a 0.x package is a *patch* pin, which held them on 0.511.x
|
|
72
|
+
while the line moved to 1.x. The range is wide on purpose: the kit imports named icon
|
|
73
|
+
components and nothing else, and that has been stable across the whole span. *Migration:*
|
|
74
|
+
none if you already depend on it; otherwise `npm install lucide-react`.
|
|
75
|
+
|
|
76
|
+
**`flag-icons` is a host contract, not a dependency.** `CurrencyFlag`, `CurrencySelect`
|
|
77
|
+
(and `AmountInput`'s currency picker, which uses it) and `LanguageMenu` render flags as
|
|
78
|
+
class names — `<span class="fi fi-ch">` — and nothing in the package imports a stylesheet.
|
|
79
|
+
The app provides it:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm install flag-icons
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// main.tsx, once, next to your other global CSS
|
|
87
|
+
import "flag-icons/css/flag-icons.min.css";
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Without it those flags are empty boxes: no error, no warning, just missing glyphs in the
|
|
91
|
+
currency picker and the language menu. It was a 5.6 MB hard dependency through 0.4.x —
|
|
92
|
+
installed into every consumer and imported by nothing — so it may still be in your tree
|
|
93
|
+
transitively after upgrading. Depend on it explicitly if you render any of the three.
|
|
42
94
|
|
|
43
95
|
## Wiring
|
|
44
96
|
|
|
@@ -59,10 +111,28 @@ resolve: {
|
|
|
59
111
|
```css
|
|
60
112
|
/* app.css */
|
|
61
113
|
@import "tailwindcss";
|
|
62
|
-
@import "@eifi1/ui-kit/tokens.css";
|
|
63
|
-
@source "../../node_modules/@eifi1/ui-kit/
|
|
114
|
+
@import "@eifi1/ui-kit/tokens.css"; /* design tokens, semantic utilities, chrome */
|
|
115
|
+
@source "../../node_modules/@eifi1/ui-kit/dist"; /* keep the class names @eifi1/ui-kit uses */
|
|
64
116
|
```
|
|
65
117
|
|
|
118
|
+
**Get this path right, and check it.** Tailwind never scans `node_modules`, so without
|
|
119
|
+
`@source` none of the kit's class names are generated and the components render
|
|
120
|
+
*unstyled* — laid out, interactive, and completely unpainted. Nothing errors, so it
|
|
121
|
+
looks like a broken design system rather than a missing line. The path is relative to
|
|
122
|
+
**the CSS file it is written in**, not to the project root; count the `../` from there.
|
|
123
|
+
|
|
124
|
+
To verify in ten seconds: build, then grep the emitted CSS for a class only this
|
|
125
|
+
package uses.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
npm run build && grep -c 'pointer-events-auto' dist/assets/*.css # 0 means the scan missed
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Scanning `dist` is the recommended path: it is published by every version. From
|
|
132
|
+
v0.5.0 the tarball also ships `src`, so `@source ".../@eifi1/ui-kit/src"` works too and
|
|
133
|
+
scans the original TSX rather than transpiled output — but it is not present in
|
|
134
|
+
v0.4.x, and an `@source` pointing at a directory that does not exist fails silently.
|
|
135
|
+
|
|
66
136
|
### 3. Theme + palette stores (own persistence keys)
|
|
67
137
|
|
|
68
138
|
The stores are factories so each app namespaces its own `localStorage`:
|
|
@@ -75,8 +145,201 @@ export const { usePalette, useApplyPalette, useActiveTokenSet, useChartHex, useH
|
|
|
75
145
|
```
|
|
76
146
|
|
|
77
147
|
Call `useApplyTheme()` + `useApplyPalette()` once near the root. For a no-flash
|
|
78
|
-
first paint, apply the persisted theme class + token set before hydration
|
|
79
|
-
|
|
148
|
+
first paint, apply the persisted theme class + token set **before** hydration —
|
|
149
|
+
`applyPersistedTheme(key)` resolves the stored preference, toggles `.dark` and
|
|
150
|
+
returns the mode, which `applyPersistedPalette(key, mode)` then uses:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
// main.tsx, at module scope, before createRoot
|
|
154
|
+
const mode = applyPersistedTheme("myapp-theme");
|
|
155
|
+
applyPersistedPalette("myapp-palette", mode);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Worked example: [`showcase/src/main.tsx`](showcase/src/main.tsx).
|
|
159
|
+
|
|
160
|
+
## Tokens
|
|
161
|
+
|
|
162
|
+
Everything the components paint with comes from `tokens.css`, so a consuming app
|
|
163
|
+
re-skins the kit by changing values rather than by forking components. Three layers:
|
|
164
|
+
|
|
165
|
+
| Layer | Tokens | Set by |
|
|
166
|
+
|---|---|---|
|
|
167
|
+
| **Palette** | `--bg-page` `--bg-surface` `--bg-surface-2` `--border` `--text-primary` `--text-secondary` `--text-muted` `--brand` `--brand-hover` `--brand-contrast` `--money-income` `--money-expense` `--money-net` `--money-neutral` `--chart-1…9` | `applyTokenSet()`, written inline on `<html>` from the active `PalettePreset` |
|
|
168
|
+
| **Derived** | `--text-placeholder` `--bg-hover` `--bg-active` `--bg-inverse` `--text-inverse` `--border-strong` `--brand-bg` `--brand-bg-hover` `--brand-muted` | `color-mix()` in `tokens.css`, from the layer above — so they follow the preset with no preset having to list them |
|
|
169
|
+
| **Semantic** | `--danger*` `--warning*` `--info*`, and `--status-synced/-pending/-edited/-error` | literals in `tokens.css`, per theme |
|
|
170
|
+
|
|
171
|
+
The semantic layer is deliberately **not** part of `TokenSet`: a destructive action and a
|
|
172
|
+
failed save are fixed meanings, and they should not change because somebody picked a
|
|
173
|
+
different appearance preset. Everything else does follow the preset.
|
|
174
|
+
|
|
175
|
+
To re-skin, override the tokens after importing the stylesheet:
|
|
176
|
+
|
|
177
|
+
```css
|
|
178
|
+
@import "@eifi1/ui-kit/tokens.css";
|
|
179
|
+
|
|
180
|
+
:root { --brand: #0f766e; --brand-hover: #115e59; --brand-contrast: #fff; }
|
|
181
|
+
.dark { --brand: #5eead4; --brand-hover: #99f6e4; --brand-contrast: #042f2e; }
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`--brand-bg`, `--brand-bg-hover` and `--brand-muted` are derived from `--brand`, so the
|
|
185
|
+
soft brand chips (an active filter, a selected day) follow that override automatically.
|
|
186
|
+
|
|
187
|
+
`npm run check:tokens` fails if a component reaches for a raw Tailwind palette colour
|
|
188
|
+
instead of a token. It is a ratchet: when the count drops, lower the budget in the same
|
|
189
|
+
commit.
|
|
190
|
+
|
|
191
|
+
## Colour
|
|
192
|
+
|
|
193
|
+
### Three systems, deliberately separate
|
|
194
|
+
|
|
195
|
+
A colour in this kit belongs to exactly one of three systems, and they are kept apart
|
|
196
|
+
because they answer different questions.
|
|
197
|
+
|
|
198
|
+
| System | Tokens | The question it answers |
|
|
199
|
+
|---|---|---|
|
|
200
|
+
| **Semantic UI** | `--danger*` `--warning*` `--info*` `--success*`, `--status-*` | *What does this mean?* Danger is red because every other interface the reader has used made it red. Fixed meanings, so they live in `tokens.css` and are **not** part of `TokenSet` — a destructive action must not change colour because somebody picked a different preset. |
|
|
201
|
+
| **Semantic data** | `--money-income` `--money-expense` `--money-net` `--money-neutral` | *Which direction is this number?* Never red/green: that pair is exactly the axis dichromacy collapses. Always paired with a `+`/`−` or an arrow at the call site, so colour is never the only signal. |
|
|
202
|
+
| **Categorical chart** | `--chart-1` … `--chart-9` | *Which series is this?* No meaning and no order — nine hues that must stay separable from each other. Paul Tol's "Muted" set, CVD-safe across protan/deutan/tritan. `paletteFor(i)` returns the CSS var, so a Recharts series is theme-aware for free. |
|
|
203
|
+
|
|
204
|
+
Optimising a set for one of these makes it worse at the others. A UI colour needs contrast
|
|
205
|
+
against one known surface and carries a fixed meaning; a chart colour needs to stay
|
|
206
|
+
separable from eight unknown siblings at roughly equal salience with no implied order.
|
|
207
|
+
That is why `derivePalette` leaves the chart ramp alone unless you ask for
|
|
208
|
+
`deriveChartRamp` explicitly.
|
|
209
|
+
|
|
210
|
+
One consequence to know about: the `chart` array it returns is **empty, not absent**. A
|
|
211
|
+
caller who hands the result straight to `applyTokenSet` keeps whatever `--chart-1…9` were
|
|
212
|
+
already on the element — deliberate, because clearing them would leave charts unpainted,
|
|
213
|
+
but it means a derived palette applied over another preset is a *mix* until you supply a
|
|
214
|
+
ramp of your own.
|
|
215
|
+
|
|
216
|
+
### Deriving a palette
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { derivePalette, auditPalette, auditChartRamp } from "@eifi1/ui-kit";
|
|
220
|
+
|
|
221
|
+
const { tokens, semantic, audit, warnings } = derivePalette({
|
|
222
|
+
anchors: { brand: "#4f46e5", danger: "#b91c1c" }, // brand required; the rest optional
|
|
223
|
+
mode: "light",
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
`brand` is required and `accent`, `danger`, `warning`, `success` and `info` are optional
|
|
228
|
+
hard points. Pinned hues are honoured exactly; the rest are placed away from the brand and
|
|
229
|
+
from each other, each within its own narrow licence to move — enough to get out of the
|
|
230
|
+
brand's way, not enough to stop meaning what it means. If a role cannot get far enough,
|
|
231
|
+
that is a `warnings` entry, not a silent compromise.
|
|
232
|
+
|
|
233
|
+
Everything is **solved to a target and then measured**. Text is solved against the *worst*
|
|
234
|
+
of the three surfaces (`--bg-page`, `--bg-surface`, `--bg-surface-2`) — 10:1 primary, 7:1
|
|
235
|
+
secondary, 4.6:1 muted by default — because solving against `--bg-surface` alone is the
|
|
236
|
+
mistake that makes a muted label fail on the page background it also sits on. The brand
|
|
237
|
+
keeps the hue and chroma you asked for and moves only in lightness, and only as far as the
|
|
238
|
+
3:1 that WCAG 1.4.11 asks of a control boundary.
|
|
239
|
+
|
|
240
|
+
It exists because the presets this package shipped were assembled by eye and annotated with
|
|
241
|
+
the ratios they were *believed* to hold — `tokens.css` recorded "7.0:1 and 4.8:1",
|
|
242
|
+
`palette-presets.ts` recorded "2.67:1 … lifted they clear it at 3.30:1" — and nothing
|
|
243
|
+
computed any of them. A comment is not a test. The audit found four of the nine default
|
|
244
|
+
light chart hues below 3:1.
|
|
245
|
+
|
|
246
|
+
`auditPalette(tokens, semantic)` and `auditChartRamp(colors, surfaces)` measure a palette
|
|
247
|
+
instead of trusting it, and run in CI over everything the package ships. The ramp report
|
|
248
|
+
gives pairwise collisions under normal vision *and* each of the three dichromacies, every
|
|
249
|
+
series below 3:1 against a surface it may be drawn on, and the worst of each.
|
|
250
|
+
|
|
251
|
+
The colour maths (`src/theme/color.ts`: sRGB ↔ OKLab ↔ OKLCH, WCAG contrast, gamut
|
|
252
|
+
clipping, dichromat simulation, OKLab ΔE) is dependency-free, and OKLCH rather than HSL
|
|
253
|
+
because HSL's "lightness" is not lightness — `hsl(60 100% 50%)` and `hsl(240 100% 50%)`
|
|
254
|
+
claim the same 50% and differ about twelvefold in apparent brightness.
|
|
255
|
+
|
|
256
|
+
### The categorical trade-off, measured
|
|
257
|
+
|
|
258
|
+
**At a single lightness, the most categorical series that can satisfy both the 3:1 fill
|
|
259
|
+
contrast of WCAG 1.4.11 and the dichromat separation floor is four.** Searched exhaustively
|
|
260
|
+
over starting hue and lightness:
|
|
261
|
+
|
|
262
|
+
| Series | Best separation | Both satisfiable |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| 4 | 0.065 | yes |
|
|
265
|
+
| 5 | 0.041 | no |
|
|
266
|
+
| 9 | 0.015 | no |
|
|
267
|
+
|
|
268
|
+
The floor is 0.05 in OKLab, calibrated rather than chosen: Paul Tol's "Muted" set — known
|
|
269
|
+
to work — bottoms out at 0.059 light and 0.032 in the lightened dark variant, and a
|
|
270
|
+
threshold above that would fail a palette that is known good, which is worse than no check
|
|
271
|
+
at all.
|
|
272
|
+
|
|
273
|
+
The reason is structural. Dichromacy collapses the red-green axis, so hue alone stops
|
|
274
|
+
distinguishing colours past a handful, and the only channel left is **lightness** — the
|
|
275
|
+
very thing a uniform-contrast ramp holds constant. Tol's set varies lightness deliberately
|
|
276
|
+
and pays for it in contrast; that is not an oversight in their palette, it is the only
|
|
277
|
+
currency left. Above four series `deriveChartRamp` varies lightness too, in a three-step
|
|
278
|
+
cycle so adjacent series differ in lightness as well as hue, and reports what it gave up.
|
|
279
|
+
|
|
280
|
+
Two honest caveats. That bound describes the **problem**, not a guarantee about
|
|
281
|
+
`deriveChartRamp`: it fixes lightness and starts the hue wheel at the brand's own hue
|
|
282
|
+
rather than searching for the best start, so it reaches the bound only where the brand
|
|
283
|
+
happens to sit well — sweeping 72 brand hues against the default light surfaces, **7 of 72
|
|
284
|
+
produced a passing 4-series ramp** (12 of 72 on dark), and none passed at 5 or 9. Read the
|
|
285
|
+
report it returns; do not assume a pass. And `deriveChartRamp` is offered, not used by
|
|
286
|
+
default: evenly spaced hues at one lightness are a reasonable generic answer, and Tol's set
|
|
287
|
+
is a better specific one, because it was optimised against real confusion lines rather than
|
|
288
|
+
derived from a formula.
|
|
289
|
+
|
|
290
|
+
## Showcase
|
|
291
|
+
|
|
292
|
+
Every component in the package, rendered on one page, with the theme and palette
|
|
293
|
+
switchers live:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
npm run dev:showcase
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
and open **http://localhost:4170**.
|
|
300
|
+
|
|
301
|
+
The port is harmonised with the sibling apps rather than left on Vite's default, so the
|
|
302
|
+
showcase can run next to whatever you are testing it against:
|
|
303
|
+
|
|
304
|
+
| Port | What |
|
|
305
|
+
|---|---|
|
|
306
|
+
| **4170** | **this showcase** (`dev:showcase`) |
|
|
307
|
+
| **4171** | this showcase, built (`preview:showcase`) |
|
|
308
|
+
| 4173 | keksdose frontend (backend 8000) |
|
|
309
|
+
| 4175 | lenkbank frontend (backend 8001) |
|
|
310
|
+
| 5173 | kastlan frontend (Vite's default) |
|
|
311
|
+
|
|
312
|
+
`strictPort` is on: a collision fails loudly instead of silently moving to another port
|
|
313
|
+
and printing a URL that is not the one documented here. For a throwaway instance that
|
|
314
|
+
must not take the port your editor's build task wants:
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
SHOWCASE_PORT=4199 npm run dev:showcase
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
It renders **`src/`, not `dist/`** — no build step first, and an edit to a component
|
|
321
|
+
is on screen on save. It is also the package's broadest test: `npm test` mounts the
|
|
322
|
+
whole page under jsdom, so a component that throws on mount fails CI, and `tsc`
|
|
323
|
+
covers it, so an export renamed out of the barrel is a compile error rather than a
|
|
324
|
+
demo that quietly disappears.
|
|
325
|
+
|
|
326
|
+
```
|
|
327
|
+
showcase/
|
|
328
|
+
index.html
|
|
329
|
+
vite.config.ts # root; aliases @eifi1/ui-kit → ../src
|
|
330
|
+
alias.ts # that alias, shared with the root vitest.config.ts
|
|
331
|
+
src/
|
|
332
|
+
main.tsx # the pre-hydration no-flash boot, as a worked example
|
|
333
|
+
app.css # tailwind + tokens.css + the @source scan
|
|
334
|
+
stores.ts # createThemeStore / createPaletteStore, showcase keys
|
|
335
|
+
showcase.tsx # the AppShell frame + the SECTIONS registry
|
|
336
|
+
sections/*.tsx # one file per section
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Adding a component to the kit means adding it to a section — that is how the page
|
|
340
|
+
stays true. `npm run build:showcase` produces a static site; CI builds it on every
|
|
341
|
+
push and asserts the emitted CSS actually contains the kit's utility classes, which
|
|
342
|
+
is the only automated check that the documented Tailwind `@source` step works.
|
|
80
343
|
|
|
81
344
|
## Tests
|
|
82
345
|
|
|
@@ -99,42 +362,159 @@ a test written after the fix proves only that the fix is self-consistent.
|
|
|
99
362
|
|
|
100
363
|
## What's exported
|
|
101
364
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
365
|
+
The full inventory, generated from the build rather than maintained by hand — the
|
|
366
|
+
hand-written version named 93 of 263 and had been advertising five deleted wizard exports
|
|
367
|
+
since 0.4.0. Regenerate it with `node scripts/gen-export-inventory.mjs` after a build.
|
|
368
|
+
|
|
369
|
+
Two names that read as something they are not: `WizardStepper` is a bare two-step
|
|
370
|
+
indicator and has nothing to do with the wizard engine below, and the feedback exports are
|
|
371
|
+
the vocabulary, the transition policy and the look only — each app still wires its own API,
|
|
372
|
+
columns, strings and permissions (see the note at the top of `src/feedback/feedback-inbox.tsx`).
|
|
373
|
+
|
|
374
|
+
<!-- BEGIN GENERATED: exports — node scripts/gen-export-inventory.mjs -->
|
|
375
|
+
|
|
376
|
+
**324 names from 76 modules** — 212 values and 112 types. _Italic_ is a type-only export.
|
|
377
|
+
|
|
378
|
+
Generated from `dist/index.d.ts` by `node scripts/gen-export-inventory.mjs`; the count
|
|
379
|
+
is pinned by `src/__tests__/public-surface.test.ts`. Do not edit between the markers.
|
|
380
|
+
|
|
381
|
+
| Entry point | Names |
|
|
382
|
+
|---|---|
|
|
383
|
+
| `@eifi1/ui-kit` | 324 |
|
|
384
|
+
| `@eifi1/ui-kit/chart` | 15 |
|
|
385
|
+
| `@eifi1/ui-kit/shell` | 16 |
|
|
386
|
+
| `@eifi1/ui-kit/data-table` | 27 |
|
|
387
|
+
| `@eifi1/ui-kit/wizard` | 20 |
|
|
388
|
+
| `@eifi1/ui-kit/tour` | 6 |
|
|
389
|
+
| `@eifi1/ui-kit/feedback` | 27 |
|
|
390
|
+
| `@eifi1/ui-kit/search` | 4 |
|
|
391
|
+
| `@eifi1/ui-kit/dates` | 16 |
|
|
392
|
+
|
|
393
|
+
Everything below is reachable from the main `@eifi1/ui-kit` barrel. The subpaths are a
|
|
394
|
+
re-slicing of it, never a second API.
|
|
395
|
+
|
|
396
|
+
### lib — pure helpers
|
|
397
|
+
|
|
398
|
+
| Module | Exports |
|
|
399
|
+
|---|---|
|
|
400
|
+
| `lib/calc` | `commitExpression`, `evaluateExpression`, `formatResult`, `isBareAmount`, `looksLikeExpression`, `sanitizeLive`, `splitLeadingSign` |
|
|
401
|
+
| `lib/cn` | `cn` |
|
|
402
|
+
| `lib/logger` | `logger`, `setStoreLog` |
|
|
403
|
+
|
|
404
|
+
### hooks
|
|
405
|
+
|
|
406
|
+
| Module | Exports |
|
|
407
|
+
|---|---|
|
|
408
|
+
| `hooks/use-media-query` | `useMediaQuery` |
|
|
409
|
+
| `hooks/use-body-scroll-lock` | `useBodyScrollLock` |
|
|
410
|
+
| `hooks/use-anchored-rect` | `useAnchoredRect`, _`AnchorRect`_ |
|
|
411
|
+
| `hooks/use-anchored-panel` | `anchoredPanelPlacement`, `useAnchoredPanel`, `useVisualViewport`, _`AnchoredPanel`_, _`AnchoredPanelOptions`_, _`ViewportBox`_ |
|
|
412
|
+
| `hooks/use-dismiss` | `useEscapeKey`, `useOutsideClick` |
|
|
413
|
+
| `hooks/use-focus-trap` | `useFocusTrap`, _`FocusTrapOptions`_ |
|
|
414
|
+
| `hooks/use-announce` | `useAnnounce`, _`AnnounceRegionProps`_, _`UseAnnounceOptions`_, _`UseAnnounceReturn`_ |
|
|
415
|
+
| `hooks/use-overlay-history` | `useOverlayHistory` |
|
|
416
|
+
| `hooks/use-close-transition` | `OVERLAY_EXIT_MS`, `useCloseTransition` |
|
|
417
|
+
| `hooks/use-row-swipe` | `useRowSwipe`, _`RowSwipeOptions`_, _`RowSwipeReturn`_, _`SwipeStage`_ |
|
|
418
|
+
|
|
419
|
+
### theme, palettes, colour
|
|
420
|
+
|
|
421
|
+
| Module | Exports |
|
|
422
|
+
|---|---|
|
|
423
|
+
| `theme/chart-palette` | `CHART_COLORS`, `HEATMAP_HEX`, `lerpHex`, `PALETTE_HEX`, `paletteFor`, `textOn`, _`HeatStops`_ |
|
|
424
|
+
| `theme/color` | `contrast`, `deltaE`, `hexToOklch`, `luminance`, `oklchToHex`, `oklchToRgb`, `parseHex`, `rgbToOklch`, `simulateCvd`, `solveLightness`, `toHex`, _`CvdType`_, _`Oklch`_, _`Rgb`_ |
|
|
425
|
+
| `theme/palette-derive` | `auditChartRamp`, `auditPalette`, `deriveChartRamp`, `derivePalette`, `describe`, _`AnchorRole`_, _`ChartRampReport`_, _`ContrastCheck`_, _`ContrastReport`_, _`DerivedPalette`_, _`DeriveOptions`_, _`PaletteAnchors`_, _`SemanticTokens`_ |
|
|
426
|
+
| `theme/palette-presets` | `ALTERNATIVE_PRESETS`, `applyTokenSet`, `DEFAULT_PRESET`, `DERIVED_PRESETS`, `IMPRINT_PRESET`, `PALETTES`, `presetById`, _`PalettePreset`_, _`TokenSet`_ |
|
|
427
|
+
| `theme/theme-store` | `applyPersistedTheme`, `createThemeStore`, _`ThemeMode`_, _`ThemePreference`_, _`ThemeState`_, _`ThemeStore`_ |
|
|
428
|
+
| `theme/palette-store` | `applyPersistedPalette`, `createPaletteStore`, _`PaletteStore`_ |
|
|
429
|
+
|
|
430
|
+
### components
|
|
431
|
+
|
|
432
|
+
| Module | Exports |
|
|
433
|
+
|---|---|
|
|
434
|
+
| `components/ui` | `Button`, `buttonClasses`, `Card`, `CardAction`, `CardContent`, `CardDescription`, `CardFooter`, `CardHeader`, `CardTitle`, `DEFAULT_PASSWORD_REVEAL_LABELS`, `EmptyState`, `FIELD_BASE`, `FIELD_DISPLAY`, `FIELD_FLOATING_PAD`, `FIELD_INVALID`, `FIELD_TRIGGER`, `FIELD_WRITABLE_LOOK`, `FieldChevron`, `FieldHint`, `FieldLabel`, `FLOATING_INPUT_CLASS`, `FLOATING_LABEL_CLASS`, `FLOATING_LABEL_STATIC`, `FloatingField`, `IconButton`, `Input`, `PHONE_QUERY`, `resolvePasswordRevealLabels`, `Select`, `Spinner`, `Tabs`, `Textarea`, _`ButtonVariant`_, _`PasswordRevealLabels`_, _`TabsProps`_ |
|
|
435
|
+
| `components/search-field` | `SearchField`, _`SearchFieldProps`_ |
|
|
436
|
+
| `components/dropdown` | `DropdownPanel`, `DropdownSearchHeader`, `useDropdown`, `useDropdownSearch` |
|
|
437
|
+
| `components/popover` | `Popover`, _`PopoverLabels`_ |
|
|
438
|
+
| `components/swipeable-row` | `SwipeableRow`, _`SwipeableRowProps`_, _`SwipeAction`_ |
|
|
439
|
+
| `components/calculator` | `CalculatorButton`, _`CalculatorButtonLabels`_ |
|
|
440
|
+
| `components/numpad-sheet` | `NumberPadSheet`, _`NumberPadSheetLabels`_ |
|
|
441
|
+
| `components/number-input` | `NumberInput` |
|
|
442
|
+
| `components/currency-select` | `CURRENCIES`, `CurrencyFlag`, `currencyName`, `CurrencySelect`, `getCurrency`, _`CurrencyOption`_ |
|
|
443
|
+
| `components/amount-input` | `AmountInput` |
|
|
444
|
+
| `components/combobox` | `Combobox`, `InlineEntityCombobox` |
|
|
445
|
+
| `components/picker-sheet` | `PickerSheet`, `SHEET_ROW_CLASS` |
|
|
446
|
+
| `components/entity-combobox` | `EntityCombobox`, _`EntityComboboxProps`_ |
|
|
447
|
+
| `components/multi-entity-combobox` | `MultiEntityCombobox`, _`MultiEntityComboboxProps`_ |
|
|
448
|
+
| `components/multi-select` | `MultiSelect`, _`MultiSelectOption`_ |
|
|
449
|
+
| `components/tooltip` | `placeTooltip`, `Tooltip`, _`TooltipPlacement`_, _`TooltipSize`_, _`TooltipViewport`_ |
|
|
450
|
+
| `components/user-avatar` | `avatarInitials`, `UserAvatar`, _`UserAvatarProps`_ |
|
|
451
|
+
| `components/settings-fields` | `LanguageSetting`, `ThemeSetting`, _`LanguageSettingProps`_, _`ThemeSettingProps`_ |
|
|
452
|
+
| `components/field-sync` | `DEFAULT_FIELD_SYNC_LABELS`, `FieldSyncIndicator`, `FieldSyncRow`, `resolveFieldSyncLabels`, `useFieldSync`, _`FieldSyncIndicatorProps`_, _`FieldSyncLabels`_, _`FieldSyncRowProps`_, _`FieldSyncState`_, _`UseFieldSyncOptions`_, _`UseFieldSyncReturn`_ |
|
|
453
|
+
| `components/account-settings` | `PasswordSetting`, `ProfileSetting`, `TwoFactorSetting`, _`PasswordSettingLabels`_, _`ProfileSettingLabels`_, _`TwoFactorSettingLabels`_ |
|
|
454
|
+
| `components/alert-banner` | `AlertBanner`, `alertFrameClass`, `toneFrameClass`, _`AlertTone`_ |
|
|
455
|
+
| `components/toggle-group` | `ToggleGroup` |
|
|
456
|
+
| `components/chip` | `Chip`, `ChipInput`, `DEFAULT_CHIP_INPUT_LABELS`, `resolveChipInputLabels`, _`ChipInputLabels`_, _`ChipInputProps`_, _`ChipProps`_, _`ChipSize`_, _`ChipTone`_ |
|
|
457
|
+
| `components/wizard-stepper` | `WizardStepper` |
|
|
458
|
+
| `components/hover-menu` | `HoverMenu` |
|
|
459
|
+
| `components/modal` | `Modal`, `useBackdropClose`, _`ModalProps`_ |
|
|
460
|
+
| `components/full-bleed-dialog` | `FullBleedDialog` |
|
|
461
|
+
| `components/grouped-picker` | `GroupedPicker`, _`PickerGroup`_ |
|
|
462
|
+
| `components/file-dropzone` | `FileDropzone` |
|
|
463
|
+
| `components/mini-calendar` | `MiniCalendar`, _`MiniCalendarLabels`_, _`MiniCalendarProps`_ |
|
|
464
|
+
| `components/date-picker` | `DatePicker`, `DateRangePicker`, _`DatePickerProps`_, _`DateRangePickerPreset`_, _`DateRangePickerProps`_ |
|
|
465
|
+
| `components/chart` | `ChartContainer`, `ChartLegend`, `ChartLegendContent`, `ChartTooltip`, `ChartTooltipContent`, `useChart`, _`ChartConfig`_, _`ChartSeriesConfig`_ |
|
|
466
|
+
| `components/data-table-labels` | `DEFAULT_DATA_TABLE_LABELS`, `missingDataTableLabels`, `resolveDataTableLabels`, _`DataTableLabels`_ |
|
|
467
|
+
| `components/data-table-sort` | `decodeSorts`, `encodeSorts`, `nextSorts`, `normalizeSorts`, _`SortDir`_, _`SortState`_ |
|
|
468
|
+
| `components/data-table-filters` | `decodeFilterValue`, `decodeFilterValueOfType`, `defaultFilterState`, `encodeFilterValue`, `isFilterActive`, `resolveFilter`, `rowMatches`, _`ColumnFilter`_, _`FilterValue`_ |
|
|
469
|
+
| `components/data-table` | `DataTable`, _`DataTableColumn`_, _`DataTableProps`_, _`FilterState`_, _`ServerPagination`_ |
|
|
470
|
+
| `components/data-table-pagination` | `PAGE_SIZE_OPTIONS`, `Pagination` |
|
|
471
|
+
| `components/data-table-filter-popover` | `FilterPopover` |
|
|
472
|
+
| `components/combobox-core` | _`ComboOption`_ |
|
|
473
|
+
|
|
474
|
+
### shell
|
|
475
|
+
|
|
476
|
+
| Module | Exports |
|
|
477
|
+
|---|---|
|
|
478
|
+
| `shell/topbar-controls` | `LanguageMenu`, `PaletteMenu`, `ThemeToggle`, `TOPBAR_MENU_ITEM_CLASS`, `TOPBAR_TRIGGER_CLASS`, _`LanguageOption`_ |
|
|
479
|
+
| `shell/top-bar` | `TopBar` |
|
|
480
|
+
| `shell/app-shell` | `AppShell`, _`AppShellNavItem`_, _`AppShellSubItem`_ |
|
|
481
|
+
| `shell/option-switcher-menu` | `OptionSwitcherMenu`, _`OptionSwitcherOption`_ |
|
|
482
|
+
| `shell/role-switcher` | `RoleSwitcher`, _`RoleSwitcherProps`_ |
|
|
483
|
+
| `shell/topbar-action-menu` | `TopBarActionMenu`, _`TopBarMenuEntry`_ |
|
|
484
|
+
|
|
485
|
+
### feedback
|
|
486
|
+
|
|
487
|
+
| Module | Exports |
|
|
488
|
+
|---|---|
|
|
489
|
+
| `feedback/feedback-attachment` | `DEFAULT_ATTACHMENT_ACCEPT`, `DEFAULT_MAX_ATTACHMENT_BYTES`, `FeedbackAttachmentField`, `pastedName` |
|
|
490
|
+
| `feedback/feedback-dialog` | `FeedbackDialog`, _`FeedbackAttachmentLabels`_, _`FeedbackCategoryOption`_, _`FeedbackDialogLabels`_, _`FeedbackSubmission`_ |
|
|
491
|
+
| `feedback/feedback-inbox` | `FEEDBACK_CATEGORY_META`, `FEEDBACK_CATEGORY_ORDER`, `FEEDBACK_STATUS_META`, `FEEDBACK_STATUS_ORDER`, `FeedbackCategoryBadge`, `feedbackCategoryRank`, `FeedbackDetail`, `FeedbackDetailSection`, `FeedbackNoteEditor`, `FeedbackProse`, `FeedbackStatusBadge`, `FeedbackStatusTransitions`, `nextFeedbackStatus`, `selectableFeedbackStatuses`, `visibleFeedbackStatuses`, _`FeedbackCategory`_, _`FeedbackNoteAttachment`_, _`FeedbackStatus`_ |
|
|
492
|
+
|
|
493
|
+
### wizard
|
|
494
|
+
|
|
495
|
+
| Module | Exports |
|
|
496
|
+
|---|---|
|
|
497
|
+
| `wizard/types` | `DEFAULT_WIZARD_LABELS`, `resolveWizardLabels`, _`FieldErrors`_, _`StepStatus`_, _`SummaryItem`_, _`SummarySection`_, _`UseWizardOptions`_, _`UseWizardReturn`_, _`ValidateResult`_, _`WizardLabels`_, _`WizardStepConfig`_ |
|
|
498
|
+
| `wizard/use-wizard` | `useWizard` |
|
|
499
|
+
| `wizard/wizard-context` | `useWizardContext`, `WizardContextProvider`, _`WizardContextValue`_ |
|
|
500
|
+
| `wizard/validation` | `requiredFieldsValidator`, _`RequiredFieldSpec`_ |
|
|
501
|
+
| `wizard/wizard-step` | `WizardStep` |
|
|
502
|
+
| `wizard/wizard-summary` | `WizardSummary` |
|
|
503
|
+
| `wizard/stepper-nav` | `StepperNav` |
|
|
504
|
+
|
|
505
|
+
### tour
|
|
506
|
+
|
|
507
|
+
| Module | Exports |
|
|
508
|
+
|---|---|
|
|
509
|
+
| `tour/tour` | `TourProvider`, `useTour`, `useTourOptional`, _`TourLabels`_, _`TourPlacement`_, _`TourStep`_ |
|
|
510
|
+
|
|
511
|
+
### search
|
|
512
|
+
|
|
513
|
+
| Module | Exports |
|
|
514
|
+
|---|---|
|
|
515
|
+
| `search/command-palette` | `CommandPalette`, `useCommandKey`, _`CommandItem`_, _`CommandPaletteLabels`_ |
|
|
516
|
+
|
|
517
|
+
<!-- END GENERATED: exports -->
|
|
138
518
|
|
|
139
519
|
## Forms / refs
|
|
140
520
|
|
|
@@ -145,14 +525,76 @@ focus-and-scroll-to-error for free.
|
|
|
145
525
|
|
|
146
526
|
## i18n
|
|
147
527
|
|
|
148
|
-
The
|
|
149
|
-
|
|
528
|
+
**The kit resolves no strings.** It carries no translation catalogue, no locale detection
|
|
529
|
+
and no `t()`. Every string it renders is a key in one typed tree, `UiKitLabels`, with an
|
|
530
|
+
English default — and the app hands its translation to every component at once:
|
|
150
531
|
|
|
151
532
|
```tsx
|
|
152
|
-
|
|
153
|
-
|
|
533
|
+
import { UiKitProvider } from "@eifi1/ui-kit";
|
|
534
|
+
|
|
535
|
+
<UiKitProvider labels={de} locale="de-DE"> {/* de: UiKitLabels, or any part of it */}
|
|
536
|
+
<App />
|
|
537
|
+
</UiKitProvider>
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
Precedence is fixed: **a component's own prop > the provider > the English default.** So
|
|
541
|
+
one table can still say `labels={{ table: "Transactions" }}` inside a German app, and a
|
|
542
|
+
component outside any provider behaves exactly as it always did.
|
|
543
|
+
|
|
544
|
+
The tree is namespaced by component and addressed by dot path — `dataTable.pageSize`,
|
|
545
|
+
`miniCalendar.previousMonth`, `datePicker.today`, `appShell.collapse`,
|
|
546
|
+
`common.fieldValue` — and `DEFAULT_UI_KIT_LABELS` is the whole English reference in one
|
|
547
|
+
object. Write the translation against its type and `tsc` refuses a missing key; for a
|
|
548
|
+
translation built at runtime, assert in the app's own test:
|
|
549
|
+
|
|
550
|
+
```ts
|
|
551
|
+
expect(missingKitLabels(de, DEFAULT_UI_KIT_LABELS)).toEqual([]);
|
|
154
552
|
```
|
|
155
553
|
|
|
554
|
+
The provider's `locale` reaches every `Intl` formatter in the kit that is not handed a
|
|
555
|
+
`locale` prop of its own: calendar month and weekday names, day numbers, the data table's
|
|
556
|
+
counts, file sizes.
|
|
557
|
+
|
|
558
|
+
**Why a provider, when every component already took a `labels` prop.** Because a prop has
|
|
559
|
+
to be passed at every call site, under a different name per component (`labels`,
|
|
560
|
+
`calendarLabels`, `passwordLabels`, `clearLabel`, `ariaLabel` …), and one forgotten prop is
|
|
561
|
+
one English word in a German UI that nothing reports. Worse, a component NESTED inside
|
|
562
|
+
another — the calendar inside the data table's date filter, the popover inside the date
|
|
563
|
+
picker — could not be reached from the outer call site at all. The per-component props
|
|
564
|
+
still work and still win; they are now the exception rather than the mechanism.
|
|
565
|
+
|
|
566
|
+
**A label that interpolates a value is a function of that value, never a template.** Word
|
|
567
|
+
order, pluralisation and where the number goes are the translator's business, and a string
|
|
568
|
+
with a `{count}` hole in it decides all three on their behalf:
|
|
569
|
+
|
|
570
|
+
```ts
|
|
571
|
+
// UiKitLabels["dataTable"]
|
|
572
|
+
pageChanged: (page: number, totalPages: number) => string;
|
|
573
|
+
// UiKitLabels["common"] — even "Label: value" is not universal punctuation
|
|
574
|
+
fieldValue: (field: string, value: string) => string;
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### The worked example
|
|
578
|
+
|
|
579
|
+
`showcase/src/i18n/` runs the whole showcase in seven locales — English, German, French,
|
|
580
|
+
Italian, Spanish, Hungarian and Chinese — and it is deliberately **not** an i18n library: a
|
|
581
|
+
dictionary in context, a hook to read it, and ONE `<UiKitProvider labels={dict.kit}
|
|
582
|
+
locale={dict.tag}>` at the root. Each dictionary's `kit` is typed as the full
|
|
583
|
+
`UiKitLabels`, so a translation with a hole does not compile; the Localisation page shows
|
|
584
|
+
the tree and the per-language completeness live. The long explanatory prose on each page is
|
|
585
|
+
*not* translated: it is developer documentation about the kit's internals. The chrome, the
|
|
586
|
+
navigation and every component label are.
|
|
587
|
+
|
|
588
|
+
### Right-to-left is partial
|
|
589
|
+
|
|
590
|
+
Newer components (the sidebar's inline groups, the date range band, the month picker, the
|
|
591
|
+
checkbox, switch and slider) use logical properties (`ms-*`, `pe-*`, `text-start`) and
|
|
592
|
+
flip correctly under `dir="rtl"`. The older ones still carry roughly 130 physical-direction
|
|
593
|
+
utilities plus pointer maths (column resize, row swipe) that assume left-to-right —
|
|
594
|
+
`docs/module-audit-2026-09-22.md` §10 has the site-by-site detail. None of the showcase's
|
|
595
|
+
seven locales is right-to-left, so nothing exercises it today; plan around that before
|
|
596
|
+
shipping Arabic or Hebrew.
|
|
597
|
+
|
|
156
598
|
## Wizard
|
|
157
599
|
|
|
158
600
|
A multi-step form engine: a step machine with per-step validation gates, collected
|
|
@@ -182,11 +624,9 @@ const wizard = useWizard<LeaseDraft>({
|
|
|
182
624
|
</WizardContextProvider>
|
|
183
625
|
```
|
|
184
626
|
|
|
185
|
-
A step gates forward navigation
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
(which also reports its own inline messages). `useWizardNextGate(blocked)`
|
|
189
|
-
disables Next/Skip outright.
|
|
627
|
+
A step gates forward navigation two ways, and `goNext` runs both: its `validate`
|
|
628
|
+
in the config above, and `useWizardStepValidate(fn)` for a step that checks by
|
|
629
|
+
hand. `useWizardNextGate(blocked)` disables Next/Skip outright.
|
|
190
630
|
|
|
191
631
|
Like the rest of the package it resolves **no strings**: a step carries a `label`
|
|
192
632
|
node, and the chrome takes a `labels` object (`WizardLabels`, every key optional
|
|
@@ -194,10 +634,11 @@ over an English default) — the same split `DataTable` and `TourProvider` use.
|
|
|
194
634
|
app with i18n wraps `useWizard`/`StepperNav`/`WizardSummary` once and maps its
|
|
195
635
|
own keys; see Kastlan's `shared/components/wizard/app-wizard.tsx`.
|
|
196
636
|
|
|
197
|
-
**
|
|
198
|
-
|
|
199
|
-
carries the "fill in the required fields" toast and is
|
|
200
|
-
that failure path only — pass `onValidationFailed` to
|
|
637
|
+
**Peers.** `react-router` backs the `?step=` sync in `useWizard` — and is imported
|
|
638
|
+
unconditionally, so a wizard needs a Router mounted even if you never read the
|
|
639
|
+
step from the URL. `sonner` carries the "fill in the required fields" toast and is
|
|
640
|
+
imported dynamically, on that failure path only — pass `onValidationFailed` to
|
|
641
|
+
route it elsewhere.
|
|
201
642
|
|
|
202
643
|
## Shell
|
|
203
644
|
|