@thewhileloop/whileui 1.2.3 → 2.0.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 +246 -83
- package/dist/blocks/chat/chat.d.ts +3 -4
- package/dist/blocks/chat/chat.js +29 -17
- package/dist/blocks/chat/index.d.ts +0 -1
- package/dist/blocks/chat/index.js +0 -1
- package/dist/blocks/commerce/checkout-summary.d.ts +1 -2
- package/dist/blocks/commerce/checkout-summary.js +16 -4
- package/dist/blocks/commerce/feature-gate.d.ts +1 -2
- package/dist/blocks/commerce/feature-gate.js +14 -4
- package/dist/blocks/commerce/index.d.ts +0 -1
- package/dist/blocks/commerce/index.js +0 -1
- package/dist/blocks/commerce/metric-card.d.ts +3 -4
- package/dist/blocks/commerce/metric-card.js +7 -3
- package/dist/blocks/commerce/plan-toggle.d.ts +1 -2
- package/dist/blocks/commerce/plan-toggle.js +11 -9
- package/dist/blocks/commerce/pricing-card.d.ts +1 -2
- package/dist/blocks/commerce/pricing-card.js +23 -6
- package/dist/blocks/commerce/product-card.d.ts +1 -2
- package/dist/blocks/commerce/product-card.js +23 -9
- package/dist/blocks/commerce/subscription-card.d.ts +1 -2
- package/dist/blocks/commerce/subscription-card.js +6 -3
- package/dist/blocks/commerce/upgrade-banner.d.ts +1 -2
- package/dist/blocks/commerce/upgrade-banner.js +13 -3
- package/dist/blocks/commerce/usage-bar.d.ts +1 -2
- package/dist/blocks/commerce/usage-bar.js +4 -2
- package/dist/blocks/datepicker/date-range-picker-modal.d.ts +2 -3
- package/dist/blocks/datepicker/date-range-picker-modal.js +33 -7
- package/dist/blocks/datepicker/datepicker-inline.d.ts +1 -2
- package/dist/blocks/datepicker/datepicker-inline.js +9 -3
- package/dist/blocks/datepicker/datepicker-modal.d.ts +2 -3
- package/dist/blocks/datepicker/datepicker-modal.js +49 -17
- package/dist/blocks/datepicker/index.d.ts +0 -1
- package/dist/blocks/datepicker/index.js +0 -1
- package/dist/blocks/datepicker/use-calendar-theme.d.ts +0 -1
- package/dist/blocks/datepicker/use-calendar-theme.js +0 -1
- package/dist/blocks/layout/action-bar.d.ts +1 -2
- package/dist/blocks/layout/action-bar.js +0 -1
- package/dist/blocks/layout/app-shell.d.ts +1 -2
- package/dist/blocks/layout/app-shell.js +11 -5
- package/dist/blocks/layout/confirm-action-sheet.d.ts +1 -2
- package/dist/blocks/layout/confirm-action-sheet.js +18 -6
- package/dist/blocks/layout/content-skeleton.d.ts +1 -2
- package/dist/blocks/layout/content-skeleton.js +22 -9
- package/dist/blocks/layout/docked-input.d.ts +11 -0
- package/dist/blocks/layout/docked-input.js +27 -0
- package/dist/blocks/layout/empty-state.d.ts +1 -2
- package/dist/blocks/layout/empty-state.js +10 -5
- package/dist/blocks/layout/error-boundary.d.ts +1 -2
- package/dist/blocks/layout/error-boundary.js +0 -2
- package/dist/blocks/layout/error-state.d.ts +1 -2
- package/dist/blocks/layout/error-state.js +0 -2
- package/dist/blocks/layout/form-modal-screen.d.ts +1 -2
- package/dist/blocks/layout/form-modal-screen.js +24 -21
- package/dist/blocks/layout/index.d.ts +2 -2
- package/dist/blocks/layout/index.js +2 -2
- package/dist/blocks/layout/keyboard-aware-screen.d.ts +14 -0
- package/dist/blocks/layout/keyboard-aware-screen.js +12 -0
- package/dist/blocks/layout/loading-screen.d.ts +1 -2
- package/dist/blocks/layout/loading-screen.js +6 -8
- package/dist/blocks/layout/page-skeleton.d.ts +1 -2
- package/dist/blocks/layout/page-skeleton.js +38 -20
- package/dist/blocks/layout/pull-to-refresh-scroll-view.d.ts +8 -4
- package/dist/blocks/layout/pull-to-refresh-scroll-view.js +17 -4
- package/dist/blocks/layout/screen-skeleton.d.ts +1 -2
- package/dist/blocks/layout/screen-skeleton.js +0 -1
- package/dist/blocks/layout/sheet.d.ts +9 -9
- package/dist/blocks/layout/sheet.js +51 -21
- package/dist/blocks/layout/smart-input.d.ts +6 -1
- package/dist/blocks/layout/smart-input.js +121 -9
- package/dist/blocks/lists/index.d.ts +0 -2
- package/dist/blocks/lists/index.js +0 -2
- package/dist/blocks/lists/list-item.d.ts +1 -2
- package/dist/blocks/lists/list-item.js +20 -6
- package/dist/blocks/lists/notification-item.d.ts +1 -2
- package/dist/blocks/lists/notification-item.js +19 -6
- package/dist/blocks/lists/timeline-feed.d.ts +1 -2
- package/dist/blocks/lists/timeline-feed.js +4 -2
- package/dist/blocks/media/index.d.ts +0 -1
- package/dist/blocks/media/index.js +0 -1
- package/dist/blocks/media/smart-image.d.ts +0 -1
- package/dist/blocks/media/smart-image.js +24 -8
- package/dist/blocks/navigation/bottom-nav.d.ts +1 -2
- package/dist/blocks/navigation/bottom-nav.js +7 -4
- package/dist/blocks/navigation/drawer-menu.d.ts +1 -2
- package/dist/blocks/navigation/drawer-menu.js +52 -15
- package/dist/blocks/navigation/floating-bottom-nav.d.ts +1 -2
- package/dist/blocks/navigation/floating-bottom-nav.js +14 -5
- package/dist/blocks/navigation/header.d.ts +2 -3
- package/dist/blocks/navigation/header.js +13 -5
- package/dist/blocks/navigation/index.d.ts +0 -2
- package/dist/blocks/navigation/index.js +0 -2
- package/dist/blocks/navigation/tab-bar.d.ts +1 -2
- package/dist/blocks/navigation/tab-bar.js +22 -10
- package/dist/blocks/splash/index.d.ts +0 -1
- package/dist/blocks/splash/index.js +0 -1
- package/dist/blocks/splash/splash-screen.d.ts +3 -4
- package/dist/blocks/splash/splash-screen.js +15 -11
- package/dist/components/accordion/accordion.d.ts +4 -5
- package/dist/components/accordion/accordion.js +6 -7
- package/dist/components/accordion/index.d.ts +0 -1
- package/dist/components/accordion/index.js +0 -1
- package/dist/components/alert/alert.d.ts +2 -3
- package/dist/components/alert/alert.js +19 -8
- package/dist/components/alert/index.d.ts +0 -1
- package/dist/components/alert/index.js +0 -1
- package/dist/components/alert-dialog/alert-dialog.d.ts +9 -10
- package/dist/components/alert-dialog/alert-dialog.js +175 -51
- package/dist/components/alert-dialog/index.d.ts +0 -1
- package/dist/components/alert-dialog/index.js +0 -1
- package/dist/components/aspect-ratio/aspect-ratio.d.ts +1 -2
- package/dist/components/aspect-ratio/aspect-ratio.js +0 -3
- package/dist/components/aspect-ratio/index.d.ts +0 -1
- package/dist/components/aspect-ratio/index.js +0 -1
- package/dist/components/avatar/avatar.d.ts +2 -3
- package/dist/components/avatar/avatar.js +7 -8
- package/dist/components/avatar/index.d.ts +0 -1
- package/dist/components/avatar/index.js +0 -1
- package/dist/components/badge/badge.d.ts +6 -7
- package/dist/components/badge/badge.js +21 -9
- package/dist/components/badge/index.d.ts +0 -1
- package/dist/components/badge/index.js +0 -1
- package/dist/components/button/button.d.ts +11 -10
- package/dist/components/button/button.js +62 -33
- package/dist/components/button/index.d.ts +0 -1
- package/dist/components/button/index.js +0 -1
- package/dist/components/card/card.d.ts +5 -3
- package/dist/components/card/card.js +28 -14
- package/dist/components/card/index.d.ts +0 -1
- package/dist/components/card/index.js +0 -1
- package/dist/components/checkbox/checkbox.d.ts +1 -2
- package/dist/components/checkbox/checkbox.js +15 -2
- package/dist/components/checkbox/index.d.ts +0 -1
- package/dist/components/checkbox/index.js +0 -1
- package/dist/components/collapsible/collapsible.d.ts +4 -4
- package/dist/components/collapsible/collapsible.js +8 -11
- package/dist/components/collapsible/index.d.ts +0 -1
- package/dist/components/collapsible/index.js +0 -1
- package/dist/components/container/container.d.ts +146 -0
- package/dist/components/container/container.js +43 -0
- package/dist/components/container/index.d.ts +1 -0
- package/dist/components/container/index.js +1 -0
- package/dist/components/context-menu/context-menu.d.ts +6 -7
- package/dist/components/context-menu/context-menu.js +42 -12
- package/dist/components/context-menu/index.d.ts +0 -1
- package/dist/components/context-menu/index.js +0 -1
- package/dist/components/data-row/data-row.d.ts +0 -1
- package/dist/components/data-row/data-row.js +35 -17
- package/dist/components/data-row/index.d.ts +0 -1
- package/dist/components/data-row/index.js +0 -1
- package/dist/components/dialog/dialog.d.ts +8 -9
- package/dist/components/dialog/dialog.js +48 -24
- package/dist/components/dialog/index.d.ts +0 -1
- package/dist/components/dialog/index.js +0 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +6 -7
- package/dist/components/dropdown-menu/dropdown-menu.js +45 -11
- package/dist/components/dropdown-menu/index.d.ts +0 -1
- package/dist/components/dropdown-menu/index.js +0 -1
- package/dist/components/form-field/form-field.d.ts +0 -1
- package/dist/components/form-field/form-field.js +26 -13
- package/dist/components/form-field/index.d.ts +0 -1
- package/dist/components/form-field/index.js +0 -1
- package/dist/components/hover-card/hover-card.d.ts +1 -2
- package/dist/components/hover-card/hover-card.js +12 -3
- package/dist/components/hover-card/index.d.ts +0 -1
- package/dist/components/hover-card/index.js +0 -1
- package/dist/components/input/index.d.ts +0 -1
- package/dist/components/input/index.js +0 -1
- package/dist/components/input/input.d.ts +2 -3
- package/dist/components/input/input.js +18 -3
- package/dist/components/label/index.d.ts +0 -1
- package/dist/components/label/index.js +0 -1
- package/dist/components/label/label.d.ts +0 -1
- package/dist/components/label/label.js +0 -1
- package/dist/components/labeled-field/index.d.ts +0 -1
- package/dist/components/labeled-field/index.js +0 -1
- package/dist/components/labeled-field/labeled-field.d.ts +1 -2
- package/dist/components/labeled-field/labeled-field.js +10 -2
- package/dist/components/menubar/index.d.ts +0 -1
- package/dist/components/menubar/index.js +0 -1
- package/dist/components/menubar/menubar.d.ts +7 -8
- package/dist/components/menubar/menubar.js +48 -15
- package/dist/components/numeric-input/index.d.ts +0 -1
- package/dist/components/numeric-input/index.js +0 -1
- package/dist/components/numeric-input/numeric-input.d.ts +6 -5
- package/dist/components/numeric-input/numeric-input.js +55 -26
- package/dist/components/otp-input/index.d.ts +0 -1
- package/dist/components/otp-input/index.js +0 -1
- package/dist/components/otp-input/otp-input.d.ts +3 -4
- package/dist/components/otp-input/otp-input.js +13 -9
- package/dist/components/popover/index.d.ts +0 -1
- package/dist/components/popover/index.js +0 -1
- package/dist/components/popover/popover.d.ts +4 -2
- package/dist/components/popover/popover.js +21 -4
- package/dist/components/pressable/index.d.ts +0 -1
- package/dist/components/pressable/index.js +0 -1
- package/dist/components/pressable/pressable.d.ts +7 -1
- package/dist/components/pressable/pressable.js +47 -4
- package/dist/components/progress/index.d.ts +0 -1
- package/dist/components/progress/index.js +0 -1
- package/dist/components/progress/progress.d.ts +0 -1
- package/dist/components/progress/progress.js +5 -2
- package/dist/components/radio-group/index.d.ts +0 -1
- package/dist/components/radio-group/index.js +0 -1
- package/dist/components/radio-group/radio-group.d.ts +2 -3
- package/dist/components/radio-group/radio-group.js +16 -7
- package/dist/components/row/index.d.ts +0 -1
- package/dist/components/row/index.js +0 -1
- package/dist/components/row/row.d.ts +0 -1
- package/dist/components/row/row.js +0 -1
- package/dist/components/segmented-control/index.d.ts +0 -1
- package/dist/components/segmented-control/index.js +0 -1
- package/dist/components/segmented-control/segmented-control.d.ts +7 -8
- package/dist/components/segmented-control/segmented-control.js +57 -24
- package/dist/components/select/index.d.ts +0 -1
- package/dist/components/select/index.js +0 -1
- package/dist/components/select/select.d.ts +15 -7
- package/dist/components/select/select.js +53 -11
- package/dist/components/separator/index.d.ts +0 -1
- package/dist/components/separator/index.js +0 -1
- package/dist/components/separator/separator.d.ts +0 -1
- package/dist/components/separator/separator.js +0 -1
- package/dist/components/skeleton/index.d.ts +0 -1
- package/dist/components/skeleton/index.js +0 -1
- package/dist/components/skeleton/skeleton.d.ts +3 -4
- package/dist/components/skeleton/skeleton.js +7 -8
- package/dist/components/spinner/index.d.ts +0 -1
- package/dist/components/spinner/index.js +0 -1
- package/dist/components/spinner/spinner.d.ts +1 -2
- package/dist/components/spinner/spinner.js +4 -2
- package/dist/components/stack/index.d.ts +0 -1
- package/dist/components/stack/index.js +0 -1
- package/dist/components/stack/stack.d.ts +0 -1
- package/dist/components/stack/stack.js +0 -1
- package/dist/components/switch/index.d.ts +0 -1
- package/dist/components/switch/index.js +0 -1
- package/dist/components/switch/switch.d.ts +1 -2
- package/dist/components/switch/switch.js +21 -2
- package/dist/components/tabs/index.d.ts +0 -1
- package/dist/components/tabs/index.js +0 -1
- package/dist/components/tabs/tabs.d.ts +6 -7
- package/dist/components/tabs/tabs.js +42 -12
- package/dist/components/text/index.d.ts +0 -1
- package/dist/components/text/index.js +0 -1
- package/dist/components/text/text.d.ts +0 -1
- package/dist/components/text/text.js +0 -1
- package/dist/components/textarea/index.d.ts +0 -1
- package/dist/components/textarea/index.js +0 -1
- package/dist/components/textarea/textarea.d.ts +2 -3
- package/dist/components/textarea/textarea.js +16 -8
- package/dist/components/toast/index.d.ts +0 -1
- package/dist/components/toast/index.js +0 -1
- package/dist/components/toast/toast.d.ts +5 -6
- package/dist/components/toast/toast.js +40 -24
- package/dist/components/toggle/index.d.ts +0 -1
- package/dist/components/toggle/index.js +0 -1
- package/dist/components/toggle/toggle.d.ts +6 -7
- package/dist/components/toggle/toggle.js +32 -16
- package/dist/components/toggle-group/index.d.ts +0 -1
- package/dist/components/toggle-group/index.js +0 -1
- package/dist/components/toggle-group/toggle-group.d.ts +7 -8
- package/dist/components/toggle-group/toggle-group.js +36 -19
- package/dist/components/tooltip/index.d.ts +0 -1
- package/dist/components/tooltip/index.js +0 -1
- package/dist/components/tooltip/tooltip.d.ts +1 -2
- package/dist/components/tooltip/tooltip.js +20 -3
- package/dist/components/view/index.d.ts +0 -1
- package/dist/components/view/index.js +0 -1
- package/dist/components/view/view.d.ts +0 -1
- package/dist/components/view/view.js +0 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.js +9 -7
- package/dist/lib/cn.d.ts +0 -1
- package/dist/lib/cn.js +0 -1
- package/dist/lib/compose-event-handlers.d.ts +15 -0
- package/dist/lib/compose-event-handlers.js +20 -0
- package/dist/lib/focus-ring.d.ts +25 -0
- package/dist/lib/focus-ring.js +25 -0
- package/dist/lib/font-context.d.ts +1 -1
- package/dist/lib/font-context.js +6 -4
- package/dist/lib/frosted-surface.d.ts +0 -1
- package/dist/lib/frosted-surface.js +31 -6
- package/dist/lib/interaction-tokens.d.ts +12 -1
- package/dist/lib/interaction-tokens.js +27 -13
- package/dist/lib/motion-policy.d.ts +25 -0
- package/dist/lib/motion-policy.js +97 -0
- package/dist/lib/overlay-insets.d.ts +17 -0
- package/dist/lib/overlay-insets.js +23 -0
- package/dist/lib/portal.d.ts +0 -1
- package/dist/lib/portal.js +0 -1
- package/dist/lib/react-native-classname.d.ts +0 -1
- package/dist/lib/react-native-classname.js +0 -1
- package/dist/lib/recipes.d.ts +30 -0
- package/dist/lib/recipes.js +138 -0
- package/dist/lib/tap-only.d.ts +11 -0
- package/dist/lib/tap-only.js +24 -0
- package/dist/lib/theme-bridge.d.ts +0 -1
- package/dist/lib/theme-bridge.js +11 -3
- package/dist/lib/theme-colors.d.ts +2 -46
- package/dist/lib/theme-colors.js +25 -226
- package/dist/lib/theme-contract.d.ts +78 -0
- package/dist/lib/theme-contract.js +481 -0
- package/dist/lib/theme-derive.d.ts +4 -0
- package/dist/lib/theme-derive.js +80 -0
- package/dist/lib/theme-presets.d.ts +31 -0
- package/dist/lib/theme-presets.js +221 -0
- package/dist/lib/tv.d.ts +0 -1
- package/dist/lib/tv.js +0 -1
- package/dist/lib/visual-token-contract.d.ts +110 -0
- package/dist/lib/visual-token-contract.js +583 -0
- package/dist/lib/visual-tokens.d.ts +2 -38
- package/dist/lib/visual-tokens.js +22 -75
- package/dist/tokens.d.ts +4 -0
- package/dist/tokens.js +6 -0
- package/dist/vite.d.ts +0 -1
- package/dist/vite.js +0 -1
- package/package.json +30 -20
- package/dist/blocks/auth/forgot-password-form.d.ts +0 -10
- package/dist/blocks/auth/forgot-password-form.d.ts.map +0 -1
- package/dist/blocks/auth/forgot-password-form.js +0 -17
- package/dist/blocks/auth/forgot-password-form.js.map +0 -1
- package/dist/blocks/auth/index.d.ts +0 -8
- package/dist/blocks/auth/index.d.ts.map +0 -1
- package/dist/blocks/auth/index.js +0 -8
- package/dist/blocks/auth/index.js.map +0 -1
- package/dist/blocks/auth/reset-password-form.d.ts +0 -9
- package/dist/blocks/auth/reset-password-form.d.ts.map +0 -1
- package/dist/blocks/auth/reset-password-form.js +0 -16
- package/dist/blocks/auth/reset-password-form.js.map +0 -1
- package/dist/blocks/auth/sign-in-form.d.ts +0 -17
- package/dist/blocks/auth/sign-in-form.d.ts.map +0 -1
- package/dist/blocks/auth/sign-in-form.js +0 -19
- package/dist/blocks/auth/sign-in-form.js.map +0 -1
- package/dist/blocks/auth/sign-up-form.d.ts +0 -17
- package/dist/blocks/auth/sign-up-form.d.ts.map +0 -1
- package/dist/blocks/auth/sign-up-form.js +0 -21
- package/dist/blocks/auth/sign-up-form.js.map +0 -1
- package/dist/blocks/auth/social-connections.d.ts +0 -10
- package/dist/blocks/auth/social-connections.d.ts.map +0 -1
- package/dist/blocks/auth/social-connections.js +0 -8
- package/dist/blocks/auth/social-connections.js.map +0 -1
- package/dist/blocks/auth/user-menu.d.ts +0 -12
- package/dist/blocks/auth/user-menu.d.ts.map +0 -1
- package/dist/blocks/auth/user-menu.js +0 -10
- package/dist/blocks/auth/user-menu.js.map +0 -1
- package/dist/blocks/auth/verify-email-form.d.ts +0 -10
- package/dist/blocks/auth/verify-email-form.d.ts.map +0 -1
- package/dist/blocks/auth/verify-email-form.js +0 -17
- package/dist/blocks/auth/verify-email-form.js.map +0 -1
- package/dist/blocks/chat/chat.d.ts.map +0 -1
- package/dist/blocks/chat/chat.js.map +0 -1
- package/dist/blocks/chat/index.d.ts.map +0 -1
- package/dist/blocks/chat/index.js.map +0 -1
- package/dist/blocks/commerce/checkout-summary.d.ts.map +0 -1
- package/dist/blocks/commerce/checkout-summary.js.map +0 -1
- package/dist/blocks/commerce/feature-gate.d.ts.map +0 -1
- package/dist/blocks/commerce/feature-gate.js.map +0 -1
- package/dist/blocks/commerce/index.d.ts.map +0 -1
- package/dist/blocks/commerce/index.js.map +0 -1
- package/dist/blocks/commerce/metric-card.d.ts.map +0 -1
- package/dist/blocks/commerce/metric-card.js.map +0 -1
- package/dist/blocks/commerce/plan-toggle.d.ts.map +0 -1
- package/dist/blocks/commerce/plan-toggle.js.map +0 -1
- package/dist/blocks/commerce/pricing-card.d.ts.map +0 -1
- package/dist/blocks/commerce/pricing-card.js.map +0 -1
- package/dist/blocks/commerce/product-card.d.ts.map +0 -1
- package/dist/blocks/commerce/product-card.js.map +0 -1
- package/dist/blocks/commerce/subscription-card.d.ts.map +0 -1
- package/dist/blocks/commerce/subscription-card.js.map +0 -1
- package/dist/blocks/commerce/upgrade-banner.d.ts.map +0 -1
- package/dist/blocks/commerce/upgrade-banner.js.map +0 -1
- package/dist/blocks/commerce/usage-bar.d.ts.map +0 -1
- package/dist/blocks/commerce/usage-bar.js.map +0 -1
- package/dist/blocks/datepicker/date-range-picker-modal.d.ts.map +0 -1
- package/dist/blocks/datepicker/date-range-picker-modal.js.map +0 -1
- package/dist/blocks/datepicker/datepicker-inline.d.ts.map +0 -1
- package/dist/blocks/datepicker/datepicker-inline.js.map +0 -1
- package/dist/blocks/datepicker/datepicker-modal.d.ts.map +0 -1
- package/dist/blocks/datepicker/datepicker-modal.js.map +0 -1
- package/dist/blocks/datepicker/index.d.ts.map +0 -1
- package/dist/blocks/datepicker/index.js.map +0 -1
- package/dist/blocks/datepicker/use-calendar-theme.d.ts.map +0 -1
- package/dist/blocks/datepicker/use-calendar-theme.js.map +0 -1
- package/dist/blocks/layout/action-bar.d.ts.map +0 -1
- package/dist/blocks/layout/action-bar.js.map +0 -1
- package/dist/blocks/layout/app-shell.d.ts.map +0 -1
- package/dist/blocks/layout/app-shell.js.map +0 -1
- package/dist/blocks/layout/confirm-action-sheet.d.ts.map +0 -1
- package/dist/blocks/layout/confirm-action-sheet.js.map +0 -1
- package/dist/blocks/layout/content-skeleton.d.ts.map +0 -1
- package/dist/blocks/layout/content-skeleton.js.map +0 -1
- package/dist/blocks/layout/empty-state.d.ts.map +0 -1
- package/dist/blocks/layout/empty-state.js.map +0 -1
- package/dist/blocks/layout/error-boundary.d.ts.map +0 -1
- package/dist/blocks/layout/error-boundary.js.map +0 -1
- package/dist/blocks/layout/error-state.d.ts.map +0 -1
- package/dist/blocks/layout/error-state.js.map +0 -1
- package/dist/blocks/layout/form-modal-screen.d.ts.map +0 -1
- package/dist/blocks/layout/form-modal-screen.js.map +0 -1
- package/dist/blocks/layout/index.d.ts.map +0 -1
- package/dist/blocks/layout/index.js.map +0 -1
- package/dist/blocks/layout/loading-screen.d.ts.map +0 -1
- package/dist/blocks/layout/loading-screen.js.map +0 -1
- package/dist/blocks/layout/onboarding-screen.d.ts +0 -19
- package/dist/blocks/layout/onboarding-screen.d.ts.map +0 -1
- package/dist/blocks/layout/onboarding-screen.js +0 -35
- package/dist/blocks/layout/onboarding-screen.js.map +0 -1
- package/dist/blocks/layout/page-skeleton.d.ts.map +0 -1
- package/dist/blocks/layout/page-skeleton.js.map +0 -1
- package/dist/blocks/layout/pull-to-refresh-scroll-view.d.ts.map +0 -1
- package/dist/blocks/layout/pull-to-refresh-scroll-view.js.map +0 -1
- package/dist/blocks/layout/screen-skeleton.d.ts.map +0 -1
- package/dist/blocks/layout/screen-skeleton.js.map +0 -1
- package/dist/blocks/layout/sheet.d.ts.map +0 -1
- package/dist/blocks/layout/sheet.js.map +0 -1
- package/dist/blocks/layout/smart-image.d.ts +0 -9
- package/dist/blocks/layout/smart-image.d.ts.map +0 -1
- package/dist/blocks/layout/smart-image.js +0 -23
- package/dist/blocks/layout/smart-image.js.map +0 -1
- package/dist/blocks/layout/smart-input.d.ts.map +0 -1
- package/dist/blocks/layout/smart-input.js.map +0 -1
- package/dist/blocks/lists/index.d.ts.map +0 -1
- package/dist/blocks/lists/index.js.map +0 -1
- package/dist/blocks/lists/list-item.d.ts.map +0 -1
- package/dist/blocks/lists/list-item.js.map +0 -1
- package/dist/blocks/lists/notification-item.d.ts.map +0 -1
- package/dist/blocks/lists/notification-item.js.map +0 -1
- package/dist/blocks/lists/swipeable-item.d.ts +0 -17
- package/dist/blocks/lists/swipeable-item.d.ts.map +0 -1
- package/dist/blocks/lists/swipeable-item.js +0 -65
- package/dist/blocks/lists/swipeable-item.js.map +0 -1
- package/dist/blocks/lists/timeline-feed.d.ts.map +0 -1
- package/dist/blocks/lists/timeline-feed.js.map +0 -1
- package/dist/blocks/media/index.d.ts.map +0 -1
- package/dist/blocks/media/index.js.map +0 -1
- package/dist/blocks/media/smart-image.d.ts.map +0 -1
- package/dist/blocks/media/smart-image.js.map +0 -1
- package/dist/blocks/navigation/bottom-nav.d.ts.map +0 -1
- package/dist/blocks/navigation/bottom-nav.js.map +0 -1
- package/dist/blocks/navigation/drawer-menu.d.ts.map +0 -1
- package/dist/blocks/navigation/drawer-menu.js.map +0 -1
- package/dist/blocks/navigation/floating-bottom-nav.d.ts.map +0 -1
- package/dist/blocks/navigation/floating-bottom-nav.js.map +0 -1
- package/dist/blocks/navigation/header.d.ts.map +0 -1
- package/dist/blocks/navigation/header.js.map +0 -1
- package/dist/blocks/navigation/index.d.ts.map +0 -1
- package/dist/blocks/navigation/index.js.map +0 -1
- package/dist/blocks/navigation/navigation-sidebar.d.ts +0 -25
- package/dist/blocks/navigation/navigation-sidebar.d.ts.map +0 -1
- package/dist/blocks/navigation/navigation-sidebar.js +0 -18
- package/dist/blocks/navigation/navigation-sidebar.js.map +0 -1
- package/dist/blocks/navigation/tab-bar.d.ts.map +0 -1
- package/dist/blocks/navigation/tab-bar.js.map +0 -1
- package/dist/blocks/profile/account-card.d.ts +0 -11
- package/dist/blocks/profile/account-card.d.ts.map +0 -1
- package/dist/blocks/profile/account-card.js +0 -10
- package/dist/blocks/profile/account-card.js.map +0 -1
- package/dist/blocks/profile/index.d.ts +0 -5
- package/dist/blocks/profile/index.d.ts.map +0 -1
- package/dist/blocks/profile/index.js +0 -5
- package/dist/blocks/profile/index.js.map +0 -1
- package/dist/blocks/profile/profile-header.d.ts +0 -27
- package/dist/blocks/profile/profile-header.d.ts.map +0 -1
- package/dist/blocks/profile/profile-header.js +0 -11
- package/dist/blocks/profile/profile-header.js.map +0 -1
- package/dist/blocks/profile/settings-item.d.ts +0 -15
- package/dist/blocks/profile/settings-item.d.ts.map +0 -1
- package/dist/blocks/profile/settings-item.js +0 -11
- package/dist/blocks/profile/settings-item.js.map +0 -1
- package/dist/blocks/profile/settings-section.d.ts +0 -7
- package/dist/blocks/profile/settings-section.d.ts.map +0 -1
- package/dist/blocks/profile/settings-section.js +0 -9
- package/dist/blocks/profile/settings-section.js.map +0 -1
- package/dist/blocks/splash/index.d.ts.map +0 -1
- package/dist/blocks/splash/index.js.map +0 -1
- package/dist/blocks/splash/splash-screen.d.ts.map +0 -1
- package/dist/blocks/splash/splash-screen.js.map +0 -1
- package/dist/components/accordion/accordion.d.ts.map +0 -1
- package/dist/components/accordion/accordion.js.map +0 -1
- package/dist/components/accordion/index.d.ts.map +0 -1
- package/dist/components/accordion/index.js.map +0 -1
- package/dist/components/alert/alert.d.ts.map +0 -1
- package/dist/components/alert/alert.js.map +0 -1
- package/dist/components/alert/index.d.ts.map +0 -1
- package/dist/components/alert/index.js.map +0 -1
- package/dist/components/alert-dialog/alert-dialog.d.ts.map +0 -1
- package/dist/components/alert-dialog/alert-dialog.js.map +0 -1
- package/dist/components/alert-dialog/index.d.ts.map +0 -1
- package/dist/components/alert-dialog/index.js.map +0 -1
- package/dist/components/aspect-ratio/aspect-ratio.d.ts.map +0 -1
- package/dist/components/aspect-ratio/aspect-ratio.js.map +0 -1
- package/dist/components/aspect-ratio/index.d.ts.map +0 -1
- package/dist/components/aspect-ratio/index.js.map +0 -1
- package/dist/components/avatar/avatar.d.ts.map +0 -1
- package/dist/components/avatar/avatar.js.map +0 -1
- package/dist/components/avatar/index.d.ts.map +0 -1
- package/dist/components/avatar/index.js.map +0 -1
- package/dist/components/badge/badge.d.ts.map +0 -1
- package/dist/components/badge/badge.js.map +0 -1
- package/dist/components/badge/index.d.ts.map +0 -1
- package/dist/components/badge/index.js.map +0 -1
- package/dist/components/box/box.d.ts +0 -143
- package/dist/components/box/box.d.ts.map +0 -1
- package/dist/components/box/box.js +0 -38
- package/dist/components/box/box.js.map +0 -1
- package/dist/components/box/index.d.ts +0 -2
- package/dist/components/box/index.d.ts.map +0 -1
- package/dist/components/box/index.js +0 -2
- package/dist/components/box/index.js.map +0 -1
- package/dist/components/button/button.d.ts.map +0 -1
- package/dist/components/button/button.js.map +0 -1
- package/dist/components/button/index.d.ts.map +0 -1
- package/dist/components/button/index.js.map +0 -1
- package/dist/components/card/card.d.ts.map +0 -1
- package/dist/components/card/card.js.map +0 -1
- package/dist/components/card/index.d.ts.map +0 -1
- package/dist/components/card/index.js.map +0 -1
- package/dist/components/checkbox/checkbox.d.ts.map +0 -1
- package/dist/components/checkbox/checkbox.js.map +0 -1
- package/dist/components/checkbox/index.d.ts.map +0 -1
- package/dist/components/checkbox/index.js.map +0 -1
- package/dist/components/collapsible/collapsible.d.ts.map +0 -1
- package/dist/components/collapsible/collapsible.js.map +0 -1
- package/dist/components/collapsible/index.d.ts.map +0 -1
- package/dist/components/collapsible/index.js.map +0 -1
- package/dist/components/context-menu/context-menu.d.ts.map +0 -1
- package/dist/components/context-menu/context-menu.js.map +0 -1
- package/dist/components/context-menu/index.d.ts.map +0 -1
- package/dist/components/context-menu/index.js.map +0 -1
- package/dist/components/data-row/data-row.d.ts.map +0 -1
- package/dist/components/data-row/data-row.js.map +0 -1
- package/dist/components/data-row/index.d.ts.map +0 -1
- package/dist/components/data-row/index.js.map +0 -1
- package/dist/components/dialog/dialog.d.ts.map +0 -1
- package/dist/components/dialog/dialog.js.map +0 -1
- package/dist/components/dialog/index.d.ts.map +0 -1
- package/dist/components/dialog/index.js.map +0 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +0 -1
- package/dist/components/dropdown-menu/dropdown-menu.js.map +0 -1
- package/dist/components/dropdown-menu/index.d.ts.map +0 -1
- package/dist/components/dropdown-menu/index.js.map +0 -1
- package/dist/components/form-field/form-field.d.ts.map +0 -1
- package/dist/components/form-field/form-field.js.map +0 -1
- package/dist/components/form-field/index.d.ts.map +0 -1
- package/dist/components/form-field/index.js.map +0 -1
- package/dist/components/hover-card/hover-card.d.ts.map +0 -1
- package/dist/components/hover-card/hover-card.js.map +0 -1
- package/dist/components/hover-card/index.d.ts.map +0 -1
- package/dist/components/hover-card/index.js.map +0 -1
- package/dist/components/input/index.d.ts.map +0 -1
- package/dist/components/input/index.js.map +0 -1
- package/dist/components/input/input.d.ts.map +0 -1
- package/dist/components/input/input.js.map +0 -1
- package/dist/components/label/index.d.ts.map +0 -1
- package/dist/components/label/index.js.map +0 -1
- package/dist/components/label/label.d.ts.map +0 -1
- package/dist/components/label/label.js.map +0 -1
- package/dist/components/labeled-field/index.d.ts.map +0 -1
- package/dist/components/labeled-field/index.js.map +0 -1
- package/dist/components/labeled-field/labeled-field.d.ts.map +0 -1
- package/dist/components/labeled-field/labeled-field.js.map +0 -1
- package/dist/components/layout/index.d.ts +0 -2
- package/dist/components/layout/index.d.ts.map +0 -1
- package/dist/components/layout/index.js +0 -2
- package/dist/components/layout/index.js.map +0 -1
- package/dist/components/layout/layout.d.ts +0 -395
- package/dist/components/layout/layout.d.ts.map +0 -1
- package/dist/components/layout/layout.js +0 -93
- package/dist/components/layout/layout.js.map +0 -1
- package/dist/components/menubar/index.d.ts.map +0 -1
- package/dist/components/menubar/index.js.map +0 -1
- package/dist/components/menubar/menubar.d.ts.map +0 -1
- package/dist/components/menubar/menubar.js.map +0 -1
- package/dist/components/numeric-input/index.d.ts.map +0 -1
- package/dist/components/numeric-input/index.js.map +0 -1
- package/dist/components/numeric-input/numeric-input.d.ts.map +0 -1
- package/dist/components/numeric-input/numeric-input.js.map +0 -1
- package/dist/components/otp-input/index.d.ts.map +0 -1
- package/dist/components/otp-input/index.js.map +0 -1
- package/dist/components/otp-input/otp-input.d.ts.map +0 -1
- package/dist/components/otp-input/otp-input.js.map +0 -1
- package/dist/components/popover/index.d.ts.map +0 -1
- package/dist/components/popover/index.js.map +0 -1
- package/dist/components/popover/popover.d.ts.map +0 -1
- package/dist/components/popover/popover.js.map +0 -1
- package/dist/components/pressable/index.d.ts.map +0 -1
- package/dist/components/pressable/index.js.map +0 -1
- package/dist/components/pressable/pressable.d.ts.map +0 -1
- package/dist/components/pressable/pressable.js.map +0 -1
- package/dist/components/progress/index.d.ts.map +0 -1
- package/dist/components/progress/index.js.map +0 -1
- package/dist/components/progress/progress.d.ts.map +0 -1
- package/dist/components/progress/progress.js.map +0 -1
- package/dist/components/radio-group/index.d.ts.map +0 -1
- package/dist/components/radio-group/index.js.map +0 -1
- package/dist/components/radio-group/radio-group.d.ts.map +0 -1
- package/dist/components/radio-group/radio-group.js.map +0 -1
- package/dist/components/row/index.d.ts.map +0 -1
- package/dist/components/row/index.js.map +0 -1
- package/dist/components/row/row.d.ts.map +0 -1
- package/dist/components/row/row.js.map +0 -1
- package/dist/components/segmented-control/index.d.ts.map +0 -1
- package/dist/components/segmented-control/index.js.map +0 -1
- package/dist/components/segmented-control/segmented-control.d.ts.map +0 -1
- package/dist/components/segmented-control/segmented-control.js.map +0 -1
- package/dist/components/select/index.d.ts.map +0 -1
- package/dist/components/select/index.js.map +0 -1
- package/dist/components/select/select.d.ts.map +0 -1
- package/dist/components/select/select.js.map +0 -1
- package/dist/components/separator/index.d.ts.map +0 -1
- package/dist/components/separator/index.js.map +0 -1
- package/dist/components/separator/separator.d.ts.map +0 -1
- package/dist/components/separator/separator.js.map +0 -1
- package/dist/components/skeleton/index.d.ts.map +0 -1
- package/dist/components/skeleton/index.js.map +0 -1
- package/dist/components/skeleton/skeleton.d.ts.map +0 -1
- package/dist/components/skeleton/skeleton.js.map +0 -1
- package/dist/components/spinner/index.d.ts.map +0 -1
- package/dist/components/spinner/index.js.map +0 -1
- package/dist/components/spinner/spinner.d.ts.map +0 -1
- package/dist/components/spinner/spinner.js.map +0 -1
- package/dist/components/stack/index.d.ts.map +0 -1
- package/dist/components/stack/index.js.map +0 -1
- package/dist/components/stack/stack.d.ts.map +0 -1
- package/dist/components/stack/stack.js.map +0 -1
- package/dist/components/switch/index.d.ts.map +0 -1
- package/dist/components/switch/index.js.map +0 -1
- package/dist/components/switch/switch.d.ts.map +0 -1
- package/dist/components/switch/switch.js.map +0 -1
- package/dist/components/tabs/index.d.ts.map +0 -1
- package/dist/components/tabs/index.js.map +0 -1
- package/dist/components/tabs/tabs.d.ts.map +0 -1
- package/dist/components/tabs/tabs.js.map +0 -1
- package/dist/components/text/index.d.ts.map +0 -1
- package/dist/components/text/index.js.map +0 -1
- package/dist/components/text/text.d.ts.map +0 -1
- package/dist/components/text/text.js.map +0 -1
- package/dist/components/textarea/index.d.ts.map +0 -1
- package/dist/components/textarea/index.js.map +0 -1
- package/dist/components/textarea/textarea.d.ts.map +0 -1
- package/dist/components/textarea/textarea.js.map +0 -1
- package/dist/components/toast/index.d.ts.map +0 -1
- package/dist/components/toast/index.js.map +0 -1
- package/dist/components/toast/toast.d.ts.map +0 -1
- package/dist/components/toast/toast.js.map +0 -1
- package/dist/components/toggle/index.d.ts.map +0 -1
- package/dist/components/toggle/index.js.map +0 -1
- package/dist/components/toggle/toggle.d.ts.map +0 -1
- package/dist/components/toggle/toggle.js.map +0 -1
- package/dist/components/toggle-group/index.d.ts.map +0 -1
- package/dist/components/toggle-group/index.js.map +0 -1
- package/dist/components/toggle-group/toggle-group.d.ts.map +0 -1
- package/dist/components/toggle-group/toggle-group.js.map +0 -1
- package/dist/components/tooltip/index.d.ts.map +0 -1
- package/dist/components/tooltip/index.js.map +0 -1
- package/dist/components/tooltip/tooltip.d.ts.map +0 -1
- package/dist/components/tooltip/tooltip.js.map +0 -1
- package/dist/components/view/index.d.ts.map +0 -1
- package/dist/components/view/index.js.map +0 -1
- package/dist/components/view/view.d.ts.map +0 -1
- package/dist/components/view/view.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/cn.d.ts.map +0 -1
- package/dist/lib/cn.js.map +0 -1
- package/dist/lib/font-context.d.ts.map +0 -1
- package/dist/lib/font-context.js.map +0 -1
- package/dist/lib/frosted-surface.d.ts.map +0 -1
- package/dist/lib/frosted-surface.js.map +0 -1
- package/dist/lib/index.d.ts +0 -6
- package/dist/lib/index.d.ts.map +0 -1
- package/dist/lib/index.js +0 -6
- package/dist/lib/index.js.map +0 -1
- package/dist/lib/interaction-tokens.d.ts.map +0 -1
- package/dist/lib/interaction-tokens.js.map +0 -1
- package/dist/lib/portal.d.ts.map +0 -1
- package/dist/lib/portal.js.map +0 -1
- package/dist/lib/react-native-classname.d.ts.map +0 -1
- package/dist/lib/react-native-classname.js.map +0 -1
- package/dist/lib/theme-bridge.d.ts.map +0 -1
- package/dist/lib/theme-bridge.js.map +0 -1
- package/dist/lib/theme-colors.d.ts.map +0 -1
- package/dist/lib/theme-colors.js.map +0 -1
- package/dist/lib/tv.d.ts.map +0 -1
- package/dist/lib/tv.js.map +0 -1
- package/dist/lib/visual-tokens.d.ts.map +0 -1
- package/dist/lib/visual-tokens.js.map +0 -1
- package/dist/vite.d.ts.map +0 -1
- package/dist/vite.js.map +0 -1
package/README.md
CHANGED
|
@@ -6,6 +6,11 @@ Beautiful, accessible, themeable components built with [Uniwind](https://uniwind
|
|
|
6
6
|
|
|
7
7
|
**Requirements:** React 19+, React Native 0.81+, Expo 52+ (if using Expo). Supports React Native Web.
|
|
8
8
|
|
|
9
|
+
WhileUI has one renderer: React Native. iOS, Android and React Native Web are all
|
|
10
|
+
production targets — iOS and Android set the interaction baseline. See
|
|
11
|
+
[ROADMAP.md](./ROADMAP.md) for the product boundary and extraction rules, and
|
|
12
|
+
[PLAN.md](./PLAN.md) for the supported stack and production contracts.
|
|
13
|
+
|
|
9
14
|
## Installation
|
|
10
15
|
|
|
11
16
|
```bash
|
|
@@ -101,15 +106,15 @@ module.exports = withUniwindConfig({
|
|
|
101
106
|
|
|
102
107
|
```tsx
|
|
103
108
|
import './global.css';
|
|
104
|
-
import { PortalHost } from '@thewhileloop/whileui';
|
|
109
|
+
import { MotionProvider, PortalHost } from '@thewhileloop/whileui';
|
|
105
110
|
import { Button, ButtonText } from '@thewhileloop/whileui';
|
|
106
111
|
|
|
107
112
|
export default function App() {
|
|
108
113
|
return (
|
|
109
|
-
|
|
114
|
+
<MotionProvider>
|
|
110
115
|
{/* Your app content */}
|
|
111
116
|
<PortalHost />
|
|
112
|
-
|
|
117
|
+
</MotionProvider>
|
|
113
118
|
);
|
|
114
119
|
}
|
|
115
120
|
```
|
|
@@ -209,6 +214,8 @@ function MyScreen() {
|
|
|
209
214
|
- **Layout:** `Stack` (vertical), `Row` (horizontal) — both support `gap`, `align`, `justify`
|
|
210
215
|
- **Auth callbacks:** Auth templates use objects: `onSubmit({ email, password })`, `onSubmit({ firstName, lastName, email, password })`, etc. Copy templates from `apps/showcase/templates/auth/`.
|
|
211
216
|
- **PortalHost:** Add `<PortalHost />` at app root for Select, Popover, Tooltip, HoverCard.
|
|
217
|
+
- **Motion:** Wrap the root in `<MotionProvider>`; use `useMotionPolicy()` for semantic
|
|
218
|
+
durations, the responsive spring, and reduced-motion behavior.
|
|
212
219
|
- **Uniwind:** `withUniwindConfig` must wrap metro config. `global.css` at app root, imported in `App.tsx`.
|
|
213
220
|
- **Reference:** Block props in `packages/ui/src/blocks` (core) and `apps/showcase/templates/` (auth, profile); flow patterns in README "Flow Patterns" section.
|
|
214
221
|
|
|
@@ -223,7 +230,12 @@ function MyScreen() {
|
|
|
223
230
|
| **Pressable** | Themed pressable wrapper |
|
|
224
231
|
| **Stack** | Vertical flex layout with gap |
|
|
225
232
|
| **Row** | Horizontal flex layout with gap |
|
|
226
|
-
|
|
233
|
+
|
|
234
|
+
### Root Providers
|
|
235
|
+
|
|
236
|
+
| Provider | Notes |
|
|
237
|
+
| ------------------ | ------------------------------------------------------------------------ |
|
|
238
|
+
| **MotionProvider** | System reduced motion, explicit preview modes, and deterministic testing |
|
|
227
239
|
|
|
228
240
|
### Form Controls
|
|
229
241
|
|
|
@@ -267,6 +279,7 @@ function MyScreen() {
|
|
|
267
279
|
| **Tabs** | TabsList, TabsTrigger, TabsContent |
|
|
268
280
|
| **Accordion** | AccordionItem, AccordionTrigger, Content |
|
|
269
281
|
| **Collapsible** | CollapsibleTrigger, CollapsibleContent |
|
|
282
|
+
| **Container** | Centred content column with a max width |
|
|
270
283
|
|
|
271
284
|
### Overlays & Menus
|
|
272
285
|
|
|
@@ -305,37 +318,37 @@ Copy from `apps/showcase/templates/auth/`:
|
|
|
305
318
|
|
|
306
319
|
### Navigation
|
|
307
320
|
|
|
308
|
-
| Block | Description
|
|
309
|
-
| --------------------- |
|
|
310
|
-
| **AppShell** | Layout shell with header/footer/bottomNav slots
|
|
311
|
-
| **
|
|
312
|
-
| **
|
|
313
|
-
| **
|
|
314
|
-
| **
|
|
315
|
-
| **
|
|
316
|
-
| **DrawerMenu** | Drawer with sections and items |
|
|
321
|
+
| Block | Description |
|
|
322
|
+
| --------------------- | ----------------------------------------------- |
|
|
323
|
+
| **AppShell** | Layout shell with header/footer/bottomNav slots |
|
|
324
|
+
| **Header** | Top app bar with back/actions |
|
|
325
|
+
| **BottomNav** | Tab-style bottom navigation bar |
|
|
326
|
+
| **FloatingBottomNav** | Elevated bottom nav with safe area support |
|
|
327
|
+
| **TabBar** | Top tab bar with indicator |
|
|
328
|
+
| **DrawerMenu** | Drawer with sections and items |
|
|
317
329
|
|
|
318
330
|
### Layout
|
|
319
331
|
|
|
320
|
-
| Block | Description
|
|
321
|
-
| --------------------------- |
|
|
322
|
-
| **ActionBar** | Sticky bottom action row with safe-area padding
|
|
323
|
-
| **ConfirmActionSheet** | Reusable destructive confirmation sheet
|
|
324
|
-
| **Sheet** | Bottom sheet modal with header/content/footer slots
|
|
325
|
-
| **FormModalScreen** | Modal scaffold for forms with loading states
|
|
326
|
-
| **ContentSkeleton** | Page/content placeholder with variants (list, card, generic)
|
|
327
|
-
| **PageSkeleton** | Variant-based page layouts (dashboard, list, settings, card, generic)
|
|
328
|
-
| **ScreenSkeleton** | Header slot/placeholder + PageSkeleton content in one block
|
|
329
|
-
| **ErrorBoundary** | React ErrorBoundary that renders ErrorState by default
|
|
330
|
-
| **EmptyState** | Empty content placeholder
|
|
331
|
-
| **ErrorState** | Error display with retry
|
|
332
|
-
| **LoadingScreen** | Full-screen loading indicator
|
|
333
|
-
| **PullToRefreshScrollView** | Themed ScrollView with RefreshControl (useThemeTokens for colors)
|
|
334
|
-
| **
|
|
335
|
-
| **
|
|
336
|
-
| **
|
|
337
|
-
| **
|
|
338
|
-
| **
|
|
332
|
+
| Block | Description |
|
|
333
|
+
| --------------------------- | --------------------------------------------------------------------- |
|
|
334
|
+
| **ActionBar** | Sticky bottom action row with safe-area padding |
|
|
335
|
+
| **ConfirmActionSheet** | Reusable destructive confirmation sheet |
|
|
336
|
+
| **Sheet** | Bottom sheet modal with header/content/footer slots |
|
|
337
|
+
| **FormModalScreen** | Modal scaffold for forms with loading states |
|
|
338
|
+
| **ContentSkeleton** | Page/content placeholder with variants (list, card, generic) |
|
|
339
|
+
| **PageSkeleton** | Variant-based page layouts (dashboard, list, settings, card, generic) |
|
|
340
|
+
| **ScreenSkeleton** | Header slot/placeholder + PageSkeleton content in one block |
|
|
341
|
+
| **ErrorBoundary** | React ErrorBoundary that renders ErrorState by default |
|
|
342
|
+
| **EmptyState** | Empty content placeholder |
|
|
343
|
+
| **ErrorState** | Error display with retry |
|
|
344
|
+
| **LoadingScreen** | Full-screen loading indicator |
|
|
345
|
+
| **PullToRefreshScrollView** | Themed ScrollView with RefreshControl (useThemeTokens for colors) |
|
|
346
|
+
| **KeyboardAwareScreen** | One screen-level keyboard policy for bottom-docked controls |
|
|
347
|
+
| **DockedInput** | Safe-area-aware bottom dock that reports its complete height |
|
|
348
|
+
| **SmartInput** | Compose input with slots, variants, and optional rotating examples |
|
|
349
|
+
| **SplashScreen** | Branded splash (fade/scale/slide variants) |
|
|
350
|
+
| **MinimalSplash** | Minimal monochrome splash |
|
|
351
|
+
| **BrandedSplash** | Splash with brand imagery |
|
|
339
352
|
|
|
340
353
|
### Chat
|
|
341
354
|
|
|
@@ -362,7 +375,6 @@ Copy from `apps/showcase/templates/profile/`:
|
|
|
362
375
|
| -------------------- | ----------------------------------- |
|
|
363
376
|
| **ListItem** | Title/subtitle row |
|
|
364
377
|
| **NotificationItem** | Notification row with metadata |
|
|
365
|
-
| **SwipeableItem** | Swipe actions list item |
|
|
366
378
|
| **TimelineFeed** | Vertical feed with connecting lines |
|
|
367
379
|
|
|
368
380
|
### Commerce
|
|
@@ -393,12 +405,19 @@ Copy from `apps/showcase/templates/profile/`:
|
|
|
393
405
|
| **DatePickerInline** | Inline calendar for forms or dashboards |
|
|
394
406
|
| **DateRangePickerModal** | Range selection modal with period marking |
|
|
395
407
|
|
|
396
|
-
|
|
408
|
+
**Tokens without a renderer.** `@thewhileloop/whileui/tokens` exports the theme
|
|
409
|
+
and visual contracts, the presets, and `deriveThemeColors(base, scheme)` — give it
|
|
410
|
+
the 25 base colours an app defines and it returns all 52, using the same ratios
|
|
411
|
+
as the default presets. Safe in a build script (no React, RN or Uniwind
|
|
412
|
+
imports); `useThemeColors()` uses it too, so a missing `--color-primary-soft`
|
|
413
|
+
derives from the app's own primary instead of falling back to the default palette.
|
|
414
|
+
|
|
415
|
+
## Layout Primitives (Stack, Row)
|
|
397
416
|
|
|
398
417
|
Use `Stack` for vertical layouts, `Row` for horizontal layouts. Both support `gap`, `align`, and `justify` variants.
|
|
399
418
|
|
|
400
419
|
```tsx
|
|
401
|
-
import { Stack, Row
|
|
420
|
+
import { Stack, Row } from '@thewhileloop/whileui';
|
|
402
421
|
|
|
403
422
|
<Stack gap="lg">
|
|
404
423
|
<Text>Title</Text>
|
|
@@ -419,7 +438,32 @@ import { Stack, Row, Box } from '@thewhileloop/whileui';
|
|
|
419
438
|
| align | `'start' \| 'center' \| 'end' \| 'stretch' \| 'baseline'` | Cross-axis alignment |
|
|
420
439
|
| justify | `'start' \| 'center' \| 'end' \| 'between' \| 'around' \| 'evenly'` | Main-axis alignment |
|
|
421
440
|
|
|
422
|
-
|
|
441
|
+
### Container
|
|
442
|
+
|
|
443
|
+
Caps content width and centres it. Phone-first layouts stretch to the viewport, which
|
|
444
|
+
is right at 390px and wrong at 1600px — line lengths become unreadable and related
|
|
445
|
+
controls drift apart.
|
|
446
|
+
|
|
447
|
+
```tsx
|
|
448
|
+
<Container size="lg">{children}</Container>
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
| Prop | Type | Default | Notes |
|
|
452
|
+
| ----------- | -------------------------------------- | ------- | --------------------------- |
|
|
453
|
+
| `size` | `sm` \| `md` \| `lg` \| `xl` \| `full` | `md` | `sm` forms, `lg` dashboards |
|
|
454
|
+
| `fill` | `boolean` | `false` | `flex-1`, for a screen root |
|
|
455
|
+
| `className` | `string` | — | Merged after the variant |
|
|
456
|
+
|
|
457
|
+
No platform branch, and none is needed: every size is wider than any phone, so on iOS
|
|
458
|
+
and Android the cap never engages and it renders as a plain full-width `View`. The same
|
|
459
|
+
component is a no-op on native and the whole fix on desktop.
|
|
460
|
+
|
|
461
|
+
For a scroll view, put the column on the content container so the scrollbar stays at
|
|
462
|
+
the window edge:
|
|
463
|
+
|
|
464
|
+
```tsx
|
|
465
|
+
<ScrollView contentContainerClassName="w-full max-w-5xl self-center" />
|
|
466
|
+
```
|
|
423
467
|
|
|
424
468
|
## Full-Screen Composition
|
|
425
469
|
|
|
@@ -548,7 +592,7 @@ The WhileUI token contract is strict for cross-app reuse. Define these in **ever
|
|
|
548
592
|
- Required core tokens: `background`, `foreground`, `card`, `card-foreground`, `popover`, `popover-foreground`, `primary`, `primary-foreground`, `secondary`, `secondary-foreground`, `muted`, `muted-foreground`, `accent`, `accent-foreground`, `destructive`, `destructive-foreground`, `border`, `input`, `ring`
|
|
549
593
|
- Optional status tokens: `success`, `success-foreground`, `warning`, `warning-foreground`, `info`, `info-foreground`
|
|
550
594
|
- Optional effect tokens: `overlay`, `overlay-strong`, `surface-elevated`, `surface-border`, `surface-highlight`, `surface-translucent`, `surface-translucent-border`, `state-hover`, `state-pressed`, `state-disabled`
|
|
551
|
-
- Optional interaction/motion tokens: `--ui-press-opacity`, `--ui-press-opacity-strong`, `--ui-disabled-opacity`, `--ui-disabled-opacity-soft`, `--ui-disabled-opacity-subtle`, `--ui-inactive-opacity`, `--ui-motion-fast`, `--ui-motion-normal`, `--ui-motion-slow`, `--ui-drawer-open-duration`, `--ui-drawer-close-duration`, `--ui-blur-intensity-subtle`, `--ui-blur-intensity-medium`, `--ui-blur-intensity-strong`, `--ui-blur-saturation-pct`, `--ui-frosted-highlight-height`, `--ui-frosted-backdrop-blur-intensity`, `--ui-frosted-backdrop-blur-scale`, `--ui-frosted-android-experimental-blur`, `--ui-drawer-frosted-inset`, `--ui-drawer-frosted-radius`, `--ui-drawer-content-top-padding`
|
|
595
|
+
- Optional interaction/motion tokens: `--ui-press-opacity`, `--ui-press-opacity-strong`, `--ui-disabled-opacity`, `--ui-disabled-opacity-soft`, `--ui-disabled-opacity-subtle`, `--ui-inactive-opacity`, `--ui-motion-fast`, `--ui-motion-normal`, `--ui-motion-slow`, `--ui-motion-spring-damping`, `--ui-motion-spring-stiffness`, `--ui-motion-spring-mass`, `--ui-drawer-open-duration`, `--ui-drawer-close-duration`, `--ui-blur-intensity-subtle`, `--ui-blur-intensity-medium`, `--ui-blur-intensity-strong`, `--ui-blur-saturation-pct`, `--ui-frosted-highlight-height`, `--ui-frosted-backdrop-blur-intensity`, `--ui-frosted-backdrop-blur-scale`, `--ui-frosted-android-tint-alpha-scale`, `--ui-frosted-android-experimental-blur`, `--ui-drawer-frosted-inset`, `--ui-drawer-frosted-radius`, `--ui-drawer-content-top-padding`
|
|
552
596
|
- Optional scale tokens: spacing (`--spacing`, `--spacing-*`), typography (`--text-*`, `--leading-*`, `--tracking-*`), radius (`--radius-*`), elevation (`--shadow-*`)
|
|
553
597
|
|
|
554
598
|
Minimal contract example:
|
|
@@ -608,6 +652,8 @@ Some apps want a frosted or translucent look for floating panels (modals, sheets
|
|
|
608
652
|
|
|
609
653
|
**Optional:** Add `expo-blur` and register its `BlurView` once at app startup for full frosted blur. For tint-only (no blur), translucent surface tokens are sufficient.
|
|
610
654
|
|
|
655
|
+
**Android note:** frosted panels usually need denser tint than iOS/web. WhileUI now scales frosted tint alpha on Android with `--ui-frosted-android-tint-alpha-scale` (default `1.18`). Set it to `1` to match other platforms exactly, or raise it if your Android surfaces still feel washed out.
|
|
656
|
+
|
|
611
657
|
```tsx
|
|
612
658
|
import { BlurView } from 'expo-blur';
|
|
613
659
|
import { registerFrostedBlurView } from '@thewhileloop/whileui';
|
|
@@ -635,6 +681,7 @@ Additional frosted tuning tokens:
|
|
|
635
681
|
- `--ui-frosted-highlight-height` (top highlight strip height in px, set `0` to disable hard top sheen)
|
|
636
682
|
- `--ui-frosted-backdrop-blur-intensity` (default backdrop blur amount)
|
|
637
683
|
- `--ui-frosted-backdrop-blur-scale` (ratio used when component blur is overridden)
|
|
684
|
+
- `--ui-frosted-android-tint-alpha-scale` (Android-only alpha multiplier applied to frosted tint and backdrop layers)
|
|
638
685
|
- `--ui-frosted-android-experimental-blur` (`1` enables `expo-blur` Android experimental path)
|
|
639
686
|
- `--ui-drawer-frosted-inset` (floating inset for frosted drawer shells)
|
|
640
687
|
- `--ui-drawer-frosted-radius` (drawer corner radius in px)
|
|
@@ -678,6 +725,9 @@ WhileUI components also read optional `--ui-*` tokens for deeper control of pres
|
|
|
678
725
|
--ui-motion-fast: 160;
|
|
679
726
|
--ui-motion-normal: 220;
|
|
680
727
|
--ui-motion-slow: 300;
|
|
728
|
+
--ui-motion-spring-damping: 20;
|
|
729
|
+
--ui-motion-spring-stiffness: 260;
|
|
730
|
+
--ui-motion-spring-mass: 0.8;
|
|
681
731
|
--ui-drawer-open-duration: 300;
|
|
682
732
|
--ui-drawer-close-duration: 220;
|
|
683
733
|
--ui-blur-intensity-subtle: 18;
|
|
@@ -687,6 +737,7 @@ WhileUI components also read optional `--ui-*` tokens for deeper control of pres
|
|
|
687
737
|
--ui-frosted-highlight-height: 0;
|
|
688
738
|
--ui-frosted-backdrop-blur-intensity: 14;
|
|
689
739
|
--ui-frosted-backdrop-blur-scale: 0.55;
|
|
740
|
+
--ui-frosted-android-tint-alpha-scale: 1.22;
|
|
690
741
|
--ui-frosted-android-experimental-blur: 1;
|
|
691
742
|
--ui-drawer-frosted-inset: 0;
|
|
692
743
|
--ui-drawer-frosted-radius: 28;
|
|
@@ -700,6 +751,23 @@ For custom components, use:
|
|
|
700
751
|
import { useInteractionTokens, withInteractivePressableStyle } from '@thewhileloop/whileui';
|
|
701
752
|
```
|
|
702
753
|
|
|
754
|
+
Wrap the application in `MotionProvider` to coordinate system reduced motion, explicit
|
|
755
|
+
preview overrides, and deterministic animation-free tests. The provider is optional:
|
|
756
|
+
without it `useMotionPolicy` returns the token defaults with Reanimated following the
|
|
757
|
+
system setting, and `--ui-motion-*` overrides are not read. `reduced` preserves
|
|
758
|
+
non-spatial feedback while asking Reanimated to skip motion; `disabled` also resolves
|
|
759
|
+
semantic durations to zero.
|
|
760
|
+
|
|
761
|
+
```tsx
|
|
762
|
+
import { MotionProvider, useMotionPolicy } from '@thewhileloop/whileui';
|
|
763
|
+
|
|
764
|
+
<MotionProvider mode="system">{/* application */}</MotionProvider>;
|
|
765
|
+
|
|
766
|
+
const motion = useMotionPolicy();
|
|
767
|
+
motion.durations.normal;
|
|
768
|
+
motion.springs.responsive;
|
|
769
|
+
```
|
|
770
|
+
|
|
703
771
|
Optional RN fallback tokens (hex/rgb/hsl/named):
|
|
704
772
|
|
|
705
773
|
```css
|
|
@@ -798,6 +866,33 @@ const adapter: ThemeBridgeAdapter = {
|
|
|
798
866
|
const { mode, resolvedTheme, setMode, cycleMode } = useThemeBridge({ adapter });
|
|
799
867
|
```
|
|
800
868
|
|
|
869
|
+
## Focus rings
|
|
870
|
+
|
|
871
|
+
Every interactive component draws a themed focus ring on web. It uses `:focus-visible`,
|
|
872
|
+
so it appears for keyboard users and not after a mouse click, and it is driven by the
|
|
873
|
+
`--color-ring` token — restyle it with your theme, not with component overrides.
|
|
874
|
+
|
|
875
|
+
Use the same treatment on your own controls:
|
|
876
|
+
|
|
877
|
+
```tsx
|
|
878
|
+
import { focusRing, focusRingInset, cn } from '@thewhileloop/whileui';
|
|
879
|
+
|
|
880
|
+
<Pressable className={cn('rounded-full px-4 py-2', focusRing)} onPress={onPress}>
|
|
881
|
+
<Text>Custom control</Text>
|
|
882
|
+
</Pressable>;
|
|
883
|
+
```
|
|
884
|
+
|
|
885
|
+
| Export | Use for |
|
|
886
|
+
| ---------------- | ------------------------------------------------------------------------------- |
|
|
887
|
+
| `focusRing` | Standalone controls — buttons, inputs, cards, nav items |
|
|
888
|
+
| `focusRingInset` | Controls flush inside a track, where an offset ring would clip (segments, tabs) |
|
|
889
|
+
|
|
890
|
+
**Do not use a bare `outline-none`.** It removes the browser's indicator and leaves
|
|
891
|
+
keyboard users with nothing, which fails WCAG 2.4.7. `focusRing` removes the default and
|
|
892
|
+
supplies a themed replacement in the same class. The one exemption is a visually hidden
|
|
893
|
+
input, where a visible proxy shows the focus instead — `OTPInput` does this with its
|
|
894
|
+
blinking cursor.
|
|
895
|
+
|
|
801
896
|
## Tech Stack
|
|
802
897
|
|
|
803
898
|
- **Styling**: [Uniwind](https://uniwind.dev) (free tier) + Tailwind CSS v4
|
|
@@ -808,28 +903,57 @@ const { mode, resolvedTheme, setMode, cycleMode } = useThemeBridge({ adapter });
|
|
|
808
903
|
|
|
809
904
|
# API Reference
|
|
810
905
|
|
|
906
|
+
## Pressable
|
|
907
|
+
|
|
908
|
+
```tsx
|
|
909
|
+
import { Pressable, Text } from '@thewhileloop/whileui';
|
|
910
|
+
|
|
911
|
+
<Pressable
|
|
912
|
+
accessibilityRole="button"
|
|
913
|
+
feedback="strong"
|
|
914
|
+
disabledFeedback="default"
|
|
915
|
+
loading={false}
|
|
916
|
+
onPress={() => {}}
|
|
917
|
+
>
|
|
918
|
+
<Text>Open</Text>
|
|
919
|
+
</Pressable>;
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
`Pressable` preserves React Native's event, ref, accessibility, and function-style
|
|
923
|
+
`style` contracts. Feedback changes opacity without changing layout. Native press state
|
|
924
|
+
comes directly from React Native; web adds a motion-policy-aware opacity transition.
|
|
925
|
+
|
|
926
|
+
| Prop | Type | Default | Description |
|
|
927
|
+
| ---------------- | ------------------------------------------- | ----------- | ------------------------------------------ |
|
|
928
|
+
| feedback | `'none' \| 'default' \| 'strong'` | `'none'` | Semantic pressed opacity |
|
|
929
|
+
| disabledFeedback | `'none' \| 'default' \| 'soft' \| 'subtle'` | `'default'` | Semantic unavailable opacity |
|
|
930
|
+
| loading | `boolean` | `false` | Expose busy/disabled state and block input |
|
|
931
|
+
| className | `string` | — | Additional Tailwind classes |
|
|
932
|
+
|
|
811
933
|
## Button
|
|
812
934
|
|
|
813
935
|
```tsx
|
|
814
936
|
import { Button, ButtonText, ButtonIcon } from '@thewhileloop/whileui';
|
|
815
937
|
|
|
816
|
-
<Button variant="default" size="default" disabled={false} onPress={() => {}}>
|
|
938
|
+
<Button variant="default" size="default" disabled={false} loading={false} onPress={() => {}}>
|
|
817
939
|
<ButtonIcon>
|
|
818
940
|
<Icon />
|
|
819
941
|
</ButtonIcon>
|
|
820
942
|
<ButtonText>Click me</ButtonText>
|
|
821
|
-
|
|
943
|
+
{/* Placement is child order — a trailing ButtonIcon renders after the label. */}
|
|
944
|
+
<ButtonIcon>
|
|
822
945
|
<Icon />
|
|
823
946
|
</ButtonIcon>
|
|
824
947
|
</Button>;
|
|
825
948
|
```
|
|
826
949
|
|
|
827
|
-
| Prop | Type | Default | Description
|
|
828
|
-
| --------- | ----------------------------------------------------------------------------- | ----------- |
|
|
829
|
-
| variant | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Button style variant
|
|
830
|
-
| size | `'default' \| 'sm' \| 'lg' \| 'icon'` | `'default'` | Button size
|
|
831
|
-
| disabled | `boolean` | `false` | Disable the button
|
|
832
|
-
|
|
|
950
|
+
| Prop | Type | Default | Description |
|
|
951
|
+
| --------- | ----------------------------------------------------------------------------- | ----------- | -------------------------------------------------- |
|
|
952
|
+
| variant | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Button style variant |
|
|
953
|
+
| size | `'default' \| 'sm' \| 'lg' \| 'icon'` | `'default'` | Button size |
|
|
954
|
+
| disabled | `boolean` | `false` | Disable the button |
|
|
955
|
+
| loading | `boolean` | `false` | Show a spinner, expose busy state, and block input |
|
|
956
|
+
| className | `string` | — | Additional Tailwind classes |
|
|
833
957
|
|
|
834
958
|
## Input
|
|
835
959
|
|
|
@@ -1138,12 +1262,12 @@ import {
|
|
|
1138
1262
|
|
|
1139
1263
|
`AlertDialogContent` supports the same frosted props as `DialogContent`.
|
|
1140
1264
|
|
|
1141
|
-
| Prop | Type
|
|
1142
|
-
| ------------- |
|
|
1143
|
-
| presentation | `'modal' \| 'native' \| 'overlay'`
|
|
1144
|
-
| frosted | `boolean`
|
|
1145
|
-
| blurIntensity | `number`
|
|
1146
|
-
| blurTintToken | `'surfaceElevated' \| …`
|
|
1265
|
+
| Prop | Type | Default | Description |
|
|
1266
|
+
| ------------- | ---------------------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1267
|
+
| presentation | `'modal' \| 'native' \| 'overlay'` | `'modal'` | **`modal`** — themed card in an RN `Modal` (iOS `overFullScreen`). **`native`** — `Alert.alert` on iOS/Android (system UI); use when a second `Modal` won’t stack; ignored on web. **`overlay`** — same themed card as `modal`, but absolutely positioned **inside the parent view** (no second `Modal`). Nest `<AlertDialog>` under your fullscreen sheet’s root so the confirm matches app styling. **Web:** `'native'` is ignored; `overlay` behaves like `modal`. |
|
|
1268
|
+
| frosted | `boolean` | `false` | Same as `DialogContent` |
|
|
1269
|
+
| blurIntensity | `number` | — | Same as `DialogContent` |
|
|
1270
|
+
| blurTintToken | `'surfaceElevated' \| …` | — | Same as `DialogContent` |
|
|
1147
1271
|
|
|
1148
1272
|
### React Native: stacked modals
|
|
1149
1273
|
|
|
@@ -1384,6 +1508,40 @@ import {
|
|
|
1384
1508
|
|
|
1385
1509
|
## Menubar
|
|
1386
1510
|
|
|
1511
|
+
```tsx
|
|
1512
|
+
import {
|
|
1513
|
+
Menubar,
|
|
1514
|
+
MenubarMenu,
|
|
1515
|
+
MenubarTrigger,
|
|
1516
|
+
MenubarContent,
|
|
1517
|
+
MenubarLabel,
|
|
1518
|
+
MenubarItem,
|
|
1519
|
+
MenubarSeparator,
|
|
1520
|
+
} from '@thewhileloop/whileui';
|
|
1521
|
+
|
|
1522
|
+
<Menubar>
|
|
1523
|
+
<MenubarMenu>
|
|
1524
|
+
<MenubarTrigger>
|
|
1525
|
+
<Text className="text-foreground text-sm">File</Text>
|
|
1526
|
+
</MenubarTrigger>
|
|
1527
|
+
<MenubarContent>
|
|
1528
|
+
<MenubarLabel>Project</MenubarLabel>
|
|
1529
|
+
<MenubarItem>
|
|
1530
|
+
<Text className="text-foreground">New Project</Text>
|
|
1531
|
+
</MenubarItem>
|
|
1532
|
+
<MenubarSeparator />
|
|
1533
|
+
<MenubarItem>
|
|
1534
|
+
<Text className="text-foreground">Export</Text>
|
|
1535
|
+
</MenubarItem>
|
|
1536
|
+
</MenubarContent>
|
|
1537
|
+
</MenubarMenu>
|
|
1538
|
+
</Menubar>;
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
`MenubarLabel` is a non-interactive section heading. It takes a string or elements, and
|
|
1542
|
+
announces as a heading to assistive technology — as do `DropdownMenuLabel` and
|
|
1543
|
+
`ContextMenuLabel`.
|
|
1544
|
+
|
|
1387
1545
|
`MenubarContent` supports the same frosted props as `PopoverContent` (default blur preset: medium).
|
|
1388
1546
|
|
|
1389
1547
|
---
|
|
@@ -1494,9 +1652,24 @@ import { ActionBar, Button, ButtonText } from '@thewhileloop/whileui';
|
|
|
1494
1652
|
</ActionBar>;
|
|
1495
1653
|
```
|
|
1496
1654
|
|
|
1655
|
+
## KeyboardAwareScreen and DockedInput
|
|
1656
|
+
|
|
1657
|
+
Use one keyboard-aware root for the screen, then place the composer in a bottom dock. Feed the dock height into the scroll content inset so the last item remains visible.
|
|
1658
|
+
|
|
1659
|
+
```tsx
|
|
1660
|
+
import { DockedInput, KeyboardAwareScreen, SmartInput } from '@thewhileloop/whileui';
|
|
1661
|
+
|
|
1662
|
+
<KeyboardAwareScreen>
|
|
1663
|
+
<ScrollView contentContainerStyle={{ paddingBottom: inputHeight }} />
|
|
1664
|
+
<DockedInput onHeightChange={setInputHeight}>
|
|
1665
|
+
<SmartInput variant="card" safeArea={false} />
|
|
1666
|
+
</DockedInput>
|
|
1667
|
+
</KeyboardAwareScreen>;
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1497
1670
|
## SmartInput
|
|
1498
1671
|
|
|
1499
|
-
|
|
1672
|
+
Compose input for use inline or inside `DockedInput`. `variant`: "bar" or "card". Slots: `leftSlot`, `centerSlot` (intent selector), `rightSlot`. `submitBehavior`: "newline" (default) or "submit"/"blurAndSubmit". `placeholderExamples` animates rotating prompts and respects the platform reduced-motion setting. Forwards ref to `TextInput`.
|
|
1500
1673
|
|
|
1501
1674
|
```tsx
|
|
1502
1675
|
import { SmartInput, Button, ButtonText } from '@thewhileloop/whileui';
|
|
@@ -1504,7 +1677,7 @@ import { SmartInput, Button, ButtonText } from '@thewhileloop/whileui';
|
|
|
1504
1677
|
<SmartInput
|
|
1505
1678
|
value={message}
|
|
1506
1679
|
onChangeText={setMessage}
|
|
1507
|
-
|
|
1680
|
+
placeholderExamples={['Log breakfast', 'Add a 30 minute walk', 'Set weight to 72 kg']}
|
|
1508
1681
|
leftSlot={
|
|
1509
1682
|
<Button variant="ghost" size="icon">
|
|
1510
1683
|
<Icon name="add" />
|
|
@@ -1677,27 +1850,12 @@ import {
|
|
|
1677
1850
|
| blurIntensity | `number` | medium preset |
|
|
1678
1851
|
| blurTintToken | `'surfaceElevated' \| 'surfaceTranslucent' \| 'card' \| 'popover'` | `'surfaceTranslucent'` |
|
|
1679
1852
|
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
sections={[
|
|
1687
|
-
{
|
|
1688
|
-
title: 'Workspace',
|
|
1689
|
-
items: [
|
|
1690
|
-
{ key: 'overview', label: 'Overview', icon: <Icon /> },
|
|
1691
|
-
{ key: 'billing', label: 'Billing', icon: <Icon />, badge: 2 },
|
|
1692
|
-
],
|
|
1693
|
-
},
|
|
1694
|
-
]}
|
|
1695
|
-
activeKey="overview"
|
|
1696
|
-
onSelect={(key) => {}}
|
|
1697
|
-
header={<Text>Acme Inc.</Text>}
|
|
1698
|
-
footer={<Text className="text-xs text-muted-foreground">v1.0.0</Text>}
|
|
1699
|
-
/>;
|
|
1700
|
-
```
|
|
1853
|
+
`SheetContent` is a `ScrollView` and accepts its props. It enables nested scrolling and
|
|
1854
|
+
keeps taps on inputs while the keyboard is open (`keyboardShouldPersistTaps="handled"`).
|
|
1855
|
+
Your `contentContainerStyle` is merged after the default padding. Tapping the backdrop
|
|
1856
|
+
closes the sheet; a drag across the backdrop does not, so a missed scroll never dismisses
|
|
1857
|
+
it. There is no drag-to-dismiss: close with the backdrop, Android back, Escape on web or
|
|
1858
|
+
`SheetClose`.
|
|
1701
1859
|
|
|
1702
1860
|
## Header
|
|
1703
1861
|
|
|
@@ -1825,11 +1983,17 @@ import { PullToRefreshScrollView } from '@thewhileloop/whileui';
|
|
|
1825
1983
|
</PullToRefreshScrollView>;
|
|
1826
1984
|
```
|
|
1827
1985
|
|
|
1828
|
-
| Prop | Type
|
|
1829
|
-
| ------------ |
|
|
1830
|
-
| refreshing | `boolean`
|
|
1831
|
-
| onRefresh | `() => void
|
|
1832
|
-
| refreshColor | `string`
|
|
1986
|
+
| Prop | Type | Description |
|
|
1987
|
+
| ------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
1988
|
+
| refreshing | `boolean` | Whether refresh is in progress |
|
|
1989
|
+
| onRefresh | `() => void \| Promise<void>` | Called when user pulls to refresh. Not awaited — drive the spinner with `refreshing`, and catch your own errors |
|
|
1990
|
+
| refreshColor | `string` | Optional hex override; defaults to primary |
|
|
1991
|
+
|
|
1992
|
+
The scroll view owns the refresh gesture; don't pass `refreshControl`. It bounces even
|
|
1993
|
+
when content is shorter than the screen, so a short list can still be pulled. Screen
|
|
1994
|
+
reader users get the same refresh as a **Refresh** accessibility action, since they
|
|
1995
|
+
cannot pull. It is ignored while `refreshing` is true, and any `accessibilityActions` you
|
|
1996
|
+
pass are kept.
|
|
1833
1997
|
|
|
1834
1998
|
## EmptyState
|
|
1835
1999
|
|
|
@@ -2064,13 +2228,12 @@ Tracked work items for future releases.
|
|
|
2064
2228
|
|
|
2065
2229
|
- [x] ProductCard, ListItem, NotificationItem, MetricCard, SubscriptionCard, PricingCard
|
|
2066
2230
|
- [x] AppShell, Chat, FormModalScreen, CheckoutSummary (already had `loading`)
|
|
2067
|
-
- [ ] Add `loading` to remaining blocks: Header, BottomNav, DrawerMenu, TimelineFeed
|
|
2231
|
+
- [ ] Add `loading` to remaining blocks: Header, BottomNav, DrawerMenu, TimelineFeed
|
|
2068
2232
|
|
|
2069
2233
|
### Documentation Gaps
|
|
2070
2234
|
|
|
2071
|
-
- [ ] Add `## API` sections for: Textarea, Toggle, ToggleGroup, Label, Separator, Skeleton, AspectRatio, Collapsible, Text, View
|
|
2072
|
-
- [ ] Add `## API` sections for blocks: FloatingBottomNav, TabBar, FormModalScreen, ErrorState, LoadingScreen,
|
|
2073
|
-
- [ ] Build `apps/site/` (docs website) with `registry.ts`, `demos.tsx`, `block-demos.tsx`, `props-data.ts`
|
|
2235
|
+
- [ ] Add `## API` sections for: Textarea, Toggle, ToggleGroup, Label, Separator, Skeleton, AspectRatio, Collapsible, Text, View
|
|
2236
|
+
- [ ] Add `## API` sections for blocks: FloatingBottomNav, TabBar, FormModalScreen, ErrorState, LoadingScreen, ListItem, NotificationItem, MetricCard, SmartImage, TimelineFeed
|
|
2074
2237
|
|
|
2075
2238
|
### Infrastructure
|
|
2076
2239
|
|
|
@@ -43,7 +43,6 @@ export interface ChatProps {
|
|
|
43
43
|
export declare function ChatMessageBubble({ message, contentClassName, }: {
|
|
44
44
|
message: ChatMessage;
|
|
45
45
|
contentClassName?: string;
|
|
46
|
-
}):
|
|
47
|
-
export declare function ChatSuggestions({ suggestions, onSelect, className }: ChatSuggestionsProps):
|
|
48
|
-
export declare function Chat({ messages, value, onChangeText, onSend, placeholder, suggestions, onSuggestionPress, leftSlot, rightSlot, loading, header, emptyTitle, emptyDescription, exampleMessage, renderMessage, loadingIndicator, inputSafeArea, keyboardVerticalOffset, className, messagesClassName, }: ChatProps):
|
|
49
|
-
//# sourceMappingURL=chat.d.ts.map
|
|
46
|
+
}): React.JSX.Element;
|
|
47
|
+
export declare function ChatSuggestions({ suggestions, onSelect, className }: ChatSuggestionsProps): React.JSX.Element;
|
|
48
|
+
export declare function Chat({ messages, value, onChangeText, onSend, placeholder, suggestions, onSuggestionPress, leftSlot, rightSlot, loading, header, emptyTitle, emptyDescription, exampleMessage, renderMessage, loadingIndicator, inputSafeArea, keyboardVerticalOffset, className, messagesClassName, }: ChatProps): React.JSX.Element;
|
package/dist/blocks/chat/chat.js
CHANGED
|
@@ -6,15 +6,15 @@ import { SmartInput } from '../layout/smart-input';
|
|
|
6
6
|
import { cn } from '../../lib/cn';
|
|
7
7
|
import { useInteractionTokens, withInteractivePressableStyle } from '../../lib/interaction-tokens';
|
|
8
8
|
import { useVisualTokens } from '../../lib/visual-tokens';
|
|
9
|
+
import { typographyStyle } from '../../lib/recipes';
|
|
9
10
|
import { tv } from '../../lib/tv';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
lg: 'text-lg',
|
|
11
|
+
const CONTENT_SIZE_ROLE = {
|
|
12
|
+
sm: 'label',
|
|
13
|
+
default: 'body',
|
|
14
|
+
lg: 'emphasis',
|
|
15
15
|
};
|
|
16
16
|
const chatMessageBubbleVariants = tv({
|
|
17
|
-
base: '
|
|
17
|
+
base: '',
|
|
18
18
|
variants: {
|
|
19
19
|
role: {
|
|
20
20
|
user: 'self-end bg-primary',
|
|
@@ -24,25 +24,35 @@ const chatMessageBubbleVariants = tv({
|
|
|
24
24
|
},
|
|
25
25
|
defaultVariants: { role: 'assistant' },
|
|
26
26
|
});
|
|
27
|
-
// ─── ChatMessage ─────────────────────────────────────────────
|
|
28
27
|
export function ChatMessageBubble({ message, contentClassName, }) {
|
|
29
28
|
const role = message.role === 'system' ? 'system' : message.role;
|
|
30
29
|
const isUser = message.role === 'user';
|
|
31
|
-
const
|
|
30
|
+
const contentRole = CONTENT_SIZE_ROLE[message.contentSize ?? 'default'];
|
|
32
31
|
const visual = useVisualTokens();
|
|
33
32
|
const { width: screenWidth } = useWindowDimensions();
|
|
34
33
|
const ratio = role === 'system' ? visual.chatSystemBubbleMaxWidthRatio : visual.chatBubbleMaxWidthRatio;
|
|
35
34
|
const maxWidth = screenWidth * ratio;
|
|
36
|
-
return (_jsxs(View, { accessible: true, accessibilityRole: "none", accessibilityLabel: isUser ? 'Your message' : message.role === 'system' ? 'System message' : 'Assistant message', className: chatMessageBubbleVariants({ role }), style: {
|
|
35
|
+
return (_jsxs(View, { accessible: true, accessibilityRole: "none", accessibilityLabel: isUser ? 'Your message' : message.role === 'system' ? 'System message' : 'Assistant message', className: chatMessageBubbleVariants({ role }), style: {
|
|
36
|
+
maxWidth,
|
|
37
|
+
borderRadius: visual.radiusLg,
|
|
38
|
+
paddingHorizontal: visual.controlPaddingXDefault,
|
|
39
|
+
paddingVertical: visual.controlPaddingYDefault,
|
|
40
|
+
}, children: [_jsx(Text, { className: cn('leading-relaxed', isUser ? 'text-primary-foreground' : 'text-foreground', contentClassName), style: typographyStyle(visual, contentRole), children: message.content }), message.secondary && (_jsx(Text, { className: cn('mt-1', isUser ? 'text-primary-foreground-muted' : 'text-muted-foreground'), style: typographyStyle(visual, 'caption'), children: message.secondary }))] }));
|
|
37
41
|
}
|
|
38
|
-
// ─── ChatSuggestions ──────────────────────────────────────────
|
|
39
42
|
export function ChatSuggestions({ suggestions, onSelect, className }) {
|
|
40
|
-
|
|
43
|
+
const visual = useVisualTokens();
|
|
44
|
+
return (_jsx(View, { className: cn('flex-row flex-wrap justify-center gap-2 px-4 py-6', className), children: suggestions.map((text) => (_jsx(Pressable, { onPress: () => onSelect(text), accessibilityRole: "button", accessibilityLabel: `Suggestion: ${text}`, className: "rounded-full border-border bg-muted active:bg-muted", style: {
|
|
45
|
+
borderWidth: visual.borderWidthHairline,
|
|
46
|
+
paddingHorizontal: visual.controlPaddingXDefault,
|
|
47
|
+
paddingVertical: visual.controlPaddingYSm,
|
|
48
|
+
}, children: _jsx(Text, { className: "text-foreground", style: typographyStyle(visual, 'label'), children: text }) }, text))) }));
|
|
41
49
|
}
|
|
42
50
|
const EMPTY_SUGGESTIONS = [];
|
|
43
|
-
// ─── Chat ────────────────────────────────────────────────────
|
|
44
51
|
export function Chat({ messages, value, onChangeText, onSend, placeholder = 'Message...', suggestions = EMPTY_SUGGESTIONS, onSuggestionPress, leftSlot, rightSlot, loading = false, header, emptyTitle, emptyDescription, exampleMessage, renderMessage, loadingIndicator, inputSafeArea = true, keyboardVerticalOffset = 0, className, messagesClassName, }) {
|
|
45
52
|
const scrollRef = useRef(null);
|
|
53
|
+
const visual = useVisualTokens();
|
|
54
|
+
const emptyTitleTypography = typographyStyle(visual, 'emphasis');
|
|
55
|
+
const emptyDescriptionTypography = typographyStyle(visual, 'label');
|
|
46
56
|
const isEmpty = messages.length === 0;
|
|
47
57
|
const showSuggestions = isEmpty && suggestions.length > 0;
|
|
48
58
|
useEffect(() => {
|
|
@@ -55,14 +65,16 @@ export function Chat({ messages, value, onChangeText, onSend, placeholder = 'Mes
|
|
|
55
65
|
flexGrow: 1,
|
|
56
66
|
paddingBottom: 8,
|
|
57
67
|
justifyContent: showSuggestions ? 'center' : 'flex-end',
|
|
58
|
-
}, keyboardShouldPersistTaps: "handled", children: showSuggestions ? (_jsxs(View, { className: "flex-1 justify-center", children: [exampleMessage && (_jsx(View, { className: "mb-6 px-4", children: renderMessage ? (renderMessage(exampleMessage)) : (_jsx(ChatMessageBubble, { message: exampleMessage })) })), emptyTitle && (_jsx(Text, { className: "mb-1 text-center
|
|
68
|
+
}, keyboardShouldPersistTaps: "handled", children: showSuggestions ? (_jsxs(View, { className: "flex-1 justify-center", children: [exampleMessage && (_jsx(View, { className: "mb-6 px-4", children: renderMessage ? (renderMessage(exampleMessage)) : (_jsx(ChatMessageBubble, { message: exampleMessage })) })), emptyTitle && (_jsx(Text, { className: "mb-1 text-center font-medium text-foreground", style: emptyTitleTypography, children: emptyTitle })), emptyDescription && (_jsx(Text, { className: "mb-4 text-center text-muted-foreground", style: emptyDescriptionTypography, children: emptyDescription })), _jsx(ChatSuggestions, { suggestions: suggestions, onSelect: onSuggestionPress ?? (() => { }) })] })) : (_jsxs(View, { className: "gap-3 px-4 pt-4", children: [messages.map((msg) => renderMessage ? (_jsx(React.Fragment, { children: renderMessage(msg) }, msg.id)) : (_jsx(ChatMessageBubble, { message: msg }, msg.id))), loading && loadingIndicator && _jsx(View, { className: "px-4", children: loadingIndicator })] })) }), _jsx(SmartInput, { value: value, onChangeText: onChangeText, placeholder: placeholder, leftSlot: leftSlot, rightSlot: defaultRightSlot, editable: !loading, safeArea: inputSafeArea })] }));
|
|
59
69
|
}
|
|
60
|
-
// ─── ChatSendButton ───────────────────────────────────────────
|
|
61
70
|
function ChatSendButton({ onPress, disabled }) {
|
|
62
71
|
const interaction = useInteractionTokens();
|
|
63
|
-
|
|
72
|
+
const visual = useVisualTokens();
|
|
73
|
+
return (_jsx(Pressable, { onPress: onPress, disabled: disabled, accessibilityRole: "button", accessibilityLabel: disabled ? 'Send (disabled)' : 'Send message', style: withInteractivePressableStyle({
|
|
74
|
+
height: visual.controlHeightDefault,
|
|
75
|
+
width: visual.controlHeightDefault,
|
|
76
|
+
}, interaction, {
|
|
64
77
|
disabled: Boolean(disabled),
|
|
65
78
|
pressedVariant: 'strong',
|
|
66
|
-
}), className: cn('
|
|
79
|
+
}), className: cn('items-center justify-center rounded-full', disabled ? 'bg-muted' : 'bg-primary'), children: _jsx(Text, { className: "text-primary-foreground", style: typographyStyle(visual, 'emphasis'), children: "\u2191" }) }));
|
|
67
80
|
}
|
|
68
|
-
//# sourceMappingURL=chat.js.map
|