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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import { useCallback, useEffect, useMemo, useRef, useState, type ComponentRef } from 'react';
|
|
2
2
|
import type { LayoutChangeEvent, NativeScrollEvent, NativeSyntheticEvent, ScrollView } from 'react-native';
|
|
3
3
|
import { useReduceMotion } from '../atoms/Transition';
|
|
4
4
|
|
|
@@ -10,13 +10,13 @@ export interface UseSlidesOptions {
|
|
|
10
10
|
loop: boolean;
|
|
11
11
|
autoPlay: boolean;
|
|
12
12
|
interval: number;
|
|
13
|
-
/**
|
|
13
|
+
/** Controlled index; without it the internal state rules. */
|
|
14
14
|
index?: number;
|
|
15
15
|
defaultIndex: number;
|
|
16
16
|
onIndexChange?: (index: number) => void;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
/**
|
|
19
|
+
/** A page of the scroll. The infinite mode's clones repeat a neighbor's `real`. */
|
|
20
20
|
export interface SlidesPage {
|
|
21
21
|
real: number;
|
|
22
22
|
clone: 'head' | 'tail' | null;
|
|
@@ -28,18 +28,18 @@ export interface UseSlidesResult {
|
|
|
28
28
|
isHorizontal: boolean;
|
|
29
29
|
isLoop: boolean;
|
|
30
30
|
size: { width: number; height: number };
|
|
31
|
-
/**
|
|
31
|
+
/** Length of a page along the scroll axis. At 0 it hasn't been measured yet. */
|
|
32
32
|
pageSize: number;
|
|
33
|
-
scrollRef: React.RefObject<ScrollView | null>;
|
|
33
|
+
scrollRef: React.RefObject<ComponentRef<typeof ScrollView> | null>;
|
|
34
34
|
autoPlayPaused: boolean;
|
|
35
|
-
/**
|
|
35
|
+
/** The system asked to reduce motion: no autoPlay or transitions. */
|
|
36
36
|
motionReduced: boolean;
|
|
37
37
|
goTo: (index: number) => void;
|
|
38
38
|
toggleAutoPlay: () => void;
|
|
39
39
|
onLayout: (event: LayoutChangeEvent) => void;
|
|
40
40
|
onMomentumScrollEnd: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
41
|
-
onScrollBeginDrag: () => void;
|
|
42
|
-
onScrollEndDrag: () => void;
|
|
41
|
+
onScrollBeginDrag: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
42
|
+
onScrollEndDrag: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function clampIndex(value: number, total: number): number {
|
|
@@ -51,13 +51,16 @@ export function clampIndex(value: number, total: number): number {
|
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
53
|
* useSlides
|
|
54
|
-
*
|
|
55
|
-
* scroll,
|
|
56
|
-
*
|
|
54
|
+
* Everything in `Slides` that isn't visible: which page is framed, when to
|
|
55
|
+
* move the scroll, how the infinite mode's clones map to real indexes, and the
|
|
56
|
+
* autoplay clock.
|
|
57
57
|
*
|
|
58
|
-
*
|
|
59
|
-
* `T
|
|
58
|
+
* It works only with indexes, never with the items: that way it doesn't need
|
|
59
|
+
* the component's generic `T`, and the UI resolves `pages[i].real` against its own `data`.
|
|
60
60
|
*/
|
|
61
|
+
/** Points a finger has to move the slides for the drag to count as a swipe. */
|
|
62
|
+
const DRAG_SLOP = 10;
|
|
63
|
+
|
|
61
64
|
export function useSlides({
|
|
62
65
|
total,
|
|
63
66
|
orientation,
|
|
@@ -70,8 +73,8 @@ export function useSlides({
|
|
|
70
73
|
}: UseSlidesOptions): UseSlidesResult {
|
|
71
74
|
const motionReduced = useReduceMotion();
|
|
72
75
|
const isHorizontal = orientation === 'horizontal';
|
|
73
|
-
//
|
|
74
|
-
//
|
|
76
|
+
// A single element has nowhere to cycle to: it would be swipeable between
|
|
77
|
+
// three copies of the same thing.
|
|
75
78
|
const isLoop = loop && total > 1;
|
|
76
79
|
|
|
77
80
|
const [uncontrolled, setUncontrolled] = useState(() => clampIndex(defaultIndex, total));
|
|
@@ -83,12 +86,19 @@ export function useSlides({
|
|
|
83
86
|
const [size, setSize] = useState({ width: 0, height: 0 });
|
|
84
87
|
const pageSize = isHorizontal ? size.width : size.height;
|
|
85
88
|
|
|
86
|
-
const scrollRef = useRef<ScrollView
|
|
87
|
-
/**
|
|
89
|
+
const scrollRef = useRef<ComponentRef<typeof ScrollView>>(null);
|
|
90
|
+
/** The page actually visible (index within `pages`, clones included). */
|
|
88
91
|
const offsetPageRef = useRef(isLoop ? 1 : 0);
|
|
89
92
|
const didInitRef = useRef(false);
|
|
90
93
|
const lastPageSizeRef = useRef(0);
|
|
91
94
|
const draggingRef = useRef(false);
|
|
95
|
+
/**
|
|
96
|
+
* Page an animated `scrollTo` was sent to and hasn't reached yet. On iOS a
|
|
97
|
+
* touch (tapping another indicator) stops that animation midway: the
|
|
98
|
+
* scroll then ends on the wrong page, and committing it undid the tap.
|
|
99
|
+
*/
|
|
100
|
+
const pendingPageRef = useRef<number | null>(null);
|
|
101
|
+
const dragStartRef = useRef(0);
|
|
92
102
|
|
|
93
103
|
const pages = useMemo<SlidesPage[]>(() => {
|
|
94
104
|
const real = Array.from({ length: total }, (_, i) => ({ real: i, clone: null }));
|
|
@@ -118,19 +128,20 @@ export function useSlides({
|
|
|
118
128
|
[index, onIndexChange]
|
|
119
129
|
);
|
|
120
130
|
|
|
121
|
-
//
|
|
122
|
-
//
|
|
131
|
+
// Only acts when the index and the visible page disagree: a change that
|
|
132
|
+
// came from the gesture itself doesn't fire a second scroll on top of the one that stopped.
|
|
123
133
|
useEffect(() => {
|
|
124
134
|
if (pageSize === 0 || total === 0) return;
|
|
125
135
|
const target = isLoop ? active + 1 : active;
|
|
126
136
|
const resized = lastPageSizeRef.current !== pageSize;
|
|
127
137
|
if (offsetPageRef.current === target && didInitRef.current && !resized) return;
|
|
128
|
-
//
|
|
129
|
-
//
|
|
138
|
+
// Neither the first positioning nor the rearrangement on rotation is a
|
|
139
|
+
// slide change: animating them would be a slide nobody asked for.
|
|
130
140
|
const animated = didInitRef.current && !resized;
|
|
131
141
|
didInitRef.current = true;
|
|
132
142
|
lastPageSizeRef.current = pageSize;
|
|
133
143
|
offsetPageRef.current = target;
|
|
144
|
+
pendingPageRef.current = animated ? target : null;
|
|
134
145
|
scrollToPage(target, animated);
|
|
135
146
|
}, [active, isLoop, pageSize, scrollToPage, total]);
|
|
136
147
|
|
|
@@ -145,6 +156,16 @@ export function useSlides({
|
|
|
145
156
|
if (pageSize === 0) return;
|
|
146
157
|
const { contentOffset } = event.nativeEvent;
|
|
147
158
|
const page = Math.round((isHorizontal ? contentOffset.x : contentOffset.y) / pageSize);
|
|
159
|
+
// A scrollTo still on its way: if it stopped short (a touch interrupted
|
|
160
|
+
// it), finish the trip instead of committing where it stopped.
|
|
161
|
+
const pending = pendingPageRef.current;
|
|
162
|
+
if (pending !== null) {
|
|
163
|
+
if (page !== pending) {
|
|
164
|
+
scrollToPage(pending, true);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
pendingPageRef.current = null;
|
|
168
|
+
}
|
|
148
169
|
|
|
149
170
|
if (isLoop) {
|
|
150
171
|
if (page === 0) {
|
|
@@ -170,15 +191,28 @@ export function useSlides({
|
|
|
170
191
|
[goTo, isHorizontal, isLoop, pageSize, scrollToPage, total]
|
|
171
192
|
);
|
|
172
193
|
|
|
173
|
-
const onScrollBeginDrag = useCallback(
|
|
174
|
-
|
|
175
|
-
|
|
194
|
+
const onScrollBeginDrag = useCallback(
|
|
195
|
+
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
196
|
+
draggingRef.current = true;
|
|
197
|
+
const { contentOffset } = event.nativeEvent;
|
|
198
|
+
dragStartRef.current = isHorizontal ? contentOffset.x : contentOffset.y;
|
|
199
|
+
},
|
|
200
|
+
[isHorizontal]
|
|
201
|
+
);
|
|
176
202
|
|
|
177
|
-
const onScrollEndDrag = useCallback(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
203
|
+
const onScrollEndDrag = useCallback(
|
|
204
|
+
(event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
|
205
|
+
// A short drag can be released without momentum and not emit
|
|
206
|
+
// momentumScrollEnd: without this autoPlay would stay paused forever.
|
|
207
|
+
draggingRef.current = false;
|
|
208
|
+
// A finger that really moved the slides takes over from a pending
|
|
209
|
+
// scrollTo; a tap (no movement) doesn't.
|
|
210
|
+
const { contentOffset } = event.nativeEvent;
|
|
211
|
+
const moved = Math.abs((isHorizontal ? contentOffset.x : contentOffset.y) - dragStartRef.current);
|
|
212
|
+
if (moved > DRAG_SLOP) pendingPageRef.current = null;
|
|
213
|
+
},
|
|
214
|
+
[isHorizontal]
|
|
215
|
+
);
|
|
182
216
|
|
|
183
217
|
const toggleAutoPlay = useCallback(() => setAutoPlayPaused((paused) => !paused), []);
|
|
184
218
|
|
|
@@ -192,9 +226,10 @@ export function useSlides({
|
|
|
192
226
|
return;
|
|
193
227
|
}
|
|
194
228
|
if (!isLoop) return;
|
|
195
|
-
//
|
|
196
|
-
//
|
|
229
|
+
// Last one in infinite mode: advances to the clone of the first instead
|
|
230
|
+
// of rewinding; momentumScrollEnd completes the jump to the original.
|
|
197
231
|
offsetPageRef.current = total + 1;
|
|
232
|
+
pendingPageRef.current = total + 1;
|
|
198
233
|
scrollToPage(total + 1, true);
|
|
199
234
|
}, interval);
|
|
200
235
|
return () => clearInterval(timer);
|
|
@@ -1,72 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import type { ViewStyle } from 'react-native';
|
|
3
|
-
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
-
import {
|
|
5
|
-
UIProvider,
|
|
6
|
-
useInsets,
|
|
7
|
-
type ModalSafeAreaBoundaryProps,
|
|
8
|
-
type UIProviderProps,
|
|
9
|
-
} from '../theme/UIProvider';
|
|
10
|
-
import type { EdgeInsets } from '../theme/insets';
|
|
1
|
+
import { UIProvider, type UIProviderProps } from '../theme/UIProvider';
|
|
11
2
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated Use `UIProvider` from 'orn-ui': it now measures the safe area
|
|
5
|
+
* insets itself (react-native-safe-area-context is a required peer). This
|
|
6
|
+
* alias stays for one minor version so existing imports keep working.
|
|
7
|
+
*/
|
|
8
|
+
export type SafeAreaUIProviderProps = UIProviderProps;
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function sameInsets(a: EdgeInsets, b: EdgeInsets) {
|
|
20
|
-
return a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function InsetsProbe({ onMeasure }: { onMeasure: (insets: EdgeInsets) => void }) {
|
|
24
|
-
const insets = useSafeAreaInsets();
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
onMeasure(insets);
|
|
27
|
-
}, [insets, onMeasure]);
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function RemeasuringModalSafeAreaBoundary({ children }: ModalSafeAreaBoundaryProps) {
|
|
32
|
-
const ambient = useInsets();
|
|
33
|
-
const [measured, setMeasured] = useState<EdgeInsets | null>(null);
|
|
34
|
-
const onMeasure = React.useCallback(
|
|
35
|
-
(next: EdgeInsets) => setMeasured((prev) => (prev && sameInsets(prev, next) ? prev : next)),
|
|
36
|
-
[]
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<>
|
|
41
|
-
<SafeAreaProvider style={probeStyle} pointerEvents="none">
|
|
42
|
-
<InsetsProbe onMeasure={onMeasure} />
|
|
43
|
-
</SafeAreaProvider>
|
|
44
|
-
{children(measured ?? ambient)}
|
|
45
|
-
</>
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function Measured({ insets: override, children, ...rest }: SafeAreaUIProviderProps) {
|
|
50
|
-
const measured = useSafeAreaInsets();
|
|
51
|
-
return (
|
|
52
|
-
<UIProvider
|
|
53
|
-
insets={override ?? measured}
|
|
54
|
-
ModalSafeAreaBoundary={RemeasuringModalSafeAreaBoundary}
|
|
55
|
-
{...rest}
|
|
56
|
-
>
|
|
57
|
-
{children}
|
|
58
|
-
</UIProvider>
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function SafeAreaUIProvider({
|
|
63
|
-
mountSafeAreaProvider = true,
|
|
64
|
-
...props
|
|
65
|
-
}: SafeAreaUIProviderProps) {
|
|
66
|
-
if (!mountSafeAreaProvider) return <Measured {...props} />;
|
|
67
|
-
return (
|
|
68
|
-
<SafeAreaProvider>
|
|
69
|
-
<Measured {...props} />
|
|
70
|
-
</SafeAreaProvider>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
10
|
+
/** @deprecated Use `UIProvider` from 'orn-ui' — same component. */
|
|
11
|
+
export const SafeAreaUIProvider = UIProvider;
|
package/src/safe-area/index.ts
CHANGED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import React, { createContext, useContext, useEffect, useMemo, useRef, type ComponentRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
Animated,
|
|
4
|
+
Easing,
|
|
5
|
+
Keyboard,
|
|
6
|
+
Platform,
|
|
7
|
+
StyleSheet,
|
|
8
|
+
View,
|
|
9
|
+
type KeyboardEvent,
|
|
10
|
+
} from 'react-native';
|
|
11
|
+
import { useReduceMotion } from './useReduceMotion';
|
|
12
|
+
|
|
13
|
+
/** A focused field the host has to keep in view. */
|
|
14
|
+
export interface KeyboardField {
|
|
15
|
+
/** The field's box in window coordinates (label, field and error included). */
|
|
16
|
+
measure: () => Promise<{ y: number; height: number } | null>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface KeyboardHost {
|
|
20
|
+
focus: (field: KeyboardField) => void;
|
|
21
|
+
blur: (field: KeyboardField) => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const KeyboardHostContext = createContext<KeyboardHost | null>(null);
|
|
25
|
+
|
|
26
|
+
/** The active host, or null if a container already handles the keyboard (or it is off). */
|
|
27
|
+
export function useKeyboardHost(): KeyboardHost | null {
|
|
28
|
+
return useContext(KeyboardHostContext);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* For containers that already keep the focused field visible on their own:
|
|
33
|
+
* a Modal or BottomSheet (its own native window, which the root's shift
|
|
34
|
+
* doesn't move) or a ScrollView with `automaticallyAdjustKeyboardInsets`.
|
|
35
|
+
* Inside, Inputs ask nothing of the host and the keyboard isn't compensated
|
|
36
|
+
* twice.
|
|
37
|
+
*/
|
|
38
|
+
export function KeyboardHandled({ children }: { children: React.ReactNode }) {
|
|
39
|
+
return <KeyboardHostContext.Provider value={null}>{children}</KeyboardHostContext.Provider>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Duration when the keyboard event doesn't carry one (Android). */
|
|
43
|
+
const FALLBACK_DURATION = 250;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Vertical shift (≤ 0) so the whole field sits above the keyboard, with
|
|
47
|
+
* `margin` of room, without its top edge going past `topLimit`.
|
|
48
|
+
* `fieldY` is the position measured with the `current` shift applied.
|
|
49
|
+
* If the field is already visible, it moves back toward 0: it never rises more than needed.
|
|
50
|
+
*/
|
|
51
|
+
export function computeKeyboardOffset({
|
|
52
|
+
fieldY,
|
|
53
|
+
fieldHeight,
|
|
54
|
+
keyboardTop,
|
|
55
|
+
current,
|
|
56
|
+
margin,
|
|
57
|
+
topLimit,
|
|
58
|
+
}: {
|
|
59
|
+
fieldY: number;
|
|
60
|
+
fieldHeight: number;
|
|
61
|
+
keyboardTop: number;
|
|
62
|
+
current: number;
|
|
63
|
+
margin: number;
|
|
64
|
+
topLimit: number;
|
|
65
|
+
}): number {
|
|
66
|
+
const base = fieldY - current;
|
|
67
|
+
let target = Math.min(0, keyboardTop - margin - (base + fieldHeight));
|
|
68
|
+
// A field taller than the available gap: seeing where you type (its top
|
|
69
|
+
// part) takes priority over its error.
|
|
70
|
+
target = Math.max(target, topLimit - base);
|
|
71
|
+
return Math.min(0, target);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* An area that shifts so the focused Input inside it sits above the
|
|
76
|
+
* keyboard (transform on the native thread; it returns to 0 on close). It is
|
|
77
|
+
* Android's `adjustPan`, the same on both platforms.
|
|
78
|
+
*
|
|
79
|
+
* - The root UIProvider mounts one around the whole app: the fallback, so
|
|
80
|
+
* an Input is visible even when it isn't inside a Screen.
|
|
81
|
+
* - Screen mounts another around its content, with `clip`: only the content
|
|
82
|
+
* moves and the header (`header` prop) and the tab bar stay still, as in a
|
|
83
|
+
* native app. The Input registers with the nearest area, so inside a
|
|
84
|
+
* Screen the root doesn't move.
|
|
85
|
+
*
|
|
86
|
+
* With `clip`, whatever rises is clipped at the area's top edge and the field
|
|
87
|
+
* never goes above that edge (it stays under the header).
|
|
88
|
+
*/
|
|
89
|
+
export function KeyboardPanArea({
|
|
90
|
+
margin,
|
|
91
|
+
topLimit,
|
|
92
|
+
clip = false,
|
|
93
|
+
children,
|
|
94
|
+
}: {
|
|
95
|
+
margin: number;
|
|
96
|
+
/** Top limit in window coordinates. With `clip`, the area's edge is used if it is lower. */
|
|
97
|
+
topLimit: number;
|
|
98
|
+
clip?: boolean;
|
|
99
|
+
children: React.ReactNode;
|
|
100
|
+
}) {
|
|
101
|
+
const areaRef = useRef<ComponentRef<typeof View>>(null);
|
|
102
|
+
const pan = useRef(new Animated.Value(0)).current;
|
|
103
|
+
const offset = useRef(0);
|
|
104
|
+
const field = useRef<KeyboardField | null>(null);
|
|
105
|
+
const keyboardTop = useRef<number | null>(null);
|
|
106
|
+
const reduceMotion = useReduceMotion();
|
|
107
|
+
const config = useRef({ margin, topLimit, reduceMotion, clip });
|
|
108
|
+
config.current = { margin, topLimit, reduceMotion, clip };
|
|
109
|
+
|
|
110
|
+
const host = useMemo<KeyboardHost>(() => {
|
|
111
|
+
const animateTo = (to: number, duration: number) => {
|
|
112
|
+
if (to === offset.current) return;
|
|
113
|
+
offset.current = to;
|
|
114
|
+
Animated.timing(pan, {
|
|
115
|
+
toValue: to,
|
|
116
|
+
duration: config.current.reduceMotion ? 0 : duration,
|
|
117
|
+
easing: Easing.out(Easing.cubic),
|
|
118
|
+
useNativeDriver: true,
|
|
119
|
+
}).start();
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const adjust = async (duration: number) => {
|
|
123
|
+
const current = field.current;
|
|
124
|
+
const top = keyboardTop.current;
|
|
125
|
+
if (!current || top === null) return;
|
|
126
|
+
const box = await current.measure();
|
|
127
|
+
// While measuring, focus may have moved to another field or the keyboard closed.
|
|
128
|
+
if (!box || field.current !== current || keyboardTop.current === null) return;
|
|
129
|
+
let limit = config.current.topLimit;
|
|
130
|
+
if (config.current.clip) {
|
|
131
|
+
const areaTop = await measureTop(areaRef.current);
|
|
132
|
+
if (areaTop !== null) limit = Math.max(limit, areaTop);
|
|
133
|
+
}
|
|
134
|
+
animateTo(
|
|
135
|
+
computeKeyboardOffset({
|
|
136
|
+
fieldY: box.y,
|
|
137
|
+
fieldHeight: box.height,
|
|
138
|
+
keyboardTop: keyboardTop.current,
|
|
139
|
+
current: offset.current,
|
|
140
|
+
margin: config.current.margin,
|
|
141
|
+
topLimit: limit,
|
|
142
|
+
}),
|
|
143
|
+
duration
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return {
|
|
148
|
+
focus(next) {
|
|
149
|
+
field.current = next;
|
|
150
|
+
// With the keyboard already open (moving from one field to another) it readjusts right away.
|
|
151
|
+
if (keyboardTop.current !== null) void adjust(FALLBACK_DURATION);
|
|
152
|
+
},
|
|
153
|
+
blur(prev) {
|
|
154
|
+
if (field.current === prev) field.current = null;
|
|
155
|
+
},
|
|
156
|
+
// Internal use by the listeners below.
|
|
157
|
+
_show(e: KeyboardEvent | undefined) {
|
|
158
|
+
if (!e?.endCoordinates) return;
|
|
159
|
+
keyboardTop.current = e.endCoordinates.screenY;
|
|
160
|
+
const duration = e.duration || FALLBACK_DURATION;
|
|
161
|
+
// Android emits didShow after resizing the window: measure on the
|
|
162
|
+
// next frame, with the layout already settled.
|
|
163
|
+
if (Platform.OS === 'android') requestAnimationFrame(() => void adjust(duration));
|
|
164
|
+
else void adjust(duration);
|
|
165
|
+
},
|
|
166
|
+
_hide(e: KeyboardEvent | undefined) {
|
|
167
|
+
keyboardTop.current = null;
|
|
168
|
+
animateTo(0, e?.duration || FALLBACK_DURATION);
|
|
169
|
+
},
|
|
170
|
+
} as KeyboardHost & { _show: (e: KeyboardEvent) => void; _hide: (e?: KeyboardEvent) => void };
|
|
171
|
+
}, [pan]);
|
|
172
|
+
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
const h = host as KeyboardHost & { _show: (e: KeyboardEvent) => void; _hide: (e?: KeyboardEvent) => void };
|
|
175
|
+
// iOS notifies before animating (will*): the shift follows the keyboard.
|
|
176
|
+
// Android only has did*.
|
|
177
|
+
const subs =
|
|
178
|
+
Platform.OS === 'ios'
|
|
179
|
+
? [
|
|
180
|
+
Keyboard.addListener('keyboardWillShow', h._show),
|
|
181
|
+
Keyboard.addListener('keyboardWillChangeFrame', h._show),
|
|
182
|
+
Keyboard.addListener('keyboardWillHide', h._hide),
|
|
183
|
+
]
|
|
184
|
+
: [Keyboard.addListener('keyboardDidShow', h._show), Keyboard.addListener('keyboardDidHide', h._hide)];
|
|
185
|
+
return () => subs.forEach((s) => s.remove());
|
|
186
|
+
}, [host]);
|
|
187
|
+
|
|
188
|
+
const moving = <Animated.View style={[styles.fill, { transform: [{ translateY: pan }] }]}>{children}</Animated.View>;
|
|
189
|
+
return (
|
|
190
|
+
<KeyboardHostContext.Provider value={host}>
|
|
191
|
+
{clip ? (
|
|
192
|
+
<View ref={areaRef} style={[styles.fill, styles.clip]} collapsable={false}>
|
|
193
|
+
{moving}
|
|
194
|
+
</View>
|
|
195
|
+
) : (
|
|
196
|
+
moving
|
|
197
|
+
)}
|
|
198
|
+
</KeyboardHostContext.Provider>
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** If the measurement never comes back (node unmounted), carry on without that limit. */
|
|
203
|
+
const MEASURE_TIMEOUT_MS = 100;
|
|
204
|
+
|
|
205
|
+
function measureTop(node: ComponentRef<typeof View> | null): Promise<number | null> {
|
|
206
|
+
return new Promise((resolve) => {
|
|
207
|
+
if (!node) return resolve(null);
|
|
208
|
+
const timer = setTimeout(() => resolve(null), MEASURE_TIMEOUT_MS);
|
|
209
|
+
node.measureInWindow((_x, y) => {
|
|
210
|
+
clearTimeout(timer);
|
|
211
|
+
resolve(y);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const styles = StyleSheet.create({ fill: { flex: 1 }, clip: { overflow: 'hidden' } });
|