orn-ui 0.2.10 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +66 -51
- package/README.md +3 -7
- package/lib/commonjs/atoms/Avatar.js +77 -5
- package/lib/commonjs/atoms/Avatar.js.map +1 -1
- package/lib/commonjs/atoms/Badge.js +17 -8
- package/lib/commonjs/atoms/Badge.js.map +1 -1
- package/lib/commonjs/atoms/Button.js +108 -39
- package/lib/commonjs/atoms/Button.js.map +1 -1
- package/lib/commonjs/atoms/Card.js +24 -2
- package/lib/commonjs/atoms/Card.js.map +1 -1
- package/lib/commonjs/atoms/Checkbox.js +41 -10
- package/lib/commonjs/atoms/Checkbox.js.map +1 -1
- package/lib/commonjs/atoms/Divider.js +30 -5
- package/lib/commonjs/atoms/Divider.js.map +1 -1
- package/lib/commonjs/atoms/EmptyState.js +58 -20
- package/lib/commonjs/atoms/EmptyState.js.map +1 -1
- package/lib/commonjs/atoms/Fab.js +32 -12
- package/lib/commonjs/atoms/Fab.js.map +1 -1
- package/lib/commonjs/atoms/Gradient.js +102 -36
- package/lib/commonjs/atoms/Gradient.js.map +1 -1
- package/lib/commonjs/atoms/IconButton.js +25 -4
- package/lib/commonjs/atoms/IconButton.js.map +1 -1
- package/lib/commonjs/atoms/Image.js +61 -25
- package/lib/commonjs/atoms/Image.js.map +1 -1
- package/lib/commonjs/atoms/Input.js +105 -17
- package/lib/commonjs/atoms/Input.js.map +1 -1
- package/lib/commonjs/atoms/KeyValueRow.js +37 -9
- package/lib/commonjs/atoms/KeyValueRow.js.map +1 -1
- package/lib/commonjs/atoms/PressableScale.js +25 -5
- package/lib/commonjs/atoms/PressableScale.js.map +1 -1
- package/lib/commonjs/atoms/ShinyText.js +29 -29
- package/lib/commonjs/atoms/Skeleton.js +28 -13
- package/lib/commonjs/atoms/Skeleton.js.map +1 -1
- package/lib/commonjs/atoms/Spinner.js +81 -22
- package/lib/commonjs/atoms/Spinner.js.map +1 -1
- package/lib/commonjs/atoms/Text.js +56 -5
- package/lib/commonjs/atoms/Text.js.map +1 -1
- package/lib/commonjs/atoms/Transition.js +46 -43
- package/lib/commonjs/atoms/Transition.js.map +1 -1
- package/lib/commonjs/atoms/index.js +6 -0
- package/lib/commonjs/atoms/index.js.map +1 -1
- package/lib/commonjs/atoms/inputValidation.js +56 -0
- package/lib/commonjs/atoms/inputValidation.js.map +1 -0
- package/lib/commonjs/icons/Icon.js +4 -4
- package/lib/commonjs/icons/defaultIcons.js +576 -24
- package/lib/commonjs/icons/defaultIcons.js.map +1 -1
- package/lib/commonjs/icons/index.js +6 -0
- package/lib/commonjs/icons/index.js.map +1 -1
- package/lib/commonjs/molecules/AvatarHeader.js +47 -14
- package/lib/commonjs/molecules/AvatarHeader.js.map +1 -1
- package/lib/commonjs/molecules/FormActions.js +25 -9
- package/lib/commonjs/molecules/FormActions.js.map +1 -1
- package/lib/commonjs/molecules/InfoRow.js +30 -14
- package/lib/commonjs/molecules/InfoRow.js.map +1 -1
- package/lib/commonjs/molecules/OptionCard.js +37 -22
- package/lib/commonjs/molecules/OptionCard.js.map +1 -1
- package/lib/commonjs/molecules/SegmentedControl.js +103 -14
- package/lib/commonjs/molecules/SegmentedControl.js.map +1 -1
- package/lib/commonjs/molecules/Stepper.js +61 -16
- package/lib/commonjs/molecules/Stepper.js.map +1 -1
- package/lib/commonjs/molecules/Steps.js +105 -41
- package/lib/commonjs/molecules/Steps.js.map +1 -1
- package/lib/commonjs/molecules/SymmetricGrid.js +26 -18
- package/lib/commonjs/molecules/SymmetricGrid.js.map +1 -1
- package/lib/commonjs/organisms/Alert.js +49 -35
- package/lib/commonjs/organisms/Alert.js.map +1 -1
- package/lib/commonjs/organisms/AlertProvider.js +10 -10
- package/lib/commonjs/organisms/BottomSheet.js +137 -85
- package/lib/commonjs/organisms/BottomSheet.js.map +1 -1
- package/lib/commonjs/organisms/Chart.js +174 -154
- package/lib/commonjs/organisms/Chart.js.map +1 -1
- package/lib/commonjs/organisms/DateField.js +36 -20
- package/lib/commonjs/organisms/DateField.js.map +1 -1
- package/lib/commonjs/organisms/DatePicker.js +56 -33
- package/lib/commonjs/organisms/DatePicker.js.map +1 -1
- package/lib/commonjs/organisms/List.js +62 -34
- package/lib/commonjs/organisms/List.js.map +1 -1
- package/lib/commonjs/organisms/Modal.js +120 -82
- package/lib/commonjs/organisms/Modal.js.map +1 -1
- package/lib/commonjs/organisms/NavigationBar.js +63 -24
- package/lib/commonjs/organisms/NavigationBar.js.map +1 -1
- package/lib/commonjs/organisms/OptionWheel.js +64 -64
- package/lib/commonjs/organisms/OptionWheel.js.map +1 -1
- package/lib/commonjs/organisms/ReorderableList.js +48 -27
- package/lib/commonjs/organisms/ReorderableList.js.map +1 -1
- package/lib/commonjs/organisms/Screen.js +68 -35
- package/lib/commonjs/organisms/Screen.js.map +1 -1
- package/lib/commonjs/organisms/SearchList.js +56 -26
- package/lib/commonjs/organisms/SearchList.js.map +1 -1
- package/lib/commonjs/organisms/Select.js +45 -24
- package/lib/commonjs/organisms/Select.js.map +1 -1
- package/lib/commonjs/organisms/Slides.js +36 -23
- package/lib/commonjs/organisms/Slides.js.map +1 -1
- package/lib/commonjs/organisms/ThemeToggle.js +10 -9
- package/lib/commonjs/organisms/ThemeToggle.js.map +1 -1
- package/lib/commonjs/organisms/Timeline.js +73 -56
- package/lib/commonjs/organisms/Timeline.js.map +1 -1
- package/lib/commonjs/organisms/Toast.js +46 -15
- package/lib/commonjs/organisms/Toast.js.map +1 -1
- package/lib/commonjs/organisms/ToastProvider.js +14 -10
- package/lib/commonjs/organisms/ToastProvider.js.map +1 -1
- package/lib/commonjs/organisms/Wizard.js +40 -15
- package/lib/commonjs/organisms/Wizard.js.map +1 -1
- package/lib/commonjs/organisms/chart/frame.js +25 -25
- package/lib/commonjs/organisms/chart/frame.js.map +1 -1
- package/lib/commonjs/organisms/chart/marks.js +42 -42
- package/lib/commonjs/organisms/chart/math.js +84 -85
- package/lib/commonjs/organisms/chart/math.js.map +1 -1
- package/lib/commonjs/organisms/chart/palette.js +28 -28
- package/lib/commonjs/organisms/imperativeBridge.js +5 -5
- package/lib/commonjs/organisms/imperativeBridge.js.map +1 -1
- package/lib/commonjs/organisms/useSlides.js +53 -21
- package/lib/commonjs/organisms/useSlides.js.map +1 -1
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js +9 -66
- package/lib/commonjs/safe-area/SafeAreaUIProvider.js.map +1 -1
- package/lib/commonjs/safe-area/index.js.map +1 -1
- package/lib/commonjs/theme/KeyboardAvoidance.js +206 -0
- package/lib/commonjs/theme/KeyboardAvoidance.js.map +1 -0
- package/lib/commonjs/theme/NativeOverlay.js +263 -0
- package/lib/commonjs/theme/NativeOverlay.js.map +1 -0
- package/lib/commonjs/theme/UIProvider.js +86 -33
- package/lib/commonjs/theme/UIProvider.js.map +1 -1
- package/lib/commonjs/theme/colors.js +17 -17
- package/lib/commonjs/theme/colors.js.map +1 -1
- package/lib/commonjs/theme/createStyles.js +19 -16
- package/lib/commonjs/theme/createStyles.js.map +1 -1
- package/lib/commonjs/theme/createTheme.js +6 -6
- package/lib/commonjs/theme/index.js +6 -0
- package/lib/commonjs/theme/index.js.map +1 -1
- package/lib/commonjs/theme/insets.js +1 -1
- package/lib/commonjs/theme/labels.js +29 -1
- package/lib/commonjs/theme/labels.js.map +1 -1
- package/lib/commonjs/theme/palettes.js +25 -23
- package/lib/commonjs/theme/palettes.js.map +1 -1
- package/lib/commonjs/theme/tokens.js +28 -14
- package/lib/commonjs/theme/tokens.js.map +1 -1
- package/lib/commonjs/theme/useKeyboardField.js +36 -0
- package/lib/commonjs/theme/useKeyboardField.js.map +1 -0
- package/lib/commonjs/theme/useReduceMotion.js +31 -0
- package/lib/commonjs/theme/useReduceMotion.js.map +1 -0
- package/lib/module/atoms/Avatar.js +79 -8
- package/lib/module/atoms/Avatar.js.map +1 -1
- package/lib/module/atoms/Badge.js +17 -8
- package/lib/module/atoms/Badge.js.map +1 -1
- package/lib/module/atoms/Button.js +110 -41
- package/lib/module/atoms/Button.js.map +1 -1
- package/lib/module/atoms/Card.js +24 -2
- package/lib/module/atoms/Card.js.map +1 -1
- package/lib/module/atoms/Checkbox.js +42 -11
- package/lib/module/atoms/Checkbox.js.map +1 -1
- package/lib/module/atoms/Divider.js +31 -6
- package/lib/module/atoms/Divider.js.map +1 -1
- package/lib/module/atoms/EmptyState.js +58 -20
- package/lib/module/atoms/EmptyState.js.map +1 -1
- package/lib/module/atoms/Fab.js +33 -13
- package/lib/module/atoms/Fab.js.map +1 -1
- package/lib/module/atoms/Gradient.js +103 -37
- package/lib/module/atoms/Gradient.js.map +1 -1
- package/lib/module/atoms/IconButton.js +25 -4
- package/lib/module/atoms/IconButton.js.map +1 -1
- package/lib/module/atoms/Image.js +61 -25
- package/lib/module/atoms/Image.js.map +1 -1
- package/lib/module/atoms/Input.js +108 -20
- package/lib/module/atoms/Input.js.map +1 -1
- package/lib/module/atoms/KeyValueRow.js +37 -9
- package/lib/module/atoms/KeyValueRow.js.map +1 -1
- package/lib/module/atoms/PressableScale.js +25 -5
- package/lib/module/atoms/PressableScale.js.map +1 -1
- package/lib/module/atoms/ShinyText.js +29 -29
- package/lib/module/atoms/Skeleton.js +30 -13
- package/lib/module/atoms/Skeleton.js.map +1 -1
- package/lib/module/atoms/Spinner.js +82 -23
- package/lib/module/atoms/Spinner.js.map +1 -1
- package/lib/module/atoms/Text.js +56 -5
- package/lib/module/atoms/Text.js.map +1 -1
- package/lib/module/atoms/Transition.js +41 -42
- package/lib/module/atoms/Transition.js.map +1 -1
- package/lib/module/atoms/index.js +1 -1
- package/lib/module/atoms/index.js.map +1 -1
- package/lib/module/atoms/inputValidation.js +52 -0
- package/lib/module/atoms/inputValidation.js.map +1 -0
- package/lib/module/icons/Icon.js +4 -4
- package/lib/module/icons/defaultIcons.js +574 -24
- package/lib/module/icons/defaultIcons.js.map +1 -1
- package/lib/module/icons/index.js +1 -1
- package/lib/module/icons/index.js.map +1 -1
- package/lib/module/molecules/AvatarHeader.js +47 -14
- package/lib/module/molecules/AvatarHeader.js.map +1 -1
- package/lib/module/molecules/FormActions.js +25 -9
- package/lib/module/molecules/FormActions.js.map +1 -1
- package/lib/module/molecules/InfoRow.js +30 -14
- package/lib/module/molecules/InfoRow.js.map +1 -1
- package/lib/module/molecules/OptionCard.js +37 -22
- package/lib/module/molecules/OptionCard.js.map +1 -1
- package/lib/module/molecules/SegmentedControl.js +107 -18
- package/lib/module/molecules/SegmentedControl.js.map +1 -1
- package/lib/module/molecules/Stepper.js +63 -18
- package/lib/module/molecules/Stepper.js.map +1 -1
- package/lib/module/molecules/Steps.js +107 -43
- package/lib/module/molecules/Steps.js.map +1 -1
- package/lib/module/molecules/SymmetricGrid.js +26 -18
- package/lib/module/molecules/SymmetricGrid.js.map +1 -1
- package/lib/module/organisms/Alert.js +51 -37
- package/lib/module/organisms/Alert.js.map +1 -1
- package/lib/module/organisms/AlertProvider.js +10 -10
- package/lib/module/organisms/BottomSheet.js +142 -88
- package/lib/module/organisms/BottomSheet.js.map +1 -1
- package/lib/module/organisms/Chart.js +176 -156
- package/lib/module/organisms/Chart.js.map +1 -1
- package/lib/module/organisms/DateField.js +36 -20
- package/lib/module/organisms/DateField.js.map +1 -1
- package/lib/module/organisms/DatePicker.js +56 -33
- package/lib/module/organisms/DatePicker.js.map +1 -1
- package/lib/module/organisms/List.js +62 -34
- package/lib/module/organisms/List.js.map +1 -1
- package/lib/module/organisms/Modal.js +122 -84
- package/lib/module/organisms/Modal.js.map +1 -1
- package/lib/module/organisms/NavigationBar.js +64 -25
- package/lib/module/organisms/NavigationBar.js.map +1 -1
- package/lib/module/organisms/OptionWheel.js +64 -64
- package/lib/module/organisms/OptionWheel.js.map +1 -1
- package/lib/module/organisms/ReorderableList.js +48 -27
- package/lib/module/organisms/ReorderableList.js.map +1 -1
- package/lib/module/organisms/Screen.js +70 -37
- package/lib/module/organisms/Screen.js.map +1 -1
- package/lib/module/organisms/SearchList.js +56 -26
- package/lib/module/organisms/SearchList.js.map +1 -1
- package/lib/module/organisms/Select.js +46 -25
- package/lib/module/organisms/Select.js.map +1 -1
- package/lib/module/organisms/Slides.js +37 -24
- package/lib/module/organisms/Slides.js.map +1 -1
- package/lib/module/organisms/ThemeToggle.js +11 -10
- package/lib/module/organisms/ThemeToggle.js.map +1 -1
- package/lib/module/organisms/Timeline.js +73 -56
- package/lib/module/organisms/Timeline.js.map +1 -1
- package/lib/module/organisms/Toast.js +47 -16
- package/lib/module/organisms/Toast.js.map +1 -1
- package/lib/module/organisms/ToastProvider.js +15 -11
- package/lib/module/organisms/ToastProvider.js.map +1 -1
- package/lib/module/organisms/Wizard.js +41 -16
- package/lib/module/organisms/Wizard.js.map +1 -1
- package/lib/module/organisms/chart/frame.js +25 -25
- package/lib/module/organisms/chart/frame.js.map +1 -1
- package/lib/module/organisms/chart/marks.js +42 -42
- package/lib/module/organisms/chart/math.js +84 -85
- package/lib/module/organisms/chart/math.js.map +1 -1
- package/lib/module/organisms/chart/palette.js +28 -28
- package/lib/module/organisms/imperativeBridge.js +5 -5
- package/lib/module/organisms/imperativeBridge.js.map +1 -1
- package/lib/module/organisms/useSlides.js +53 -21
- package/lib/module/organisms/useSlides.js.map +1 -1
- package/lib/module/safe-area/SafeAreaUIProvider.js +10 -65
- package/lib/module/safe-area/SafeAreaUIProvider.js.map +1 -1
- package/lib/module/safe-area/index.js +1 -0
- package/lib/module/safe-area/index.js.map +1 -1
- package/lib/module/theme/KeyboardAvoidance.js +198 -0
- package/lib/module/theme/KeyboardAvoidance.js.map +1 -0
- package/lib/module/theme/NativeOverlay.js +257 -0
- package/lib/module/theme/NativeOverlay.js.map +1 -0
- package/lib/module/theme/UIProvider.js +88 -35
- package/lib/module/theme/UIProvider.js.map +1 -1
- package/lib/module/theme/colors.js +17 -17
- package/lib/module/theme/colors.js.map +1 -1
- package/lib/module/theme/createStyles.js +20 -16
- package/lib/module/theme/createStyles.js.map +1 -1
- package/lib/module/theme/createTheme.js +6 -6
- package/lib/module/theme/index.js +1 -1
- package/lib/module/theme/index.js.map +1 -1
- package/lib/module/theme/insets.js +1 -1
- package/lib/module/theme/labels.js +29 -1
- package/lib/module/theme/labels.js.map +1 -1
- package/lib/module/theme/palettes.js +25 -23
- package/lib/module/theme/palettes.js.map +1 -1
- package/lib/module/theme/tokens.js +27 -13
- package/lib/module/theme/tokens.js.map +1 -1
- package/lib/module/theme/useKeyboardField.js +33 -0
- package/lib/module/theme/useKeyboardField.js.map +1 -0
- package/lib/module/theme/useReduceMotion.js +28 -0
- package/lib/module/theme/useReduceMotion.js.map +1 -0
- package/lib/typescript/atoms/Avatar.d.ts +35 -5
- package/lib/typescript/atoms/Avatar.d.ts.map +1 -1
- package/lib/typescript/atoms/Badge.d.ts +14 -3
- package/lib/typescript/atoms/Badge.d.ts.map +1 -1
- package/lib/typescript/atoms/Button.d.ts +34 -3
- package/lib/typescript/atoms/Button.d.ts.map +1 -1
- package/lib/typescript/atoms/Card.d.ts +13 -2
- package/lib/typescript/atoms/Card.d.ts.map +1 -1
- package/lib/typescript/atoms/Checkbox.d.ts +26 -1
- package/lib/typescript/atoms/Checkbox.d.ts.map +1 -1
- package/lib/typescript/atoms/Divider.d.ts +18 -1
- package/lib/typescript/atoms/Divider.d.ts.map +1 -1
- package/lib/typescript/atoms/EmptyState.d.ts +30 -3
- package/lib/typescript/atoms/EmptyState.d.ts.map +1 -1
- package/lib/typescript/atoms/Fab.d.ts +24 -4
- package/lib/typescript/atoms/Fab.d.ts.map +1 -1
- package/lib/typescript/atoms/Gradient.d.ts +21 -15
- package/lib/typescript/atoms/Gradient.d.ts.map +1 -1
- package/lib/typescript/atoms/IconButton.d.ts +18 -4
- package/lib/typescript/atoms/IconButton.d.ts.map +1 -1
- package/lib/typescript/atoms/Image.d.ts +39 -17
- package/lib/typescript/atoms/Image.d.ts.map +1 -1
- package/lib/typescript/atoms/Input.d.ts +57 -7
- package/lib/typescript/atoms/Input.d.ts.map +1 -1
- package/lib/typescript/atoms/KeyValueRow.d.ts +16 -4
- package/lib/typescript/atoms/KeyValueRow.d.ts.map +1 -1
- package/lib/typescript/atoms/PressableScale.d.ts +12 -5
- package/lib/typescript/atoms/PressableScale.d.ts.map +1 -1
- package/lib/typescript/atoms/ShinyText.d.ts +17 -17
- package/lib/typescript/atoms/ShinyText.d.ts.map +1 -1
- package/lib/typescript/atoms/Skeleton.d.ts +12 -7
- package/lib/typescript/atoms/Skeleton.d.ts.map +1 -1
- package/lib/typescript/atoms/Spinner.d.ts +29 -1
- package/lib/typescript/atoms/Spinner.d.ts.map +1 -1
- package/lib/typescript/atoms/Text.d.ts +46 -0
- package/lib/typescript/atoms/Text.d.ts.map +1 -1
- package/lib/typescript/atoms/Transition.d.ts +19 -15
- package/lib/typescript/atoms/Transition.d.ts.map +1 -1
- package/lib/typescript/atoms/index.d.ts +3 -3
- package/lib/typescript/atoms/index.d.ts.map +1 -1
- package/lib/typescript/atoms/inputValidation.d.ts +29 -0
- package/lib/typescript/atoms/inputValidation.d.ts.map +1 -0
- package/lib/typescript/icons/Icon.d.ts +4 -4
- package/lib/typescript/icons/defaultIcons.d.ts +19 -2
- package/lib/typescript/icons/defaultIcons.d.ts.map +1 -1
- package/lib/typescript/icons/index.d.ts +2 -2
- package/lib/typescript/icons/index.d.ts.map +1 -1
- package/lib/typescript/icons/types.d.ts +13 -3
- package/lib/typescript/icons/types.d.ts.map +1 -1
- package/lib/typescript/molecules/AvatarHeader.d.ts +23 -4
- package/lib/typescript/molecules/AvatarHeader.d.ts.map +1 -1
- package/lib/typescript/molecules/FormActions.d.ts +21 -4
- package/lib/typescript/molecules/FormActions.d.ts.map +1 -1
- package/lib/typescript/molecules/InfoRow.d.ts +17 -3
- package/lib/typescript/molecules/InfoRow.d.ts.map +1 -1
- package/lib/typescript/molecules/OptionCard.d.ts +20 -5
- package/lib/typescript/molecules/OptionCard.d.ts.map +1 -1
- package/lib/typescript/molecules/SegmentedControl.d.ts +18 -2
- package/lib/typescript/molecules/SegmentedControl.d.ts.map +1 -1
- package/lib/typescript/molecules/Stepper.d.ts +23 -7
- package/lib/typescript/molecules/Stepper.d.ts.map +1 -1
- package/lib/typescript/molecules/Steps.d.ts +18 -4
- package/lib/typescript/molecules/Steps.d.ts.map +1 -1
- package/lib/typescript/molecules/SymmetricGrid.d.ts +15 -5
- package/lib/typescript/molecules/SymmetricGrid.d.ts.map +1 -1
- package/lib/typescript/organisms/Alert.d.ts +28 -2
- package/lib/typescript/organisms/Alert.d.ts.map +1 -1
- package/lib/typescript/organisms/AlertProvider.d.ts +10 -10
- package/lib/typescript/organisms/AlertProvider.d.ts.map +1 -1
- package/lib/typescript/organisms/BottomSheet.d.ts +20 -5
- package/lib/typescript/organisms/BottomSheet.d.ts.map +1 -1
- package/lib/typescript/organisms/Chart.d.ts +86 -75
- package/lib/typescript/organisms/Chart.d.ts.map +1 -1
- package/lib/typescript/organisms/DateField.d.ts +17 -3
- package/lib/typescript/organisms/DateField.d.ts.map +1 -1
- package/lib/typescript/organisms/DatePicker.d.ts +7 -11
- package/lib/typescript/organisms/DatePicker.d.ts.map +1 -1
- package/lib/typescript/organisms/List.d.ts +30 -3
- package/lib/typescript/organisms/List.d.ts.map +1 -1
- package/lib/typescript/organisms/Modal.d.ts +30 -3
- package/lib/typescript/organisms/Modal.d.ts.map +1 -1
- package/lib/typescript/organisms/NavigationBar.d.ts +26 -7
- package/lib/typescript/organisms/NavigationBar.d.ts.map +1 -1
- package/lib/typescript/organisms/OptionWheel.d.ts +20 -16
- package/lib/typescript/organisms/OptionWheel.d.ts.map +1 -1
- package/lib/typescript/organisms/ReorderableList.d.ts +20 -11
- package/lib/typescript/organisms/ReorderableList.d.ts.map +1 -1
- package/lib/typescript/organisms/Screen.d.ts +27 -8
- package/lib/typescript/organisms/Screen.d.ts.map +1 -1
- package/lib/typescript/organisms/SearchList.d.ts +46 -3
- package/lib/typescript/organisms/SearchList.d.ts.map +1 -1
- package/lib/typescript/organisms/Select.d.ts +26 -6
- package/lib/typescript/organisms/Select.d.ts.map +1 -1
- package/lib/typescript/organisms/Slides.d.ts +44 -26
- package/lib/typescript/organisms/Slides.d.ts.map +1 -1
- package/lib/typescript/organisms/ThemeToggle.d.ts +6 -2
- package/lib/typescript/organisms/ThemeToggle.d.ts.map +1 -1
- package/lib/typescript/organisms/Timeline.d.ts +26 -9
- package/lib/typescript/organisms/Timeline.d.ts.map +1 -1
- package/lib/typescript/organisms/Toast.d.ts +19 -4
- package/lib/typescript/organisms/Toast.d.ts.map +1 -1
- package/lib/typescript/organisms/ToastProvider.d.ts +8 -8
- package/lib/typescript/organisms/ToastProvider.d.ts.map +1 -1
- package/lib/typescript/organisms/Wizard.d.ts +24 -6
- package/lib/typescript/organisms/Wizard.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/frame.d.ts +21 -21
- package/lib/typescript/organisms/chart/frame.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/marks.d.ts +28 -28
- package/lib/typescript/organisms/chart/marks.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/math.d.ts +69 -70
- package/lib/typescript/organisms/chart/math.d.ts.map +1 -1
- package/lib/typescript/organisms/chart/palette.d.ts +2 -2
- package/lib/typescript/organisms/chart/palette.d.ts.map +1 -1
- package/lib/typescript/organisms/imperativeBridge.d.ts +4 -4
- package/lib/typescript/organisms/useSlides.d.ts +8 -16
- package/lib/typescript/organisms/useSlides.d.ts.map +1 -1
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts +9 -7
- package/lib/typescript/safe-area/SafeAreaUIProvider.d.ts.map +1 -1
- package/lib/typescript/safe-area/index.d.ts.map +1 -1
- package/lib/typescript/theme/KeyboardAvoidance.d.ts +62 -0
- package/lib/typescript/theme/KeyboardAvoidance.d.ts.map +1 -0
- package/lib/typescript/theme/NativeOverlay.d.ts +43 -0
- package/lib/typescript/theme/NativeOverlay.d.ts.map +1 -0
- package/lib/typescript/theme/UIProvider.d.ts +38 -20
- package/lib/typescript/theme/UIProvider.d.ts.map +1 -1
- package/lib/typescript/theme/colors.d.ts +13 -13
- package/lib/typescript/theme/colors.d.ts.map +1 -1
- package/lib/typescript/theme/createStyles.d.ts +20 -14
- package/lib/typescript/theme/createStyles.d.ts.map +1 -1
- package/lib/typescript/theme/createTheme.d.ts +5 -5
- package/lib/typescript/theme/index.d.ts +1 -1
- package/lib/typescript/theme/index.d.ts.map +1 -1
- package/lib/typescript/theme/insets.d.ts +1 -1
- package/lib/typescript/theme/insets.d.ts.map +1 -1
- package/lib/typescript/theme/labels.d.ts +57 -2
- package/lib/typescript/theme/labels.d.ts.map +1 -1
- package/lib/typescript/theme/palettes.d.ts +25 -19
- package/lib/typescript/theme/palettes.d.ts.map +1 -1
- package/lib/typescript/theme/tokens.d.ts +15 -8
- package/lib/typescript/theme/tokens.d.ts.map +1 -1
- package/lib/typescript/theme/types.d.ts +7 -7
- package/lib/typescript/theme/types.d.ts.map +1 -1
- package/lib/typescript/theme/useKeyboardField.d.ts +17 -0
- package/lib/typescript/theme/useKeyboardField.d.ts.map +1 -0
- package/lib/typescript/theme/useReduceMotion.d.ts +7 -0
- package/lib/typescript/theme/useReduceMotion.d.ts.map +1 -0
- package/llms.txt +4 -4
- package/package.json +15 -14
- package/registry/alert-provider.json +4 -3
- package/registry/alert.json +3 -2
- package/registry/avatar-header.json +1 -1
- package/registry/avatar.json +3 -2
- package/registry/badge.json +1 -1
- package/registry/bottom-sheet.json +1 -1
- package/registry/button.json +3 -2
- package/registry/card.json +1 -1
- package/registry/chart.json +5 -5
- package/registry/checkbox.json +3 -2
- package/registry/core.json +31 -15
- package/registry/date-field.json +1 -1
- package/registry/date-picker.json +3 -2
- package/registry/divider.json +1 -1
- package/registry/empty-state.json +4 -2
- package/registry/fab.json +3 -2
- package/registry/form-actions.json +3 -2
- package/registry/gradient.json +1 -1
- package/registry/icon-button.json +3 -2
- package/registry/image.json +1 -1
- package/registry/index.json +79 -61
- package/registry/info-row.json +1 -1
- package/registry/input.json +5 -1
- package/registry/key-value-row.json +1 -1
- package/registry/list.json +3 -1
- package/registry/manifest.json +3 -1
- package/registry/modal.json +1 -1
- package/registry/navigation-bar.json +1 -1
- package/registry/option-card.json +3 -2
- package/registry/option-wheel.json +1 -1
- package/registry/pressable-scale.json +3 -2
- package/registry/reorderable-list.json +1 -1
- package/registry/screen.json +1 -1
- package/registry/search-list.json +7 -1
- package/registry/segmented-control.json +1 -1
- package/registry/select.json +1 -1
- package/registry/shiny-text.json +1 -1
- package/registry/skeleton.json +3 -2
- package/registry/slides.json +2 -2
- package/registry/spinner.json +1 -1
- package/registry/stepper.json +1 -1
- package/registry/steps.json +1 -1
- package/registry/symmetric-grid.json +1 -1
- package/registry/theme-toggle.json +1 -1
- package/registry/timeline.json +1 -1
- package/registry/title.json +1 -1
- package/registry/toast-provider.json +2 -2
- package/registry/toast.json +1 -1
- package/registry/transition.json +1 -1
- package/registry/wizard.json +1 -1
- package/src/atoms/Avatar.tsx +117 -26
- package/src/atoms/Badge.tsx +20 -9
- package/src/atoms/Button.tsx +102 -30
- package/src/atoms/Card.tsx +23 -3
- package/src/atoms/Checkbox.tsx +49 -12
- package/src/atoms/Divider.tsx +34 -4
- package/src/atoms/EmptyState.tsx +63 -16
- package/src/atoms/Fab.tsx +56 -9
- package/src/atoms/Gradient.tsx +92 -41
- package/src/atoms/IconButton.tsx +27 -4
- package/src/atoms/Image.tsx +74 -28
- package/src/atoms/Input.tsx +129 -19
- package/src/atoms/KeyValueRow.tsx +72 -28
- package/src/atoms/PressableScale.tsx +31 -7
- package/src/atoms/ShinyText.tsx +31 -31
- package/src/atoms/Skeleton.tsx +37 -17
- package/src/atoms/Spinner.tsx +87 -24
- package/src/atoms/Text.tsx +66 -6
- package/src/atoms/Transition.tsx +40 -44
- package/src/atoms/index.ts +3 -3
- package/src/atoms/inputValidation.ts +59 -0
- package/src/icons/Icon.tsx +4 -4
- package/src/icons/defaultIcons.tsx +445 -22
- package/src/icons/index.ts +2 -2
- package/src/icons/types.ts +26 -4
- package/src/molecules/AvatarHeader.tsx +88 -34
- package/src/molecules/FormActions.tsx +36 -6
- package/src/molecules/InfoRow.tsx +39 -12
- package/src/molecules/OptionCard.tsx +55 -20
- package/src/molecules/SegmentedControl.tsx +135 -15
- package/src/molecules/Stepper.tsx +73 -19
- package/src/molecules/Steps.tsx +121 -39
- package/src/molecules/SymmetricGrid.tsx +28 -12
- package/src/organisms/Alert.tsx +97 -26
- package/src/organisms/AlertProvider.tsx +13 -13
- package/src/organisms/BottomSheet.tsx +115 -43
- package/src/organisms/Chart.tsx +193 -164
- package/src/organisms/DateField.tsx +40 -15
- package/src/organisms/DatePicker.tsx +53 -32
- package/src/organisms/List.tsx +64 -15
- package/src/organisms/Modal.tsx +122 -63
- package/src/organisms/NavigationBar.tsx +73 -23
- package/src/organisms/OptionWheel.tsx +70 -66
- package/src/organisms/ReorderableList.tsx +49 -27
- package/src/organisms/Screen.tsx +79 -42
- package/src/organisms/SearchList.tsx +84 -20
- package/src/organisms/Select.tsx +63 -29
- package/src/organisms/Slides.tsx +63 -44
- package/src/organisms/ThemeToggle.tsx +15 -6
- package/src/organisms/Timeline.tsx +79 -62
- package/src/organisms/Toast.tsx +50 -15
- package/src/organisms/ToastProvider.tsx +17 -13
- package/src/organisms/Wizard.tsx +58 -21
- package/src/organisms/chart/frame.tsx +35 -35
- package/src/organisms/chart/marks.tsx +53 -53
- package/src/organisms/chart/math.ts +93 -94
- package/src/organisms/chart/palette.ts +28 -28
- package/src/organisms/imperativeBridge.ts +5 -5
- package/src/organisms/useSlides.ts +66 -31
- package/src/safe-area/SafeAreaUIProvider.tsx +9 -70
- package/src/safe-area/index.ts +1 -0
- package/src/theme/KeyboardAvoidance.tsx +216 -0
- package/src/theme/NativeOverlay.tsx +269 -0
- package/src/theme/UIProvider.tsx +109 -46
- package/src/theme/colors.ts +21 -21
- package/src/theme/createStyles.ts +23 -19
- package/src/theme/createTheme.ts +6 -6
- package/src/theme/index.ts +1 -1
- package/src/theme/insets.ts +1 -1
- package/src/theme/labels.ts +85 -2
- package/src/theme/palettes.ts +33 -25
- package/src/theme/tokens.ts +27 -13
- package/src/theme/types.ts +7 -7
- package/src/theme/useKeyboardField.ts +33 -0
- package/src/theme/useReduceMotion.ts +27 -0
package/src/organisms/Chart.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React, { createContext, memo, useCallback, useContext, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Pressable,
|
|
4
4
|
Text,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import { contrast } from '../theme/colors';
|
|
12
12
|
import { createStyles } from '../theme/createStyles';
|
|
13
13
|
import { useAllowFontScaling, useLabels, useTheme } from '../theme/UIProvider';
|
|
14
|
+
import { useReduceMotion } from '../theme/useReduceMotion';
|
|
14
15
|
import { SegmentedControl } from '../molecules/SegmentedControl';
|
|
15
16
|
import { Bar, Dot, Polyline, Wedge } from './chart/marks';
|
|
16
17
|
import { AxisLabels, CartesianGrid, Legend, RadarGrid, Tooltip, type LegendItem, type TooltipRow } from './chart/frame';
|
|
@@ -43,11 +44,11 @@ export type { ChartRow } from './chart/math';
|
|
|
43
44
|
export type ChartType = 'bar' | 'line' | 'area' | 'pie' | 'donut' | 'radar';
|
|
44
45
|
|
|
45
46
|
export interface ChartSeries {
|
|
46
|
-
/**
|
|
47
|
+
/** Column of `data` this series reads. */
|
|
47
48
|
key: string;
|
|
48
|
-
/**
|
|
49
|
+
/** Text shown in the legend and tooltip. Defaults to `key`. */
|
|
49
50
|
label?: string;
|
|
50
|
-
/**
|
|
51
|
+
/** Overrides the color derived from the theme. */
|
|
51
52
|
color?: string;
|
|
52
53
|
}
|
|
53
54
|
|
|
@@ -57,9 +58,9 @@ export interface ChartFilterOption {
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
61
|
+
* A filter in the top bar. Chart doesn't filter anything on its own: it shows
|
|
62
|
+
* the control and reports. Whoever has the data decides what "last 7 days"
|
|
63
|
+
* means, and that can't be guessed from here.
|
|
63
64
|
*/
|
|
64
65
|
export interface ChartFilter {
|
|
65
66
|
key: string;
|
|
@@ -70,130 +71,147 @@ export interface ChartFilter {
|
|
|
70
71
|
|
|
71
72
|
export interface ChartSelection {
|
|
72
73
|
/**
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
74
|
+
* Row identity, stable across a `window` or decimation. Comes from
|
|
75
|
+
* `selectBy`; without it, it is the index, which does not survive the data
|
|
76
|
+
* shifting.
|
|
76
77
|
*/
|
|
77
78
|
id: string;
|
|
78
79
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
80
|
+
* Index within the **drawn** rows, not `data`: with `window` or decimation
|
|
81
|
+
* they are not the same list. Use `row` to get back to the datum.
|
|
81
82
|
*/
|
|
82
83
|
index: number;
|
|
83
|
-
/**
|
|
84
|
+
/** The whole row, without resolving the index against anything. */
|
|
84
85
|
row: ChartRow;
|
|
85
|
-
/**
|
|
86
|
+
/** Value of `xKey` in that row. */
|
|
86
87
|
label: string;
|
|
87
|
-
/**
|
|
88
|
+
/** Series that was touched. In a pie it is the row, which is the category there. */
|
|
88
89
|
seriesKey: string;
|
|
89
90
|
value: number;
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
interface ChartBaseProps {
|
|
94
|
+
/** Rows: one per category, with the label in `xKey` and one column per series. */
|
|
93
95
|
data: ChartRow[];
|
|
94
96
|
/**
|
|
95
|
-
* Series
|
|
96
|
-
*
|
|
97
|
+
* Series to draw. 'pie'/'donut' only use the first one: a pie's categories
|
|
98
|
+
* are the rows, not the columns.
|
|
97
99
|
*/
|
|
98
100
|
series: ChartSeries[];
|
|
99
|
-
/**
|
|
101
|
+
/** Column holding each row's label. @default 'x' */
|
|
100
102
|
xKey?: string;
|
|
101
103
|
/**
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
104
|
+
* Stable identity of a row. Without it the selection is stored by index,
|
|
105
|
+
* and in a sliding window the index shifts: the highlighted point ends up
|
|
106
|
+
* pointing at another datum without anyone touching it. With it the
|
|
107
|
+
* highlight follows the datum and disappears only when it leaves the window.
|
|
106
108
|
*/
|
|
107
109
|
selectBy?: (row: ChartRow, index: number) => string;
|
|
108
110
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
+
* Draws only the last N rows. It is the sliding window of a live chart: the
|
|
112
|
+
* code pushing data doesn't have to trim it on every tick.
|
|
111
113
|
*/
|
|
112
114
|
window?: number;
|
|
113
|
-
/**
|
|
115
|
+
/** Height of the plot area, excluding filters and legend. @default 220 */
|
|
114
116
|
height?: number;
|
|
115
117
|
/**
|
|
116
|
-
* 'toggle'
|
|
117
|
-
*
|
|
118
|
+
* 'toggle' turns the legend into the cheapest filter a chart has: tapping a
|
|
119
|
+
* series hides it. @default 'auto' (toggle with 2+ series, none with one)
|
|
118
120
|
*/
|
|
119
121
|
legend?: 'auto' | 'none' | 'static' | 'toggle';
|
|
120
|
-
/**
|
|
122
|
+
/** Hidden series (controlled). Without it, Chart tracks them itself. */
|
|
121
123
|
hiddenKeys?: string[];
|
|
122
|
-
/** @default [] */
|
|
124
|
+
/** Series hidden at first (uncontrolled). @default [] */
|
|
123
125
|
defaultHiddenKeys?: string[];
|
|
126
|
+
/** Called when the legend shows or hides a series. */
|
|
124
127
|
onHiddenKeysChange?: (keys: string[]) => void;
|
|
125
|
-
/**
|
|
128
|
+
/** Controls above the chart, one per filter. */
|
|
126
129
|
filters?: ChartFilter[];
|
|
127
|
-
/**
|
|
130
|
+
/** Highlighted point (controlled). `null` means none. */
|
|
128
131
|
selected?: ChartSelection | null;
|
|
132
|
+
/** Called when a category is tapped, with `null` when it is released. */
|
|
129
133
|
onSelect?: (selection: ChartSelection | null) => void;
|
|
130
|
-
/**
|
|
134
|
+
/** Bubble with the values of the touched category. @default true */
|
|
131
135
|
tooltip?: boolean;
|
|
132
|
-
/** @default
|
|
136
|
+
/** Formats values on the axis, tooltip and slices. @default compact format: 1.2k, 3.4M */
|
|
133
137
|
formatValue?: (value: number) => string;
|
|
134
|
-
/** @default true */
|
|
138
|
+
/** Marks grow in on mount and morph on data changes (off with Reduce Motion). @default true */
|
|
135
139
|
animate?: boolean;
|
|
136
|
-
/**
|
|
140
|
+
/** Duration in ms of the marks' animation. @default tokens.duration.slow * 2 */
|
|
137
141
|
duration?: number;
|
|
138
|
-
/**
|
|
142
|
+
/** Text shown when there is nothing left to draw. */
|
|
139
143
|
emptyText?: string;
|
|
140
|
-
/**
|
|
144
|
+
/** Required: a chart has no text that describes it. */
|
|
141
145
|
accessibilityLabel: string;
|
|
146
|
+
/**
|
|
147
|
+
* Color behind the chart. The donut hole and the ring around points are
|
|
148
|
+
* painted with it, so they must match whatever the chart sits on.
|
|
149
|
+
* @default colors.surfaceRaised (a Chart usually lives in a Card)
|
|
150
|
+
*/
|
|
151
|
+
surfaceColor?: string;
|
|
142
152
|
style?: StyleProp<ViewStyle>;
|
|
143
153
|
testID?: string;
|
|
144
154
|
}
|
|
145
155
|
|
|
156
|
+
/** Background the marks paint "holes" with (donut center, point rings). */
|
|
157
|
+
const ChartSurfaceContext = createContext<string | undefined>(undefined);
|
|
158
|
+
function useChartSurface(): string {
|
|
159
|
+
const theme = useTheme();
|
|
160
|
+
return useContext(ChartSurfaceContext) ?? theme.colors.surfaceRaised;
|
|
161
|
+
}
|
|
162
|
+
|
|
146
163
|
interface CartesianProps {
|
|
147
164
|
/**
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
165
|
+
* Fixes the value axis. By default it is recomputed with every datum, which
|
|
166
|
+
* is right for a static chart and worst for a live one: a higher value
|
|
167
|
+
* arrives, the whole scale shifts and the line jumps even though the data
|
|
168
|
+
* didn't move.
|
|
152
169
|
*
|
|
153
|
-
* - `[min, max]` —
|
|
154
|
-
* - `'sticky'` —
|
|
155
|
-
*
|
|
170
|
+
* - `[min, max]` — exact, not rounded to nice numbers.
|
|
171
|
+
* - `'sticky'` — starts from the data and grows when something doesn't fit,
|
|
172
|
+
* but never shrinks back.
|
|
156
173
|
*/
|
|
157
174
|
domain?: [number, number] | 'sticky';
|
|
158
|
-
/**
|
|
175
|
+
/** Reference lines on the value axis. @default true */
|
|
159
176
|
grid?: boolean;
|
|
160
|
-
/**
|
|
177
|
+
/** Target tick count on the value axis; rounding may yield one more or one fewer. @default 4 */
|
|
161
178
|
ticks?: number;
|
|
162
|
-
/**
|
|
179
|
+
/** Labels on the horizontal axis. @default true */
|
|
163
180
|
xAxis?: boolean;
|
|
164
|
-
/**
|
|
181
|
+
/** Labels on the vertical axis. @default true */
|
|
165
182
|
yAxis?: boolean;
|
|
166
183
|
}
|
|
167
184
|
|
|
168
185
|
interface BarChartProps extends CartesianProps {
|
|
186
|
+
/** Kind of chart. Props marked "Only with type" depend on it. */
|
|
169
187
|
type: 'bar';
|
|
170
|
-
/** 'horizontal'
|
|
188
|
+
/** 'horizontal' puts the categories on the vertical axis. @default 'vertical' */
|
|
171
189
|
orientation?: 'vertical' | 'horizontal';
|
|
172
|
-
/**
|
|
190
|
+
/** Stacks the series instead of placing them side by side. @default false */
|
|
173
191
|
stacked?: boolean;
|
|
174
|
-
/**
|
|
192
|
+
/** Radius of each bar's free end. @default radius.xs */
|
|
175
193
|
barRadius?: number;
|
|
176
194
|
}
|
|
177
195
|
|
|
178
196
|
interface LineChartProps extends CartesianProps {
|
|
179
197
|
type: 'line';
|
|
180
198
|
/**
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
* `false`
|
|
199
|
+
* Maximum number of points to draw, picked with LTTB. Defaults to a value
|
|
200
|
+
* derived from the measured width: more than one point every two pixels
|
|
201
|
+
* isn't visible but still costs. `false` draws them all.
|
|
184
202
|
*/
|
|
185
203
|
decimate?: number | false;
|
|
186
|
-
/** Catmull-Rom
|
|
204
|
+
/** Catmull-Rom curves instead of straight segments. @default false */
|
|
187
205
|
smooth?: boolean;
|
|
188
|
-
/** @default 2 */
|
|
206
|
+
/** Line width in pt. @default 2 */
|
|
189
207
|
thickness?: number;
|
|
190
|
-
/**
|
|
208
|
+
/** A dot on each datum. @default true */
|
|
191
209
|
dots?: boolean;
|
|
192
210
|
}
|
|
193
211
|
|
|
194
212
|
interface AreaChartProps extends CartesianProps {
|
|
195
213
|
type: 'area';
|
|
196
|
-
/**
|
|
214
|
+
/** Same as in 'line'. */
|
|
197
215
|
decimate?: number | false;
|
|
198
216
|
smooth?: boolean;
|
|
199
217
|
thickness?: number;
|
|
@@ -201,20 +219,21 @@ interface AreaChartProps extends CartesianProps {
|
|
|
201
219
|
dots?: boolean;
|
|
202
220
|
/** @default false */
|
|
203
221
|
stacked?: boolean;
|
|
204
|
-
/**
|
|
222
|
+
/** Opacity of the fill under the line. @default 0.22 */
|
|
205
223
|
fillOpacity?: number;
|
|
206
224
|
}
|
|
207
225
|
|
|
208
226
|
interface PieBaseProps {
|
|
209
|
-
/**
|
|
227
|
+
/** Hole as a fraction of the radius, 0–0.9. @default 0 for 'pie', 0.6 for 'donut' */
|
|
210
228
|
innerRadius?: number;
|
|
211
|
-
/**
|
|
229
|
+
/** What to write on each slice. @default 'percent' */
|
|
212
230
|
sliceLabels?: 'none' | 'percent' | 'value';
|
|
213
231
|
}
|
|
214
232
|
|
|
215
|
-
// 'pie'
|
|
216
|
-
//
|
|
217
|
-
//
|
|
233
|
+
// 'pie' and 'donut' are kept separate even though they share everything: with
|
|
234
|
+
// a single member whose `type` were `'pie' | 'donut'`, TypeScript doesn't drop
|
|
235
|
+
// that member from the union when ruling it out, and the rest of the component
|
|
236
|
+
// stops narrowing.
|
|
218
237
|
interface PieChartProps extends PieBaseProps {
|
|
219
238
|
type: 'pie';
|
|
220
239
|
}
|
|
@@ -226,13 +245,13 @@ interface DonutChartProps extends PieBaseProps {
|
|
|
226
245
|
interface RadarChartProps {
|
|
227
246
|
type: 'radar';
|
|
228
247
|
/**
|
|
229
|
-
*
|
|
230
|
-
*
|
|
248
|
+
* Fixes the axes' range. A radar measures from the center, so the minimum is
|
|
249
|
+
* always 0 and only `max` of `[min, max]` is used.
|
|
231
250
|
*/
|
|
232
251
|
domain?: [number, number] | 'sticky';
|
|
233
|
-
/**
|
|
252
|
+
/** Rings of the web. @default 4 */
|
|
234
253
|
levels?: number;
|
|
235
|
-
/**
|
|
254
|
+
/** Fills the polygon in addition to drawing its outline. @default true */
|
|
236
255
|
fill?: boolean;
|
|
237
256
|
thickness?: number;
|
|
238
257
|
/** @default true */
|
|
@@ -244,24 +263,24 @@ export type ChartProps = ChartBaseProps &
|
|
|
244
263
|
|
|
245
264
|
const DEFAULT_HEIGHT = 220;
|
|
246
265
|
const DEFAULT_TICKS = 4;
|
|
247
|
-
/**
|
|
266
|
+
/** Floor of the value-label gutter, on the left. */
|
|
248
267
|
const VALUE_GUTTER = 38;
|
|
249
268
|
/**
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
269
|
+
* Estimated width of a label character. React Native doesn't measure text
|
|
270
|
+
* without rendering it, and measuring to decide the layout would make the
|
|
271
|
+
* chart show up shifted for a frame; at `fontSize.xs` a digit is around
|
|
272
|
+
* 0.6em, and too much is better than too little — extra room, no clipped number.
|
|
254
273
|
*/
|
|
255
274
|
const VALUE_CHAR = 6.5;
|
|
256
|
-
/**
|
|
275
|
+
/** Gutter cap: a wide axis can't eat the plot. */
|
|
257
276
|
const VALUE_GUTTER_MAX = 0.3;
|
|
258
|
-
/**
|
|
277
|
+
/** Category gutter when they go on the left (horizontal bars). */
|
|
259
278
|
const CATEGORY_GUTTER = 64;
|
|
260
|
-
/**
|
|
279
|
+
/** Gutter for the bottom labels. */
|
|
261
280
|
const BOTTOM_GUTTER = 16;
|
|
262
|
-
/**
|
|
281
|
+
/** Fraction of the band width taken by the bars; the rest is room. */
|
|
263
282
|
const BAND_FILL = 0.7;
|
|
264
|
-
/**
|
|
283
|
+
/** Room around the radar so the axis labels fit. */
|
|
265
284
|
const RADAR_INSET = 26;
|
|
266
285
|
const DIM_OPACITY = 0.3;
|
|
267
286
|
|
|
@@ -293,7 +312,7 @@ const useStyles = createStyles((theme) => ({
|
|
|
293
312
|
},
|
|
294
313
|
}));
|
|
295
314
|
|
|
296
|
-
/**
|
|
315
|
+
/** Controlled or own state, with the same contract in both cases. */
|
|
297
316
|
function useControlled<T>(controlled: T | undefined, fallback: T): [T, (next: T) => void, boolean] {
|
|
298
317
|
const [own, setOwn] = useState(fallback);
|
|
299
318
|
const isControlled = controlled !== undefined;
|
|
@@ -301,10 +320,10 @@ function useControlled<T>(controlled: T | undefined, fallback: T): [T, (next: T)
|
|
|
301
320
|
}
|
|
302
321
|
|
|
303
322
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
323
|
+
* Resolves the value axis domain from what the consumer asked for. In
|
|
324
|
+
* 'sticky' the reference lives in a ref: what matters isn't this render's
|
|
325
|
+
* domain but the widest one seen so far, and keeping it in state would fire
|
|
326
|
+
* an extra render for every tick that widens the axis.
|
|
308
327
|
*/
|
|
309
328
|
function useDomain(measured: [number, number], domain: [number, number] | 'sticky' | undefined): [number, number] {
|
|
310
329
|
const widest = useRef<[number, number] | null>(null);
|
|
@@ -318,19 +337,20 @@ function useDomain(measured: [number, number], domain: [number, number] | 'stick
|
|
|
318
337
|
|
|
319
338
|
/**
|
|
320
339
|
* Chart
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
340
|
+
* Bars (vertical, horizontal, grouped, stacked), line, area, pie, donut and
|
|
341
|
+
* radar in a single component, because what changes between them is the mark
|
|
342
|
+
* being drawn and not the rest: data, scale, axes, legend, tooltip, selection
|
|
343
|
+
* and filters are the same six mechanisms in all of them.
|
|
325
344
|
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
345
|
+
* It is drawn with `View`: React Native ships no vector canvas and the library
|
|
346
|
+
* can't add one. The three primitives are in `chart/marks.tsx` and the whole
|
|
347
|
+
* geometry, without React, in `chart/math.ts`.
|
|
329
348
|
*
|
|
330
|
-
* Gestalt:
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
349
|
+
* Gestalt: common fate — when you tap a category, everything that isn't it
|
|
350
|
+
* drops to {@link DIM_OPACITY} at once, so what is highlighted reads as a group
|
|
351
|
+
* and not as a loose mark. The legend uses similarity: the same color as the
|
|
352
|
+
* series, which is why it can turn it off without having to explain what it
|
|
353
|
+
* turns off.
|
|
334
354
|
*/
|
|
335
355
|
export function Chart(props: ChartProps) {
|
|
336
356
|
const {
|
|
@@ -349,10 +369,11 @@ export function Chart(props: ChartProps) {
|
|
|
349
369
|
onSelect,
|
|
350
370
|
tooltip = true,
|
|
351
371
|
formatValue = formatNumber,
|
|
352
|
-
animate = true,
|
|
372
|
+
animate: animateProp = true,
|
|
353
373
|
duration,
|
|
354
374
|
emptyText,
|
|
355
375
|
accessibilityLabel,
|
|
376
|
+
surfaceColor,
|
|
356
377
|
style,
|
|
357
378
|
testID,
|
|
358
379
|
} = props;
|
|
@@ -361,6 +382,9 @@ export function Chart(props: ChartProps) {
|
|
|
361
382
|
const styles = useStyles();
|
|
362
383
|
const allowFontScaling = useAllowFontScaling();
|
|
363
384
|
const uiLabels = useLabels();
|
|
385
|
+
// Reduce Motion: the marks appear in their final shape instead of growing.
|
|
386
|
+
const reduceMotion = useReduceMotion();
|
|
387
|
+
const animate = animateProp && !reduceMotion;
|
|
364
388
|
const [width, setWidth] = useState(0);
|
|
365
389
|
|
|
366
390
|
const [hidden, setHidden, hiddenIsControlled] = useControlled(hiddenKeys, defaultHiddenKeys ?? []);
|
|
@@ -371,15 +395,15 @@ export function Chart(props: ChartProps) {
|
|
|
371
395
|
const decimate = polyline ? props.decimate : false;
|
|
372
396
|
|
|
373
397
|
/**
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
398
|
+
* What gets drawn: the window of `data`, and from that the points that fit.
|
|
399
|
+
* Decimation runs over the whole row, chosen with the first visible series:
|
|
400
|
+
* the series share the x axis, so keeping different indexes per series would
|
|
401
|
+
* break the alignment, the touch layer and the tooltip.
|
|
378
402
|
*/
|
|
379
403
|
const rows = useMemo(() => {
|
|
380
404
|
const windowed = windowSize && windowSize > 0 ? data.slice(-windowSize) : data;
|
|
381
405
|
if (!polyline || decimate === false || width === 0) return windowed;
|
|
382
|
-
//
|
|
406
|
+
// One point every two pixels: more can't be seen but still has to be paid for.
|
|
383
407
|
const target = typeof decimate === 'number' ? decimate : Math.floor(width / 2);
|
|
384
408
|
if (windowed.length <= target) return windowed;
|
|
385
409
|
const lead = series.find((item) => !hidden.includes(item.key))?.key ?? series[0]?.key;
|
|
@@ -394,10 +418,10 @@ export function Chart(props: ChartProps) {
|
|
|
394
418
|
);
|
|
395
419
|
|
|
396
420
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
421
|
+
* The selection is stored by `id` and resolved against the current rows:
|
|
422
|
+
* if the datum shifted, the highlight follows it; if it left the window, it
|
|
423
|
+
* disappears. Blindly reusing the index would point at the datum that ended
|
|
424
|
+
* up in that spot, which isn't the one anyone picked.
|
|
401
425
|
*/
|
|
402
426
|
const selection = useMemo(() => {
|
|
403
427
|
if (!pick) return null;
|
|
@@ -413,8 +437,8 @@ export function Chart(props: ChartProps) {
|
|
|
413
437
|
};
|
|
414
438
|
}, [pick, ids, rows, labels]);
|
|
415
439
|
|
|
416
|
-
//
|
|
417
|
-
//
|
|
440
|
+
// In a pie the categories are the rows; in the rest, the columns. The
|
|
441
|
+
// color, the legend and what a tap on it turns off depend on that.
|
|
418
442
|
const palette = seriesPalette(theme, Math.max(1, isPie ? rows.length : series.length));
|
|
419
443
|
const entries: LegendItem[] = useMemo(
|
|
420
444
|
() =>
|
|
@@ -441,9 +465,9 @@ export function Chart(props: ChartProps) {
|
|
|
441
465
|
);
|
|
442
466
|
|
|
443
467
|
/**
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
468
|
+
* The plots report what was tapped —row and series— and the whole selection
|
|
469
|
+
* is built here: it is the only place that knows `selectBy`, the labels and
|
|
470
|
+
* the actual rows, so the three don't repeat the building.
|
|
447
471
|
*/
|
|
448
472
|
const applySelection = useCallback(
|
|
449
473
|
(hit: { index: number; seriesKey: string } | null) => {
|
|
@@ -459,9 +483,9 @@ export function Chart(props: ChartProps) {
|
|
|
459
483
|
value: toNumber(row[hit.seriesKey]) ?? 0,
|
|
460
484
|
}
|
|
461
485
|
: null;
|
|
462
|
-
//
|
|
463
|
-
//
|
|
464
|
-
//
|
|
486
|
+
// Tapping what is already selected releases it: without that there would
|
|
487
|
+
// be no way back to the whole chart without tapping outside, and
|
|
488
|
+
// "outside" doesn't always exist on a scrolling screen.
|
|
465
489
|
const same = next && selection && next.id === selection.id && next.seriesKey === selection.seriesKey;
|
|
466
490
|
const value = same ? null : next;
|
|
467
491
|
if (!selectionIsControlled) setPick(value);
|
|
@@ -493,6 +517,7 @@ export function Chart(props: ChartProps) {
|
|
|
493
517
|
};
|
|
494
518
|
|
|
495
519
|
return (
|
|
520
|
+
<ChartSurfaceContext.Provider value={surfaceColor ?? theme.colors.surfaceRaised}>
|
|
496
521
|
<View style={[styles.root, style]} testID={testID} accessible={false}>
|
|
497
522
|
{filters && filters.length > 0 ? (
|
|
498
523
|
<View style={styles.filters}>
|
|
@@ -565,19 +590,20 @@ export function Chart(props: ChartProps) {
|
|
|
565
590
|
<Legend items={entries} hidden={hidden} onToggle={toggleable ? applyHidden : undefined} testID={testID && `${testID}-legend`} />
|
|
566
591
|
) : null}
|
|
567
592
|
</View>
|
|
593
|
+
</ChartSurfaceContext.Provider>
|
|
568
594
|
);
|
|
569
595
|
}
|
|
570
596
|
|
|
571
597
|
Chart.displayName = 'Chart';
|
|
572
598
|
|
|
573
|
-
// ──
|
|
599
|
+
// ── what the three plots share ─────────────────────────────────────────────
|
|
574
600
|
|
|
575
601
|
interface PlotProps {
|
|
576
602
|
rows: ChartRow[];
|
|
577
603
|
labels: string[];
|
|
578
|
-
/**
|
|
604
|
+
/** All categories, with their color: the color doesn't change when one is turned off. */
|
|
579
605
|
entries: LegendItem[];
|
|
580
|
-
/**
|
|
606
|
+
/** The ones still turned on. */
|
|
581
607
|
visible: LegendItem[];
|
|
582
608
|
width: number;
|
|
583
609
|
height: number;
|
|
@@ -585,13 +611,13 @@ interface PlotProps {
|
|
|
585
611
|
animate: boolean;
|
|
586
612
|
duration: number;
|
|
587
613
|
selection: ChartSelection | null;
|
|
588
|
-
/**
|
|
614
|
+
/** Reports what was tapped; Chart builds the selection. `null` releases it. */
|
|
589
615
|
onPick: (hit: { index: number; seriesKey: string } | null) => void;
|
|
590
616
|
tooltip: boolean;
|
|
591
617
|
testID?: string;
|
|
592
618
|
}
|
|
593
619
|
|
|
594
|
-
/**
|
|
620
|
+
/** Tooltip rows for a category on the x axis. */
|
|
595
621
|
function tooltipRowsAt(rows: ChartRow[], index: number, visible: LegendItem[], format: (value: number) => string): TooltipRow[] {
|
|
596
622
|
const row = rows[index];
|
|
597
623
|
if (!row) return [];
|
|
@@ -603,7 +629,7 @@ function tooltipRowsAt(rows: ChartRow[], index: number, visible: LegendItem[], f
|
|
|
603
629
|
.filter((item): item is TooltipRow => item !== null);
|
|
604
630
|
}
|
|
605
631
|
|
|
606
|
-
// ──
|
|
632
|
+
// ── bars, line and area ────────────────────────────────────────────────────
|
|
607
633
|
|
|
608
634
|
interface CartesianPlotProps extends PlotProps {
|
|
609
635
|
type: 'bar' | 'line' | 'area';
|
|
@@ -621,10 +647,10 @@ interface CartesianPlotProps extends PlotProps {
|
|
|
621
647
|
yAxis: boolean;
|
|
622
648
|
}
|
|
623
649
|
|
|
624
|
-
/**
|
|
650
|
+
/** Width of one strip of the area fill, in pixels. Thinner = more views. */
|
|
625
651
|
const STRIP_WIDTH = 4;
|
|
626
652
|
const MAX_STRIPS = 140;
|
|
627
|
-
/**
|
|
653
|
+
/** Room between two bars of the same group. */
|
|
628
654
|
const GROUP_GAP = 2;
|
|
629
655
|
|
|
630
656
|
const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
@@ -657,31 +683,32 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
657
683
|
} = props;
|
|
658
684
|
|
|
659
685
|
const theme = useTheme();
|
|
686
|
+
const surface = useChartSurface();
|
|
660
687
|
const horizontal = type === 'bar' && orientation === 'horizontal';
|
|
661
688
|
const keys = useMemo(() => visible.map((entry) => entry.key), [visible]);
|
|
662
689
|
|
|
663
690
|
const bottomGutter = xAxis ? BOTTOM_GUTTER : 0;
|
|
664
691
|
|
|
665
|
-
//
|
|
666
|
-
//
|
|
692
|
+
// The line may not touch zero (a temperature, a ranking); a bar does have
|
|
693
|
+
// to, because its length is what states the value.
|
|
667
694
|
const measured = useMemo(
|
|
668
695
|
() => extent(rows, keys, { stacked, includeZero: type !== 'line' }),
|
|
669
696
|
[rows, keys, stacked, type]
|
|
670
697
|
);
|
|
671
698
|
const [low, high] = useDomain(measured, domain);
|
|
672
699
|
|
|
673
|
-
//
|
|
674
|
-
//
|
|
700
|
+
// A hand-set domain is respected as is; a measured one (or 'sticky') is
|
|
701
|
+
// rounded, which is what makes the axis legible.
|
|
675
702
|
const nice = useMemo(
|
|
676
703
|
() => (Array.isArray(domain) ? exactTicks(low, high, tickCount) : niceScale(low, high, tickCount)),
|
|
677
704
|
[domain, low, high, tickCount]
|
|
678
705
|
);
|
|
679
706
|
|
|
680
707
|
/**
|
|
681
|
-
*
|
|
682
|
-
* `formatValue`
|
|
683
|
-
*
|
|
684
|
-
*
|
|
708
|
+
* The gutter comes from the longest label, not from a constant: with a
|
|
709
|
+
* custom `formatValue` ("$3000", "1.250 ms") a fixed width clips the number
|
|
710
|
+
* and the axis ends up saying "$30…". The ticks don't depend on the plot's
|
|
711
|
+
* width, so they can be measured before splitting it up.
|
|
685
712
|
*/
|
|
686
713
|
const leftGutter = useMemo(() => {
|
|
687
714
|
if (!yAxis) return 0;
|
|
@@ -709,7 +736,7 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
709
736
|
|
|
710
737
|
const stacks = useMemo(() => (stacked ? rows.map((row) => stackRow(row, keys)) : null), [stacked, rows, keys]);
|
|
711
738
|
|
|
712
|
-
/**
|
|
739
|
+
/** A series' points: `to` is the value, `from` the floor it is filled from. */
|
|
713
740
|
const pointsFor = useCallback(
|
|
714
741
|
(key: string, edge: 'to' | 'from'): Point[] => {
|
|
715
742
|
const out: Point[] = [];
|
|
@@ -731,8 +758,8 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
731
758
|
|
|
732
759
|
const pickAt = useCallback(
|
|
733
760
|
(index: number, event: GestureResponderEvent) => {
|
|
734
|
-
//
|
|
735
|
-
//
|
|
761
|
+
// Which series the finger landed on: the one whose mark is closest to
|
|
762
|
+
// the touch on the value axis. With a single series it is always that one.
|
|
736
763
|
const touch = (horizontal ? event?.nativeEvent?.locationX : event?.nativeEvent?.locationY) ?? 0;
|
|
737
764
|
let bestKey = keys[0] ?? '';
|
|
738
765
|
let bestDistance = Infinity;
|
|
@@ -768,7 +795,7 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
768
795
|
|
|
769
796
|
return (
|
|
770
797
|
<>
|
|
771
|
-
{/*
|
|
798
|
+
{/* Frame: grid and labels, beneath the marks. */}
|
|
772
799
|
<View style={{ position: 'absolute', left: leftGutter, top: 0, width: plotW, height: plotH }}>
|
|
773
800
|
{grid ? (
|
|
774
801
|
<CartesianGrid
|
|
@@ -847,14 +874,14 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
847
874
|
|
|
848
875
|
return (
|
|
849
876
|
<View key={entry.key} style={{ position: 'absolute', left: 0, top: 0, width: plotW, height: plotH }}>
|
|
850
|
-
{/*
|
|
851
|
-
|
|
852
|
-
|
|
877
|
+
{/* Area: without `path` there is no fill under a curve, so it
|
|
878
|
+
is cut into vertical strips and each one asks the polyline
|
|
879
|
+
for its height. At 4px per strip the edge already reads as continuous. */}
|
|
853
880
|
{type === 'area' ? (
|
|
854
|
-
//
|
|
855
|
-
//
|
|
856
|
-
//
|
|
857
|
-
//
|
|
881
|
+
// Opacity goes on the group, not on each strip: the half
|
|
882
|
+
// pixel of overlap that hides the antialias seam is
|
|
883
|
+
// composited twice and leaves a vertical stripe every four
|
|
884
|
+
// pixels. Dimming the whole group, it is painted only once.
|
|
858
885
|
<View
|
|
859
886
|
pointerEvents="none"
|
|
860
887
|
style={{ position: 'absolute', left: 0, top: 0, width: plotW, height: plotH, opacity: fillOpacity }}
|
|
@@ -889,7 +916,7 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
889
916
|
key={index}
|
|
890
917
|
point={point}
|
|
891
918
|
color={entry.color}
|
|
892
|
-
ringColor={
|
|
919
|
+
ringColor={surface}
|
|
893
920
|
size={selection?.index === index ? 8 : 6}
|
|
894
921
|
testID={testID && `${testID}-dot-${entry.key}-${index}`}
|
|
895
922
|
/>
|
|
@@ -899,8 +926,8 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
899
926
|
);
|
|
900
927
|
})}
|
|
901
928
|
|
|
902
|
-
{/*
|
|
903
|
-
|
|
929
|
+
{/* Touch layer: a whole band per category. Tapping a 2px line is
|
|
930
|
+
impossible; tapping its column isn't. */}
|
|
904
931
|
{rows.map((row, index) => (
|
|
905
932
|
<Pressable
|
|
906
933
|
key={index}
|
|
@@ -964,7 +991,7 @@ const CartesianPlot = memo((props: CartesianPlotProps) => {
|
|
|
964
991
|
});
|
|
965
992
|
CartesianPlot.displayName = 'CartesianPlot';
|
|
966
993
|
|
|
967
|
-
// ──
|
|
994
|
+
// ── pie and donut ──────────────────────────────────────────────────────────
|
|
968
995
|
|
|
969
996
|
interface PiePlotProps extends PlotProps {
|
|
970
997
|
donut: boolean;
|
|
@@ -974,12 +1001,12 @@ interface PiePlotProps extends PlotProps {
|
|
|
974
1001
|
}
|
|
975
1002
|
|
|
976
1003
|
const DONUT_RADIUS = 0.6;
|
|
977
|
-
/**
|
|
1004
|
+
/** How far the selected slice pops out, in pixels. */
|
|
978
1005
|
const EXPLODE = 8;
|
|
979
|
-
/**
|
|
1006
|
+
/** Where the label falls, as a fraction between the hole and the edge. */
|
|
980
1007
|
const LABEL_AT = 0.62;
|
|
981
1008
|
|
|
982
|
-
/**
|
|
1009
|
+
/** White or black, whichever reads over the color. An odd color doesn't break: it falls back to `text`. */
|
|
983
1010
|
function inkOn(background: string, theme: { colors: { white: string; black: string; text: string } }): string {
|
|
984
1011
|
try {
|
|
985
1012
|
return contrast(background, theme.colors.white) >= contrast(background, theme.colors.black)
|
|
@@ -993,6 +1020,7 @@ function inkOn(background: string, theme: { colors: { white: string; black: stri
|
|
|
993
1020
|
const PiePlot = memo((props: PiePlotProps) => {
|
|
994
1021
|
const { rows, labels, entries, visible, width, height, formatValue, selection, onPick, tooltip, testID, donut, innerRadius, sliceLabels, valueKey } = props;
|
|
995
1022
|
const theme = useTheme();
|
|
1023
|
+
const surface = useChartSurface();
|
|
996
1024
|
const styles = useStyles();
|
|
997
1025
|
const allowFontScaling = useAllowFontScaling();
|
|
998
1026
|
|
|
@@ -1001,8 +1029,8 @@ const PiePlot = memo((props: PiePlotProps) => {
|
|
|
1001
1029
|
const hole = clamp(innerRadius ?? (donut ? DONUT_RADIUS : 0), 0, 0.9) * radius;
|
|
1002
1030
|
|
|
1003
1031
|
const arcs = useMemo(() => {
|
|
1004
|
-
//
|
|
1005
|
-
// 100%,
|
|
1032
|
+
// A turned-off category is worth 0: it leaves the pie and the rest share
|
|
1033
|
+
// the 100%, which is what whoever turned it off from the legend expects.
|
|
1006
1034
|
const values = rows.map((row, index) =>
|
|
1007
1035
|
visible.some((entry) => entry.key === labels[index]) ? (toNumber(row[valueKey]) ?? 0) : 0
|
|
1008
1036
|
);
|
|
@@ -1013,8 +1041,8 @@ const PiePlot = memo((props: PiePlotProps) => {
|
|
|
1013
1041
|
(event: GestureResponderEvent) => {
|
|
1014
1042
|
const point = { x: event?.nativeEvent?.locationX ?? 0, y: event?.nativeEvent?.locationY ?? 0 };
|
|
1015
1043
|
const distance = Math.hypot(point.x - center.x, point.y - center.y);
|
|
1016
|
-
//
|
|
1017
|
-
//
|
|
1044
|
+
// A donut's hole isn't part of any slice, and neither is the area
|
|
1045
|
+
// outside the circle: both release the selection.
|
|
1018
1046
|
if (distance > radius || distance < hole) return onPick(null);
|
|
1019
1047
|
const index = arcAt(arcs, angleOf(center, point));
|
|
1020
1048
|
if (index === -1) return onPick(null);
|
|
@@ -1054,7 +1082,7 @@ const PiePlot = memo((props: PiePlotProps) => {
|
|
|
1054
1082
|
width: hole * 2,
|
|
1055
1083
|
height: hole * 2,
|
|
1056
1084
|
borderRadius: hole,
|
|
1057
|
-
backgroundColor:
|
|
1085
|
+
backgroundColor: surface,
|
|
1058
1086
|
}}
|
|
1059
1087
|
/>
|
|
1060
1088
|
) : null}
|
|
@@ -1062,8 +1090,8 @@ const PiePlot = memo((props: PiePlotProps) => {
|
|
|
1062
1090
|
{sliceLabels === 'none'
|
|
1063
1091
|
? null
|
|
1064
1092
|
: arcs.map((arc) => {
|
|
1065
|
-
//
|
|
1066
|
-
//
|
|
1093
|
+
// A very thin slice has nowhere to write: the label would spill
|
|
1094
|
+
// over its neighbors and none would be readable.
|
|
1067
1095
|
if (arc.sweep < 18) return null;
|
|
1068
1096
|
const at = polar(center, hole + (radius - hole) * LABEL_AT, arc.start + arc.sweep / 2);
|
|
1069
1097
|
const color = entries[arc.index]?.color ?? theme.colors.primary;
|
|
@@ -1118,7 +1146,7 @@ interface RadarPlotProps extends PlotProps {
|
|
|
1118
1146
|
dots: boolean;
|
|
1119
1147
|
}
|
|
1120
1148
|
|
|
1121
|
-
/**
|
|
1149
|
+
/** Strips per side of the polygon when it is filled. More = cleaner edge, more views. */
|
|
1122
1150
|
const RADAR_STEPS = 5;
|
|
1123
1151
|
const RADAR_FILL_OPACITY = 0.18;
|
|
1124
1152
|
const RADAR_LABEL_WIDTH = 56;
|
|
@@ -1126,6 +1154,7 @@ const RADAR_LABEL_WIDTH = 56;
|
|
|
1126
1154
|
const RadarPlot = memo((props: RadarPlotProps) => {
|
|
1127
1155
|
const { rows, labels, visible, width, height, formatValue, selection, onPick, tooltip, testID, domain, levels, fill, thickness, dots } = props;
|
|
1128
1156
|
const theme = useTheme();
|
|
1157
|
+
const surface = useChartSurface();
|
|
1129
1158
|
const styles = useStyles();
|
|
1130
1159
|
const allowFontScaling = useAllowFontScaling();
|
|
1131
1160
|
|
|
@@ -1134,8 +1163,8 @@ const RadarPlot = memo((props: RadarPlotProps) => {
|
|
|
1134
1163
|
const angles = useMemo(() => radarAngles(rows.length), [rows.length]);
|
|
1135
1164
|
const keys = useMemo(() => visible.map((entry) => entry.key), [visible]);
|
|
1136
1165
|
|
|
1137
|
-
//
|
|
1138
|
-
//
|
|
1166
|
+
// The radar measures from the center, and the center is 0: a minimum other
|
|
1167
|
+
// than zero would make two similar values look miles apart.
|
|
1139
1168
|
const measured = useMemo(() => [0, extent(rows, keys, { includeZero: true })[1]] as [number, number], [rows, keys]);
|
|
1140
1169
|
const [, top] = useDomain(measured, domain);
|
|
1141
1170
|
|
|
@@ -1169,14 +1198,14 @@ const RadarPlot = memo((props: RadarPlotProps) => {
|
|
|
1169
1198
|
const points = pointsOf(entry.key);
|
|
1170
1199
|
return (
|
|
1171
1200
|
<View key={entry.key} style={{ position: 'absolute', left: 0, top: 0, width, height }}>
|
|
1172
|
-
{/*
|
|
1173
|
-
|
|
1201
|
+
{/* Fill: the same sector a pie draws, one per strip of the
|
|
1202
|
+
polygon, with the radius that strip gets. */}
|
|
1174
1203
|
{fill ? (
|
|
1175
|
-
//
|
|
1176
|
-
//
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
//
|
|
1204
|
+
// Opacity goes on the group, not on each strip. Per strip, the
|
|
1205
|
+
// 0.4° overlap that hides the antialias seam is composited
|
|
1206
|
+
// twice and leaves a darker radius at each cut: the fill ends
|
|
1207
|
+
// up looking like a spider web. Applied to the group, the strips
|
|
1208
|
+
// paint opaque against each other and the whole is dimmed once.
|
|
1180
1209
|
<View
|
|
1181
1210
|
pointerEvents="none"
|
|
1182
1211
|
style={{ position: 'absolute', left: 0, top: 0, width, height, opacity: RADAR_FILL_OPACITY }}
|
|
@@ -1201,7 +1230,7 @@ const RadarPlot = memo((props: RadarPlotProps) => {
|
|
|
1201
1230
|
key={index}
|
|
1202
1231
|
point={point}
|
|
1203
1232
|
color={entry.color}
|
|
1204
|
-
ringColor={
|
|
1233
|
+
ringColor={surface}
|
|
1205
1234
|
size={selection?.index === index ? 8 : 6}
|
|
1206
1235
|
/>
|
|
1207
1236
|
))
|