@delacour/react-native-ui 0.1.0-alpha.4 → 0.2.0-alpha.20261010061731
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 +10 -6
- package/package.json +49 -5
- package/src/components/accordion/AGENTS.md +21 -9
- package/src/components/accordion/accordion-content.tsx +7 -4
- package/src/components/accordion/accordion-item.tsx +15 -13
- package/src/components/accordion/accordion.context.tsx +11 -5
- package/src/components/accordion/accordion.variants.test.ts +64 -3
- package/src/components/accordion/accordion.variants.ts +33 -9
- package/src/components/alert/AGENTS.md +102 -0
- package/src/components/alert/alert-action.tsx +17 -0
- package/src/components/alert/alert-close-button.tsx +50 -0
- package/src/components/alert/alert-content.tsx +15 -0
- package/src/components/alert/alert-description.tsx +16 -0
- package/src/components/alert/alert-glyphs.ts +25 -0
- package/src/components/alert/alert-indicator.tsx +40 -0
- package/src/components/alert/alert-title.tsx +18 -0
- package/src/components/alert/alert.context.tsx +69 -0
- package/src/components/alert/alert.tsx +160 -0
- package/src/components/alert/alert.types.ts +10 -0
- package/src/components/alert/alert.variants.test.ts +218 -0
- package/src/components/alert/alert.variants.ts +180 -0
- package/src/components/alert/index.ts +23 -0
- package/src/components/avatar/AGENTS.md +106 -0
- package/src/components/avatar/avatar-badge.tsx +51 -0
- package/src/components/avatar/avatar-group.tsx +139 -0
- package/src/components/avatar/avatar.context.tsx +93 -0
- package/src/components/avatar/avatar.tsx +201 -0
- package/src/components/avatar/avatar.utils.test.ts +174 -0
- package/src/components/avatar/avatar.utils.ts +141 -0
- package/src/components/avatar/avatar.variants.test.ts +251 -0
- package/src/components/avatar/avatar.variants.ts +270 -0
- package/src/components/avatar/index.ts +39 -0
- package/src/components/badge/AGENTS.md +10 -0
- package/src/components/badge/badge-close-button.tsx +2 -2
- package/src/components/badge/badge.context.tsx +2 -1
- package/src/components/badge/badge.tsx +13 -4
- package/src/components/badge/badge.variants.test.ts +26 -0
- package/src/components/badge/badge.variants.ts +21 -0
- package/src/components/bottom-sheet/AGENTS.md +186 -231
- package/src/components/bottom-sheet/bottom-sheet-background.tsx +31 -22
- package/src/components/bottom-sheet/bottom-sheet-close.tsx +23 -30
- package/src/components/bottom-sheet/bottom-sheet-container.tsx +54 -208
- package/src/components/bottom-sheet/bottom-sheet-content.tsx +25 -48
- package/src/components/bottom-sheet/bottom-sheet-description.tsx +8 -2
- package/src/components/bottom-sheet/bottom-sheet-flat-list.tsx +65 -0
- package/src/components/bottom-sheet/bottom-sheet-footer.tsx +53 -122
- package/src/components/bottom-sheet/bottom-sheet-handle.tsx +31 -26
- package/src/components/bottom-sheet/bottom-sheet-legend-list.tsx +69 -0
- package/src/components/bottom-sheet/bottom-sheet-overlay.tsx +25 -147
- package/src/components/bottom-sheet/bottom-sheet-provider.tsx +42 -0
- package/src/components/bottom-sheet/bottom-sheet-scroll-view.tsx +38 -62
- package/src/components/bottom-sheet/bottom-sheet-section-list.tsx +58 -0
- package/src/components/bottom-sheet/bottom-sheet-steps.tsx +88 -0
- package/src/components/bottom-sheet/bottom-sheet-text-input.tsx +44 -0
- package/src/components/bottom-sheet/bottom-sheet-title.tsx +12 -8
- package/src/components/bottom-sheet/bottom-sheet-trigger.tsx +19 -37
- package/src/components/bottom-sheet/bottom-sheet.tsx +113 -60
- package/src/components/bottom-sheet/bottom-sheet.variants.test.ts +47 -87
- package/src/components/bottom-sheet/bottom-sheet.variants.ts +50 -126
- package/src/components/bottom-sheet/index.ts +39 -17
- package/src/components/bottom-sheet/use-bottom-sheet-input.ts +16 -115
- package/src/components/button/AGENTS.md +51 -11
- package/src/components/button/button-group.tsx +44 -8
- package/src/components/button/button.context.tsx +10 -0
- package/src/components/button/button.tsx +7 -1
- package/src/components/button/button.variants.test.ts +190 -0
- package/src/components/button/button.variants.ts +87 -6
- package/src/components/button/index.ts +2 -0
- package/src/components/calendar/AGENTS.md +142 -0
- package/src/components/calendar/calendar-caption.tsx +116 -0
- package/src/components/calendar/calendar-day.tsx +103 -0
- package/src/components/calendar/calendar-grid.tsx +183 -0
- package/src/components/calendar/calendar-header.tsx +34 -0
- package/src/components/calendar/calendar-nav.tsx +51 -0
- package/src/components/calendar/calendar-picker.tsx +128 -0
- package/src/components/calendar/calendar-weekdays.tsx +48 -0
- package/src/components/calendar/calendar.context.tsx +108 -0
- package/src/components/calendar/calendar.date.test.ts +456 -0
- package/src/components/calendar/calendar.date.ts +584 -0
- package/src/components/calendar/calendar.tsx +389 -0
- package/src/components/calendar/calendar.types.ts +87 -0
- package/src/components/calendar/calendar.variants.test.ts +363 -0
- package/src/components/calendar/calendar.variants.ts +426 -0
- package/src/components/calendar/index.ts +96 -0
- package/src/components/card/AGENTS.md +92 -0
- package/src/components/card/card-action.tsx +16 -0
- package/src/components/card/card-content.tsx +12 -0
- package/src/components/card/card-description.tsx +12 -0
- package/src/components/card/card-footer.tsx +30 -0
- package/src/components/card/card-header.tsx +45 -0
- package/src/components/card/card-title.tsx +25 -0
- package/src/components/card/card.context.tsx +64 -0
- package/src/components/card/card.tsx +100 -0
- package/src/components/card/card.types.ts +13 -0
- package/src/components/card/card.variants.test.ts +240 -0
- package/src/components/card/card.variants.ts +177 -0
- package/src/components/card/index.ts +15 -0
- package/src/components/chart/AGENTS.md +8 -0
- package/src/components/chart/chart.tsx +8 -1
- package/src/components/chip/AGENTS.md +113 -0
- package/src/components/chip/chip-close-button.tsx +48 -0
- package/src/components/chip/chip-end-content.tsx +15 -0
- package/src/components/chip/chip-label.tsx +21 -0
- package/src/components/chip/chip-start-content.tsx +16 -0
- package/src/components/chip/chip.context.tsx +66 -0
- package/src/components/chip/chip.tsx +268 -0
- package/src/components/chip/chip.types.ts +10 -0
- package/src/components/chip/chip.variants.test.ts +335 -0
- package/src/components/chip/chip.variants.ts +321 -0
- package/src/components/chip/index.ts +24 -0
- package/src/components/collapsible/AGENTS.md +97 -0
- package/src/components/collapsible/collapsible-content.tsx +97 -0
- package/src/components/collapsible/collapsible-description.tsx +17 -0
- package/src/components/collapsible/collapsible-indicator.tsx +92 -0
- package/src/components/collapsible/collapsible-title.tsx +17 -0
- package/src/components/collapsible/collapsible-trigger.tsx +133 -0
- package/src/components/collapsible/collapsible.context.tsx +91 -0
- package/src/components/collapsible/collapsible.tsx +167 -0
- package/src/components/collapsible/collapsible.types.ts +9 -0
- package/src/components/collapsible/collapsible.variants.test.ts +338 -0
- package/src/components/collapsible/collapsible.variants.ts +228 -0
- package/src/components/collapsible/index.ts +32 -0
- package/src/components/context-menu/AGENTS.md +103 -0
- package/src/components/context-menu/context-menu-content.tsx +64 -0
- package/src/components/context-menu/context-menu-item.tsx +22 -0
- package/src/components/context-menu/context-menu-preview.tsx +60 -0
- package/src/components/context-menu/context-menu-trigger.tsx +160 -0
- package/src/components/context-menu/context-menu.context.tsx +91 -0
- package/src/components/context-menu/context-menu.tsx +90 -0
- package/src/components/context-menu/context-menu.variants.test.ts +266 -0
- package/src/components/context-menu/context-menu.variants.ts +147 -0
- package/src/components/context-menu/index.ts +18 -0
- package/src/components/dialog/AGENTS.md +97 -0
- package/src/components/dialog/dialog-body.tsx +21 -0
- package/src/components/dialog/dialog-close.tsx +82 -0
- package/src/components/dialog/dialog-content.tsx +153 -0
- package/src/components/dialog/dialog-description.tsx +23 -0
- package/src/components/dialog/dialog-footer.tsx +32 -0
- package/src/components/dialog/dialog-header.tsx +20 -0
- package/src/components/dialog/dialog-title.tsx +42 -0
- package/src/components/dialog/dialog-trigger.tsx +54 -0
- package/src/components/dialog/dialog.context.tsx +90 -0
- package/src/components/dialog/dialog.tsx +119 -0
- package/src/components/dialog/dialog.variants.test.ts +224 -0
- package/src/components/dialog/dialog.variants.ts +173 -0
- package/src/components/dialog/index.ts +30 -0
- package/src/components/drawer/AGENTS.md +123 -0
- package/src/components/drawer/drawer-body.tsx +46 -0
- package/src/components/drawer/drawer-close.tsx +76 -0
- package/src/components/drawer/drawer-content.tsx +186 -0
- package/src/components/drawer/drawer-description.tsx +23 -0
- package/src/components/drawer/drawer-footer.tsx +21 -0
- package/src/components/drawer/drawer-header.tsx +42 -0
- package/src/components/drawer/drawer-title.tsx +35 -0
- package/src/components/drawer/drawer-trigger.tsx +54 -0
- package/src/components/drawer/drawer.context.tsx +114 -0
- package/src/components/drawer/drawer.tsx +119 -0
- package/src/components/drawer/drawer.variants.test.ts +392 -0
- package/src/components/drawer/drawer.variants.ts +244 -0
- package/src/components/drawer/index.ts +41 -0
- package/src/components/drawer/use-drawer-pan.ts +108 -0
- package/src/components/empty-state/AGENTS.md +90 -0
- package/src/components/empty-state/empty-state-content.tsx +17 -0
- package/src/components/empty-state/empty-state-description.tsx +12 -0
- package/src/components/empty-state/empty-state-header.tsx +17 -0
- package/src/components/empty-state/empty-state-media.tsx +56 -0
- package/src/components/empty-state/empty-state-title.tsx +18 -0
- package/src/components/empty-state/empty-state.context.tsx +65 -0
- package/src/components/empty-state/empty-state.tsx +84 -0
- package/src/components/empty-state/empty-state.types.ts +14 -0
- package/src/components/empty-state/empty-state.variants.test.ts +245 -0
- package/src/components/empty-state/empty-state.variants.ts +132 -0
- package/src/components/empty-state/index.ts +20 -0
- package/src/components/fab/AGENTS.md +119 -0
- package/src/components/fab/fab-action.tsx +118 -0
- package/src/components/fab/fab-group.tsx +214 -0
- package/src/components/fab/fab-label.tsx +18 -0
- package/src/components/fab/fab.context.tsx +125 -0
- package/src/components/fab/fab.tsx +156 -0
- package/src/components/fab/fab.types.ts +17 -0
- package/src/components/fab/fab.variants.test.ts +274 -0
- package/src/components/fab/fab.variants.ts +234 -0
- package/src/components/fab/index.ts +37 -0
- package/src/components/feedback/AGENTS.md +95 -0
- package/src/components/feedback/feedback-action.tsx +16 -0
- package/src/components/feedback/feedback-cancel.tsx +34 -0
- package/src/components/feedback/feedback-close.tsx +21 -0
- package/src/components/feedback/feedback-content.tsx +24 -0
- package/src/components/feedback/feedback-field.tsx +70 -0
- package/src/components/feedback/feedback-footer.tsx +21 -0
- package/src/components/feedback/feedback-panel.tsx +54 -0
- package/src/components/feedback/feedback-submit.tsx +74 -0
- package/src/components/feedback/feedback-title.tsx +34 -0
- package/src/components/feedback/feedback-trigger.tsx +20 -0
- package/src/components/feedback/feedback.context.tsx +73 -0
- package/src/components/feedback/feedback.tsx +135 -0
- package/src/components/feedback/feedback.variants.test.ts +185 -0
- package/src/components/feedback/feedback.variants.ts +128 -0
- package/src/components/feedback/index.ts +24 -0
- package/src/components/field/AGENTS.md +19 -0
- package/src/components/field/field-label.tsx +19 -5
- package/src/components/field/field.context.tsx +17 -0
- package/src/components/field/field.tsx +15 -2
- package/src/components/field/field.variants.test.ts +24 -0
- package/src/components/field/field.variants.ts +20 -0
- package/src/components/field/index.ts +1 -0
- package/src/components/input/AGENTS.md +5 -0
- package/src/components/input/input.variants.test.ts +32 -0
- package/src/components/input/input.variants.ts +13 -1
- package/src/components/item/AGENTS.md +92 -0
- package/src/components/item/index.ts +25 -0
- package/src/components/item/item-actions.tsx +28 -0
- package/src/components/item/item-content.tsx +15 -0
- package/src/components/item/item-description.tsx +12 -0
- package/src/components/item/item-footer.tsx +13 -0
- package/src/components/item/item-group.tsx +32 -0
- package/src/components/item/item-header.tsx +13 -0
- package/src/components/item/item-media.tsx +37 -0
- package/src/components/item/item-separator.tsx +13 -0
- package/src/components/item/item-title.tsx +17 -0
- package/src/components/item/item.context.tsx +66 -0
- package/src/components/item/item.tsx +218 -0
- package/src/components/item/item.types.ts +12 -0
- package/src/components/item/item.variants.test.ts +263 -0
- package/src/components/item/item.variants.ts +200 -0
- package/src/components/kpi/AGENTS.md +125 -0
- package/src/components/kpi/index.ts +45 -0
- package/src/components/kpi/kpi-action.tsx +12 -0
- package/src/components/kpi/kpi-content.tsx +35 -0
- package/src/components/kpi/kpi-footer.tsx +52 -0
- package/src/components/kpi/kpi-group.tsx +70 -0
- package/src/components/kpi/kpi-header.tsx +25 -0
- package/src/components/kpi/kpi-icon.tsx +28 -0
- package/src/components/kpi/kpi-sparkline.tsx +145 -0
- package/src/components/kpi/kpi-stat.tsx +20 -0
- package/src/components/kpi/kpi-title.tsx +19 -0
- package/src/components/kpi/kpi-trend.tsx +105 -0
- package/src/components/kpi/kpi-value.tsx +32 -0
- package/src/components/kpi/kpi.context.tsx +111 -0
- package/src/components/kpi/kpi.tsx +154 -0
- package/src/components/kpi/kpi.types.ts +9 -0
- package/src/components/kpi/kpi.variants.test.ts +428 -0
- package/src/components/kpi/kpi.variants.ts +347 -0
- package/src/components/label/AGENTS.md +89 -0
- package/src/components/label/index.ts +10 -0
- package/src/components/label/label.tsx +97 -0
- package/src/components/label/label.variants.test.ts +176 -0
- package/src/components/label/label.variants.ts +123 -0
- package/src/components/menu/AGENTS.md +176 -0
- package/src/components/menu/index.ts +44 -0
- package/src/components/menu/menu-background.tsx +17 -0
- package/src/components/menu/menu-checkbox-item.tsx +57 -0
- package/src/components/menu/menu-content.tsx +303 -0
- package/src/components/menu/menu-item.tsx +162 -0
- package/src/components/menu/menu-label.tsx +14 -0
- package/src/components/menu/menu-radio-group.tsx +50 -0
- package/src/components/menu/menu-radio-item.tsx +57 -0
- package/src/components/menu/menu-separator.tsx +11 -0
- package/src/components/menu/menu-sub-content.tsx +72 -0
- package/src/components/menu/menu-sub-trigger.tsx +50 -0
- package/src/components/menu/menu-sub.tsx +75 -0
- package/src/components/menu/menu-trigger.tsx +57 -0
- package/src/components/menu/menu.context.tsx +214 -0
- package/src/components/menu/menu.tsx +88 -0
- package/src/components/menu/menu.types.ts +33 -0
- package/src/components/menu/menu.variants.test.ts +400 -0
- package/src/components/menu/menu.variants.ts +353 -0
- package/src/components/meter/AGENTS.md +135 -0
- package/src/components/meter/index.ts +43 -0
- package/src/components/meter/meter-fill.tsx +19 -0
- package/src/components/meter/meter-header.tsx +17 -0
- package/src/components/meter/meter-label.tsx +18 -0
- package/src/components/meter/meter-output.tsx +42 -0
- package/src/components/meter/meter-segments.tsx +83 -0
- package/src/components/meter/meter-track.tsx +16 -0
- package/src/components/meter/meter.context.tsx +62 -0
- package/src/components/meter/meter.tsx +286 -0
- package/src/components/meter/meter.types.ts +30 -0
- package/src/components/meter/meter.variants.test.ts +430 -0
- package/src/components/meter/meter.variants.ts +347 -0
- package/src/components/overlay/AGENTS.md +89 -0
- package/src/components/overlay/index.ts +27 -0
- package/src/components/overlay/overlay-portal.tsx +84 -0
- package/src/components/overlay/overlay-presence.test.ts +46 -0
- package/src/components/overlay/overlay-presence.ts +49 -0
- package/src/components/overlay/overlay-registry.test.ts +96 -0
- package/src/components/overlay/overlay-registry.ts +99 -0
- package/src/components/overlay/overlay-scrim.tsx +49 -0
- package/src/components/overlay/overlay.context.tsx +48 -0
- package/src/components/overlay/overlay.tsx +118 -0
- package/src/components/overlay/overlay.variants.test.ts +37 -0
- package/src/components/overlay/overlay.variants.ts +33 -0
- package/src/components/overlay/use-overlay-back-handler.ts +34 -0
- package/src/components/overlay/use-overlay-presence.ts +87 -0
- package/src/components/popover/AGENTS.md +138 -0
- package/src/components/popover/index.ts +48 -0
- package/src/components/popover/popover-anchor.tsx +49 -0
- package/src/components/popover/popover-arrow.tsx +89 -0
- package/src/components/popover/popover-close.tsx +73 -0
- package/src/components/popover/popover-content.tsx +235 -0
- package/src/components/popover/popover-description.tsx +18 -0
- package/src/components/popover/popover-title.tsx +33 -0
- package/src/components/popover/popover-trigger.tsx +56 -0
- package/src/components/popover/popover.context.tsx +71 -0
- package/src/components/popover/popover.position.test.ts +354 -0
- package/src/components/popover/popover.position.ts +286 -0
- package/src/components/popover/popover.tsx +123 -0
- package/src/components/popover/popover.variants.test.ts +135 -0
- package/src/components/popover/popover.variants.ts +85 -0
- package/src/components/popover/use-anchor-measure.ts +76 -0
- package/src/components/popover/use-anchored-content.ts +219 -0
- package/src/components/pressable/AGENTS.md +11 -1
- package/src/components/pressable/pressable.tsx +7 -2
- package/src/components/pressable/pressable.variants.test.ts +29 -0
- package/src/components/pressable/pressable.variants.ts +17 -0
- package/src/components/progress/AGENTS.md +120 -0
- package/src/components/progress/index.ts +40 -0
- package/src/components/progress/progress-fill.tsx +152 -0
- package/src/components/progress/progress-header.tsx +19 -0
- package/src/components/progress/progress-label.tsx +27 -0
- package/src/components/progress/progress-output.tsx +47 -0
- package/src/components/progress/progress-track.tsx +38 -0
- package/src/components/progress/progress.context.tsx +79 -0
- package/src/components/progress/progress.tsx +171 -0
- package/src/components/progress/progress.types.ts +23 -0
- package/src/components/progress/progress.variants.test.ts +335 -0
- package/src/components/progress/progress.variants.ts +284 -0
- package/src/components/progress-button/AGENTS.md +116 -0
- package/src/components/progress-button/index.ts +36 -0
- package/src/components/progress-button/progress-button-done.tsx +33 -0
- package/src/components/progress-button/progress-button-label.tsx +27 -0
- package/src/components/progress-button/progress-button.context.tsx +93 -0
- package/src/components/progress-button/progress-button.tsx +414 -0
- package/src/components/progress-button/progress-button.variants.test.ts +314 -0
- package/src/components/progress-button/progress-button.variants.ts +236 -0
- package/src/components/provider/AGENTS.md +38 -25
- package/src/components/provider/provider.tsx +38 -11
- package/src/components/radio/AGENTS.md +8 -10
- package/src/components/radio/radio.variants.test.ts +5 -6
- package/src/components/radio/radio.variants.ts +6 -7
- package/src/components/rating/AGENTS.md +143 -0
- package/src/components/rating/index.ts +43 -0
- package/src/components/rating/rating-output.tsx +39 -0
- package/src/components/rating/rating-star.tsx +70 -0
- package/src/components/rating/rating-stars.tsx +219 -0
- package/src/components/rating/rating.context.tsx +79 -0
- package/src/components/rating/rating.tsx +163 -0
- package/src/components/rating/rating.variants.test.ts +347 -0
- package/src/components/rating/rating.variants.ts +354 -0
- package/src/components/selection-mode/AGENTS.md +155 -0
- package/src/components/selection-mode/index.ts +43 -0
- package/src/components/selection-mode/selection-mode-action.tsx +65 -0
- package/src/components/selection-mode/selection-mode-bar.tsx +79 -0
- package/src/components/selection-mode/selection-mode-group.tsx +123 -0
- package/src/components/selection-mode/selection-mode-header.tsx +85 -0
- package/src/components/selection-mode/selection-mode-indicator.tsx +118 -0
- package/src/components/selection-mode/selection-mode-item.tsx +182 -0
- package/src/components/selection-mode/selection-mode.context.tsx +89 -0
- package/src/components/selection-mode/selection-mode.tsx +207 -0
- package/src/components/selection-mode/selection-mode.types.ts +36 -0
- package/src/components/selection-mode/selection-mode.variants.test.ts +292 -0
- package/src/components/selection-mode/selection-mode.variants.ts +329 -0
- package/src/components/skeleton/AGENTS.md +120 -0
- package/src/components/skeleton/index.ts +15 -0
- package/src/components/skeleton/skeleton-clock.ts +48 -0
- package/src/components/skeleton/skeleton-group.tsx +64 -0
- package/src/components/skeleton/skeleton-shimmer.tsx +80 -0
- package/src/components/skeleton/skeleton.context.tsx +45 -0
- package/src/components/skeleton/skeleton.tsx +227 -0
- package/src/components/skeleton/skeleton.variants.test.ts +245 -0
- package/src/components/skeleton/skeleton.variants.ts +222 -0
- package/src/components/slide-button/AGENTS.md +122 -0
- package/src/components/slide-button/index.ts +43 -0
- package/src/components/slide-button/slide-button-label.tsx +70 -0
- package/src/components/slide-button/slide-button-thumb.tsx +93 -0
- package/src/components/slide-button/slide-button.context.tsx +76 -0
- package/src/components/slide-button/slide-button.tsx +457 -0
- package/src/components/slide-button/slide-button.variants.test.ts +288 -0
- package/src/components/slide-button/slide-button.variants.ts +324 -0
- package/src/components/slider/index.ts +2 -0
- package/src/components/slider/slider-thumb.tsx +33 -1
- package/src/components/slider/slider.variants.test.ts +52 -0
- package/src/components/slider/slider.variants.ts +56 -2
- package/src/components/stack-card/AGENTS.md +169 -0
- package/src/components/stack-card/index.ts +37 -0
- package/src/components/stack-card/stack-card-action.tsx +66 -0
- package/src/components/stack-card/stack-card-actions.tsx +18 -0
- package/src/components/stack-card/stack-card-card.tsx +71 -0
- package/src/components/stack-card/stack-card-empty.tsx +30 -0
- package/src/components/stack-card/stack-card-slot.tsx +90 -0
- package/src/components/stack-card/stack-card-stamp.tsx +76 -0
- package/src/components/stack-card/stack-card.context.tsx +117 -0
- package/src/components/stack-card/stack-card.tsx +557 -0
- package/src/components/stack-card/stack-card.types.ts +26 -0
- package/src/components/stack-card/stack-card.variants.test.ts +355 -0
- package/src/components/stack-card/stack-card.variants.ts +360 -0
- package/src/components/steps/AGENTS.md +153 -0
- package/src/components/steps/index.ts +45 -0
- package/src/components/steps/steps-connector.tsx +31 -0
- package/src/components/steps/steps-description.tsx +26 -0
- package/src/components/steps/steps-indicator.tsx +106 -0
- package/src/components/steps/steps-item.tsx +225 -0
- package/src/components/steps/steps-panel.tsx +41 -0
- package/src/components/steps/steps-title.tsx +32 -0
- package/src/components/steps/steps-track.tsx +59 -0
- package/src/components/steps/steps.context.tsx +123 -0
- package/src/components/steps/steps.tsx +166 -0
- package/src/components/steps/steps.variants.test.ts +388 -0
- package/src/components/steps/steps.variants.ts +468 -0
- package/src/components/surface/AGENTS.md +82 -0
- package/src/components/surface/index.ts +15 -0
- package/src/components/surface/surface.context.tsx +56 -0
- package/src/components/surface/surface.tsx +87 -0
- package/src/components/surface/surface.variants.test.ts +227 -0
- package/src/components/surface/surface.variants.ts +165 -0
- package/src/components/swipe/AGENTS.md +140 -0
- package/src/components/swipe/index.ts +31 -0
- package/src/components/swipe/swipe-action.tsx +99 -0
- package/src/components/swipe/swipe-end.tsx +14 -0
- package/src/components/swipe/swipe-group.tsx +55 -0
- package/src/components/swipe/swipe-panel.tsx +55 -0
- package/src/components/swipe/swipe-start.tsx +15 -0
- package/src/components/swipe/swipe.context.tsx +135 -0
- package/src/components/swipe/swipe.tsx +393 -0
- package/src/components/swipe/swipe.types.ts +7 -0
- package/src/components/swipe/swipe.variants.test.ts +337 -0
- package/src/components/swipe/swipe.variants.ts +290 -0
- package/src/components/switch/switch.variants.ts +2 -2
- package/src/components/tabs/AGENTS.md +4 -3
- package/src/components/tabs/tabs.variants.test.ts +1 -1
- package/src/components/tabs/tabs.variants.ts +4 -6
- package/src/components/text/AGENTS.md +8 -2
- package/src/components/text/text.tsx +7 -0
- package/src/components/text/text.variants.test.ts +24 -1
- package/src/components/text/text.variants.ts +5 -0
- package/src/components/textarea/AGENTS.md +89 -0
- package/src/components/textarea/index.ts +16 -0
- package/src/components/textarea/textarea.tsx +157 -0
- package/src/components/textarea/textarea.variants.test.ts +219 -0
- package/src/components/textarea/textarea.variants.ts +171 -0
- package/src/components/toast/AGENTS.md +140 -0
- package/src/components/toast/index.ts +74 -0
- package/src/components/toast/toast-action.tsx +59 -0
- package/src/components/toast/toast-api.ts +32 -0
- package/src/components/toast/toast-close.tsx +44 -0
- package/src/components/toast/toast-content.tsx +11 -0
- package/src/components/toast/toast-description.tsx +11 -0
- package/src/components/toast/toast-indicator.tsx +34 -0
- package/src/components/toast/toast-item.tsx +308 -0
- package/src/components/toast/toast-title.tsx +13 -0
- package/src/components/toast/toast-viewport.tsx +135 -0
- package/src/components/toast/toast.context.tsx +69 -0
- package/src/components/toast/toast.store.test.ts +259 -0
- package/src/components/toast/toast.store.ts +338 -0
- package/src/components/toast/toast.timer.test.ts +64 -0
- package/src/components/toast/toast.timer.ts +51 -0
- package/src/components/toast/toast.tsx +132 -0
- package/src/components/toast/toast.variants.test.ts +393 -0
- package/src/components/toast/toast.variants.ts +304 -0
- package/src/components/toggle-button/AGENTS.md +106 -0
- package/src/components/toggle-button/index.ts +30 -0
- package/src/components/toggle-button/toggle-button-group.tsx +156 -0
- package/src/components/toggle-button/toggle-button-label.tsx +19 -0
- package/src/components/toggle-button/toggle-button.context.tsx +130 -0
- package/src/components/toggle-button/toggle-button.tsx +172 -0
- package/src/components/toggle-button/toggle-button.variants.test.ts +189 -0
- package/src/components/toggle-button/toggle-button.variants.ts +160 -0
- package/src/components/tooltip/AGENTS.md +133 -0
- package/src/components/tooltip/index.ts +28 -0
- package/src/components/tooltip/tooltip-arrow.tsx +40 -0
- package/src/components/tooltip/tooltip-content.tsx +179 -0
- package/src/components/tooltip/tooltip-description.tsx +19 -0
- package/src/components/tooltip/tooltip-text.tsx +21 -0
- package/src/components/tooltip/tooltip-title.tsx +20 -0
- package/src/components/tooltip/tooltip-trigger.tsx +103 -0
- package/src/components/tooltip/tooltip.context.tsx +68 -0
- package/src/components/tooltip/tooltip.tsx +213 -0
- package/src/components/tooltip/tooltip.variants.test.ts +231 -0
- package/src/components/tooltip/tooltip.variants.ts +177 -0
- package/src/hooks/use-calm-motion.tsx +31 -0
- package/src/lib/calm-motion.test.ts +17 -0
- package/src/lib/calm-motion.ts +23 -0
- package/src/lib/cn.parity.test.ts +62 -0
- package/src/lib/cn.test.ts +14 -0
- package/src/lib/cn.ts +11 -6
- package/src/no-gorhom.test.ts +54 -0
- package/src/styles/geometry.test.ts +1 -0
- package/src/styles/theme.css +4 -0
- package/src/styles/tokens.css +44 -0
- package/src/styles/tokens.test.ts +56 -0
- package/src/styles/tokens.ts +29 -1
- package/src/components/bottom-sheet/bottom-sheet-portal.tsx +0 -72
- package/src/components/bottom-sheet/bottom-sheet.context.tsx +0 -135
|
@@ -1,150 +1,81 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BottomSheet as Headless,
|
|
3
|
+
type BottomSheetFooterProps as HeadlessProps,
|
|
4
|
+
} from "@delacour/react-native-bottom-sheet";
|
|
5
|
+
import type { ReactElement } from "react";
|
|
6
|
+
import { withUniwind } from "uniwind";
|
|
7
7
|
import { BOTTOM_SHEET_FOOTER_PADDING, bottomSheetVariants } from "./bottom-sheet.variants";
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type StyledFooterComponent = (props: HeadlessProps & { className?: string }) => ReactElement | null;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* Off by default, matching `Screen.Footer` — a footer holding a submit button
|
|
17
|
-
* under a short sheet wants to sit where it was written, and a sheet only
|
|
18
|
-
* needs the pinned treatment once its body can scroll under one.
|
|
19
|
-
*
|
|
20
|
-
* @default false
|
|
21
|
-
*/
|
|
22
|
-
sticky?: boolean;
|
|
11
|
+
// Built once at module scope; the classes land on the engine's inner, measured
|
|
12
|
+
// view, after its own `padding`, so the gutter here wins the horizontal axis.
|
|
13
|
+
const StyledFooter = withUniwind(Headless.Footer) as unknown as StyledFooterComponent;
|
|
14
|
+
|
|
15
|
+
export type BottomSheetFooterProps = HeadlessProps & {
|
|
23
16
|
className?: string;
|
|
24
|
-
children?: ReactNode;
|
|
25
|
-
/**
|
|
26
|
-
* The sheet's own footer position. Injected by `BottomSheet.Container` when it
|
|
27
|
-
* hoists a sticky footer; never written at a call site.
|
|
28
|
-
*/
|
|
29
|
-
animatedFooterPosition?: GorhomFooterProps["animatedFooterPosition"];
|
|
30
|
-
/**
|
|
31
|
-
* Where this footer publishes its measured height. Injected alongside the
|
|
32
|
-
* position, and read by whatever the sheet's body is so it can reserve exactly
|
|
33
|
-
* what the footer covers. Never written at a call site.
|
|
34
|
-
*/
|
|
35
|
-
footerHeight?: SharedValue<number>;
|
|
36
17
|
};
|
|
37
18
|
|
|
38
19
|
/**
|
|
39
|
-
* A row of controls at the bottom of the sheet —
|
|
40
|
-
*
|
|
41
|
-
* **A sticky footer is not rendered where it is written.** gorhom takes it as a
|
|
42
|
-
* `footerComponent` render prop rather than as a child, so
|
|
43
|
-
* `BottomSheet.Container` lifts this element out of its children and clones it
|
|
44
|
-
* into that slot with the sheet's animated footer position attached. An inline
|
|
45
|
-
* footer needs none of that and stays exactly where it was put.
|
|
46
|
-
*
|
|
47
|
-
* The two branches deliberately look different. An inline footer is in the flow
|
|
48
|
-
* and inherits the sheet's surface; a pinned one draws OVER the content, so it
|
|
49
|
-
* brings a background and a top hairline of its own — without them the content
|
|
50
|
-
* scrolls straight through it and its buttons are legible only where they happen
|
|
51
|
-
* to overlap blank space. That is `Screen.Footer`'s rule about its backing, one
|
|
52
|
-
* component along.
|
|
53
|
-
*
|
|
54
|
-
* **A pinned footer is TALLER by the safe-area band; it is not moved up by it.**
|
|
55
|
-
* gorhom's own `bottomInset` translates the whole footer up instead, which
|
|
56
|
-
* leaves a band the height of the home indicator between the footer and the
|
|
57
|
-
* bottom of the sheet — and the content scrolls through it in plain view. So
|
|
58
|
-
* `bottomInset` stays 0 and the band becomes the footer's own `paddingBottom`,
|
|
59
|
-
* which puts its surface against the bottom of the screen where it belongs.
|
|
60
|
-
*
|
|
61
|
-
* The keyboard then needs that band back, and **only that band**. Its own
|
|
62
|
-
* padding stays, so the controls never end up flush against the keyboard, and
|
|
63
|
-
* the footer genuinely gets shorter rather than sliding down — which is what
|
|
64
|
-
* lets the body's reserve shrink with it instead of over-reserving by the height
|
|
65
|
-
* of a home indicator that is no longer there.
|
|
20
|
+
* A row of controls at the bottom of the sheet — in the flow, or pinned.
|
|
66
21
|
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
22
|
+
* **`sticky` is off by default, matching `Screen.Footer`**, and that is the one
|
|
23
|
+
* place this skin overrides the engine's default: a footer holding a submit
|
|
24
|
+
* button under a short sheet wants to sit where it was written, and a sheet
|
|
25
|
+
* only needs the pinned treatment once its body can scroll under one. Write a
|
|
26
|
+
* pinned footer inside `Container`, after the body; an inline one inside the
|
|
27
|
+
* body, where it should scroll.
|
|
73
28
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
29
|
+
* The two branches deliberately look different. An inline footer is in the
|
|
30
|
+
* flow and inherits the sheet's surface; a pinned one draws OVER the content,
|
|
31
|
+
* so it brings a background and a top hairline of its own — without them the
|
|
32
|
+
* content scrolls straight through it. That is `Screen.Footer`'s rule about its
|
|
33
|
+
* backing, one component along.
|
|
78
34
|
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
35
|
+
* Everything else is the engine's: a pinned footer is translated to the
|
|
36
|
+
* geometry's footer line, which the core proves holds still through a keyboard
|
|
37
|
+
* animation, so its buttons land on the keyboard's top edge without moving;
|
|
38
|
+
* the safe-area band under it is a spacer the geometry owns; and its measured
|
|
39
|
+
* height is what the body reserves and the dynamic snap point counts. The
|
|
40
|
+
* `padding` goes to the engine rather than a class for that reason — it has to
|
|
41
|
+
* be inside the measured box.
|
|
82
42
|
*
|
|
83
43
|
* @example
|
|
84
|
-
* <BottomSheet.
|
|
85
|
-
* <
|
|
86
|
-
*
|
|
44
|
+
* <BottomSheet.Container>
|
|
45
|
+
* <BottomSheet.Content>{fields}</BottomSheet.Content>
|
|
46
|
+
* <BottomSheet.Footer sticky>
|
|
47
|
+
* <Button onPress={save}>Save</Button>
|
|
48
|
+
* </BottomSheet.Footer>
|
|
49
|
+
* </BottomSheet.Container>
|
|
87
50
|
*
|
|
88
51
|
* @example
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
52
|
+
* // In the flow — inside the body, scrolling with it.
|
|
53
|
+
* <BottomSheet.ScrollView>
|
|
54
|
+
* {copy}
|
|
55
|
+
* <BottomSheet.Footer>
|
|
56
|
+
* <Button>Continue</Button>
|
|
57
|
+
* </BottomSheet.Footer>
|
|
58
|
+
* </BottomSheet.ScrollView>
|
|
92
59
|
*/
|
|
93
60
|
export function BottomSheetFooter({
|
|
94
|
-
animatedFooterPosition,
|
|
95
61
|
className,
|
|
96
|
-
children,
|
|
97
|
-
footerHeight,
|
|
98
|
-
onLayout,
|
|
99
62
|
sticky = false,
|
|
100
|
-
|
|
63
|
+
padding,
|
|
101
64
|
...props
|
|
102
65
|
}: BottomSheetFooterProps): ReactElement {
|
|
103
|
-
const { bottom } = useSafeAreaInsets();
|
|
104
|
-
const { progress } = useReanimatedKeyboardAnimation();
|
|
105
66
|
const slots = bottomSheetVariants();
|
|
106
67
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
// own animation, so the two travel together.
|
|
110
|
-
const padding = useAnimatedStyle(() => ({
|
|
111
|
-
paddingBottom: BOTTOM_SHEET_FOOTER_PADDING + bottom * (1 - progress.value),
|
|
112
|
-
paddingTop: BOTTOM_SHEET_FOOTER_PADDING,
|
|
113
|
-
}));
|
|
114
|
-
|
|
115
|
-
const handleLayout = useCallback(
|
|
116
|
-
(event: LayoutChangeEvent) => {
|
|
117
|
-
if (footerHeight) footerHeight.value = event.nativeEvent.layout.height;
|
|
118
|
-
onLayout?.(event);
|
|
119
|
-
},
|
|
120
|
-
[footerHeight, onLayout]
|
|
121
|
-
);
|
|
122
|
-
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
return () => {
|
|
125
|
-
if (footerHeight) footerHeight.value = 0;
|
|
126
|
-
};
|
|
127
|
-
}, [footerHeight]);
|
|
128
|
-
|
|
129
|
-
if (!sticky || animatedFooterPosition === undefined) {
|
|
130
|
-
return (
|
|
131
|
-
<View className={slots.footer({ className })} style={style} {...props}>
|
|
132
|
-
{children}
|
|
133
|
-
</View>
|
|
134
|
-
);
|
|
68
|
+
if (!sticky) {
|
|
69
|
+
return <StyledFooter className={slots.footer({ className })} padding={padding} sticky={false} {...props} />;
|
|
135
70
|
}
|
|
136
71
|
|
|
137
72
|
return (
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
>
|
|
145
|
-
{children}
|
|
146
|
-
</Animated.View>
|
|
147
|
-
</GorhomBottomSheetFooter>
|
|
73
|
+
<StyledFooter
|
|
74
|
+
className={slots.stickyFooter({ className })}
|
|
75
|
+
padding={padding ?? BOTTOM_SHEET_FOOTER_PADDING}
|
|
76
|
+
sticky
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
148
79
|
);
|
|
149
80
|
}
|
|
150
81
|
BottomSheetFooter.displayName = "DelacourUI.BottomSheet.Footer";
|
|
@@ -1,36 +1,41 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
BottomSheet as Headless,
|
|
3
|
+
type BottomSheetHandleProps as HeadlessProps,
|
|
4
|
+
} from "@delacour/react-native-bottom-sheet";
|
|
2
5
|
import type { ReactElement } from "react";
|
|
3
|
-
import { View, type
|
|
6
|
+
import { type StyleProp, View, type ViewStyle } from "react-native";
|
|
7
|
+
import { withUniwind } from "uniwind";
|
|
4
8
|
import { bottomSheetVariants } from "./bottom-sheet.variants";
|
|
5
9
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
type StyledHandleComponent = (props: HeadlessProps & { className?: string }) => ReactElement | null;
|
|
11
|
+
|
|
12
|
+
// Built at module scope, or every render mints a new component type and the
|
|
13
|
+
// engine's pan re-attaches to a fresh view.
|
|
14
|
+
const StyledHandle = withUniwind(Headless.Handle) as unknown as StyledHandleComponent;
|
|
15
|
+
|
|
16
|
+
export type BottomSheetHandleProps = HeadlessProps & {
|
|
17
|
+
className?: string;
|
|
18
|
+
/** Classes for the grabber itself. */
|
|
19
|
+
indicatorClassName?: string;
|
|
20
|
+
indicatorStyle?: StyleProp<ViewStyle>;
|
|
21
|
+
};
|
|
13
22
|
|
|
14
23
|
/**
|
|
15
|
-
* The grabber
|
|
24
|
+
* The grabber's row.
|
|
16
25
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* rather than a class is not locked out.
|
|
26
|
+
* The engine's handle draws nothing of its own: it owns the pan, measures
|
|
27
|
+
* itself into the sheet's height, and is the adjustable element a screen
|
|
28
|
+
* reader steps through the snap points with. This puts the pill inside it, and
|
|
29
|
+
* classes on both.
|
|
22
30
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* so a second announced element here would put a nameless control in front of
|
|
26
|
-
* every sheet.
|
|
31
|
+
* Pass children to replace the pill; the row, the pan and the accessibility
|
|
32
|
+
* stay.
|
|
27
33
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
34
|
+
* @example
|
|
35
|
+
* <BottomSheet.Handle indicatorClassName="bg-primary" />
|
|
30
36
|
*/
|
|
31
37
|
export function BottomSheetHandle({
|
|
32
|
-
|
|
33
|
-
animatedPosition: _animatedPosition,
|
|
38
|
+
children,
|
|
34
39
|
className,
|
|
35
40
|
indicatorClassName,
|
|
36
41
|
indicatorStyle,
|
|
@@ -39,9 +44,9 @@ export function BottomSheetHandle({
|
|
|
39
44
|
const slots = bottomSheetVariants();
|
|
40
45
|
|
|
41
46
|
return (
|
|
42
|
-
<
|
|
43
|
-
<View className={slots.handleIndicator({ className: indicatorClassName })} style={indicatorStyle} />
|
|
44
|
-
</
|
|
47
|
+
<StyledHandle className={slots.handle({ className })} {...props}>
|
|
48
|
+
{children ?? <View className={slots.handleIndicator({ className: indicatorClassName })} style={indicatorStyle} />}
|
|
49
|
+
</StyledHandle>
|
|
45
50
|
);
|
|
46
51
|
}
|
|
47
52
|
BottomSheetHandle.displayName = "DelacourUI.BottomSheet.Handle";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type BottomSheetScrollableProps,
|
|
3
|
+
createBottomSheetScrollable,
|
|
4
|
+
SCROLLABLE_TYPE,
|
|
5
|
+
useBottomSheetInternal,
|
|
6
|
+
} from "@delacour/react-native-bottom-sheet";
|
|
7
|
+
import type { LegendListRef } from "@legendapp/list/react-native";
|
|
8
|
+
import { AnimatedLegendList, type AnimatedLegendListProps } from "@legendapp/list/reanimated";
|
|
9
|
+
import type { ReactElement, Ref } from "react";
|
|
10
|
+
import { withUniwind } from "uniwind";
|
|
11
|
+
import { cn } from "../../lib/cn";
|
|
12
|
+
import { BOTTOM_SHEET_FOOTER_GAP, bottomSheetVariants } from "./bottom-sheet.variants";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `AnimatedLegendList` as a sheet body.
|
|
16
|
+
*
|
|
17
|
+
* Made once at module scope, as the factory requires: the wrapper drives the
|
|
18
|
+
* list with `animatedProps` and an animated `onScroll`, and a component made
|
|
19
|
+
* inside a render is a new type every frame. Registered as a flat list, which
|
|
20
|
+
* is what it is to the sheet — one scroll offset, one drag budget.
|
|
21
|
+
*/
|
|
22
|
+
const SheetLegendList = createBottomSheetScrollable(AnimatedLegendList, SCROLLABLE_TYPE.FLAT_LIST);
|
|
23
|
+
|
|
24
|
+
/** The class props restated so `<ItemT>` survives `withUniwind` — see `bottom-sheet-flat-list.tsx`. */
|
|
25
|
+
type StyledLegendListComponent = <ItemT>(
|
|
26
|
+
props: AnimatedLegendListProps<ItemT> &
|
|
27
|
+
BottomSheetScrollableProps & { ref?: Ref<LegendListRef>; className?: string; contentContainerClassName?: string }
|
|
28
|
+
) => ReactElement | null;
|
|
29
|
+
|
|
30
|
+
const StyledLegendList = withUniwind(SheetLegendList) as unknown as StyledLegendListComponent;
|
|
31
|
+
|
|
32
|
+
export type BottomSheetLegendListProps<ItemT> = Omit<AnimatedLegendListProps<ItemT>, "renderScrollComponent"> &
|
|
33
|
+
BottomSheetScrollableProps & {
|
|
34
|
+
ref?: Ref<LegendListRef>;
|
|
35
|
+
className?: string;
|
|
36
|
+
/** Classes for the content container. Same gutter and gap as `Content`. */
|
|
37
|
+
contentContainerClassName?: string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A `LegendList` body, for a list long enough that `FlatList`'s virtualisation
|
|
42
|
+
* shows.
|
|
43
|
+
*
|
|
44
|
+
* Built here rather than in the engine because `@legendapp/list` is this
|
|
45
|
+
* library's optional peer, not the engine's: the engine exports the factory,
|
|
46
|
+
* and this is what the factory is for. The same scroll lock, drag budget and
|
|
47
|
+
* content-size snap point as the other three bodies.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* <BottomSheet.LegendList data={rows} keyExtractor={(row) => row.id} renderItem={renderRow} />
|
|
51
|
+
*/
|
|
52
|
+
export function BottomSheetLegendList<ItemT>({
|
|
53
|
+
className,
|
|
54
|
+
contentContainerClassName,
|
|
55
|
+
contentContainerStyle,
|
|
56
|
+
...props
|
|
57
|
+
}: BottomSheetLegendListProps<ItemT>): ReactElement {
|
|
58
|
+
const { hasFooter } = useBottomSheetInternal();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<StyledLegendList
|
|
62
|
+
className={cn(className)}
|
|
63
|
+
contentContainerClassName={bottomSheetVariants().scrollContent({ className: contentContainerClassName })}
|
|
64
|
+
contentContainerStyle={[{ paddingBottom: hasFooter ? BOTTOM_SHEET_FOOTER_GAP : 0 }, contentContainerStyle]}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
BottomSheetLegendList.displayName = "DelacourUI.BottomSheet.LegendList";
|
|
@@ -1,180 +1,58 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
} from "
|
|
6
|
-
import type { ReactElement, ReactNode } from "react";
|
|
7
|
-
import { StyleSheet } from "react-native";
|
|
8
|
-
import Animated, { useAnimatedStyle } from "react-native-reanimated";
|
|
2
|
+
BottomSheet as Headless,
|
|
3
|
+
type BottomSheetOverlayProps as HeadlessProps,
|
|
4
|
+
} from "@delacour/react-native-bottom-sheet";
|
|
5
|
+
import type { ReactElement } from "react";
|
|
9
6
|
import { withUniwind } from "uniwind";
|
|
10
|
-
import { Pressable } from "../pressable";
|
|
11
7
|
import {
|
|
12
8
|
BOTTOM_SHEET_BACKDROP_INDICES,
|
|
13
9
|
BOTTOM_SHEET_OVERLAY_OPACITY,
|
|
14
10
|
bottomSheetVariants,
|
|
15
11
|
} from "./bottom-sheet.variants";
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
* frame and remount the scrim mid-fade. See AGENTS.md rule 7.
|
|
23
|
-
*/
|
|
24
|
-
const StyledBackdrop = withUniwind(BottomSheetBackdrop);
|
|
13
|
+
type StyledOverlayComponent = (props: HeadlessProps & { className?: string }) => ReactElement | null;
|
|
14
|
+
|
|
15
|
+
// Third-party to Uniwind, so `className` needs the wrapper, built once at
|
|
16
|
+
// module scope.
|
|
17
|
+
const StyledOverlay = withUniwind(Headless.Overlay) as unknown as StyledOverlayComponent;
|
|
25
18
|
|
|
26
|
-
export type BottomSheetOverlayProps =
|
|
19
|
+
export type BottomSheetOverlayProps = HeadlessProps & {
|
|
27
20
|
className?: string;
|
|
28
|
-
/**
|
|
29
|
-
* Opacity at full appearance.
|
|
30
|
-
*
|
|
31
|
-
* Defaults to 1 rather than gorhom's 0.5, because `--overlay` carries
|
|
32
|
-
* its own alpha — the two would otherwise multiply and land the scrim at a
|
|
33
|
-
* fifth of what the theme asked for.
|
|
34
|
-
*/
|
|
35
|
-
opacity?: number;
|
|
36
|
-
/** Snap index the scrim is fully in by. @default 0, the first snap point */
|
|
37
|
-
appearsOnIndex?: number;
|
|
38
|
-
/** Snap index the scrim is gone by. @default -1, the closed position */
|
|
39
|
-
disappearsOnIndex?: number;
|
|
40
|
-
/** Let touches reach the app behind the scrim. @default false */
|
|
41
|
-
enableTouchThrough?: boolean;
|
|
42
|
-
/** Close the sheet when the scrim is pressed. @default true */
|
|
43
|
-
isCloseOnPress?: boolean;
|
|
44
|
-
/** Announced on the pressable scrim. Ignored when it does not close. */
|
|
45
|
-
accessibilityLabel?: string;
|
|
46
|
-
onPress?: () => void;
|
|
47
|
-
children?: ReactNode;
|
|
48
21
|
};
|
|
49
22
|
|
|
50
23
|
/**
|
|
51
24
|
* The scrim over the app behind the sheet.
|
|
52
25
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* what makes the anatomy read like the thing it draws.
|
|
59
|
-
*
|
|
60
|
-
* Omit it and the sheet has no scrim at all — gorhom's own default for
|
|
61
|
-
* `backdropComponent` is nothing.
|
|
62
|
-
*
|
|
63
|
-
* **gorhom's own press handling is deliberately turned off, and the press area
|
|
64
|
-
* is rebuilt here.** Its backdrop puts a full-screen `Gesture.Tap()` behind the
|
|
65
|
-
* sheet, and Gesture Handler resolves a touch between competing GESTURES: a
|
|
66
|
-
* `Button` in the sheet has one of its own and wins, but a `TextInput` has none,
|
|
67
|
-
* so the backdrop takes the tap and the sheet closes instead of the field
|
|
68
|
-
* focusing. That is why gorhom ships its own `BottomSheetTextInput` — and taking
|
|
69
|
-
* that route would mean this package's `Input`, with its variants, its
|
|
70
|
-
* `Input.Group` and its `Field` cascade, could not be used in a sheet at all.
|
|
26
|
+
* `bg-overlay`, a token that carries its own alpha, so the `opacity` here is 1
|
|
27
|
+
* and the two theme variants can differ. The engine fades it with the sheet's
|
|
28
|
+
* index — never with the keyboard — and makes it a plain `Pressable` written
|
|
29
|
+
* before the panel, which is what lets a tap on a field inside the sheet reach
|
|
30
|
+
* the field.
|
|
71
31
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* `animatedPosition`. It never overlaps the sheet, so there is nothing for it to
|
|
75
|
-
* take, and pressing the part of the scrim anyone can actually see still closes.
|
|
76
|
-
* The colour and the fade stay gorhom's, driven off the sheet's position on the
|
|
77
|
-
* UI thread; the slot therefore carries no `opacity-*`, or a class and an
|
|
78
|
-
* animated style would be two writers of one property.
|
|
32
|
+
* Omit it and the sheet has no scrim at all. `pressBehavior="none"` keeps it
|
|
33
|
+
* and makes it inert, for a sheet that must be answered.
|
|
79
34
|
*
|
|
80
35
|
* @example
|
|
81
36
|
* <BottomSheet.Overlay />
|
|
82
37
|
*
|
|
83
38
|
* @example
|
|
84
|
-
*
|
|
85
|
-
* <BottomSheet.Overlay isCloseOnPress={false} />
|
|
39
|
+
* <BottomSheet.Overlay pressBehavior="none" />
|
|
86
40
|
*/
|
|
87
41
|
export function BottomSheetOverlay({
|
|
88
|
-
accessibilityLabel = "Close",
|
|
89
|
-
animatedIndex,
|
|
90
|
-
animatedPosition,
|
|
91
42
|
appearsOnIndex = BOTTOM_SHEET_BACKDROP_INDICES.appearsOnIndex,
|
|
92
43
|
className,
|
|
93
44
|
disappearsOnIndex = BOTTOM_SHEET_BACKDROP_INDICES.disappearsOnIndex,
|
|
94
|
-
isCloseOnPress = true,
|
|
95
45
|
opacity = BOTTOM_SHEET_OVERLAY_OPACITY,
|
|
96
|
-
onPress,
|
|
97
46
|
...props
|
|
98
47
|
}: BottomSheetOverlayProps): ReactElement {
|
|
99
|
-
if (animatedIndex === undefined || animatedPosition === undefined) {
|
|
100
|
-
throw new Error(
|
|
101
|
-
"BottomSheet.Overlay must be written inside a <BottomSheet.Portal>, beside its <BottomSheet.Container>."
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
48
|
return (
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
opacity={opacity}
|
|
114
|
-
pressBehavior="none"
|
|
115
|
-
{...props}
|
|
116
|
-
/>
|
|
117
|
-
{isCloseOnPress ? (
|
|
118
|
-
<BottomSheetOverlayPressArea
|
|
119
|
-
accessibilityLabel={accessibilityLabel}
|
|
120
|
-
animatedPosition={animatedPosition}
|
|
121
|
-
onPress={onPress}
|
|
122
|
-
/>
|
|
123
|
-
) : null}
|
|
124
|
-
</>
|
|
49
|
+
<StyledOverlay
|
|
50
|
+
appearsOnIndex={appearsOnIndex}
|
|
51
|
+
className={bottomSheetVariants().overlay({ className })}
|
|
52
|
+
disappearsOnIndex={disappearsOnIndex}
|
|
53
|
+
opacity={opacity}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
125
56
|
);
|
|
126
57
|
}
|
|
127
58
|
BottomSheetOverlay.displayName = "DelacourUI.BottomSheet.Overlay";
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* The pressable band between the top of the screen and the top of the sheet.
|
|
131
|
-
*
|
|
132
|
-
* Its height is the sheet's own `animatedPosition`, so it grows and shrinks with
|
|
133
|
-
* the sheet on the UI thread and stops exactly where the sheet begins — which is
|
|
134
|
-
* the whole point. The `Pressable` is a child rather than the animated view
|
|
135
|
-
* itself because `Pressable` takes no `style`: its own `Animated.View` already
|
|
136
|
-
* owns one, and a second would fight it for prop ownership every frame.
|
|
137
|
-
*
|
|
138
|
-
* It reads gorhom's `useBottomSheet()` rather than this package's. The backdrop
|
|
139
|
-
* is rendered by gorhom's own container, OUTSIDE the children
|
|
140
|
-
* `BottomSheet.Container` re-publishes its context around, so the sheet's own
|
|
141
|
-
* handle is the one thing in scope here — and closing through it lands on
|
|
142
|
-
* `onDismiss`, which is where `onOpenChange` already is.
|
|
143
|
-
*/
|
|
144
|
-
function BottomSheetOverlayPressArea({
|
|
145
|
-
accessibilityLabel,
|
|
146
|
-
animatedPosition,
|
|
147
|
-
onPress,
|
|
148
|
-
}: {
|
|
149
|
-
accessibilityLabel: string;
|
|
150
|
-
animatedPosition: NonNullable<BottomSheetBackdropProps["animatedPosition"]>;
|
|
151
|
-
onPress?: () => void;
|
|
152
|
-
}): ReactElement {
|
|
153
|
-
const { close } = useGorhomBottomSheet();
|
|
154
|
-
|
|
155
|
-
const style = useAnimatedStyle(() => ({ height: Math.max(0, animatedPosition.value) }));
|
|
156
|
-
|
|
157
|
-
const handlePress = () => {
|
|
158
|
-
onPress?.();
|
|
159
|
-
close();
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
return (
|
|
163
|
-
<Animated.View style={[styles.pressArea, style]}>
|
|
164
|
-
<Pressable
|
|
165
|
-
accessibilityLabel={accessibilityLabel}
|
|
166
|
-
accessibilityRole="button"
|
|
167
|
-
className="flex-1"
|
|
168
|
-
feedback="none"
|
|
169
|
-
onPress={handlePress}
|
|
170
|
-
/>
|
|
171
|
-
</Animated.View>
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
BottomSheetOverlayPressArea.displayName = "DelacourUI.BottomSheet.Overlay.PressArea";
|
|
175
|
-
|
|
176
|
-
// A style rather than a class: the height beside it is an animated value, and the
|
|
177
|
-
// two have to arrive on the same node.
|
|
178
|
-
const styles = StyleSheet.create({
|
|
179
|
-
pressArea: { left: 0, position: "absolute", right: 0, top: 0 },
|
|
180
|
-
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BottomSheetProvider as HeadlessProvider,
|
|
3
|
+
type BottomSheetProviderProps as HeadlessProviderProps,
|
|
4
|
+
} from "@delacour/react-native-bottom-sheet";
|
|
5
|
+
import type { ReactElement } from "react";
|
|
6
|
+
import { TeleportProvidedContext, useIsTeleportProvided } from "../overlay/overlay.context";
|
|
7
|
+
|
|
8
|
+
export type BottomSheetProviderProps = Omit<HeadlessProviderProps, "hasPortalProvider">;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The engine's provider, mounted once by the app — and aware of
|
|
12
|
+
* `OverlayProvider`.
|
|
13
|
+
*
|
|
14
|
+
* Both providers need teleport's `PortalProvider`, and there must be exactly
|
|
15
|
+
* one: teleport registers hosts natively by name, so two would mean two hosts
|
|
16
|
+
* called `"root"`. Whichever of the two mounts outermost mounts it and says so
|
|
17
|
+
* through `TeleportProvidedContext`; the inner one skips its own. Sheets and
|
|
18
|
+
* overlays then share one `"root"` host, ordered by `zIndex` — every overlay's
|
|
19
|
+
* band starts above every sheet's.
|
|
20
|
+
*
|
|
21
|
+
* The overlay folder's context file is a leaf (rule 3): it imports nothing but
|
|
22
|
+
* React, so this cross-folder import cannot close a cycle.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* <DelacourProvider>
|
|
26
|
+
* <OverlayProvider>
|
|
27
|
+
* <BottomSheetProvider>
|
|
28
|
+
* <Stack />
|
|
29
|
+
* </BottomSheetProvider>
|
|
30
|
+
* </OverlayProvider>
|
|
31
|
+
* </DelacourProvider>
|
|
32
|
+
*/
|
|
33
|
+
export function BottomSheetProvider({ children }: BottomSheetProviderProps): ReactElement {
|
|
34
|
+
const isTeleportProvided = useIsTeleportProvided();
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<HeadlessProvider hasPortalProvider={isTeleportProvided}>
|
|
38
|
+
<TeleportProvidedContext.Provider value>{children}</TeleportProvidedContext.Provider>
|
|
39
|
+
</HeadlessProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
BottomSheetProvider.displayName = "DelacourUI.BottomSheet.Provider";
|