orn-ui 0.2.9 → 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 +67 -52
- package/README.md +5 -9
- 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 +197 -156
- 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 +199 -158
- 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 +223 -165
- package/src/organisms/DateField.tsx +40 -15
- package/src/organisms/DatePicker.tsx +53 -32
- package/src/organisms/List.tsx +64 -15
- package/src/organisms/Modal.tsx +122 -63
- package/src/organisms/NavigationBar.tsx +73 -23
- package/src/organisms/OptionWheel.tsx +70 -66
- package/src/organisms/ReorderableList.tsx +49 -27
- package/src/organisms/Screen.tsx +79 -42
- package/src/organisms/SearchList.tsx +84 -20
- package/src/organisms/Select.tsx +63 -29
- package/src/organisms/Slides.tsx +63 -44
- package/src/organisms/ThemeToggle.tsx +15 -6
- package/src/organisms/Timeline.tsx +79 -62
- package/src/organisms/Toast.tsx +50 -15
- package/src/organisms/ToastProvider.tsx +17 -13
- package/src/organisms/Wizard.tsx +58 -21
- package/src/organisms/chart/frame.tsx +35 -35
- package/src/organisms/chart/marks.tsx +53 -53
- package/src/organisms/chart/math.ts +93 -94
- package/src/organisms/chart/palette.ts +28 -28
- package/src/organisms/imperativeBridge.ts +5 -5
- package/src/organisms/useSlides.ts +66 -31
- package/src/safe-area/SafeAreaUIProvider.tsx +9 -70
- package/src/safe-area/index.ts +1 -0
- package/src/theme/KeyboardAvoidance.tsx +216 -0
- package/src/theme/NativeOverlay.tsx +269 -0
- package/src/theme/UIProvider.tsx +109 -46
- package/src/theme/colors.ts +21 -21
- package/src/theme/createStyles.ts +23 -19
- package/src/theme/createTheme.ts +6 -6
- package/src/theme/index.ts +1 -1
- package/src/theme/insets.ts +1 -1
- package/src/theme/labels.ts +85 -2
- package/src/theme/palettes.ts +33 -25
- package/src/theme/tokens.ts +27 -13
- package/src/theme/types.ts +7 -7
- package/src/theme/useKeyboardField.ts +33 -0
- package/src/theme/useReduceMotion.ts +27 -0
package/src/organisms/Slides.tsx
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type ViewStyle,
|
|
12
12
|
} from 'react-native';
|
|
13
13
|
import { createStyles } from '../theme/createStyles';
|
|
14
|
-
import { useAllowFontScaling, useColors, useTheme } from '../theme/UIProvider';
|
|
14
|
+
import { useAllowFontScaling, useColors, useLabels, useTheme } from '../theme/UIProvider';
|
|
15
15
|
import { useReduceMotion } from '../atoms/Transition';
|
|
16
16
|
import { Gradient, type GradientDirection } from '../atoms/Gradient';
|
|
17
17
|
import { useSlides, type SlidesOrientation } from './useSlides';
|
|
@@ -20,53 +20,59 @@ export type { SlidesOrientation } from './useSlides';
|
|
|
20
20
|
export type SlidesIndicators = 'dots' | 'numbers' | 'none';
|
|
21
21
|
export type SlidesIndicatorPlacement = 'overlay' | 'outside';
|
|
22
22
|
|
|
23
|
-
/**
|
|
23
|
+
/** A solid color, or two or more for a gradient (see `Gradient`). */
|
|
24
24
|
export type SlideBackground = string | string[];
|
|
25
25
|
|
|
26
26
|
export interface SlidesProps<T> {
|
|
27
|
+
/** One item per slide. */
|
|
27
28
|
data: T[];
|
|
29
|
+
/** Stable key per item. */
|
|
28
30
|
keyExtractor: (item: T, index: number) => string;
|
|
29
|
-
/**
|
|
31
|
+
/** Slide content: images, buttons, anything. Drawn on top of `background`. */
|
|
30
32
|
renderItem: (item: T, index: number) => React.ReactNode;
|
|
31
|
-
/**
|
|
33
|
+
/** Per-slide background: `'#101014'` paints flat, `['#004cef', '#00cae1']` paints a gradient. */
|
|
32
34
|
background?: (item: T, index: number) => SlideBackground | undefined;
|
|
33
|
-
/**
|
|
35
|
+
/** Gradient direction when `background` returns several colors. @default 'vertical' */
|
|
34
36
|
gradientDirection?: GradientDirection;
|
|
35
|
-
/** @default 'horizontal' */
|
|
37
|
+
/** Direction of the swipe. @default 'horizontal' */
|
|
36
38
|
orientation?: SlidesOrientation;
|
|
37
|
-
/**
|
|
39
|
+
/** Dots, numbered dots, or none. @default 'dots' */
|
|
38
40
|
indicators?: SlidesIndicators;
|
|
39
41
|
/**
|
|
40
|
-
* 'overlay'
|
|
41
|
-
*
|
|
42
|
+
* 'overlay' places them on the slide, in white; 'outside' moves them out of
|
|
43
|
+
* the swipeable area, in theme colors.
|
|
42
44
|
* @default 'overlay'
|
|
43
45
|
*/
|
|
44
46
|
indicatorPlacement?: SlidesIndicatorPlacement;
|
|
45
|
-
/**
|
|
47
|
+
/** After the last slide, wraps to the first (and vice versa). @default false */
|
|
46
48
|
loop?: boolean;
|
|
47
|
-
/**
|
|
49
|
+
/** Advances automatically. Pauses while a finger is dragging. @default false */
|
|
48
50
|
autoPlay?: boolean;
|
|
49
|
-
/**
|
|
51
|
+
/** Milliseconds between `autoPlay` advances. @default 4000 */
|
|
50
52
|
interval?: number;
|
|
51
53
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
54
|
+
* Button that pauses auto-advance. Only shown with `autoPlay`; on by default
|
|
55
|
+
* because content that moves on its own needs a way to pause it
|
|
56
|
+
* (WCAG 2.2.2).
|
|
55
57
|
* @default true
|
|
56
58
|
*/
|
|
57
59
|
showAutoPlayToggle?: boolean;
|
|
58
|
-
/**
|
|
60
|
+
/** Gap between slides, in px. At 0 they touch. @default 0 */
|
|
59
61
|
spacing?: number;
|
|
60
|
-
/**
|
|
62
|
+
/** Controlled index. Without it, the component manages its own from `defaultIndex`. */
|
|
61
63
|
index?: number;
|
|
62
|
-
/** @default 0 */
|
|
64
|
+
/** Starting slide when the index is uncontrolled. @default 0 */
|
|
63
65
|
defaultIndex?: number;
|
|
66
|
+
/** Called with the new index when the active slide changes. */
|
|
64
67
|
onIndexChange?: (index: number) => void;
|
|
65
|
-
/**
|
|
68
|
+
/** Height of the swipeable area. @default 240 */
|
|
66
69
|
height?: number;
|
|
67
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Lets the user swipe between slides. When false, they change only through the indicators,
|
|
72
|
+
* `autoPlay` or `index`. @default true
|
|
73
|
+
*/
|
|
68
74
|
swipeEnabled?: boolean;
|
|
69
|
-
/**
|
|
75
|
+
/** Styles for each slide's visible box — padding, alignment, radius. */
|
|
70
76
|
slideStyle?: StyleProp<ViewStyle>;
|
|
71
77
|
style?: StyleProp<ViewStyle>;
|
|
72
78
|
testID?: string;
|
|
@@ -80,15 +86,15 @@ const DEFAULT_HEIGHT = 240;
|
|
|
80
86
|
const DEFAULT_INTERVAL = 4000;
|
|
81
87
|
|
|
82
88
|
const useStyles = createStyles((theme) => ({
|
|
83
|
-
//
|
|
89
|
+
// Lets the block be rounded via `style` without the gradient spilling out.
|
|
84
90
|
root: { overflow: 'hidden' },
|
|
85
91
|
viewport: { flex: 1 },
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
92
|
+
// The visible slide is the inner box: with `spacing` the page is wider
|
|
93
|
+
// than it, and the background has to be clipped here and not on the page, or
|
|
94
|
+
// the gradient paints the gap too.
|
|
89
95
|
slide: { flex: 1, overflow: 'hidden' },
|
|
90
|
-
//
|
|
91
|
-
//
|
|
96
|
+
// With indicators outside and vertical orientation the container is a row:
|
|
97
|
+
// without flex the window has no width of its own and collapses to 0.
|
|
92
98
|
viewportInRow: { flex: 1 },
|
|
93
99
|
slideContent: { flex: 1 },
|
|
94
100
|
|
|
@@ -115,7 +121,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
115
121
|
gap: 3,
|
|
116
122
|
},
|
|
117
123
|
pauseBar: { width: 3, height: 12, borderRadius: 1 },
|
|
118
|
-
//
|
|
124
|
+
// Triangle made of borders: a "play" without SVG or an icon set.
|
|
119
125
|
playTriangle: {
|
|
120
126
|
width: 0,
|
|
121
127
|
height: 0,
|
|
@@ -145,7 +151,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
145
151
|
interface DotProps {
|
|
146
152
|
selected: boolean;
|
|
147
153
|
isHorizontal: boolean;
|
|
148
|
-
/**
|
|
154
|
+
/** In overlay the contrast comes from opacity; outside, from color. */
|
|
149
155
|
overlay: boolean;
|
|
150
156
|
activeColor: string;
|
|
151
157
|
inactiveColor: string;
|
|
@@ -153,9 +159,9 @@ interface DotProps {
|
|
|
153
159
|
}
|
|
154
160
|
|
|
155
161
|
/**
|
|
156
|
-
*
|
|
157
|
-
* "
|
|
158
|
-
*
|
|
162
|
+
* The active dot stretches instead of jumping: an abrupt change reads as
|
|
163
|
+
* "another dot appeared", not as "the same one moved". Width and color are
|
|
164
|
+
* layout/paint props, so they go through the JS driver.
|
|
159
165
|
*/
|
|
160
166
|
const Dot = memo(({ selected, isHorizontal, overlay, activeColor, inactiveColor, testID }: DotProps) => {
|
|
161
167
|
const styles = useStyles();
|
|
@@ -191,13 +197,25 @@ Dot.displayName = 'SlidesDot';
|
|
|
191
197
|
|
|
192
198
|
/**
|
|
193
199
|
* Slides
|
|
194
|
-
*
|
|
195
|
-
* `renderItem`
|
|
196
|
-
*
|
|
200
|
+
* Carousel with its own background (flat color or gradient) and free-form
|
|
201
|
+
* content: `renderItem` decides whether an image, text or buttons go inside.
|
|
202
|
+
* The state lives in `useSlides`; only the tree is here.
|
|
203
|
+
*
|
|
204
|
+
* Sliding is a `ScrollView` with `pagingEnabled` instead of hand-made
|
|
205
|
+
* gestures: it is the only thing that gives native snapping on iOS and
|
|
206
|
+
* Android without `react-native-gesture-handler`, across the whole supported
|
|
207
|
+
* range of Expo SDKs.
|
|
197
208
|
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
*
|
|
209
|
+
* Design:
|
|
210
|
+
* - Jakob's law: native paging swipe and dots under the slide, like the
|
|
211
|
+
* system's own onboarding carousels.
|
|
212
|
+
* - Similarity + Von Restorff: every indicator looks the same except the
|
|
213
|
+
* current one.
|
|
214
|
+
* - Continuity: the slides slide (a jump with Reduce Motion, and autoPlay
|
|
215
|
+
* stops); infinite mode clones the edges so the swipe never rewinds.
|
|
216
|
+
* - Fitts's law: indicators have padding around the dot as touch area.
|
|
217
|
+
* - Screen readers: each indicator is "Slide n of total" (`labels.slideOf`),
|
|
218
|
+
* and autoPlay can be paused from its own button.
|
|
201
219
|
*/
|
|
202
220
|
export function Slides<T>({
|
|
203
221
|
data,
|
|
@@ -223,6 +241,7 @@ export function Slides<T>({
|
|
|
223
241
|
testID,
|
|
224
242
|
}: SlidesProps<T>) {
|
|
225
243
|
const colors = useColors();
|
|
244
|
+
const labels = useLabels();
|
|
226
245
|
const styles = useStyles();
|
|
227
246
|
const allowFontScaling = useAllowFontScaling();
|
|
228
247
|
|
|
@@ -296,7 +315,7 @@ export function Slides<T>({
|
|
|
296
315
|
);
|
|
297
316
|
};
|
|
298
317
|
|
|
299
|
-
//
|
|
318
|
+
// With reduce-motion autoPlay is already off: there is nothing to pause.
|
|
300
319
|
const renderAutoPlayToggle = () => {
|
|
301
320
|
if (!autoPlay || !showAutoPlayToggle || motionReduced || total < 2) return null;
|
|
302
321
|
return (
|
|
@@ -306,7 +325,7 @@ export function Slides<T>({
|
|
|
306
325
|
activeOpacity={0.7}
|
|
307
326
|
onPress={toggleAutoPlay}
|
|
308
327
|
accessibilityRole="button"
|
|
309
|
-
accessibilityLabel={autoPlayPaused ?
|
|
328
|
+
accessibilityLabel={autoPlayPaused ? labels.resumeSlides : labels.pauseSlides}
|
|
310
329
|
accessibilityState={{ selected: !autoPlayPaused }}
|
|
311
330
|
>
|
|
312
331
|
{autoPlayPaused ? (
|
|
@@ -346,7 +365,7 @@ export function Slides<T>({
|
|
|
346
365
|
activeOpacity={0.7}
|
|
347
366
|
onPress={() => goTo(position)}
|
|
348
367
|
accessibilityRole="button"
|
|
349
|
-
accessibilityLabel={
|
|
368
|
+
accessibilityLabel={labels.slideOf.replace('{n}', String(position + 1)).replace('{total}', String(total))}
|
|
350
369
|
accessibilityState={{ selected: position === active }}
|
|
351
370
|
>
|
|
352
371
|
{renderIndicator(position)}
|
|
@@ -379,9 +398,9 @@ export function Slides<T>({
|
|
|
379
398
|
pages.map(({ real, clone }) => {
|
|
380
399
|
const item = data[real] as T;
|
|
381
400
|
return (
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
401
|
+
// The gap is split on both sides of each page: that way the
|
|
402
|
+
// separation between two slides is a full `spacing` and the page
|
|
403
|
+
// still measures exactly what the ScrollView pages by.
|
|
385
404
|
<View
|
|
386
405
|
key={clone ? `slides-clone-${clone}` : keyExtractor(item, real)}
|
|
387
406
|
style={[
|
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import { type StyleProp, type ViewStyle } from 'react-native';
|
|
3
|
-
import { useThemeMode, type ThemeMode } from '../theme/UIProvider';
|
|
3
|
+
import { useLabels, useThemeMode, type ThemeMode } from '../theme/UIProvider';
|
|
4
4
|
import { SegmentedControl } from '../molecules/SegmentedControl';
|
|
5
5
|
|
|
6
6
|
export interface ThemeToggleProps {
|
|
7
7
|
style?: StyleProp<ViewStyle>;
|
|
8
|
+
/** Text of each segment; any mode left out keeps its default (`labels.themeSystem`, `themeLight`, `themeDark`). */
|
|
8
9
|
labels?: Partial<Record<ThemeMode, string>>;
|
|
9
10
|
testID?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const MODES: ThemeMode[] = ['system', 'light', 'dark'];
|
|
13
|
-
const DEFAULT_LABELS: Record<ThemeMode, string> = { system: 'Auto', light: 'Light', dark: 'Dark' };
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* ThemeToggle
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* Connects a SegmentedControl to UIProvider.setMode. No persistence — the
|
|
18
|
+
* consumer handles it via onModeChange on <UIProvider>.
|
|
19
|
+
*
|
|
20
|
+
* Design: Jakob's law — the same Auto / Light / Dark choice as the system
|
|
21
|
+
* settings, in that order; Hick's law — three options, nothing to configure.
|
|
19
22
|
*/
|
|
20
23
|
export const ThemeToggle = memo(({ style, labels: labelOverrides, testID }: ThemeToggleProps) => {
|
|
21
24
|
const { mode, setMode } = useThemeMode();
|
|
25
|
+
const providerLabels = useLabels();
|
|
22
26
|
|
|
23
27
|
const options = useMemo(() => {
|
|
24
|
-
const labels = {
|
|
28
|
+
const labels: Record<ThemeMode, string> = {
|
|
29
|
+
system: providerLabels.themeSystem,
|
|
30
|
+
light: providerLabels.themeLight,
|
|
31
|
+
dark: providerLabels.themeDark,
|
|
32
|
+
...labelOverrides,
|
|
33
|
+
};
|
|
25
34
|
return MODES.map((value) => ({ value, label: labels[value] }));
|
|
26
|
-
}, [labelOverrides]);
|
|
35
|
+
}, [labelOverrides, providerLabels]);
|
|
27
36
|
|
|
28
37
|
return <SegmentedControl options={options} value={mode} onChange={setMode} style={style} testID={testID} />;
|
|
29
38
|
});
|
|
@@ -10,15 +10,15 @@ import type { IconName } from '../icons/types';
|
|
|
10
10
|
export type TimelineStatus = 'done' | 'pending';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* - 'free':
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - 'sequential':
|
|
18
|
-
*
|
|
19
|
-
* - 'revisit':
|
|
20
|
-
*
|
|
21
|
-
*
|
|
13
|
+
* What a tap can do.
|
|
14
|
+
* - 'free': any milestone responds and the line follows `items` wherever it
|
|
15
|
+
* goes, forward or back. It is the one to use when the path isn't
|
|
16
|
+
* progress, or when something else drives it.
|
|
17
|
+
* - 'sequential': only the one after the reached milestone responds, and the
|
|
18
|
+
* line never goes back. Strict progression.
|
|
19
|
+
* - 'revisit': the next one and all those already reached respond, and the
|
|
20
|
+
* line doesn't go back either. It is the "I can look at what came before
|
|
21
|
+
* without losing my progress" case.
|
|
22
22
|
*/
|
|
23
23
|
export type TimelineAdvance = 'free' | 'sequential' | 'revisit';
|
|
24
24
|
|
|
@@ -33,6 +33,7 @@ export interface TimelineItem {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export interface TimelineProps {
|
|
36
|
+
/** The milestones, in order. Each has a label, optionally an icon or emoji, and its status. */
|
|
36
37
|
items: TimelineItem[];
|
|
37
38
|
/** Pixels the line bows away from the straight path. 0 draws it straight. @default 28 */
|
|
38
39
|
curve?: number;
|
|
@@ -71,24 +72,24 @@ const DEFAULT_CURVE = 28;
|
|
|
71
72
|
const DEFAULT_SPACING = 84;
|
|
72
73
|
const NODE = 14;
|
|
73
74
|
const LINE = 2;
|
|
74
|
-
/**
|
|
75
|
+
/** Straight segments per span: with fewer, the curve looks polygonal. */
|
|
75
76
|
const SEGMENTS = 14;
|
|
76
77
|
const DOT = 3;
|
|
77
|
-
/**
|
|
78
|
+
/** One dot every how many segments: the whole path is dotted underneath. */
|
|
78
79
|
const DOT_EVERY = 2;
|
|
79
80
|
const DEFAULT_DURATION = 420;
|
|
80
81
|
/**
|
|
81
|
-
*
|
|
82
|
-
*
|
|
82
|
+
* How long a segment takes to light up, measured in milestones. Small so the
|
|
83
|
+
* front of the line reads as an edge and not as a long gradient.
|
|
83
84
|
*/
|
|
84
85
|
const FADE = 0.06;
|
|
85
86
|
/**
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
87
|
+
* Halo layers, from the outside in. There are many and very faint on
|
|
88
|
+
* purpose: with three layers you see the rings, which is exactly the opposite
|
|
89
|
+
* of a blur. The more steps and the smaller the opacity jump, the closer it
|
|
90
|
+
* gets to a gradient.
|
|
90
91
|
*/
|
|
91
|
-
/**
|
|
92
|
+
/** How far the halo sticks out of the pill: that is the room it needs. */
|
|
92
93
|
const GLOW_BLEED = 20;
|
|
93
94
|
const GLOW_LAYERS = [
|
|
94
95
|
{ inset: -GLOW_BLEED, opacity: 0.03 },
|
|
@@ -113,7 +114,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
113
114
|
borderWidth: LINE,
|
|
114
115
|
},
|
|
115
116
|
nodePending: { backgroundColor: 'transparent', borderColor: theme.colors.border },
|
|
116
|
-
//
|
|
117
|
+
// Takes the whole circle minus the border, so the fill doesn't cover it.
|
|
117
118
|
nodeFill: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, borderRadius: NODE / 2 },
|
|
118
119
|
pill: {
|
|
119
120
|
flexDirection: 'row',
|
|
@@ -124,10 +125,10 @@ const useStyles = createStyles((theme) => ({
|
|
|
124
125
|
borderRadius: theme.tokens.radius.full,
|
|
125
126
|
borderWidth: 1,
|
|
126
127
|
borderColor: theme.colors.border,
|
|
127
|
-
backgroundColor: theme.colors.
|
|
128
|
+
backgroundColor: theme.colors.surfaceRaised,
|
|
128
129
|
},
|
|
129
|
-
//
|
|
130
|
-
//
|
|
130
|
+
// Focus is marked with the border, not the fill: the fill is already
|
|
131
|
+
// saying something else (whether the milestone has been reached or not).
|
|
131
132
|
pillSelected: { borderColor: theme.colors.primary, borderWidth: 2 },
|
|
132
133
|
label: { fontSize: theme.tokens.fontSize.md, color: theme.colors.text },
|
|
133
134
|
labelPending: { color: theme.colors.textLight },
|
|
@@ -137,29 +138,45 @@ const useStyles = createStyles((theme) => ({
|
|
|
137
138
|
borderRadius: theme.tokens.radius.full,
|
|
138
139
|
backgroundColor: theme.colors.text,
|
|
139
140
|
},
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
//
|
|
143
|
-
//
|
|
144
|
-
//
|
|
141
|
+
// The line and the nodes live in the same layer and are positioned with the
|
|
142
|
+
// same coordinates. It is the only thing that guarantees the circle lands on
|
|
143
|
+
// the curve: in the row's flow the node gets shifted by flex —and by the
|
|
144
|
+
// paddings each side needs so its pill isn't clipped—, so it ended up to one
|
|
145
|
+
// side of the line instead of on top of it.
|
|
145
146
|
lineLayer: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, alignItems: 'center' },
|
|
146
|
-
//
|
|
147
|
-
//
|
|
147
|
+
// Gap the width of the node in the row: the pill is set apart from the
|
|
148
|
+
// center the same as before, but the circle is no longer drawn here.
|
|
148
149
|
nodeSlot: { width: NODE },
|
|
149
150
|
segment: { position: 'absolute', width: LINE },
|
|
150
151
|
dot: { position: 'absolute', width: DOT, height: DOT, borderRadius: DOT / 2 },
|
|
151
152
|
}));
|
|
152
153
|
|
|
153
154
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
155
|
+
* Horizontal offset of node `index` from the axis. One full wave along the
|
|
156
|
+
* list: the first and the last fall on the axis, and the ones in the middle
|
|
157
|
+
* swing to one side and the other. It is what turns a column into a path.
|
|
157
158
|
*/
|
|
158
159
|
function offsetAt(index: number, count: number, curve: number): number {
|
|
159
160
|
if (count < 2) return 0;
|
|
160
161
|
return curve * Math.sin((2 * Math.PI * index) / (count - 1));
|
|
161
162
|
}
|
|
162
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Timeline
|
|
166
|
+
* Milestones on a path: a line that bows from one to the next and fills up to
|
|
167
|
+
* the last one reached, with each label in a pill on alternating sides.
|
|
168
|
+
*
|
|
169
|
+
* Design:
|
|
170
|
+
* - Continuity (Gestalt): one curved line joins the milestones, so they read
|
|
171
|
+
* as a single path; the reached part of it is filled.
|
|
172
|
+
* - Similarity + figure/ground: reached and pending milestones differ only by
|
|
173
|
+
* fill, so status reads at a glance.
|
|
174
|
+
* - Common fate: when a milestone is reached the line travels there, gap by
|
|
175
|
+
* gap (in place with Reduce Motion).
|
|
176
|
+
* - Fitts's law: with `onItemPress` the whole pill is the target.
|
|
177
|
+
* - Screen readers: each milestone is checked or not; with `onItemPress` it
|
|
178
|
+
* is a button, disabled when `advance` doesn't let it respond.
|
|
179
|
+
*/
|
|
163
180
|
export const Timeline = memo(
|
|
164
181
|
({
|
|
165
182
|
items,
|
|
@@ -182,9 +199,9 @@ export const Timeline = memo(
|
|
|
182
199
|
const count = items.length;
|
|
183
200
|
|
|
184
201
|
/**
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
202
|
+
* How far the path has gotten, in milestone units. It is counted from the
|
|
203
|
+
* start and cut at the first pending one: a milestone completed after one
|
|
204
|
+
* that isn't doesn't move the line forward, because a path is a path.
|
|
188
205
|
*/
|
|
189
206
|
const reached = useMemo(() => {
|
|
190
207
|
let last = -1;
|
|
@@ -196,9 +213,9 @@ export const Timeline = memo(
|
|
|
196
213
|
}, [items]);
|
|
197
214
|
|
|
198
215
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
216
|
+
* High-water mark: except in 'free', the line stays at the furthest point
|
|
217
|
+
* it reached. Progress belongs to the user, not the render — the parent
|
|
218
|
+
* sending a shorter list can't undo the distance already covered.
|
|
202
219
|
*/
|
|
203
220
|
const furthest = useRef(reached);
|
|
204
221
|
if (advance === 'free') furthest.current = reached;
|
|
@@ -210,8 +227,8 @@ export const Timeline = memo(
|
|
|
210
227
|
useEffect(() => {
|
|
211
228
|
const animation = Animated.timing(progress, {
|
|
212
229
|
toValue: lineTo,
|
|
213
|
-
//
|
|
214
|
-
//
|
|
230
|
+
// One milestone per `duration`: advancing three at once takes three
|
|
231
|
+
// times longer, so you see the path and not a jump.
|
|
215
232
|
duration: reduceMotion ? 0 : duration,
|
|
216
233
|
easing: Easing.inOut(Easing.cubic),
|
|
217
234
|
useNativeDriver: true,
|
|
@@ -221,10 +238,10 @@ export const Timeline = memo(
|
|
|
221
238
|
}, [lineTo, duration, reduceMotion, progress]);
|
|
222
239
|
|
|
223
240
|
/**
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
241
|
+
* Each span split into short straight segments, each with its own length
|
|
242
|
+
* and angle. It is the same idea as `Gradient`: the platform has no curves
|
|
243
|
+
* without a native dependency, so the curve is composed from straight
|
|
244
|
+
* pieces small enough for the eye not to see the break.
|
|
228
245
|
*/
|
|
229
246
|
const pieces = useMemo(() => {
|
|
230
247
|
const out: {
|
|
@@ -254,11 +271,11 @@ export const Timeline = memo(
|
|
|
254
271
|
x: (x1 + x2) / 2,
|
|
255
272
|
y: (y1 + y2) / 2,
|
|
256
273
|
length,
|
|
257
|
-
//
|
|
258
|
-
//
|
|
274
|
+
// The segment is drawn vertically and rotated to the slope: the
|
|
275
|
+
// angle is measured from the Y axis, not the X.
|
|
259
276
|
angle: `${Math.atan2(dx, dy) * (180 / Math.PI) * -1}deg`,
|
|
260
|
-
//
|
|
261
|
-
// `progress`,
|
|
277
|
+
// Segment position measured in milestones: it is the same scale as
|
|
278
|
+
// `progress`, so comparing one with the other is direct.
|
|
262
279
|
at: to,
|
|
263
280
|
dotted: step % DOT_EVERY === 0,
|
|
264
281
|
});
|
|
@@ -280,7 +297,7 @@ export const Timeline = memo(
|
|
|
280
297
|
testID={testID}
|
|
281
298
|
>
|
|
282
299
|
<View style={styles.lineLayer} pointerEvents="none">
|
|
283
|
-
{/*
|
|
300
|
+
{/* The whole path, dotted: it is what is left to travel. */}
|
|
284
301
|
{pieces.map(
|
|
285
302
|
(piece) =>
|
|
286
303
|
piece.dotted && (
|
|
@@ -298,9 +315,9 @@ export const Timeline = memo(
|
|
|
298
315
|
)
|
|
299
316
|
)}
|
|
300
317
|
|
|
301
|
-
{/*
|
|
302
|
-
`progress`
|
|
303
|
-
|
|
318
|
+
{/* And on top the solid line, revealed segment by segment as
|
|
319
|
+
`progress` advances. The only thing that changes per frame is
|
|
320
|
+
`opacity`, which means the path is drawn on the native thread. */}
|
|
304
321
|
{pieces.map((piece) => (
|
|
305
322
|
<Animated.View
|
|
306
323
|
key={`line-${piece.key}`}
|
|
@@ -333,8 +350,8 @@ export const Timeline = memo(
|
|
|
333
350
|
},
|
|
334
351
|
]}
|
|
335
352
|
>
|
|
336
|
-
{/*
|
|
337
|
-
|
|
353
|
+
{/* The fill is a separate node on top of the hollow: color can't
|
|
354
|
+
be animated on the native thread, opacity can. */}
|
|
338
355
|
<Animated.View
|
|
339
356
|
style={[
|
|
340
357
|
styles.nodeFill,
|
|
@@ -365,10 +382,10 @@ export const Timeline = memo(
|
|
|
365
382
|
const pending = item.status === 'pending';
|
|
366
383
|
const onRight = (index % 2 === 0) === (startSide === 'right');
|
|
367
384
|
const offset = offsetAt(index, count, curve);
|
|
368
|
-
//
|
|
369
|
-
//
|
|
370
|
-
//
|
|
371
|
-
//
|
|
385
|
+
// The whole row shifts with the curve, pill included, so the side it
|
|
386
|
+
// moved toward loses that space against the edge. We give it back as
|
|
387
|
+
// padding, plus what the halo sticks out: without this the outermost
|
|
388
|
+
// pill gets clipped flush.
|
|
372
389
|
const bleed = glow ? GLOW_BLEED : 0;
|
|
373
390
|
const roomLeft = Math.max(0, -offset) + bleed;
|
|
374
391
|
const roomRight = Math.max(0, offset) + bleed;
|
|
@@ -409,10 +426,10 @@ export const Timeline = memo(
|
|
|
409
426
|
</View>
|
|
410
427
|
);
|
|
411
428
|
|
|
412
|
-
// 'sequential'
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
//
|
|
429
|
+
// 'sequential' only allows tapping the next one; 'revisit' also the
|
|
430
|
+
// ones already covered. The one that doesn't respond is marked as
|
|
431
|
+
// disabled instead of staying silent: a button that does nothing
|
|
432
|
+
// and doesn't say so is worse than a disabled button.
|
|
416
433
|
const reachable =
|
|
417
434
|
advance === 'sequential'
|
|
418
435
|
? index === lineTo + 1
|