orn-ui 0.2.10 → 0.3.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/AGENTS.md +66 -51
- package/README.md +3 -7
- package/lib/commonjs/atoms/Avatar.js +77 -5
- package/lib/commonjs/atoms/Avatar.js.map +1 -1
- package/lib/commonjs/atoms/Badge.js +17 -8
- package/lib/commonjs/atoms/Badge.js.map +1 -1
- package/lib/commonjs/atoms/Button.js +108 -39
- package/lib/commonjs/atoms/Button.js.map +1 -1
- package/lib/commonjs/atoms/Card.js +24 -2
- package/lib/commonjs/atoms/Card.js.map +1 -1
- package/lib/commonjs/atoms/Checkbox.js +41 -10
- package/lib/commonjs/atoms/Checkbox.js.map +1 -1
- package/lib/commonjs/atoms/Divider.js +30 -5
- package/lib/commonjs/atoms/Divider.js.map +1 -1
- package/lib/commonjs/atoms/EmptyState.js +58 -20
- package/lib/commonjs/atoms/EmptyState.js.map +1 -1
- package/lib/commonjs/atoms/Fab.js +32 -12
- package/lib/commonjs/atoms/Fab.js.map +1 -1
- package/lib/commonjs/atoms/Gradient.js +102 -36
- package/lib/commonjs/atoms/Gradient.js.map +1 -1
- package/lib/commonjs/atoms/IconButton.js +25 -4
- package/lib/commonjs/atoms/IconButton.js.map +1 -1
- package/lib/commonjs/atoms/Image.js +61 -25
- package/lib/commonjs/atoms/Image.js.map +1 -1
- package/lib/commonjs/atoms/Input.js +105 -17
- package/lib/commonjs/atoms/Input.js.map +1 -1
- package/lib/commonjs/atoms/KeyValueRow.js +37 -9
- package/lib/commonjs/atoms/KeyValueRow.js.map +1 -1
- package/lib/commonjs/atoms/PressableScale.js +25 -5
- package/lib/commonjs/atoms/PressableScale.js.map +1 -1
- package/lib/commonjs/atoms/ShinyText.js +29 -29
- package/lib/commonjs/atoms/Skeleton.js +28 -13
- package/lib/commonjs/atoms/Skeleton.js.map +1 -1
- package/lib/commonjs/atoms/Spinner.js +81 -22
- package/lib/commonjs/atoms/Spinner.js.map +1 -1
- package/lib/commonjs/atoms/Text.js +56 -5
- package/lib/commonjs/atoms/Text.js.map +1 -1
- package/lib/commonjs/atoms/Transition.js +46 -43
- package/lib/commonjs/atoms/Transition.js.map +1 -1
- package/lib/commonjs/atoms/index.js +6 -0
- package/lib/commonjs/atoms/index.js.map +1 -1
- package/lib/commonjs/atoms/inputValidation.js +56 -0
- package/lib/commonjs/atoms/inputValidation.js.map +1 -0
- package/lib/commonjs/icons/Icon.js +4 -4
- package/lib/commonjs/icons/defaultIcons.js +576 -24
- package/lib/commonjs/icons/defaultIcons.js.map +1 -1
- package/lib/commonjs/icons/index.js +6 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/molecules/AvatarHeader.js +47 -14
- package/lib/commonjs/molecules/AvatarHeader.js.map +1 -1
- package/lib/commonjs/molecules/FormActions.js +25 -9
- package/lib/commonjs/molecules/FormActions.js.map +1 -1
- package/lib/commonjs/molecules/InfoRow.js +30 -14
- package/lib/commonjs/molecules/InfoRow.js.map +1 -1
- package/lib/commonjs/molecules/OptionCard.js +37 -22
- package/lib/commonjs/molecules/OptionCard.js.map +1 -1
- package/lib/commonjs/molecules/SegmentedControl.js +103 -14
- package/lib/commonjs/molecules/SegmentedControl.js.map +1 -1
- package/lib/commonjs/molecules/Stepper.js +61 -16
- package/lib/commonjs/molecules/Stepper.js.map +1 -1
- package/lib/commonjs/molecules/Steps.js +105 -41
- package/lib/commonjs/molecules/Steps.js.map +1 -1
- package/lib/commonjs/molecules/SymmetricGrid.js +26 -18
- package/lib/commonjs/molecules/SymmetricGrid.js.map +1 -1
- package/lib/commonjs/organisms/Alert.js +49 -35
- package/lib/commonjs/organisms/Alert.js.map +1 -1
- package/lib/commonjs/organisms/AlertProvider.js +10 -10
- package/lib/commonjs/organisms/BottomSheet.js +137 -85
- package/lib/commonjs/organisms/BottomSheet.js.map +1 -1
- package/lib/commonjs/organisms/Chart.js +174 -154
- package/lib/commonjs/organisms/Chart.js.map +1 -1
- package/lib/commonjs/organisms/DateField.js +36 -20
- package/lib/commonjs/organisms/DateField.js.map +1 -1
- package/lib/commonjs/organisms/DatePicker.js +56 -33
- package/lib/commonjs/organisms/DatePicker.js.map +1 -1
- package/lib/commonjs/organisms/List.js +62 -34
- package/lib/commonjs/organisms/List.js.map +1 -1
- package/lib/commonjs/organisms/Modal.js +120 -82
- package/lib/commonjs/organisms/Modal.js.map +1 -1
- package/lib/commonjs/organisms/NavigationBar.js +63 -24
- package/lib/commonjs/organisms/NavigationBar.js.map +1 -1
- package/lib/commonjs/organisms/OptionWheel.js +64 -64
- package/lib/commonjs/organisms/OptionWheel.js.map +1 -1
- package/lib/commonjs/organisms/ReorderableList.js +48 -27
- package/lib/commonjs/organisms/ReorderableList.js.map +1 -1
- package/lib/commonjs/organisms/Screen.js +68 -35
- package/lib/commonjs/organisms/Screen.js.map +1 -1
- package/lib/commonjs/organisms/SearchList.js +56 -26
- package/lib/commonjs/organisms/SearchList.js.map +1 -1
- package/lib/commonjs/organisms/Select.js +45 -24
- package/lib/commonjs/organisms/Select.js.map +1 -1
- package/lib/commonjs/organisms/Slides.js +36 -23
- package/lib/commonjs/organisms/Slides.js.map +1 -1
- package/lib/commonjs/organisms/ThemeToggle.js +10 -9
- package/lib/commonjs/organisms/ThemeToggle.js.map +1 -1
- package/lib/commonjs/organisms/Timeline.js +73 -56
- package/lib/commonjs/organisms/Timeline.js.map +1 -1
- package/lib/commonjs/organisms/Toast.js +46 -15
- package/lib/commonjs/organisms/Toast.js.map +1 -1
- package/lib/commonjs/organisms/ToastProvider.js +14 -10
- package/lib/commonjs/organisms/ToastProvider.js.map +1 -1
- package/lib/commonjs/organisms/Wizard.js +40 -15
- package/lib/commonjs/organisms/Wizard.js.map +1 -1
- package/lib/commonjs/organisms/chart/frame.js +25 -25
- package/lib/commonjs/organisms/chart/frame.js.map +1 -1
- package/lib/commonjs/organisms/chart/marks.js +42 -42
- package/lib/commonjs/organisms/chart/math.js +84 -85
- package/lib/commonjs/organisms/chart/math.js.map +1 -1
- package/lib/commonjs/organisms/chart/palette.js +28 -28
- package/lib/commonjs/organisms/imperativeBridge.js +5 -5
- package/lib/commonjs/organisms/imperativeBridge.js.map +1 -1
- package/lib/commonjs/organisms/useSlides.js +53 -21
- package/lib/commonjs/organisms/useSlides.js.map +1 -1
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js +9 -66
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js.map +1 -1
- package/lib/commonjs/safe-area/index.js.map +1 -1
- package/lib/commonjs/theme/KeyboardAvoidance.js +206 -0
- package/lib/commonjs/theme/KeyboardAvoidance.js.map +1 -0
- package/lib/commonjs/theme/NativeOverlay.js +263 -0
- package/lib/commonjs/theme/NativeOverlay.js.map +1 -0
- package/lib/commonjs/theme/UIProvider.js +86 -33
- package/lib/commonjs/theme/UIProvider.js.map +1 -1
- package/lib/commonjs/theme/colors.js +17 -17
- package/lib/commonjs/theme/colors.js.map +1 -1
- package/lib/commonjs/theme/createStyles.js +19 -16
- package/lib/commonjs/theme/createStyles.js.map +1 -1
- package/lib/commonjs/theme/createTheme.js +6 -6
- package/lib/commonjs/theme/index.js +6 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/commonjs/theme/insets.js +1 -1
- package/lib/commonjs/theme/labels.js +29 -1
- package/lib/commonjs/theme/labels.js.map +1 -1
- package/lib/commonjs/theme/palettes.js +25 -23
- package/lib/commonjs/theme/palettes.js.map +1 -1
- package/lib/commonjs/theme/tokens.js +28 -14
- package/lib/commonjs/theme/tokens.js.map +1 -1
- package/lib/commonjs/theme/useKeyboardField.js +36 -0
- package/lib/commonjs/theme/useKeyboardField.js.map +1 -0
- package/lib/commonjs/theme/useReduceMotion.js +31 -0
- package/lib/commonjs/theme/useReduceMotion.js.map +1 -0
- package/lib/module/atoms/Avatar.js +79 -8
- package/lib/module/atoms/Avatar.js.map +1 -1
- package/lib/module/atoms/Badge.js +17 -8
- package/lib/module/atoms/Badge.js.map +1 -1
- package/lib/module/atoms/Button.js +110 -41
- package/lib/module/atoms/Button.js.map +1 -1
- package/lib/module/atoms/Card.js +24 -2
- package/lib/module/atoms/Card.js.map +1 -1
- package/lib/module/atoms/Checkbox.js +42 -11
- package/lib/module/atoms/Checkbox.js.map +1 -1
- package/lib/module/atoms/Divider.js +31 -6
- package/lib/module/atoms/Divider.js.map +1 -1
- package/lib/module/atoms/EmptyState.js +58 -20
- package/lib/module/atoms/EmptyState.js.map +1 -1
- package/lib/module/atoms/Fab.js +33 -13
- package/lib/module/atoms/Fab.js.map +1 -1
- package/lib/module/atoms/Gradient.js +103 -37
- package/lib/module/atoms/Gradient.js.map +1 -1
- package/lib/module/atoms/IconButton.js +25 -4
- package/lib/module/atoms/IconButton.js.map +1 -1
- package/lib/module/atoms/Image.js +61 -25
- package/lib/module/atoms/Image.js.map +1 -1
- package/lib/module/atoms/Input.js +108 -20
- package/lib/module/atoms/Input.js.map +1 -1
- package/lib/module/atoms/KeyValueRow.js +37 -9
- package/lib/module/atoms/KeyValueRow.js.map +1 -1
- package/lib/module/atoms/PressableScale.js +25 -5
- package/lib/module/atoms/PressableScale.js.map +1 -1
- package/lib/module/atoms/ShinyText.js +29 -29
- package/lib/module/atoms/Skeleton.js +30 -13
- package/lib/module/atoms/Skeleton.js.map +1 -1
- package/lib/module/atoms/Spinner.js +82 -23
- package/lib/module/atoms/Spinner.js.map +1 -1
- package/lib/module/atoms/Text.js +56 -5
- package/lib/module/atoms/Text.js.map +1 -1
- package/lib/module/atoms/Transition.js +41 -42
- package/lib/module/atoms/Transition.js.map +1 -1
- package/lib/module/atoms/index.js +1 -1
- package/lib/module/atoms/index.js.map +1 -1
- package/lib/module/atoms/inputValidation.js +52 -0
- package/lib/module/atoms/inputValidation.js.map +1 -0
- package/lib/module/icons/Icon.js +4 -4
- package/lib/module/icons/defaultIcons.js +574 -24
- package/lib/module/icons/defaultIcons.js.map +1 -1
- package/lib/module/icons/index.js +1 -1
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/molecules/AvatarHeader.js +47 -14
- package/lib/module/molecules/AvatarHeader.js.map +1 -1
- package/lib/module/molecules/FormActions.js +25 -9
- package/lib/module/molecules/FormActions.js.map +1 -1
- package/lib/module/molecules/InfoRow.js +30 -14
- package/lib/module/molecules/InfoRow.js.map +1 -1
- package/lib/module/molecules/OptionCard.js +37 -22
- package/lib/module/molecules/OptionCard.js.map +1 -1
- package/lib/module/molecules/SegmentedControl.js +107 -18
- package/lib/module/molecules/SegmentedControl.js.map +1 -1
- package/lib/module/molecules/Stepper.js +63 -18
- package/lib/module/molecules/Stepper.js.map +1 -1
- package/lib/module/molecules/Steps.js +107 -43
- package/lib/module/molecules/Steps.js.map +1 -1
- package/lib/module/molecules/SymmetricGrid.js +26 -18
- package/lib/module/molecules/SymmetricGrid.js.map +1 -1
- package/lib/module/organisms/Alert.js +51 -37
- package/lib/module/organisms/Alert.js.map +1 -1
- package/lib/module/organisms/AlertProvider.js +10 -10
- package/lib/module/organisms/BottomSheet.js +142 -88
- package/lib/module/organisms/BottomSheet.js.map +1 -1
- package/lib/module/organisms/Chart.js +176 -156
- package/lib/module/organisms/Chart.js.map +1 -1
- package/lib/module/organisms/DateField.js +36 -20
- package/lib/module/organisms/DateField.js.map +1 -1
- package/lib/module/organisms/DatePicker.js +56 -33
- package/lib/module/organisms/DatePicker.js.map +1 -1
- package/lib/module/organisms/List.js +62 -34
- package/lib/module/organisms/List.js.map +1 -1
- package/lib/module/organisms/Modal.js +122 -84
- package/lib/module/organisms/Modal.js.map +1 -1
- package/lib/module/organisms/NavigationBar.js +64 -25
- package/lib/module/organisms/NavigationBar.js.map +1 -1
- package/lib/module/organisms/OptionWheel.js +64 -64
- package/lib/module/organisms/OptionWheel.js.map +1 -1
- package/lib/module/organisms/ReorderableList.js +48 -27
- package/lib/module/organisms/ReorderableList.js.map +1 -1
- package/lib/module/organisms/Screen.js +70 -37
- package/lib/module/organisms/Screen.js.map +1 -1
- package/lib/module/organisms/SearchList.js +56 -26
- package/lib/module/organisms/SearchList.js.map +1 -1
- package/lib/module/organisms/Select.js +46 -25
- package/lib/module/organisms/Select.js.map +1 -1
- package/lib/module/organisms/Slides.js +37 -24
- package/lib/module/organisms/Slides.js.map +1 -1
- package/lib/module/organisms/ThemeToggle.js +11 -10
- package/lib/module/organisms/ThemeToggle.js.map +1 -1
- package/lib/module/organisms/Timeline.js +73 -56
- package/lib/module/organisms/Timeline.js.map +1 -1
- package/lib/module/organisms/Toast.js +47 -16
- package/lib/module/organisms/Toast.js.map +1 -1
- package/lib/module/organisms/ToastProvider.js +15 -11
- package/lib/module/organisms/ToastProvider.js.map +1 -1
- package/lib/module/organisms/Wizard.js +41 -16
- package/lib/module/organisms/Wizard.js.map +1 -1
- package/lib/module/organisms/chart/frame.js +25 -25
- package/lib/module/organisms/chart/frame.js.map +1 -1
- package/lib/module/organisms/chart/marks.js +42 -42
- package/lib/module/organisms/chart/math.js +84 -85
- package/lib/module/organisms/chart/math.js.map +1 -1
- package/lib/module/organisms/chart/palette.js +28 -28
- package/lib/module/organisms/imperativeBridge.js +5 -5
- package/lib/module/organisms/imperativeBridge.js.map +1 -1
- package/lib/module/organisms/useSlides.js +53 -21
- package/lib/module/organisms/useSlides.js.map +1 -1
- package/lib/module/safe-area/SafeAreaUIProvider.js +10 -65
- package/lib/module/safe-area/SafeAreaUIProvider.js.map +1 -1
- package/lib/module/safe-area/index.js +1 -0
- package/lib/module/safe-area/index.js.map +1 -1
- package/lib/module/theme/KeyboardAvoidance.js +198 -0
- package/lib/module/theme/KeyboardAvoidance.js.map +1 -0
- package/lib/module/theme/NativeOverlay.js +257 -0
- package/lib/module/theme/NativeOverlay.js.map +1 -0
- package/lib/module/theme/UIProvider.js +88 -35
- package/lib/module/theme/UIProvider.js.map +1 -1
- package/lib/module/theme/colors.js +17 -17
- package/lib/module/theme/colors.js.map +1 -1
- package/lib/module/theme/createStyles.js +20 -16
- package/lib/module/theme/createStyles.js.map +1 -1
- package/lib/module/theme/createTheme.js +6 -6
- package/lib/module/theme/index.js +1 -1
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/insets.js +1 -1
- package/lib/module/theme/labels.js +29 -1
- package/lib/module/theme/labels.js.map +1 -1
- package/lib/module/theme/palettes.js +25 -23
- package/lib/module/theme/palettes.js.map +1 -1
- package/lib/module/theme/tokens.js +27 -13
- package/lib/module/theme/tokens.js.map +1 -1
- package/lib/module/theme/useKeyboardField.js +33 -0
- package/lib/module/theme/useKeyboardField.js.map +1 -0
- package/lib/module/theme/useReduceMotion.js +28 -0
- package/lib/module/theme/useReduceMotion.js.map +1 -0
- package/lib/typescript/atoms/Avatar.d.ts +35 -5
- package/lib/typescript/atoms/Avatar.d.ts.map +1 -1
- package/lib/typescript/atoms/Badge.d.ts +14 -3
- package/lib/typescript/atoms/Badge.d.ts.map +1 -1
- package/lib/typescript/atoms/Button.d.ts +34 -3
- package/lib/typescript/atoms/Button.d.ts.map +1 -1
- package/lib/typescript/atoms/Card.d.ts +13 -2
- package/lib/typescript/atoms/Card.d.ts.map +1 -1
- package/lib/typescript/atoms/Checkbox.d.ts +26 -1
- package/lib/typescript/atoms/Checkbox.d.ts.map +1 -1
- package/lib/typescript/atoms/Divider.d.ts +18 -1
- package/lib/typescript/atoms/Divider.d.ts.map +1 -1
- package/lib/typescript/atoms/EmptyState.d.ts +30 -3
- package/lib/typescript/atoms/EmptyState.d.ts.map +1 -1
- package/lib/typescript/atoms/Fab.d.ts +24 -4
- package/lib/typescript/atoms/Fab.d.ts.map +1 -1
- package/lib/typescript/atoms/Gradient.d.ts +21 -15
- package/lib/typescript/atoms/Gradient.d.ts.map +1 -1
- package/lib/typescript/atoms/IconButton.d.ts +18 -4
- package/lib/typescript/atoms/IconButton.d.ts.map +1 -1
- package/lib/typescript/atoms/Image.d.ts +39 -17
- package/lib/typescript/atoms/Image.d.ts.map +1 -1
- package/lib/typescript/atoms/Input.d.ts +57 -7
- package/lib/typescript/atoms/Input.d.ts.map +1 -1
- package/lib/typescript/atoms/KeyValueRow.d.ts +16 -4
- package/lib/typescript/atoms/KeyValueRow.d.ts.map +1 -1
- package/lib/typescript/atoms/PressableScale.d.ts +12 -5
- package/lib/typescript/atoms/PressableScale.d.ts.map +1 -1
- package/lib/typescript/atoms/ShinyText.d.ts +17 -17
- package/lib/typescript/atoms/ShinyText.d.ts.map +1 -1
- package/lib/typescript/atoms/Skeleton.d.ts +12 -7
- package/lib/typescript/atoms/Skeleton.d.ts.map +1 -1
- package/lib/typescript/atoms/Spinner.d.ts +29 -1
- package/lib/typescript/atoms/Spinner.d.ts.map +1 -1
- package/lib/typescript/atoms/Text.d.ts +46 -0
- package/lib/typescript/atoms/Text.d.ts.map +1 -1
- package/lib/typescript/atoms/Transition.d.ts +19 -15
- package/lib/typescript/atoms/Transition.d.ts.map +1 -1
- package/lib/typescript/atoms/index.d.ts +3 -3
- package/lib/typescript/atoms/index.d.ts.map +1 -1
- package/lib/typescript/atoms/inputValidation.d.ts +29 -0
- package/lib/typescript/atoms/inputValidation.d.ts.map +1 -0
- package/lib/typescript/icons/Icon.d.ts +4 -4
- package/lib/typescript/icons/defaultIcons.d.ts +19 -2
- package/lib/typescript/icons/defaultIcons.d.ts.map +1 -1
- package/lib/typescript/icons/index.d.ts +2 -2
- package/lib/typescript/icons/index.d.ts.map +1 -1
- package/lib/typescript/icons/types.d.ts +13 -3
- package/lib/typescript/icons/types.d.ts.map +1 -1
- package/lib/typescript/molecules/AvatarHeader.d.ts +23 -4
- package/lib/typescript/molecules/AvatarHeader.d.ts.map +1 -1
- package/lib/typescript/molecules/FormActions.d.ts +21 -4
- package/lib/typescript/molecules/FormActions.d.ts.map +1 -1
- package/lib/typescript/molecules/InfoRow.d.ts +17 -3
- package/lib/typescript/molecules/InfoRow.d.ts.map +1 -1
- package/lib/typescript/molecules/OptionCard.d.ts +20 -5
- package/lib/typescript/molecules/OptionCard.d.ts.map +1 -1
- package/lib/typescript/molecules/SegmentedControl.d.ts +18 -2
- package/lib/typescript/molecules/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/molecules/Stepper.d.ts +23 -7
- package/lib/typescript/molecules/Stepper.d.ts.map +1 -1
- package/lib/typescript/molecules/Steps.d.ts +18 -4
- package/lib/typescript/molecules/Steps.d.ts.map +1 -1
- package/lib/typescript/molecules/SymmetricGrid.d.ts +15 -5
- package/lib/typescript/molecules/SymmetricGrid.d.ts.map +1 -1
- package/lib/typescript/organisms/Alert.d.ts +28 -2
- package/lib/typescript/organisms/Alert.d.ts.map +1 -1
- package/lib/typescript/organisms/AlertProvider.d.ts +10 -10
- package/lib/typescript/organisms/AlertProvider.d.ts.map +1 -1
- package/lib/typescript/organisms/BottomSheet.d.ts +20 -5
- package/lib/typescript/organisms/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/organisms/Chart.d.ts +86 -75
- package/lib/typescript/organisms/Chart.d.ts.map +1 -1
- package/lib/typescript/organisms/DateField.d.ts +17 -3
- package/lib/typescript/organisms/DateField.d.ts.map +1 -1
- package/lib/typescript/organisms/DatePicker.d.ts +7 -11
- package/lib/typescript/organisms/DatePicker.d.ts.map +1 -1
- package/lib/typescript/organisms/List.d.ts +30 -3
- package/lib/typescript/organisms/List.d.ts.map +1 -1
- package/lib/typescript/organisms/Modal.d.ts +30 -3
- package/lib/typescript/organisms/Modal.d.ts.map +1 -1
- package/lib/typescript/organisms/NavigationBar.d.ts +26 -7
- package/lib/typescript/organisms/NavigationBar.d.ts.map +1 -1
- package/lib/typescript/organisms/OptionWheel.d.ts +20 -16
- package/lib/typescript/organisms/OptionWheel.d.ts.map +1 -1
- package/lib/typescript/organisms/ReorderableList.d.ts +20 -11
- package/lib/typescript/organisms/ReorderableList.d.ts.map +1 -1
- package/lib/typescript/organisms/Screen.d.ts +27 -8
- package/lib/typescript/organisms/Screen.d.ts.map +1 -1
- package/lib/typescript/organisms/SearchList.d.ts +46 -3
- package/lib/typescript/organisms/SearchList.d.ts.map +1 -1
- package/lib/typescript/organisms/Select.d.ts +26 -6
- package/lib/typescript/organisms/Select.d.ts.map +1 -1
- package/lib/typescript/organisms/Slides.d.ts +44 -26
- package/lib/typescript/organisms/Slides.d.ts.map +1 -1
- package/lib/typescript/organisms/ThemeToggle.d.ts +6 -2
- package/lib/typescript/organisms/ThemeToggle.d.ts.map +1 -1
- package/lib/typescript/organisms/Timeline.d.ts +26 -9
- package/lib/typescript/organisms/Timeline.d.ts.map +1 -1
- package/lib/typescript/organisms/Toast.d.ts +19 -4
- package/lib/typescript/organisms/Toast.d.ts.map +1 -1
- package/lib/typescript/organisms/ToastProvider.d.ts +8 -8
- package/lib/typescript/organisms/ToastProvider.d.ts.map +1 -1
- package/lib/typescript/organisms/Wizard.d.ts +24 -6
- package/lib/typescript/organisms/Wizard.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/frame.d.ts +21 -21
- package/lib/typescript/organisms/chart/frame.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/marks.d.ts +28 -28
- package/lib/typescript/organisms/chart/marks.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/math.d.ts +69 -70
- package/lib/typescript/organisms/chart/math.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/palette.d.ts +2 -2
- package/lib/typescript/organisms/chart/palette.d.ts.map +1 -1
- package/lib/typescript/organisms/imperativeBridge.d.ts +4 -4
- package/lib/typescript/organisms/useSlides.d.ts +8 -16
- package/lib/typescript/organisms/useSlides.d.ts.map +1 -1
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts +9 -7
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts.map +1 -1
- package/lib/typescript/safe-area/index.d.ts.map +1 -1
- package/lib/typescript/theme/KeyboardAvoidance.d.ts +62 -0
- package/lib/typescript/theme/KeyboardAvoidance.d.ts.map +1 -0
- package/lib/typescript/theme/NativeOverlay.d.ts +43 -0
- package/lib/typescript/theme/NativeOverlay.d.ts.map +1 -0
- package/lib/typescript/theme/UIProvider.d.ts +38 -20
- package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
- package/lib/typescript/theme/colors.d.ts +13 -13
- package/lib/typescript/theme/colors.d.ts.map +1 -1
- package/lib/typescript/theme/createStyles.d.ts +20 -14
- package/lib/typescript/theme/createStyles.d.ts.map +1 -1
- package/lib/typescript/theme/createTheme.d.ts +5 -5
- package/lib/typescript/theme/index.d.ts +1 -1
- package/lib/typescript/theme/index.d.ts.map +1 -1
- package/lib/typescript/theme/insets.d.ts +1 -1
- package/lib/typescript/theme/insets.d.ts.map +1 -1
- package/lib/typescript/theme/labels.d.ts +57 -2
- package/lib/typescript/theme/labels.d.ts.map +1 -1
- package/lib/typescript/theme/palettes.d.ts +25 -19
- package/lib/typescript/theme/palettes.d.ts.map +1 -1
- package/lib/typescript/theme/tokens.d.ts +15 -8
- package/lib/typescript/theme/tokens.d.ts.map +1 -1
- package/lib/typescript/theme/types.d.ts +7 -7
- package/lib/typescript/theme/types.d.ts.map +1 -1
- package/lib/typescript/theme/useKeyboardField.d.ts +17 -0
- package/lib/typescript/theme/useKeyboardField.d.ts.map +1 -0
- package/lib/typescript/theme/useReduceMotion.d.ts +7 -0
- package/lib/typescript/theme/useReduceMotion.d.ts.map +1 -0
- package/llms.txt +4 -4
- package/package.json +15 -14
- package/registry/alert-provider.json +4 -3
- package/registry/alert.json +3 -2
- package/registry/avatar-header.json +1 -1
- package/registry/avatar.json +3 -2
- package/registry/badge.json +1 -1
- package/registry/bottom-sheet.json +1 -1
- package/registry/button.json +3 -2
- package/registry/card.json +1 -1
- package/registry/chart.json +5 -5
- package/registry/checkbox.json +3 -2
- package/registry/core.json +31 -15
- package/registry/date-field.json +1 -1
- package/registry/date-picker.json +3 -2
- package/registry/divider.json +1 -1
- package/registry/empty-state.json +4 -2
- package/registry/fab.json +3 -2
- package/registry/form-actions.json +3 -2
- package/registry/gradient.json +1 -1
- package/registry/icon-button.json +3 -2
- package/registry/image.json +1 -1
- package/registry/index.json +79 -61
- package/registry/info-row.json +1 -1
- package/registry/input.json +5 -1
- package/registry/key-value-row.json +1 -1
- package/registry/list.json +3 -1
- package/registry/manifest.json +3 -1
- package/registry/modal.json +1 -1
- package/registry/navigation-bar.json +1 -1
- package/registry/option-card.json +3 -2
- package/registry/option-wheel.json +1 -1
- package/registry/pressable-scale.json +3 -2
- package/registry/reorderable-list.json +1 -1
- package/registry/screen.json +1 -1
- package/registry/search-list.json +7 -1
- package/registry/segmented-control.json +1 -1
- package/registry/select.json +1 -1
- package/registry/shiny-text.json +1 -1
- package/registry/skeleton.json +3 -2
- package/registry/slides.json +2 -2
- package/registry/spinner.json +1 -1
- package/registry/stepper.json +1 -1
- package/registry/steps.json +1 -1
- package/registry/symmetric-grid.json +1 -1
- package/registry/theme-toggle.json +1 -1
- package/registry/timeline.json +1 -1
- package/registry/title.json +1 -1
- package/registry/toast-provider.json +2 -2
- package/registry/toast.json +1 -1
- package/registry/transition.json +1 -1
- package/registry/wizard.json +1 -1
- package/src/atoms/Avatar.tsx +117 -26
- package/src/atoms/Badge.tsx +20 -9
- package/src/atoms/Button.tsx +102 -30
- package/src/atoms/Card.tsx +23 -3
- package/src/atoms/Checkbox.tsx +49 -12
- package/src/atoms/Divider.tsx +34 -4
- package/src/atoms/EmptyState.tsx +63 -16
- package/src/atoms/Fab.tsx +56 -9
- package/src/atoms/Gradient.tsx +92 -41
- package/src/atoms/IconButton.tsx +27 -4
- package/src/atoms/Image.tsx +74 -28
- package/src/atoms/Input.tsx +129 -19
- package/src/atoms/KeyValueRow.tsx +72 -28
- package/src/atoms/PressableScale.tsx +31 -7
- package/src/atoms/ShinyText.tsx +31 -31
- package/src/atoms/Skeleton.tsx +37 -17
- package/src/atoms/Spinner.tsx +87 -24
- package/src/atoms/Text.tsx +66 -6
- package/src/atoms/Transition.tsx +40 -44
- package/src/atoms/index.ts +3 -3
- package/src/atoms/inputValidation.ts +59 -0
- package/src/icons/Icon.tsx +4 -4
- package/src/icons/defaultIcons.tsx +445 -22
- package/src/icons/index.ts +2 -2
- package/src/icons/types.ts +26 -4
- package/src/molecules/AvatarHeader.tsx +88 -34
- package/src/molecules/FormActions.tsx +36 -6
- package/src/molecules/InfoRow.tsx +39 -12
- package/src/molecules/OptionCard.tsx +55 -20
- package/src/molecules/SegmentedControl.tsx +135 -15
- package/src/molecules/Stepper.tsx +73 -19
- package/src/molecules/Steps.tsx +121 -39
- package/src/molecules/SymmetricGrid.tsx +28 -12
- package/src/organisms/Alert.tsx +97 -26
- package/src/organisms/AlertProvider.tsx +13 -13
- package/src/organisms/BottomSheet.tsx +115 -43
- package/src/organisms/Chart.tsx +193 -164
- package/src/organisms/DateField.tsx +40 -15
- package/src/organisms/DatePicker.tsx +53 -32
- package/src/organisms/List.tsx +64 -15
- package/src/organisms/Modal.tsx +122 -63
- package/src/organisms/NavigationBar.tsx +73 -23
- package/src/organisms/OptionWheel.tsx +70 -66
- package/src/organisms/ReorderableList.tsx +49 -27
- package/src/organisms/Screen.tsx +79 -42
- package/src/organisms/SearchList.tsx +84 -20
- package/src/organisms/Select.tsx +63 -29
- package/src/organisms/Slides.tsx +63 -44
- package/src/organisms/ThemeToggle.tsx +15 -6
- package/src/organisms/Timeline.tsx +79 -62
- package/src/organisms/Toast.tsx +50 -15
- package/src/organisms/ToastProvider.tsx +17 -13
- package/src/organisms/Wizard.tsx +58 -21
- package/src/organisms/chart/frame.tsx +35 -35
- package/src/organisms/chart/marks.tsx +53 -53
- package/src/organisms/chart/math.ts +93 -94
- package/src/organisms/chart/palette.ts +28 -28
- package/src/organisms/imperativeBridge.ts +5 -5
- package/src/organisms/useSlides.ts +66 -31
- package/src/safe-area/SafeAreaUIProvider.tsx +9 -70
- package/src/safe-area/index.ts +1 -0
- package/src/theme/KeyboardAvoidance.tsx +216 -0
- package/src/theme/NativeOverlay.tsx +269 -0
- package/src/theme/UIProvider.tsx +109 -46
- package/src/theme/colors.ts +21 -21
- package/src/theme/createStyles.ts +23 -19
- package/src/theme/createTheme.ts +6 -6
- package/src/theme/index.ts +1 -1
- package/src/theme/insets.ts +1 -1
- package/src/theme/labels.ts +85 -2
- package/src/theme/palettes.ts +33 -25
- package/src/theme/tokens.ts +27 -13
- package/src/theme/types.ts +7 -7
- package/src/theme/useKeyboardField.ts +33 -0
- package/src/theme/useReduceMotion.ts +27 -0
package/src/organisms/Alert.tsx
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Text, TouchableWithoutFeedback, View } from 'react-native';
|
|
3
|
+
import { NativeOverlay } from '../theme/NativeOverlay';
|
|
3
4
|
import { createStyles } from '../theme/createStyles';
|
|
4
|
-
import { useAllowFontScaling, useColors, useLabels } from '../theme/UIProvider';
|
|
5
|
+
import { useAllowFontScaling, useColors, useLabels, useTheme } from '../theme/UIProvider';
|
|
5
6
|
import { Button, type ButtonVariant } from '../atoms/Button';
|
|
6
7
|
import { Icon } from '../icons/Icon';
|
|
7
8
|
import type { IconName } from '../icons/types';
|
|
@@ -9,23 +10,40 @@ import type { IconName } from '../icons/types';
|
|
|
9
10
|
export type AlertType = 'success' | 'error' | 'warning' | 'info' | 'question';
|
|
10
11
|
|
|
11
12
|
export interface AlertButton {
|
|
13
|
+
/** Button label. */
|
|
12
14
|
text: string;
|
|
15
|
+
/** Called on press; without it the button calls `onClose`. */
|
|
13
16
|
onPress?: () => void;
|
|
17
|
+
/** 'cancel' renders outline, 'destructive' renders in the error color. */
|
|
14
18
|
style?: 'cancel' | 'default' | 'destructive';
|
|
19
|
+
/** Explicit Button variant; wins over `style`. */
|
|
15
20
|
variant?: ButtonVariant;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
export interface AlertProps {
|
|
24
|
+
/** Shows or hides the dialog. */
|
|
19
25
|
visible: boolean;
|
|
26
|
+
/** Short heading; screen readers announce it as a header. */
|
|
20
27
|
title: string;
|
|
28
|
+
/** Optional explanation under the title. */
|
|
21
29
|
message?: string;
|
|
30
|
+
/** Icon and color of the dialog. @default 'info' */
|
|
22
31
|
type?: AlertType;
|
|
32
|
+
/** Tap on the backdrop, Android back, VoiceOver escape. Without it the backdrop does nothing. */
|
|
23
33
|
onClose?: () => void;
|
|
34
|
+
/** Custom buttons; three or more stack vertically. */
|
|
24
35
|
buttons?: AlertButton[];
|
|
36
|
+
/** Shorthand: label of the confirm button. @default labels.confirm */
|
|
25
37
|
confirmText?: string;
|
|
38
|
+
/** Shorthand: label of the cancel button (shown with `onCancel` or `cancelText`). @default labels.cancel */
|
|
26
39
|
cancelText?: string;
|
|
40
|
+
/** Shorthand: confirm action. */
|
|
27
41
|
onConfirm?: () => void;
|
|
42
|
+
/** Shorthand: cancel action (falls back to `onClose`). */
|
|
28
43
|
onCancel?: () => void;
|
|
44
|
+
/** The confirm button uses the destructive color (delete, discard). @default false */
|
|
45
|
+
destructive?: boolean;
|
|
46
|
+
/** Draws the dialog inside its parent instead of over the screen (docs, previews). @default false */
|
|
29
47
|
inline?: boolean;
|
|
30
48
|
}
|
|
31
49
|
|
|
@@ -37,31 +55,62 @@ const ICON_BY_TYPE: Record<AlertType, IconName> = {
|
|
|
37
55
|
info: 'info',
|
|
38
56
|
};
|
|
39
57
|
|
|
58
|
+
/** Readable line length for a short dialog on tablets too. */
|
|
59
|
+
const DIALOG_MAX_WIDTH = 340;
|
|
60
|
+
const ICON_SIZE = 48;
|
|
61
|
+
/** Above any sibling of the inline host. */
|
|
62
|
+
const INLINE_Z = 9999;
|
|
63
|
+
|
|
40
64
|
const useStyles = createStyles((theme) => ({
|
|
41
|
-
overlay: {
|
|
42
|
-
|
|
65
|
+
overlay: {
|
|
66
|
+
flex: 1,
|
|
67
|
+
backgroundColor: theme.colors.overlay,
|
|
68
|
+
justifyContent: 'center',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
padding: theme.tokens.spacing.xl,
|
|
71
|
+
},
|
|
72
|
+
fill: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 },
|
|
73
|
+
overlayInline: { zIndex: INLINE_Z },
|
|
43
74
|
container: {
|
|
44
|
-
|
|
75
|
+
// Raised: in dark mode the plain surface sank into the dimmed backdrop.
|
|
76
|
+
backgroundColor: theme.colors.surfaceRaised,
|
|
45
77
|
borderRadius: theme.tokens.radius.xl,
|
|
46
78
|
padding: theme.tokens.spacing.xl,
|
|
47
79
|
width: '100%',
|
|
48
|
-
maxWidth:
|
|
80
|
+
maxWidth: DIALOG_MAX_WIDTH,
|
|
49
81
|
alignItems: 'center',
|
|
50
82
|
...theme.tokens.shadow.md,
|
|
51
83
|
},
|
|
52
|
-
iconContainer: { marginBottom: theme.tokens.spacing.lg
|
|
53
|
-
title: {
|
|
54
|
-
|
|
55
|
-
|
|
84
|
+
iconContainer: { marginBottom: theme.tokens.spacing.lg },
|
|
85
|
+
title: {
|
|
86
|
+
fontSize: theme.tokens.fontSize.xl,
|
|
87
|
+
lineHeight: theme.tokens.lineHeight.lg,
|
|
88
|
+
fontWeight: theme.tokens.fontWeight.bold,
|
|
89
|
+
color: theme.colors.text,
|
|
90
|
+
textAlign: 'center',
|
|
91
|
+
marginBottom: theme.tokens.spacing.sm,
|
|
92
|
+
},
|
|
93
|
+
message: {
|
|
94
|
+
fontSize: theme.tokens.fontSize.md,
|
|
95
|
+
lineHeight: theme.tokens.lineHeight.md,
|
|
96
|
+
color: theme.colors.textLight,
|
|
97
|
+
textAlign: 'center',
|
|
98
|
+
},
|
|
99
|
+
buttonContainer: {
|
|
100
|
+
flexDirection: 'row',
|
|
101
|
+
justifyContent: 'center',
|
|
102
|
+
gap: theme.tokens.spacing.sm,
|
|
103
|
+
width: '100%',
|
|
104
|
+
marginTop: theme.tokens.spacing.xl,
|
|
105
|
+
},
|
|
56
106
|
buttonContainerVertical: { flexDirection: 'column' },
|
|
57
|
-
button: { paddingVertical: theme.tokens.spacing.md - 2, paddingHorizontal: theme.tokens.spacing.xl },
|
|
58
107
|
buttonHorizontal: { flex: 1 },
|
|
59
108
|
buttonVertical: { width: '100%' },
|
|
60
109
|
}));
|
|
61
110
|
|
|
62
|
-
/**
|
|
111
|
+
/** Derives the list of buttons from props, without mutating the `buttons` received through props. */
|
|
63
112
|
function resolveButtons(props: AlertProps, labels: { confirm: string; cancel: string; close: string }): AlertButton[] {
|
|
64
|
-
const { buttons, confirmText, cancelText, onConfirm, onCancel, onClose } = props;
|
|
113
|
+
const { buttons, confirmText, cancelText, onConfirm, onCancel, onClose, destructive } = props;
|
|
65
114
|
if (buttons && buttons.length > 0) return buttons;
|
|
66
115
|
|
|
67
116
|
if (confirmText || onConfirm) {
|
|
@@ -69,7 +118,7 @@ function resolveButtons(props: AlertProps, labels: { confirm: string; cancel: st
|
|
|
69
118
|
if (cancelText || onCancel) {
|
|
70
119
|
list.push({ text: cancelText || labels.cancel, onPress: onCancel || onClose, variant: 'outline', style: 'cancel' });
|
|
71
120
|
}
|
|
72
|
-
list.push({ text: confirmText || labels.confirm, onPress: onConfirm, variant: 'primary' });
|
|
121
|
+
list.push({ text: confirmText || labels.confirm, onPress: onConfirm, variant: destructive ? 'destructive' : 'primary' });
|
|
73
122
|
return list;
|
|
74
123
|
}
|
|
75
124
|
|
|
@@ -78,11 +127,21 @@ function resolveButtons(props: AlertProps, labels: { confirm: string; cancel: st
|
|
|
78
127
|
|
|
79
128
|
/**
|
|
80
129
|
* Alert
|
|
81
|
-
*
|
|
82
|
-
*
|
|
130
|
+
* Declarative dialog component. For imperative use (showing it from a
|
|
131
|
+
* handler without lifting your own state), use AlertProvider + useAlert().
|
|
132
|
+
*
|
|
133
|
+
* Gestalt, figure-ground: the overlay dims everything behind, so the dialog
|
|
134
|
+
* is the only figure. Proximity: icon, title and message sit together and the
|
|
135
|
+
* buttons a larger step below, as the answer block. Von Restorff: only the
|
|
136
|
+
* main action is filled (or red when `destructive`); cancel is outline.
|
|
137
|
+
* Hick: two buttons side by side; three or more stack so each reads alone.
|
|
138
|
+
*
|
|
139
|
+
* Accessibility: the title is a header, the dialog is modal for VoiceOver and
|
|
140
|
+
* the escape gesture (two-finger Z) calls `onClose`.
|
|
83
141
|
*/
|
|
84
142
|
export const Alert = memo((props: AlertProps) => {
|
|
85
143
|
const { visible, title, message, type = 'info', onClose, inline = false } = props;
|
|
144
|
+
const theme = useTheme();
|
|
86
145
|
const colors = useColors();
|
|
87
146
|
const styles = useStyles();
|
|
88
147
|
const labels = useLabels();
|
|
@@ -91,7 +150,7 @@ export const Alert = memo((props: AlertProps) => {
|
|
|
91
150
|
if (!visible) return null;
|
|
92
151
|
|
|
93
152
|
const iconColor: Record<AlertType, string> = {
|
|
94
|
-
//
|
|
153
|
+
// Icons over the dialog's surface: `*Text` role, not the full accent.
|
|
95
154
|
success: colors.successText,
|
|
96
155
|
error: colors.errorText,
|
|
97
156
|
warning: colors.warningText,
|
|
@@ -104,14 +163,19 @@ export const Alert = memo((props: AlertProps) => {
|
|
|
104
163
|
|
|
105
164
|
const content = (
|
|
106
165
|
<TouchableWithoutFeedback onPress={onClose} accessibilityRole="none">
|
|
107
|
-
<View style={[styles.overlay, inline && styles.overlayInline]}>
|
|
166
|
+
<View style={[styles.overlay, inline && [styles.fill, styles.overlayInline]]}>
|
|
108
167
|
<TouchableWithoutFeedback>
|
|
109
|
-
<View
|
|
168
|
+
<View
|
|
169
|
+
style={styles.container}
|
|
170
|
+
accessibilityRole="alert"
|
|
171
|
+
accessibilityViewIsModal
|
|
172
|
+
onAccessibilityEscape={onClose}
|
|
173
|
+
>
|
|
110
174
|
<View style={styles.iconContainer}>
|
|
111
|
-
<Icon name={ICON_BY_TYPE[type]} size={
|
|
175
|
+
<Icon name={ICON_BY_TYPE[type]} size={ICON_SIZE} color={iconColor[type]} />
|
|
112
176
|
</View>
|
|
113
177
|
|
|
114
|
-
<Text allowFontScaling={allowFontScaling} style={styles.title}>
|
|
178
|
+
<Text allowFontScaling={allowFontScaling} style={styles.title} accessibilityRole="header">
|
|
115
179
|
{title}
|
|
116
180
|
</Text>
|
|
117
181
|
|
|
@@ -134,8 +198,8 @@ export const Alert = memo((props: AlertProps) => {
|
|
|
134
198
|
title={btn.text}
|
|
135
199
|
onPress={btn.onPress || onClose || (() => {})}
|
|
136
200
|
variant={variant}
|
|
137
|
-
style={
|
|
138
|
-
textStyle={{ fontSize:
|
|
201
|
+
style={vertical ? styles.buttonVertical : styles.buttonHorizontal}
|
|
202
|
+
textStyle={{ fontSize: theme.tokens.fontSize.md }}
|
|
139
203
|
/>
|
|
140
204
|
);
|
|
141
205
|
})}
|
|
@@ -148,16 +212,23 @@ export const Alert = memo((props: AlertProps) => {
|
|
|
148
212
|
|
|
149
213
|
if (inline) {
|
|
150
214
|
return (
|
|
151
|
-
<View style={
|
|
215
|
+
<View style={styles.fill} pointerEvents="box-none">
|
|
152
216
|
{content}
|
|
153
217
|
</View>
|
|
154
218
|
);
|
|
155
219
|
}
|
|
156
220
|
|
|
157
221
|
return (
|
|
158
|
-
<
|
|
222
|
+
<NativeOverlay
|
|
223
|
+
dialog
|
|
224
|
+
transparent
|
|
225
|
+
animationType="fade"
|
|
226
|
+
statusBarTranslucent
|
|
227
|
+
presentationStyle="overFullScreen"
|
|
228
|
+
onRequestClose={onClose || (() => {})}
|
|
229
|
+
>
|
|
159
230
|
{content}
|
|
160
|
-
</
|
|
231
|
+
</NativeOverlay>
|
|
161
232
|
);
|
|
162
233
|
});
|
|
163
234
|
Alert.displayName = 'Alert';
|
|
@@ -11,14 +11,14 @@ export interface AlertOptions {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface ConfirmOptions extends AlertOptions {
|
|
14
|
-
/**
|
|
14
|
+
/** Shows the confirm button as destructive/red (for "delete", etc.). */
|
|
15
15
|
destructive?: boolean;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
interface AlertContextValue {
|
|
19
|
-
/**
|
|
19
|
+
/** Shows a single-button alert. Resolves when it closes. */
|
|
20
20
|
alert: (options: AlertOptions) => Promise<void>;
|
|
21
|
-
/**
|
|
21
|
+
/** Shows confirm/cancel. Resolves true if confirmed, false if cancelled. */
|
|
22
22
|
confirm: (options: ConfirmOptions) => Promise<boolean>;
|
|
23
23
|
hide: () => void;
|
|
24
24
|
}
|
|
@@ -27,15 +27,15 @@ const AlertContext = createContext<AlertContextValue | undefined>(undefined);
|
|
|
27
27
|
const bridge = createImperativeBridge<AlertContextValue>('AlertProvider');
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Opens an alert from outside the React tree —a service, an interceptor—
|
|
31
|
+
* without going through the hook. Without a mounted <AlertProvider> it
|
|
32
|
+
* resolves immediately, so an `await` never hangs.
|
|
33
33
|
*/
|
|
34
34
|
export function showAlert(options: AlertOptions): Promise<void> {
|
|
35
35
|
return bridge.get()?.alert(options) ?? Promise.resolve();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/**
|
|
38
|
+
/** Same as showAlert, but resolves true/false. Without a provider, false. */
|
|
39
39
|
export function showConfirm(options: ConfirmOptions): Promise<boolean> {
|
|
40
40
|
return bridge.get()?.confirm(options) ?? Promise.resolve(false);
|
|
41
41
|
}
|
|
@@ -56,16 +56,16 @@ const HIDDEN: InternalState = { visible: false, title: '', type: 'info', buttons
|
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
58
|
* AlertProvider
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* `const ok = await confirm({ title: '
|
|
59
|
+
* Mounts a single imperatively controlled <Alert>. Place it once near the
|
|
60
|
+
* root (inside UIProvider). Async handlers can do
|
|
61
|
+
* `const ok = await confirm({ title: 'Delete', destructive: true })`.
|
|
62
62
|
*/
|
|
63
63
|
export function AlertProvider({ children }: { children: React.ReactNode }) {
|
|
64
64
|
const [state, setState] = useState<InternalState>(HIDDEN);
|
|
65
65
|
const resolverRef = useRef<((value: any) => void) | null>(null);
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
//
|
|
66
|
+
// If alert()/confirm() are called again while one is already open, the
|
|
67
|
+
// previous request is resolved (not discarded) before showing the new one:
|
|
68
|
+
// this keeps its promise from hanging forever.
|
|
69
69
|
const settlePending = useCallback(() => {
|
|
70
70
|
resolverRef.current?.(undefined);
|
|
71
71
|
resolverRef.current = null;
|
|
@@ -1,31 +1,42 @@
|
|
|
1
1
|
import React, { memo, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Animated,
|
|
4
|
-
Dimensions,
|
|
5
4
|
Keyboard,
|
|
6
5
|
KeyboardAvoidingView,
|
|
7
|
-
Modal,
|
|
8
6
|
PanResponder,
|
|
9
7
|
Platform,
|
|
10
8
|
Pressable,
|
|
11
9
|
ScrollView,
|
|
12
10
|
View,
|
|
11
|
+
useWindowDimensions,
|
|
13
12
|
type ViewStyle,
|
|
14
13
|
} from 'react-native';
|
|
15
14
|
import { createStyles } from '../theme/createStyles';
|
|
16
|
-
import { useColors, useModalSafeAreaBoundary } from '../theme/UIProvider';
|
|
15
|
+
import { useColors, useLabels, useModalSafeAreaBoundary, useTheme } from '../theme/UIProvider';
|
|
16
|
+
import { useReduceMotion } from '../theme/useReduceMotion';
|
|
17
|
+
import { KeyboardHandled } from '../theme/KeyboardAvoidance';
|
|
18
|
+
import { NativeOverlay } from '../theme/NativeOverlay';
|
|
17
19
|
import { Title } from '../atoms/Text';
|
|
18
20
|
import { IconButton } from '../atoms/IconButton';
|
|
19
21
|
import { Transition } from '../atoms/Transition';
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
+
/** Drag distance (pt) that closes the sheet on release. */
|
|
24
|
+
const DISMISS_DISTANCE = 100;
|
|
25
|
+
/** Downward release speed that closes it even after a short drag (a flick). */
|
|
26
|
+
const DISMISS_VELOCITY = 0.5;
|
|
27
|
+
const HANDLE_WIDTH = 40;
|
|
28
|
+
const HANDLE_HEIGHT = 5;
|
|
29
|
+
const HANDLE_OPACITY = 0.4;
|
|
30
|
+
const CLOSE_ICON_SIZE = 24;
|
|
23
31
|
|
|
24
32
|
export type FooterPlacement = 'fixed' | 'scroll' | 'hide-with-keyboard';
|
|
25
33
|
|
|
26
34
|
export interface BottomSheetProps {
|
|
35
|
+
/** Shows or hides the sheet (it slides in and out). */
|
|
27
36
|
visible: boolean;
|
|
37
|
+
/** Called by the backdrop, the close button, the drag and Android back. */
|
|
28
38
|
onClose: () => void;
|
|
39
|
+
/** Sheet content. */
|
|
29
40
|
children: React.ReactNode;
|
|
30
41
|
/** With a title, the header appears, with its close button. */
|
|
31
42
|
title?: string;
|
|
@@ -43,9 +54,14 @@ export interface BottomSheetProps {
|
|
|
43
54
|
draggable?: boolean;
|
|
44
55
|
/** Fraction of the screen (0-1) or pixels. @default 0.9 */
|
|
45
56
|
maxHeight?: number;
|
|
57
|
+
/** Accessible name of the close button and backdrop. @default labels.close */
|
|
46
58
|
closeAccessibilityLabel?: string;
|
|
59
|
+
/** Style of the sheet itself (background, radius). */
|
|
47
60
|
containerStyle?: ViewStyle;
|
|
61
|
+
/** Style of the content area (padding). */
|
|
48
62
|
contentStyle?: ViewStyle;
|
|
63
|
+
/** Draws the sheet inside its parent instead of over the screen (docs, previews). @default false */
|
|
64
|
+
inline?: boolean;
|
|
49
65
|
testID?: string;
|
|
50
66
|
}
|
|
51
67
|
|
|
@@ -53,13 +69,22 @@ const useStyles = createStyles((theme) => ({
|
|
|
53
69
|
container: { flex: 1, justifyContent: 'flex-end' },
|
|
54
70
|
backdrop: { backgroundColor: theme.colors.overlay },
|
|
55
71
|
sheet: {
|
|
56
|
-
|
|
72
|
+
// Raised: in dark mode the plain surface sank into the dimmed backdrop.
|
|
73
|
+
backgroundColor: theme.colors.surfaceRaised,
|
|
57
74
|
borderTopLeftRadius: theme.tokens.radius.xxl,
|
|
58
75
|
borderTopRightRadius: theme.tokens.radius.xxl,
|
|
59
76
|
...theme.tokens.shadow.lg,
|
|
60
77
|
},
|
|
61
78
|
handleArea: { paddingVertical: theme.tokens.spacing.md, alignItems: 'center' },
|
|
62
|
-
handle: {
|
|
79
|
+
handle: {
|
|
80
|
+
width: HANDLE_WIDTH,
|
|
81
|
+
height: HANDLE_HEIGHT,
|
|
82
|
+
borderRadius: HANDLE_HEIGHT / 2,
|
|
83
|
+
// textLight, faded: `border` was nearly invisible on a white sheet, and
|
|
84
|
+
// the handle is the only hint that the sheet can be dragged.
|
|
85
|
+
backgroundColor: theme.colors.textLight,
|
|
86
|
+
opacity: HANDLE_OPACITY,
|
|
87
|
+
},
|
|
63
88
|
header: {
|
|
64
89
|
flexDirection: 'row',
|
|
65
90
|
alignItems: 'center',
|
|
@@ -84,10 +109,17 @@ const absoluteFill: ViewStyle = { position: 'absolute', top: 0, left: 0, right:
|
|
|
84
109
|
|
|
85
110
|
/**
|
|
86
111
|
* BottomSheet
|
|
87
|
-
*
|
|
88
|
-
* gesture-handler
|
|
89
|
-
* scroll
|
|
90
|
-
*
|
|
112
|
+
* Sheet that slides in from the bottom, with drag to close (PanResponder, not
|
|
113
|
+
* an external gesture-handler: the library is zero-dependency). Header, footer
|
|
114
|
+
* and scroll are optional, so it covers both the bare sheet and the full
|
|
115
|
+
* form.
|
|
116
|
+
*
|
|
117
|
+
* Gestalt, figure-ground: the backdrop dims the screen, so the sheet is the
|
|
118
|
+
* only figure. Common region: header, content and footer share one panel;
|
|
119
|
+
* the footer's top border separates the actions from the content. Continuity:
|
|
120
|
+
* it slides from the edge it lives on and the drag follows the finger back
|
|
121
|
+
* down; a short flick closes it too. Fitts: content sits in the thumb zone.
|
|
122
|
+
* Reduce Motion: it appears and leaves without sliding.
|
|
91
123
|
*/
|
|
92
124
|
export const BottomSheet = memo(
|
|
93
125
|
({
|
|
@@ -100,36 +132,50 @@ export const BottomSheet = memo(
|
|
|
100
132
|
scrollable = true,
|
|
101
133
|
draggable = true,
|
|
102
134
|
maxHeight = 0.9,
|
|
103
|
-
closeAccessibilityLabel
|
|
135
|
+
closeAccessibilityLabel,
|
|
104
136
|
containerStyle,
|
|
105
137
|
contentStyle,
|
|
138
|
+
inline = false,
|
|
106
139
|
testID,
|
|
107
140
|
}: BottomSheetProps) => {
|
|
108
141
|
const styles = useStyles();
|
|
109
142
|
const colors = useColors();
|
|
143
|
+
const theme = useTheme();
|
|
144
|
+
const labels = useLabels();
|
|
145
|
+
const reduceMotion = useReduceMotion();
|
|
146
|
+
const { height: screenHeight } = useWindowDimensions();
|
|
147
|
+
const closeLabel = closeAccessibilityLabel ?? labels.close;
|
|
148
|
+
const { duration } = theme.tokens;
|
|
149
|
+
// The PanResponder is created once: it reads these through refs.
|
|
150
|
+
const screenHeightRef = useRef(screenHeight);
|
|
151
|
+
screenHeightRef.current = screenHeight;
|
|
152
|
+
const snapBackMs = useRef(duration.fast);
|
|
153
|
+
snapBackMs.current = reduceMotion ? 0 : duration.fast;
|
|
110
154
|
const ModalSafeAreaBoundary = useModalSafeAreaBoundary();
|
|
111
155
|
const [mounted, setMounted] = useState(visible);
|
|
112
156
|
const [keyboardOpen, setKeyboardOpen] = useState(false);
|
|
113
157
|
const progress = useRef(new Animated.Value(0)).current;
|
|
114
|
-
//
|
|
115
|
-
//
|
|
116
|
-
//
|
|
158
|
+
// The PanResponder further down is created only once; reading `onClose`
|
|
159
|
+
// straight from the closure would always give the one from that first
|
|
160
|
+
// render. The ref reflects the latest prop no matter when the closure was created.
|
|
117
161
|
const onCloseRef = useRef(onClose);
|
|
118
162
|
onCloseRef.current = onClose;
|
|
119
163
|
|
|
120
164
|
useEffect(() => {
|
|
121
|
-
const animation =
|
|
122
|
-
|
|
123
|
-
:
|
|
165
|
+
const animation = Animated.timing(progress, {
|
|
166
|
+
toValue: visible ? 1 : 0,
|
|
167
|
+
duration: reduceMotion ? 0 : visible ? duration.slow : duration.base,
|
|
168
|
+
useNativeDriver: true,
|
|
169
|
+
});
|
|
124
170
|
if (visible) setMounted(true);
|
|
125
171
|
animation.start(({ finished }) => {
|
|
126
172
|
if (!visible && finished) setMounted(false);
|
|
127
173
|
});
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
// `setMounted`
|
|
174
|
+
// If the effect runs again (or the component unmounts) before it
|
|
175
|
+
// finishes, it is cut short: otherwise, a late `finished` could call
|
|
176
|
+
// `setMounted` on an already unmounted component.
|
|
131
177
|
return () => animation.stop();
|
|
132
|
-
}, [visible, progress]);
|
|
178
|
+
}, [visible, progress, reduceMotion, duration.slow, duration.base]);
|
|
133
179
|
|
|
134
180
|
useEffect(() => {
|
|
135
181
|
if (footerPlacement !== 'hide-with-keyboard') return;
|
|
@@ -146,13 +192,14 @@ export const BottomSheet = memo(
|
|
|
146
192
|
PanResponder.create({
|
|
147
193
|
onMoveShouldSetPanResponder: (_, gesture) => gesture.dy > 5 && Math.abs(gesture.dy) > Math.abs(gesture.dx),
|
|
148
194
|
onPanResponderMove: (_, gesture) => {
|
|
149
|
-
|
|
195
|
+
const h = screenHeightRef.current;
|
|
196
|
+
if (gesture.dy > 0) progress.setValue(1 - Math.min(gesture.dy, h) / h);
|
|
150
197
|
},
|
|
151
198
|
onPanResponderRelease: (_, gesture) => {
|
|
152
|
-
if (gesture.dy >
|
|
199
|
+
if (gesture.dy > DISMISS_DISTANCE || (gesture.dy > 0 && gesture.vy > DISMISS_VELOCITY)) {
|
|
153
200
|
onCloseRef.current();
|
|
154
201
|
} else {
|
|
155
|
-
Animated.timing(progress, { toValue: 1, duration:
|
|
202
|
+
Animated.timing(progress, { toValue: 1, duration: snapBackMs.current, useNativeDriver: true }).start();
|
|
156
203
|
}
|
|
157
204
|
},
|
|
158
205
|
})
|
|
@@ -160,8 +207,8 @@ export const BottomSheet = memo(
|
|
|
160
207
|
|
|
161
208
|
if (!mounted) return null;
|
|
162
209
|
|
|
163
|
-
//
|
|
164
|
-
//
|
|
210
|
+
// Percentage, not pixels: it is measured against the container, which is
|
|
211
|
+
// shorter with the keyboard open, so the sheet always fits entirely.
|
|
165
212
|
const resolvedMaxHeight: number | `${number}%` = maxHeight <= 1 ? `${maxHeight * 100}%` : maxHeight;
|
|
166
213
|
const hasHeader = !!title;
|
|
167
214
|
|
|
@@ -190,44 +237,53 @@ export const BottomSheet = memo(
|
|
|
190
237
|
</View>
|
|
191
238
|
);
|
|
192
239
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
{/*
|
|
196
|
-
|
|
197
|
-
|
|
240
|
+
const tree = (
|
|
241
|
+
<>
|
|
242
|
+
{/* The sheet is anchored at the bottom, so the keyboard covers it
|
|
243
|
+
entirely: it has to be pushed up, not adjusted with insets inside
|
|
244
|
+
the scroll. A single compensation, the container's. */}
|
|
245
|
+
<KeyboardHandled>
|
|
198
246
|
<KeyboardAvoidingView
|
|
199
247
|
style={styles.container}
|
|
200
248
|
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
|
201
249
|
>
|
|
202
250
|
<Transition value={progress} preset="fade" style={[absoluteFill, styles.backdrop]}>
|
|
203
|
-
{/*
|
|
204
|
-
label
|
|
251
|
+
{/* With a header, the close button already exposes the action:
|
|
252
|
+
repeating the label here leaves two elements with the same name. */}
|
|
205
253
|
<Pressable
|
|
206
254
|
style={absoluteFill}
|
|
207
255
|
onPress={onClose}
|
|
208
256
|
testID="bottom-sheet-backdrop"
|
|
209
257
|
accessibilityRole={hasHeader ? undefined : 'button'}
|
|
210
|
-
accessibilityLabel={hasHeader ? undefined :
|
|
258
|
+
accessibilityLabel={hasHeader ? undefined : closeLabel}
|
|
211
259
|
/>
|
|
212
260
|
</Transition>
|
|
213
261
|
|
|
214
|
-
{/* Insets
|
|
215
|
-
|
|
262
|
+
{/* Insets measured inside this native window (the native Modal
|
|
263
|
+
BottomSheet uses underneath), not the app root's. */}
|
|
216
264
|
<ModalSafeAreaBoundary>
|
|
217
265
|
{(insets) => (
|
|
218
266
|
<Transition
|
|
219
267
|
value={progress}
|
|
220
268
|
preset="slide-up"
|
|
221
|
-
distance={
|
|
269
|
+
distance={screenHeight}
|
|
222
270
|
testID={testID}
|
|
223
271
|
style={[
|
|
224
272
|
styles.sheet,
|
|
225
|
-
{ maxHeight: resolvedMaxHeight, paddingBottom: Math.max(insets.bottom,
|
|
273
|
+
{ maxHeight: resolvedMaxHeight, paddingBottom: Math.max(insets.bottom, theme.tokens.spacing.xl) },
|
|
226
274
|
containerStyle,
|
|
227
275
|
]}
|
|
228
276
|
>
|
|
229
277
|
{draggable && (
|
|
230
|
-
|
|
278
|
+
// Decorative for screen readers: closing is already exposed by the
|
|
279
|
+
// close button (with a title) or by the backdrop (without one).
|
|
280
|
+
<View
|
|
281
|
+
style={styles.handleArea}
|
|
282
|
+
testID="bottom-sheet-handle"
|
|
283
|
+
accessibilityElementsHidden
|
|
284
|
+
importantForAccessibility="no-hide-descendants"
|
|
285
|
+
{...panResponder.panHandlers}
|
|
286
|
+
>
|
|
231
287
|
<View style={styles.handle} />
|
|
232
288
|
</View>
|
|
233
289
|
)}
|
|
@@ -239,10 +295,10 @@ export const BottomSheet = memo(
|
|
|
239
295
|
</Title>
|
|
240
296
|
<IconButton
|
|
241
297
|
iconName="close"
|
|
242
|
-
size={
|
|
298
|
+
size={CLOSE_ICON_SIZE}
|
|
243
299
|
color={colors.text}
|
|
244
300
|
onPress={onClose}
|
|
245
|
-
accessibilityLabel={
|
|
301
|
+
accessibilityLabel={closeLabel}
|
|
246
302
|
/>
|
|
247
303
|
</View>
|
|
248
304
|
)}
|
|
@@ -254,7 +310,23 @@ export const BottomSheet = memo(
|
|
|
254
310
|
)}
|
|
255
311
|
</ModalSafeAreaBoundary>
|
|
256
312
|
</KeyboardAvoidingView>
|
|
257
|
-
|
|
313
|
+
</KeyboardHandled>
|
|
314
|
+
</>
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
if (inline) {
|
|
318
|
+
return (
|
|
319
|
+
<View style={absoluteFill} pointerEvents="box-none">
|
|
320
|
+
{tree}
|
|
321
|
+
</View>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
// closing: while the exit animation plays, no other overlay layers into it.
|
|
327
|
+
<NativeOverlay closing={!visible} transparent animationType="none" statusBarTranslucent onRequestClose={onClose}>
|
|
328
|
+
{tree}
|
|
329
|
+
</NativeOverlay>
|
|
258
330
|
);
|
|
259
331
|
}
|
|
260
332
|
);
|