@poodle64/ui 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +624 -0
- package/dist/components/ui/alert/alert-description.svelte +23 -0
- package/dist/components/ui/alert/alert-description.svelte.d.ts +9 -0
- package/dist/components/ui/alert/alert-title.svelte +23 -0
- package/dist/components/ui/alert/alert-title.svelte.d.ts +9 -0
- package/dist/components/ui/alert/alert.svelte +46 -0
- package/dist/components/ui/alert/alert.svelte.d.ts +28 -0
- package/dist/components/ui/alert/index.d.ts +4 -0
- package/dist/components/ui/alert/index.js +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +27 -0
- package/dist/components/ui/alert-dialog/alert-dialog-action.svelte.d.ts +9 -0
- package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +27 -0
- package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte.d.ts +9 -0
- package/dist/components/ui/alert-dialog/alert-dialog-content.svelte +39 -0
- package/dist/components/ui/alert-dialog/alert-dialog-content.svelte.d.ts +11 -0
- package/dist/components/ui/alert-dialog/alert-dialog-description.svelte +20 -0
- package/dist/components/ui/alert-dialog/alert-dialog-description.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte +23 -0
- package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte.d.ts +5 -0
- package/dist/components/ui/alert-dialog/alert-dialog-header.svelte +23 -0
- package/dist/components/ui/alert-dialog/alert-dialog-header.svelte.d.ts +5 -0
- package/dist/components/ui/alert-dialog/alert-dialog-media.svelte +23 -0
- package/dist/components/ui/alert-dialog/alert-dialog-media.svelte.d.ts +5 -0
- package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte +20 -0
- package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte +7 -0
- package/dist/components/ui/alert-dialog/alert-dialog-portal.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/alert-dialog-title.svelte +20 -0
- package/dist/components/ui/alert-dialog/alert-dialog-title.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog-trigger.svelte +7 -0
- package/dist/components/ui/alert-dialog/alert-dialog-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/alert-dialog/alert-dialog.svelte +7 -0
- package/dist/components/ui/alert-dialog/alert-dialog.svelte.d.ts +3 -0
- package/dist/components/ui/alert-dialog/index.d.ts +13 -0
- package/dist/components/ui/alert-dialog/index.js +15 -0
- package/dist/components/ui/app-dialog/app-dialog.svelte +111 -0
- package/dist/components/ui/app-dialog/app-dialog.svelte.d.ts +41 -0
- package/dist/components/ui/app-dialog/index.d.ts +2 -0
- package/dist/components/ui/app-dialog/index.js +2 -0
- package/dist/components/ui/app-shell/app-nav.svelte +299 -0
- package/dist/components/ui/app-shell/app-nav.svelte.d.ts +22 -0
- package/dist/components/ui/app-shell/app-shell.svelte +675 -0
- package/dist/components/ui/app-shell/app-shell.svelte.d.ts +157 -0
- package/dist/components/ui/app-shell/index.d.ts +6 -0
- package/dist/components/ui/app-shell/index.js +6 -0
- package/dist/components/ui/app-shell/measure.d.ts +28 -0
- package/dist/components/ui/app-shell/measure.js +21 -0
- package/dist/components/ui/app-shell/texture.d.ts +32 -0
- package/dist/components/ui/app-shell/texture.js +27 -0
- package/dist/components/ui/app-shell/types.d.ts +134 -0
- package/dist/components/ui/app-shell/types.js +88 -0
- package/dist/components/ui/arc-gauge/arc-gauge.svelte +112 -0
- package/dist/components/ui/arc-gauge/arc-gauge.svelte.d.ts +15 -0
- package/dist/components/ui/arc-gauge/index.d.ts +3 -0
- package/dist/components/ui/arc-gauge/index.js +2 -0
- package/dist/components/ui/avatar/avatar-fallback.svelte +26 -0
- package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +4 -0
- package/dist/components/ui/avatar/avatar-image.svelte +17 -0
- package/dist/components/ui/avatar/avatar-image.svelte.d.ts +4 -0
- package/dist/components/ui/avatar/avatar.svelte +31 -0
- package/dist/components/ui/avatar/avatar.svelte.d.ts +4 -0
- package/dist/components/ui/avatar/index.d.ts +4 -0
- package/dist/components/ui/avatar/index.js +6 -0
- package/dist/components/ui/badge/badge.svelte +50 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +38 -0
- package/dist/components/ui/badge/index.d.ts +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/bar-row/bar-row.svelte +42 -0
- package/dist/components/ui/bar-row/bar-row.svelte.d.ts +12 -0
- package/dist/components/ui/bar-row/index.d.ts +2 -0
- package/dist/components/ui/bar-row/index.js +2 -0
- package/dist/components/ui/button/button.svelte +89 -0
- package/dist/components/ui/button/button.svelte.d.ts +70 -0
- package/dist/components/ui/button/index.d.ts +2 -0
- package/dist/components/ui/button/index.js +4 -0
- package/dist/components/ui/card/card-action.svelte +23 -0
- package/dist/components/ui/card/card-action.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-content.svelte +20 -0
- package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-description.svelte +20 -0
- package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-footer.svelte +23 -0
- package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-header.svelte +23 -0
- package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
- package/dist/components/ui/card/card-title.svelte +52 -0
- package/dist/components/ui/card/card-title.svelte.d.ts +8 -0
- package/dist/components/ui/card/card.svelte +25 -0
- package/dist/components/ui/card/card.svelte.d.ts +8 -0
- package/dist/components/ui/card/index.d.ts +8 -0
- package/dist/components/ui/card/index.js +10 -0
- package/dist/components/ui/checkbox/checkbox.svelte +36 -0
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +8 -0
- package/dist/components/ui/checkbox/index.d.ts +2 -0
- package/dist/components/ui/checkbox/index.js +2 -0
- package/dist/components/ui/command/command-dialog.svelte +42 -0
- package/dist/components/ui/command/command-dialog.svelte.d.ts +14 -0
- package/dist/components/ui/command/command-empty.svelte +17 -0
- package/dist/components/ui/command/command-empty.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-group.svelte +33 -0
- package/dist/components/ui/command/command-group.svelte.d.ts +7 -0
- package/dist/components/ui/command/command-input.svelte +36 -0
- package/dist/components/ui/command/command-input.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-item.svelte +27 -0
- package/dist/components/ui/command/command-item.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-link-item.svelte +20 -0
- package/dist/components/ui/command/command-link-item.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-list.svelte +20 -0
- package/dist/components/ui/command/command-list.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-loading.svelte +7 -0
- package/dist/components/ui/command/command-loading.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-separator.svelte +17 -0
- package/dist/components/ui/command/command-separator.svelte.d.ts +4 -0
- package/dist/components/ui/command/command-shortcut.svelte +23 -0
- package/dist/components/ui/command/command-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/command/command.svelte +28 -0
- package/dist/components/ui/command/command.svelte.d.ts +8 -0
- package/dist/components/ui/command/index.d.ts +12 -0
- package/dist/components/ui/command/index.js +14 -0
- package/dist/components/ui/command-palette/command-palette.svelte +94 -0
- package/dist/components/ui/command-palette/command-palette.svelte.d.ts +40 -0
- package/dist/components/ui/command-palette/index.d.ts +3 -0
- package/dist/components/ui/command-palette/index.js +2 -0
- package/dist/components/ui/context-column/context-column.svelte +56 -0
- package/dist/components/ui/context-column/context-column.svelte.d.ts +14 -0
- package/dist/components/ui/context-column/index.d.ts +2 -0
- package/dist/components/ui/context-column/index.js +2 -0
- package/dist/components/ui/data-table/data-table.svelte.d.ts +40 -0
- package/dist/components/ui/data-table/data-table.svelte.js +110 -0
- package/dist/components/ui/data-table/flex-render.svelte +40 -0
- package/dist/components/ui/data-table/flex-render.svelte.d.ts +33 -0
- package/dist/components/ui/data-table/index.d.ts +3 -0
- package/dist/components/ui/data-table/index.js +3 -0
- package/dist/components/ui/data-table/render-helpers.d.ts +90 -0
- package/dist/components/ui/data-table/render-helpers.js +99 -0
- package/dist/components/ui/data-table-tanstack/data-table-tanstack.svelte +247 -0
- package/dist/components/ui/data-table-tanstack/data-table-tanstack.svelte.d.ts +79 -0
- package/dist/components/ui/data-table-tanstack/index.d.ts +3 -0
- package/dist/components/ui/data-table-tanstack/index.js +2 -0
- package/dist/components/ui/data-table-toolbar/data-table-toolbar.svelte +102 -0
- package/dist/components/ui/data-table-toolbar/data-table-toolbar.svelte.d.ts +32 -0
- package/dist/components/ui/data-table-toolbar/index.d.ts +3 -0
- package/dist/components/ui/data-table-toolbar/index.js +2 -0
- package/dist/components/ui/detail-panel/detail-panel.svelte +95 -0
- package/dist/components/ui/detail-panel/detail-panel.svelte.d.ts +26 -0
- package/dist/components/ui/detail-panel/index.d.ts +2 -0
- package/dist/components/ui/detail-panel/index.js +2 -0
- package/dist/components/ui/dialog/dialog-close.svelte +11 -0
- package/dist/components/ui/dialog/dialog-close.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-content.svelte +48 -0
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +13 -0
- package/dist/components/ui/dialog/dialog-description.svelte +20 -0
- package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-footer.svelte +35 -0
- package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +8 -0
- package/dist/components/ui/dialog/dialog-header.svelte +20 -0
- package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
- package/dist/components/ui/dialog/dialog-overlay.svelte +20 -0
- package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-portal.svelte +7 -0
- package/dist/components/ui/dialog/dialog-portal.svelte.d.ts +3 -0
- package/dist/components/ui/dialog/dialog-title.svelte +17 -0
- package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog-trigger.svelte +11 -0
- package/dist/components/ui/dialog/dialog-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/dialog/dialog.svelte +7 -0
- package/dist/components/ui/dialog/dialog.svelte.d.ts +3 -0
- package/dist/components/ui/dialog/index.d.ts +11 -0
- package/dist/components/ui/dialog/index.js +13 -0
- package/dist/components/ui/dialog-section/dialog-section.svelte +20 -0
- package/dist/components/ui/dialog-section/dialog-section.svelte.d.ts +8 -0
- package/dist/components/ui/dialog-section/index.d.ts +2 -0
- package/dist/components/ui/dialog-section/index.js +2 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +44 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +9 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +31 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +10 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +22 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +27 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +27 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +8 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-portal.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +16 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +34 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +17 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +23 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +5 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +20 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +29 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte +7 -0
- package/dist/components/ui/dropdown-menu/dropdown-menu.svelte.d.ts +3 -0
- package/dist/components/ui/dropdown-menu/index.d.ts +18 -0
- package/dist/components/ui/dropdown-menu/index.js +18 -0
- package/dist/components/ui/empty-state/empty-state.svelte +44 -0
- package/dist/components/ui/empty-state/empty-state.svelte.d.ts +14 -0
- package/dist/components/ui/empty-state/index.d.ts +2 -0
- package/dist/components/ui/empty-state/index.js +2 -0
- package/dist/components/ui/error-state/error-state.svelte +52 -0
- package/dist/components/ui/error-state/error-state.svelte.d.ts +10 -0
- package/dist/components/ui/error-state/index.d.ts +2 -0
- package/dist/components/ui/error-state/index.js +2 -0
- package/dist/components/ui/info-tip/index.d.ts +2 -0
- package/dist/components/ui/info-tip/index.js +2 -0
- package/dist/components/ui/info-tip/info-tip.svelte +37 -0
- package/dist/components/ui/info-tip/info-tip.svelte.d.ts +10 -0
- package/dist/components/ui/input/index.d.ts +2 -0
- package/dist/components/ui/input/index.js +4 -0
- package/dist/components/ui/input/input.svelte +48 -0
- package/dist/components/ui/input/input.svelte.d.ts +13 -0
- package/dist/components/ui/input-group/index.d.ts +7 -0
- package/dist/components/ui/input-group/index.js +9 -0
- package/dist/components/ui/input-group/input-group-addon.svelte +53 -0
- package/dist/components/ui/input-group/input-group-addon.svelte.d.ts +32 -0
- package/dist/components/ui/input-group/input-group-button.svelte +49 -0
- package/dist/components/ui/input-group/input-group-button.svelte.d.ts +32 -0
- package/dist/components/ui/input-group/input-group-input.svelte +23 -0
- package/dist/components/ui/input-group/input-group-input.svelte.d.ts +11 -0
- package/dist/components/ui/input-group/input-group-text.svelte +22 -0
- package/dist/components/ui/input-group/input-group-text.svelte.d.ts +5 -0
- package/dist/components/ui/input-group/input-group-textarea.svelte +23 -0
- package/dist/components/ui/input-group/input-group-textarea.svelte.d.ts +3 -0
- package/dist/components/ui/input-group/input-group.svelte +24 -0
- package/dist/components/ui/input-group/input-group.svelte.d.ts +5 -0
- package/dist/components/ui/label/index.d.ts +2 -0
- package/dist/components/ui/label/index.js +4 -0
- package/dist/components/ui/label/label.svelte +20 -0
- package/dist/components/ui/label/label.svelte.d.ts +4 -0
- package/dist/components/ui/loading-state/index.d.ts +2 -0
- package/dist/components/ui/loading-state/index.js +2 -0
- package/dist/components/ui/loading-state/loading-state.svelte +28 -0
- package/dist/components/ui/loading-state/loading-state.svelte.d.ts +8 -0
- package/dist/components/ui/page-header/index.d.ts +2 -0
- package/dist/components/ui/page-header/index.js +2 -0
- package/dist/components/ui/page-header/page-header.svelte +100 -0
- package/dist/components/ui/page-header/page-header.svelte.d.ts +17 -0
- package/dist/components/ui/panel/index.d.ts +2 -0
- package/dist/components/ui/panel/index.js +2 -0
- package/dist/components/ui/panel/panel.svelte +54 -0
- package/dist/components/ui/panel/panel.svelte.d.ts +16 -0
- package/dist/components/ui/password-input/index.d.ts +2 -0
- package/dist/components/ui/password-input/index.js +4 -0
- package/dist/components/ui/password-input/password-input.svelte +48 -0
- package/dist/components/ui/password-input/password-input.svelte.d.ts +8 -0
- package/dist/components/ui/popover/index.d.ts +4 -0
- package/dist/components/ui/popover/index.js +6 -0
- package/dist/components/ui/popover/popover-content.svelte +45 -0
- package/dist/components/ui/popover/popover-content.svelte.d.ts +7 -0
- package/dist/components/ui/popover/popover-trigger.svelte +7 -0
- package/dist/components/ui/popover/popover-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/popover/popover.svelte +7 -0
- package/dist/components/ui/popover/popover.svelte.d.ts +3 -0
- package/dist/components/ui/progress/index.d.ts +2 -0
- package/dist/components/ui/progress/index.js +4 -0
- package/dist/components/ui/progress/progress.svelte +30 -0
- package/dist/components/ui/progress/progress.svelte.d.ts +4 -0
- package/dist/components/ui/scorecard/index.d.ts +2 -0
- package/dist/components/ui/scorecard/index.js +2 -0
- package/dist/components/ui/scorecard/scorecard.svelte +35 -0
- package/dist/components/ui/scorecard/scorecard.svelte.d.ts +8 -0
- package/dist/components/ui/select/index.d.ts +12 -0
- package/dist/components/ui/select/index.js +14 -0
- package/dist/components/ui/select/select-content.svelte +45 -0
- package/dist/components/ui/select/select-content.svelte.d.ts +11 -0
- package/dist/components/ui/select/select-group-heading.svelte +21 -0
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +10 -0
- package/dist/components/ui/select/select-group.svelte +17 -0
- package/dist/components/ui/select/select-group.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-item.svelte +38 -0
- package/dist/components/ui/select/select-item.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-label.svelte +20 -0
- package/dist/components/ui/select/select-label.svelte.d.ts +6 -0
- package/dist/components/ui/select/select-portal.svelte +7 -0
- package/dist/components/ui/select/select-portal.svelte.d.ts +3 -0
- package/dist/components/ui/select/select-scroll-down-button.svelte +23 -0
- package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-scroll-up-button.svelte +23 -0
- package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-separator.svelte +18 -0
- package/dist/components/ui/select/select-separator.svelte.d.ts +4 -0
- package/dist/components/ui/select/select-trigger.svelte +29 -0
- package/dist/components/ui/select/select-trigger.svelte.d.ts +8 -0
- package/dist/components/ui/select/select.svelte +11 -0
- package/dist/components/ui/select/select.svelte.d.ts +3 -0
- package/dist/components/ui/separator/index.d.ts +2 -0
- package/dist/components/ui/separator/index.js +4 -0
- package/dist/components/ui/separator/separator.svelte +23 -0
- package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
- package/dist/components/ui/skeleton/index.d.ts +2 -0
- package/dist/components/ui/skeleton/index.js +4 -0
- package/dist/components/ui/skeleton/skeleton.svelte +17 -0
- package/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
- package/dist/components/ui/sonner/index.d.ts +1 -0
- package/dist/components/ui/sonner/index.js +1 -0
- package/dist/components/ui/sonner/sonner.svelte +34 -0
- package/dist/components/ui/sonner/sonner.svelte.d.ts +4 -0
- package/dist/components/ui/sparkline/index.d.ts +3 -0
- package/dist/components/ui/sparkline/index.js +2 -0
- package/dist/components/ui/sparkline/sparkline.svelte +90 -0
- package/dist/components/ui/sparkline/sparkline.svelte.d.ts +16 -0
- package/dist/components/ui/stat-card/index.d.ts +2 -0
- package/dist/components/ui/stat-card/index.js +2 -0
- package/dist/components/ui/stat-card/stat-card.svelte +77 -0
- package/dist/components/ui/stat-card/stat-card.svelte.d.ts +34 -0
- package/dist/components/ui/stat-list/index.d.ts +3 -0
- package/dist/components/ui/stat-list/index.js +2 -0
- package/dist/components/ui/stat-list/stat-list.svelte +80 -0
- package/dist/components/ui/stat-list/stat-list.svelte.d.ts +23 -0
- package/dist/components/ui/status/index.d.ts +1 -0
- package/dist/components/ui/status/index.js +1 -0
- package/dist/components/ui/status-badge/index.d.ts +3 -0
- package/dist/components/ui/status-badge/index.js +2 -0
- package/dist/components/ui/status-badge/status-badge.svelte +53 -0
- package/dist/components/ui/status-badge/status-badge.svelte.d.ts +39 -0
- package/dist/components/ui/switch/index.d.ts +2 -0
- package/dist/components/ui/switch/index.js +4 -0
- package/dist/components/ui/switch/switch.svelte +39 -0
- package/dist/components/ui/switch/switch.svelte.d.ts +4 -0
- package/dist/components/ui/table/index.d.ts +10 -0
- package/dist/components/ui/table/index.js +12 -0
- package/dist/components/ui/table/table-body.svelte +20 -0
- package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-caption.svelte +20 -0
- package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-cell.svelte +20 -0
- package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-classes.d.ts +15 -0
- package/dist/components/ui/table/table-classes.js +15 -0
- package/dist/components/ui/table/table-footer.svelte +20 -0
- package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-head.svelte +23 -0
- package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-header.svelte +20 -0
- package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
- package/dist/components/ui/table/table-row.svelte +23 -0
- package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
- package/dist/components/ui/table/table.svelte +37 -0
- package/dist/components/ui/table/table.svelte.d.ts +20 -0
- package/dist/components/ui/tabs/index.d.ts +5 -0
- package/dist/components/ui/tabs/index.js +7 -0
- package/dist/components/ui/tabs/tabs-content.svelte +13 -0
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-list.svelte +16 -0
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte +16 -0
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tabs/tabs.svelte +19 -0
- package/dist/components/ui/tabs/tabs.svelte.d.ts +4 -0
- package/dist/components/ui/textarea/index.d.ts +2 -0
- package/dist/components/ui/textarea/index.js +4 -0
- package/dist/components/ui/textarea/textarea.svelte +22 -0
- package/dist/components/ui/textarea/textarea.svelte.d.ts +5 -0
- package/dist/components/ui/tile-grid/index.d.ts +2 -0
- package/dist/components/ui/tile-grid/index.js +2 -0
- package/dist/components/ui/tile-grid/tile-grid.svelte +66 -0
- package/dist/components/ui/tile-grid/tile-grid.svelte.d.ts +43 -0
- package/dist/components/ui/tooltip/index.d.ts +6 -0
- package/dist/components/ui/tooltip/index.js +8 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte +52 -0
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +11 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-portal.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-provider.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +4 -0
- package/dist/components/ui/tooltip/tooltip.svelte +7 -0
- package/dist/components/ui/tooltip/tooltip.svelte.d.ts +4 -0
- package/dist/styles.css +961 -0
- package/dist/utils.d.ts +12 -0
- package/dist/utils.js +5 -0
- package/package.json +81 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The application shell: navigation, top bar and page frame, once.
|
|
3
|
+
*
|
|
4
|
+
* Primitives and page chrome are not what makes an app feel like an app — the
|
|
5
|
+
* shell is. Five household frontends were surveyed before this API was
|
|
6
|
+
* settled, and between them they had built five shells: a rail-plus-drawer,
|
|
7
|
+
* an eleven-file collapsible sidebar tree under its own top bar, and three
|
|
8
|
+
* header-only bars that each solved the mobile question differently. They
|
|
9
|
+
* agreed on almost nothing structurally while looking like they were trying
|
|
10
|
+
* to be the same thing.
|
|
11
|
+
*
|
|
12
|
+
* There is now exactly one composition, no variant prop to choose it: a
|
|
13
|
+
* permanent side rail on md+ (an overlay drawer below it) carrying primary
|
|
14
|
+
* navigation and a brand row that also carries the collapse toggle, PLUS a
|
|
15
|
+
* real top navbar (search, leading/trailing slots, theme toggle, identity) —
|
|
16
|
+
* always both together. Operator ruling, 31/07/2026: every household app
|
|
17
|
+
* renders one shell shape; apps do not choose variants.
|
|
18
|
+
*
|
|
19
|
+
* The collapse toggle sits at the rail's own top edge, on the brand row,
|
|
20
|
+
* where every comparable shell puts a control that acts on the rail — icon
|
|
21
|
+
* only, right of the wordmark, stacking under the mark when the rail is
|
|
22
|
+
* collapsed. The foot is left to the app.
|
|
23
|
+
*
|
|
24
|
+
* Search can sit in either of two places, because it reads as a different
|
|
25
|
+
* thing depending on what is beside it. `searchPlacement` defaults to
|
|
26
|
+
* `leading` — its historical spot just after the `context` slot, so a shell
|
|
27
|
+
* that never names the prop is unchanged — and `trailing` moves it into the
|
|
28
|
+
* right-hand group with the theme toggle and identity, so that when `context`
|
|
29
|
+
* carries route content the global affordance reads as global rather than as
|
|
30
|
+
* part of the switcher next to it.
|
|
31
|
+
*
|
|
32
|
+
* Content WIDTH is the one dimension that came back, as `measure`, and it
|
|
33
|
+
* came back on a measurement rather than on taste. "Always full-width" did
|
|
34
|
+
* not remove the decision, it pushed it down into every page: a consumer was
|
|
35
|
+
* surveyed at 2560px and had six distinct caps across nine routes, every one
|
|
36
|
+
* of them a hand-written `mx-auto max-w-*` at the top of a `+page.svelte`,
|
|
37
|
+
* between them using 15% to 79% of the width actually available. That is
|
|
38
|
+
* fifteen independent guesses, not a shell shape.
|
|
39
|
+
*
|
|
40
|
+
* `measure` is a small named scale, chosen once in the layout, and it is not
|
|
41
|
+
* the old `content` prop returning. It defaults to `full`, so a shell that
|
|
42
|
+
* never mentions it renders byte-identically; its tiers are CSS custom
|
|
43
|
+
* properties an app retunes without a release; and it exists to REPLACE
|
|
44
|
+
* per-page width decisions rather than to offer an app a look.
|
|
45
|
+
*
|
|
46
|
+
* Content TEXTURE came back the same way, on the same kind of evidence. Two
|
|
47
|
+
* apps had separately built one picture — a faint dot-grid floor with a soft
|
|
48
|
+
* accent vignette — under two names in two app.css files, and one of them
|
|
49
|
+
* applied it as a helper class per route, so it reached four routes out of
|
|
50
|
+
* about fifteen. Which pages wore the house atmosphere was decided by which
|
|
51
|
+
* pages someone had happened to touch. `texture` is one named picture the
|
|
52
|
+
* SHELL paints once, off by default, its inks tuned by custom properties.
|
|
53
|
+
*
|
|
54
|
+
* Everything else the surveyed apps differed on turned out to be a slot, not
|
|
55
|
+
* a variant: the brand, the identity surface, a context switcher, a banner, a
|
|
56
|
+
* secondary column. Those are snippets, so this package imports no app store,
|
|
57
|
+
* no app route and no app brand — the coupling that made the best shell in
|
|
58
|
+
* the estate unliftable in the first place.
|
|
59
|
+
*
|
|
60
|
+
* The minimum useful call is two props:
|
|
61
|
+
*
|
|
62
|
+
* <AppShell nav={navGroups} brandTitle="Console" currentPath={page.url.pathname}>
|
|
63
|
+
* {@render children()}
|
|
64
|
+
* </AppShell>
|
|
65
|
+
*/
|
|
66
|
+
import type { Snippet } from 'svelte';
|
|
67
|
+
import type { ShellMeasure } from './measure.js';
|
|
68
|
+
import type { ShellTexture } from './texture.js';
|
|
69
|
+
import { type NavSource } from './types.js';
|
|
70
|
+
type $$ComponentProps = {
|
|
71
|
+
/** Navigation: bare items, groups, or a mix. Filter for permissions first. */
|
|
72
|
+
nav?: NavSource;
|
|
73
|
+
/** The primary nav landmark's accessible name — forwarded to the rail/drawer
|
|
74
|
+
AppNav. Distinguish it from a second shell on the same page, or from a
|
|
75
|
+
route-scoped secondary AppNav. */
|
|
76
|
+
navLabel?: string;
|
|
77
|
+
/**
|
|
78
|
+
* The current path, for active state and for closing the mobile nav on
|
|
79
|
+
* navigation. Apps pass `page.url.pathname`.
|
|
80
|
+
*
|
|
81
|
+
* It is a prop rather than a `$app/state` import on purpose: this package
|
|
82
|
+
* is built with svelte-package and has no SvelteKit runtime of its own, so
|
|
83
|
+
* importing `$app/state` would make SvelteKit a hard peer AND make the
|
|
84
|
+
* shell untestable outside a running app. One line at the call site buys
|
|
85
|
+
* a component that is framework-agnostic and genuinely drivable.
|
|
86
|
+
*/
|
|
87
|
+
currentPath?: string;
|
|
88
|
+
/** Offer an icon-only collapse toggle at the rail head, on the brand row. */
|
|
89
|
+
collapsible?: boolean;
|
|
90
|
+
/** Rail collapse state. Bind it to persist the choice across sessions. */
|
|
91
|
+
collapsed?: boolean;
|
|
92
|
+
/** Full control of the brand lockup. Overrides brandTitle/brandMark. */
|
|
93
|
+
brand?: Snippet;
|
|
94
|
+
/** Wordmark text, rendered in the display face. */
|
|
95
|
+
brandTitle?: string;
|
|
96
|
+
/** The mark beside the wordmark — an app's own logo component. */
|
|
97
|
+
brandMark?: Snippet;
|
|
98
|
+
/** Where the brand links. */
|
|
99
|
+
homeHref?: string;
|
|
100
|
+
/** Full-width region directly under the top bar: reconnect notices, trials. */
|
|
101
|
+
banner?: Snippet;
|
|
102
|
+
/** Leading top-bar slot, before the search affordance: a context switcher. */
|
|
103
|
+
context?: Snippet;
|
|
104
|
+
/** Trailing top-bar slot, before the theme toggle: app-level action buttons. */
|
|
105
|
+
actions?: Snippet;
|
|
106
|
+
/** The signed-in user surface. Rendered once, at the end of the top bar. */
|
|
107
|
+
identity?: Snippet;
|
|
108
|
+
/** A secondary, route-scoped column between the nav and the page body. */
|
|
109
|
+
sidebar?: Snippet;
|
|
110
|
+
/** Provide to render the search affordance. Usually opens a CommandPalette. */
|
|
111
|
+
onSearch?: () => void;
|
|
112
|
+
searchLabel?: string;
|
|
113
|
+
/** The shortcut hint rendered in the search affordance; '' hides the kbd. */
|
|
114
|
+
searchShortcut?: string;
|
|
115
|
+
/**
|
|
116
|
+
* Where the search affordance sits in the top bar. `leading` (default)
|
|
117
|
+
* keeps its historical position just after the `context` slot; `trailing`
|
|
118
|
+
* moves it into the right-hand group with the theme toggle and identity —
|
|
119
|
+
* for when `context` carries route content and search should read as a
|
|
120
|
+
* global control rather than as part of it.
|
|
121
|
+
*/
|
|
122
|
+
searchPlacement?: 'leading' | 'trailing';
|
|
123
|
+
themeToggle?: boolean;
|
|
124
|
+
/** Override the theme action. Defaults to mode-watcher's toggleMode. */
|
|
125
|
+
onToggleTheme?: () => void;
|
|
126
|
+
padded?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* How wide the page body may get, from a named scale: `prose` (72ch, for
|
|
129
|
+
* long-form running text), `page` (80rem — forms, detail views,
|
|
130
|
+
* settings), `wide` (120rem — indexes, grids, tables, dashboards), or
|
|
131
|
+
* `full` (no cap).
|
|
132
|
+
*
|
|
133
|
+
* Defaults to `full`, so a shell that does not mention it is unchanged.
|
|
134
|
+
* Set it in the layout, once: the point is that pages stop each deciding
|
|
135
|
+
* their own width. The cap is the content box's border box, so `padded`
|
|
136
|
+
* spends its padding inside the measure.
|
|
137
|
+
*/
|
|
138
|
+
measure?: ShellMeasure;
|
|
139
|
+
/**
|
|
140
|
+
* The house atmosphere on the content region: `grid` (a dot-grid floor
|
|
141
|
+
* plus a corner vignette) or `none`.
|
|
142
|
+
*
|
|
143
|
+
* Defaults to `none`, so a shell that does not mention it is unchanged.
|
|
144
|
+
* Set it in the layout, once — that the SHELL paints it is the whole
|
|
145
|
+
* point, because a helper class apps apply per route is how one consumer
|
|
146
|
+
* ended up wearing the house texture on four routes out of fifteen. The
|
|
147
|
+
* inks and the pitch are `--ds-shell-texture-*` custom properties an app
|
|
148
|
+
* retunes in one declaration.
|
|
149
|
+
*/
|
|
150
|
+
texture?: ShellTexture;
|
|
151
|
+
/** Extra classes on the scrolling content container. */
|
|
152
|
+
mainClass?: string;
|
|
153
|
+
children: Snippet;
|
|
154
|
+
};
|
|
155
|
+
declare const AppShell: import("svelte").Component<$$ComponentProps, {}, "collapsed">;
|
|
156
|
+
type AppShell = ReturnType<typeof AppShell>;
|
|
157
|
+
export default AppShell;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as AppShell } from './app-shell.svelte';
|
|
2
|
+
export { default as AppNav } from './app-nav.svelte';
|
|
3
|
+
export { default } from './app-shell.svelte';
|
|
4
|
+
export { SHELL_MEASURES, type ShellMeasure } from './measure.js';
|
|
5
|
+
export { SHELL_TEXTURES, type ShellTexture } from './texture.js';
|
|
6
|
+
export { hasActiveNavChild, isNavGroup, isNavItemActive, navChildren, toGroups, toItems, type IconComponent, type NavChildItem, type NavEntry, type NavGroup, type NavItem, type NavSource } from './types.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as AppShell } from './app-shell.svelte';
|
|
2
|
+
export { default as AppNav } from './app-nav.svelte';
|
|
3
|
+
export { default } from './app-shell.svelte';
|
|
4
|
+
export { SHELL_MEASURES } from './measure.js';
|
|
5
|
+
export { SHELL_TEXTURES } from './texture.js';
|
|
6
|
+
export { hasActiveNavChild, isNavGroup, isNavItemActive, navChildren, toGroups, toItems } from './types.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content measure: how wide the page body is allowed to get.
|
|
3
|
+
*
|
|
4
|
+
* A named scale rather than a width, because a width at the call site is the
|
|
5
|
+
* problem this exists to solve. Surveyed at 2560px, one consumer had six
|
|
6
|
+
* distinct caps across nine routes — `max-w-4xl` here, `max-w-[1600px]` there,
|
|
7
|
+
* a `max-w-md` form somewhere else — each written by whoever built that page,
|
|
8
|
+
* none of them wrong on its own, and no two agreeing. Between them they used
|
|
9
|
+
* 15% to 79% of the width available. A scale with four names cannot drift like
|
|
10
|
+
* that: it is one decision, taken once, in the layout.
|
|
11
|
+
*
|
|
12
|
+
* The tiers resolve through `--ds-shell-measure-*` custom properties (see
|
|
13
|
+
* `styles.css`), so an app retunes any of them in one declaration.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* - `prose` — a genuine reading measure (`72ch`) for long-form running text.
|
|
17
|
+
* - `page` — everyday pages: forms, detail views, settings (`80rem`).
|
|
18
|
+
* - `wide` — indexes, card grids, tables, dashboards (`120rem`).
|
|
19
|
+
* - `full` — no cap. The default, so omitting `measure` changes nothing.
|
|
20
|
+
*
|
|
21
|
+
* The 80rem tier is `page` rather than `default` on purpose. The prop's default
|
|
22
|
+
* is `full`, and a value literally named `default` that you do NOT get by
|
|
23
|
+
* default is a trap a reader falls into once each. It is also not `standard`,
|
|
24
|
+
* which this package already retired for being a name that says nothing.
|
|
25
|
+
*/
|
|
26
|
+
export type ShellMeasure = 'prose' | 'page' | 'wide' | 'full';
|
|
27
|
+
/** Every measure, narrowest first — the order the scale is documented in. */
|
|
28
|
+
export declare const SHELL_MEASURES: readonly ["prose", "page", "wide", "full"];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content measure: how wide the page body is allowed to get.
|
|
3
|
+
*
|
|
4
|
+
* A named scale rather than a width, because a width at the call site is the
|
|
5
|
+
* problem this exists to solve. Surveyed at 2560px, one consumer had six
|
|
6
|
+
* distinct caps across nine routes — `max-w-4xl` here, `max-w-[1600px]` there,
|
|
7
|
+
* a `max-w-md` form somewhere else — each written by whoever built that page,
|
|
8
|
+
* none of them wrong on its own, and no two agreeing. Between them they used
|
|
9
|
+
* 15% to 79% of the width available. A scale with four names cannot drift like
|
|
10
|
+
* that: it is one decision, taken once, in the layout.
|
|
11
|
+
*
|
|
12
|
+
* The tiers resolve through `--ds-shell-measure-*` custom properties (see
|
|
13
|
+
* `styles.css`), so an app retunes any of them in one declaration.
|
|
14
|
+
*/
|
|
15
|
+
/** Every measure, narrowest first — the order the scale is documented in. */
|
|
16
|
+
export const SHELL_MEASURES = [
|
|
17
|
+
'prose',
|
|
18
|
+
'page',
|
|
19
|
+
'wide',
|
|
20
|
+
'full'
|
|
21
|
+
];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content texture: the house "atmosphere" the shell paints on its own
|
|
3
|
+
* scrolling content region.
|
|
4
|
+
*
|
|
5
|
+
* Two apps had independently built the same thing — a faint dot-grid floor with
|
|
6
|
+
* a soft accent vignette in one corner — under two names, in two app.css files,
|
|
7
|
+
* with two sets of local variables. Neither was wrong; between them they are
|
|
8
|
+
* exactly the drift this package exists to end. Worse, one of them applied it as
|
|
9
|
+
* a helper class per route: four routes out of about fifteen carried it, so
|
|
10
|
+
* whether a page wore the house atmosphere came down to which page someone had
|
|
11
|
+
* happened to touch. A texture an app has to REMEMBER to apply is not a texture,
|
|
12
|
+
* it is a coin toss with a stylesheet.
|
|
13
|
+
*
|
|
14
|
+
* So it moves onto the shell, where there is exactly one place to say it and no
|
|
15
|
+
* per-route decision left to get wrong. `none` is the default, so a shell that
|
|
16
|
+
* never mentions it renders byte-identically.
|
|
17
|
+
*
|
|
18
|
+
* It is one texture, not a menu. Both apps wanted the same picture, and the
|
|
19
|
+
* axes they actually differed on — how dark the dots are, how the vignette is
|
|
20
|
+
* tinted, how far apart the dots sit — are values, not designs. They are
|
|
21
|
+
* `--ds-shell-texture-*` custom properties an app retunes in one declaration
|
|
22
|
+
* (see `styles.css`), which is also how a "plain wash" is reached without a
|
|
23
|
+
* second name in this union: set the grid ink to `transparent` and the vignette
|
|
24
|
+
* remains.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* - `grid` — the house atmosphere: a dot-grid floor plus a corner vignette.
|
|
28
|
+
* - `none` — no texture. The default, so omitting `texture` changes nothing.
|
|
29
|
+
*/
|
|
30
|
+
export type ShellTexture = 'none' | 'grid';
|
|
31
|
+
/** Every texture, the untextured default first — the order it is documented in. */
|
|
32
|
+
export declare const SHELL_TEXTURES: readonly ["none", "grid"];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The content texture: the house "atmosphere" the shell paints on its own
|
|
3
|
+
* scrolling content region.
|
|
4
|
+
*
|
|
5
|
+
* Two apps had independently built the same thing — a faint dot-grid floor with
|
|
6
|
+
* a soft accent vignette in one corner — under two names, in two app.css files,
|
|
7
|
+
* with two sets of local variables. Neither was wrong; between them they are
|
|
8
|
+
* exactly the drift this package exists to end. Worse, one of them applied it as
|
|
9
|
+
* a helper class per route: four routes out of about fifteen carried it, so
|
|
10
|
+
* whether a page wore the house atmosphere came down to which page someone had
|
|
11
|
+
* happened to touch. A texture an app has to REMEMBER to apply is not a texture,
|
|
12
|
+
* it is a coin toss with a stylesheet.
|
|
13
|
+
*
|
|
14
|
+
* So it moves onto the shell, where there is exactly one place to say it and no
|
|
15
|
+
* per-route decision left to get wrong. `none` is the default, so a shell that
|
|
16
|
+
* never mentions it renders byte-identically.
|
|
17
|
+
*
|
|
18
|
+
* It is one texture, not a menu. Both apps wanted the same picture, and the
|
|
19
|
+
* axes they actually differed on — how dark the dots are, how the vignette is
|
|
20
|
+
* tinted, how far apart the dots sit — are values, not designs. They are
|
|
21
|
+
* `--ds-shell-texture-*` custom properties an app retunes in one declaration
|
|
22
|
+
* (see `styles.css`), which is also how a "plain wash" is reached without a
|
|
23
|
+
* second name in this union: set the grid ink to `transparent` and the vignette
|
|
24
|
+
* remains.
|
|
25
|
+
*/
|
|
26
|
+
/** Every texture, the untextured default first — the order it is documented in. */
|
|
27
|
+
export const SHELL_TEXTURES = ['none', 'grid'];
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The navigation vocabulary every app types its own config against.
|
|
3
|
+
*
|
|
4
|
+
* Five apps in the estate were surveyed before this shape was settled, and each
|
|
5
|
+
* had reinvented the same three fields under different names (`label`/`title`,
|
|
6
|
+
* `href`/`path`) plus one or two extras nobody else had. The intersection —
|
|
7
|
+
* label, href, icon — is what every one of them actually needed; `badge`,
|
|
8
|
+
* `exact` and `external` are the union of the genuine extras, each optional so
|
|
9
|
+
* the common case stays two fields.
|
|
10
|
+
*
|
|
11
|
+
* Deliberately ABSENT: any notion of who may see an item. Two apps gate nav on
|
|
12
|
+
* `is_admin` / per-module permission, and both do it with their own auth store.
|
|
13
|
+
* A shared package that knew about permissions would have to know about auth,
|
|
14
|
+
* which is exactly the coupling that made the reference shell unliftable. Apps
|
|
15
|
+
* filter before they pass:
|
|
16
|
+
*
|
|
17
|
+
* const nav = $derived(allNav.filter((i) => !i.adminOnly || user.isAdmin));
|
|
18
|
+
*/
|
|
19
|
+
import type { Component } from 'svelte';
|
|
20
|
+
/** A Lucide (or equivalent) icon component: takes a class, renders an SVG. */
|
|
21
|
+
export type IconComponent = Component<{
|
|
22
|
+
class?: string;
|
|
23
|
+
}>;
|
|
24
|
+
/** One navigable destination. */
|
|
25
|
+
export interface NavItem {
|
|
26
|
+
/** The visible text. Also the accessible name when the rail is collapsed. */
|
|
27
|
+
label: string;
|
|
28
|
+
/** Destination path. */
|
|
29
|
+
href: string;
|
|
30
|
+
/** Optional leading icon. Omit it for a label-only row; alignment is kept. */
|
|
31
|
+
icon?: IconComponent;
|
|
32
|
+
/** Optional trailing count or short tag (an unread count, a "beta" tag). */
|
|
33
|
+
badge?: string | number;
|
|
34
|
+
/**
|
|
35
|
+
* Match the current path exactly rather than by prefix. Prefix is the
|
|
36
|
+
* default because a section root should stay lit while you are inside it;
|
|
37
|
+
* `href: '/'` is always treated as exact, since every path is prefixed by it.
|
|
38
|
+
*/
|
|
39
|
+
exact?: boolean;
|
|
40
|
+
/** Open in a new tab. Renders the standard rel and an off-site affordance. */
|
|
41
|
+
external?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Additional path prefixes this item also owns, beyond its own `href`.
|
|
44
|
+
*
|
|
45
|
+
* Flat navigation has every section's children living under the section's
|
|
46
|
+
* own path, which `href`'s prefix match already covers. It breaks for a
|
|
47
|
+
* section whose children live under a different top-level route — a
|
|
48
|
+
* "browse" list whose detail pages sit at their own short URL rather than
|
|
49
|
+
* nested under the list. Each prefix here is matched exactly like `href`
|
|
50
|
+
* is (prefix, with the same path-segment boundary), independently of
|
|
51
|
+
* `exact` and independently of `href` being forced to exact at `/`: a root
|
|
52
|
+
* item can still claim an additional prefix by full path match.
|
|
53
|
+
*/
|
|
54
|
+
matchPrefixes?: string[];
|
|
55
|
+
/**
|
|
56
|
+
* A section's own sub-navigation, disclosed in place beneath it.
|
|
57
|
+
*
|
|
58
|
+
* Without this, an app whose sections have their own inner navigation has
|
|
59
|
+
* nowhere to put it inside the rail. The observed workaround was modules in
|
|
60
|
+
* `nav` and the current module's pages in the `sidebar` snippet — two
|
|
61
|
+
* left-hand columns on a desktop, and, the reason this shape won over moving
|
|
62
|
+
* modules to a top bar, two surfaces on a phone that both want the same
|
|
63
|
+
* hamburger. One nested tree collapses to one drawer.
|
|
64
|
+
*
|
|
65
|
+
* Named `children`, not `items`, for a mechanical reason as well as a
|
|
66
|
+
* readable one: `isNavGroup` narrows on `'items' in entry`, so an item
|
|
67
|
+
* carrying `items` would be misread as a GROUP by every consumer of this
|
|
68
|
+
* vocabulary, this package's own renderer included.
|
|
69
|
+
*
|
|
70
|
+
* ONE level, and the type is what enforces it: a child is `NavItem` minus
|
|
71
|
+
* this field, so a second nesting is a compile error where the nav is
|
|
72
|
+
* authored rather than a rail nobody can read. The cap is deliberate. The
|
|
73
|
+
* rail is 15.5rem and every level costs an indent; by depth three the label
|
|
74
|
+
* has less room than the chevron beside it. Every household case is one
|
|
75
|
+
* level, and a genuinely deeper tree belongs in the page body, which has the
|
|
76
|
+
* width for it.
|
|
77
|
+
*/
|
|
78
|
+
children?: readonly NavChildItem[];
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A row inside a parent's disclosure: everything an item is, minus the ability
|
|
82
|
+
* to nest again.
|
|
83
|
+
*/
|
|
84
|
+
export type NavChildItem = Omit<NavItem, 'children'>;
|
|
85
|
+
/** A titled run of items. The heading is optional — a leading group usually has none. */
|
|
86
|
+
export interface NavGroup {
|
|
87
|
+
heading?: string;
|
|
88
|
+
items: NavItem[];
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* What the `nav` prop accepts: bare items, groups, or a mix.
|
|
92
|
+
*
|
|
93
|
+
* Three of the five surveyed apps have flat navigation and two have groups, so
|
|
94
|
+
* requiring one shape would have made three apps write `[{ items: [...] }]`
|
|
95
|
+
* wrapper noise or two apps flatten away their headings. A mixed array costs one
|
|
96
|
+
* type guard here and nothing at the call site.
|
|
97
|
+
*/
|
|
98
|
+
export type NavEntry = NavItem | NavGroup;
|
|
99
|
+
export type NavSource = readonly NavEntry[];
|
|
100
|
+
/** Narrow a mixed entry to a group. */
|
|
101
|
+
export declare function isNavGroup(entry: NavEntry): entry is NavGroup;
|
|
102
|
+
/** Normalise any accepted shape to groups, dropping groups that would render empty. */
|
|
103
|
+
export declare function toGroups(nav: NavSource | undefined): NavGroup[];
|
|
104
|
+
/** An item's disclosed rows, normalised — an empty list where there are none. */
|
|
105
|
+
export declare function navChildren(item: NavItem): readonly NavChildItem[];
|
|
106
|
+
/**
|
|
107
|
+
* Every item in source order, ignoring grouping — a parent immediately followed
|
|
108
|
+
* by its own children. Used by the command palette.
|
|
109
|
+
*
|
|
110
|
+
* Children are included because they are destinations like any other, and the
|
|
111
|
+
* palette is the fastest route to a page three levels into a section. An item
|
|
112
|
+
* with no children flattens exactly as it always did.
|
|
113
|
+
*/
|
|
114
|
+
export declare function toItems(nav: NavSource | undefined): NavItem[];
|
|
115
|
+
/**
|
|
116
|
+
* Whether `item` is the current page.
|
|
117
|
+
*
|
|
118
|
+
* Prefix matching is what makes a section root stay lit on its children; the
|
|
119
|
+
* `+ '/'` is what stops `/audit` lighting up on `/audit-log`. A root href is
|
|
120
|
+
* forced to exact or it would match every path in the app — but that forcing
|
|
121
|
+
* applies only to `href` itself; `matchPrefixes` is always prefix-matched, so
|
|
122
|
+
* a root item can still claim a second, unrelated section by full path.
|
|
123
|
+
*/
|
|
124
|
+
export declare function isNavItemActive(item: NavItem, currentPath: string | undefined): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Whether one of `item`'s disclosed children is the current page.
|
|
127
|
+
*
|
|
128
|
+
* Two things read this. It is what auto-opens the group you have navigated
|
|
129
|
+
* into — a rail that will not show you where you are is the defect this whole
|
|
130
|
+
* feature exists to avoid. And it marks a parent whose section you are inside
|
|
131
|
+
* but whose own `href` does not match, which flat prefix matching cannot see
|
|
132
|
+
* when the children live at their own top-level routes.
|
|
133
|
+
*/
|
|
134
|
+
export declare function hasActiveNavChild(item: NavItem, currentPath: string | undefined): boolean;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** Narrow a mixed entry to a group. */
|
|
2
|
+
export function isNavGroup(entry) {
|
|
3
|
+
return 'items' in entry && Array.isArray(entry.items);
|
|
4
|
+
}
|
|
5
|
+
/** Normalise any accepted shape to groups, dropping groups that would render empty. */
|
|
6
|
+
export function toGroups(nav) {
|
|
7
|
+
if (!nav)
|
|
8
|
+
return [];
|
|
9
|
+
const groups = [];
|
|
10
|
+
// Consecutive bare items collapse into one unheaded run, so a flat array
|
|
11
|
+
// renders as a single group rather than one group per item (which would
|
|
12
|
+
// space every link apart). A group entry closes the run.
|
|
13
|
+
let run = null;
|
|
14
|
+
for (const entry of nav) {
|
|
15
|
+
if (isNavGroup(entry)) {
|
|
16
|
+
run = null;
|
|
17
|
+
if (entry.items.length > 0)
|
|
18
|
+
groups.push(entry);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
if (!run) {
|
|
22
|
+
run = { items: [] };
|
|
23
|
+
groups.push(run);
|
|
24
|
+
}
|
|
25
|
+
run.items.push(entry);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return groups;
|
|
29
|
+
}
|
|
30
|
+
/** No allocation per call for the overwhelmingly common childless item. */
|
|
31
|
+
const NO_CHILDREN = [];
|
|
32
|
+
/** An item's disclosed rows, normalised — an empty list where there are none. */
|
|
33
|
+
export function navChildren(item) {
|
|
34
|
+
return item.children ?? NO_CHILDREN;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Every item in source order, ignoring grouping — a parent immediately followed
|
|
38
|
+
* by its own children. Used by the command palette.
|
|
39
|
+
*
|
|
40
|
+
* Children are included because they are destinations like any other, and the
|
|
41
|
+
* palette is the fastest route to a page three levels into a section. An item
|
|
42
|
+
* with no children flattens exactly as it always did.
|
|
43
|
+
*/
|
|
44
|
+
export function toItems(nav) {
|
|
45
|
+
if (!nav)
|
|
46
|
+
return [];
|
|
47
|
+
return nav.flatMap((entry) => {
|
|
48
|
+
const items = isNavGroup(entry) ? entry.items : [entry];
|
|
49
|
+
return items.flatMap((item) => [item, ...navChildren(item)]);
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/** Prefix-match `path` against `prefix`, without running past a path segment. */
|
|
53
|
+
function matchesPrefix(path, prefix) {
|
|
54
|
+
return path === prefix || path.startsWith(prefix + '/');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Whether `item` is the current page.
|
|
58
|
+
*
|
|
59
|
+
* Prefix matching is what makes a section root stay lit on its children; the
|
|
60
|
+
* `+ '/'` is what stops `/audit` lighting up on `/audit-log`. A root href is
|
|
61
|
+
* forced to exact or it would match every path in the app — but that forcing
|
|
62
|
+
* applies only to `href` itself; `matchPrefixes` is always prefix-matched, so
|
|
63
|
+
* a root item can still claim a second, unrelated section by full path.
|
|
64
|
+
*/
|
|
65
|
+
export function isNavItemActive(item, currentPath) {
|
|
66
|
+
if (!currentPath)
|
|
67
|
+
return false;
|
|
68
|
+
const ownMatch = item.exact || item.href === '/'
|
|
69
|
+
? currentPath === item.href
|
|
70
|
+
: matchesPrefix(currentPath, item.href);
|
|
71
|
+
if (ownMatch)
|
|
72
|
+
return true;
|
|
73
|
+
return (item.matchPrefixes ?? []).some((prefix) => matchesPrefix(currentPath, prefix));
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether one of `item`'s disclosed children is the current page.
|
|
77
|
+
*
|
|
78
|
+
* Two things read this. It is what auto-opens the group you have navigated
|
|
79
|
+
* into — a rail that will not show you where you are is the defect this whole
|
|
80
|
+
* feature exists to avoid. And it marks a parent whose section you are inside
|
|
81
|
+
* but whose own `href` does not match, which flat prefix matching cannot see
|
|
82
|
+
* when the children live at their own top-level routes.
|
|
83
|
+
*/
|
|
84
|
+
export function hasActiveNavChild(item, currentPath) {
|
|
85
|
+
if (!currentPath)
|
|
86
|
+
return false;
|
|
87
|
+
return navChildren(item).some((child) => isNavItemActive(child, currentPath));
|
|
88
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Status } from '../status/index.js';
|
|
3
|
+
|
|
4
|
+
// The gauge's tone is a health read, not the full five-state vocabulary —
|
|
5
|
+
// info/neutral have no caller today, so the type stays a named subset
|
|
6
|
+
// rather than widening to all of Status speculatively.
|
|
7
|
+
export type GaugeTone = Extract<Status, 'success' | 'warning' | 'error'>;
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
12
|
+
import { cn } from '../../../utils.js';
|
|
13
|
+
|
|
14
|
+
// Radial capacity/percentage gauge: a compact SVG ring for a single 0–100
|
|
15
|
+
// metric where a StatCard's full metric tile would be too heavy — a
|
|
16
|
+
// token-burn dial, a rate-limit-window ring. `size` is both the viewBox
|
|
17
|
+
// unit and the gauge's physical footprint, so a consumer picks its
|
|
18
|
+
// on-screen size directly (36 for a small inline dial, 42 for a
|
|
19
|
+
// standalone one) rather than trusting ambient sizing.
|
|
20
|
+
let {
|
|
21
|
+
pct = 0,
|
|
22
|
+
tone = 'success',
|
|
23
|
+
size = 42,
|
|
24
|
+
showLabel = false,
|
|
25
|
+
label = '',
|
|
26
|
+
ref = $bindable(null),
|
|
27
|
+
class: className,
|
|
28
|
+
...restProps
|
|
29
|
+
}: Omit<SVGAttributes<SVGSVGElement>, 'class'> & {
|
|
30
|
+
pct?: number;
|
|
31
|
+
tone?: GaugeTone;
|
|
32
|
+
size?: number;
|
|
33
|
+
showLabel?: boolean;
|
|
34
|
+
label?: string;
|
|
35
|
+
ref?: SVGSVGElement | null;
|
|
36
|
+
class?: string;
|
|
37
|
+
} = $props();
|
|
38
|
+
|
|
39
|
+
const clampedPct = $derived(Math.max(0, Math.min(100, pct)));
|
|
40
|
+
|
|
41
|
+
const toneVar: Record<GaugeTone, string> = {
|
|
42
|
+
success: 'var(--ds-color-status-success)',
|
|
43
|
+
warning: 'var(--ds-color-status-warning)',
|
|
44
|
+
error: 'var(--ds-color-status-error)'
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const cx = $derived(size / 2);
|
|
48
|
+
const cy = $derived(size / 2);
|
|
49
|
+
const r = $derived(size / 2 - 4);
|
|
50
|
+
const circumference = $derived(2 * Math.PI * r);
|
|
51
|
+
const offset = $derived(circumference * (1 - clampedPct / 100));
|
|
52
|
+
const color = $derived(toneVar[tone] ?? toneVar.success);
|
|
53
|
+
const big = $derived(size >= 40);
|
|
54
|
+
const strokeWidth = 4;
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<svg
|
|
58
|
+
bind:this={ref}
|
|
59
|
+
viewBox="0 0 {size} {size}"
|
|
60
|
+
width={size}
|
|
61
|
+
height={size}
|
|
62
|
+
aria-label="{clampedPct}% used"
|
|
63
|
+
class={cn(className)}
|
|
64
|
+
{...restProps}
|
|
65
|
+
>
|
|
66
|
+
<circle cx={cx} cy={cy} r={r} fill="none" stroke="var(--ds-color-surface-3)" stroke-width={strokeWidth} />
|
|
67
|
+
<circle
|
|
68
|
+
cx={cx}
|
|
69
|
+
cy={cy}
|
|
70
|
+
r={r}
|
|
71
|
+
fill="none"
|
|
72
|
+
stroke={color}
|
|
73
|
+
stroke-width={strokeWidth}
|
|
74
|
+
stroke-linecap="round"
|
|
75
|
+
stroke-dasharray={circumference}
|
|
76
|
+
stroke-dashoffset={offset}
|
|
77
|
+
transform="rotate(-90 {cx} {cy})"
|
|
78
|
+
/>
|
|
79
|
+
{#if big && showLabel}
|
|
80
|
+
<!--
|
|
81
|
+
The percentage and unit-label glyphs below are graphic annotations
|
|
82
|
+
scaled by the viewBox, not CSS/DOM running text — the household's
|
|
83
|
+
~0.75rem type floor governs body copy, not a numeral drawn inside a
|
|
84
|
+
purpose-built, self-contained radial gauge. Growing them to clear
|
|
85
|
+
that floor would blow out the ring's established compact geometry
|
|
86
|
+
(a 36–42 SVG-unit footprint), so they stay at their literal 10 and
|
|
87
|
+
5.4 user-unit sizes deliberately (design-system#15).
|
|
88
|
+
-->
|
|
89
|
+
<text
|
|
90
|
+
x={cx}
|
|
91
|
+
y={cy - 0.5}
|
|
92
|
+
text-anchor="middle"
|
|
93
|
+
dominant-baseline="central"
|
|
94
|
+
font-family="var(--ds-font-code)"
|
|
95
|
+
font-size="10"
|
|
96
|
+
font-weight="600"
|
|
97
|
+
fill="var(--ds-color-foreground)"
|
|
98
|
+
>{clampedPct}%</text>
|
|
99
|
+
{#if label}
|
|
100
|
+
<text
|
|
101
|
+
x={cx}
|
|
102
|
+
y={cy + 7.5}
|
|
103
|
+
text-anchor="middle"
|
|
104
|
+
dominant-baseline="central"
|
|
105
|
+
font-family="var(--ds-font-body)"
|
|
106
|
+
font-size="5.4"
|
|
107
|
+
fill="var(--ds-color-muted-foreground)"
|
|
108
|
+
letter-spacing="0.5"
|
|
109
|
+
>{label.toUpperCase()}</text>
|
|
110
|
+
{/if}
|
|
111
|
+
{/if}
|
|
112
|
+
</svg>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Status } from '../status/index.js';
|
|
2
|
+
export type GaugeTone = Extract<Status, 'success' | 'warning' | 'error'>;
|
|
3
|
+
import type { SVGAttributes } from 'svelte/elements';
|
|
4
|
+
type $$ComponentProps = Omit<SVGAttributes<SVGSVGElement>, 'class'> & {
|
|
5
|
+
pct?: number;
|
|
6
|
+
tone?: GaugeTone;
|
|
7
|
+
size?: number;
|
|
8
|
+
showLabel?: boolean;
|
|
9
|
+
label?: string;
|
|
10
|
+
ref?: SVGSVGElement | null;
|
|
11
|
+
class?: string;
|
|
12
|
+
};
|
|
13
|
+
declare const ArcGauge: import("svelte").Component<$$ComponentProps, {}, "ref">;
|
|
14
|
+
type ArcGauge = ReturnType<typeof ArcGauge>;
|
|
15
|
+
export default ArcGauge;
|