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/Toast.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { memo } from 'react';
|
|
2
2
|
import { Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
import { createStyles } from '../theme/createStyles';
|
|
4
|
-
import { useAllowFontScaling, useColors } from '../theme/UIProvider';
|
|
4
|
+
import { useAllowFontScaling, useColors, useLabels } from '../theme/UIProvider';
|
|
5
5
|
import { Transition } from '../atoms/Transition';
|
|
6
6
|
import { Icon } from '../icons/Icon';
|
|
7
7
|
import type { IconName } from '../icons/types';
|
|
@@ -9,11 +9,15 @@ import type { IconName } from '../icons/types';
|
|
|
9
9
|
export type ToastVariant = 'success' | 'error' | 'warning' | 'info';
|
|
10
10
|
|
|
11
11
|
export interface ToastProps {
|
|
12
|
+
/** Main line. */
|
|
12
13
|
title: string;
|
|
14
|
+
/** Optional second line. */
|
|
13
15
|
message?: string;
|
|
16
|
+
/** Sets the icon and the color of the side bar. @default 'info' */
|
|
14
17
|
variant?: ToastVariant;
|
|
15
18
|
/** Fires when the toast is tapped (in addition to closing it). */
|
|
16
19
|
onPress?: () => void;
|
|
20
|
+
/** Shows the close X (unless `hideCloseButton`) and is called when it is pressed. */
|
|
17
21
|
onDismiss?: () => void;
|
|
18
22
|
/** Hides the close X. The toast still auto-dismisses by timeout. */
|
|
19
23
|
hideCloseButton?: boolean;
|
|
@@ -28,12 +32,21 @@ const ICON_BY_VARIANT: Record<ToastVariant, IconName> = {
|
|
|
28
32
|
info: 'info',
|
|
29
33
|
};
|
|
30
34
|
|
|
35
|
+
/** Width of the colored bar on the left edge. */
|
|
36
|
+
const ACCENT_WIDTH = 4;
|
|
37
|
+
const ICON_SIZE = 22;
|
|
38
|
+
const CLOSE_ICON_SIZE = 18;
|
|
39
|
+
/** Pads the close glyph out to a 44pt target without growing the toast. */
|
|
40
|
+
const CLOSE_HIT_SLOP = (44 - CLOSE_ICON_SIZE) / 2;
|
|
41
|
+
/** How far it drops in from above. */
|
|
42
|
+
const ENTER_DISTANCE = 16;
|
|
43
|
+
|
|
31
44
|
const useStyles = createStyles((theme) => ({
|
|
32
45
|
container: {
|
|
33
46
|
flexDirection: 'row',
|
|
34
47
|
alignItems: 'center',
|
|
35
48
|
gap: theme.tokens.spacing.md,
|
|
36
|
-
backgroundColor: theme.colors.
|
|
49
|
+
backgroundColor: theme.colors.surfaceRaised,
|
|
37
50
|
borderRadius: theme.tokens.radius.lg,
|
|
38
51
|
borderWidth: 1,
|
|
39
52
|
borderColor: theme.colors.border,
|
|
@@ -46,11 +59,11 @@ const useStyles = createStyles((theme) => ({
|
|
|
46
59
|
left: 0,
|
|
47
60
|
top: 0,
|
|
48
61
|
bottom: 0,
|
|
49
|
-
width:
|
|
62
|
+
width: ACCENT_WIDTH,
|
|
50
63
|
borderTopLeftRadius: theme.tokens.radius.lg,
|
|
51
64
|
borderBottomLeftRadius: theme.tokens.radius.lg,
|
|
52
65
|
},
|
|
53
|
-
text: { flex: 1, gap:
|
|
66
|
+
text: { flex: 1, gap: theme.tokens.spacing.xxs },
|
|
54
67
|
title: {
|
|
55
68
|
fontSize: theme.tokens.fontSize.md,
|
|
56
69
|
fontWeight: theme.tokens.fontWeight.semibold,
|
|
@@ -61,18 +74,30 @@ const useStyles = createStyles((theme) => ({
|
|
|
61
74
|
|
|
62
75
|
/**
|
|
63
76
|
* Toast
|
|
64
|
-
*
|
|
65
|
-
* `useToast()`
|
|
66
|
-
*
|
|
77
|
+
* Ephemeral notification. Normally not used directly: `ToastProvider` +
|
|
78
|
+
* `useToast()` mount and dismiss it for you. It is exposed anyway in case
|
|
79
|
+
* you want to place it yourself inside a specific screen.
|
|
80
|
+
*
|
|
81
|
+
* Design:
|
|
82
|
+
* - Doherty threshold: immediate feedback for an action, without blocking
|
|
83
|
+
* the screen; it leaves on its own.
|
|
84
|
+
* - Similarity: the variant sets both the bar and the icon color, so success,
|
|
85
|
+
* error, warning and info read at a glance (and not by color alone: each
|
|
86
|
+
* has its own glyph).
|
|
87
|
+
* - Figure/ground: a raised surface with a shadow, above the content.
|
|
88
|
+
* - Fitts's law: the close button is a 44pt target.
|
|
89
|
+
* - Screen readers: `ToastProvider` announces each toast as it appears; a
|
|
90
|
+
* pressable toast reads title and message, and offers "Close" as an action.
|
|
67
91
|
*/
|
|
68
92
|
export const Toast = memo(
|
|
69
93
|
({ title, message, variant = 'info', onPress, onDismiss, hideCloseButton, style, testID }: ToastProps) => {
|
|
70
94
|
const colors = useColors();
|
|
71
95
|
const styles = useStyles();
|
|
72
96
|
const allowFontScaling = useAllowFontScaling();
|
|
97
|
+
const labels = useLabels();
|
|
73
98
|
|
|
74
|
-
//
|
|
75
|
-
//
|
|
99
|
+
// The side bar is a fill (full accent); the icon is content over the
|
|
100
|
+
// toast's surface and needs the `*Text` role.
|
|
76
101
|
const barColor: Record<ToastVariant, string> = {
|
|
77
102
|
success: colors.success,
|
|
78
103
|
error: colors.error,
|
|
@@ -89,7 +114,7 @@ export const Toast = memo(
|
|
|
89
114
|
const body = (
|
|
90
115
|
<View style={[styles.container, style]} testID={testID} accessibilityRole="alert">
|
|
91
116
|
<View style={[styles.accent, { backgroundColor: barColor[variant] }]} />
|
|
92
|
-
<Icon name={ICON_BY_VARIANT[variant]} size={
|
|
117
|
+
<Icon name={ICON_BY_VARIANT[variant]} size={ICON_SIZE} color={iconColor[variant]} />
|
|
93
118
|
<View style={styles.text}>
|
|
94
119
|
<Text allowFontScaling={allowFontScaling} style={styles.title}>
|
|
95
120
|
{title}
|
|
@@ -101,8 +126,8 @@ export const Toast = memo(
|
|
|
101
126
|
)}
|
|
102
127
|
</View>
|
|
103
128
|
{!hideCloseButton && !!onDismiss && (
|
|
104
|
-
<Pressable onPress={onDismiss} accessibilityRole="button" accessibilityLabel=
|
|
105
|
-
<Icon name="close" size={
|
|
129
|
+
<Pressable onPress={onDismiss} accessibilityRole="button" accessibilityLabel={labels.close} hitSlop={CLOSE_HIT_SLOP}>
|
|
130
|
+
<Icon name="close" size={CLOSE_ICON_SIZE} color={colors.textLight} />
|
|
106
131
|
</Pressable>
|
|
107
132
|
)}
|
|
108
133
|
</View>
|
|
@@ -111,7 +136,17 @@ export const Toast = memo(
|
|
|
111
136
|
if (!onPress) return body;
|
|
112
137
|
|
|
113
138
|
return (
|
|
114
|
-
<Pressable
|
|
139
|
+
<Pressable
|
|
140
|
+
onPress={onPress}
|
|
141
|
+
accessibilityRole="button"
|
|
142
|
+
accessibilityLabel={message ? `${title}, ${message}` : title}
|
|
143
|
+
// The close X inside a pressable toast isn't reachable on its own:
|
|
144
|
+
// the reader gets it as an action of the toast.
|
|
145
|
+
accessibilityActions={!hideCloseButton && onDismiss ? [{ name: 'dismiss', label: labels.close }] : undefined}
|
|
146
|
+
onAccessibilityAction={(event) => {
|
|
147
|
+
if (event.nativeEvent.actionName === 'dismiss') onDismiss?.();
|
|
148
|
+
}}
|
|
149
|
+
>
|
|
115
150
|
{body}
|
|
116
151
|
</Pressable>
|
|
117
152
|
);
|
|
@@ -119,10 +154,10 @@ export const Toast = memo(
|
|
|
119
154
|
);
|
|
120
155
|
Toast.displayName = 'Toast';
|
|
121
156
|
|
|
122
|
-
/**
|
|
157
|
+
/** Wraps a Toast with its enter/exit animation. Internal use by the provider. */
|
|
123
158
|
export const AnimatedToast = memo(
|
|
124
159
|
({ children, onHeight }: { children: React.ReactNode; onHeight?: (h: number) => void }) => (
|
|
125
|
-
<Transition preset={['fade', 'slide-down']} distance={
|
|
160
|
+
<Transition preset={['fade', 'slide-down']} distance={ENTER_DISTANCE} spring>
|
|
126
161
|
<View onLayout={(e) => onHeight?.(e.nativeEvent.layout.height)}>{children}</View>
|
|
127
162
|
</Transition>
|
|
128
163
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
2
|
+
import { AccessibilityInfo, View } from 'react-native';
|
|
3
3
|
import { AnimatedToast, Toast, type ToastVariant } from './Toast';
|
|
4
4
|
import { useInsets } from '../theme/UIProvider';
|
|
5
5
|
import { createStyles } from '../theme/createStyles';
|
|
@@ -9,7 +9,7 @@ export interface ToastOptions {
|
|
|
9
9
|
title: string;
|
|
10
10
|
message?: string;
|
|
11
11
|
variant?: ToastVariant;
|
|
12
|
-
/**
|
|
12
|
+
/** Milliseconds before auto-dismiss. 0 = never dismisses on its own. @default 4000 */
|
|
13
13
|
duration?: number;
|
|
14
14
|
onPress?: () => void;
|
|
15
15
|
hideCloseButton?: boolean;
|
|
@@ -20,7 +20,7 @@ interface ToastEntry extends ToastOptions {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
interface ToastContextValue {
|
|
23
|
-
/**
|
|
23
|
+
/** Shows a toast and returns its id (to close it early if needed). */
|
|
24
24
|
show: (options: ToastOptions) => string;
|
|
25
25
|
hide: (id: string) => void;
|
|
26
26
|
hideAll: () => void;
|
|
@@ -30,9 +30,9 @@ const ToastContext = createContext<ToastContextValue | undefined>(undefined);
|
|
|
30
30
|
const bridge = createImperativeBridge<ToastContextValue>('ToastProvider');
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* <ToastProvider
|
|
33
|
+
* Shows a toast from outside the React tree —a service, an interceptor—
|
|
34
|
+
* without going through the hook. Returns the id, or '' if there is no
|
|
35
|
+
* mounted <ToastProvider>.
|
|
36
36
|
*/
|
|
37
37
|
export function showToast(options: ToastOptions): string {
|
|
38
38
|
return bridge.get()?.show(options) ?? '';
|
|
@@ -62,9 +62,9 @@ export interface ToastProviderProps {
|
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* ToastProvider
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
65
|
+
* Mounts the toast layer above the rest of the app. Place it once near the
|
|
66
|
+
* root, inside UIProvider. The auto-dismiss timers are cleared on unmount and
|
|
67
|
+
* when each toast closes, so no callbacks are left hanging.
|
|
68
68
|
*/
|
|
69
69
|
export function ToastProvider({
|
|
70
70
|
children,
|
|
@@ -108,8 +108,8 @@ export function ToastProvider({
|
|
|
108
108
|
|
|
109
109
|
setToasts((prev) => {
|
|
110
110
|
const next = [...prev, { ...options, id }];
|
|
111
|
-
//
|
|
112
|
-
//
|
|
111
|
+
// The oldest are dropped, not the newcomers: a new toast is always
|
|
112
|
+
// visible.
|
|
113
113
|
const overflow = next.length - maxVisible;
|
|
114
114
|
if (overflow > 0) {
|
|
115
115
|
next.slice(0, overflow).forEach((t) => clearTimer(t.id));
|
|
@@ -118,6 +118,10 @@ export function ToastProvider({
|
|
|
118
118
|
return next;
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
+
// It appears without focus: screen readers only hear it if it is
|
|
122
|
+
// announced (iOS ignores accessibilityRole="alert" on its own).
|
|
123
|
+
AccessibilityInfo.announceForAccessibility(options.message ? `${options.title}. ${options.message}` : options.title);
|
|
124
|
+
|
|
121
125
|
if (duration > 0) {
|
|
122
126
|
timers.current.set(
|
|
123
127
|
id,
|
|
@@ -129,8 +133,8 @@ export function ToastProvider({
|
|
|
129
133
|
[defaultDuration, maxVisible, hide, clearTimer]
|
|
130
134
|
);
|
|
131
135
|
|
|
132
|
-
//
|
|
133
|
-
// setState
|
|
136
|
+
// When the provider unmounts no setTimeout must be left pointing at a
|
|
137
|
+
// setState of an already unmounted tree.
|
|
134
138
|
useEffect(() => {
|
|
135
139
|
const pending = timers.current;
|
|
136
140
|
return () => {
|
package/src/organisms/Wizard.tsx
CHANGED
|
@@ -1,29 +1,38 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import { ScrollView, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
2
|
+
import { AccessibilityInfo, Platform, ScrollView, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
3
3
|
import { createStyles } from '../theme/createStyles';
|
|
4
|
+
import { useLabels } from '../theme/UIProvider';
|
|
5
|
+
import { KeyboardHandled } from '../theme/KeyboardAvoidance';
|
|
4
6
|
import { Steps, type StepItem } from '../molecules/Steps';
|
|
5
7
|
import { Button } from '../atoms/Button';
|
|
6
8
|
import { Transition } from '../atoms/Transition';
|
|
7
9
|
|
|
8
10
|
export interface WizardStep extends StepItem {
|
|
9
11
|
content: React.ReactNode;
|
|
10
|
-
/** false
|
|
12
|
+
/** `false` blocks advancing from this step (validation). @default true */
|
|
11
13
|
canGoNext?: boolean;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface WizardProps {
|
|
17
|
+
/** The steps, in order: label, optional description, content and `canGoNext`. */
|
|
15
18
|
steps: WizardStep[];
|
|
16
19
|
/** Current step (controlled). If omitted, the Wizard manages its own state. */
|
|
17
20
|
current?: number;
|
|
21
|
+
/** Called with the new index when the step changes (Back, Next or a tap on the indicator). */
|
|
18
22
|
onStepChange?: (index: number) => void;
|
|
23
|
+
/** Called when the finish button is pressed on the last step. */
|
|
19
24
|
onFinish?: () => void;
|
|
20
|
-
/** @default 'horizontal' */
|
|
25
|
+
/** Layout of the step indicator: a row or a column. @default 'horizontal' */
|
|
21
26
|
orientation?: 'horizontal' | 'vertical';
|
|
27
|
+
/** What the circle of a completed step shows: a check, or its number. @default 'check' */
|
|
22
28
|
completedIndicator?: 'check' | 'number';
|
|
23
29
|
/** Allows returning to an already-completed step by tapping it in the indicator. @default true */
|
|
24
30
|
allowStepNavigation?: boolean;
|
|
31
|
+
/** Text of the back button (hidden on the first step). @default labels.back */
|
|
25
32
|
backLabel?: string;
|
|
33
|
+
/** Text of the next button. @default labels.next */
|
|
26
34
|
nextLabel?: string;
|
|
35
|
+
/** Text of the next button on the last step. @default labels.finish */
|
|
27
36
|
finishLabel?: string;
|
|
28
37
|
/**
|
|
29
38
|
* The step content scrolls when it doesn't fit. Set to false only if
|
|
@@ -51,10 +60,21 @@ const useStyles = createStyles((theme) => ({
|
|
|
51
60
|
|
|
52
61
|
/**
|
|
53
62
|
* Wizard
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
63
|
+
* Multi-step flow: indicator (Steps) + content of the current step +
|
|
64
|
+
* navigation bar. Works controlled (`current` + `onStepChange`) or on its
|
|
65
|
+
* own. `canGoNext: false` on a step disables moving forward, which is where
|
|
66
|
+
* that step's form validation hooks in.
|
|
67
|
+
*
|
|
68
|
+
* Design:
|
|
69
|
+
* - Chunking (Miller) + Hick's law: a long form split into a few steps, one
|
|
70
|
+
* decision set at a time.
|
|
71
|
+
* - Continuity: the content slides in the direction of travel (a fade with
|
|
72
|
+
* Reduce Motion), so forward and back feel like a path.
|
|
73
|
+
* - Proximity + Fitts's law: Back and Next share one row at the bottom, full
|
|
74
|
+
* width, within thumb reach; Next is the filled one (Von Restorff).
|
|
75
|
+
* - Error prevention: Next stays disabled until the step is valid, and the
|
|
76
|
+
* indicator only jumps back, never past an unvalidated step.
|
|
77
|
+
* - Screen readers: each step change is announced ("Step 2 of 3: Plan").
|
|
58
78
|
*/
|
|
59
79
|
export function Wizard({
|
|
60
80
|
steps,
|
|
@@ -64,14 +84,15 @@ export function Wizard({
|
|
|
64
84
|
orientation = 'horizontal',
|
|
65
85
|
completedIndicator = 'check',
|
|
66
86
|
allowStepNavigation = true,
|
|
67
|
-
backLabel
|
|
68
|
-
nextLabel
|
|
69
|
-
finishLabel
|
|
87
|
+
backLabel,
|
|
88
|
+
nextLabel,
|
|
89
|
+
finishLabel,
|
|
70
90
|
scrollableContent = true,
|
|
71
91
|
animated = true,
|
|
72
92
|
style,
|
|
73
93
|
}: WizardProps) {
|
|
74
94
|
const styles = useStyles();
|
|
95
|
+
const labels = useLabels();
|
|
75
96
|
const [uncontrolled, setUncontrolled] = useState(0);
|
|
76
97
|
const isControlled = controlledCurrent !== undefined;
|
|
77
98
|
const current = isControlled ? controlledCurrent : uncontrolled;
|
|
@@ -90,13 +111,27 @@ export function Wizard({
|
|
|
90
111
|
[steps]
|
|
91
112
|
);
|
|
92
113
|
|
|
93
|
-
//
|
|
114
|
+
// The ref still holds the previous step during the render that brings the new one.
|
|
94
115
|
const previous = useRef(current);
|
|
95
116
|
const forward = current >= previous.current;
|
|
96
117
|
const entered = useRef(false);
|
|
97
118
|
useEffect(() => {
|
|
119
|
+
// Next/Back keep the focus on the button: without this the reader never
|
|
120
|
+
// learns that the content changed. Not on mount, only on a change.
|
|
121
|
+
if (entered.current && previous.current !== current) {
|
|
122
|
+
const step = steps[current];
|
|
123
|
+
if (step) {
|
|
124
|
+
AccessibilityInfo.announceForAccessibility(
|
|
125
|
+
labels.stepOf
|
|
126
|
+
.replace('{n}', String(current + 1))
|
|
127
|
+
.replace('{total}', String(steps.length))
|
|
128
|
+
.replace('{label}', step.label)
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
98
132
|
previous.current = current;
|
|
99
133
|
entered.current = true;
|
|
134
|
+
// Only a step change announces; new `steps` with the same step don't.
|
|
100
135
|
}, [current]);
|
|
101
136
|
|
|
102
137
|
const activeStep = steps[current];
|
|
@@ -109,8 +144,8 @@ export function Wizard({
|
|
|
109
144
|
else goTo(current + 1);
|
|
110
145
|
};
|
|
111
146
|
|
|
112
|
-
//
|
|
113
|
-
//
|
|
147
|
+
// The outgoing step isn't animated: keeping both mounted at once would
|
|
148
|
+
// duplicate the forms and their state.
|
|
114
149
|
const renderContent = () =>
|
|
115
150
|
animated ? (
|
|
116
151
|
<Transition
|
|
@@ -132,14 +167,14 @@ export function Wizard({
|
|
|
132
167
|
current={current}
|
|
133
168
|
orientation={orientation}
|
|
134
169
|
completedIndicator={completedIndicator}
|
|
135
|
-
//
|
|
136
|
-
//
|
|
170
|
+
// You can only go back by tapping the indicator; jumping forward
|
|
171
|
+
// would skip the validation of the steps in between.
|
|
137
172
|
onStepPress={allowStepNavigation ? (index) => index < current && goTo(index) : undefined}
|
|
138
173
|
/>
|
|
139
174
|
|
|
140
|
-
{/*
|
|
141
|
-
form
|
|
142
|
-
|
|
175
|
+
{/* The content scrolls instead of overflowing: with the keyboard open a
|
|
176
|
+
long form ate the footer and the buttons ended up painted over the
|
|
177
|
+
fields. */}
|
|
143
178
|
{scrollableContent ? (
|
|
144
179
|
<ScrollView
|
|
145
180
|
testID="wizard-content"
|
|
@@ -149,7 +184,9 @@ export function Wizard({
|
|
|
149
184
|
automaticallyAdjustKeyboardInsets
|
|
150
185
|
showsVerticalScrollIndicator={false}
|
|
151
186
|
>
|
|
152
|
-
{
|
|
187
|
+
{/* iOS: the ScrollView already lifts the field (automaticallyAdjustKeyboardInsets).
|
|
188
|
+
Android doesn't have that prop: there the root host handles it. */}
|
|
189
|
+
{Platform.OS === 'ios' ? <KeyboardHandled>{renderContent()}</KeyboardHandled> : renderContent()}
|
|
153
190
|
</ScrollView>
|
|
154
191
|
) : (
|
|
155
192
|
<View style={styles.content}>{renderContent()}</View>
|
|
@@ -157,10 +194,10 @@ export function Wizard({
|
|
|
157
194
|
|
|
158
195
|
<View style={styles.footer}>
|
|
159
196
|
{!isFirst && (
|
|
160
|
-
<Button title={backLabel} variant="outline" onPress={() => goTo(current - 1)} style={styles.footerButton} />
|
|
197
|
+
<Button title={backLabel ?? labels.back} variant="outline" onPress={() => goTo(current - 1)} style={styles.footerButton} />
|
|
161
198
|
)}
|
|
162
199
|
<Button
|
|
163
|
-
title={isLast ? finishLabel : nextLabel}
|
|
200
|
+
title={isLast ? (finishLabel ?? labels.finish) : (nextLabel ?? labels.next)}
|
|
164
201
|
onPress={handleNext}
|
|
165
202
|
disabled={!canGoNext}
|
|
166
203
|
style={styles.footerButton}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* tooltip.
|
|
4
|
-
*
|
|
2
|
+
* Chart's frame: everything around the marks — grid, axes, legend and
|
|
3
|
+
* tooltip. Nothing here knows the chart type; it receives numbers and texts
|
|
4
|
+
* already resolved.
|
|
5
5
|
*
|
|
6
|
-
* Gestalt:
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* Gestalt: the grid uses `border`, two steps below the series' color, so the
|
|
7
|
+
* data stays as figure and the reference as ground. The legend repeats each
|
|
8
|
+
* series' exact color (similarity), which is why it can act as a filter
|
|
9
|
+
* control without explaining what it turns off: whatever has that color
|
|
10
|
+
* turns off.
|
|
11
11
|
*/
|
|
12
12
|
import React, { memo } from 'react';
|
|
13
13
|
import { Text, TouchableOpacity, View, type StyleProp, type ViewStyle } from 'react-native';
|
|
@@ -47,7 +47,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
47
47
|
paddingVertical: theme.tokens.spacing.sm,
|
|
48
48
|
paddingHorizontal: theme.tokens.spacing.md,
|
|
49
49
|
borderRadius: theme.tokens.radius.md,
|
|
50
|
-
backgroundColor: theme.colors.
|
|
50
|
+
backgroundColor: theme.colors.surfaceRaised,
|
|
51
51
|
borderWidth: 1,
|
|
52
52
|
borderColor: theme.colors.border,
|
|
53
53
|
gap: theme.tokens.spacing.xxs,
|
|
@@ -68,16 +68,16 @@ const useStyles = createStyles((theme) => ({
|
|
|
68
68
|
},
|
|
69
69
|
}));
|
|
70
70
|
|
|
71
|
-
// ──
|
|
71
|
+
// ── grid and cartesian axes ────────────────────────────────────────────────
|
|
72
72
|
|
|
73
73
|
export interface CartesianGridProps {
|
|
74
74
|
width: number;
|
|
75
75
|
height: number;
|
|
76
|
-
/**
|
|
76
|
+
/** Pixel position of each line, along the axis perpendicular to it. */
|
|
77
77
|
lines: number[];
|
|
78
|
-
/** 'horizontal'
|
|
78
|
+
/** 'horizontal' draws lines running across the width (y axis with ticks). */
|
|
79
79
|
orientation: 'horizontal' | 'vertical';
|
|
80
|
-
/**
|
|
80
|
+
/** Index of the zero line, more marked than the rest. */
|
|
81
81
|
zeroIndex?: number;
|
|
82
82
|
testID?: string;
|
|
83
83
|
}
|
|
@@ -98,8 +98,8 @@ export const CartesianGrid = memo(({ width, height, lines, orientation, zeroInde
|
|
|
98
98
|
orientation === 'horizontal'
|
|
99
99
|
? { left: 0, width, top: position, height: 1 }
|
|
100
100
|
: { top: 0, height, left: position, width: 1 },
|
|
101
|
-
//
|
|
102
|
-
// divide
|
|
101
|
+
// The zero line is a different reference from the others: it
|
|
102
|
+
// doesn't divide the space, it separates what adds from what subtracts.
|
|
103
103
|
isZero && { backgroundColor: colors.textLight },
|
|
104
104
|
]}
|
|
105
105
|
/>
|
|
@@ -112,11 +112,11 @@ CartesianGrid.displayName = 'CartesianGrid';
|
|
|
112
112
|
|
|
113
113
|
export interface AxisLabelsProps {
|
|
114
114
|
labels: { text: string; position: number }[];
|
|
115
|
-
/** 'x'
|
|
115
|
+
/** 'x' spreads them across the width below the plot; 'y' stacks them on the left. */
|
|
116
116
|
axis: 'x' | 'y';
|
|
117
|
-
/**
|
|
117
|
+
/** Width of the gutter reserved for the labels. */
|
|
118
118
|
gutter: number;
|
|
119
|
-
/**
|
|
119
|
+
/** Size of the plot along the labels' axis. */
|
|
120
120
|
span: number;
|
|
121
121
|
testID?: string;
|
|
122
122
|
}
|
|
@@ -126,8 +126,8 @@ const LABEL_HEIGHT = 14;
|
|
|
126
126
|
export const AxisLabels = memo(({ labels, axis, gutter, span, testID }: AxisLabelsProps) => {
|
|
127
127
|
const styles = useStyles();
|
|
128
128
|
const allowFontScaling = useAllowFontScaling();
|
|
129
|
-
//
|
|
130
|
-
//
|
|
129
|
+
// An x label is centered under its category and can overlap its neighbor;
|
|
130
|
+
// it gets the plot's even share as its width and is truncated to one line.
|
|
131
131
|
const slot = axis === 'x' ? Math.max(24, span / Math.max(1, labels.length)) : gutter;
|
|
132
132
|
|
|
133
133
|
return (
|
|
@@ -152,21 +152,21 @@ export const AxisLabels = memo(({ labels, axis, gutter, span, testID }: AxisLabe
|
|
|
152
152
|
});
|
|
153
153
|
AxisLabels.displayName = 'AxisLabels';
|
|
154
154
|
|
|
155
|
-
// ──
|
|
155
|
+
// ── radar grid ─────────────────────────────────────────────────────────────
|
|
156
156
|
|
|
157
157
|
export interface RadarGridProps {
|
|
158
158
|
center: Point;
|
|
159
159
|
radius: number;
|
|
160
160
|
angles: number[];
|
|
161
|
-
/**
|
|
161
|
+
/** Concentric rings, including the edge. */
|
|
162
162
|
levels: number;
|
|
163
163
|
testID?: string;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
167
|
+
* The radar's rings and spokes. The rings are polygons, not circles: a circle
|
|
168
|
+
* suggests there are values between one axis and the next, and there aren't —
|
|
169
|
+
* there are only the axes that were passed in.
|
|
170
170
|
*/
|
|
171
171
|
export const RadarGrid = memo(({ center, radius, angles, levels, testID }: RadarGridProps) => {
|
|
172
172
|
const colors = useColors();
|
|
@@ -223,7 +223,7 @@ export const RadarGrid = memo(({ center, radius, angles, levels, testID }: Radar
|
|
|
223
223
|
});
|
|
224
224
|
RadarGrid.displayName = 'RadarGrid';
|
|
225
225
|
|
|
226
|
-
// ──
|
|
226
|
+
// ── legend ─────────────────────────────────────────────────────────────────
|
|
227
227
|
|
|
228
228
|
export interface LegendItem {
|
|
229
229
|
key: string;
|
|
@@ -234,7 +234,7 @@ export interface LegendItem {
|
|
|
234
234
|
export interface LegendProps {
|
|
235
235
|
items: LegendItem[];
|
|
236
236
|
hidden: string[];
|
|
237
|
-
/**
|
|
237
|
+
/** Without this the legend is only a reference; with it, it is the filter. */
|
|
238
238
|
onToggle?: (key: string) => void;
|
|
239
239
|
testID?: string;
|
|
240
240
|
}
|
|
@@ -295,9 +295,9 @@ export interface TooltipRow {
|
|
|
295
295
|
export interface TooltipProps {
|
|
296
296
|
title: string;
|
|
297
297
|
rows: TooltipRow[];
|
|
298
|
-
/**
|
|
298
|
+
/** The point it describes, in container coordinates. */
|
|
299
299
|
anchor: Point;
|
|
300
|
-
/**
|
|
300
|
+
/** Available width: the bubble shifts so it doesn't spill out. */
|
|
301
301
|
containerWidth: number;
|
|
302
302
|
style?: StyleProp<ViewStyle>;
|
|
303
303
|
testID?: string;
|
|
@@ -305,19 +305,19 @@ export interface TooltipProps {
|
|
|
305
305
|
|
|
306
306
|
const TOOLTIP_WIDTH = 148;
|
|
307
307
|
const TOOLTIP_GAP = 10;
|
|
308
|
-
/**
|
|
309
|
-
*
|
|
308
|
+
/** Estimated bubble height: the real one isn't known until it's measured, and
|
|
309
|
+
* measuring it to decide where to put it would make it show up shifted for a frame. */
|
|
310
310
|
const TOOLTIP_TITLE = 22;
|
|
311
311
|
const TOOLTIP_ROW = 17;
|
|
312
312
|
|
|
313
313
|
export const Tooltip = memo(({ title, rows, anchor, containerWidth, style, testID }: TooltipProps) => {
|
|
314
314
|
const styles = useStyles();
|
|
315
315
|
const allowFontScaling = useAllowFontScaling();
|
|
316
|
-
// Clamp
|
|
317
|
-
//
|
|
316
|
+
// Clamp instead of flip: moving it to the other side of the finger makes it
|
|
317
|
+
// jump sides while dragging, and the jump reads as a bug.
|
|
318
318
|
const left = Math.max(0, Math.min(containerWidth - TOOLTIP_WIDTH, anchor.x - TOOLTIP_WIDTH / 2));
|
|
319
|
-
//
|
|
320
|
-
//
|
|
319
|
+
// It goes above the point, unless there is no room: then it goes below,
|
|
320
|
+
// because getting cut off against the top edge makes it unreadable.
|
|
321
321
|
const estimated = TOOLTIP_TITLE + rows.length * TOOLTIP_ROW;
|
|
322
322
|
const above = anchor.y - TOOLTIP_GAP - estimated;
|
|
323
323
|
const top = above >= 0 ? above : anchor.y + TOOLTIP_GAP;
|