@passui/react 0.1.47 → 0.2.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 +29 -109
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/accordion.d.ts +15 -0
- package/dist/accordion.js +93 -0
- package/dist/alert-dialog.d.ts +26 -0
- package/dist/alert-dialog.js +142 -0
- package/dist/alert.d.ts +10 -0
- package/dist/alert.js +28 -0
- package/dist/{types/src/components/ambient/ambient.d.ts → ambient.d.ts} +4 -4
- package/dist/ambient.js +22 -0
- package/dist/{types/src/appearance → appearance}/platform.d.ts +3 -3
- package/dist/appearance/platform.js +43 -0
- package/dist/appearance/theme.d.ts +71 -0
- package/dist/appearance/theme.js +236 -0
- package/dist/appearance.d.ts +3 -0
- package/dist/appearance.js +3 -0
- package/dist/{types/src/components/aspect-ratio/aspect-ratio.d.ts → aspect-ratio.d.ts} +4 -4
- package/dist/aspect-ratio.js +17 -0
- package/dist/avatar.d.ts +5 -0
- package/dist/avatar.js +43 -0
- package/dist/badge.d.ts +8 -0
- package/dist/badge.js +21 -0
- package/dist/breadcrumb.d.ts +13 -0
- package/dist/breadcrumb.js +63 -0
- package/dist/button-group.d.ts +5 -0
- package/dist/button-group.js +14 -0
- package/dist/button.d.ts +21 -0
- package/dist/button.js +58 -0
- package/dist/calendar.d.ts +35 -0
- package/dist/calendar.js +225 -0
- package/dist/card.d.ts +9 -0
- package/dist/card.js +54 -0
- package/dist/chart.d.ts +30 -0
- package/dist/chart.js +226 -0
- package/dist/checkbox.d.ts +13 -0
- package/dist/checkbox.js +53 -0
- package/dist/{types/src/lib/clipboard.d.ts → clipboard.d.ts} +1 -1
- package/dist/clipboard.js +16 -0
- package/dist/cn.d.ts +2 -0
- package/dist/cn.js +10 -0
- package/dist/code-block.d.ts +34 -0
- package/dist/code-block.js +87 -0
- package/dist/collapsible.d.ts +13 -0
- package/dist/collapsible.js +49 -0
- package/dist/combobox.d.ts +25 -0
- package/dist/combobox.js +112 -0
- package/dist/command.d.ts +22 -0
- package/dist/command.js +129 -0
- package/dist/components/toast/toast-store.d.ts +60 -0
- package/dist/components/toast/toast-store.js +96 -0
- package/dist/{types/src/components → components}/toast/toaster.d.ts +4 -4
- package/dist/components/toast/toaster.js +345 -0
- package/dist/context-menu.d.ts +2 -0
- package/dist/context-menu.js +2 -0
- package/dist/conversation.d.ts +48 -0
- package/dist/conversation.js +202 -0
- package/dist/date-time-picker.d.ts +50 -0
- package/dist/date-time-picker.js +235 -0
- package/dist/date.d.ts +50 -0
- package/dist/date.js +77 -0
- package/dist/dialog.d.ts +21 -0
- package/dist/dialog.js +113 -0
- package/dist/drawer.d.ts +30 -0
- package/dist/drawer.js +140 -0
- package/dist/dropdown-menu.d.ts +56 -0
- package/dist/dropdown-menu.js +295 -0
- package/dist/empty.d.ts +11 -0
- package/dist/empty.js +51 -0
- package/dist/field.d.ts +16 -0
- package/dist/field.js +47 -0
- package/{src/hooks/scroll/minimize-decision.ts → dist/hooks/scroll/minimize-decision.js} +3 -5
- package/dist/{types/src/hooks → hooks}/use-anchored-placement.d.ts +2 -2
- package/dist/hooks/use-anchored-placement.js +33 -0
- package/dist/{types/src/hooks → hooks}/use-minimize-on-scroll.d.ts +1 -1
- package/dist/hooks/use-minimize-on-scroll.js +59 -0
- package/dist/{types/src/hooks → hooks}/use-visual-viewport.d.ts +2 -2
- package/{src/hooks/use-visual-viewport.ts → dist/hooks/use-visual-viewport.js} +20 -35
- package/dist/hooks/viewport/types.d.ts +7 -0
- package/dist/hooks/viewport/viewport-metrics.js +13 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.js +80 -0
- package/dist/input-group.d.ts +17 -0
- package/dist/input-group.js +55 -0
- package/dist/input-otp.d.ts +13 -0
- package/dist/input-otp.js +36 -0
- package/dist/input.d.ts +4 -0
- package/dist/input.js +14 -0
- package/dist/item.d.ts +49 -0
- package/dist/item.js +142 -0
- package/dist/kbd.d.ts +4 -0
- package/dist/kbd.js +86 -0
- package/dist/label.d.ts +3 -0
- package/dist/label.js +12 -0
- package/dist/labeled-content.d.ts +24 -0
- package/dist/labeled-content.js +41 -0
- package/dist/{types/src/lib/language.d.ts → language.d.ts} +1 -1
- package/dist/language.js +11 -0
- package/dist/layout.d.ts +24 -0
- package/dist/layout.js +36 -0
- package/dist/{types/src/lib → lib}/anchored-placement.d.ts +27 -27
- package/dist/lib/anchored-placement.js +42 -0
- package/dist/lib/calendar-month.js +90 -0
- package/dist/lib/cx.js +6 -0
- package/dist/lib/drawer.math.js +29 -0
- package/dist/lib/floating-layers.d.ts +3 -0
- package/dist/lib/floating-layers.js +25 -0
- package/dist/{types/src/lib → lib}/haptics.d.ts +1 -1
- package/dist/lib/haptics.js +13 -0
- package/dist/lib/liquid-step.js +33 -0
- package/dist/lib/page-scale.js +58 -0
- package/dist/lib/portal.js +12 -0
- package/dist/lib/presence.js +53 -0
- package/dist/lib/range-value.js +25 -0
- package/dist/lib/render.d.ts +8 -0
- package/dist/lib/render.js +42 -0
- package/dist/lib/rolling-digit.js +83 -0
- package/dist/{types/src/lib → lib}/screen-edges.d.ts +5 -5
- package/dist/lib/screen-edges.js +30 -0
- package/dist/lib/swipe-touch-action.js +34 -0
- package/dist/lib/visual-viewport.js +27 -0
- package/dist/lib/water-drop.js +412 -0
- package/dist/lib/wheel.js +125 -0
- package/dist/list.d.ts +26 -0
- package/dist/list.js +80 -0
- package/dist/locales.d.ts +18 -0
- package/dist/locales.js +36 -0
- package/dist/marker.d.ts +13 -0
- package/dist/marker.js +33 -0
- package/dist/motion/transitions.d.ts +170 -0
- package/dist/motion/transitions.js +156 -0
- package/dist/pagination.d.ts +30 -0
- package/dist/pagination.js +117 -0
- package/dist/popover.d.ts +26 -0
- package/dist/popover.js +101 -0
- package/dist/progress.d.ts +9 -0
- package/dist/progress.js +24 -0
- package/dist/questionnaire.d.ts +46 -0
- package/dist/questionnaire.js +133 -0
- package/dist/radio-group.d.ts +21 -0
- package/dist/radio-group.js +67 -0
- package/dist/search-field.d.ts +18 -0
- package/dist/search-field.js +45 -0
- package/dist/segmented-control.d.ts +16 -0
- package/dist/segmented-control.js +25 -0
- package/dist/select.d.ts +24 -0
- package/dist/select.js +107 -0
- package/dist/separator.d.ts +9 -0
- package/dist/separator.js +17 -0
- package/dist/{types/src/lib/shapes.d.ts → shapes.d.ts} +2 -2
- package/dist/shapes.js +65 -0
- package/dist/sheet.d.ts +24 -0
- package/dist/sheet.js +141 -0
- package/dist/sidebar.d.ts +32 -0
- package/dist/sidebar.js +85 -0
- package/dist/skeleton.d.ts +3 -0
- package/dist/skeleton.js +13 -0
- package/dist/slider.d.ts +9 -0
- package/dist/slider.js +42 -0
- package/dist/slosh-slider.d.ts +21 -0
- package/dist/slosh-slider.js +205 -0
- package/dist/spinner.d.ts +3 -0
- package/dist/spinner.js +20 -0
- package/dist/stat-tile.d.ts +20 -0
- package/dist/stat-tile.js +53 -0
- package/dist/stepper.d.ts +22 -0
- package/dist/stepper.js +98 -0
- package/dist/swatch-picker.d.ts +22 -0
- package/dist/swatch-picker.js +70 -0
- package/dist/switch.d.ts +10 -0
- package/dist/switch.js +44 -0
- package/dist/tab-bar.d.ts +15 -0
- package/dist/tab-bar.js +34 -0
- package/dist/{types/src/components/table/table.d.ts → table.d.ts} +3 -3
- package/dist/table.js +93 -0
- package/dist/tabs.d.ts +32 -0
- package/dist/tabs.js +131 -0
- package/dist/text.d.ts +25 -0
- package/dist/text.js +44 -0
- package/dist/textarea.d.ts +3 -0
- package/dist/textarea.js +13 -0
- package/dist/toast.d.ts +3 -0
- package/dist/toast.js +3 -0
- package/dist/toggle-group.d.ts +20 -0
- package/dist/toggle-group.js +68 -0
- package/dist/toggle.d.ts +24 -0
- package/dist/toggle.js +37 -0
- package/dist/tokens.d.ts +1 -0
- package/dist/tooltip.d.ts +21 -0
- package/dist/tooltip.js +61 -0
- package/dist/trace.d.ts +14 -0
- package/dist/trace.js +54 -0
- package/dist/{types/src/hooks/use-dismiss.d.ts → use-dismiss.d.ts} +3 -3
- package/dist/use-dismiss.js +38 -0
- package/dist/{types/src/hooks/use-media-query.d.ts → use-media-query.d.ts} +12 -12
- package/dist/use-media-query.js +56 -0
- package/dist/use-os.d.ts +12 -0
- package/dist/use-os.js +17 -0
- package/dist/wake-slider.d.ts +15 -0
- package/dist/wake-slider.js +174 -0
- package/package.json +122 -253
- package/src/styles/code-block.css +4 -0
- package/src/styles/globals.css +5 -0
- package/src/styles/motion-controls.css +10 -0
- package/src/styles/page-scale.css +27 -0
- package/src/styles/styles.css +4 -2
- package/dist/types/src/appearance/index.d.ts +0 -2
- package/dist/types/src/appearance/theme.d.ts +0 -71
- package/dist/types/src/components/accordion/accordion.d.ts +0 -23
- package/dist/types/src/components/ambient/index.d.ts +0 -1
- package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +0 -19
- package/dist/types/src/components/button/button-styles.d.ts +0 -12
- package/dist/types/src/components/button/button.d.ts +0 -32
- package/dist/types/src/components/button/icon-button.d.ts +0 -10
- package/dist/types/src/components/button/pending-spinner.d.ts +0 -5
- package/dist/types/src/components/button/use-pending-indicator.d.ts +0 -2
- package/dist/types/src/components/chip/chip.d.ts +0 -10
- package/dist/types/src/components/code-block/code-block.d.ts +0 -13
- package/dist/types/src/components/combo-box/combo-box.d.ts +0 -9
- package/dist/types/src/components/command/command.d.ts +0 -18
- package/dist/types/src/components/compact-date-picker/calendar-month.d.ts +0 -25
- package/dist/types/src/components/compact-date-picker/compact-date-picker.d.ts +0 -30
- package/dist/types/src/components/compact-time-picker/compact-time-picker.d.ts +0 -29
- package/dist/types/src/components/compact-time-picker/time-value.d.ts +0 -18
- package/dist/types/src/components/content-unavailable-view/content-unavailable-view.d.ts +0 -12
- package/dist/types/src/components/content-view/content-view.d.ts +0 -51
- package/dist/types/src/components/content-view/index.d.ts +0 -1
- package/dist/types/src/components/context-menu/conceal-menu-source.d.ts +0 -2
- package/dist/types/src/components/context-menu/context-menu-host.d.ts +0 -2
- package/dist/types/src/components/context-menu/context-menu-store.d.ts +0 -62
- package/dist/types/src/components/context-menu/menu-navigation.d.ts +0 -6
- package/dist/types/src/components/context-menu/menu-position.d.ts +0 -21
- package/dist/types/src/components/context-menu/menu-reveal.d.ts +0 -26
- package/dist/types/src/components/context-menu/use-context-menu.d.ts +0 -14
- package/dist/types/src/components/conversation/conversation.d.ts +0 -48
- package/dist/types/src/components/conversation/index.d.ts +0 -1
- package/dist/types/src/components/date-picker/date-picker.d.ts +0 -19
- package/dist/types/src/components/date-picker/date-value.d.ts +0 -2
- package/dist/types/src/components/dialog/dialog-host.d.ts +0 -6
- package/dist/types/src/components/dialog/dialog-store.d.ts +0 -23
- package/dist/types/src/components/dialog/dialog.d.ts +0 -33
- package/dist/types/src/components/dialog/index.d.ts +0 -1
- package/dist/types/src/components/disclosure-group/disclosure-group.d.ts +0 -18
- package/dist/types/src/components/divider/divider.d.ts +0 -9
- package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +0 -15
- package/dist/types/src/components/keyboard-shortcut/keyboard-shortcut.d.ts +0 -8
- package/dist/types/src/components/labeled-content/labeled-content.d.ts +0 -22
- package/dist/types/src/components/locale-switcher/index.d.ts +0 -1
- package/dist/types/src/components/locale-switcher/locale-switcher.d.ts +0 -13
- package/dist/types/src/components/menu/menu.d.ts +0 -16
- package/dist/types/src/components/morph/index.d.ts +0 -2
- package/dist/types/src/components/morph/morph.d.ts +0 -32
- package/dist/types/src/components/morph/use-morph-disclosure.d.ts +0 -13
- package/dist/types/src/components/one-time-code/one-time-code.d.ts +0 -26
- package/dist/types/src/components/picker/picker-trigger.d.ts +0 -3
- package/dist/types/src/components/picker/picker.d.ts +0 -46
- package/dist/types/src/components/popover/anchored-surface.d.ts +0 -17
- package/dist/types/src/components/popover/index.d.ts +0 -41
- package/dist/types/src/components/popover/popover-content.d.ts +0 -38
- package/dist/types/src/components/popover/popover-root.d.ts +0 -22
- package/dist/types/src/components/popover/popover-trigger.d.ts +0 -23
- package/dist/types/src/components/profile-image/profile-image.d.ts +0 -9
- package/dist/types/src/components/progress-view/progress-view.d.ts +0 -13
- package/dist/types/src/components/progress-view/use-liquid-progress.d.ts +0 -3
- package/dist/types/src/components/radio-group/radio-group.d.ts +0 -20
- package/dist/types/src/components/search-field/expanding-search-field.d.ts +0 -5
- package/dist/types/src/components/search-field/search-field.d.ts +0 -9
- package/dist/types/src/components/search-list/search-list.d.ts +0 -22
- package/dist/types/src/components/section/section.d.ts +0 -18
- package/dist/types/src/components/secure-field/secure-field.d.ts +0 -4
- package/dist/types/src/components/segmented-control/segmented-control.d.ts +0 -25
- package/dist/types/src/components/sheet/modal-environment.d.ts +0 -2
- package/dist/types/src/components/sheet/sheet-portal.d.ts +0 -5
- package/dist/types/src/components/sheet/sheet.d.ts +0 -26
- package/dist/types/src/components/sheet/use-sheet-focus.d.ts +0 -3
- package/dist/types/src/components/sidebar/sidebar.d.ts +0 -24
- package/dist/types/src/components/skeleton/skeleton.d.ts +0 -9
- package/dist/types/src/components/slider/slider.d.ts +0 -17
- package/dist/types/src/components/slosh-slider/liquid-step.d.ts +0 -6
- package/dist/types/src/components/slosh-slider/slosh-slider.d.ts +0 -21
- package/dist/types/src/components/stat-tile/index.d.ts +0 -1
- package/dist/types/src/components/stat-tile/stat-tile.d.ts +0 -20
- package/dist/types/src/components/status-indicator/status-indicator.d.ts +0 -17
- package/dist/types/src/components/stepper/rolling-digit.d.ts +0 -11
- package/dist/types/src/components/stepper/stepper.d.ts +0 -22
- package/dist/types/src/components/swatch-picker/swatch-picker.d.ts +0 -22
- package/dist/types/src/components/tab-bar/tab-bar.d.ts +0 -43
- package/dist/types/src/components/tab-view/tab-view.d.ts +0 -27
- package/dist/types/src/components/text-editor/text-editor.d.ts +0 -9
- package/dist/types/src/components/text-field/text-field.d.ts +0 -33
- package/dist/types/src/components/toast/toast-store.d.ts +0 -52
- package/dist/types/src/components/toggle/toggle.d.ts +0 -22
- package/dist/types/src/components/tooltip/tooltip-host.d.ts +0 -7
- package/dist/types/src/components/view-controller/index.d.ts +0 -1
- package/dist/types/src/components/view-controller/view-controller.d.ts +0 -21
- package/dist/types/src/components/wake-slider/wake-slider.d.ts +0 -15
- package/dist/types/src/hooks/scroll/minimize-decision.d.ts +0 -2
- package/dist/types/src/hooks/use-anchored-disclosure.d.ts +0 -9
- package/dist/types/src/hooks/use-floating-dismiss.d.ts +0 -3
- package/dist/types/src/hooks/viewport/types.d.ts +0 -19
- package/dist/types/src/hooks/viewport/viewport-metrics.d.ts +0 -3
- package/dist/types/src/icons/icons.d.ts +0 -616
- package/dist/types/src/index.d.ts +0 -73
- package/dist/types/src/lib/class-names.d.ts +0 -2
- package/dist/types/src/lib/date.d.ts +0 -50
- package/dist/types/src/lib/floating-layers.d.ts +0 -8
- package/dist/types/src/lib/range-value.d.ts +0 -4
- package/dist/types/src/machines/popover.machine.d.ts +0 -30
- package/dist/types/src/motion/transitions.d.ts +0 -170
- package/src/appearance/index.ts +0 -2
- package/src/appearance/platform.tsx +0 -102
- package/src/appearance/theme.tsx +0 -467
- package/src/components/accordion/accordion.tsx +0 -70
- package/src/components/ambient/ambient.tsx +0 -35
- package/src/components/ambient/index.ts +0 -1
- package/src/components/aspect-ratio/aspect-ratio.tsx +0 -27
- package/src/components/breadcrumb/breadcrumb.tsx +0 -73
- package/src/components/button/button-styles.ts +0 -49
- package/src/components/button/button.tsx +0 -107
- package/src/components/button/icon-button.tsx +0 -33
- package/src/components/button/pending-spinner.tsx +0 -14
- package/src/components/button/use-pending-indicator.ts +0 -22
- package/src/components/chip/chip.tsx +0 -45
- package/src/components/code-block/code-block.tsx +0 -48
- package/src/components/combo-box/combo-box.tsx +0 -13
- package/src/components/command/command.tsx +0 -149
- package/src/components/compact-date-picker/calendar-month.ts +0 -109
- package/src/components/compact-date-picker/compact-date-picker.tsx +0 -337
- package/src/components/compact-time-picker/compact-time-picker.tsx +0 -321
- package/src/components/compact-time-picker/time-value.ts +0 -58
- package/src/components/content-unavailable-view/content-unavailable-view.tsx +0 -78
- package/src/components/content-view/content-view.tsx +0 -215
- package/src/components/content-view/index.ts +0 -1
- package/src/components/context-menu/conceal-menu-source.ts +0 -30
- package/src/components/context-menu/context-menu-host.tsx +0 -459
- package/src/components/context-menu/context-menu-store.ts +0 -167
- package/src/components/context-menu/menu-navigation.ts +0 -36
- package/src/components/context-menu/menu-position.ts +0 -38
- package/src/components/context-menu/menu-reveal.ts +0 -42
- package/src/components/context-menu/use-context-menu.ts +0 -73
- package/src/components/conversation/conversation.tsx +0 -309
- package/src/components/conversation/index.ts +0 -1
- package/src/components/date-picker/date-picker.tsx +0 -106
- package/src/components/date-picker/date-value.ts +0 -22
- package/src/components/dialog/dialog-host.tsx +0 -119
- package/src/components/dialog/dialog-store.ts +0 -66
- package/src/components/dialog/dialog.tsx +0 -211
- package/src/components/dialog/index.ts +0 -1
- package/src/components/disclosure-group/disclosure-group.tsx +0 -108
- package/src/components/divider/divider.tsx +0 -33
- package/src/components/inline-disclosure/inline-disclosure.tsx +0 -53
- package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +0 -32
- package/src/components/labeled-content/labeled-content.tsx +0 -84
- package/src/components/locale-switcher/index.ts +0 -1
- package/src/components/locale-switcher/locale-switcher.tsx +0 -310
- package/src/components/menu/menu.tsx +0 -85
- package/src/components/morph/index.ts +0 -2
- package/src/components/morph/morph.tsx +0 -258
- package/src/components/morph/use-morph-disclosure.ts +0 -27
- package/src/components/one-time-code/one-time-code.tsx +0 -234
- package/src/components/picker/picker-trigger.ts +0 -22
- package/src/components/picker/picker.tsx +0 -404
- package/src/components/popover/anchored-surface.tsx +0 -264
- package/src/components/popover/index.ts +0 -50
- package/src/components/popover/popover-content.tsx +0 -374
- package/src/components/popover/popover-root.tsx +0 -97
- package/src/components/popover/popover-trigger.tsx +0 -71
- package/src/components/profile-image/profile-image.tsx +0 -96
- package/src/components/progress-view/progress-view.tsx +0 -72
- package/src/components/progress-view/use-liquid-progress.ts +0 -43
- package/src/components/radio-group/radio-group.tsx +0 -86
- package/src/components/search-field/expanding-search-field.tsx +0 -197
- package/src/components/search-field/search-field.tsx +0 -66
- package/src/components/search-list/search-list.tsx +0 -276
- package/src/components/section/section.tsx +0 -75
- package/src/components/secure-field/secure-field.tsx +0 -8
- package/src/components/segmented-control/segmented-control.tsx +0 -157
- package/src/components/sheet/modal-environment.ts +0 -82
- package/src/components/sheet/sheet-portal.tsx +0 -62
- package/src/components/sheet/sheet.tsx +0 -165
- package/src/components/sheet/use-sheet-focus.ts +0 -109
- package/src/components/sidebar/sidebar.tsx +0 -102
- package/src/components/skeleton/skeleton.tsx +0 -38
- package/src/components/slider/slider.tsx +0 -134
- package/src/components/slosh-slider/liquid-step.ts +0 -43
- package/src/components/slosh-slider/slosh-slider.tsx +0 -294
- package/src/components/stat-tile/index.ts +0 -1
- package/src/components/stat-tile/stat-tile.tsx +0 -90
- package/src/components/status-indicator/status-indicator.tsx +0 -54
- package/src/components/stepper/rolling-digit.tsx +0 -91
- package/src/components/stepper/stepper.tsx +0 -136
- package/src/components/swatch-picker/swatch-picker.tsx +0 -138
- package/src/components/tab-bar/tab-bar.tsx +0 -182
- package/src/components/tab-view/tab-view.tsx +0 -155
- package/src/components/table/table.tsx +0 -151
- package/src/components/text-editor/text-editor.tsx +0 -42
- package/src/components/text-field/text-field.tsx +0 -200
- package/src/components/toast/toast-store.ts +0 -164
- package/src/components/toast/toaster.tsx +0 -407
- package/src/components/toggle/toggle.tsx +0 -320
- package/src/components/tooltip/tooltip-host.tsx +0 -178
- package/src/components/view-controller/index.ts +0 -1
- package/src/components/view-controller/view-controller.tsx +0 -75
- package/src/components/wake-slider/wake-slider.tsx +0 -260
- package/src/hooks/use-anchored-disclosure.ts +0 -23
- package/src/hooks/use-anchored-placement.ts +0 -40
- package/src/hooks/use-dismiss.ts +0 -44
- package/src/hooks/use-floating-dismiss.ts +0 -30
- package/src/hooks/use-media-query.ts +0 -94
- package/src/hooks/use-minimize-on-scroll.ts +0 -77
- package/src/hooks/viewport/types.ts +0 -19
- package/src/hooks/viewport/viewport-metrics.ts +0 -19
- package/src/icons/icons.tsx +0 -458
- package/src/index.ts +0 -107
- package/src/lib/anchored-placement.ts +0 -91
- package/src/lib/class-names.ts +0 -21
- package/src/lib/clipboard.ts +0 -15
- package/src/lib/date.ts +0 -86
- package/src/lib/floating-layers.ts +0 -53
- package/src/lib/haptics.ts +0 -23
- package/src/lib/language.ts +0 -16
- package/src/lib/range-value.ts +0 -38
- package/src/lib/screen-edges.ts +0 -44
- package/src/lib/shapes.ts +0 -59
- package/src/machines/popover.machine.ts +0 -51
- package/src/motion/transitions.ts +0 -97
- package/src/tokens.ts +0 -1
- /package/dist/{types/src/tokens.d.ts → tokens.js} +0 -0
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ReactNode,
|
|
3
|
-
useEffect,
|
|
4
|
-
useId,
|
|
5
|
-
useReducer,
|
|
6
|
-
useRef,
|
|
7
|
-
type RefObject,
|
|
8
|
-
} from "react";
|
|
9
|
-
import { createContext, useContext } from "react";
|
|
10
|
-
import {
|
|
11
|
-
popoverMachine,
|
|
12
|
-
type PopoverContextValue,
|
|
13
|
-
type PopoverEvent,
|
|
14
|
-
type PopoverState,
|
|
15
|
-
} from "../../machines/popover.machine";
|
|
16
|
-
|
|
17
|
-
const PopoverContext = createContext<PopoverContextValue | null>(null);
|
|
18
|
-
|
|
19
|
-
export function usePopover(): PopoverContextValue {
|
|
20
|
-
const ctx = useContext(PopoverContext);
|
|
21
|
-
if (!ctx) throw new Error("Popover parts need a <Popover.Root> parent");
|
|
22
|
-
return ctx;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface PopoverRootProps {
|
|
26
|
-
children: ReactNode;
|
|
27
|
-
/**
|
|
28
|
-
* Start open (uncontrolled) or set the initial state.
|
|
29
|
-
* Ignored when `open` is provided.
|
|
30
|
-
*/
|
|
31
|
-
defaultOpen?: boolean;
|
|
32
|
-
/**
|
|
33
|
-
* Controlled open state. When provided, the popover is driven by this
|
|
34
|
-
* prop: setting it to true opens, false closes. The internal machine
|
|
35
|
-
* still runs the open/close transitions so the morph can play.
|
|
36
|
-
*/
|
|
37
|
-
open?: boolean;
|
|
38
|
-
/** Called when the popover finishes opening or closing. */
|
|
39
|
-
onOpenChange?: (open: boolean) => void;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function PopoverRoot({
|
|
43
|
-
children,
|
|
44
|
-
defaultOpen = false,
|
|
45
|
-
open,
|
|
46
|
-
onOpenChange,
|
|
47
|
-
}: PopoverRootProps) {
|
|
48
|
-
const [state, dispatch] = useReducer(
|
|
49
|
-
popoverMachine,
|
|
50
|
-
defaultOpen ? "opening" : ("closed" satisfies PopoverState),
|
|
51
|
-
);
|
|
52
|
-
const triggerRef = useRef<HTMLElement | null>(null);
|
|
53
|
-
const contentId = useId();
|
|
54
|
-
const surfaceId = useId();
|
|
55
|
-
const onOpenChangeRef = useRef(onOpenChange);
|
|
56
|
-
|
|
57
|
-
// Keep the latest callback without re-rendering the tree.
|
|
58
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
59
|
-
onOpenChangeRef.current = onOpenChange;
|
|
60
|
-
|
|
61
|
-
const send = (event: PopoverEvent) => {
|
|
62
|
-
const next = popoverMachine(state, event);
|
|
63
|
-
if (next !== state) {
|
|
64
|
-
dispatch(event);
|
|
65
|
-
// Fire onOpenChange only when fully open or fully closed — not
|
|
66
|
-
// during transitions. This lets the consumer close the popover
|
|
67
|
-
// (set open=false) and have it animate out, rather than unmounting.
|
|
68
|
-
if (next === "open") onOpenChangeRef.current?.(true);
|
|
69
|
-
if (next === "closed") onOpenChangeRef.current?.(false);
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
// Controlled mode: drive OPEN/CLOSE from the `open` prop. The machine
|
|
74
|
-
// still runs the morph transitions; we only nudge it when the desired
|
|
75
|
-
// presence differs from the current presence.
|
|
76
|
-
const present = state !== "closed";
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
if (open === undefined) return;
|
|
79
|
-
if (open && !present) send("OPEN");
|
|
80
|
-
if (!open && present) send("CLOSE");
|
|
81
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
82
|
-
}, [open]);
|
|
83
|
-
|
|
84
|
-
const isPresent = present;
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<PopoverContext
|
|
88
|
-
value={{ state, send, triggerRef, contentId, surfaceId, isPresent }}
|
|
89
|
-
>
|
|
90
|
-
{children}
|
|
91
|
-
</PopoverContext>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Re-export the context type for consumers that need it.
|
|
96
|
-
export type { PopoverContextValue };
|
|
97
|
-
export type { RefObject };
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { type ReactNode, cloneElement, isValidElement } from "react";
|
|
2
|
-
import { usePopover } from "./popover-root";
|
|
3
|
-
|
|
4
|
-
export type PopoverTriggerRenderProps = {
|
|
5
|
-
ref: (node: HTMLElement | null) => void;
|
|
6
|
-
"aria-haspopup": "dialog";
|
|
7
|
-
"aria-expanded": boolean;
|
|
8
|
-
"aria-controls": string | undefined;
|
|
9
|
-
onClick: () => void;
|
|
10
|
-
onKeyDown: (event: React.KeyboardEvent) => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export interface PopoverTriggerProps {
|
|
14
|
-
/** The trigger content when using render prop. */
|
|
15
|
-
children?: ReactNode;
|
|
16
|
-
/**
|
|
17
|
-
* Render prop: receives the trigger props (ref, aria, onClick) and
|
|
18
|
-
* returns the trigger element. This prevents ref-passing conflicts
|
|
19
|
-
* when multiple triggers exist — borrowed from Base UI.
|
|
20
|
-
*
|
|
21
|
-
* If you pass a single element as children instead, it will be
|
|
22
|
-
* cloned with the trigger props merged in.
|
|
23
|
-
*/
|
|
24
|
-
render?: (props: PopoverTriggerRenderProps) => ReactNode;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function PopoverTrigger({ children, render }: PopoverTriggerProps) {
|
|
28
|
-
const { state, send, triggerRef, contentId } = usePopover();
|
|
29
|
-
|
|
30
|
-
const triggerProps: PopoverTriggerRenderProps = {
|
|
31
|
-
ref: (node) => {
|
|
32
|
-
triggerRef.current = node;
|
|
33
|
-
},
|
|
34
|
-
"aria-haspopup": "dialog",
|
|
35
|
-
"aria-expanded": state === "open" || state === "opening",
|
|
36
|
-
"aria-controls": state !== "closed" ? contentId : undefined,
|
|
37
|
-
onClick: () => send("TOGGLE"),
|
|
38
|
-
onKeyDown: (event) => {
|
|
39
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
40
|
-
event.preventDefault();
|
|
41
|
-
send("TOGGLE");
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
if (render) {
|
|
47
|
-
return render(triggerProps);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Clone a single child element with the trigger props merged.
|
|
51
|
-
if (isValidElement(children)) {
|
|
52
|
-
const child = children as React.ReactElement<Record<string, unknown>>;
|
|
53
|
-
return cloneElement(child, {
|
|
54
|
-
ref: (node: HTMLElement | null) => {
|
|
55
|
-
triggerRef.current = node;
|
|
56
|
-
},
|
|
57
|
-
"aria-haspopup": "dialog",
|
|
58
|
-
"aria-expanded": state === "open" || state === "opening",
|
|
59
|
-
"aria-controls": state !== "closed" ? contentId : undefined,
|
|
60
|
-
onClick: () => send("TOGGLE"),
|
|
61
|
-
onKeyDown: (event: React.KeyboardEvent) => {
|
|
62
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
63
|
-
event.preventDefault();
|
|
64
|
-
send("TOGGLE");
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createContext,
|
|
3
|
-
useContext,
|
|
4
|
-
useEffect,
|
|
5
|
-
useState,
|
|
6
|
-
type ComponentProps,
|
|
7
|
-
} from "react";
|
|
8
|
-
import { cn } from "../../lib/class-names";
|
|
9
|
-
|
|
10
|
-
export type ProfileImageSize = "sm" | "md" | "lg";
|
|
11
|
-
|
|
12
|
-
const diameters: Record<ProfileImageSize, string> = {
|
|
13
|
-
sm: "size-7",
|
|
14
|
-
md: "size-9",
|
|
15
|
-
lg: "size-12",
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const fallbackTextSizes: Record<ProfileImageSize, string> = {
|
|
19
|
-
sm: "text-caption",
|
|
20
|
-
md: "text-footnote",
|
|
21
|
-
lg: "text-subheadline",
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const ImageContext = createContext<{
|
|
25
|
-
loaded: boolean;
|
|
26
|
-
setLoaded: (loaded: boolean) => void;
|
|
27
|
-
size: ProfileImageSize;
|
|
28
|
-
}>({ loaded: false, setLoaded: () => {}, size: "md" });
|
|
29
|
-
|
|
30
|
-
export interface ProfileImageProps extends ComponentProps<"span"> {
|
|
31
|
-
/** Avatar diameter; fallback initials scale with it. @default "md" */
|
|
32
|
-
size?: ProfileImageSize;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function ProfileImage({
|
|
36
|
-
size = "md",
|
|
37
|
-
className,
|
|
38
|
-
...props
|
|
39
|
-
}: ProfileImageProps) {
|
|
40
|
-
const [loaded, setLoaded] = useState(false);
|
|
41
|
-
return (
|
|
42
|
-
<ImageContext value={{ loaded, setLoaded, size }}>
|
|
43
|
-
<span
|
|
44
|
-
{...props}
|
|
45
|
-
className={cn(
|
|
46
|
-
"bg-fill text-label-secondary relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full",
|
|
47
|
-
diameters[size],
|
|
48
|
-
className,
|
|
49
|
-
)}
|
|
50
|
-
/>
|
|
51
|
-
</ImageContext>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
export function ProfileImageContent({
|
|
55
|
-
src,
|
|
56
|
-
className,
|
|
57
|
-
onLoad,
|
|
58
|
-
onError,
|
|
59
|
-
...props
|
|
60
|
-
}: ComponentProps<"img">) {
|
|
61
|
-
const { setLoaded } = useContext(ImageContext);
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
if (src) setLoaded(false);
|
|
64
|
-
}, [src, setLoaded]);
|
|
65
|
-
if (!src) return null;
|
|
66
|
-
return (
|
|
67
|
-
<img
|
|
68
|
-
key={src}
|
|
69
|
-
alt=""
|
|
70
|
-
{...props}
|
|
71
|
-
src={src}
|
|
72
|
-
className={cn("absolute inset-0 size-full object-cover", className)}
|
|
73
|
-
onLoad={(event) => {
|
|
74
|
-
setLoaded(true);
|
|
75
|
-
onLoad?.(event);
|
|
76
|
-
}}
|
|
77
|
-
onError={(event) => {
|
|
78
|
-
setLoaded(false);
|
|
79
|
-
onError?.(event);
|
|
80
|
-
event.currentTarget.style.visibility = "hidden";
|
|
81
|
-
}}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
export function ProfileImageFallback({
|
|
86
|
-
className,
|
|
87
|
-
...props
|
|
88
|
-
}: ComponentProps<"span">) {
|
|
89
|
-
const { loaded, size } = useContext(ImageContext);
|
|
90
|
-
return loaded ? null : (
|
|
91
|
-
<span
|
|
92
|
-
{...props}
|
|
93
|
-
className={cn(fallbackTextSizes[size], "font-medium", className)}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { type HTMLAttributes, useRef } from "react";
|
|
2
|
-
import { useLiquidProgress } from "./use-liquid-progress";
|
|
3
|
-
import { cn } from "../../lib/class-names";
|
|
4
|
-
import { clampRange } from "../../lib/range-value";
|
|
5
|
-
|
|
6
|
-
export type ProgressViewSize = "sm" | "md" | "lg";
|
|
7
|
-
|
|
8
|
-
export interface ProgressViewProps
|
|
9
|
-
extends Omit<HTMLAttributes<HTMLDivElement>, "children"> {
|
|
10
|
-
label: string;
|
|
11
|
-
/** Omit for an indeterminate operation. */
|
|
12
|
-
value?: number;
|
|
13
|
-
max?: number;
|
|
14
|
-
size?: ProgressViewSize;
|
|
15
|
-
/** Secondary text, such as bytes uploaded. */
|
|
16
|
-
detail?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const trackHeight: Record<ProgressViewSize, string> = {
|
|
20
|
-
sm: "h-1",
|
|
21
|
-
md: "h-2",
|
|
22
|
-
lg: "h-3",
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
/** A determinate or indeterminate progress track respecting reduced motion. */
|
|
26
|
-
export function ProgressView({
|
|
27
|
-
label,
|
|
28
|
-
value,
|
|
29
|
-
max = 100,
|
|
30
|
-
size = "md",
|
|
31
|
-
detail,
|
|
32
|
-
className,
|
|
33
|
-
...props
|
|
34
|
-
}: ProgressViewProps) {
|
|
35
|
-
const limit = Number.isFinite(max) && max > 0 ? max : 100;
|
|
36
|
-
const current = value === undefined ? undefined : clampRange(value, 0, limit);
|
|
37
|
-
const progress = current === undefined ? undefined : (current / limit) * 100;
|
|
38
|
-
const fill = useRef<HTMLDivElement>(null);
|
|
39
|
-
useLiquidProgress(fill, progress);
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<div {...props} className={cn("flex min-w-0 flex-col gap-2", className)}>
|
|
43
|
-
<div className="text-footnote flex items-center justify-between gap-3">
|
|
44
|
-
<span className="text-label font-semibold">{label}</span>
|
|
45
|
-
{detail && <span className="text-label-secondary">{detail}</span>}
|
|
46
|
-
</div>
|
|
47
|
-
<div
|
|
48
|
-
role="progressbar"
|
|
49
|
-
aria-label={label}
|
|
50
|
-
aria-valuemin={current === undefined ? undefined : 0}
|
|
51
|
-
aria-valuemax={current === undefined ? undefined : limit}
|
|
52
|
-
aria-valuenow={current}
|
|
53
|
-
className={cn(
|
|
54
|
-
"bg-separator/70 relative w-full overflow-hidden rounded-full",
|
|
55
|
-
trackHeight[size],
|
|
56
|
-
)}
|
|
57
|
-
>
|
|
58
|
-
<div
|
|
59
|
-
ref={fill}
|
|
60
|
-
aria-hidden="true"
|
|
61
|
-
className={cn(
|
|
62
|
-
"bg-accent h-full rounded-full",
|
|
63
|
-
current !== undefined && "passui-progress-fill",
|
|
64
|
-
current === undefined &&
|
|
65
|
-
"w-1/3 animate-pulse motion-reduce:animate-none",
|
|
66
|
-
)}
|
|
67
|
-
style={progress === undefined ? undefined : { width: `${progress}%` }}
|
|
68
|
-
/>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { type RefObject, useLayoutEffect, useRef } from "react";
|
|
2
|
-
import { useMediaQuery } from "../../hooks/use-media-query";
|
|
3
|
-
import { clampRange } from "../../lib/range-value";
|
|
4
|
-
import { stepLiquid } from "../slosh-slider/liquid-step";
|
|
5
|
-
|
|
6
|
-
/** Read-only progress shares the liquid fill without acquiring slider semantics. */
|
|
7
|
-
export function useLiquidProgress(
|
|
8
|
-
ref: RefObject<HTMLDivElement | null>,
|
|
9
|
-
target: number | undefined,
|
|
10
|
-
) {
|
|
11
|
-
const reduced = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
12
|
-
const state = useRef({ fill: target ?? 0, velocity: 0 });
|
|
13
|
-
useLayoutEffect(() => {
|
|
14
|
-
const element = ref.current;
|
|
15
|
-
if (!element || target === undefined) return;
|
|
16
|
-
let frame = 0;
|
|
17
|
-
let previous = 0;
|
|
18
|
-
const paint = () => {
|
|
19
|
-
element.style.width = `${state.current.fill}%`;
|
|
20
|
-
element.style.setProperty(
|
|
21
|
-
"--progress-lean",
|
|
22
|
-
`${reduced ? 0 : clampRange(state.current.velocity * 0.4, -4, 4)}px`,
|
|
23
|
-
);
|
|
24
|
-
};
|
|
25
|
-
if (reduced) {
|
|
26
|
-
state.current = { fill: target, velocity: 0 };
|
|
27
|
-
paint();
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const tick = (now: number) => {
|
|
31
|
-
const dt = previous ? Math.min(2.5, (now - previous) / 16.67) : 1;
|
|
32
|
-
previous = now;
|
|
33
|
-
state.current = stepLiquid(state.current, target, 15, dt);
|
|
34
|
-
paint();
|
|
35
|
-
if (state.current.fill !== target || state.current.velocity)
|
|
36
|
-
frame = requestAnimationFrame(tick);
|
|
37
|
-
};
|
|
38
|
-
paint();
|
|
39
|
-
if (state.current.fill !== target || state.current.velocity)
|
|
40
|
-
frame = requestAnimationFrame(tick);
|
|
41
|
-
return () => cancelAnimationFrame(frame);
|
|
42
|
-
}, [ref, target, reduced]);
|
|
43
|
-
}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { useId } from "react";
|
|
2
|
-
import { cn } from "../../lib/class-names";
|
|
3
|
-
|
|
4
|
-
export type RadioGroupSize = "sm" | "md" | "lg";
|
|
5
|
-
|
|
6
|
-
const legendSizes: Record<RadioGroupSize, string> = {
|
|
7
|
-
sm: "mb-1.5 text-caption2 font-medium text-label-secondary",
|
|
8
|
-
md: "mb-2 text-footnote font-medium text-label-secondary",
|
|
9
|
-
lg: "mb-2.5 text-subheadline font-medium text-label-secondary",
|
|
10
|
-
};
|
|
11
|
-
const rowSizes: Record<RadioGroupSize, string> = {
|
|
12
|
-
sm: "flex min-h-7 items-start gap-1.5 text-footnote text-label has-disabled:opacity-40 [@media(pointer:coarse)]:min-h-10",
|
|
13
|
-
md: "flex min-h-8 items-start gap-2 text-subheadline text-label has-disabled:opacity-40 [@media(pointer:coarse)]:min-h-11",
|
|
14
|
-
lg: "flex min-h-10 items-start gap-2.5 text-body text-label has-disabled:opacity-40 [@media(pointer:coarse)]:min-h-12",
|
|
15
|
-
};
|
|
16
|
-
const radioSizes: Record<RadioGroupSize, string> = {
|
|
17
|
-
sm: "mt-0.5 size-3.5 shrink-0 accent-accent-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent-text",
|
|
18
|
-
md: "mt-1 size-4 shrink-0 accent-accent-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent-text",
|
|
19
|
-
lg: "mt-1 size-5 shrink-0 accent-accent-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-accent-text",
|
|
20
|
-
};
|
|
21
|
-
const descriptionSizes: Record<RadioGroupSize, string> = {
|
|
22
|
-
sm: "block text-caption2 text-label-secondary",
|
|
23
|
-
md: "block text-footnote text-label-secondary",
|
|
24
|
-
lg: "block text-subheadline text-label-secondary",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export interface RadioGroupOption<T extends string> {
|
|
28
|
-
value: T;
|
|
29
|
-
label: string;
|
|
30
|
-
description?: string;
|
|
31
|
-
disabled?: boolean;
|
|
32
|
-
}
|
|
33
|
-
export interface RadioGroupProps<T extends string> {
|
|
34
|
-
value: T;
|
|
35
|
-
onChange: (value: NoInfer<T>) => void;
|
|
36
|
-
label: string;
|
|
37
|
-
options: readonly RadioGroupOption<T>[];
|
|
38
|
-
disabled?: boolean;
|
|
39
|
-
name?: string;
|
|
40
|
-
className?: string;
|
|
41
|
-
/** Legend, row, radio glyph and description density. @default "md" */
|
|
42
|
-
size?: RadioGroupSize;
|
|
43
|
-
}
|
|
44
|
-
/** A labelled choice group using the browser's native radio keyboard behavior. */
|
|
45
|
-
export function RadioGroup<T extends string>({
|
|
46
|
-
value,
|
|
47
|
-
onChange,
|
|
48
|
-
label,
|
|
49
|
-
options,
|
|
50
|
-
disabled,
|
|
51
|
-
name,
|
|
52
|
-
className,
|
|
53
|
-
size = "md",
|
|
54
|
-
}: RadioGroupProps<T>) {
|
|
55
|
-
const id = useId();
|
|
56
|
-
return (
|
|
57
|
-
<fieldset
|
|
58
|
-
disabled={disabled}
|
|
59
|
-
className={cn("flex min-w-0 flex-col gap-2", className)}
|
|
60
|
-
>
|
|
61
|
-
<legend className={legendSizes[size]}>{label}</legend>
|
|
62
|
-
{options.map((option, index) => (
|
|
63
|
-
<label key={option.value} className={rowSizes[size]}>
|
|
64
|
-
<input
|
|
65
|
-
type="radio"
|
|
66
|
-
name={name ?? id}
|
|
67
|
-
value={option.value}
|
|
68
|
-
checked={value === option.value}
|
|
69
|
-
disabled={option.disabled}
|
|
70
|
-
onChange={() => onChange(option.value)}
|
|
71
|
-
aria-describedby={option.description ? `${id}-${index}` : undefined}
|
|
72
|
-
className={radioSizes[size]}
|
|
73
|
-
/>
|
|
74
|
-
<span>
|
|
75
|
-
{option.label}
|
|
76
|
-
{option.description && (
|
|
77
|
-
<span id={`${id}-${index}`} className={descriptionSizes[size]}>
|
|
78
|
-
{option.description}
|
|
79
|
-
</span>
|
|
80
|
-
)}
|
|
81
|
-
</span>
|
|
82
|
-
</label>
|
|
83
|
-
))}
|
|
84
|
-
</fieldset>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type InputHTMLAttributes,
|
|
3
|
-
type Ref,
|
|
4
|
-
useEffect,
|
|
5
|
-
useLayoutEffect,
|
|
6
|
-
useRef,
|
|
7
|
-
useState,
|
|
8
|
-
} from "react";
|
|
9
|
-
import { useMediaQuery } from "../../hooks/use-media-query";
|
|
10
|
-
import { SearchIcon } from "../../icons/icons";
|
|
11
|
-
import { cn } from "../../lib/class-names";
|
|
12
|
-
import { springs } from "@passui/tokens/motion";
|
|
13
|
-
|
|
14
|
-
/** One object: the field stays inside the pill, and the lens never moves within it. */
|
|
15
|
-
export function ExpandingSearchField({
|
|
16
|
-
inputRef,
|
|
17
|
-
className,
|
|
18
|
-
placeholder = "Search",
|
|
19
|
-
...props
|
|
20
|
-
}: InputHTMLAttributes<HTMLInputElement> & {
|
|
21
|
-
inputRef: Ref<HTMLInputElement>;
|
|
22
|
-
}) {
|
|
23
|
-
const [expanded, setExpanded] = useState(
|
|
24
|
-
Boolean(props.value ?? props.defaultValue),
|
|
25
|
-
);
|
|
26
|
-
const reduced = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
27
|
-
const frame = useRef<HTMLDivElement>(null);
|
|
28
|
-
const pill = useRef<HTMLLabelElement>(null);
|
|
29
|
-
const input = useRef<HTMLInputElement>(null);
|
|
30
|
-
const geometry = useRef({
|
|
31
|
-
width: expanded ? 320 : 44,
|
|
32
|
-
velocity: 0,
|
|
33
|
-
x: 0,
|
|
34
|
-
y: 0,
|
|
35
|
-
vx: 0,
|
|
36
|
-
vy: 0,
|
|
37
|
-
pullX: 0,
|
|
38
|
-
pullY: 0,
|
|
39
|
-
capacity: 320,
|
|
40
|
-
raf: 0,
|
|
41
|
-
});
|
|
42
|
-
const current = useRef({ expanded, reduced });
|
|
43
|
-
const wake = useRef<() => void>(() => {});
|
|
44
|
-
useLayoutEffect(() => {
|
|
45
|
-
const box = frame.current;
|
|
46
|
-
const label = pill.current;
|
|
47
|
-
const field = input.current;
|
|
48
|
-
if (!box || !label || !field) return;
|
|
49
|
-
const s = geometry.current;
|
|
50
|
-
let previous = 0;
|
|
51
|
-
const tick = (now: number) => {
|
|
52
|
-
const dt = previous ? Math.min(0.032, (now - previous) / 1000) : 1 / 60;
|
|
53
|
-
previous = now;
|
|
54
|
-
const target = current.current.expanded
|
|
55
|
-
? s.capacity
|
|
56
|
-
: Math.min(44, s.capacity);
|
|
57
|
-
const pullX = current.current.expanded ? 0 : s.pullX;
|
|
58
|
-
const pullY = current.current.expanded ? 0 : s.pullY;
|
|
59
|
-
const { stiffness, damping, mass } = springs.smooth;
|
|
60
|
-
if (current.current.reduced) {
|
|
61
|
-
s.width = target;
|
|
62
|
-
s.x = 0;
|
|
63
|
-
s.y = 0;
|
|
64
|
-
s.velocity = 0;
|
|
65
|
-
s.vx = 0;
|
|
66
|
-
s.vy = 0;
|
|
67
|
-
} else {
|
|
68
|
-
s.velocity +=
|
|
69
|
-
(((target - s.width) * stiffness - s.velocity * damping) / mass) * dt;
|
|
70
|
-
s.width += s.velocity * dt;
|
|
71
|
-
s.vx += (((pullX - s.x) * stiffness - s.vx * damping) / mass) * dt;
|
|
72
|
-
s.vy += (((pullY - s.y) * stiffness - s.vy * damping) / mass) * dt;
|
|
73
|
-
s.x += s.vx * dt;
|
|
74
|
-
s.y += s.vy * dt;
|
|
75
|
-
}
|
|
76
|
-
label.style.width = `${Math.max(0, s.width)}px`;
|
|
77
|
-
label.style.transform = `translate(${s.x}px, ${s.y}px)`;
|
|
78
|
-
/* One number drives the field's reveal; focus lands with the
|
|
79
|
-
expansion, so the caret arrives while the shape is growing. */
|
|
80
|
-
const progress = (s.width - 44) / Math.max(1, s.capacity - 44);
|
|
81
|
-
field.style.opacity = String(
|
|
82
|
-
Math.max(0, Math.min(1, (progress - 0.55) / 0.45)),
|
|
83
|
-
);
|
|
84
|
-
if (
|
|
85
|
-
Math.abs(s.width - target) < 0.05 &&
|
|
86
|
-
Math.abs(s.velocity) < 0.05 &&
|
|
87
|
-
Math.abs(s.x - pullX) +
|
|
88
|
-
Math.abs(s.y - pullY) +
|
|
89
|
-
Math.abs(s.vx) +
|
|
90
|
-
Math.abs(s.vy) <
|
|
91
|
-
0.05
|
|
92
|
-
) {
|
|
93
|
-
label.style.width = `${target}px`;
|
|
94
|
-
s.raf = 0;
|
|
95
|
-
previous = 0;
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
s.raf = requestAnimationFrame(tick);
|
|
99
|
-
};
|
|
100
|
-
wake.current = () => {
|
|
101
|
-
if (!s.raf) s.raf = requestAnimationFrame(tick);
|
|
102
|
-
};
|
|
103
|
-
const measure = () => {
|
|
104
|
-
s.capacity = Math.min(320, box.clientWidth);
|
|
105
|
-
wake.current();
|
|
106
|
-
};
|
|
107
|
-
measure();
|
|
108
|
-
const observer = new ResizeObserver(measure);
|
|
109
|
-
observer.observe(box);
|
|
110
|
-
return () => {
|
|
111
|
-
observer.disconnect();
|
|
112
|
-
cancelAnimationFrame(s.raf);
|
|
113
|
-
s.raf = 0;
|
|
114
|
-
};
|
|
115
|
-
}, []);
|
|
116
|
-
useEffect(() => {
|
|
117
|
-
current.current = { expanded, reduced };
|
|
118
|
-
wake.current();
|
|
119
|
-
}, [expanded, reduced]);
|
|
120
|
-
return (
|
|
121
|
-
<div
|
|
122
|
-
ref={frame}
|
|
123
|
-
className={cn(
|
|
124
|
-
"relative flex h-11 w-full max-w-xs items-center justify-center",
|
|
125
|
-
className,
|
|
126
|
-
)}
|
|
127
|
-
onPointerMove={(event) => {
|
|
128
|
-
if (expanded || reduced || event.pointerType !== "mouse") return;
|
|
129
|
-
// Measure the frame, which stays still; measuring the object being
|
|
130
|
-
// moved creates a feedback loop and a visible shiver.
|
|
131
|
-
const rect = event.currentTarget.getBoundingClientRect();
|
|
132
|
-
const dx = event.clientX - rect.left - rect.width / 2;
|
|
133
|
-
const dy = event.clientY - rect.top - rect.height / 2;
|
|
134
|
-
const distance = Math.hypot(dx, dy);
|
|
135
|
-
const pull = Math.max(0, 1 - distance / 72) ** 1.4 * 7;
|
|
136
|
-
geometry.current.pullX = distance ? (dx / distance) * pull : 0;
|
|
137
|
-
geometry.current.pullY = distance ? (dy / distance) * pull : 0;
|
|
138
|
-
wake.current();
|
|
139
|
-
}}
|
|
140
|
-
onPointerLeave={() => {
|
|
141
|
-
geometry.current.pullX = 0;
|
|
142
|
-
geometry.current.pullY = 0;
|
|
143
|
-
wake.current();
|
|
144
|
-
}}
|
|
145
|
-
>
|
|
146
|
-
<label
|
|
147
|
-
ref={pill}
|
|
148
|
-
className={cn(
|
|
149
|
-
"passui-search-pill control-field relative block h-11 max-w-full overflow-hidden rounded-full",
|
|
150
|
-
props.disabled && "opacity-40",
|
|
151
|
-
)}
|
|
152
|
-
style={{ width: expanded ? 320 : 44 }}
|
|
153
|
-
>
|
|
154
|
-
<SearchIcon
|
|
155
|
-
aria-hidden="true"
|
|
156
|
-
size={18}
|
|
157
|
-
className="text-label-secondary pointer-events-none absolute start-[13px] top-1/2 -translate-y-1/2"
|
|
158
|
-
/>
|
|
159
|
-
<input
|
|
160
|
-
{...props}
|
|
161
|
-
ref={(node) => {
|
|
162
|
-
input.current = node;
|
|
163
|
-
if (typeof inputRef === "function") inputRef(node);
|
|
164
|
-
else if (inputRef) inputRef.current = node;
|
|
165
|
-
}}
|
|
166
|
-
type="search"
|
|
167
|
-
placeholder={placeholder}
|
|
168
|
-
aria-label={
|
|
169
|
-
props["aria-labelledby"]
|
|
170
|
-
? undefined
|
|
171
|
-
: (props["aria-label"] ?? placeholder)
|
|
172
|
-
}
|
|
173
|
-
className="text-subheadline text-label placeholder:text-label-tertiary h-11 w-full min-w-0 bg-transparent ps-11 pe-3 outline-none"
|
|
174
|
-
onFocus={(event) => {
|
|
175
|
-
setExpanded(true);
|
|
176
|
-
props.onFocus?.(event);
|
|
177
|
-
}}
|
|
178
|
-
onBlur={(event) => {
|
|
179
|
-
if (!event.currentTarget.value) setExpanded(false);
|
|
180
|
-
props.onBlur?.(event);
|
|
181
|
-
}}
|
|
182
|
-
onKeyDown={(event) => {
|
|
183
|
-
props.onKeyDown?.(event);
|
|
184
|
-
if (
|
|
185
|
-
!event.defaultPrevented &&
|
|
186
|
-
event.key === "Escape" &&
|
|
187
|
-
!event.currentTarget.value
|
|
188
|
-
) {
|
|
189
|
-
setExpanded(false);
|
|
190
|
-
event.currentTarget.blur();
|
|
191
|
-
}
|
|
192
|
-
}}
|
|
193
|
-
/>
|
|
194
|
-
</label>
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
197
|
-
}
|