@evinvest/uikit 0.31.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -12
- package/dist/components/{accordion.js → atomic/accordion.js} +5 -4
- package/dist/components/atomic/accordion.js.map +1 -0
- package/dist/components/{alert-dialog.js → atomic/alert-dialog.js} +9 -9
- package/dist/components/atomic/alert-dialog.js.map +1 -0
- package/dist/components/{alert.js → atomic/alert.js} +6 -6
- package/dist/components/atomic/alert.js.map +1 -0
- package/dist/components/{animated-number-columns.js → atomic/animated-number-columns.js} +1 -1
- package/dist/components/atomic/animated-number-columns.js.map +1 -0
- package/dist/components/{avatar.js → atomic/avatar.js} +2 -2
- package/dist/components/atomic/avatar.js.map +1 -0
- package/dist/components/atomic/badge.js +26 -0
- package/dist/components/atomic/badge.js.map +1 -0
- package/dist/components/{band.js → atomic/band.js} +2 -2
- package/dist/components/atomic/band.js.map +1 -0
- package/dist/components/{breadcrumb.js → atomic/breadcrumb.js} +10 -12
- package/dist/components/atomic/breadcrumb.js.map +1 -0
- package/dist/components/{button-group.js → atomic/button-group.js} +3 -3
- package/dist/components/atomic/button-group.js.map +1 -0
- package/dist/components/{button.js → atomic/button.js} +8 -7
- package/dist/components/atomic/button.js.map +1 -0
- package/dist/components/{calendar.js → atomic/calendar.js} +12 -27
- package/dist/components/atomic/calendar.js.map +1 -0
- package/dist/components/{card.js → atomic/card.js} +2 -2
- package/dist/components/atomic/card.js.map +1 -0
- package/dist/components/{checkbox.js → atomic/checkbox.js} +6 -5
- package/dist/components/atomic/checkbox.js.map +1 -0
- package/dist/components/{collapsible.js → atomic/collapsible.js} +1 -1
- package/dist/components/atomic/collapsible.js.map +1 -0
- package/dist/components/{command.js → atomic/command.js} +11 -26
- package/dist/components/atomic/command.js.map +1 -0
- package/dist/components/{container.js → atomic/container.js} +2 -2
- package/dist/components/atomic/container.js.map +1 -0
- package/dist/components/{context-menu.js → atomic/context-menu.js} +15 -22
- package/dist/components/atomic/context-menu.js.map +1 -0
- package/dist/components/{dialog.js → atomic/dialog.js} +13 -11
- package/dist/components/atomic/dialog.js.map +1 -0
- package/dist/components/{drawer.js → atomic/drawer.js} +8 -8
- package/dist/components/atomic/drawer.js.map +1 -0
- package/dist/components/{dropdown-menu.js → atomic/dropdown-menu.js} +16 -24
- package/dist/components/atomic/dropdown-menu.js.map +1 -0
- package/dist/components/{empty.js → atomic/empty.js} +2 -2
- package/dist/components/atomic/empty.js.map +1 -0
- package/dist/components/atomic/field-context.js.map +1 -0
- package/dist/components/{form-row.js → atomic/form-row.js} +2 -2
- package/dist/components/atomic/form-row.js.map +1 -0
- package/dist/components/{hover-card.js → atomic/hover-card.js} +8 -8
- package/dist/components/atomic/hover-card.js.map +1 -0
- package/dist/components/{info-tip.js → atomic/info-tip.js} +18 -19
- package/dist/components/atomic/info-tip.js.map +1 -0
- package/dist/components/{input-otp.js → atomic/input-otp.js} +5 -4
- package/dist/components/atomic/input-otp.js.map +1 -0
- package/dist/components/{input.js → atomic/input.js} +3 -3
- package/dist/components/atomic/input.js.map +1 -0
- package/dist/components/{kbd.js → atomic/kbd.js} +2 -2
- package/dist/components/atomic/kbd.js.map +1 -0
- package/dist/components/{key-value.js → atomic/key-value.js} +8 -7
- package/dist/components/atomic/key-value.js.map +1 -0
- package/dist/components/{label.js → atomic/label.js} +2 -2
- package/dist/components/atomic/label.js.map +1 -0
- package/dist/components/{menubar.js → atomic/menubar.js} +16 -27
- package/dist/components/atomic/menubar.js.map +1 -0
- package/dist/components/{native-select.js → atomic/native-select.js} +5 -5
- package/dist/components/atomic/native-select.js.map +1 -0
- package/dist/components/{navigation-menu.js → atomic/navigation-menu.js} +12 -20
- package/dist/components/atomic/navigation-menu.js.map +1 -0
- package/dist/components/{pagination.js → atomic/pagination.js} +19 -20
- package/dist/components/atomic/pagination.js.map +1 -0
- package/dist/components/{popover.js → atomic/popover.js} +10 -10
- package/dist/components/atomic/popover.js.map +1 -0
- package/dist/components/{progress.js → atomic/progress.js} +2 -2
- package/dist/components/atomic/progress.js.map +1 -0
- package/dist/components/{radio-group.js → atomic/radio-group.js} +8 -7
- package/dist/components/atomic/radio-group.js.map +1 -0
- package/dist/components/{scroll-area.js → atomic/scroll-area.js} +2 -2
- package/dist/components/atomic/scroll-area.js.map +1 -0
- package/dist/components/{section-descriptor.js → atomic/section-descriptor.js} +7 -10
- package/dist/components/atomic/section-descriptor.js.map +1 -0
- package/dist/components/{select-listbox.js → atomic/select-listbox.js} +3 -3
- package/dist/components/atomic/select-listbox.js.map +1 -0
- package/dist/components/{select.js → atomic/select.js} +15 -23
- package/dist/components/atomic/select.js.map +1 -0
- package/dist/components/{separator.js → atomic/separator.js} +2 -2
- package/dist/components/atomic/separator.js.map +1 -0
- package/dist/components/{sheet.js → atomic/sheet.js} +13 -11
- package/dist/components/atomic/sheet.js.map +1 -0
- package/dist/components/{sidebar.js → atomic/sidebar.js} +11 -30
- package/dist/components/atomic/sidebar.js.map +1 -0
- package/dist/components/{skeleton.js → atomic/skeleton.js} +2 -2
- package/dist/components/atomic/skeleton.js.map +1 -0
- package/dist/components/{slider.js → atomic/slider.js} +3 -3
- package/dist/components/atomic/slider.js.map +1 -0
- package/dist/components/{sonner.js → atomic/sonner.js} +22 -20
- package/dist/components/atomic/sonner.js.map +1 -0
- package/dist/components/atomic/spinner.js +26 -0
- package/dist/components/atomic/spinner.js.map +1 -0
- package/dist/components/{status-item.js → atomic/status-item.js} +2 -2
- package/dist/components/atomic/status-item.js.map +1 -0
- package/dist/components/{switch.js → atomic/switch.js} +4 -4
- package/dist/components/atomic/switch.js.map +1 -0
- package/dist/components/{table.js → atomic/table.js} +2 -2
- package/dist/components/atomic/table.js.map +1 -0
- package/dist/components/{tabs.js → atomic/tabs.js} +4 -4
- package/dist/components/atomic/tabs.js.map +1 -0
- package/dist/components/{textarea.js → atomic/textarea.js} +3 -3
- package/dist/components/atomic/textarea.js.map +1 -0
- package/dist/components/{toggle-group.js → atomic/toggle-group.js} +4 -4
- package/dist/components/atomic/toggle-group.js.map +1 -0
- package/dist/components/{toggle.js → atomic/toggle.js} +5 -8
- package/dist/components/atomic/toggle.js.map +1 -0
- package/dist/components/{tooltip.js → atomic/tooltip.js} +8 -8
- package/dist/components/atomic/tooltip.js.map +1 -0
- package/dist/components/{use-count-tween.js → atomic/use-count-tween.js} +1 -1
- package/dist/components/atomic/use-count-tween.js.map +1 -0
- package/dist/components/{animated-number.js → derived/animated-number.js} +5 -5
- package/dist/components/derived/animated-number.js.map +1 -0
- package/dist/components/{carousel.js → derived/carousel.js} +10 -10
- package/dist/components/derived/carousel.js.map +1 -0
- package/dist/components/{command-palette.js → derived/command-palette.js} +14 -13
- package/dist/components/derived/command-palette.js.map +1 -0
- package/dist/components/{confirm-dialog.js → derived/confirm-dialog.js} +15 -20
- package/dist/components/derived/confirm-dialog.js.map +1 -0
- package/dist/components/{date-time-picker.js → derived/date-time-picker.js} +18 -22
- package/dist/components/derived/date-time-picker.js.map +1 -0
- package/dist/components/{field.js → derived/field.js} +6 -6
- package/dist/components/derived/field.js.map +1 -0
- package/dist/components/{form.js → derived/form.js} +4 -5
- package/dist/components/derived/form.js.map +1 -0
- package/dist/components/{icon-button.js → derived/icon-button.js} +4 -4
- package/dist/components/derived/icon-button.js.map +1 -0
- package/dist/components/{input-group.js → derived/input-group.js} +5 -5
- package/dist/components/derived/input-group.js.map +1 -0
- package/dist/components/{item.js → derived/item.js} +4 -5
- package/dist/components/derived/item.js.map +1 -0
- package/dist/components/{popover-form.js → derived/popover-form.js} +9 -8
- package/dist/components/derived/popover-form.js.map +1 -0
- package/dist/components/{settings.js → derived/settings.js} +7 -7
- package/dist/components/derived/settings.js.map +1 -0
- package/dist/components/{account-list.js → shell/account-list.js} +5 -5
- package/dist/components/shell/account-list.js.map +1 -0
- package/dist/components/{account-menu-profile.js → shell/account-menu-profile.js} +7 -7
- package/dist/components/shell/account-menu-profile.js.map +1 -0
- package/dist/components/{account-menu.js → shell/account-menu.js} +4 -4
- package/dist/components/shell/account-menu.js.map +1 -0
- package/dist/components/{account-settings-dialog.js → shell/account-settings-dialog.js} +9 -8
- package/dist/components/shell/account-settings-dialog.js.map +1 -0
- package/dist/components/{app-shell.js → shell/app-shell.js} +1 -1
- package/dist/components/shell/app-shell.js.map +1 -0
- package/dist/components/{aside.js → shell/aside.js} +12 -10
- package/dist/components/shell/aside.js.map +1 -0
- package/dist/components/{auth-wall.js → shell/auth-wall.js} +4 -6
- package/dist/components/shell/auth-wall.js.map +1 -0
- package/dist/components/{bottom-tab-bar.js → shell/bottom-tab-bar.js} +4 -4
- package/dist/components/shell/bottom-tab-bar.js.map +1 -0
- package/dist/components/{chat-composer.js → shell/chat-composer.js} +16 -14
- package/dist/components/shell/chat-composer.js.map +1 -0
- package/dist/components/{chat-message.js → shell/chat-message.js} +4 -4
- package/dist/components/shell/chat-message.js.map +1 -0
- package/dist/components/{chat-panel.js → shell/chat-panel.js} +3 -3
- package/dist/components/shell/chat-panel.js.map +1 -0
- package/dist/components/shell/chat-stream-text.js.map +1 -0
- package/dist/components/{chat-typing.js → shell/chat-typing.js} +4 -3
- package/dist/components/shell/chat-typing.js.map +1 -0
- package/dist/components/{footer.js → shell/footer.js} +27 -25
- package/dist/components/shell/footer.js.map +1 -0
- package/dist/components/{header-controls.js → shell/header-controls.js} +25 -23
- package/dist/components/shell/header-controls.js.map +1 -0
- package/dist/components/shell/hotbar.js +158 -0
- package/dist/components/shell/hotbar.js.map +1 -0
- package/dist/components/{list-rows.js → shell/list-rows.js} +1 -1
- package/dist/components/shell/list-rows.js.map +1 -0
- package/dist/components/{logo.js → shell/logo.js} +4 -3
- package/dist/components/shell/logo.js.map +1 -0
- package/dist/components/{mobile-app-bar.js → shell/mobile-app-bar.js} +5 -5
- package/dist/components/shell/mobile-app-bar.js.map +1 -0
- package/dist/components/{nav-badge.js → shell/nav-badge.js} +1 -1
- package/dist/components/shell/nav-badge.js.map +1 -0
- package/dist/components/{nav-collapse.js → shell/nav-collapse.js} +8 -7
- package/dist/components/shell/nav-collapse.js.map +1 -0
- package/dist/components/shell/nav-link.js.map +1 -0
- package/dist/components/shell/nav-model.js.map +1 -0
- package/dist/components/{page-frame.js → shell/page-frame.js} +2 -2
- package/dist/components/shell/page-frame.js.map +1 -0
- package/dist/components/{resource-error.js → shell/resource-error.js} +5 -5
- package/dist/components/shell/resource-error.js.map +1 -0
- package/dist/components/{section-nav.js → shell/section-nav.js} +4 -4
- package/dist/components/shell/section-nav.js.map +1 -0
- package/dist/components/shell/settled.js.map +1 -0
- package/dist/components/shell/shell-icons.js +42 -0
- package/dist/components/shell/shell-icons.js.map +1 -0
- package/dist/components/{shell-nav.js → shell/shell-nav.js} +5 -5
- package/dist/components/shell/shell-nav.js.map +1 -0
- package/dist/components/{smart-header.js → shell/smart-header.js} +2 -2
- package/dist/components/shell/smart-header.js.map +1 -0
- package/dist/components/shell/status-screen.js +145 -0
- package/dist/components/shell/status-screen.js.map +1 -0
- package/dist/components/{system-banner.js → shell/system-banner.js} +8 -8
- package/dist/components/shell/system-banner.js.map +1 -0
- package/dist/components/{top-bar.js → shell/top-bar.js} +2 -2
- package/dist/components/shell/top-bar.js.map +1 -0
- package/dist/components/shell/use-shell-nav.js.map +1 -0
- package/dist/components/{workspace-tab.js → shell/workspace-tab.js} +6 -5
- package/dist/components/shell/workspace-tab.js.map +1 -0
- package/dist/generated/accent.js +10 -10
- package/dist/generated/accent.js.map +1 -1
- package/dist/generated/accordion.js +6 -2
- package/dist/generated/accordion.js.map +1 -1
- package/dist/generated/account-list.js +4 -4
- package/dist/generated/account-list.js.map +1 -1
- package/dist/generated/account-settings-dialog.js +6 -2
- package/dist/generated/account-settings-dialog.js.map +1 -1
- package/dist/generated/alert-dialog.js +1 -1
- package/dist/generated/alert-dialog.js.map +1 -1
- package/dist/generated/alert.js +3 -10
- package/dist/generated/alert.js.map +1 -1
- package/dist/generated/aside.js +7 -0
- package/dist/generated/aside.js.map +1 -1
- package/dist/generated/badge.js +2 -11
- package/dist/generated/badge.js.map +1 -1
- package/dist/generated/band.js +10 -10
- package/dist/generated/band.js.map +1 -1
- package/dist/generated/breadcrumb.js +1 -1
- package/dist/generated/breadcrumb.js.map +1 -1
- package/dist/generated/button-group.js +3 -3
- package/dist/generated/button-group.js.map +1 -1
- package/dist/generated/button.js +4 -20
- package/dist/generated/button.js.map +1 -1
- package/dist/generated/calendar.js +5 -5
- package/dist/generated/calendar.js.map +1 -1
- package/dist/generated/card.js +1 -1
- package/dist/generated/card.js.map +1 -1
- package/dist/generated/carousel.js +1 -1
- package/dist/generated/carousel.js.map +1 -1
- package/dist/generated/chat-composer.js +9 -2
- package/dist/generated/chat-composer.js.map +1 -1
- package/dist/generated/chat-message.js +25 -19
- package/dist/generated/chat-message.js.map +1 -1
- package/dist/generated/checkbox.js +1 -1
- package/dist/generated/checkbox.js.map +1 -1
- package/dist/generated/command-palette.js +10 -1
- package/dist/generated/command-palette.js.map +1 -1
- package/dist/generated/command.js +8 -6
- package/dist/generated/command.js.map +1 -1
- package/dist/generated/confirm-dialog.js +8 -8
- package/dist/generated/confirm-dialog.js.map +1 -1
- package/dist/generated/context-menu.js +7 -5
- package/dist/generated/context-menu.js.map +1 -1
- package/dist/generated/copy.js +97 -0
- package/dist/generated/copy.js.map +1 -0
- package/dist/generated/date-time-picker.js +10 -0
- package/dist/generated/date-time-picker.js.map +1 -1
- package/dist/generated/dialog.js +2 -2
- package/dist/generated/dialog.js.map +1 -1
- package/dist/generated/drawer.js +6 -6
- package/dist/generated/drawer.js.map +1 -1
- package/dist/generated/dropdown-menu.js +7 -5
- package/dist/generated/dropdown-menu.js.map +1 -1
- package/dist/generated/empty.js +5 -5
- package/dist/generated/empty.js.map +1 -1
- package/dist/generated/field.js +9 -7
- package/dist/generated/field.js.map +1 -1
- package/dist/generated/footer.js +45 -0
- package/dist/generated/footer.js.map +1 -0
- package/dist/generated/header-controls.js +5 -10
- package/dist/generated/header-controls.js.map +1 -1
- package/dist/generated/hover-card.js +1 -1
- package/dist/generated/hover-card.js.map +1 -1
- package/dist/generated/icon-button.js +4 -2
- package/dist/generated/icon-button.js.map +1 -1
- package/dist/generated/icons.js +36 -0
- package/dist/generated/icons.js.map +1 -0
- package/dist/generated/info-tip.js +5 -0
- package/dist/generated/info-tip.js.map +1 -0
- package/dist/generated/input-group.js +10 -10
- package/dist/generated/input-group.js.map +1 -1
- package/dist/generated/input-otp.js +2 -2
- package/dist/generated/input-otp.js.map +1 -1
- package/dist/generated/input.js +4 -4
- package/dist/generated/input.js.map +1 -1
- package/dist/generated/item.js +11 -11
- package/dist/generated/item.js.map +1 -1
- package/dist/generated/kbd.js +1 -1
- package/dist/generated/kbd.js.map +1 -1
- package/dist/generated/key-value.js +7 -1
- package/dist/generated/key-value.js.map +1 -1
- package/dist/generated/label.js +1 -1
- package/dist/generated/label.js.map +1 -1
- package/dist/generated/logo.js +9 -0
- package/dist/generated/logo.js.map +1 -0
- package/dist/generated/menu.js +7 -0
- package/dist/generated/menu.js.map +1 -0
- package/dist/generated/menubar.js +10 -8
- package/dist/generated/menubar.js.map +1 -1
- package/dist/generated/navigation-menu.js +11 -5
- package/dist/generated/navigation-menu.js.map +1 -1
- package/dist/generated/orientation.js +5 -0
- package/dist/generated/orientation.js.map +1 -0
- package/dist/generated/pagination.js +15 -0
- package/dist/generated/pagination.js.map +1 -0
- package/dist/generated/popover-form.js +5 -0
- package/dist/generated/popover-form.js.map +1 -1
- package/dist/generated/popover.js +1 -1
- package/dist/generated/popover.js.map +1 -1
- package/dist/generated/primitives.js +7 -0
- package/dist/generated/primitives.js.map +1 -0
- package/dist/generated/radio-group.js +5 -1
- package/dist/generated/radio-group.js.map +1 -1
- package/dist/generated/section-descriptor.js +7 -0
- package/dist/generated/section-descriptor.js.map +1 -0
- package/dist/generated/select.js +16 -10
- package/dist/generated/select.js.map +1 -1
- package/dist/generated/settings.js +2 -7
- package/dist/generated/settings.js.map +1 -1
- package/dist/generated/sheet.js +1 -1
- package/dist/generated/sheet.js.map +1 -1
- package/dist/generated/sidebar.js +24 -12
- package/dist/generated/sidebar.js.map +1 -1
- package/dist/generated/size.js +12 -0
- package/dist/generated/size.js.map +1 -0
- package/dist/generated/skeleton.js +1 -1
- package/dist/generated/skeleton.js.map +1 -1
- package/dist/generated/slider.js +2 -2
- package/dist/generated/slider.js.map +1 -1
- package/dist/generated/slot.js +5 -0
- package/dist/generated/slot.js.map +1 -0
- package/dist/generated/smart-header.js +2 -0
- package/dist/generated/smart-header.js.map +1 -1
- package/dist/generated/sonner.js +11 -13
- package/dist/generated/sonner.js.map +1 -1
- package/dist/generated/spinner.js +5 -0
- package/dist/generated/spinner.js.map +1 -0
- package/dist/generated/status-screen.js +27 -0
- package/dist/generated/status-screen.js.map +1 -0
- package/dist/generated/switch.js +2 -2
- package/dist/generated/switch.js.map +1 -1
- package/dist/generated/system-banner.js +6 -16
- package/dist/generated/system-banner.js.map +1 -1
- package/dist/generated/table.js +9 -9
- package/dist/generated/table.js.map +1 -1
- package/dist/generated/tabs.js +2 -2
- package/dist/generated/tabs.js.map +1 -1
- package/dist/generated/textarea.js +1 -1
- package/dist/generated/textarea.js.map +1 -1
- package/dist/generated/toggle-group.js +9 -0
- package/dist/generated/toggle-group.js.map +1 -0
- package/dist/generated/toggle.js +1 -9
- package/dist/generated/toggle.js.map +1 -1
- package/dist/generated/tone.js +12 -0
- package/dist/generated/tone.js.map +1 -0
- package/dist/generated/tooltip.js +1 -1
- package/dist/generated/tooltip.js.map +1 -1
- package/dist/generated/workspace-tab.js +3 -3
- package/dist/generated/workspace-tab.js.map +1 -1
- package/dist/icons/icon-shapes.js +10 -0
- package/dist/icons/icon-shapes.js.map +1 -0
- package/dist/{components → icons}/select-chevron.js +2 -1
- package/dist/icons/select-chevron.js.map +1 -0
- package/dist/icons/ui-icons.js +23 -0
- package/dist/icons/ui-icons.js.map +1 -0
- package/dist/index.d.ts +203 -155
- package/dist/index.js +97 -96
- package/dist/lib/cn.js +1 -0
- package/dist/lib/cn.js.map +1 -1
- package/dist/primitives/use-floating.js.map +1 -1
- package/dist/primitives/use-roving-focus.js.map +1 -1
- package/package.json +2 -2
- package/styles/ev.css +13 -76
- package/styles/theme.css +133 -66
- package/styles/tokens.css +157 -149
- package/dist/components/accordion.js.map +0 -1
- package/dist/components/account-list.js.map +0 -1
- package/dist/components/account-menu-profile.js.map +0 -1
- package/dist/components/account-menu.js.map +0 -1
- package/dist/components/account-settings-dialog.js.map +0 -1
- package/dist/components/alert-dialog.js.map +0 -1
- package/dist/components/alert.js.map +0 -1
- package/dist/components/animated-number-columns.js.map +0 -1
- package/dist/components/animated-number.js.map +0 -1
- package/dist/components/app-shell.js.map +0 -1
- package/dist/components/aside.js.map +0 -1
- package/dist/components/auth-wall.js.map +0 -1
- package/dist/components/avatar.js.map +0 -1
- package/dist/components/badge.js +0 -25
- package/dist/components/badge.js.map +0 -1
- package/dist/components/band.js.map +0 -1
- package/dist/components/bottom-tab-bar.js.map +0 -1
- package/dist/components/breadcrumb.js.map +0 -1
- package/dist/components/button-group.js.map +0 -1
- package/dist/components/button.js.map +0 -1
- package/dist/components/calendar.js.map +0 -1
- package/dist/components/card.js.map +0 -1
- package/dist/components/carousel.js.map +0 -1
- package/dist/components/chat-composer.js.map +0 -1
- package/dist/components/chat-message.js.map +0 -1
- package/dist/components/chat-panel.js.map +0 -1
- package/dist/components/chat-stream-text.js.map +0 -1
- package/dist/components/chat-typing.js.map +0 -1
- package/dist/components/checkbox.js.map +0 -1
- package/dist/components/collapsible.js.map +0 -1
- package/dist/components/command-palette.js.map +0 -1
- package/dist/components/command.js.map +0 -1
- package/dist/components/confirm-dialog.js.map +0 -1
- package/dist/components/container.js.map +0 -1
- package/dist/components/context-menu.js.map +0 -1
- package/dist/components/date-time-picker.js.map +0 -1
- package/dist/components/dialog.js.map +0 -1
- package/dist/components/drawer.js.map +0 -1
- package/dist/components/dropdown-menu.js.map +0 -1
- package/dist/components/empty.js.map +0 -1
- package/dist/components/field-context.js.map +0 -1
- package/dist/components/field.js.map +0 -1
- package/dist/components/footer.js.map +0 -1
- package/dist/components/form-row.js.map +0 -1
- package/dist/components/form.js.map +0 -1
- package/dist/components/header-controls.js.map +0 -1
- package/dist/components/hover-card.js.map +0 -1
- package/dist/components/icon-button.js.map +0 -1
- package/dist/components/info-tip.js.map +0 -1
- package/dist/components/input-group.js.map +0 -1
- package/dist/components/input-otp.js.map +0 -1
- package/dist/components/input.js.map +0 -1
- package/dist/components/item.js.map +0 -1
- package/dist/components/kbd.js.map +0 -1
- package/dist/components/key-value.js.map +0 -1
- package/dist/components/label.js.map +0 -1
- package/dist/components/list-rows.js.map +0 -1
- package/dist/components/logo.js.map +0 -1
- package/dist/components/menubar.js.map +0 -1
- package/dist/components/mobile-app-bar.js.map +0 -1
- package/dist/components/native-select.js.map +0 -1
- package/dist/components/nav-badge.js.map +0 -1
- package/dist/components/nav-collapse.js.map +0 -1
- package/dist/components/nav-link.js.map +0 -1
- package/dist/components/nav-model.js.map +0 -1
- package/dist/components/navigation-menu.js.map +0 -1
- package/dist/components/page-frame.js.map +0 -1
- package/dist/components/pagination.js.map +0 -1
- package/dist/components/popover-form.js.map +0 -1
- package/dist/components/popover.js.map +0 -1
- package/dist/components/progress.js.map +0 -1
- package/dist/components/radio-group.js.map +0 -1
- package/dist/components/resource-error.js.map +0 -1
- package/dist/components/scroll-area.js.map +0 -1
- package/dist/components/section-descriptor.js.map +0 -1
- package/dist/components/section-nav.js.map +0 -1
- package/dist/components/select-chevron.js.map +0 -1
- package/dist/components/select-listbox.js.map +0 -1
- package/dist/components/select.js.map +0 -1
- package/dist/components/separator.js.map +0 -1
- package/dist/components/settings.js.map +0 -1
- package/dist/components/settled.js.map +0 -1
- package/dist/components/sheet.js.map +0 -1
- package/dist/components/shell-icons.js +0 -57
- package/dist/components/shell-icons.js.map +0 -1
- package/dist/components/shell-nav.js.map +0 -1
- package/dist/components/sidebar.js.map +0 -1
- package/dist/components/skeleton.js.map +0 -1
- package/dist/components/slider.js.map +0 -1
- package/dist/components/smart-header.js.map +0 -1
- package/dist/components/sonner.js.map +0 -1
- package/dist/components/spinner.js +0 -23
- package/dist/components/spinner.js.map +0 -1
- package/dist/components/status-item.js.map +0 -1
- package/dist/components/status-screen.js +0 -145
- package/dist/components/status-screen.js.map +0 -1
- package/dist/components/switch.js.map +0 -1
- package/dist/components/system-banner.js.map +0 -1
- package/dist/components/table.js.map +0 -1
- package/dist/components/tabs.js.map +0 -1
- package/dist/components/textarea.js.map +0 -1
- package/dist/components/toggle-group.js.map +0 -1
- package/dist/components/toggle.js.map +0 -1
- package/dist/components/tooltip.js.map +0 -1
- package/dist/components/top-bar.js.map +0 -1
- package/dist/components/ui-icons.js +0 -77
- package/dist/components/ui-icons.js.map +0 -1
- package/dist/components/use-count-tween.js.map +0 -1
- package/dist/components/use-shell-nav.js.map +0 -1
- package/dist/components/workspace-tab.js.map +0 -1
- /package/dist/components/{field-context.js → atomic/field-context.js} +0 -0
- /package/dist/components/{chat-stream-text.js → shell/chat-stream-text.js} +0 -0
- /package/dist/components/{nav-link.js → shell/nav-link.js} +0 -0
- /package/dist/components/{nav-model.js → shell/nav-model.js} +0 -0
- /package/dist/components/{settled.js → shell/settled.js} +0 -0
- /package/dist/components/{use-shell-nav.js → shell/use-shell-nav.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { cn } from "
|
|
4
|
-
import { SECTION_LABEL_BASE, sectionLabelToneClasses } from "
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
import { SECTION_LABEL_BASE, sectionLabelToneClasses } from "../../generated/section-label.js";
|
|
5
5
|
function SectionLabel({ as: Comp = "p", tone = "muted", className, ...props }) {
|
|
6
6
|
return /* @__PURE__ */ jsx(
|
|
7
7
|
Comp,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/page-frame.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { SECTION_LABEL_BASE, sectionLabelToneClasses, type SectionLabelTone } from \"../../generated/section-label\";\nimport type { ShellBreakpoint } from \"./app-shell\";\n\nexport type { SectionLabelTone };\n\nexport interface SectionLabelProps extends React.HTMLAttributes<HTMLElement> {\n as?: React.ElementType;\n /** `muted` labels a group or a section; `accent` announces a hero figure. */\n tone?: SectionLabelTone;\n}\n\n/** The tracked-uppercase label above a figure, a group or a section. */\nexport function SectionLabel({ as: Comp = \"p\", tone = \"muted\", className, ...props }: SectionLabelProps) {\n return (\n <Comp\n data-slot=\"section-label\"\n className={cn(SECTION_LABEL_BASE, sectionLabelToneClasses[tone], className)}\n {...props}\n />\n );\n}\n\nexport interface PageHeadingProps extends Omit<React.ComponentProps<\"header\">, \"title\"> {\n title: React.ReactNode;\n /** What the screen is for, in a sentence. */\n description?: React.ReactNode;\n eyebrow?: React.ReactNode;\n /** The screen's own controls, on the right. */\n actions?: React.ReactNode;\n}\n\n/** The title row: eyebrow → title → description on the left, actions on the right. */\nexport function PageHeading({ title, description, eyebrow, actions, className, ...props }: PageHeadingProps) {\n return (\n <header\n data-slot=\"page-heading\"\n className={cn(\"flex items-center justify-between gap-4\", className)}\n {...props}\n >\n <div className=\"flex min-w-0 flex-col gap-1\">\n {eyebrow !== undefined && <SectionLabel tone=\"accent\">{eyebrow}</SectionLabel>}\n <h1 className=\"text-2xl font-semibold leading-tight text-ink\">{title}</h1>\n {description !== undefined && <p className=\"text-sm text-ink-soft\">{description}</p>}\n </div>\n {actions !== undefined && <div className=\"flex shrink-0 items-center gap-2.5\">{actions}</div>}\n </header>\n );\n}\n\nexport type PageFrameWidth = \"full\" | \"content\";\n\nexport interface PageFrameProps extends Omit<React.ComponentProps<\"div\">, \"title\"> {\n /** Omit when the screen's heading is its own composition. */\n title?: React.ReactNode;\n description?: React.ReactNode;\n eyebrow?: React.ReactNode;\n actions?: React.ReactNode;\n /**\n * The bar titling the screen on a phone (`MobileAppBar`). With one, the heading\n * shows from `breakpoint` up only and the sections arrive a step after the bar.\n */\n appBar?: React.ReactNode;\n /** Default `lg`. */\n breakpoint?: ShellBreakpoint;\n /** `full` fills the column (the rail already bounds it); `content` caps it at a reading measure. */\n width?: PageFrameWidth;\n headingClassName?: string;\n}\n\nconst HEADING_FROM = { md: \"hidden md:flex\", lg: \"hidden lg:flex\" } as const;\nconst PAD = {\n md: \"gap-4 px-4 pb-6 pt-5 md:gap-6 md:px-8 md:pb-7 md:pt-6\",\n lg: \"gap-4 px-4 pb-6 pt-5 lg:gap-6 lg:px-8 lg:pb-7 lg:pt-6\",\n} as const;\n\n/**\n * The frame every screen sits in: one inset, one section rhythm, one title scale,\n * so moving between screens never reads as moving between products.\n *\n * Its sections arrive in sequence by CSS alone (`data-enter=\"stagger\"`, see\n * motion.css): every direct child fades and rises `--ev-rise`, one\n * `--ev-stagger-section` after the previous, the heading first. Server-safe —\n * no motion library, no hydration needed for the entrance.\n */\nexport function PageFrame({\n title,\n description,\n eyebrow,\n actions,\n appBar,\n breakpoint = \"lg\",\n width = \"full\",\n headingClassName,\n className,\n style,\n children,\n ...props\n}: PageFrameProps) {\n const hasBar = appBar !== undefined && appBar !== null && appBar !== false;\n const enter = {\n \"--enter-step\": \"var(--ev-stagger-section, 50ms)\",\n ...(hasBar ? { \"--enter-delay\": \"var(--ev-stagger-section, 50ms)\" } : {}),\n };\n return (\n <>\n {appBar}\n <div\n data-slot=\"page-frame\"\n data-enter=\"stagger\"\n className={cn(\"flex flex-col\", PAD[breakpoint], width === \"content\" && \"max-w-5xl\", className)}\n style={{ ...enter, ...style }}\n {...props}\n >\n {title !== undefined && (\n <PageHeading\n title={title}\n description={description}\n eyebrow={eyebrow}\n actions={actions}\n className={cn(hasBar && HEADING_FROM[breakpoint], headingClassName)}\n />\n )}\n {children}\n </div>\n </>\n );\n}\n"],"mappings":"AAgBI,SA0FA,UA1FA,KAyBE,YAzBF;AAhBJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,oBAAoB,+BAAsD;AAY5E,SAAS,aAAa,EAAE,IAAI,OAAO,KAAK,OAAO,SAAS,WAAW,GAAG,MAAM,GAAsB;AACvG,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,oBAAoB,wBAAwB,IAAI,GAAG,SAAS;AAAA,MACzE,GAAG;AAAA;AAAA,EACN;AAEJ;AAYO,SAAS,YAAY,EAAE,OAAO,aAAa,SAAS,SAAS,WAAW,GAAG,MAAM,GAAqB;AAC3G,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,2CAA2C,SAAS;AAAA,MACjE,GAAG;AAAA,MAEJ;AAAA,6BAAC,SAAI,WAAU,+BACZ;AAAA,sBAAY,UAAa,oBAAC,gBAAa,MAAK,UAAU,mBAAQ;AAAA,UAC/D,oBAAC,QAAG,WAAU,iDAAiD,iBAAM;AAAA,UACpE,gBAAgB,UAAa,oBAAC,OAAE,WAAU,yBAAyB,uBAAY;AAAA,WAClF;AAAA,QACC,YAAY,UAAa,oBAAC,SAAI,WAAU,sCAAsC,mBAAQ;AAAA;AAAA;AAAA,EACzF;AAEJ;AAsBA,MAAM,eAAe,EAAE,IAAI,kBAAkB,IAAI,iBAAiB;AAClE,MAAM,MAAM;AAAA,EACV,IAAI;AAAA,EACJ,IAAI;AACN;AAWO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAmB;AACjB,QAAM,SAAS,WAAW,UAAa,WAAW,QAAQ,WAAW;AACrE,QAAM,QAAQ;AAAA,IACZ,gBAAgB;AAAA,IAChB,GAAI,SAAS,EAAE,iBAAiB,kCAAkC,IAAI,CAAC;AAAA,EACzE;AACA,SACE,iCACG;AAAA;AAAA,IACD;AAAA,MAAC;AAAA;AAAA,QACC,aAAU;AAAA,QACV,cAAW;AAAA,QACX,WAAW,GAAG,iBAAiB,IAAI,UAAU,GAAG,UAAU,aAAa,aAAa,SAAS;AAAA,QAC7F,OAAO,EAAE,GAAG,OAAO,GAAG,MAAM;AAAA,QAC3B,GAAG;AAAA,QAEH;AAAA,oBAAU,UACT;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,WAAW,GAAG,UAAU,aAAa,UAAU,GAAG,gBAAgB;AAAA;AAAA,UACpE;AAAA,UAED;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { cn } from "
|
|
5
|
-
import { Alert, AlertDescription, AlertTitle } from "
|
|
6
|
-
import { Button } from "
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { Alert, AlertDescription, AlertTitle } from "../atomic/alert.js";
|
|
6
|
+
import { Button } from "../atomic/button.js";
|
|
7
7
|
import { RefreshIcon, TriangleAlertIcon } from "./shell-icons.js";
|
|
8
8
|
function ResourceError(props) {
|
|
9
9
|
if (props.variant === "alert") {
|
|
10
10
|
const { message: message2, title, labels: _labels, variant: _variant2, className: className2, ...rest2 } = props;
|
|
11
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "resource-error", "data-variant": "alert", className: className2, ...rest2, children: /* @__PURE__ */ jsxs(Alert, {
|
|
11
|
+
return /* @__PURE__ */ jsx("div", { "data-slot": "resource-error", "data-variant": "alert", className: className2, ...rest2, children: /* @__PURE__ */ jsxs(Alert, { tone: "error", children: [
|
|
12
12
|
/* @__PURE__ */ jsx(TriangleAlertIcon, { className: "size-4" }),
|
|
13
13
|
title !== void 0 && /* @__PURE__ */ jsx(AlertTitle, { children: title }),
|
|
14
14
|
/* @__PURE__ */ jsx(AlertDescription, { children: message2 })
|
|
@@ -27,7 +27,7 @@ function ResourceError(props) {
|
|
|
27
27
|
"data-variant": "inline",
|
|
28
28
|
role: "alert",
|
|
29
29
|
className: cn(
|
|
30
|
-
onRetry && "flex flex-wrap items-center gap-3 rounded-
|
|
30
|
+
onRetry && "flex flex-wrap items-center gap-3 rounded-panel border border-tint-error-edge bg-accent-error/(--tint-hover) px-3 py-2.5",
|
|
31
31
|
className
|
|
32
32
|
),
|
|
33
33
|
...rest,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/resource-error.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Alert, AlertDescription, AlertTitle } from \"../atomic/alert\";\nimport { Button } from \"../atomic/button\";\nimport { RefreshIcon, TriangleAlertIcon } from \"./shell-icons\";\n\nexport interface ResourceErrorLabels {\n /** The retry button. Default `\"Try again\"`. */\n retry?: string;\n}\n\ninterface ResourceErrorBase extends Omit<React.ComponentProps<\"div\">, \"title\" | \"children\"> {\n /** What failed, already in the reader's words — the kit formats no errors. */\n message: React.ReactNode;\n labels?: ResourceErrorLabels;\n}\n\n// The two forms take different props and the union says so: an `alert` has no\n// retry and an `inline` line has no heading, so asking for either is a type\n// error rather than a prop that silently does nothing.\nexport type ResourceErrorProps = ResourceErrorBase &\n (\n | {\n /** One line under the page header — for dense screens where a block would push everything down. */\n variant?: \"inline\";\n title?: never;\n /** Re-run the read; boxes the line so the button and the message read as one thing. */\n onRetry?: () => void;\n /** The retry is in flight: the button is disabled and its icon spins. */\n retrying?: boolean;\n }\n | {\n /** The kit's `Alert` with a heading — for screens that address the reader. */\n variant: \"alert\";\n title?: React.ReactNode;\n onRetry?: never;\n retrying?: never;\n }\n );\n\n/**\n * What a screen shows when a read it needed never arrived. Whether there is\n * anything to report stays with the caller — only it knows whether stale data is\n * still on screen, and a failed refresh over figures the reader can see belongs\n * beside them, not in place of them.\n */\nexport function ResourceError(props: ResourceErrorProps) {\n if (props.variant === \"alert\") {\n const { message, title, labels: _labels, variant: _variant, className, ...rest } = props;\n return (\n <div data-slot=\"resource-error\" data-variant=\"alert\" className={className} {...rest}>\n <Alert tone=\"error\">\n <TriangleAlertIcon className=\"size-4\" />\n {title !== undefined && <AlertTitle>{title}</AlertTitle>}\n <AlertDescription>{message}</AlertDescription>\n </Alert>\n </div>\n );\n }\n const { message, onRetry, retrying = false, labels = {}, variant: _variant, title: _title, className, ...rest } = props;\n const line = (\n <p className=\"flex min-w-0 items-center gap-2 text-sm text-accent-error\">\n {/* Holds its size: beside the button it is the first thing squeezed, and a\n half-width triangle reads as a rendering fault. */}\n <TriangleAlertIcon className=\"size-4 shrink-0\" /> {message}\n </p>\n );\n return (\n <div\n data-slot=\"resource-error\"\n data-variant=\"inline\"\n role=\"alert\"\n className={cn(\n onRetry &&\n \"flex flex-wrap items-center gap-3 rounded-panel border border-tint-error-edge bg-accent-error/(--tint-hover) px-3 py-2.5\",\n className,\n )}\n {...rest}\n >\n {line}\n {onRetry && (\n <Button type=\"button\" variant=\"outline\" size=\"xs\" disabled={retrying} onClick={onRetry}>\n <RefreshIcon className={cn(\"size-4\", retrying && \"motion-safe:animate-spin\")} />\n {labels.retry ?? \"Try again\"}\n </Button>\n )}\n </div>\n );\n}\n"],"mappings":";AAqDQ,SACE,KADF;AAnDR,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,OAAO,kBAAkB,kBAAkB;AACpD,SAAS,cAAc;AACvB,SAAS,aAAa,yBAAyB;AA0CxC,SAAS,cAAc,OAA2B;AACvD,MAAI,MAAM,YAAY,SAAS;AAC7B,UAAM,EAAE,SAAAA,UAAS,OAAO,QAAQ,SAAS,SAASC,WAAU,WAAAC,YAAW,GAAGC,MAAK,IAAI;AACnF,WACE,oBAAC,SAAI,aAAU,kBAAiB,gBAAa,SAAQ,WAAWD,YAAY,GAAGC,OAC7E,+BAAC,SAAM,MAAK,SACV;AAAA,0BAAC,qBAAkB,WAAU,UAAS;AAAA,MACrC,UAAU,UAAa,oBAAC,cAAY,iBAAM;AAAA,MAC3C,oBAAC,oBAAkB,UAAAH,UAAQ;AAAA,OAC7B,GACF;AAAA,EAEJ;AACA,QAAM,EAAE,SAAS,SAAS,WAAW,OAAO,SAAS,CAAC,GAAG,SAAS,UAAU,OAAO,QAAQ,WAAW,GAAG,KAAK,IAAI;AAClH,QAAM,OACJ,qBAAC,OAAE,WAAU,6DAGX;AAAA,wBAAC,qBAAkB,WAAU,mBAAkB;AAAA,IAAE;AAAA,IAAE;AAAA,KACrD;AAEF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,gBAAa;AAAA,MACb,MAAK;AAAA,MACL,WAAW;AAAA,QACT,WACE;AAAA,QACF;AAAA,MACF;AAAA,MACC,GAAG;AAAA,MAEH;AAAA;AAAA,QACA,WACC,qBAAC,UAAO,MAAK,UAAS,SAAQ,WAAU,MAAK,MAAK,UAAU,UAAU,SAAS,SAC7E;AAAA,8BAAC,eAAY,WAAW,GAAG,UAAU,YAAY,0BAA0B,GAAG;AAAA,UAC7E,OAAO,SAAS;AAAA,WACnB;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":["message","_variant","className","rest"]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { cn } from "
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
5
|
import {
|
|
6
6
|
NavCollapse,
|
|
7
7
|
NavGroupHeader,
|
|
8
8
|
useNavGroupOpen
|
|
9
9
|
} from "./nav-collapse.js";
|
|
10
10
|
import { SectionLabel } from "./page-frame.js";
|
|
11
|
-
const ITEM = "flex h-
|
|
11
|
+
const ITEM = "flex h-(--control-h-sm) w-full items-center gap-2.5 rounded-row px-2.5 text-left text-body outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-(--disabled-opacity)";
|
|
12
12
|
function SectionNav({
|
|
13
13
|
groups,
|
|
14
14
|
value,
|
|
@@ -100,8 +100,8 @@ function SectionNavRow({
|
|
|
100
100
|
const Icon = item.icon;
|
|
101
101
|
const className = cn(
|
|
102
102
|
ITEM,
|
|
103
|
-
active ? "bg-
|
|
104
|
-
nested && "h-
|
|
103
|
+
active ? "bg-selected text-ink" : "text-ink-mid hover:bg-hover",
|
|
104
|
+
nested && "h-(--control-h-md)"
|
|
105
105
|
);
|
|
106
106
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
107
107
|
Icon && /* @__PURE__ */ jsx(Icon, { className: "size-4 shrink-0 text-ink-soft" }),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/section-nav.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n NavCollapse,\n NavGroupHeader,\n useNavGroupOpen,\n type NavCollapseLabels,\n type NavGroupCollapse,\n} from \"./nav-collapse\";\nimport { SectionLabel } from \"./page-frame\";\n\nexport interface SectionNavItem {\n id: string;\n label: React.ReactNode;\n icon?: React.ComponentType<{ className?: string }>;\n /** A link (`?section=…`, a sub-route) instead of a button calling `onValueChange`. */\n href?: string;\n /** After the label — a count, a status chip. */\n trailing?: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface SectionNavGroup extends NavGroupCollapse {\n id: string;\n label?: React.ReactNode;\n /** One line under the label saying what kind of thing lives here. */\n description?: React.ReactNode;\n items: readonly SectionNavItem[];\n}\n\nexport interface SectionNavLabels extends NavCollapseLabels {\n /** Accessible name of the nav. Default `\"Sections\"`. */\n nav?: string;\n}\n\nexport interface SectionNavProps extends Omit<React.ComponentProps<\"nav\">, \"children\"> {\n groups: readonly SectionNavGroup[];\n /** The current section's id. */\n value: string;\n /** Called by button items (those without `href`), and by link items on click. */\n onValueChange?: (id: string) => void;\n linkComponent?: React.ElementType;\n labels?: SectionNavLabels;\n /** Makes every labelled group collapsible; a group's own `collapsible` wins. Default `false`. */\n collapsible?: boolean;\n}\n\nconst ITEM =\n \"flex h-(--control-h-sm) w-full items-center gap-2.5 rounded-row px-2.5 text-left text-body outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-(--disabled-opacity)\";\n\n/**\n * A screen's own section rail — settings panes, a document's chapters: grouped\n * rows, one current (`aria-current`), each a button or a link. The shell's rail\n * is `ShellNav`; this one lives inside a page, so it carries a tint rather than\n * the rail's solid marker and does not slide.\n */\nexport function SectionNav({\n groups,\n value,\n onValueChange,\n linkComponent,\n labels = {},\n collapsible = false,\n className,\n ...props\n}: SectionNavProps) {\n return (\n <nav\n data-slot=\"section-nav\"\n aria-label={labels.nav ?? \"Sections\"}\n className={cn(\"flex w-64 shrink-0 flex-col gap-0.5\", className)}\n {...props}\n >\n {groups.map((group) => (\n <SectionNavGroupView\n key={group.id}\n group={group}\n value={value}\n onSelect={onValueChange}\n linkComponent={linkComponent}\n labels={labels}\n collapsible={collapsible}\n />\n ))}\n </nav>\n );\n}\n\nfunction SectionNavGroupView({\n group,\n value,\n onSelect,\n linkComponent,\n labels,\n collapsible,\n}: {\n group: SectionNavGroup;\n value: string;\n onSelect: ((id: string) => void) | undefined;\n linkComponent: React.ElementType | undefined;\n labels: SectionNavLabels;\n collapsible: boolean;\n}) {\n const labelId = React.useId();\n const regionId = React.useId();\n const [open, setOpen] = useNavGroupOpen(group, group.items.some((i) => i.id === value));\n const folds = (group.collapsible ?? collapsible) && group.label !== undefined;\n const rows = group.items.map((item) => (\n <SectionNavRow\n key={item.id}\n item={item}\n active={item.id === value}\n nested={folds}\n onSelect={onSelect}\n linkComponent={linkComponent}\n />\n ));\n if (folds) {\n return (\n <div className=\"flex flex-col pt-1.5 first:pt-0\">\n <NavGroupHeader\n label={group.label}\n labelId={labelId}\n regionId={regionId}\n open={open}\n onToggle={() => setOpen(!open)}\n href={group.href}\n linkComponent={linkComponent}\n labels={labels}\n />\n <NavCollapse open={open} id={regionId}>\n <div className=\"flex flex-col gap-0.5 pt-0.5 pl-3\">{rows}</div>\n </NavCollapse>\n </div>\n );\n }\n return (\n <div className=\"flex flex-col gap-0.5 pt-3.5 first:pt-0\">\n {(group.label !== undefined || group.description !== undefined) && (\n <div className=\"flex flex-col\">\n {group.label !== undefined && <SectionLabel className=\"px-2 py-1\">{group.label}</SectionLabel>}\n {group.description !== undefined && (\n <p className=\"px-2 text-caption text-ink-soft\">{group.description}</p>\n )}\n </div>\n )}\n {rows}\n </div>\n );\n}\n\nfunction SectionNavRow({\n item,\n active,\n nested,\n onSelect,\n linkComponent,\n}: {\n item: SectionNavItem;\n active: boolean;\n nested: boolean;\n onSelect: ((id: string) => void) | undefined;\n linkComponent: React.ElementType | undefined;\n}) {\n const Icon = item.icon;\n const className = cn(\n ITEM,\n active ? \"bg-selected text-ink\" : \"text-ink-mid hover:bg-hover\",\n nested && \"h-(--control-h-md)\",\n );\n const content = (\n <>\n {Icon && <Icon className=\"size-4 shrink-0 text-ink-soft\" />}\n <span className=\"min-w-0 flex-1 truncate\">{item.label}</span>\n {item.trailing}\n </>\n );\n if (item.href !== undefined && !item.disabled) {\n const Link = linkComponent ?? \"a\";\n return (\n <Link\n href={item.href}\n aria-current={active ? \"page\" : undefined}\n className={className}\n onClick={() => onSelect?.(item.id)}\n >\n {content}\n </Link>\n );\n }\n return (\n <button\n type=\"button\"\n disabled={item.disabled}\n aria-current={active ? \"true\" : undefined}\n className={className}\n onClick={() => onSelect?.(item.id)}\n >\n {content}\n </button>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/settled.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nexport interface SettledProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n /** True while the data this surface needs is in flight. */\n loading: boolean;\n /** What stands in meanwhile — a `Skeleton` or a group of them. */\n skeleton: React.ReactNode;\n /** The content; also the empty and error states, guarded on the same condition. */\n children: React.ReactNode;\n}\n\n/**\n * The skeleton → content handover. Swapped in a single frame, a skeleton reads\n * as a flicker — the eye sees that something changed, not what. Here the\n * content fades and rises the last `--ev-rise` into place\n * (`data-state=\"revealed\"`, motion.css).\n *\n * Deliberately not a cross-fade: the two would have to overlap, which means\n * taking one out of flow and animating a height, and the surface would jump\n * when the content is a different size. And no entrance when no skeleton was\n * shown — data already present on the first render cuts straight in; fading it\n * would invent a delay the data never had.\n *\n * `data-state`: `loading` → `revealed` after a skeleton, `ready` without one.\n */\nexport function Settled({ loading, skeleton, children, ...props }: SettledProps) {\n // Adjusted during render, not in an effect, so the entrance plays on the very\n // first render after `loading` drops: an effect would paint the content opaque\n // once and only then start the fade. `reveals` keys the wrapper, so a later\n // refetch that shows the skeleton again gets a handover of its own.\n const [wasLoading, setWasLoading] = React.useState(loading);\n const [reveals, setReveals] = React.useState(0);\n if (wasLoading !== loading) {\n setWasLoading(loading);\n if (wasLoading) setReveals((n) => n + 1);\n }\n if (loading) {\n return (\n <div data-slot=\"settled\" data-state=\"loading\" aria-busy=\"true\" {...props}>\n {skeleton}\n </div>\n );\n }\n return (\n <div key={reveals} data-slot=\"settled\" data-state={reveals > 0 ? \"revealed\" : \"ready\"} {...props}>\n {children}\n </div>\n );\n}\n"],"mappings":";AAwCM;AAtCN,YAAY,WAAW;AAyBhB,SAAS,QAAQ,EAAE,SAAS,UAAU,UAAU,GAAG,MAAM,GAAiB;AAK/E,QAAM,CAAC,YAAY,aAAa,IAAI,MAAM,SAAS,OAAO;AAC1D,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAS,CAAC;AAC9C,MAAI,eAAe,SAAS;AAC1B,kBAAc,OAAO;AACrB,QAAI,WAAY,YAAW,CAAC,MAAM,IAAI,CAAC;AAAA,EACzC;AACA,MAAI,SAAS;AACX,WACE,oBAAC,SAAI,aAAU,WAAU,cAAW,WAAU,aAAU,QAAQ,GAAG,OAChE,oBACH;AAAA,EAEJ;AACA,SACE,oBAAC,SAAkB,aAAU,WAAU,cAAY,UAAU,IAAI,aAAa,SAAU,GAAG,OACxF,YADO,OAEV;AAEJ;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { iconShapes } from "../../icons/icon-shapes.js";
|
|
4
|
+
function Glyph({ className, children }) {
|
|
5
|
+
return /* @__PURE__ */ jsx(
|
|
6
|
+
"svg",
|
|
7
|
+
{
|
|
8
|
+
className,
|
|
9
|
+
viewBox: "0 0 24 24",
|
|
10
|
+
fill: "none",
|
|
11
|
+
stroke: "currentColor",
|
|
12
|
+
strokeWidth: 2,
|
|
13
|
+
strokeLinecap: "round",
|
|
14
|
+
strokeLinejoin: "round",
|
|
15
|
+
"aria-hidden": true,
|
|
16
|
+
children
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
function ChevronLeftIcon({ className }) {
|
|
21
|
+
return /* @__PURE__ */ jsx(Glyph, { className, children: iconShapes("chevron-left") });
|
|
22
|
+
}
|
|
23
|
+
function TriangleAlertIcon({ className }) {
|
|
24
|
+
return /* @__PURE__ */ jsx(Glyph, { className, children: iconShapes("triangle-alert") });
|
|
25
|
+
}
|
|
26
|
+
function InfoIcon({ className }) {
|
|
27
|
+
return /* @__PURE__ */ jsx(Glyph, { className, children: iconShapes("info") });
|
|
28
|
+
}
|
|
29
|
+
function RefreshIcon({ className }) {
|
|
30
|
+
return /* @__PURE__ */ jsx(Glyph, { className, children: iconShapes("refresh") });
|
|
31
|
+
}
|
|
32
|
+
function CloseIcon({ className }) {
|
|
33
|
+
return /* @__PURE__ */ jsx(Glyph, { className, children: iconShapes("close") });
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
ChevronLeftIcon,
|
|
37
|
+
CloseIcon,
|
|
38
|
+
InfoIcon,
|
|
39
|
+
RefreshIcon,
|
|
40
|
+
TriangleAlertIcon
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=shell-icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/shell-icons.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { iconShapes } from \"../../icons/icon-shapes\";\n\nfunction Glyph({ className, children }: { className?: string | undefined; children: React.ReactNode }) {\n return (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n {children}\n </svg>\n );\n}\n\nexport function ChevronLeftIcon({ className }: { className?: string | undefined }) {\n return (\n <Glyph className={className}>\n {iconShapes(\"chevron-left\")}\n </Glyph>\n );\n}\n\nexport function TriangleAlertIcon({ className }: { className?: string | undefined }) {\n return (\n <Glyph className={className}>\n {iconShapes(\"triangle-alert\")}\n </Glyph>\n );\n}\n\nexport function InfoIcon({ className }: { className?: string | undefined }) {\n return (\n <Glyph className={className}>\n {iconShapes(\"info\")}\n </Glyph>\n );\n}\n\nexport function RefreshIcon({ className }: { className?: string | undefined }) {\n return (\n <Glyph className={className}>\n {iconShapes(\"refresh\")}\n </Glyph>\n );\n}\n\nexport function CloseIcon({ className }: { className?: string | undefined }) {\n return (\n <Glyph className={className}>\n {iconShapes(\"close\")}\n </Glyph>\n );\n}\n"],"mappings":"AAKI;AALJ,YAAY,WAAW;AACvB,SAAS,kBAAkB;AAE3B,SAAS,MAAM,EAAE,WAAW,SAAS,GAAkE;AACrG,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAa;AAAA,MACb,eAAc;AAAA,MACd,gBAAe;AAAA,MACf,eAAW;AAAA,MAEV;AAAA;AAAA,EACH;AAEJ;AAEO,SAAS,gBAAgB,EAAE,UAAU,GAAuC;AACjF,SACE,oBAAC,SAAM,WACJ,qBAAW,cAAc,GAC5B;AAEJ;AAEO,SAAS,kBAAkB,EAAE,UAAU,GAAuC;AACnF,SACE,oBAAC,SAAM,WACJ,qBAAW,gBAAgB,GAC9B;AAEJ;AAEO,SAAS,SAAS,EAAE,UAAU,GAAuC;AAC1E,SACE,oBAAC,SAAM,WACJ,qBAAW,MAAM,GACpB;AAEJ;AAEO,SAAS,YAAY,EAAE,UAAU,GAAuC;AAC7E,SACE,oBAAC,SAAM,WACJ,qBAAW,SAAS,GACvB;AAEJ;AAEO,SAAS,UAAU,EAAE,UAAU,GAAuC;AAC3E,SACE,oBAAC,SAAM,WACJ,qBAAW,OAAO,GACrB;AAEJ;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { cn } from "
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
5
|
import { NavBadge } from "./nav-badge.js";
|
|
6
6
|
import { labelTitle, NavLink } from "./nav-link.js";
|
|
7
7
|
import { NavCollapse, NavGroupHeader, useNavGroupOpen } from "./nav-collapse.js";
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./nav-model.js";
|
|
12
12
|
import { usePendingNavigation, useSlideMarker } from "./use-shell-nav.js";
|
|
13
13
|
const NAV_FOCUS = "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-secondary";
|
|
14
|
-
const ROW = "flex items-center gap-3 rounded-
|
|
14
|
+
const ROW = "flex items-center gap-3 rounded-row px-3 py-2 text-sm transition-colors";
|
|
15
15
|
function ShellNav({
|
|
16
16
|
groups,
|
|
17
17
|
footerGroups = [],
|
|
@@ -48,7 +48,7 @@ function ShellNav({
|
|
|
48
48
|
{
|
|
49
49
|
"data-slot": "shell-nav",
|
|
50
50
|
className: cn(
|
|
51
|
-
"flex h-full w-(--shell-rail-w) flex-col gap-7 overflow-y-auto border-r border-border bg-
|
|
51
|
+
"flex h-full w-(--shell-rail-w) flex-col gap-7 overflow-y-auto border-r border-border bg-card px-4.5 pb-5 pt-6",
|
|
52
52
|
className
|
|
53
53
|
),
|
|
54
54
|
...props,
|
|
@@ -85,7 +85,7 @@ function ShellNavSection({
|
|
|
85
85
|
{
|
|
86
86
|
"data-slot": "shell-nav-marker",
|
|
87
87
|
"aria-hidden": true,
|
|
88
|
-
className: "pointer-events-none absolute left-0 top-0 -z-10 rounded-
|
|
88
|
+
className: "pointer-events-none absolute left-0 top-0 -z-10 rounded-row bg-primary"
|
|
89
89
|
}
|
|
90
90
|
),
|
|
91
91
|
/* @__PURE__ */ jsx(
|
|
@@ -159,7 +159,7 @@ function ShellNavRow({
|
|
|
159
159
|
ROW,
|
|
160
160
|
NAV_FOCUS,
|
|
161
161
|
state.active ? "font-semibold text-on-primary" : cn("font-medium hover:bg-hover", nested ? "text-ink-mid" : "text-ink"),
|
|
162
|
-
item.disabled && "cursor-not-allowed opacity-
|
|
162
|
+
item.disabled && "cursor-not-allowed opacity-(--disabled-opacity) hover:bg-transparent"
|
|
163
163
|
),
|
|
164
164
|
children: row.renderItem ? row.renderItem(item, state) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
165
165
|
Icon && /* @__PURE__ */ jsx(Icon, { className: "size-4.5 shrink-0" }),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/shell-nav.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { NavBadge } from \"./nav-badge\";\nimport { labelTitle, NavLink, type NavLinkCallbacks } from \"./nav-link\";\nimport { NavCollapse, NavGroupHeader, useNavGroupOpen, type NavCollapseLabels } from \"./nav-collapse\";\nimport {\n navItemMatch,\n resolveActiveNavItem,\n type NavGroup,\n type NavItem,\n type NavItemState,\n} from \"./nav-model\";\nimport { usePendingNavigation, useSlideMarker } from \"./use-shell-nav\";\n\nexport interface ShellNavLabels extends NavCollapseLabels {\n /** Accessible name of the nav holding `groups`. Default `\"Main\"`. */\n primary?: string;\n /** Accessible name of the nav holding `footerGroups`. Default `\"Account\"`. */\n footer?: string;\n /** Spoken text of a numeric badge, given the real count. Default `\"{n} new\"`. */\n badge?: (count: number) => string;\n}\n\nexport interface ShellNavProps\n extends Omit<React.ComponentProps<\"aside\">, \"children\">,\n NavLinkCallbacks {\n groups: readonly NavGroup[];\n /** Pinned to the bottom of the rail (profile, notifications, settings). */\n footerGroups?: readonly NavGroup[];\n /** The router's current path — `usePathname()` in Next. */\n pathname: string;\n /** Your router's link (`next/link`); defaults to a plain `<a>`. */\n linkComponent?: React.ElementType;\n /** Above the groups — the brand lock-up. */\n header?: React.ReactNode;\n /** Below the footer groups — the signed-in account, a sign-out. */\n footer?: React.ReactNode;\n /** Replaces a row's content (icon, label, badge); the link, `aria-current` and the marker stay the kit's. */\n renderItem?: (item: NavItem, state: NavItemState) => React.ReactNode;\n labels?: ShellNavLabels;\n /** Makes every labelled group collapsible; a group's own `collapsible` wins. Default `false`. */\n collapsible?: boolean;\n}\n\n// The ring is the solid token, never a tint — at 50% it composites under the 3:1\n// non-text floor. The offset keeps it legible around the marked row, whose fill\n// is that same hue.\nconst NAV_FOCUS =\n \"outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-secondary\";\nconst ROW = \"flex items-center gap-3 rounded-row px-3 py-2 text-sm transition-colors\";\n\n/**\n * The app's left rail: data-driven groups, a footer block pinned to the bottom,\n * one sliding marker per group, and an optimistic mark on click so the row\n * answers the click rather than the router's round-trip.\n *\n * Exactly one row across the rail is current — the strongest claim on the path\n * (see {@link resolveActiveNavItem}) — so overlapping `prefix` items are safe.\n * Visibility (roles, flags) is the caller's: pass only the items to show.\n */\nexport function ShellNav({\n groups,\n footerGroups = [],\n pathname,\n linkComponent,\n header,\n footer,\n renderItem,\n onItemIntent,\n onNavigate,\n labels = {},\n collapsible = false,\n className,\n ...props\n}: ShellNavProps) {\n const [pendingId, markPending] = usePendingNavigation(pathname);\n const all = [...groups, ...footerGroups].flatMap((g) => g.items);\n const currentId =\n (pendingId !== null && all.some((i) => i.id === pendingId) ? pendingId : undefined) ??\n resolveActiveNavItem(all, pathname)?.id;\n const section = (group: NavGroup) => (\n <ShellNavSection\n key={group.id}\n group={group}\n currentId={currentId}\n pendingId={pendingId}\n pathname={pathname}\n labels={labels}\n collapsible={collapsible}\n row={{ linkComponent, markPending, onItemIntent, onNavigate, renderItem, badgeLabel: labels.badge }}\n />\n );\n return (\n <aside\n data-slot=\"shell-nav\"\n className={cn(\n \"flex h-full w-(--shell-rail-w) flex-col gap-7 overflow-y-auto border-r border-border bg-card px-4.5 pb-5 pt-6\",\n className,\n )}\n {...props}\n >\n {header}\n <nav aria-label={labels.primary ?? \"Main\"} className=\"flex flex-col gap-4.5\">\n {groups.map(section)}\n </nav>\n <div className=\"flex-1\" />\n {footerGroups.length > 0 && (\n <nav aria-label={labels.footer ?? \"Account\"} className=\"flex flex-col gap-4.5\">\n {footerGroups.map(section)}\n </nav>\n )}\n {footer}\n </aside>\n );\n}\n\ninterface RowContext extends NavLinkCallbacks {\n linkComponent: React.ElementType | undefined;\n markPending: (id: string) => void;\n renderItem: ShellNavProps[\"renderItem\"];\n badgeLabel: ((count: number) => string) | undefined;\n}\n\n// One marker node per SECTION, mounted once and moved — not one per rail: a\n// marker travelling between groups would cross headings that have nothing to do\n// with either row. Crossing groups unmounts one marker and mounts another (a\n// fade). `isolate` is load-bearing: the marker sits on a negative z-index and\n// without its own stacking context would land behind the rail's background.\n// The marker lives in the BODY, below the header, so a folding section clips it\n// together with its rows instead of leaving it painted over the next group.\nfunction ShellNavSection({\n group,\n currentId,\n pendingId,\n pathname,\n row,\n labels,\n collapsible,\n}: {\n group: NavGroup;\n currentId: string | undefined;\n pendingId: string | null;\n pathname: string;\n row: RowContext;\n labels: ShellNavLabels;\n collapsible: boolean;\n}) {\n const body = React.useRef<HTMLDivElement>(null);\n const labelId = React.useId();\n const regionId = React.useId();\n const at = group.items.some((i) => i.id === currentId) ? (currentId ?? null) : null;\n const [open, setOpen] = useNavGroupOpen(group, at !== null);\n useSlideMarker(body, at);\n const folds = (group.collapsible ?? collapsible) && group.label !== undefined;\n const landing =\n group.href !== undefined &&\n navItemMatch({ id: group.id, href: group.href, label: \"\", match: \"exact\" }, pathname) !== null;\n const content = (\n <div ref={body} className={cn(\"relative isolate\", folds && \"pt-1\")}>\n {/* First in DOM order: the pre-hydration fill in motion.css reaches the marked\n row through a sibling combinator, which only looks forward. */}\n {at !== null && (\n <span\n data-slot=\"shell-nav-marker\"\n aria-hidden\n className=\"pointer-events-none absolute left-0 top-0 -z-10 rounded-row bg-primary\"\n />\n )}\n <ul\n aria-labelledby={group.label !== undefined ? labelId : undefined}\n className={cn(\"flex flex-col gap-1\", folds && \"pl-3\")}\n >\n {group.items.map((item) => (\n <li key={item.id} className=\"flex flex-col\">\n <ShellNavRow\n item={item}\n nested={folds}\n state={{ active: item.id === currentId, pending: item.id === pendingId }}\n row={row}\n />\n </li>\n ))}\n </ul>\n </div>\n );\n if (!folds) {\n return (\n <div\n data-slot=\"shell-nav-section\"\n className={cn(\"flex flex-col gap-1\", group.label !== undefined && \"pl-1\")}\n >\n {group.label !== undefined && (\n <p id={labelId} className=\"mb-0.5 text-xs font-semibold uppercase tracking-widest text-ink-soft\">\n {group.label}\n </p>\n )}\n {content}\n </div>\n );\n }\n return (\n <div data-slot=\"shell-nav-section\" data-state={open ? \"open\" : \"closed\"} className=\"flex flex-col\">\n <NavGroupHeader\n label={group.label}\n labelId={labelId}\n regionId={regionId}\n open={open}\n onToggle={() => setOpen(!open)}\n href={group.href}\n linkComponent={row.linkComponent}\n current={landing}\n labels={labels}\n />\n <NavCollapse open={open} id={regionId}>\n {content}\n </NavCollapse>\n </div>\n );\n}\n\nfunction ShellNavRow({\n item,\n state,\n row,\n nested,\n}: {\n item: NavItem;\n state: NavItemState;\n row: RowContext;\n nested: boolean;\n}) {\n const Icon = item.icon;\n const trailing = typeof item.trailing === \"function\" ? item.trailing(state) : item.trailing;\n return (\n <NavLink\n item={item}\n current={state.active}\n pending={state.pending}\n linkComponent={row.linkComponent}\n markPending={row.markPending}\n onItemIntent={row.onItemIntent}\n onNavigate={row.onNavigate}\n title={labelTitle(item.label)}\n className={cn(\n ROW,\n NAV_FOCUS,\n state.active\n ? \"font-semibold text-on-primary\"\n : cn(\"font-medium hover:bg-hover\", nested ? \"text-ink-mid\" : \"text-ink\"),\n item.disabled && \"cursor-not-allowed opacity-(--disabled-opacity) hover:bg-transparent\",\n )}\n >\n {row.renderItem ? (\n row.renderItem(item, state)\n ) : (\n <>\n {Icon && <Icon className=\"size-4.5 shrink-0\" />}\n {/* `min-w-0`: without it the label refuses to shrink below its own text and\n the rail widens to the longest translation instead of truncating. */}\n <span className=\"min-w-0 flex-1 truncate\">{item.label}</span>\n {typeof item.badge === \"number\" ? (\n <NavBadge\n count={item.badge}\n active={state.active}\n {...(row.badgeLabel ? { label: row.badgeLabel } : {})}\n />\n ) : (\n item.badge\n )}\n {trailing}\n </>\n )}\n </NavLink>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { cn } from "
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
4
|
import {
|
|
5
5
|
SMART_HEADER_BAR,
|
|
6
6
|
SMART_HEADER_BASE,
|
|
7
7
|
SMART_HEADER_CONTEXT,
|
|
8
8
|
SMART_HEADER_TOOLBAR
|
|
9
|
-
} from "
|
|
9
|
+
} from "../../generated/smart-header.js";
|
|
10
10
|
import { TopBar } from "./top-bar.js";
|
|
11
11
|
function SmartHeader({
|
|
12
12
|
state = "default",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/smart-header.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n SMART_HEADER_BAR,\n SMART_HEADER_BASE,\n SMART_HEADER_CONTEXT,\n SMART_HEADER_TOOLBAR,\n} from \"../../generated/smart-header\";\nimport { TopBar } from \"./top-bar\";\nimport type { SmartHeaderState } from \"../../generated/smart-header\";\n\nexport type { SmartHeaderState };\n\nexport interface SmartHeaderProps extends Omit<React.ComponentProps<\"div\">, \"children\"> {\n /**\n * `default` — bar, toolbar and context line; `collapsed` — the toolbar folds\n * into the bar as `collapsed`; `banner` — a banner row above one bar;\n * `search` — one bar with the `palette` under it.\n */\n state?: SmartHeaderState;\n /** Brand, workspace tabs: the left side of the bar. */\n start?: React.ReactNode;\n /** The right side of the bar: icon actions, balance, bell, account menu. */\n end?: React.ReactNode;\n /** The folded toolbar, between `start` and `end`; shown in `collapsed` only. */\n collapsed?: React.ReactNode;\n /** A `SystemBanner`; shown in `banner` only. */\n banner?: React.ReactNode;\n /** The second row, 44 high; shown in `default` only. */\n toolbar?: React.ReactNode;\n /** The slim line on the page fill under the toolbar; shown in `default` only. */\n context?: React.ReactNode;\n /** A `CommandPalette` or any panel that drops from the bar; shown in `search` only. */\n palette?: React.ReactNode;\n}\n\n/**\n * A page header that adapts to scroll and alerts. The bar is the same in every\n * state, so switching never moves the brand or the account: only the rows\n * around it come and go. Layout only; the caller owns the state and its trigger\n * (a scroll observer, a feed status, the search button).\n */\nexport function SmartHeader({\n state = \"default\",\n start,\n end,\n collapsed,\n banner,\n toolbar,\n context,\n palette,\n className,\n ...props\n}: SmartHeaderProps) {\n return (\n <div\n data-slot=\"smart-header\"\n data-state={state}\n className={cn(SMART_HEADER_BASE, className)}\n {...props}\n >\n {state === \"banner\" && banner}\n <TopBar\n className={SMART_HEADER_BAR}\n start={\n <>\n {start}\n {state === \"collapsed\" && collapsed}\n </>\n }\n end={end}\n />\n {state === \"default\" && toolbar != null && (\n <div data-slot=\"smart-header-toolbar\" className={SMART_HEADER_TOOLBAR}>\n {toolbar}\n </div>\n )}\n {state === \"default\" && context != null && (\n <div data-slot=\"smart-header-context\" className={SMART_HEADER_CONTEXT}>\n {context}\n </div>\n )}\n {state === \"search\" && palette != null && <div data-slot=\"smart-header-palette\">{palette}</div>}\n </div>\n );\n}\n"],"mappings":"AA8DM,SAGI,UAHJ,KAGI,YAHJ;AA9DN,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,cAAc;AAkChB,SAAS,YAAY;AAAA,EAC1B,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAqB;AACnB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,cAAY;AAAA,MACZ,WAAW,GAAG,mBAAmB,SAAS;AAAA,MACzC,GAAG;AAAA,MAEH;AAAA,kBAAU,YAAY;AAAA,QACvB;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,YACX,OACE,iCACG;AAAA;AAAA,cACA,UAAU,eAAe;AAAA,eAC5B;AAAA,YAEF;AAAA;AAAA,QACF;AAAA,QACC,UAAU,aAAa,WAAW,QACjC,oBAAC,SAAI,aAAU,wBAAuB,WAAW,sBAC9C,mBACH;AAAA,QAED,UAAU,aAAa,WAAW,QACjC,oBAAC,SAAI,aAAU,wBAAuB,WAAW,sBAC9C,mBACH;AAAA,QAED,UAAU,YAAY,WAAW,QAAQ,oBAAC,SAAI,aAAU,wBAAwB,mBAAQ;AAAA;AAAA;AAAA,EAC3F;AAEJ;","names":[]}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { accentTextClasses } from "../../generated/accent.js";
|
|
6
|
+
import { buttonVariants } from "../atomic/button.js";
|
|
7
|
+
import { Logo } from "./logo.js";
|
|
8
|
+
import { STATUS_SCREEN_ACTIONS, STATUS_SCREEN_ACTION_ICON, STATUS_SCREEN_BODY, STATUS_SCREEN_CODE, STATUS_SCREEN_CTA, STATUS_SCREEN_EYEBROW, STATUS_SCREEN_GLOW, STATUS_SCREEN_LOGO, STATUS_SCREEN_ROOT, STATUS_SCREEN_STACK, STATUS_SCREEN_TITLE, STATUS_SCREEN_TITLE_ACCENT } from "../../generated/status-screen.js";
|
|
9
|
+
import { iconShapes } from "../../icons/icon-shapes.js";
|
|
10
|
+
import * as copy from "../../generated/copy.js";
|
|
11
|
+
function statusCtaClass(accent, variant) {
|
|
12
|
+
return cn(
|
|
13
|
+
buttonVariants({ variant, size: "lg", accent }),
|
|
14
|
+
STATUS_SCREEN_CTA
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
function ArrowLeftIcon({ className }) {
|
|
18
|
+
return /* @__PURE__ */ jsx(
|
|
19
|
+
"svg",
|
|
20
|
+
{
|
|
21
|
+
className,
|
|
22
|
+
viewBox: "0 0 24 24",
|
|
23
|
+
fill: "none",
|
|
24
|
+
stroke: "currentColor",
|
|
25
|
+
strokeWidth: 2,
|
|
26
|
+
strokeLinecap: "round",
|
|
27
|
+
strokeLinejoin: "round",
|
|
28
|
+
"aria-hidden": true,
|
|
29
|
+
children: iconShapes("arrow-left")
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function StatusScreen({
|
|
34
|
+
accent,
|
|
35
|
+
eyebrow,
|
|
36
|
+
code,
|
|
37
|
+
headlineLead,
|
|
38
|
+
headlineAccent,
|
|
39
|
+
headlineTail = ".",
|
|
40
|
+
subtext,
|
|
41
|
+
links,
|
|
42
|
+
children,
|
|
43
|
+
linkComponent
|
|
44
|
+
}) {
|
|
45
|
+
const L = linkComponent ?? "a";
|
|
46
|
+
const accentText = accentTextClasses[accent];
|
|
47
|
+
return /* @__PURE__ */ jsxs("section", { className: STATUS_SCREEN_ROOT, children: [
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
"div",
|
|
50
|
+
{
|
|
51
|
+
"aria-hidden": true,
|
|
52
|
+
className: cn(
|
|
53
|
+
STATUS_SCREEN_GLOW,
|
|
54
|
+
accentText
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: STATUS_SCREEN_STACK, children: [
|
|
59
|
+
/* @__PURE__ */ jsx(Logo, { className: cn(STATUS_SCREEN_LOGO, accentText) }),
|
|
60
|
+
/* @__PURE__ */ jsx("p", { className: cn(STATUS_SCREEN_EYEBROW, accentText), children: eyebrow }),
|
|
61
|
+
/* @__PURE__ */ jsx("p", { className: cn(STATUS_SCREEN_CODE, accentText), children: code }),
|
|
62
|
+
/* @__PURE__ */ jsxs("h1", { className: STATUS_SCREEN_TITLE, children: [
|
|
63
|
+
headlineLead,
|
|
64
|
+
/* @__PURE__ */ jsx("span", { className: cn(STATUS_SCREEN_TITLE_ACCENT, accentText), children: headlineAccent }),
|
|
65
|
+
headlineTail
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ jsx("p", { className: STATUS_SCREEN_BODY, children: subtext }),
|
|
68
|
+
/* @__PURE__ */ jsxs("div", { className: STATUS_SCREEN_ACTIONS, children: [
|
|
69
|
+
children,
|
|
70
|
+
links?.map((link) => /* @__PURE__ */ jsxs(L, { href: link.href, className: statusCtaClass(accent, link.variant ?? "primary"), children: [
|
|
71
|
+
link.leadingArrow ? /* @__PURE__ */ jsx(ArrowLeftIcon, { className: STATUS_SCREEN_ACTION_ICON }) : null,
|
|
72
|
+
link.label
|
|
73
|
+
] }, link.label))
|
|
74
|
+
] })
|
|
75
|
+
] })
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
function NotFound({ linkComponent = "a", homeHref = "/", contactHref = "/contact" }) {
|
|
79
|
+
return /* @__PURE__ */ jsx(
|
|
80
|
+
StatusScreen,
|
|
81
|
+
{
|
|
82
|
+
accent: "debug",
|
|
83
|
+
eyebrow: copy.NOT_FOUND_EYEBROW,
|
|
84
|
+
code: "404",
|
|
85
|
+
headlineLead: copy.NOT_FOUND_HEADLINE_LEAD,
|
|
86
|
+
headlineAccent: copy.NOT_FOUND_HEADLINE_ACCENT,
|
|
87
|
+
subtext: copy.NOT_FOUND_SUBTEXT,
|
|
88
|
+
linkComponent,
|
|
89
|
+
links: [
|
|
90
|
+
{ label: copy.STATUS_HOME, href: homeHref, leadingArrow: true },
|
|
91
|
+
{ label: copy.NOT_FOUND_CONTACT, href: contactHref, variant: "outline" }
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
function Forbidden({ linkComponent = "a", homeHref = "/", contactHref = "/contact" }) {
|
|
97
|
+
return /* @__PURE__ */ jsx(
|
|
98
|
+
StatusScreen,
|
|
99
|
+
{
|
|
100
|
+
accent: "warn",
|
|
101
|
+
eyebrow: copy.FORBIDDEN_EYEBROW,
|
|
102
|
+
code: "403",
|
|
103
|
+
headlineLead: copy.FORBIDDEN_HEADLINE_LEAD,
|
|
104
|
+
headlineAccent: copy.FORBIDDEN_HEADLINE_ACCENT,
|
|
105
|
+
subtext: copy.FORBIDDEN_SUBTEXT,
|
|
106
|
+
linkComponent,
|
|
107
|
+
links: [
|
|
108
|
+
{ label: copy.STATUS_HOME, href: homeHref, leadingArrow: true },
|
|
109
|
+
{ label: copy.FORBIDDEN_CONTACT, href: contactHref, variant: "outline" }
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
function ServerError({ linkComponent = "a", homeHref = "/", reset }) {
|
|
115
|
+
return /* @__PURE__ */ jsx(
|
|
116
|
+
StatusScreen,
|
|
117
|
+
{
|
|
118
|
+
accent: "error",
|
|
119
|
+
eyebrow: copy.SERVER_ERROR_EYEBROW,
|
|
120
|
+
code: "500",
|
|
121
|
+
headlineLead: copy.SERVER_ERROR_HEADLINE_LEAD,
|
|
122
|
+
headlineAccent: copy.SERVER_ERROR_HEADLINE_ACCENT,
|
|
123
|
+
subtext: copy.SERVER_ERROR_SUBTEXT,
|
|
124
|
+
linkComponent,
|
|
125
|
+
links: [{ label: copy.STATUS_HOME, href: homeHref, variant: "outline", leadingArrow: true }],
|
|
126
|
+
children: /* @__PURE__ */ jsx(
|
|
127
|
+
"button",
|
|
128
|
+
{
|
|
129
|
+
type: "button",
|
|
130
|
+
className: statusCtaClass("error", "primary"),
|
|
131
|
+
onClick: () => reset ? reset() : window.location.reload(),
|
|
132
|
+
children: copy.SERVER_ERROR_RETRY
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
export {
|
|
139
|
+
Forbidden,
|
|
140
|
+
NotFound,
|
|
141
|
+
ServerError,
|
|
142
|
+
StatusScreen,
|
|
143
|
+
statusCtaClass
|
|
144
|
+
};
|
|
145
|
+
//# sourceMappingURL=status-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/status-screen.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { accentTextClasses, type Accent } from \"../../generated/accent\";\nimport { buttonVariants, type ButtonVariant } from \"../atomic/button\";\nimport { Logo } from \"./logo\";\nimport { STATUS_SCREEN_ACTIONS, STATUS_SCREEN_ACTION_ICON, STATUS_SCREEN_BODY, STATUS_SCREEN_CODE, STATUS_SCREEN_CTA, STATUS_SCREEN_EYEBROW, STATUS_SCREEN_GLOW, STATUS_SCREEN_LOGO, STATUS_SCREEN_ROOT, STATUS_SCREEN_STACK, STATUS_SCREEN_TITLE, STATUS_SCREEN_TITLE_ACCENT } from \"../../generated/status-screen\";\nimport { iconShapes } from \"../../icons/icon-shapes\";\nimport * as copy from \"../../generated/copy\";\n\n/**\n * The shared 404 / 403 / 500 status surface.\n *\n * `StatusScreen` is the generic shell; `NotFound` / `Forbidden` / `ServerError`\n * are the ready-made pages with their copy baked in — a host renders those with\n * its own hrefs. The mark is `Logo`'s, i.e. the consumer's. Links default to a\n * plain `<a>` (a full document load, which is what you want off an error page);\n * pass `linkComponent` (e.g. `next/link`) for soft navigation from a client\n * boundary.\n */\nexport type { Accent };\n\n/**\n * A status CTA is a Button at the page's accent: the canonical button string for\n * that variant and rung, then the mono/uppercase treatment the error pages wear.\n *\n * Exported because a host that renders its own action into `StatusScreen`'s\n * slot — a retry button wired to Next's `reset`, say — has to be able to match\n * the CTAs beside it.\n */\nexport function statusCtaClass(accent: Accent, variant: ButtonVariant) {\n return cn(\n buttonVariants({ variant, size: \"lg\", accent }),\n STATUS_SCREEN_CTA,\n );\n}\n\nfunction ArrowLeftIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n {iconShapes(\"arrow-left\")}\n </svg>\n );\n}\n\nexport interface StatusLinkData {\n label: string;\n href: string;\n variant?: ButtonVariant;\n leadingArrow?: boolean;\n}\n\nexport interface StatusScreenProps {\n accent: Accent;\n eyebrow: string;\n code: string;\n headlineLead: string;\n headlineAccent: string;\n headlineTail?: string;\n subtext: string;\n links?: StatusLinkData[];\n /** Leading action slot, rendered before `links` (e.g. the 500 client retry). */\n children?: React.ReactNode;\n /** CTA element — `next/link` for soft nav; defaults to `<a>` (full load). */\n linkComponent?: React.ElementType;\n}\n\n/**\n * Shared skeleton for the 404 / 403 / 500 status pages: a centred hero with the\n * logo mark, a mono eyebrow, a giant Playfair code, a headline whose final clause\n * is an italic accent, supporting copy, and the CTAs. The accent threads through\n * all four marks. Actions render inline (from `links` data, plus an optional\n * `children` slot) — never passed as a JSX prop through a server boundary.\n */\nexport function StatusScreen({\n accent,\n eyebrow,\n code,\n headlineLead,\n headlineAccent,\n headlineTail = \".\",\n subtext,\n links,\n children,\n linkComponent,\n}: StatusScreenProps) {\n const L = linkComponent ?? \"a\";\n const accentText = accentTextClasses[accent];\n return (\n <section className={STATUS_SCREEN_ROOT}>\n <div\n aria-hidden\n className={cn(\n STATUS_SCREEN_GLOW,\n accentText,\n )}\n />\n <div className={STATUS_SCREEN_STACK}>\n <Logo className={cn(STATUS_SCREEN_LOGO, accentText)} />\n <p className={cn(STATUS_SCREEN_EYEBROW, accentText)}>{eyebrow}</p>\n <p className={cn(STATUS_SCREEN_CODE, accentText)}>{code}</p>\n <h1 className={STATUS_SCREEN_TITLE}>\n {headlineLead}\n <span className={cn(STATUS_SCREEN_TITLE_ACCENT, accentText)}>{headlineAccent}</span>\n {headlineTail}\n </h1>\n <p className={STATUS_SCREEN_BODY}>{subtext}</p>\n <div className={STATUS_SCREEN_ACTIONS}>\n {children}\n {links?.map((link) => (\n <L key={link.label} href={link.href} className={statusCtaClass(accent, link.variant ?? \"primary\")}>\n {link.leadingArrow ? <ArrowLeftIcon className={STATUS_SCREEN_ACTION_ICON} /> : null}\n {link.label}\n </L>\n ))}\n </div>\n </div>\n </section>\n );\n}\n\nexport interface StatusPageProps {\n /** CTA element — `next/link` for soft nav; defaults to `<a>` (full load). */\n linkComponent?: React.ElementType;\n /** copy.STATUS_HOME target — `/` for the landing, `/cabinet` for the cabinet. */\n homeHref?: string;\n /** Secondary CTA target (contact / request access). */\n contactHref?: string;\n}\n\n/** 404 — page not found. */\nexport function NotFound({ linkComponent = \"a\", homeHref = \"/\", contactHref = \"/contact\" }: StatusPageProps) {\n return (\n <StatusScreen\n accent=\"debug\"\n eyebrow={copy.NOT_FOUND_EYEBROW}\n code=\"404\"\n headlineLead={copy.NOT_FOUND_HEADLINE_LEAD}\n headlineAccent={copy.NOT_FOUND_HEADLINE_ACCENT}\n subtext={copy.NOT_FOUND_SUBTEXT}\n linkComponent={linkComponent}\n links={[\n { label: copy.STATUS_HOME, href: homeHref, leadingArrow: true },\n { label: copy.NOT_FOUND_CONTACT, href: contactHref, variant: \"outline\" },\n ]}\n />\n );\n}\n\n/** 403 — access forbidden. */\nexport function Forbidden({ linkComponent = \"a\", homeHref = \"/\", contactHref = \"/contact\" }: StatusPageProps) {\n return (\n <StatusScreen\n accent=\"warn\"\n eyebrow={copy.FORBIDDEN_EYEBROW}\n code=\"403\"\n headlineLead={copy.FORBIDDEN_HEADLINE_LEAD}\n headlineAccent={copy.FORBIDDEN_HEADLINE_ACCENT}\n subtext={copy.FORBIDDEN_SUBTEXT}\n linkComponent={linkComponent}\n links={[\n { label: copy.STATUS_HOME, href: homeHref, leadingArrow: true },\n { label: copy.FORBIDDEN_CONTACT, href: contactHref, variant: \"outline\" },\n ]}\n />\n );\n}\n\nexport interface ServerErrorProps {\n /** CTA element — `next/link` for soft nav; defaults to `<a>` (full load). */\n linkComponent?: React.ElementType;\n /** copy.STATUS_HOME target — `/` for the landing, `/cabinet` for the cabinet. */\n homeHref?: string;\n /** Retry handler (e.g. Next's error-boundary `reset`); falls back to a reload. */\n reset?: () => void;\n}\n\n/** 500 — server error. The \"Try again\" button runs `reset` or reloads the page. */\nexport function ServerError({ linkComponent = \"a\", homeHref = \"/\", reset }: ServerErrorProps) {\n return (\n <StatusScreen\n accent=\"error\"\n eyebrow={copy.SERVER_ERROR_EYEBROW}\n code=\"500\"\n headlineLead={copy.SERVER_ERROR_HEADLINE_LEAD}\n headlineAccent={copy.SERVER_ERROR_HEADLINE_ACCENT}\n subtext={copy.SERVER_ERROR_SUBTEXT}\n linkComponent={linkComponent}\n links={[{ label: copy.STATUS_HOME, href: homeHref, variant: \"outline\", leadingArrow: true }]}\n >\n <button\n type=\"button\"\n className={statusCtaClass(\"error\", \"primary\")}\n onClick={() => (reset ? reset() : window.location.reload())}\n >\n {copy.SERVER_ERROR_RETRY}\n </button>\n </StatusScreen>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { cn } from "
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
5
|
import {
|
|
6
6
|
SYSTEM_BANNER_ACTION,
|
|
7
7
|
SYSTEM_BANNER_BASE,
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
SYSTEM_BANNER_ICON,
|
|
12
12
|
SYSTEM_BANNER_MESSAGE,
|
|
13
13
|
SYSTEM_BANNER_TITLE,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from "
|
|
14
|
+
SYSTEM_BANNER_LABELS
|
|
15
|
+
} from "../../generated/system-banner.js";
|
|
16
|
+
import { toneClasses } from "../../generated/tone.js";
|
|
17
17
|
import { CloseIcon, InfoIcon, TriangleAlertIcon } from "./shell-icons.js";
|
|
18
18
|
function SystemBanner({
|
|
19
|
-
tone = "
|
|
19
|
+
tone = "neutral",
|
|
20
20
|
title,
|
|
21
21
|
icon,
|
|
22
22
|
onDismiss,
|
|
@@ -33,10 +33,10 @@ function SystemBanner({
|
|
|
33
33
|
"data-slot": "system-banner",
|
|
34
34
|
"data-tone": tone,
|
|
35
35
|
role: "status",
|
|
36
|
-
className: cn(SYSTEM_BANNER_BASE,
|
|
36
|
+
className: cn(SYSTEM_BANNER_BASE, toneClasses[tone], className),
|
|
37
37
|
...props,
|
|
38
38
|
children: [
|
|
39
|
-
glyph !== null && /* @__PURE__ */ jsx("span", { className:
|
|
39
|
+
glyph !== null && /* @__PURE__ */ jsx("span", { className: SYSTEM_BANNER_ICON, children: glyph }),
|
|
40
40
|
/* @__PURE__ */ jsxs("div", { className: SYSTEM_BANNER_MESSAGE, children: [
|
|
41
41
|
title !== void 0 && /* @__PURE__ */ jsx("span", { className: SYSTEM_BANNER_TITLE, children: title }),
|
|
42
42
|
title !== void 0 && children !== void 0 && " \u2014 ",
|
|
@@ -47,7 +47,7 @@ function SystemBanner({
|
|
|
47
47
|
"button",
|
|
48
48
|
{
|
|
49
49
|
type: "button",
|
|
50
|
-
"aria-label": labels.dismiss ??
|
|
50
|
+
"aria-label": labels.dismiss ?? SYSTEM_BANNER_LABELS.dismiss,
|
|
51
51
|
onClick: onDismiss,
|
|
52
52
|
className: SYSTEM_BANNER_DISMISS,
|
|
53
53
|
children: /* @__PURE__ */ jsx(CloseIcon, { className: SYSTEM_BANNER_GLYPH })
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/system-banner.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n SYSTEM_BANNER_ACTION,\n SYSTEM_BANNER_BASE,\n SYSTEM_BANNER_BODY_AFTER_TITLE,\n SYSTEM_BANNER_DISMISS,\n SYSTEM_BANNER_GLYPH,\n SYSTEM_BANNER_ICON,\n SYSTEM_BANNER_MESSAGE,\n SYSTEM_BANNER_TITLE,\n SYSTEM_BANNER_LABELS,\n} from \"../../generated/system-banner\";\nimport { toneClasses, type Tone } from \"../../generated/tone\";\nimport { CloseIcon, InfoIcon, TriangleAlertIcon } from \"./shell-icons\";\n\nexport interface SystemBannerLabels {\n /** The close button. Default `\"Dismiss\"`. */\n dismiss?: string;\n}\n\nexport interface SystemBannerProps extends Omit<React.ComponentProps<\"div\">, \"title\"> {\n /** `warn` — a platform state (maintenance, read-only); `info` — an announcement. */\n tone?: Tone;\n /** Bold lead before the message. */\n title?: React.ReactNode;\n /** Replaces the tone's glyph; `null` drops it. */\n icon?: React.ReactNode;\n /** Shows a close button; remembering the dismissal is the caller's. */\n onDismiss?: () => void;\n /** A link or button after the message. */\n action?: React.ReactNode;\n labels?: SystemBannerLabels;\n}\n\n/**\n * A slim full-width strip above the page — presentation only: where its state\n * comes from, and whether a dismissal sticks, are the caller's. Put it in\n * `AppShell`'s `banner` slot; several stack with a gap.\n */\nexport function SystemBanner({\n tone = \"neutral\",\n title,\n icon,\n onDismiss,\n action,\n labels = {},\n className,\n children,\n ...props\n}: SystemBannerProps) {\n const glyph =\n icon !== undefined ? icon : tone === \"warn\" ? <TriangleAlertIcon className={SYSTEM_BANNER_GLYPH} /> : <InfoIcon className={SYSTEM_BANNER_GLYPH} />;\n return (\n <div\n data-slot=\"system-banner\"\n data-tone={tone}\n role=\"status\"\n className={cn(SYSTEM_BANNER_BASE, toneClasses[tone], className)}\n {...props}\n >\n {glyph !== null && <span className={SYSTEM_BANNER_ICON}>{glyph}</span>}\n <div className={SYSTEM_BANNER_MESSAGE}>\n {title !== undefined && <span className={SYSTEM_BANNER_TITLE}>{title}</span>}\n {title !== undefined && children !== undefined && \" — \"}\n {children !== undefined && <span className={cn(title !== undefined && SYSTEM_BANNER_BODY_AFTER_TITLE)}>{children}</span>}\n </div>\n {action !== undefined && <span className={SYSTEM_BANNER_ACTION}>{action}</span>}\n {onDismiss && (\n <button\n type=\"button\"\n aria-label={labels.dismiss ?? SYSTEM_BANNER_LABELS.dismiss}\n onClick={onDismiss}\n className={SYSTEM_BANNER_DISMISS}\n >\n <CloseIcon className={SYSTEM_BANNER_GLYPH} />\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";AAsDkD,cAU5C,YAV4C;AApDlD,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,mBAA8B;AACvC,SAAS,WAAW,UAAU,yBAAyB;AA0BhD,SAAS,aAAa;AAAA,EAC3B,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS,CAAC;AAAA,EACV;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAsB;AACpB,QAAM,QACJ,SAAS,SAAY,OAAO,SAAS,SAAS,oBAAC,qBAAkB,WAAW,qBAAqB,IAAK,oBAAC,YAAS,WAAW,qBAAqB;AAClJ,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,aAAW;AAAA,MACX,MAAK;AAAA,MACL,WAAW,GAAG,oBAAoB,YAAY,IAAI,GAAG,SAAS;AAAA,MAC7D,GAAG;AAAA,MAEH;AAAA,kBAAU,QAAQ,oBAAC,UAAK,WAAW,oBAAqB,iBAAM;AAAA,QAC/D,qBAAC,SAAI,WAAW,uBACb;AAAA,oBAAU,UAAa,oBAAC,UAAK,WAAW,qBAAsB,iBAAM;AAAA,UACpE,UAAU,UAAa,aAAa,UAAa;AAAA,UACjD,aAAa,UAAa,oBAAC,UAAK,WAAW,GAAG,UAAU,UAAa,8BAA8B,GAAI,UAAS;AAAA,WACnH;AAAA,QACC,WAAW,UAAa,oBAAC,UAAK,WAAW,sBAAuB,kBAAO;AAAA,QACvE,aACC;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,cAAY,OAAO,WAAW,qBAAqB;AAAA,YACnD,SAAS;AAAA,YACT,WAAW;AAAA,YAEX,8BAAC,aAAU,WAAW,qBAAqB;AAAA;AAAA,QAC7C;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { cn } from "
|
|
4
|
-
import { TOP_BAR_BASE, TOP_BAR_END, TOP_BAR_START } from "
|
|
3
|
+
import { cn } from "../../lib/cn.js";
|
|
4
|
+
import { TOP_BAR_BASE, TOP_BAR_END, TOP_BAR_START } from "../../generated/top-bar.js";
|
|
5
5
|
function TopBar({ start, end, className, ...props }) {
|
|
6
6
|
return /* @__PURE__ */ jsxs(
|
|
7
7
|
"header",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/top-bar.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { TOP_BAR_BASE, TOP_BAR_END, TOP_BAR_START } from \"../../generated/top-bar\";\n\nexport interface TopBarProps extends React.ComponentProps<\"header\"> {\n /** The app switcher, or the service's name. */\n start?: React.ReactNode;\n /** Service stats, then an `AccountMenu` last. */\n end?: React.ReactNode;\n}\n\n/**\n * The wide screen's utility bar over the content column: who and where, never\n * product nav (that is the rail's). Layout only — `AppShell.topBar` pins it.\n */\nexport function TopBar({ start, end, className, ...props }: TopBarProps) {\n return (\n <header\n data-slot=\"top-bar\"\n className={cn(TOP_BAR_BASE, className)}\n {...props}\n >\n <div data-slot=\"top-bar-start\" className={TOP_BAR_START}>\n {start}\n </div>\n <div data-slot=\"top-bar-end\" className={TOP_BAR_END}>\n {end}\n </div>\n </header>\n );\n}\n"],"mappings":"AAiBI,SAKE,KALF;AAjBJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,cAAc,aAAa,qBAAqB;AAalD,SAAS,OAAO,EAAE,OAAO,KAAK,WAAW,GAAG,MAAM,GAAgB;AACvE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,cAAc,SAAS;AAAA,MACpC,GAAG;AAAA,MAEJ;AAAA,4BAAC,SAAI,aAAU,iBAAgB,WAAW,eACvC,iBACH;AAAA,QACA,oBAAC,SAAI,aAAU,eAAc,WAAW,aACrC,eACH;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/use-shell-nav.ts"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\n/**\n * The optimistic half of a nav: the id of the item just clicked, until the\n * pathname catches up.\n *\n * A router that waits for the next page's payload changes the pathname 150–300ms\n * after the click — exactly the window in which a highlight that has not moved\n * reads as a click that did not land. So the clicked item is marked at once.\n *\n * The entry remembers the pathname it was made on, so the moment the pathname\n * changes it is stale by construction and the URL is the truth again. It is\n * cleared during render, not in an effect (an effect would paint one frame with\n * the URL's row marked and the stale one not), and cleared rather than ignored:\n * left behind, it would come back to life on a return to the page it was made\n * on. A click that never navigates is forgotten by the next one.\n */\nexport function usePendingNavigation(\n pathname: string,\n): readonly [pendingId: string | null, markPending: (id: string) => void] {\n const [pending, setPending] = React.useState<{ id: string; from: string } | null>(null);\n if (pending && pending.from !== pathname) setPending(null);\n const pendingId = pending && pending.from === pathname ? pending.id : null;\n const markPending = React.useCallback(\n (id: string) => setPending({ id, from: pathname }),\n [pathname],\n );\n return [pendingId, markPending] as const;\n}\n\n/**\n * Places the section's `[data-slot=\"shell-nav-marker\"]` over its\n * `[aria-current=\"page\"]` row, by measurement: rows differ in count and every\n * label is somebody's translation, and SSR cannot know those offsets (until the\n * first placement the row carries the fill itself — see motion.css). Re-runs\n * when `at` changes and whenever the section resizes — rows come and go, labels\n * change width with the locale or a font swap.\n */\nexport function useSlideMarker(\n ref: React.RefObject<HTMLElement | null>,\n at: string | null,\n): void {\n // Which marker node was last placed, so a re-run over the same node — a move,\n // a resize — is told apart from a marker that has just mounted. `undefined`\n // until the first run, so only a marker mounting AFTER the section settled\n // counts as entering (and fades); one hydration finds on its row cuts in.\n const placed = React.useRef<HTMLElement | null | undefined>(undefined);\n React.useLayoutEffect(() => {\n const section = ref.current;\n if (!section) return;\n const place = () => {\n const marker = section.querySelector<HTMLElement>('[data-slot=\"shell-nav-marker\"]');\n const row = section.querySelector<HTMLElement>('[aria-current=\"page\"]');\n const fresh = marker !== placed.current;\n const entering = fresh && placed.current !== undefined;\n placed.current = marker;\n if (!marker || !row) return;\n if (fresh) marker.style.transition = \"none\";\n marker.style.transform = `translate(${row.offsetLeft}px, ${row.offsetTop}px)`;\n marker.style.width = `${row.offsetWidth}px`;\n marker.style.height = `${row.offsetHeight}px`;\n if (fresh) {\n // A transition is decided by the style AFTER the change: flushing the\n // placement first makes it the starting point, so a new marker appears on\n // its row instead of sliding in from the section's origin.\n void marker.offsetWidth;\n marker.style.transition = \"\";\n marker.dataset[\"placed\"] = entering ? \"entered\" : \"first\";\n }\n };\n place();\n if (typeof ResizeObserver === \"undefined\") return;\n const observer = new ResizeObserver(place);\n observer.observe(section);\n return () => observer.disconnect();\n }, [ref, at]);\n}\n"],"mappings":";AAEA,YAAY,WAAW;AAiBhB,SAAS,qBACd,UACwE;AACxE,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAA8C,IAAI;AACtF,MAAI,WAAW,QAAQ,SAAS,SAAU,YAAW,IAAI;AACzD,QAAM,YAAY,WAAW,QAAQ,SAAS,WAAW,QAAQ,KAAK;AACtE,QAAM,cAAc,MAAM;AAAA,IACxB,CAAC,OAAe,WAAW,EAAE,IAAI,MAAM,SAAS,CAAC;AAAA,IACjD,CAAC,QAAQ;AAAA,EACX;AACA,SAAO,CAAC,WAAW,WAAW;AAChC;AAUO,SAAS,eACd,KACA,IACM;AAKN,QAAM,SAAS,MAAM,OAAuC,MAAS;AACrE,QAAM,gBAAgB,MAAM;AAC1B,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,QAAS;AACd,UAAM,QAAQ,MAAM;AAClB,YAAM,SAAS,QAAQ,cAA2B,gCAAgC;AAClF,YAAM,MAAM,QAAQ,cAA2B,uBAAuB;AACtE,YAAM,QAAQ,WAAW,OAAO;AAChC,YAAM,WAAW,SAAS,OAAO,YAAY;AAC7C,aAAO,UAAU;AACjB,UAAI,CAAC,UAAU,CAAC,IAAK;AACrB,UAAI,MAAO,QAAO,MAAM,aAAa;AACrC,aAAO,MAAM,YAAY,aAAa,IAAI,UAAU,OAAO,IAAI,SAAS;AACxE,aAAO,MAAM,QAAQ,GAAG,IAAI,WAAW;AACvC,aAAO,MAAM,SAAS,GAAG,IAAI,YAAY;AACzC,UAAI,OAAO;AAIT,aAAK,OAAO;AACZ,eAAO,MAAM,aAAa;AAC1B,eAAO,QAAQ,QAAQ,IAAI,WAAW,YAAY;AAAA,MACpD;AAAA,IACF;AACA,UAAM;AACN,QAAI,OAAO,mBAAmB,YAAa;AAC3C,UAAM,WAAW,IAAI,eAAe,KAAK;AACzC,aAAS,QAAQ,OAAO;AACxB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,KAAK,EAAE,CAAC;AACd;","names":[]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import { cn } from "
|
|
5
|
-
import { useControllableState } from "
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { useControllableState } from "../../primitives/use-controllable-state.js";
|
|
6
6
|
import {
|
|
7
7
|
WORKSPACE_TAB_BASE,
|
|
8
8
|
WORKSPACE_TAB_CLOSE,
|
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
WORKSPACE_TAB_SPACER,
|
|
12
12
|
WORKSPACE_TAB_TRIGGER,
|
|
13
13
|
WORKSPACE_TABS_BASE
|
|
14
|
-
} from "
|
|
15
|
-
import { UiIcon } from "
|
|
14
|
+
} from "../../generated/workspace-tab.js";
|
|
15
|
+
import { UiIcon } from "../../icons/ui-icons.js";
|
|
16
|
+
import * as copy from "../../generated/copy.js";
|
|
16
17
|
const WorkspaceTabsContext = React.createContext(null);
|
|
17
18
|
function useWorkspaceTabs() {
|
|
18
19
|
const ctx = React.useContext(WorkspaceTabsContext);
|
|
@@ -65,7 +66,7 @@ function WorkspaceTab({
|
|
|
65
66
|
value,
|
|
66
67
|
icon,
|
|
67
68
|
onClose,
|
|
68
|
-
closeLabel =
|
|
69
|
+
closeLabel = copy.WORKSPACE_TAB_CLOSE,
|
|
69
70
|
className,
|
|
70
71
|
children,
|
|
71
72
|
onClick,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/shell/workspace-tab.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { useControllableState } from \"../../primitives/use-controllable-state\";\nimport {\n WORKSPACE_TAB_BASE,\n WORKSPACE_TAB_CLOSE,\n WORKSPACE_TAB_LABEL,\n WORKSPACE_TAB_SELECTED,\n WORKSPACE_TAB_SPACER,\n WORKSPACE_TAB_TRIGGER,\n WORKSPACE_TABS_BASE,\n} from \"../../generated/workspace-tab\";\nimport { UiIcon } from \"../../icons/ui-icons\";\nimport * as copy from \"../../generated/copy\";\n\ninterface WorkspaceTabsContextValue {\n value: string;\n setValue: (next: string) => void;\n /** Values of the mounted tabs, in mount order. */\n values: readonly string[];\n register: (value: string) => () => void;\n}\n\nconst WorkspaceTabsContext = React.createContext<WorkspaceTabsContextValue | null>(null);\n\nfunction useWorkspaceTabs(): WorkspaceTabsContextValue {\n const ctx = React.useContext(WorkspaceTabsContext);\n if (!ctx) throw new Error(\"WorkspaceTab must be used within <WorkspaceTabs>\");\n return ctx;\n}\n\nexport interface WorkspaceTabsProps extends Omit<React.ComponentProps<\"div\">, \"onChange\" | \"defaultValue\"> {\n value?: string;\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n}\n\n/**\n * A row of open workspaces. Arrow keys move focus (Home/End jump); selecting is\n * Enter, Space or a click, so moving through the row never swaps the screen.\n */\nexport function WorkspaceTabs({\n value,\n defaultValue = \"\",\n onValueChange,\n className,\n onKeyDown,\n ...props\n}: WorkspaceTabsProps) {\n const [active, setValue] = useControllableState<string>({\n ...(value !== undefined ? { value } : {}),\n defaultValue,\n ...(onValueChange ? { onChange: onValueChange } : {}),\n });\n const [values, setValues] = React.useState<readonly string[]>([]);\n const register = React.useCallback((v: string) => {\n setValues((prev) => [...prev, v]);\n return () => setValues((prev) => prev.filter((x) => x !== v));\n }, []);\n // Tabs come and go as workspaces open and close, so the order is read from the DOM at key time.\n const move = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const tabs = Array.from(e.currentTarget.querySelectorAll<HTMLElement>('[role=\"tab\"]'));\n const at = tabs.indexOf(document.activeElement as HTMLElement);\n if (at < 0) return;\n const target =\n e.key === \"ArrowRight\" ? (at + 1) % tabs.length\n : e.key === \"ArrowLeft\" ? (at - 1 + tabs.length) % tabs.length\n : e.key === \"Home\" ? 0\n : e.key === \"End\" ? tabs.length - 1\n : -1;\n if (target < 0) return;\n e.preventDefault();\n tabs[target]?.focus();\n };\n return (\n <WorkspaceTabsContext.Provider value={{ value: active, setValue, values, register }}>\n <div\n role=\"tablist\"\n aria-orientation=\"horizontal\"\n data-slot=\"workspace-tabs\"\n className={cn(WORKSPACE_TABS_BASE, className)}\n onKeyDown={(e) => {\n onKeyDown?.(e);\n if (!e.defaultPrevented) move(e);\n }}\n {...props}\n />\n </WorkspaceTabsContext.Provider>\n );\n}\n\nexport interface WorkspaceTabProps extends Omit<React.ComponentProps<\"button\">, \"value\"> {\n value: string;\n /** Leading glyph; the layers glyph by default. */\n icon?: React.ReactNode;\n /** Adds a close button; Delete and Backspace on the tab close it too. */\n onClose?: () => void;\n /** Names the close button, e.g. \"Close Trading\". */\n closeLabel?: string;\n}\n\nexport function WorkspaceTab({\n value,\n icon,\n onClose,\n closeLabel = copy.WORKSPACE_TAB_CLOSE,\n className,\n children,\n onClick,\n onKeyDown,\n ...props\n}: WorkspaceTabProps) {\n const { value: active, setValue, values, register } = useWorkspaceTabs();\n React.useEffect(() => register(value), [register, value]);\n const selected = active === value;\n // With no selected tab (nothing chosen yet, or the active one was just closed) the first tab\n // takes the tab stop, or the row could not be entered from the keyboard.\n const stop = selected || (!values.includes(active) && values[0] === value);\n return (\n <div\n data-slot=\"workspace-tab\"\n data-state={selected ? \"active\" : \"inactive\"}\n className={cn(\n WORKSPACE_TAB_BASE,\n selected && WORKSPACE_TAB_SELECTED,\n className,\n )}\n >\n <button\n type=\"button\"\n role=\"tab\"\n aria-selected={selected}\n tabIndex={stop ? 0 : -1}\n className={WORKSPACE_TAB_TRIGGER}\n onClick={(e) => {\n onClick?.(e);\n setValue(value);\n }}\n onKeyDown={(e) => {\n onKeyDown?.(e);\n if (onClose && (e.key === \"Delete\" || e.key === \"Backspace\")) {\n e.preventDefault();\n // Hand focus to a neighbour first: the closed tab's button unmounts and focus would fall to <body>.\n const tabs = Array.from(\n e.currentTarget.closest('[role=\"tablist\"]')?.querySelectorAll<HTMLElement>('[role=\"tab\"]') ?? [],\n );\n const at = tabs.indexOf(e.currentTarget);\n (tabs[at + 1] ?? tabs[at - 1])?.focus();\n onClose();\n }\n }}\n {...props}\n >\n {icon ?? <UiIcon name=\"layers\" />}\n <span className={WORKSPACE_TAB_LABEL}>{children}</span>\n </button>\n {onClose ? (\n <button\n type=\"button\"\n aria-label={closeLabel}\n tabIndex={-1}\n onClick={onClose}\n className={WORKSPACE_TAB_CLOSE}\n >\n <UiIcon name=\"x\" />\n </button>\n ) : (\n <span className={WORKSPACE_TAB_SPACER} aria-hidden />\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|