@passui/react 0.1.17 → 0.1.19
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 +102 -1
- package/dist/types/src/appearance/index.d.ts +2 -0
- package/dist/types/src/appearance/platform.d.ts +9 -0
- package/dist/types/src/appearance/theme.d.ts +71 -0
- package/dist/types/src/components/ambient/ambient.d.ts +12 -0
- package/dist/types/src/components/ambient/index.d.ts +1 -0
- package/dist/types/src/components/button/button-styles.d.ts +12 -0
- package/dist/types/src/components/button/button.d.ts +30 -0
- package/dist/types/src/components/button/icon-button.d.ts +10 -0
- package/dist/types/src/components/button/pending-spinner.d.ts +5 -0
- package/dist/types/src/components/button/use-pending-indicator.d.ts +2 -0
- package/dist/types/src/components/chip/chip.d.ts +7 -0
- package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +25 -0
- package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +27 -0
- package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +26 -0
- package/dist/types/src/components/compact-time-picker/time-value.d.ts +18 -0
- package/dist/types/src/components/content-view/content-view.d.ts +48 -0
- package/dist/types/src/components/content-view/index.d.ts +1 -0
- package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +2 -0
- package/dist/types/src/components/context-menu/context-menu-host.d.ts +2 -0
- package/dist/types/src/components/context-menu/context-menu-store.d.ts +57 -0
- package/dist/types/src/components/context-menu/menu-navigation.d.ts +6 -0
- package/dist/types/src/components/context-menu/menu-position.d.ts +21 -0
- package/dist/types/src/components/context-menu/menu-reveal.d.ts +22 -0
- package/dist/types/src/components/context-menu/use-context-menu.d.ts +14 -0
- package/dist/types/src/components/conversation/conversation.d.ts +43 -0
- package/dist/types/src/components/conversation/index.d.ts +1 -0
- package/dist/types/src/components/date-picker/date-picker.d.ts +16 -0
- package/dist/types/src/components/date-picker/date-value.d.ts +2 -0
- package/dist/types/src/components/dialog/dialog-host.d.ts +6 -0
- package/dist/types/src/components/dialog/dialog-store.d.ts +21 -0
- package/dist/types/src/components/dialog/dialog.d.ts +30 -0
- package/dist/types/src/components/dialog/index.d.ts +1 -0
- package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +13 -0
- package/dist/types/src/components/divider/divider.d.ts +9 -0
- package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +15 -0
- package/dist/types/src/components/labeled-content/labeled-content.d.ts +19 -0
- package/dist/types/src/components/locale-switcher/index.d.ts +1 -0
- package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +10 -0
- package/dist/types/src/components/menu/menu.d.ts +16 -0
- package/dist/types/src/components/picker/picker-trigger.d.ts +2 -0
- package/dist/types/src/components/picker/picker.d.ts +37 -0
- package/dist/types/src/components/popover/popover-fit.d.ts +21 -0
- package/dist/types/src/components/popover/popover.d.ts +14 -0
- package/dist/types/src/components/profile-image/profile-image.d.ts +4 -0
- package/dist/types/src/components/progress-view/progress-view.d.ts +13 -0
- package/dist/types/src/components/search-field/search-field.d.ts +2 -0
- package/dist/types/src/components/search-list/search-list.d.ts +19 -0
- package/dist/types/src/components/section/section.d.ts +15 -0
- package/dist/types/src/components/secure-field/secure-field.d.ts +4 -0
- package/dist/types/src/components/segmented-control/segmented-control.d.ts +20 -0
- package/dist/types/src/components/sheet/modal-environment.d.ts +2 -0
- package/dist/types/src/components/sheet/sheet-portal.d.ts +5 -0
- package/dist/types/src/components/sheet/sheet.d.ts +21 -0
- package/dist/types/src/components/sheet/use-sheet-focus.d.ts +3 -0
- package/dist/types/src/components/sidebar/sidebar.d.ts +18 -0
- package/dist/types/src/components/slider/slider.d.ts +14 -0
- package/dist/types/src/components/stat-tile/index.d.ts +1 -0
- package/dist/types/src/components/stat-tile/stat-tile.d.ts +15 -0
- package/dist/types/src/components/status-indicator/status-indicator.d.ts +14 -0
- package/dist/types/src/components/stepper/stepper.d.ts +19 -0
- package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +17 -0
- package/dist/types/src/components/tab-bar/tab-bar.d.ts +40 -0
- package/dist/types/src/components/tab-view/tab-view.d.ts +24 -0
- package/dist/types/src/components/table/table.d.ts +10 -0
- package/dist/types/src/components/text-editor/text-editor.d.ts +2 -0
- package/dist/types/src/components/text-field/text-field.d.ts +18 -0
- package/dist/types/src/components/toast/toast-store.d.ts +47 -0
- package/dist/types/src/components/toast/toaster.d.ts +10 -0
- package/dist/types/src/components/toggle/toggle.d.ts +17 -0
- package/dist/types/src/components/tooltip/tooltip-host.d.ts +6 -0
- package/dist/types/src/components/view-controller/index.d.ts +1 -0
- package/dist/types/src/components/view-controller/view-controller.d.ts +21 -0
- package/dist/types/src/hooks/scroll/minimize-decision.d.ts +2 -0
- package/dist/types/src/hooks/use-anchored-placement.d.ts +7 -0
- package/dist/types/src/hooks/use-dismiss.d.ts +9 -0
- package/dist/types/src/hooks/use-floating-dismiss.d.ts +3 -0
- package/dist/types/src/hooks/use-media-query.d.ts +21 -0
- package/dist/types/src/hooks/use-minimize-on-scroll.d.ts +6 -0
- package/dist/types/src/hooks/use-visual-viewport.d.ts +4 -0
- package/dist/types/src/hooks/viewport/types.d.ts +19 -0
- package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +3 -0
- package/dist/types/src/icons/icons.d.ts +612 -0
- package/dist/types/src/index.d.ts +58 -0
- package/dist/types/src/lib/anchored-placement.d.ts +39 -0
- package/dist/types/src/lib/class-names.d.ts +2 -0
- package/dist/types/src/lib/clipboard.d.ts +6 -0
- package/dist/types/src/lib/date.d.ts +50 -0
- package/dist/types/src/lib/floating-layers.d.ts +8 -0
- package/dist/types/src/lib/haptics.d.ts +8 -0
- package/dist/types/src/lib/language.d.ts +4 -0
- package/dist/types/src/lib/range-value.d.ts +4 -0
- package/dist/types/src/lib/screen-edges.d.ts +12 -0
- package/dist/types/src/lib/shapes.d.ts +17 -0
- package/dist/types/src/motion/transitions.d.ts +97 -0
- package/dist/types/src/tokens.d.ts +1 -0
- package/package.json +192 -40
- package/src/appearance/platform.tsx +10 -47
- package/src/appearance/theme.tsx +42 -142
- package/src/components/ambient/ambient.tsx +2 -10
- package/src/components/button/button-styles.ts +13 -31
- package/src/components/button/button.tsx +19 -14
- package/src/components/button/icon-button.tsx +14 -56
- package/src/components/button/use-pending-indicator.ts +2 -7
- package/src/components/chip/chip.tsx +8 -13
- package/src/components/compact-date-picker/calendar-month.ts +13 -57
- package/src/components/compact-date-picker/compact-date-picker.tsx +44 -123
- package/src/components/compact-time-picker/compact-time-picker.tsx +46 -130
- package/src/components/compact-time-picker/time-value.ts +4 -16
- package/src/components/content-view/content-view.tsx +13 -56
- package/src/components/context-menu/conceal-menu-source.ts +1 -4
- package/src/components/context-menu/context-menu-host.tsx +125 -195
- package/src/components/context-menu/context-menu-store.ts +3 -11
- package/src/components/context-menu/menu-navigation.ts +29 -0
- package/src/components/context-menu/menu-position.ts +6 -27
- package/src/components/context-menu/menu-reveal.ts +13 -54
- package/src/components/context-menu/use-context-menu.ts +6 -30
- package/src/components/conversation/conversation.tsx +26 -72
- package/src/components/date-picker/date-picker.tsx +8 -37
- package/src/components/date-picker/date-value.ts +5 -30
- package/src/components/dialog/dialog-host.tsx +31 -76
- package/src/components/dialog/dialog-store.ts +1 -3
- package/src/components/dialog/dialog.tsx +23 -80
- package/src/components/disclosure-group/disclosure-group.tsx +70 -0
- package/src/components/divider/divider.tsx +31 -0
- package/src/components/inline-disclosure/inline-disclosure.tsx +49 -0
- package/src/components/labeled-content/labeled-content.tsx +24 -18
- package/src/components/locale-switcher/locale-switcher.tsx +20 -70
- package/src/components/menu/menu.tsx +68 -0
- package/src/components/picker/picker-trigger.ts +10 -0
- package/src/components/picker/picker.tsx +72 -203
- package/src/components/popover/popover-fit.ts +69 -0
- package/src/components/popover/popover.tsx +94 -77
- package/src/components/profile-image/profile-image.tsx +6 -28
- package/src/components/progress-view/progress-view.tsx +65 -0
- package/src/components/search-field/search-field.tsx +27 -25
- package/src/components/search-list/search-list.tsx +43 -69
- package/src/components/section/section.tsx +18 -17
- package/src/components/secure-field/secure-field.tsx +5 -7
- package/src/components/segmented-control/segmented-control.tsx +20 -29
- package/src/components/sheet/modal-environment.ts +16 -54
- package/src/components/sheet/sheet-portal.tsx +10 -42
- package/src/components/sheet/sheet.tsx +17 -25
- package/src/components/sheet/use-sheet-focus.ts +15 -51
- package/src/components/sidebar/sidebar.tsx +27 -30
- package/src/components/slider/slider.tsx +76 -0
- package/src/components/stat-tile/stat-tile.tsx +9 -30
- package/src/components/status-indicator/status-indicator.tsx +12 -19
- package/src/components/stepper/stepper.tsx +80 -0
- package/src/components/swatch-picker/swatch-picker.tsx +19 -15
- package/src/components/tab-bar/tab-bar.tsx +59 -59
- package/src/components/tab-view/tab-view.tsx +52 -57
- package/src/components/table/table.tsx +14 -62
- package/src/components/text-editor/text-editor.tsx +2 -12
- package/src/components/text-field/text-field.tsx +11 -40
- package/src/components/toast/toast-store.ts +9 -30
- package/src/components/toast/toaster.tsx +90 -104
- package/src/components/toggle/toggle.tsx +28 -24
- package/src/components/tooltip/tooltip-host.tsx +70 -67
- package/src/components/view-controller/view-controller.tsx +4 -21
- package/src/hooks/scroll/minimize-decision.ts +1 -5
- package/src/hooks/use-anchored-placement.ts +4 -14
- package/src/hooks/use-dismiss.ts +5 -23
- package/src/hooks/use-floating-dismiss.ts +28 -0
- package/src/hooks/use-media-query.ts +12 -31
- package/src/hooks/use-minimize-on-scroll.ts +10 -34
- package/src/hooks/use-visual-viewport.ts +5 -14
- package/src/hooks/viewport/viewport-metrics.ts +4 -16
- package/src/icons/icons.tsx +167 -121
- package/src/index.ts +9 -1
- package/src/lib/anchored-placement.ts +5 -15
- package/src/lib/class-names.ts +1 -2
- package/src/lib/clipboard.ts +14 -0
- package/src/lib/date.ts +4 -15
- package/src/lib/floating-layers.ts +18 -8
- package/src/lib/haptics.ts +1 -3
- package/src/lib/language.ts +2 -7
- package/src/lib/range-value.ts +32 -0
- package/src/lib/screen-edges.ts +2 -6
- package/src/lib/shapes.ts +5 -20
- package/src/motion/transitions.ts +18 -12
- package/src/components/ambient/ambient.docs.tsx +0 -68
- package/src/components/ambient/examples/ambient-images.tsx +0 -30
- package/src/components/ambient/examples/ambient-now-playing.tsx +0 -55
- package/src/components/ambient/examples/ambient-showcase.tsx +0 -33
- package/src/components/ambient/examples/ambient-usage.tsx +0 -19
- package/src/components/button/button.docs.tsx +0 -116
- package/src/components/button/examples/button-disabled.tsx +0 -19
- package/src/components/button/examples/button-icon.tsx +0 -39
- package/src/components/button/examples/button-link.tsx +0 -12
- package/src/components/button/examples/button-pending.tsx +0 -27
- package/src/components/button/examples/button-showcase.tsx +0 -115
- package/src/components/button/examples/button-sizes.tsx +0 -12
- package/src/components/button/examples/button-usage.tsx +0 -12
- package/src/components/button/examples/button-variants.tsx +0 -15
- package/src/components/button/examples/button-with-icon.tsx +0 -32
- package/src/components/button/examples/icon-button-player.tsx +0 -38
- package/src/components/button/examples/icon-button-showcase.tsx +0 -83
- package/src/components/button/examples/icon-button-usage.tsx +0 -11
- package/src/components/button/examples/icon-button-variants.tsx +0 -39
- package/src/components/button/icon-button.docs.tsx +0 -68
- package/src/components/chip/chip.docs.tsx +0 -37
- package/src/components/chip/examples/chip-in-rows.tsx +0 -19
- package/src/components/chip/examples/chip-showcase.tsx +0 -51
- package/src/components/chip/examples/chip-tones.tsx +0 -13
- package/src/components/chip/examples/chip-usage.tsx +0 -5
- package/src/components/compact-date-picker/compact-date-picker.docs.tsx +0 -81
- package/src/components/compact-date-picker/examples/compact-date-picker-showcase.tsx +0 -35
- package/src/components/compact-date-picker/examples/compact-date-picker-usage.tsx +0 -22
- package/src/components/compact-time-picker/compact-time-picker.docs.tsx +0 -80
- package/src/components/compact-time-picker/examples/compact-time-picker-showcase.tsx +0 -31
- package/src/components/compact-time-picker/examples/compact-time-picker-usage.tsx +0 -21
- package/src/components/content-view/content-view.docs.tsx +0 -61
- package/src/components/content-view/examples/content-view-header-action.tsx +0 -33
- package/src/components/content-view/examples/content-view-showcase.tsx +0 -65
- package/src/components/content-view/examples/content-view-stats.tsx +0 -35
- package/src/components/content-view/examples/content-view-usage.tsx +0 -14
- package/src/components/context-menu/context-menu.docs.tsx +0 -92
- package/src/components/context-menu/examples/context-menu-checked.tsx +0 -37
- package/src/components/context-menu/examples/context-menu-list.tsx +0 -85
- package/src/components/context-menu/examples/context-menu-showcase.tsx +0 -56
- package/src/components/context-menu/examples/context-menu-toolbar.tsx +0 -63
- package/src/components/context-menu/examples/context-menu-usage.tsx +0 -24
- package/src/components/conversation/conversation.docs.tsx +0 -88
- package/src/components/conversation/examples/conversation-composer.tsx +0 -36
- package/src/components/conversation/examples/conversation-days.tsx +0 -48
- package/src/components/conversation/examples/conversation-showcase.tsx +0 -71
- package/src/components/conversation/examples/conversation-usage.tsx +0 -28
- package/src/components/date-picker/date-picker.docs.tsx +0 -88
- package/src/components/date-picker/examples/date-picker-locales.tsx +0 -41
- package/src/components/date-picker/examples/date-picker-past-only.tsx +0 -29
- package/src/components/date-picker/examples/date-picker-showcase.tsx +0 -49
- package/src/components/date-picker/examples/date-picker-usage.tsx +0 -22
- package/src/components/dialog/dialog.docs.tsx +0 -114
- package/src/components/dialog/examples/dialog-confirm.tsx +0 -24
- package/src/components/dialog/examples/dialog-form.tsx +0 -46
- package/src/components/dialog/examples/dialog-inline.tsx +0 -48
- package/src/components/dialog/examples/dialog-showcase.tsx +0 -53
- package/src/components/dialog/examples/dialog-usage.tsx +0 -31
- package/src/components/labeled-content/examples/labeled-content-descriptions.tsx +0 -37
- package/src/components/labeled-content/examples/labeled-content-showcase.tsx +0 -54
- package/src/components/labeled-content/examples/labeled-content-usage.tsx +0 -22
- package/src/components/labeled-content/examples/labeled-content-values.tsx +0 -26
- package/src/components/labeled-content/examples/labeled-content-wide.tsx +0 -46
- package/src/components/labeled-content/labeled-content.docs.tsx +0 -69
- package/src/components/locale-switcher/examples/locale-switcher-native-names.tsx +0 -30
- package/src/components/locale-switcher/examples/locale-switcher-showcase.tsx +0 -46
- package/src/components/locale-switcher/examples/locale-switcher-translated-page.tsx +0 -35
- package/src/components/locale-switcher/examples/locale-switcher-usage.tsx +0 -20
- package/src/components/locale-switcher/locale-switcher.docs.tsx +0 -91
- package/src/components/picker/examples/picker-details.tsx +0 -44
- package/src/components/picker/examples/picker-searchable.tsx +0 -48
- package/src/components/picker/examples/picker-showcase.tsx +0 -66
- package/src/components/picker/examples/picker-usage.tsx +0 -20
- package/src/components/picker/picker.docs.tsx +0 -68
- package/src/components/popover/examples/popover-help.tsx +0 -57
- package/src/components/popover/examples/popover-menu.tsx +0 -51
- package/src/components/popover/examples/popover-showcase.tsx +0 -61
- package/src/components/popover/examples/popover-usage.tsx +0 -31
- package/src/components/popover/popover.docs.tsx +0 -84
- package/src/components/profile-image/examples/profile-image-fallbacks.tsx +0 -29
- package/src/components/profile-image/examples/profile-image-group.tsx +0 -34
- package/src/components/profile-image/examples/profile-image-showcase.tsx +0 -30
- package/src/components/profile-image/examples/profile-image-usage.tsx +0 -14
- package/src/components/profile-image/profile-image.docs.tsx +0 -81
- package/src/components/search-field/examples/search-field-filter.tsx +0 -53
- package/src/components/search-field/examples/search-field-showcase.tsx +0 -56
- package/src/components/search-field/examples/search-field-toolbar.tsx +0 -27
- package/src/components/search-field/examples/search-field-usage.tsx +0 -18
- package/src/components/search-field/search-field.docs.tsx +0 -58
- package/src/components/search-list/examples/search-list-dropdown.tsx +0 -53
- package/src/components/search-list/examples/search-list-groups.tsx +0 -64
- package/src/components/search-list/examples/search-list-showcase.tsx +0 -67
- package/src/components/search-list/examples/search-list-usage.tsx +0 -27
- package/src/components/search-list/search-list.docs.tsx +0 -87
- package/src/components/section/examples/section-actions.tsx +0 -35
- package/src/components/section/examples/section-groups.tsx +0 -41
- package/src/components/section/examples/section-showcase.tsx +0 -63
- package/src/components/section/examples/section-usage.tsx +0 -19
- package/src/components/section/section.docs.tsx +0 -51
- package/src/components/secure-field/examples/secure-field-new-password.tsx +0 -56
- package/src/components/secure-field/examples/secure-field-reveal.tsx +0 -20
- package/src/components/secure-field/examples/secure-field-showcase.tsx +0 -62
- package/src/components/secure-field/examples/secure-field-usage.tsx +0 -19
- package/src/components/secure-field/secure-field.docs.tsx +0 -72
- package/src/components/segmented-control/examples/segmented-control-overflow.tsx +0 -28
- package/src/components/segmented-control/examples/segmented-control-showcase.tsx +0 -59
- package/src/components/segmented-control/examples/segmented-control-usage.tsx +0 -20
- package/src/components/segmented-control/examples/segmented-control-views.tsx +0 -32
- package/src/components/segmented-control/segmented-control.docs.tsx +0 -61
- package/src/components/sheet/examples/sheet-choices.tsx +0 -58
- package/src/components/sheet/examples/sheet-share.tsx +0 -51
- package/src/components/sheet/examples/sheet-showcase.tsx +0 -74
- package/src/components/sheet/examples/sheet-usage.tsx +0 -32
- package/src/components/sheet/sheet.docs.tsx +0 -75
- package/src/components/sidebar/examples/sidebar-groups.tsx +0 -133
- package/src/components/sidebar/examples/sidebar-showcase.tsx +0 -123
- package/src/components/sidebar/examples/sidebar-unread.tsx +0 -66
- package/src/components/sidebar/examples/sidebar-usage.tsx +0 -52
- package/src/components/sidebar/sidebar.docs.tsx +0 -135
- package/src/components/stat-tile/examples/stat-tile-filters.tsx +0 -32
- package/src/components/stat-tile/examples/stat-tile-grid.tsx +0 -21
- package/src/components/stat-tile/examples/stat-tile-showcase.tsx +0 -52
- package/src/components/stat-tile/examples/stat-tile-usage.tsx +0 -13
- package/src/components/stat-tile/stat-tile.docs.tsx +0 -60
- package/src/components/status-indicator/examples/status-indicator-live.tsx +0 -34
- package/src/components/status-indicator/examples/status-indicator-showcase.tsx +0 -39
- package/src/components/status-indicator/examples/status-indicator-states.tsx +0 -17
- package/src/components/status-indicator/examples/status-indicator-usage.tsx +0 -9
- package/src/components/status-indicator/status-indicator.docs.tsx +0 -43
- package/src/components/swatch-picker/examples/swatch-picker-accents.tsx +0 -42
- package/src/components/swatch-picker/examples/swatch-picker-labels.tsx +0 -45
- package/src/components/swatch-picker/examples/swatch-picker-showcase.tsx +0 -70
- package/src/components/swatch-picker/examples/swatch-picker-usage.tsx +0 -39
- package/src/components/swatch-picker/swatch-picker.docs.tsx +0 -60
- package/src/components/tab-bar/examples/tab-bar-five-tabs.tsx +0 -66
- package/src/components/tab-bar/examples/tab-bar-minimize.tsx +0 -71
- package/src/components/tab-bar/examples/tab-bar-showcase.tsx +0 -82
- package/src/components/tab-bar/examples/tab-bar-usage.tsx +0 -54
- package/src/components/tab-bar/tab-bar.docs.tsx +0 -136
- package/src/components/tab-view/examples/tab-view-keyboard.tsx +0 -39
- package/src/components/tab-view/examples/tab-view-settings.tsx +0 -56
- package/src/components/tab-view/examples/tab-view-showcase.tsx +0 -53
- package/src/components/tab-view/examples/tab-view-usage.tsx +0 -23
- package/src/components/tab-view/tab-view.docs.tsx +0 -77
- package/src/components/table/examples/table-empty.tsx +0 -53
- package/src/components/table/examples/table-invoices.tsx +0 -102
- package/src/components/table/examples/table-selection.tsx +0 -150
- package/src/components/table/examples/table-showcase.tsx +0 -115
- package/src/components/table/examples/table-usage.tsx +0 -67
- package/src/components/table/examples/table-wide.tsx +0 -75
- package/src/components/table/table.docs.tsx +0 -131
- package/src/components/text-editor/examples/text-editor-comment.tsx +0 -48
- package/src/components/text-editor/examples/text-editor-count.tsx +0 -38
- package/src/components/text-editor/examples/text-editor-showcase.tsx +0 -58
- package/src/components/text-editor/examples/text-editor-usage.tsx +0 -25
- package/src/components/text-editor/text-editor.docs.tsx +0 -61
- package/src/components/text-field/examples/text-field-icons.tsx +0 -72
- package/src/components/text-field/examples/text-field-showcase.tsx +0 -50
- package/src/components/text-field/examples/text-field-usage.tsx +0 -18
- package/src/components/text-field/examples/text-field-validation.tsx +0 -27
- package/src/components/text-field/text-field.docs.tsx +0 -118
- package/src/components/toast/examples/toast-action.tsx +0 -32
- package/src/components/toast/examples/toast-promise.tsx +0 -45
- package/src/components/toast/examples/toast-showcase.tsx +0 -49
- package/src/components/toast/examples/toast-usage.tsx +0 -13
- package/src/components/toast/toast.docs.tsx +0 -79
- package/src/components/toggle/examples/toggle-checkboxes.tsx +0 -43
- package/src/components/toggle/examples/toggle-settings.tsx +0 -31
- package/src/components/toggle/examples/toggle-showcase.tsx +0 -59
- package/src/components/toggle/examples/toggle-usage.tsx +0 -13
- package/src/components/toggle/toggle.docs.tsx +0 -69
- package/src/components/tooltip/examples/tooltip-icon-buttons.tsx +0 -27
- package/src/components/tooltip/examples/tooltip-shortcuts.tsx +0 -38
- package/src/components/tooltip/examples/tooltip-showcase.tsx +0 -44
- package/src/components/tooltip/examples/tooltip-usage.tsx +0 -13
- package/src/components/tooltip/tooltip.docs.tsx +0 -56
- package/src/components/view-controller/examples/view-controller-action.tsx +0 -27
- package/src/components/view-controller/examples/view-controller-settings.tsx +0 -31
- package/src/components/view-controller/examples/view-controller-showcase.tsx +0 -45
- package/src/components/view-controller/examples/view-controller-usage.tsx +0 -19
- package/src/components/view-controller/view-controller.docs.tsx +0 -71
- package/src/docs/index.ts +0 -3
- package/src/docs/registry.ts +0 -113
- package/src/docs/snippet.ts +0 -17
- package/src/docs/types.ts +0 -180
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { useId, type HTMLAttributes, type ReactNode } from "react"
|
|
2
|
+
import { cn } from "../../lib/class-names"
|
|
3
|
+
|
|
4
|
+
export interface SectionProps extends HTMLAttributes<HTMLElement> {
|
|
5
|
+
/** Optional group heading and accessible name. */
|
|
6
|
+
title?: string
|
|
7
|
+
/** Supporting text below the grouped rows. */
|
|
8
|
+
footer?: ReactNode
|
|
9
|
+
/** Rows, typically LabeledContent. */
|
|
10
|
+
children?: ReactNode
|
|
11
|
+
}
|
|
2
12
|
|
|
3
13
|
/**
|
|
4
14
|
* A titled, inset group of rows with an optional footer, as in iOS Settings
|
|
5
15
|
* and SwiftUI's grouped `List` with `Section(header:footer:)`. Rows are
|
|
6
16
|
* usually `LabeledContent`; dividers between them come for free.
|
|
7
17
|
*/
|
|
8
|
-
export function Section({
|
|
9
|
-
|
|
10
|
-
footer,
|
|
11
|
-
children,
|
|
12
|
-
}: {
|
|
13
|
-
/** iOS groups can stand without a header. */
|
|
14
|
-
title?: string
|
|
15
|
-
footer?: ReactNode
|
|
16
|
-
children?: ReactNode
|
|
17
|
-
}) {
|
|
18
|
+
export function Section({ title, footer, children, className, ...props }: SectionProps) {
|
|
19
|
+
const headingId = useId()
|
|
18
20
|
return (
|
|
19
21
|
<section
|
|
20
|
-
aria-
|
|
21
|
-
className="flex flex-col gap-2"
|
|
22
|
+
aria-labelledby={title ? headingId : undefined}
|
|
23
|
+
className={cn("flex flex-col gap-2", className)}
|
|
24
|
+
{...props}
|
|
22
25
|
>
|
|
23
26
|
{title && (
|
|
24
|
-
<h2 className="px-4 text-footnote font-medium text-label-tertiary">
|
|
27
|
+
<h2 id={headingId} className="px-4 text-footnote font-medium text-label-tertiary">
|
|
25
28
|
{title}
|
|
26
29
|
</h2>
|
|
27
30
|
)}
|
|
@@ -32,9 +35,7 @@ export function Section({
|
|
|
32
35
|
</div>
|
|
33
36
|
) : null}
|
|
34
37
|
{footer && (
|
|
35
|
-
<
|
|
36
|
-
{footer}
|
|
37
|
-
</p>
|
|
38
|
+
<div className="px-4 text-caption leading-snug text-label-tertiary">{footer}</div>
|
|
38
39
|
)}
|
|
39
40
|
</section>
|
|
40
41
|
)
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
TextField,
|
|
3
|
-
type TextFieldProps,
|
|
4
|
-
} from "../text-field/text-field"
|
|
1
|
+
import { TextField, type TextFieldProps } from "../text-field/text-field"
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
/** TextField's native input props, with the password type managed by SecureField. */
|
|
4
|
+
export type SecureFieldProps = Omit<TextFieldProps, "type">
|
|
5
|
+
|
|
6
|
+
export function SecureField(props: SecureFieldProps) {
|
|
9
7
|
return <TextField {...props} type="password" />
|
|
10
8
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import { motion } from "motion/react"
|
|
2
|
-
import {
|
|
3
|
-
useId,
|
|
4
|
-
useLayoutEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react"
|
|
1
|
+
import { motion, useReducedMotion } from "motion/react"
|
|
2
|
+
import { useId, useLayoutEffect, useRef, useState } from "react"
|
|
8
3
|
import { cn } from "../../lib/class-names"
|
|
9
4
|
import { haptic } from "../../lib/haptics"
|
|
10
5
|
import { spring } from "../../motion/transitions"
|
|
11
6
|
import { Picker } from "../picker/picker"
|
|
12
7
|
|
|
8
|
+
export interface SegmentedControlProps<T extends string> {
|
|
9
|
+
/** Value of the selected segment. */
|
|
10
|
+
value: T
|
|
11
|
+
/** The choices, in display order. */
|
|
12
|
+
options: ReadonlyArray<{ value: T; label: string }>
|
|
13
|
+
/** Called with the selected segment's value. */
|
|
14
|
+
onChange: (value: NoInfer<T>) => void
|
|
15
|
+
/** Accessible name for the group and its compact picker. */
|
|
16
|
+
label: string
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
/**
|
|
14
20
|
* Mutually exclusive choices with a sliding selection, as on Apple
|
|
15
21
|
* platforms. When the labels can't all fit the space it is given (a long
|
|
@@ -21,13 +27,9 @@ export function SegmentedControl<T extends string>({
|
|
|
21
27
|
options,
|
|
22
28
|
onChange,
|
|
23
29
|
label,
|
|
24
|
-
}: {
|
|
25
|
-
value: T
|
|
26
|
-
options: Array<{ value: T; label: string }>
|
|
27
|
-
onChange: (value: T) => void
|
|
28
|
-
label: string
|
|
29
|
-
}) {
|
|
30
|
+
}: SegmentedControlProps<T>) {
|
|
30
31
|
const id = useId()
|
|
32
|
+
const reducedMotion = useReducedMotion()
|
|
31
33
|
const frame = useRef<HTMLDivElement>(null)
|
|
32
34
|
const measure = useRef<HTMLDivElement>(null)
|
|
33
35
|
const [fits, setFits] = useState(true)
|
|
@@ -36,10 +38,7 @@ export function SegmentedControl<T extends string>({
|
|
|
36
38
|
const box = frame.current
|
|
37
39
|
const natural = measure.current
|
|
38
40
|
if (!box || !natural) return
|
|
39
|
-
const check = () =>
|
|
40
|
-
setFits(
|
|
41
|
-
natural.offsetWidth <= box.clientWidth + 0.5
|
|
42
|
-
)
|
|
41
|
+
const check = () => setFits(natural.offsetWidth <= box.clientWidth + 0.5)
|
|
43
42
|
check()
|
|
44
43
|
const observer = new ResizeObserver(check)
|
|
45
44
|
observer.observe(box)
|
|
@@ -56,22 +55,16 @@ export function SegmentedControl<T extends string>({
|
|
|
56
55
|
className="pointer-events-none invisible absolute top-0 flex w-max p-[3px] text-footnote font-semibold"
|
|
57
56
|
>
|
|
58
57
|
{options.map((option) => (
|
|
59
|
-
<span
|
|
60
|
-
key={option.value}
|
|
61
|
-
className="min-w-[64px] px-3 py-1 whitespace-nowrap"
|
|
62
|
-
>
|
|
58
|
+
<span key={option.value} className="min-w-[64px] px-3 py-1 whitespace-nowrap">
|
|
63
59
|
{option.label}
|
|
64
60
|
</span>
|
|
65
61
|
))}
|
|
66
62
|
</div>
|
|
67
63
|
{fits ? (
|
|
68
64
|
<fieldset className="flex w-full rounded-lg bg-fill p-[3px] shadow-[inset_0_1px_2px_rgb(40_30_0/0.06)]">
|
|
69
|
-
<legend className="sr-only">
|
|
70
|
-
{label}
|
|
71
|
-
</legend>
|
|
65
|
+
<legend className="sr-only">{label}</legend>
|
|
72
66
|
{options.map((option) => {
|
|
73
|
-
const selected =
|
|
74
|
-
option.value === value
|
|
67
|
+
const selected = option.value === value
|
|
75
68
|
return (
|
|
76
69
|
<label
|
|
77
70
|
key={option.value}
|
|
@@ -97,9 +90,7 @@ export function SegmentedControl<T extends string>({
|
|
|
97
90
|
<motion.span
|
|
98
91
|
layoutId={`segment-${id}`}
|
|
99
92
|
className="absolute inset-0 -z-10 rounded-md bg-elevated shadow-[0_0_0_0.5px_rgb(0_0_0/0.06),0_1px_2px_rgb(0_0_0/0.08),0_3px_8px_-2px_rgb(0_0_0/0.10)]"
|
|
100
|
-
transition={
|
|
101
|
-
spring.snappy
|
|
102
|
-
}
|
|
93
|
+
transition={reducedMotion ? { duration: 0 } : spring.snappy}
|
|
103
94
|
/>
|
|
104
95
|
)}
|
|
105
96
|
{option.label}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FLOATING_LAYER,
|
|
3
|
-
ownsFloatingLayer,
|
|
4
|
-
} from "../../lib/floating-layers"
|
|
1
|
+
import { FLOATING_LAYER, ownsFloatingLayer } from "../../lib/floating-layers"
|
|
5
2
|
|
|
6
3
|
const surfaces: HTMLElement[] = []
|
|
7
4
|
const isolated = new Map<HTMLElement, boolean>()
|
|
@@ -9,8 +6,7 @@ let overflow = ""
|
|
|
9
6
|
let overflowPriority = ""
|
|
10
7
|
|
|
11
8
|
function restoreBackground() {
|
|
12
|
-
for (const [element, inert] of isolated)
|
|
13
|
-
element.inert = inert
|
|
9
|
+
for (const [element, inert] of isolated) element.inert = inert
|
|
14
10
|
isolated.clear()
|
|
15
11
|
}
|
|
16
12
|
|
|
@@ -19,11 +15,8 @@ function isolateBackground() {
|
|
|
19
15
|
const surface = surfaces.at(-1)
|
|
20
16
|
if (!surface) return
|
|
21
17
|
const roots = [surface.parentElement ?? surface]
|
|
22
|
-
for (const layer of document.querySelectorAll<HTMLElement>(
|
|
23
|
-
|
|
24
|
-
)) {
|
|
25
|
-
if (ownsFloatingLayer(surface, layer))
|
|
26
|
-
roots.push(layer)
|
|
18
|
+
for (const layer of document.querySelectorAll<HTMLElement>(`[${FLOATING_LAYER}]`)) {
|
|
19
|
+
if (ownsFloatingLayer(surface, layer)) roots.push(layer)
|
|
27
20
|
}
|
|
28
21
|
const visit = (parent: HTMLElement) => {
|
|
29
22
|
for (const child of parent.children) {
|
|
@@ -31,9 +24,7 @@ function isolateBackground() {
|
|
|
31
24
|
if (roots.includes(child)) continue
|
|
32
25
|
if (roots.some((root) => child.contains(root))) {
|
|
33
26
|
visit(child)
|
|
34
|
-
} else if (
|
|
35
|
-
!child.matches("script, style, link")
|
|
36
|
-
) {
|
|
27
|
+
} else if (!child.matches("script, style, link")) {
|
|
37
28
|
isolated.set(child, child.inert)
|
|
38
29
|
child.inert = true
|
|
39
30
|
}
|
|
@@ -43,43 +34,26 @@ function isolateBackground() {
|
|
|
43
34
|
}
|
|
44
35
|
|
|
45
36
|
/** Keeps nested sheets and their portaled controls above an inactive background. */
|
|
46
|
-
export function enterModalEnvironment(
|
|
47
|
-
surface: HTMLElement
|
|
48
|
-
): () => void {
|
|
37
|
+
export function enterModalEnvironment(surface: HTMLElement): () => void {
|
|
49
38
|
if (!surfaces.length) {
|
|
50
|
-
overflow =
|
|
51
|
-
|
|
52
|
-
overflowPriority =
|
|
53
|
-
document.body.style.getPropertyPriority(
|
|
54
|
-
"overflow"
|
|
55
|
-
)
|
|
39
|
+
overflow = document.body.style.getPropertyValue("overflow")
|
|
40
|
+
overflowPriority = document.body.style.getPropertyPriority("overflow")
|
|
56
41
|
document.body.style.setProperty("overflow", "hidden")
|
|
57
42
|
}
|
|
58
43
|
surfaces.push(surface)
|
|
59
44
|
isolateBackground()
|
|
60
|
-
const preventBackgroundScroll = (
|
|
61
|
-
event: WheelEvent | TouchEvent
|
|
62
|
-
) => {
|
|
45
|
+
const preventBackgroundScroll = (event: WheelEvent | TouchEvent) => {
|
|
63
46
|
if (surfaces.at(-1) !== surface) return
|
|
64
47
|
const target = event.target
|
|
65
48
|
if (
|
|
66
49
|
target instanceof Element &&
|
|
67
|
-
(surface.contains(target) ||
|
|
68
|
-
ownsFloatingLayer(surface, target))
|
|
50
|
+
(surface.contains(target) || ownsFloatingLayer(surface, target))
|
|
69
51
|
)
|
|
70
52
|
return
|
|
71
53
|
event.preventDefault()
|
|
72
54
|
}
|
|
73
|
-
document.addEventListener(
|
|
74
|
-
|
|
75
|
-
preventBackgroundScroll,
|
|
76
|
-
{ passive: false }
|
|
77
|
-
)
|
|
78
|
-
document.addEventListener(
|
|
79
|
-
"touchmove",
|
|
80
|
-
preventBackgroundScroll,
|
|
81
|
-
{ passive: false }
|
|
82
|
-
)
|
|
55
|
+
document.addEventListener("wheel", preventBackgroundScroll, { passive: false })
|
|
56
|
+
document.addEventListener("touchmove", preventBackgroundScroll, { passive: false })
|
|
83
57
|
const observer = new MutationObserver(() => {
|
|
84
58
|
if (surfaces.at(-1) === surface) isolateBackground()
|
|
85
59
|
})
|
|
@@ -89,25 +63,13 @@ export function enterModalEnvironment(
|
|
|
89
63
|
})
|
|
90
64
|
return () => {
|
|
91
65
|
observer.disconnect()
|
|
92
|
-
document.removeEventListener(
|
|
93
|
-
|
|
94
|
-
preventBackgroundScroll
|
|
95
|
-
)
|
|
96
|
-
document.removeEventListener(
|
|
97
|
-
"touchmove",
|
|
98
|
-
preventBackgroundScroll
|
|
99
|
-
)
|
|
66
|
+
document.removeEventListener("wheel", preventBackgroundScroll)
|
|
67
|
+
document.removeEventListener("touchmove", preventBackgroundScroll)
|
|
100
68
|
surfaces.splice(surfaces.indexOf(surface), 1)
|
|
101
69
|
isolateBackground()
|
|
102
70
|
if (!surfaces.length) {
|
|
103
|
-
if (overflow)
|
|
104
|
-
|
|
105
|
-
"overflow",
|
|
106
|
-
overflow,
|
|
107
|
-
overflowPriority
|
|
108
|
-
)
|
|
109
|
-
else
|
|
110
|
-
document.body.style.removeProperty("overflow")
|
|
71
|
+
if (overflow) document.body.style.setProperty("overflow", overflow, overflowPriority)
|
|
72
|
+
else document.body.style.removeProperty("overflow")
|
|
111
73
|
}
|
|
112
74
|
}
|
|
113
75
|
}
|
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ReactNode,
|
|
3
|
-
useLayoutEffect,
|
|
4
|
-
useRef,
|
|
5
|
-
useState,
|
|
6
|
-
} from "react"
|
|
1
|
+
import { type ReactNode, useLayoutEffect, useRef, useState } from "react"
|
|
7
2
|
import { createPortal } from "react-dom"
|
|
8
3
|
|
|
9
4
|
/** Escape transformed page layers while retaining the source's scoped appearance. */
|
|
10
|
-
export function SheetPortal({
|
|
11
|
-
children,
|
|
12
|
-
}: {
|
|
13
|
-
children: ReactNode
|
|
14
|
-
}) {
|
|
5
|
+
export function SheetPortal({ children }: { children: ReactNode }) {
|
|
15
6
|
const source = useRef<HTMLSpanElement>(null)
|
|
16
|
-
const [host, setHost] = useState<HTMLDivElement | null>(
|
|
17
|
-
null
|
|
18
|
-
)
|
|
7
|
+
const [host, setHost] = useState<HTMLDivElement | null>(null)
|
|
19
8
|
useLayoutEffect(() => {
|
|
20
9
|
const marker = source.current
|
|
21
10
|
if (!marker) return
|
|
@@ -23,20 +12,12 @@ export function SheetPortal({
|
|
|
23
12
|
const layer = document.createElement("div")
|
|
24
13
|
layer.dataset.passuiOverlay = ""
|
|
25
14
|
layer.style.display = "contents"
|
|
26
|
-
const attributes = [
|
|
27
|
-
"data-theme",
|
|
28
|
-
"data-accent",
|
|
29
|
-
"data-os",
|
|
30
|
-
"dir",
|
|
31
|
-
]
|
|
15
|
+
const attributes = ["data-theme", "data-accent", "data-os", "dir"]
|
|
32
16
|
let properties = new Set<string>()
|
|
33
17
|
const inherit = () => {
|
|
34
18
|
for (const name of attributes) {
|
|
35
|
-
const value = marker
|
|
36
|
-
|
|
37
|
-
?.getAttribute(name)
|
|
38
|
-
if (value === null || value === undefined)
|
|
39
|
-
layer.removeAttribute(name)
|
|
19
|
+
const value = marker.closest(`[${name}]`)?.getAttribute(name)
|
|
20
|
+
if (value === null || value === undefined) layer.removeAttribute(name)
|
|
40
21
|
else layer.setAttribute(name, value)
|
|
41
22
|
}
|
|
42
23
|
const computed = getComputedStyle(marker)
|
|
@@ -44,14 +25,9 @@ export function SheetPortal({
|
|
|
44
25
|
for (const name of computed) {
|
|
45
26
|
if (!name.startsWith("--")) continue
|
|
46
27
|
next.add(name)
|
|
47
|
-
layer.style.setProperty(
|
|
48
|
-
name,
|
|
49
|
-
computed.getPropertyValue(name)
|
|
50
|
-
)
|
|
28
|
+
layer.style.setProperty(name, computed.getPropertyValue(name))
|
|
51
29
|
}
|
|
52
|
-
for (const name of properties)
|
|
53
|
-
if (!next.has(name))
|
|
54
|
-
layer.style.removeProperty(name)
|
|
30
|
+
for (const name of properties) if (!next.has(name)) layer.style.removeProperty(name)
|
|
55
31
|
properties = next
|
|
56
32
|
layer.style.colorScheme = computed.colorScheme
|
|
57
33
|
layer.style.fontFamily = computed.fontFamily
|
|
@@ -61,18 +37,10 @@ export function SheetPortal({
|
|
|
61
37
|
document.body.appendChild(layer)
|
|
62
38
|
setHost(layer)
|
|
63
39
|
const observer = new MutationObserver(inherit)
|
|
64
|
-
for (
|
|
65
|
-
let ancestor = marker.parentElement;
|
|
66
|
-
ancestor;
|
|
67
|
-
ancestor = ancestor.parentElement
|
|
68
|
-
) {
|
|
40
|
+
for (let ancestor = marker.parentElement; ancestor; ancestor = ancestor.parentElement) {
|
|
69
41
|
observer.observe(ancestor, {
|
|
70
42
|
attributes: true,
|
|
71
|
-
attributeFilter: [
|
|
72
|
-
...attributes,
|
|
73
|
-
"style",
|
|
74
|
-
"class",
|
|
75
|
-
],
|
|
43
|
+
attributeFilter: [...attributes, "style", "class"],
|
|
76
44
|
})
|
|
77
45
|
}
|
|
78
46
|
return () => {
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AnimatePresence,
|
|
3
|
-
motion,
|
|
4
|
-
useReducedMotion,
|
|
5
|
-
} from "motion/react"
|
|
1
|
+
import { AnimatePresence, motion, useReducedMotion } from "motion/react"
|
|
6
2
|
import { type ReactNode, useRef } from "react"
|
|
7
3
|
import { useVisualViewport } from "../../hooks/use-visual-viewport"
|
|
8
4
|
import { cn } from "../../lib/class-names"
|
|
@@ -10,12 +6,19 @@ import { spring } from "../../motion/transitions"
|
|
|
10
6
|
import { SheetPortal } from "./sheet-portal"
|
|
11
7
|
import { useSheetFocus } from "./use-sheet-focus"
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
export type SheetPlacement = "adaptive" | "center"
|
|
10
|
+
|
|
11
|
+
export interface SheetProps {
|
|
12
|
+
/** Controls whether the sheet is presented. */
|
|
14
13
|
open: boolean
|
|
14
|
+
/** Called on Escape or an outside press. */
|
|
15
15
|
onClose: () => void
|
|
16
16
|
/** Read out by screen readers as the sheet's name. */
|
|
17
17
|
label: string
|
|
18
|
+
/** ID of a visible heading to use instead of label for the accessible name. */
|
|
18
19
|
labelledBy?: string
|
|
20
|
+
/** `adaptive` rises from the bottom on phones; `center` always floats. @default "adaptive" */
|
|
21
|
+
placement?: SheetPlacement
|
|
19
22
|
className?: string
|
|
20
23
|
children: ReactNode
|
|
21
24
|
}
|
|
@@ -40,6 +43,7 @@ function OpenSheet({
|
|
|
40
43
|
onClose,
|
|
41
44
|
label,
|
|
42
45
|
labelledBy,
|
|
46
|
+
placement = "adaptive",
|
|
43
47
|
className,
|
|
44
48
|
children,
|
|
45
49
|
}: Omit<SheetProps, "open">) {
|
|
@@ -51,8 +55,8 @@ function OpenSheet({
|
|
|
51
55
|
return (
|
|
52
56
|
<div
|
|
53
57
|
className={cn(
|
|
54
|
-
"fixed inset-0 z-[65] flex
|
|
55
|
-
"sm:items-center sm:p-6"
|
|
58
|
+
"fixed inset-0 z-[65] flex justify-center",
|
|
59
|
+
placement === "center" ? "items-center p-6" : "items-end sm:items-center sm:p-6"
|
|
56
60
|
)}
|
|
57
61
|
style={
|
|
58
62
|
viewport
|
|
@@ -85,25 +89,13 @@ function OpenSheet({
|
|
|
85
89
|
className={cn(
|
|
86
90
|
"glass-menu relative flex w-full flex-col overflow-hidden",
|
|
87
91
|
"max-h-[92%] max-w-[560px]",
|
|
88
|
-
"rounded-t-sheet sm:rounded-sheet",
|
|
92
|
+
placement === "center" ? "rounded-sheet" : "rounded-t-sheet sm:rounded-sheet",
|
|
89
93
|
className
|
|
90
94
|
)}
|
|
91
|
-
initial={
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
96
|
-
animate={{ y: 0, opacity: 1, scale: 1 }}
|
|
97
|
-
exit={
|
|
98
|
-
reducedMotion
|
|
99
|
-
? { opacity: 0 }
|
|
100
|
-
: { y: 30, opacity: 0 }
|
|
101
|
-
}
|
|
102
|
-
transition={
|
|
103
|
-
reducedMotion
|
|
104
|
-
? { duration: 0 }
|
|
105
|
-
: spring.smooth
|
|
106
|
-
}
|
|
95
|
+
initial={reducedMotion ? { opacity: 0 } : { y: 40, opacity: 0 }}
|
|
96
|
+
animate={{ y: 0, opacity: 1 }}
|
|
97
|
+
exit={reducedMotion ? { opacity: 0 } : { y: 30, opacity: 0 }}
|
|
98
|
+
transition={reducedMotion ? { duration: 0 } : spring.smooth}
|
|
107
99
|
>
|
|
108
100
|
{children}
|
|
109
101
|
</motion.div>
|
|
@@ -1,10 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type RefObject,
|
|
3
|
-
useEffect,
|
|
4
|
-
useLayoutEffect,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from "react"
|
|
1
|
+
import { type RefObject, useEffect, useLayoutEffect, useRef, useState } from "react"
|
|
8
2
|
import { ownsFloatingLayer } from "../../lib/floating-layers"
|
|
9
3
|
import { enterModalEnvironment } from "./modal-environment"
|
|
10
4
|
|
|
@@ -19,12 +13,8 @@ const focusableSelector = [
|
|
|
19
13
|
"[contenteditable=true]",
|
|
20
14
|
].join(",")
|
|
21
15
|
|
|
22
|
-
function focusableElements(
|
|
23
|
-
panel
|
|
24
|
-
): HTMLElement[] {
|
|
25
|
-
return Array.from(
|
|
26
|
-
panel.querySelectorAll<HTMLElement>(focusableSelector)
|
|
27
|
-
).filter(
|
|
16
|
+
function focusableElements(panel: HTMLElement): HTMLElement[] {
|
|
17
|
+
return Array.from(panel.querySelectorAll<HTMLElement>(focusableSelector)).filter(
|
|
28
18
|
(element) =>
|
|
29
19
|
element.tabIndex >= 0 &&
|
|
30
20
|
!element.matches(":disabled") &&
|
|
@@ -35,15 +25,10 @@ function focusableElements(
|
|
|
35
25
|
}
|
|
36
26
|
|
|
37
27
|
/** Keeps keyboard focus in the foremost sheet, including its floating pickers. */
|
|
38
|
-
export function useSheetFocus(
|
|
39
|
-
panel: RefObject<HTMLDivElement | null>,
|
|
40
|
-
onClose: () => void
|
|
41
|
-
) {
|
|
28
|
+
export function useSheetFocus(panel: RefObject<HTMLDivElement | null>, onClose: () => void) {
|
|
42
29
|
// Capture before children mount, since a child may use autoFocus.
|
|
43
30
|
const [opener] = useState(() =>
|
|
44
|
-
typeof document === "undefined"
|
|
45
|
-
? null
|
|
46
|
-
: document.activeElement
|
|
31
|
+
typeof document === "undefined" ? null : document.activeElement
|
|
47
32
|
)
|
|
48
33
|
const close = useRef(onClose)
|
|
49
34
|
useEffect(() => {
|
|
@@ -55,34 +40,22 @@ export function useSheetFocus(
|
|
|
55
40
|
if (!surface) return
|
|
56
41
|
sheets.push(surface)
|
|
57
42
|
const foremost = () => sheets.at(-1) === surface
|
|
58
|
-
const focusFirst = () =>
|
|
59
|
-
|
|
60
|
-
const inFloatingLayer = (element: Element | null) =>
|
|
61
|
-
ownsFloatingLayer(surface, element)
|
|
43
|
+
const focusFirst = () => (focusableElements(surface)[0] ?? surface).focus()
|
|
44
|
+
const inFloatingLayer = (element: Element | null) => ownsFloatingLayer(surface, element)
|
|
62
45
|
const belongsToSheet = (element: Element | null) =>
|
|
63
|
-
surface.contains(element) ||
|
|
64
|
-
inFloatingLayer(element)
|
|
46
|
+
surface.contains(element) || inFloatingLayer(element)
|
|
65
47
|
|
|
66
|
-
if (!surface.contains(document.activeElement))
|
|
67
|
-
|
|
68
|
-
const leaveModalEnvironment =
|
|
69
|
-
enterModalEnvironment(surface)
|
|
48
|
+
if (!surface.contains(document.activeElement)) surface.focus({ preventScroll: true })
|
|
49
|
+
const leaveModalEnvironment = enterModalEnvironment(surface)
|
|
70
50
|
|
|
71
51
|
const onFocus = (event: FocusEvent) => {
|
|
72
|
-
if (
|
|
73
|
-
foremost() &&
|
|
74
|
-
!belongsToSheet(
|
|
75
|
-
event.target as Element | null
|
|
76
|
-
)
|
|
77
|
-
)
|
|
78
|
-
focusFirst()
|
|
52
|
+
if (foremost() && !belongsToSheet(event.target as Element | null)) focusFirst()
|
|
79
53
|
}
|
|
80
54
|
const onKey = (event: KeyboardEvent) => {
|
|
81
55
|
if (!foremost() || event.defaultPrevented) return
|
|
82
56
|
if (event.key === "Escape") {
|
|
83
57
|
// Floating controls handle their own Escape before the sheet.
|
|
84
|
-
if (inFloatingLayer(document.activeElement))
|
|
85
|
-
return
|
|
58
|
+
if (inFloatingLayer(document.activeElement)) return
|
|
86
59
|
event.preventDefault()
|
|
87
60
|
event.stopPropagation()
|
|
88
61
|
close.current()
|
|
@@ -94,17 +67,13 @@ export function useSheetFocus(
|
|
|
94
67
|
const active = document.activeElement
|
|
95
68
|
if (
|
|
96
69
|
event.shiftKey &&
|
|
97
|
-
(active === surface ||
|
|
98
|
-
active === first ||
|
|
99
|
-
!surface.contains(active))
|
|
70
|
+
(active === surface || active === first || !surface.contains(active))
|
|
100
71
|
) {
|
|
101
72
|
event.preventDefault()
|
|
102
73
|
last.focus()
|
|
103
74
|
} else if (
|
|
104
75
|
!event.shiftKey &&
|
|
105
|
-
(active === last ||
|
|
106
|
-
!surface.contains(active) ||
|
|
107
|
-
active === surface)
|
|
76
|
+
(active === last || !surface.contains(active) || active === surface)
|
|
108
77
|
) {
|
|
109
78
|
event.preventDefault()
|
|
110
79
|
first.focus()
|
|
@@ -119,12 +88,7 @@ export function useSheetFocus(
|
|
|
119
88
|
document.removeEventListener("focusin", onFocus)
|
|
120
89
|
window.removeEventListener("keydown", onKey)
|
|
121
90
|
leaveModalEnvironment()
|
|
122
|
-
if (
|
|
123
|
-
wasForemost &&
|
|
124
|
-
opener instanceof HTMLElement &&
|
|
125
|
-
opener.isConnected
|
|
126
|
-
)
|
|
127
|
-
opener.focus()
|
|
91
|
+
if (wasForemost && opener instanceof HTMLElement && opener.isConnected) opener.focus()
|
|
128
92
|
}
|
|
129
93
|
}, [panel, opener])
|
|
130
94
|
}
|
|
@@ -1,20 +1,33 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { useId, type ReactNode } from "react"
|
|
2
2
|
import { cn } from "../../lib/class-names"
|
|
3
3
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
children,
|
|
7
|
-
}: {
|
|
4
|
+
export interface SidebarSectionProps {
|
|
5
|
+
/** Visible heading for this group of navigation rows. */
|
|
8
6
|
title: string
|
|
9
7
|
children: ReactNode
|
|
10
|
-
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SidebarItemContentProps {
|
|
11
|
+
icon: ReactNode
|
|
12
|
+
/** Optional trailing count. */
|
|
13
|
+
count?: number
|
|
14
|
+
/** Matches the router link's active state. */
|
|
15
|
+
active?: boolean
|
|
16
|
+
children: ReactNode
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function SidebarSection({ title, children }: SidebarSectionProps) {
|
|
20
|
+
const headingId = useId()
|
|
11
21
|
return (
|
|
12
|
-
<
|
|
13
|
-
<
|
|
22
|
+
<section aria-labelledby={headingId} className="flex flex-col gap-0.5">
|
|
23
|
+
<h2
|
|
24
|
+
id={headingId}
|
|
25
|
+
className="px-2.5 pb-1.5 text-caption font-semibold text-label-tertiary"
|
|
26
|
+
>
|
|
14
27
|
{title}
|
|
15
|
-
</
|
|
28
|
+
</h2>
|
|
16
29
|
{children}
|
|
17
|
-
</
|
|
30
|
+
</section>
|
|
18
31
|
)
|
|
19
32
|
}
|
|
20
33
|
|
|
@@ -22,31 +35,17 @@ export function SidebarSection({
|
|
|
22
35
|
export function sidebarItemClass(active?: boolean): string {
|
|
23
36
|
return cn(
|
|
24
37
|
"group flex items-center gap-2.5 rounded-2xl px-2.5 py-[7px] text-subheadline text-label no-underline transition-colors duration-fast",
|
|
25
|
-
active
|
|
26
|
-
? "bg-accent-soft font-medium text-label"
|
|
27
|
-
: "hover:bg-fill/70"
|
|
38
|
+
active ? "bg-accent-soft font-medium text-label" : "hover:bg-fill/70"
|
|
28
39
|
)
|
|
29
40
|
}
|
|
30
41
|
|
|
31
|
-
export function SidebarItemContent({
|
|
32
|
-
icon,
|
|
33
|
-
count,
|
|
34
|
-
active,
|
|
35
|
-
children,
|
|
36
|
-
}: {
|
|
37
|
-
icon: ReactNode
|
|
38
|
-
count?: number
|
|
39
|
-
active?: boolean
|
|
40
|
-
children: ReactNode
|
|
41
|
-
}) {
|
|
42
|
+
export function SidebarItemContent({ icon, count, active, children }: SidebarItemContentProps) {
|
|
42
43
|
return (
|
|
43
44
|
<>
|
|
44
45
|
<span
|
|
45
46
|
className={cn(
|
|
46
47
|
"flex transition-colors",
|
|
47
|
-
active
|
|
48
|
-
? "text-accent-text"
|
|
49
|
-
: "text-label-secondary"
|
|
48
|
+
active ? "text-accent-text" : "text-label-secondary"
|
|
50
49
|
)}
|
|
51
50
|
>
|
|
52
51
|
{icon}
|
|
@@ -56,9 +55,7 @@ export function SidebarItemContent({
|
|
|
56
55
|
<span
|
|
57
56
|
className={cn(
|
|
58
57
|
"text-footnote tabular-nums",
|
|
59
|
-
active
|
|
60
|
-
? "text-accent-text"
|
|
61
|
-
: "text-label-tertiary"
|
|
58
|
+
active ? "text-accent-text" : "text-label-tertiary"
|
|
62
59
|
)}
|
|
63
60
|
>
|
|
64
61
|
{count}
|