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/atoms/Fab.tsx
CHANGED
|
@@ -2,22 +2,43 @@ import React, { memo } from 'react';
|
|
|
2
2
|
import { type GestureResponderEvent, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
import { PressableScale } from './PressableScale';
|
|
4
4
|
import { Icon } from '../icons/Icon';
|
|
5
|
+
import { onColor } from '../icons/defaultIcons';
|
|
5
6
|
import type { IconName } from '../icons/types';
|
|
6
7
|
import { createStyles } from '../theme/createStyles';
|
|
7
|
-
import { useColors } from '../theme/UIProvider';
|
|
8
|
+
import { useColors, useInsets, useTheme } from '../theme/UIProvider';
|
|
8
9
|
|
|
9
10
|
export interface FabProps {
|
|
11
|
+
/** Called when the button is pressed. */
|
|
10
12
|
onPress: (e: GestureResponderEvent) => void;
|
|
13
|
+
/** Built-in or custom icon name. Ignored when `icon` is passed. @default 'plus' */
|
|
11
14
|
iconName?: IconName;
|
|
15
|
+
/** Any node in place of the icon. */
|
|
12
16
|
icon?: React.ReactNode;
|
|
17
|
+
/** Diameter in pt. @default 60 */
|
|
13
18
|
size?: number;
|
|
19
|
+
/** Distance from the bottom edge, on top of the safe area. @default tokens.spacing.xl (20) */
|
|
14
20
|
bottom?: number;
|
|
21
|
+
/** Distance from the right edge, on top of the safe area. @default tokens.spacing.xl (20) */
|
|
15
22
|
right?: number;
|
|
23
|
+
/**
|
|
24
|
+
* Adds the safe-area insets to `bottom`/`right`, so the button clears the
|
|
25
|
+
* home indicator. Pass false above a NavigationBar or tab bar, which
|
|
26
|
+
* already covers that edge. @default true
|
|
27
|
+
*/
|
|
28
|
+
safeArea?: boolean;
|
|
29
|
+
/** Fill color. The icon switches to black or white for contrast. @default theme.colors.primary */
|
|
16
30
|
color?: string;
|
|
17
31
|
style?: StyleProp<ViewStyle>;
|
|
32
|
+
/** Required: the button has no visible text. */
|
|
18
33
|
accessibilityLabel: string;
|
|
34
|
+
testID?: string;
|
|
19
35
|
}
|
|
20
36
|
|
|
37
|
+
/** Default diameter: comfortably above the 44pt touch minimum (Fitts). */
|
|
38
|
+
const DEFAULT_SIZE = 60;
|
|
39
|
+
/** The glyph takes up half the circle. */
|
|
40
|
+
const ICON_RATIO = 0.5;
|
|
41
|
+
|
|
21
42
|
const useStyles = createStyles((theme) => ({
|
|
22
43
|
fab: {
|
|
23
44
|
position: 'absolute',
|
|
@@ -29,14 +50,39 @@ const useStyles = createStyles((theme) => ({
|
|
|
29
50
|
|
|
30
51
|
/**
|
|
31
52
|
* Fab
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* offset (
|
|
53
|
+
* Circular floating button for the screen's main action.
|
|
54
|
+
* `bottom`/`right` instead of the required `tabBarHeight` of the original
|
|
55
|
+
* version — the consumer decides its own offset (with or without a tab bar).
|
|
56
|
+
*
|
|
57
|
+
* Gestalt, figure/ground: it is the only thing that floats (`lg` shadow) and
|
|
58
|
+
* carries the accent, so it stands apart from the content passing beneath it
|
|
59
|
+
* (Von Restorff: one per screen). Fitts: large and in the thumb's corner,
|
|
60
|
+
* above the safe area so it doesn't compete with the home gesture.
|
|
35
61
|
*/
|
|
36
62
|
export const Fab = memo(
|
|
37
|
-
({
|
|
63
|
+
({
|
|
64
|
+
onPress,
|
|
65
|
+
iconName = 'plus',
|
|
66
|
+
icon,
|
|
67
|
+
size = DEFAULT_SIZE,
|
|
68
|
+
bottom,
|
|
69
|
+
right,
|
|
70
|
+
safeArea = true,
|
|
71
|
+
color,
|
|
72
|
+
style,
|
|
73
|
+
accessibilityLabel,
|
|
74
|
+
testID,
|
|
75
|
+
}: FabProps) => {
|
|
38
76
|
const styles = useStyles();
|
|
39
77
|
const colors = useColors();
|
|
78
|
+
const theme = useTheme();
|
|
79
|
+
const insets = useInsets();
|
|
80
|
+
const fill = color ?? colors.primary;
|
|
81
|
+
// With the theme color, its `onPrimary`; with a custom one, black or white
|
|
82
|
+
// depending on contrast (a cyan with a white icon was unreadable).
|
|
83
|
+
const glyph = color ? onColor(color) : colors.onPrimary;
|
|
84
|
+
const edge = theme.tokens.spacing.xl;
|
|
85
|
+
|
|
40
86
|
return (
|
|
41
87
|
<PressableScale
|
|
42
88
|
onPress={onPress}
|
|
@@ -46,16 +92,17 @@ export const Fab = memo(
|
|
|
46
92
|
width: size,
|
|
47
93
|
height: size,
|
|
48
94
|
borderRadius: size / 2,
|
|
49
|
-
bottom,
|
|
50
|
-
right,
|
|
51
|
-
backgroundColor:
|
|
95
|
+
bottom: (bottom ?? edge) + (safeArea ? insets.bottom : 0),
|
|
96
|
+
right: (right ?? edge) + (safeArea ? insets.right : 0),
|
|
97
|
+
backgroundColor: fill,
|
|
52
98
|
},
|
|
53
99
|
style,
|
|
54
100
|
]}
|
|
55
101
|
accessibilityRole="button"
|
|
56
102
|
accessibilityLabel={accessibilityLabel}
|
|
103
|
+
testID={testID}
|
|
57
104
|
>
|
|
58
|
-
{icon ?? <Icon name={iconName} size={size *
|
|
105
|
+
{icon ?? <Icon name={iconName} size={size * ICON_RATIO} color={glyph} />}
|
|
59
106
|
</PressableScale>
|
|
60
107
|
);
|
|
61
108
|
}
|
package/src/atoms/Gradient.tsx
CHANGED
|
@@ -1,60 +1,98 @@
|
|
|
1
|
-
import React, { memo, useMemo } from 'react';
|
|
2
|
-
import { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
1
|
+
import React, { memo, useMemo, useState } from 'react';
|
|
2
|
+
import { StyleSheet, View, type LayoutChangeEvent, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
|
|
4
4
|
export type GradientDirection = 'vertical' | 'horizontal' | 'diagonal' | 'diagonal-reverse';
|
|
5
5
|
|
|
6
6
|
export interface GradientProps {
|
|
7
|
-
/**
|
|
7
|
+
/** Gradient stops. A single color paints flat; none paints nothing. */
|
|
8
8
|
colors: string[];
|
|
9
9
|
/**
|
|
10
|
-
* 'vertical'
|
|
11
|
-
*
|
|
12
|
-
* arriba-derecha a abajo-izquierda.
|
|
10
|
+
* 'vertical' runs top to bottom, 'horizontal' left to right, 'diagonal'
|
|
11
|
+
* top-left to bottom-right and 'diagonal-reverse' top-right to bottom-left.
|
|
13
12
|
* @default 'vertical'
|
|
14
13
|
*/
|
|
15
14
|
direction?: GradientDirection;
|
|
16
15
|
/**
|
|
17
|
-
*
|
|
18
|
-
* =
|
|
19
|
-
* @default
|
|
16
|
+
* Bands per segment (a segment = a pair of consecutive colors). More bands
|
|
17
|
+
* = a smoother transition and more views in the tree.
|
|
18
|
+
* @default 48
|
|
20
19
|
*/
|
|
21
20
|
steps?: number;
|
|
22
|
-
/**
|
|
21
|
+
/** Content rendered on top of the gradient. */
|
|
23
22
|
children?: React.ReactNode;
|
|
24
23
|
style?: StyleProp<ViewStyle>;
|
|
25
24
|
testID?: string;
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
const DEFAULT_STEPS =
|
|
27
|
+
const DEFAULT_STEPS = 48;
|
|
29
28
|
|
|
30
29
|
const styles = StyleSheet.create({
|
|
31
|
-
//
|
|
30
|
+
// Clips the rotated plane of the diagonals and the gradient to the borderRadius.
|
|
32
31
|
root: { overflow: 'hidden' },
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
//
|
|
32
|
+
// Centered √2 plane: covers the corners of a SQUARE container without
|
|
33
|
+
// measuring it. Only used until the first onLayout; after that the plane is
|
|
34
|
+
// sized with the real diagonal (see `diagonalBox`).
|
|
36
35
|
diagonalPlane: { position: 'absolute', top: '-21%', left: '-21%', width: '142%', height: '142%' },
|
|
37
36
|
});
|
|
38
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Opacities of stacked layers: layer k (from 1 to n-1) starts at k/n and
|
|
40
|
+
* runs to the end of the segment; stacked with "over", the total opacity in
|
|
41
|
+
* band k is k/(n-1), same as side-by-side bands. The difference: no layer
|
|
42
|
+
* edge sits next to a gap, so the antialiasing of an edge (especially when
|
|
43
|
+
* rotated) blends with the color of the layer below and not with what is
|
|
44
|
+
* behind the gradient — without the thin lines between bands.
|
|
45
|
+
*/
|
|
46
|
+
function layerOpacities(n: number): number[] {
|
|
47
|
+
const out: number[] = [];
|
|
48
|
+
let prev = 0;
|
|
49
|
+
for (let k = 1; k < n; k += 1) {
|
|
50
|
+
const total = k / (n - 1);
|
|
51
|
+
out.push(prev >= 1 ? 1 : 1 - (1 - total) / (1 - prev));
|
|
52
|
+
prev = total;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Square with the diagonal as its side, centered: rotated 45° it covers any rectangle. */
|
|
58
|
+
function diagonalBox(width: number, height: number): ViewStyle {
|
|
59
|
+
const side = Math.hypot(width, height);
|
|
60
|
+
return { position: 'absolute', width: side, height: side, left: (width - side) / 2, top: (height - side) / 2 };
|
|
61
|
+
}
|
|
62
|
+
|
|
39
63
|
/**
|
|
40
64
|
* Gradient
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
65
|
+
* Dependency-free linear gradient: React Native doesn't ship one in the
|
|
66
|
+
* supported range (Expo SDK 54–57) and `experimental_backgroundImage` isn't
|
|
67
|
+
* available across that whole window, so it is composed from bands.
|
|
68
|
+
*
|
|
69
|
+
* Each segment paints the start color and, on top, layers of the end color
|
|
70
|
+
* that accumulate (see `layerOpacities`). The compositor blends alpha linearly:
|
|
71
|
+
* the result is the sRGB interpolation between stops without parsing the
|
|
72
|
+
* color, which is why any format RN accepts works (hex, `rgba()`, name). The
|
|
73
|
+
* layers run to the end of the plane so no thin lines are left between
|
|
74
|
+
* bands, and the diagonals rotate a square the size of the measured diagonal
|
|
75
|
+
* to cover any rectangle, not just squares.
|
|
44
76
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* cualquier formato que acepte RN (hex, `rgba()`, nombre).
|
|
77
|
+
* Gestalt, figure and ground: content on top must contrast with ALL the
|
|
78
|
+
* stops, not just the first — white text that reads well over the blue at
|
|
79
|
+
* the start can get lost over the light blue at the end.
|
|
49
80
|
*/
|
|
50
81
|
export const Gradient = memo(
|
|
51
82
|
({ colors, direction = 'vertical', steps = DEFAULT_STEPS, children, style, testID }: GradientProps) => {
|
|
52
83
|
const isRow = direction === 'horizontal';
|
|
53
84
|
const isDiagonal = direction === 'diagonal' || direction === 'diagonal-reverse';
|
|
54
|
-
// rotate
|
|
55
|
-
//
|
|
85
|
+
// positive rotate turns clockwise (Y grows downward): -45° sends the
|
|
86
|
+
// gradient axis down-right.
|
|
56
87
|
const rotate = direction === 'diagonal' ? '-45deg' : '45deg';
|
|
57
88
|
const bandCount = Math.max(2, Math.floor(steps));
|
|
89
|
+
const [size, setSize] = useState<{ width: number; height: number } | null>(null);
|
|
90
|
+
const onLayout = isDiagonal
|
|
91
|
+
? (e: LayoutChangeEvent) => {
|
|
92
|
+
const { width, height } = e.nativeEvent.layout;
|
|
93
|
+
setSize((prev) => (prev && prev.width === width && prev.height === height ? prev : { width, height }));
|
|
94
|
+
}
|
|
95
|
+
: undefined;
|
|
58
96
|
|
|
59
97
|
const painted = useMemo(() => {
|
|
60
98
|
if (colors.length === 0) return null;
|
|
@@ -62,32 +100,45 @@ export const Gradient = memo(
|
|
|
62
100
|
return <View style={[StyleSheet.absoluteFill, { backgroundColor: colors[0] }]} />;
|
|
63
101
|
}
|
|
64
102
|
|
|
65
|
-
const
|
|
103
|
+
const segmentCount = colors.length - 1;
|
|
104
|
+
const opacities = layerOpacities(bandCount);
|
|
105
|
+
// From `start` (fraction of the axis) to the end of the plane.
|
|
106
|
+
const from = (start: number): ViewStyle =>
|
|
107
|
+
isRow
|
|
108
|
+
? { position: 'absolute', top: 0, bottom: 0, right: 0, left: `${start * 100}%` }
|
|
109
|
+
: { position: 'absolute', left: 0, right: 0, bottom: 0, top: `${start * 100}%` };
|
|
110
|
+
|
|
111
|
+
// Segments are stacked too: each one covers the previous from its start,
|
|
112
|
+
// and since it begins with the color the previous one ended with, the
|
|
113
|
+
// edge between segments doesn't show the background.
|
|
114
|
+
const segments = colors.slice(0, -1).map((start, index) => {
|
|
66
115
|
const to = colors[index + 1] as string;
|
|
116
|
+
const segStart = index / segmentCount;
|
|
117
|
+
const segLength = 1 / segmentCount;
|
|
118
|
+
// The segment runs from segStart to the END of the plane; its layers
|
|
119
|
+
// sit at fractions of that remaining length.
|
|
120
|
+
const rest = 1 - segStart;
|
|
67
121
|
return (
|
|
68
|
-
<View
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
122
|
+
<View key={`${start}-${to}-${index}`} style={[from(segStart), { backgroundColor: start }]}>
|
|
123
|
+
{opacities.map((opacity, k) => (
|
|
124
|
+
<View
|
|
125
|
+
key={k}
|
|
126
|
+
style={[from((((k + 1) / bandCount) * segLength) / rest), { backgroundColor: to, opacity }]}
|
|
127
|
+
/>
|
|
74
128
|
))}
|
|
75
129
|
</View>
|
|
76
130
|
);
|
|
77
131
|
});
|
|
78
132
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (!isDiagonal) return stack;
|
|
84
|
-
return <View style={[styles.diagonalPlane, { transform: [{ rotate }] }]}>{segments}</View>;
|
|
85
|
-
}, [colors, isRow, isDiagonal, rotate, bandCount]);
|
|
133
|
+
if (!isDiagonal) return <View style={StyleSheet.absoluteFill}>{segments}</View>;
|
|
134
|
+
const plane = size ? diagonalBox(size.width, size.height) : styles.diagonalPlane;
|
|
135
|
+
return <View style={[plane, { transform: [{ rotate }] }]}>{segments}</View>;
|
|
136
|
+
}, [colors, isRow, isDiagonal, rotate, bandCount, size]);
|
|
86
137
|
|
|
87
138
|
return (
|
|
88
|
-
<View testID={testID} style={[styles.root, style]}>
|
|
89
|
-
{/* pointerEvents
|
|
90
|
-
|
|
139
|
+
<View testID={testID} style={[styles.root, style]} onLayout={onLayout}>
|
|
140
|
+
{/* pointerEvents goes on the painted layer, not the root: the gradient
|
|
141
|
+
must not steal touches from whatever the consumer places on top. */}
|
|
91
142
|
<View style={StyleSheet.absoluteFill} pointerEvents="none">
|
|
92
143
|
{painted}
|
|
93
144
|
</View>
|
package/src/atoms/IconButton.tsx
CHANGED
|
@@ -4,15 +4,23 @@ import { PressableScale } from './PressableScale';
|
|
|
4
4
|
import { Icon } from '../icons/Icon';
|
|
5
5
|
import type { IconName } from '../icons/types';
|
|
6
6
|
import { createStyles } from '../theme/createStyles';
|
|
7
|
+
import { useTheme } from '../theme/UIProvider';
|
|
7
8
|
|
|
8
9
|
export interface IconButtonProps {
|
|
10
|
+
/** Icon from the library's set. Ignored when `icon` is passed. */
|
|
9
11
|
iconName?: IconName;
|
|
12
|
+
/** Custom node in place of the icon. Takes precedence over `iconName`. */
|
|
10
13
|
icon?: React.ReactNode;
|
|
14
|
+
/** Called on press. Not called while `disabled`. */
|
|
11
15
|
onPress?: (e: GestureResponderEvent) => void;
|
|
16
|
+
/** Icon size in pt. The touch area is padded up to 44pt with `hitSlop`. @default 24 */
|
|
12
17
|
size?: number;
|
|
18
|
+
/** Icon color. Defaults to `colors.text`. */
|
|
13
19
|
color?: string;
|
|
20
|
+
/** Dims the button by half and ignores presses. */
|
|
14
21
|
disabled?: boolean;
|
|
15
22
|
style?: StyleProp<ViewStyle>;
|
|
23
|
+
/** Required: the button has no visible text, so this is all a screen reader announces. */
|
|
16
24
|
accessibilityLabel: string;
|
|
17
25
|
testID?: string;
|
|
18
26
|
}
|
|
@@ -25,20 +33,35 @@ const useStyles = createStyles((theme) => ({
|
|
|
25
33
|
},
|
|
26
34
|
}));
|
|
27
35
|
|
|
36
|
+
/** Minimum touch area recommended by Apple (44pt) and Material (48dp ≈ 44pt). */
|
|
37
|
+
const MIN_TOUCH = 44;
|
|
38
|
+
|
|
28
39
|
/**
|
|
29
40
|
* IconButton
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
41
|
+
* Icon-only button. `accessibilityLabel` is required: with no visible text,
|
|
42
|
+
* it is the only way for a screen reader to announce what it does.
|
|
43
|
+
*
|
|
44
|
+
* Fitts: the visible area is icon + `spacing.sm` per side (24 + 16 = 40pt
|
|
45
|
+
* with the default size, 32pt with `size={16}`). `hitSlop` makes up the
|
|
46
|
+
* rest up to 44pt without enlarging the layout, so a row of icons keeps its
|
|
47
|
+
* rhythm and each one is still easy to tap.
|
|
48
|
+
*
|
|
49
|
+
* Gestalt, figure and ground: it has no background of its own, the icon is
|
|
50
|
+
* the figure over whatever is behind it; that is why the default color is
|
|
51
|
+
* `colors.text` (guaranteed AA contrast) and `disabled` dims it by half.
|
|
34
52
|
*/
|
|
35
53
|
export const IconButton = memo(
|
|
36
54
|
({ iconName, icon, onPress, size = 24, color, disabled, style, accessibilityLabel, testID }: IconButtonProps) => {
|
|
37
55
|
const styles = useStyles();
|
|
56
|
+
const theme = useTheme();
|
|
57
|
+
const visible = size + theme.tokens.spacing.sm * 2;
|
|
58
|
+
const extra = Math.max(0, Math.ceil((MIN_TOUCH - visible) / 2));
|
|
59
|
+
const hitSlop = extra > 0 ? { top: extra, bottom: extra, left: extra, right: extra } : undefined;
|
|
38
60
|
return (
|
|
39
61
|
<PressableScale
|
|
40
62
|
onPress={onPress}
|
|
41
63
|
disabled={disabled}
|
|
64
|
+
hitSlop={hitSlop}
|
|
42
65
|
style={[styles.hitArea, { opacity: disabled ? 0.5 : 1 }, style]}
|
|
43
66
|
accessibilityRole="button"
|
|
44
67
|
accessibilityLabel={accessibilityLabel}
|
package/src/atoms/Image.tsx
CHANGED
|
@@ -4,27 +4,38 @@ import {
|
|
|
4
4
|
Platform,
|
|
5
5
|
StyleSheet,
|
|
6
6
|
View,
|
|
7
|
-
type
|
|
7
|
+
type ImageProps as RNImageProps,
|
|
8
8
|
type ImageResizeMode,
|
|
9
9
|
type ImageSourcePropType,
|
|
10
|
-
type NativeSyntheticEvent,
|
|
11
10
|
type StyleProp,
|
|
12
11
|
type ViewStyle,
|
|
13
12
|
} from 'react-native';
|
|
14
13
|
import { createStyles } from '../theme/createStyles';
|
|
14
|
+
import { useColors, useTheme } from '../theme/UIProvider';
|
|
15
|
+
import { Icon } from '../icons/Icon';
|
|
15
16
|
import { Spinner } from './Spinner';
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* The event RN's Image passes to `onError`. Taken from its own prop type:
|
|
20
|
+
* react-native 0.88 (Expo SDK 58) renamed the exported name
|
|
21
|
+
* (`ImageErrorEventData` -> `ImageErrorEvent`).
|
|
22
|
+
*/
|
|
23
|
+
type ImageErrorEvent = Parameters<NonNullable<RNImageProps['onError']>>[0];
|
|
24
|
+
|
|
17
25
|
export interface ImageProps {
|
|
26
|
+
/** Image to load (same as React Native's `source`). */
|
|
18
27
|
source: ImageSourcePropType;
|
|
28
|
+
/** Width of the image slot, in pt. */
|
|
19
29
|
width?: number;
|
|
30
|
+
/** Height of the image slot, in pt. */
|
|
20
31
|
height?: number;
|
|
21
|
-
/** @default 'cover' */
|
|
32
|
+
/** How the image fits its slot (same as React Native). @default 'cover' */
|
|
22
33
|
resizeMode?: ImageResizeMode;
|
|
23
34
|
/** Corner radius, same pattern as Avatar/Card. @default 0 */
|
|
24
35
|
radius?: number;
|
|
25
36
|
/** What to show while loading. `false` to show nothing. @default true (small spinner) */
|
|
26
37
|
loading?: React.ReactNode | boolean;
|
|
27
|
-
/** What to show if loading fails. @default
|
|
38
|
+
/** What to show if loading fails. @default placeholder with a warning icon */
|
|
28
39
|
fallback?: React.ReactNode;
|
|
29
40
|
/**
|
|
30
41
|
* 'high' triggers Image.prefetch() on mount, before <Image> starts
|
|
@@ -34,15 +45,22 @@ export interface ImageProps {
|
|
|
34
45
|
*/
|
|
35
46
|
priority?: 'low' | 'normal' | 'high';
|
|
36
47
|
style?: StyleProp<ViewStyle>;
|
|
48
|
+
/** Called when loading finishes, successfully or not (same as RN). */
|
|
37
49
|
onLoadEnd?: () => void;
|
|
38
|
-
|
|
50
|
+
/** Describes the image for screen readers. Without it the image is decorative. */
|
|
51
|
+
accessibilityLabel?: string;
|
|
52
|
+
/** Called when loading fails; the `fallback` is shown. */
|
|
53
|
+
onError?: (error: ImageErrorEvent) => void;
|
|
39
54
|
testID?: string;
|
|
40
55
|
}
|
|
41
56
|
|
|
42
57
|
const useStyles = createStyles((theme) => ({
|
|
43
|
-
container: { overflow: 'hidden'
|
|
58
|
+
container: { overflow: 'hidden' },
|
|
59
|
+
// Only while loading or on failure: once the image has loaded, a PNG with
|
|
60
|
+
// transparency (a logo) let this gray show through.
|
|
61
|
+
placeholder: { backgroundColor: theme.colors.skeleton },
|
|
44
62
|
overlay: { alignItems: 'center', justifyContent: 'center' },
|
|
45
|
-
fallback: { flex: 1, backgroundColor: theme.colors.skeleton },
|
|
63
|
+
fallback: { flex: 1, backgroundColor: theme.colors.skeleton, alignItems: 'center', justifyContent: 'center' },
|
|
46
64
|
}));
|
|
47
65
|
|
|
48
66
|
function sourceUri(source: ImageSourcePropType): string | undefined {
|
|
@@ -51,14 +69,22 @@ function sourceUri(source: ImageSourcePropType): string | undefined {
|
|
|
51
69
|
|
|
52
70
|
/**
|
|
53
71
|
* Image
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* `priority="high"`
|
|
57
|
-
* cache
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
72
|
+
* Zero-dependency wrapper over RN's <Image>: adds loading and error state
|
|
73
|
+
* (with the same placeholders as the rest of the library), and exposes
|
|
74
|
+
* `priority="high"` to start the download early via Image.prefetch(). The
|
|
75
|
+
* actual cache (disk/memory) is handled by RN's native image engine — this
|
|
76
|
+
* doesn't reimplement it, it just keeps it from being accidentally turned off:
|
|
77
|
+
* on iOS it forces `cache="force-cache"` (uses the disk even when the HTTP
|
|
78
|
+
* header doesn't ask for it); on Android the native image's disk cache is
|
|
79
|
+
* always on, there is no equivalent knob to touch.
|
|
80
|
+
*
|
|
81
|
+
* Gestalt, closure: the container takes its final size from the first frame
|
|
82
|
+
* (`skeleton` background), so the layout doesn't jump when the image arrives
|
|
83
|
+
* and the eye completes the shape it will fill. If loading fails, the same
|
|
84
|
+
* slot shows a warning icon: the state is visible, not a silent gray.
|
|
85
|
+
*
|
|
86
|
+
* Success is detected with `onLoad`, not `onLoadEnd`: RN also calls
|
|
87
|
+
* `onLoadEnd` on failure, and using it for "loaded" overwrote the error.
|
|
62
88
|
*/
|
|
63
89
|
export const Image = memo(
|
|
64
90
|
({
|
|
@@ -74,14 +100,17 @@ export const Image = memo(
|
|
|
74
100
|
onLoadEnd,
|
|
75
101
|
onError,
|
|
76
102
|
testID,
|
|
103
|
+
accessibilityLabel,
|
|
77
104
|
}: ImageProps) => {
|
|
78
105
|
const styles = useStyles();
|
|
106
|
+
const colors = useColors();
|
|
107
|
+
const theme = useTheme();
|
|
79
108
|
const [status, setStatus] = useState<'loading' | 'loaded' | 'error'>('loading');
|
|
80
109
|
const uri = sourceUri(source);
|
|
81
110
|
|
|
82
111
|
useEffect(() => {
|
|
83
|
-
//
|
|
84
|
-
// source
|
|
112
|
+
// Resets the state if the image changes (same Image instance, different
|
|
113
|
+
// source: e.g. one user's avatar to another's in the same row).
|
|
85
114
|
setStatus('loading');
|
|
86
115
|
}, [uri ?? source]);
|
|
87
116
|
|
|
@@ -92,28 +121,34 @@ export const Image = memo(
|
|
|
92
121
|
}, [priority, uri]);
|
|
93
122
|
|
|
94
123
|
const handleError = useCallback(
|
|
95
|
-
(e:
|
|
124
|
+
(e: ImageErrorEvent) => {
|
|
96
125
|
setStatus('error');
|
|
97
126
|
onError?.(e);
|
|
98
127
|
},
|
|
99
128
|
[onError]
|
|
100
129
|
);
|
|
101
130
|
|
|
102
|
-
const
|
|
131
|
+
const handleLoad = useCallback(() => {
|
|
103
132
|
setStatus('loaded');
|
|
104
|
-
|
|
105
|
-
}, [onLoadEnd]);
|
|
133
|
+
}, []);
|
|
106
134
|
|
|
107
135
|
return (
|
|
108
|
-
<View
|
|
136
|
+
<View
|
|
137
|
+
style={[styles.container, status !== 'loaded' && styles.placeholder, { width, height, borderRadius: radius }, style]}
|
|
138
|
+
testID={testID}
|
|
139
|
+
accessible={!!accessibilityLabel}
|
|
140
|
+
accessibilityRole={accessibilityLabel ? 'image' : undefined}
|
|
141
|
+
accessibilityLabel={accessibilityLabel}
|
|
142
|
+
>
|
|
109
143
|
{status !== 'error' && (
|
|
110
144
|
<RNImage
|
|
111
145
|
source={source}
|
|
112
146
|
resizeMode={resizeMode}
|
|
113
147
|
style={StyleSheet.absoluteFill}
|
|
114
|
-
fadeDuration={Platform.OS === 'android' ?
|
|
148
|
+
fadeDuration={Platform.OS === 'android' ? theme.tokens.duration.fast : undefined}
|
|
115
149
|
{...(Platform.OS === 'ios' ? { cache: 'force-cache' as const } : null)}
|
|
116
|
-
|
|
150
|
+
onLoad={handleLoad}
|
|
151
|
+
onLoadEnd={onLoadEnd}
|
|
117
152
|
onError={handleError}
|
|
118
153
|
/>
|
|
119
154
|
)}
|
|
@@ -122,7 +157,18 @@ export const Image = memo(
|
|
|
122
157
|
{loading === true ? <Spinner size="small" fullscreen={false} /> : loading}
|
|
123
158
|
</View>
|
|
124
159
|
)}
|
|
125
|
-
{status === 'error' && (
|
|
160
|
+
{status === 'error' && (
|
|
161
|
+
// Custom fallback or the default: always centered in the slot.
|
|
162
|
+
<View style={styles.fallback}>
|
|
163
|
+
{fallback ?? (
|
|
164
|
+
<Icon
|
|
165
|
+
name="warning"
|
|
166
|
+
size={Math.max(16, Math.min(32, Math.round(Math.min(width ?? 64, height ?? 64) * 0.3)))}
|
|
167
|
+
color={colors.textLight}
|
|
168
|
+
/>
|
|
169
|
+
)}
|
|
170
|
+
</View>
|
|
171
|
+
)}
|
|
126
172
|
</View>
|
|
127
173
|
);
|
|
128
174
|
}
|
|
@@ -130,8 +176,8 @@ export const Image = memo(
|
|
|
130
176
|
Image.displayName = 'Image';
|
|
131
177
|
|
|
132
178
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* Image.prefetch
|
|
179
|
+
* Preloads a URL before mounting the component (e.g. on receiving a list
|
|
180
|
+
* response, before navigating to the detail). Re-exports RN's
|
|
181
|
+
* Image.prefetch — there is nothing zero-dep to add on top.
|
|
136
182
|
*/
|
|
137
183
|
export const prefetchImage = RNImage.prefetch;
|