pixelize-native-library 1.2.0 → 1.2.1
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/lib/module/core/MODULE.md +2 -1
- package/lib/module/core/gradient/AccentGradientFill.js +80 -0
- package/lib/module/core/gradient/darkenHex.js +13 -0
- package/lib/module/core/gradient/gradientStops.js +27 -0
- package/lib/module/core/gradient/index.js +7 -0
- package/lib/module/core/gradient/withAlpha.js +19 -0
- package/lib/module/core/haptics/MODULE.md +4 -0
- package/lib/module/core/haptics/context.js +7 -0
- package/lib/module/core/haptics/haptics.js +17 -0
- package/lib/module/core/haptics/index.js +6 -0
- package/lib/module/core/haptics/useHaptics.js +73 -0
- package/lib/module/core/icon/MODULE.md +16 -9
- package/lib/module/core/icon/icons/trending-up.js +10 -0
- package/lib/module/core/icon/resolve.js +2 -0
- package/lib/module/core/media/expoImage.js +6 -0
- package/lib/module/core/motion/MODULE.md +12 -12
- package/lib/module/core/motion/config.js +4 -1
- package/lib/module/core/motion/index.js +2 -1
- package/lib/module/core/motion/usePressState.js +145 -0
- package/lib/module/core/style/index.js +1 -0
- package/lib/module/core/style/radius.js +4 -0
- package/lib/module/index.js +1 -0
- package/lib/module/modules/accordion/Accordion.js +69 -49
- package/lib/module/modules/accordion/Accordion.variants.js +4 -3
- package/lib/module/modules/accordion/MODULE.md +2 -1
- package/lib/module/modules/alert-dialog/AlertDialog.js +6 -5
- package/lib/module/modules/alert-dialog/AlertDialog.variants.js +4 -0
- package/lib/module/modules/app-bar/AppBar.js +6 -4
- package/lib/module/modules/app-bar/AppBar.variants.js +1 -2
- package/lib/module/modules/avatar/Avatar.js +7 -1
- package/lib/module/modules/avatar/Avatar.variants.js +1 -1
- package/lib/module/modules/avatar/MODULE.md +2 -2
- package/lib/module/modules/avatar-group/AvatarGroup.js +10 -6
- package/lib/module/modules/avatar-group/AvatarGroup.variants.js +23 -0
- package/lib/module/modules/avatar-group/MODULE.md +16 -0
- package/lib/module/modules/badge/Badge.js +11 -5
- package/lib/module/modules/badge/Badge.variants.js +2 -1
- package/lib/module/modules/badge/MODULE.md +5 -5
- package/lib/module/modules/banner/Banner.js +106 -60
- package/lib/module/modules/banner/Banner.variants.js +2 -2
- package/lib/module/modules/banner/MODULE.md +7 -2
- package/lib/module/modules/bottom-nav/BottomNav.js +6 -3
- package/lib/module/modules/bottom-nav/BottomNav.variants.js +9 -10
- package/lib/module/modules/bottom-nav/BottomNavOverflowSheet.js +28 -4
- package/lib/module/modules/bottom-nav/BottomNavTab.js +28 -4
- package/lib/module/modules/bottom-nav/MODULE.md +10 -1
- package/lib/module/modules/bottom-sheet/BottomSheet.js +20 -7
- package/lib/module/modules/bottom-sheet/BottomSheet.variants.js +15 -5
- package/lib/module/modules/bottom-sheet/MODULE.md +13 -2
- package/lib/module/modules/button/Button.js +87 -101
- package/lib/module/modules/button/Button.variants.js +8 -7
- package/lib/module/modules/button/MODULE.md +6 -0
- package/lib/module/modules/button-group/ButtonGroup.js +36 -37
- package/lib/module/modules/button-group/ButtonGroup.variants.js +21 -46
- package/lib/module/modules/button-group/MODULE.md +25 -30
- package/lib/module/modules/card/Card.js +117 -19
- package/lib/module/modules/card/Card.variants.js +1 -0
- package/lib/module/modules/card/MODULE.md +13 -10
- package/lib/module/modules/charts/BarChart.js +29 -14
- package/lib/module/modules/charts/BarList.js +31 -18
- package/lib/module/modules/charts/Charts.variants.js +66 -2
- package/lib/module/modules/charts/DonutChart.js +9 -4
- package/lib/module/modules/charts/LineChart.js +5 -3
- package/lib/module/modules/charts/MODULE.md +24 -11
- package/lib/module/modules/charts/PieChart.js +13 -4
- package/lib/module/modules/charts/Sparkline.js +4 -2
- package/lib/module/modules/checkbox/Checkbox.js +10 -2
- package/lib/module/modules/checkbox/MODULE.md +5 -0
- package/lib/module/modules/chip/Chip.js +83 -38
- package/lib/module/modules/chip/Chip.variants.js +15 -3
- package/lib/module/modules/chip/MODULE.md +6 -4
- package/lib/module/modules/combobox/Combobox.js +93 -57
- package/lib/module/modules/combobox/Combobox.variants.js +22 -7
- package/lib/module/modules/combobox/MODULE.md +14 -4
- package/lib/module/modules/composer/Composer.js +9 -2
- package/lib/module/modules/composer/Composer.variants.js +2 -0
- package/lib/module/modules/composer/MODULE.md +5 -0
- package/lib/module/modules/copy-button/CopyButton.js +22 -4
- package/lib/module/modules/copy-button/CopyButton.variants.js +4 -2
- package/lib/module/modules/copy-button/MODULE.md +5 -0
- package/lib/module/modules/data-table/DataTable.js +28 -9
- package/lib/module/modules/data-table/DataTable.variants.js +3 -2
- package/lib/module/modules/data-table/MODULE.md +1 -0
- package/lib/module/modules/date-picker/Calendar.js +75 -29
- package/lib/module/modules/date-picker/DatePicker.variants.js +24 -9
- package/lib/module/modules/date-picker/MODULE.md +25 -4
- package/lib/module/modules/date-picker/PickerField.js +13 -4
- package/lib/module/modules/date-picker/PickerShell.js +2 -0
- package/lib/module/modules/date-picker/TimePicker.js +13 -18
- package/lib/module/modules/divider/Divider.variants.js +6 -5
- package/lib/module/modules/divider/MODULE.md +2 -0
- package/lib/module/modules/drawer/Drawer.js +20 -8
- package/lib/module/modules/drawer/Drawer.variants.js +4 -4
- package/lib/module/modules/drawer/MODULE.md +3 -0
- package/lib/module/modules/empty-state/EmptyState.js +18 -29
- package/lib/module/modules/empty-state/EmptyState.variants.js +7 -0
- package/lib/module/modules/empty-state/MODULE.md +1 -0
- package/lib/module/modules/fab/Fab.js +41 -61
- package/lib/module/modules/fab/Fab.variants.js +15 -1
- package/lib/module/modules/fab/FabGroup.js +84 -57
- package/lib/module/modules/fab/MODULE.md +19 -6
- package/lib/module/modules/file-grid/FileGrid.js +30 -16
- package/lib/module/modules/file-grid/FileGrid.variants.js +2 -2
- package/lib/module/modules/file-grid/MODULE.md +3 -1
- package/lib/module/modules/file-upload/FileUpload.variants.js +3 -1
- package/lib/module/modules/file-upload/MODULE.md +2 -0
- package/lib/module/modules/filter-sheet/FilterChip.js +11 -3
- package/lib/module/modules/filter-sheet/FilterSheetBody.js +15 -3
- package/lib/module/modules/filter-sheet/MODULE.md +9 -0
- package/lib/module/modules/folder-row/FolderRow.js +29 -17
- package/lib/module/modules/folder-row/FolderRow.variants.js +4 -2
- package/lib/module/modules/folder-row/MODULE.md +2 -1
- package/lib/module/modules/gantt/Gantt.js +30 -9
- package/lib/module/modules/gantt/Gantt.variants.js +36 -0
- package/lib/module/modules/gantt/MODULE.md +11 -1
- package/lib/module/modules/image-viewer/ImageViewer.js +35 -5
- package/lib/module/modules/image-viewer/MODULE.md +6 -0
- package/lib/module/modules/input/Input.js +20 -7
- package/lib/module/modules/input/Input.variants.js +8 -7
- package/lib/module/modules/input/MODULE.md +2 -0
- package/lib/module/modules/list-item/ListItem.js +48 -26
- package/lib/module/modules/list-item/ListItem.variants.js +11 -2
- package/lib/module/modules/list-item/MODULE.md +2 -3
- package/lib/module/modules/markdown/MODULE.md +8 -1
- package/lib/module/modules/markdown/Markdown.js +57 -22
- package/lib/module/modules/markdown/Markdown.variants.js +2 -1
- package/lib/module/modules/menu/MODULE.md +11 -0
- package/lib/module/modules/menu/Menu.js +99 -40
- package/lib/module/modules/menu/Menu.variants.js +3 -3
- package/lib/module/modules/message-bubble/MODULE.md +4 -1
- package/lib/module/modules/message-bubble/MessageBubble.js +4 -5
- package/lib/module/modules/message-bubble/MessageBubble.variants.js +5 -5
- package/lib/module/modules/modal/MODULE.md +11 -0
- package/lib/module/modules/modal/Modal.js +87 -35
- package/lib/module/modules/modal/Modal.variants.js +2 -2
- package/lib/module/modules/more-items/MODULE.md +5 -0
- package/lib/module/modules/more-items/MoreItems.js +7 -1
- package/lib/module/modules/more-items/MoreItems.variants.js +4 -1
- package/lib/module/modules/multi-select/MODULE.md +5 -0
- package/lib/module/modules/multi-select/MultiSelect.js +23 -1
- package/lib/module/modules/multi-select/MultiSelect.variants.js +4 -2
- package/lib/module/modules/number-input/MODULE.md +2 -1
- package/lib/module/modules/number-input/NumberInput.js +97 -84
- package/lib/module/modules/number-input/NumberInput.variants.js +9 -6
- package/lib/module/modules/org-switcher/MODULE.md +13 -1
- package/lib/module/modules/org-switcher/OrgSwitcher.js +13 -2
- package/lib/module/modules/org-switcher/OrgSwitcher.variants.js +4 -2
- package/lib/module/modules/pagination/MODULE.md +2 -2
- package/lib/module/modules/pagination/Pagination.js +76 -37
- package/lib/module/modules/pagination/Pagination.variants.js +4 -2
- package/lib/module/modules/pagination/PaginationControls.js +55 -35
- package/lib/module/modules/pin-input/MODULE.md +5 -1
- package/lib/module/modules/pin-input/PinInput.js +9 -2
- package/lib/module/modules/pin-input/PinInput.variants.js +2 -1
- package/lib/module/modules/radio-group/MODULE.md +2 -2
- package/lib/module/modules/radio-group/RadioGroup.js +122 -63
- package/lib/module/modules/radio-group/RadioGroup.variants.js +2 -1
- package/lib/module/modules/reorder/MODULE.md +2 -0
- package/lib/module/modules/reorder/Reorder.js +4 -3
- package/lib/module/modules/reorder/Reorder.variants.js +4 -2
- package/lib/module/modules/rich-text/MODULE.md +3 -1
- package/lib/module/modules/rich-text/RichText.js +42 -22
- package/lib/module/modules/rich-text-editor/MODULE.md +4 -1
- package/lib/module/modules/rich-text-editor/RichTextEditor.js +8 -1
- package/lib/module/modules/rich-text-editor/RichTextEditor.variants.js +9 -6
- package/lib/module/modules/screen/MODULE.md +7 -0
- package/lib/module/modules/screen/Screen.js +50 -17
- package/lib/module/modules/screen/Screen.variants.js +18 -0
- package/lib/module/modules/search-bar/MODULE.md +1 -0
- package/lib/module/modules/search-bar/SearchBar.js +46 -26
- package/lib/module/modules/search-bar/SearchBar.variants.js +11 -8
- package/lib/module/modules/section/MODULE.md +2 -0
- package/lib/module/modules/section/Section.js +8 -15
- package/lib/module/modules/section/Section.variants.js +1 -6
- package/lib/module/modules/segmented-control/MODULE.md +3 -1
- package/lib/module/modules/segmented-control/SegmentedControl.js +110 -46
- package/lib/module/modules/segmented-control/SegmentedControl.variants.js +3 -2
- package/lib/module/modules/select/MODULE.md +26 -5
- package/lib/module/modules/select/Select.js +39 -12
- package/lib/module/modules/select/Select.variants.js +36 -12
- package/lib/module/modules/skeleton/MODULE.md +23 -27
- package/lib/module/modules/skeleton/Skeleton.js +46 -51
- package/lib/module/modules/skeleton/Skeleton.variants.js +17 -75
- package/lib/module/modules/slider/MODULE.md +2 -0
- package/lib/module/modules/slider/Slider.js +2 -1
- package/lib/module/modules/stage-progress/MODULE.md +12 -8
- package/lib/module/modules/stage-progress/StageProgress.js +94 -47
- package/lib/module/modules/stage-progress/StageProgress.variants.js +17 -12
- package/lib/module/modules/stat-tile/MODULE.md +2 -0
- package/lib/module/modules/stat-tile/StatTile.js +15 -10
- package/lib/module/modules/stat-tile/StatTile.variants.js +2 -0
- package/lib/module/modules/state-block/MODULE.md +3 -0
- package/lib/module/modules/state-block/StateBlock.js +11 -6
- package/lib/module/modules/state-block/StateBlock.variants.js +7 -0
- package/lib/module/modules/surface/MODULE.md +59 -0
- package/lib/module/modules/surface/Surface.js +42 -0
- package/lib/module/modules/surface/Surface.variants.js +33 -0
- package/lib/module/modules/surface/index.js +4 -0
- package/lib/module/modules/swipeable-row/MODULE.md +9 -0
- package/lib/module/modules/swipeable-row/SwipeableRow.js +28 -7
- package/lib/module/modules/switch/MODULE.md +2 -0
- package/lib/module/modules/switch/Switch.js +8 -2
- package/lib/module/modules/tabs/MODULE.md +2 -1
- package/lib/module/modules/tabs/Tabs.js +37 -18
- package/lib/module/modules/tabs/Tabs.variants.js +4 -2
- package/lib/module/modules/text/MODULE.md +5 -2
- package/lib/module/modules/text/Text.js +18 -6
- package/lib/module/modules/text/Text.variants.js +108 -44
- package/lib/module/modules/textarea/MODULE.md +2 -0
- package/lib/module/modules/textarea/Textarea.js +3 -2
- package/lib/module/modules/textarea/Textarea.variants.js +2 -1
- package/lib/module/modules/toast/MODULE.md +8 -4
- package/lib/module/modules/toast/Toast.js +31 -13
- package/lib/module/modules/toast/Toast.variants.js +5 -0
- package/lib/module/modules/tooltip/MODULE.md +15 -11
- package/lib/module/modules/tooltip/Tooltip.js +41 -9
- package/lib/module/modules/tooltip/Tooltip.variants.js +8 -1
- package/lib/module/theme/MODULE.md +3 -1
- package/lib/module/theme/platform/MODULE.md +14 -2
- package/lib/module/theme/platform/elevation.native.js +0 -44
- package/lib/module/theme/platform/floatingSurface.native.js +75 -0
- package/lib/module/theme/platform/highlight.native.js +59 -0
- package/lib/module/theme/platform/index.js +5 -0
- package/lib/module/theme/platform/motion.native.js +31 -11
- package/lib/module/theme/platform/stateLayer.native.js +14 -0
- package/lib/module/theme/platform/surfaces.native.js +11 -0
- package/lib/module/theme/provider/PixelizeProvider.js +12 -5
- package/lib/module/theme/tokens/MODULE.md +32 -28
- package/lib/module/theme/tokens/THEME-CONTRACT.md +137 -0
- package/lib/module/theme/tokens/assertPalette.js +29 -0
- package/lib/module/theme/tokens/brands/emerald/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/lavender/palette.light.js +3 -2
- package/lib/module/theme/tokens/brands/meadow/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/radiant/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/rosewood/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/skyline/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/slate/palette.light.js +8 -10
- package/lib/module/theme/tokens/brands/storefront/palette.light.js +7 -6
- package/lib/module/theme/tokens/brands/zinc/palette.dark.js +3 -2
- package/lib/module/theme/tokens/brands/zinc/palette.light.js +3 -2
- package/lib/module/theme/tokens/builders/buildDarkPalette.js +3 -2
- package/lib/module/theme/tokens/builders/finalizePalette.js +34 -0
- package/lib/module/theme/tokens/builders/liftToContrast.js +44 -0
- package/lib/module/theme/tokens/builders/placeholderInk.js +22 -0
- package/lib/module/theme/tokens/builders/semanticText.js +14 -0
- package/lib/module/theme/tokens/builders/surfaceRungs.js +44 -0
- package/lib/module/theme/tokens/index.js +5 -0
- package/lib/module/theme/tokens/roles/index.js +5 -0
- package/lib/typescript/core/gradient/AccentGradientFill.d.ts +7 -0
- package/lib/typescript/core/gradient/darkenHex.d.ts +2 -0
- package/lib/typescript/core/gradient/gradientStops.d.ts +10 -0
- package/lib/typescript/core/gradient/index.d.ts +5 -0
- package/lib/typescript/core/gradient/withAlpha.d.ts +2 -0
- package/lib/typescript/core/haptics/context.d.ts +3 -0
- package/lib/typescript/core/haptics/haptics.d.ts +33 -0
- package/lib/typescript/core/haptics/index.d.ts +6 -0
- package/lib/typescript/core/haptics/useHaptics.d.ts +12 -0
- package/lib/typescript/core/icon/icons/trending-up.d.ts +3 -0
- package/lib/typescript/core/icon/names.d.ts +1 -1
- package/lib/typescript/core/media/expoImage.d.ts +15 -6
- package/lib/typescript/core/media/pickers.d.ts +5 -5
- package/lib/typescript/core/motion/config.d.ts +2 -1
- package/lib/typescript/core/motion/index.d.ts +3 -1
- package/lib/typescript/core/motion/usePressState.d.ts +21 -0
- package/lib/typescript/core/style/index.d.ts +1 -0
- package/lib/typescript/core/style/radius.d.ts +2 -0
- package/lib/typescript/index.d.ts +4 -2
- package/lib/typescript/modules/accordion/Accordion.variants.d.ts +2 -2
- package/lib/typescript/modules/alert-dialog/AlertDialog.variants.d.ts +1 -0
- package/lib/typescript/modules/avatar/Avatar.variants.d.ts +1 -1
- package/lib/typescript/modules/avatar-group/AvatarGroup.d.ts +4 -2
- package/lib/typescript/modules/avatar-group/AvatarGroup.variants.d.ts +19 -0
- package/lib/typescript/modules/banner/Banner.d.ts +2 -0
- package/lib/typescript/modules/bottom-nav/BottomNav.variants.d.ts +1 -3
- package/lib/typescript/modules/bottom-sheet/BottomSheet.variants.d.ts +3 -1
- package/lib/typescript/modules/button/Button.d.ts +0 -25
- package/lib/typescript/modules/button/Button.variants.d.ts +6 -6
- package/lib/typescript/modules/button-group/ButtonGroup.d.ts +0 -19
- package/lib/typescript/modules/button-group/ButtonGroup.variants.d.ts +22 -56
- package/lib/typescript/modules/card/Card.d.ts +7 -5
- package/lib/typescript/modules/charts/Charts.variants.d.ts +29 -1
- package/lib/typescript/modules/chip/Chip.d.ts +3 -1
- package/lib/typescript/modules/chip/Chip.variants.d.ts +6 -2
- package/lib/typescript/modules/chip/index.d.ts +1 -1
- package/lib/typescript/modules/combobox/Combobox.variants.d.ts +17 -4
- package/lib/typescript/modules/data-table/DataTable.variants.d.ts +1 -1
- package/lib/typescript/modules/date-picker/DatePicker.variants.d.ts +15 -3
- package/lib/typescript/modules/date-picker/TimePicker.d.ts +1 -7
- package/lib/typescript/modules/divider/Divider.variants.d.ts +4 -4
- package/lib/typescript/modules/empty-state/EmptyState.d.ts +2 -0
- package/lib/typescript/modules/empty-state/EmptyState.variants.d.ts +1 -0
- package/lib/typescript/modules/fab/Fab.variants.d.ts +2 -0
- package/lib/typescript/modules/folder-row/FolderRow.d.ts +0 -8
- package/lib/typescript/modules/gantt/Gantt.variants.d.ts +21 -0
- package/lib/typescript/modules/input/Input.variants.d.ts +6 -6
- package/lib/typescript/modules/list-item/ListItem.d.ts +1 -5
- package/lib/typescript/modules/list-item/ListItem.variants.d.ts +137 -1
- package/lib/typescript/modules/markdown/Markdown.d.ts +7 -0
- package/lib/typescript/modules/message-bubble/MessageBubble.d.ts +2 -2
- package/lib/typescript/modules/message-bubble/MessageBubble.variants.d.ts +1 -2
- package/lib/typescript/modules/number-input/NumberInput.variants.d.ts +7 -5
- package/lib/typescript/modules/pagination/PaginationControls.d.ts +1 -4
- package/lib/typescript/modules/reorder/Reorder.d.ts +1 -1
- package/lib/typescript/modules/screen/Screen.d.ts +3 -9
- package/lib/typescript/modules/screen/Screen.variants.d.ts +4 -0
- package/lib/typescript/modules/search-bar/SearchBar.variants.d.ts +6 -6
- package/lib/typescript/modules/section/Section.variants.d.ts +0 -3
- package/lib/typescript/modules/segmented-control/SegmentedControl.variants.d.ts +1 -1
- package/lib/typescript/modules/select/Select.d.ts +4 -1
- package/lib/typescript/modules/select/Select.variants.d.ts +22 -8
- package/lib/typescript/modules/select/index.d.ts +1 -1
- package/lib/typescript/modules/skeleton/Skeleton.d.ts +3 -18
- package/lib/typescript/modules/skeleton/Skeleton.variants.d.ts +12 -68
- package/lib/typescript/modules/stage-progress/StageProgress.variants.d.ts +15 -6
- package/lib/typescript/modules/state-block/StateBlock.d.ts +4 -0
- package/lib/typescript/modules/state-block/StateBlock.variants.d.ts +1 -0
- package/lib/typescript/modules/surface/Surface.d.ts +19 -0
- package/lib/typescript/modules/surface/Surface.variants.d.ts +15 -0
- package/lib/typescript/modules/surface/index.d.ts +4 -0
- package/lib/typescript/modules/text/Text.d.ts +8 -4
- package/lib/typescript/modules/text/Text.variants.d.ts +14 -11
- package/lib/typescript/modules/toast/Toast.variants.d.ts +2 -0
- package/lib/typescript/modules/tooltip/Tooltip.variants.d.ts +7 -0
- package/lib/typescript/theme/index.d.ts +1 -1
- package/lib/typescript/theme/platform/elevation.native.d.ts +0 -30
- package/lib/typescript/theme/platform/floatingSurface.native.d.ts +10 -0
- package/lib/typescript/theme/platform/highlight.native.d.ts +17 -0
- package/lib/typescript/theme/platform/index.d.ts +9 -0
- package/lib/typescript/theme/platform/motion.native.d.ts +33 -13
- package/lib/typescript/theme/platform/stateLayer.native.d.ts +11 -0
- package/lib/typescript/theme/platform/surfaces.native.d.ts +8 -0
- package/lib/typescript/theme/provider/PixelizeProvider.d.ts +1 -1
- package/lib/typescript/theme/provider/types.d.ts +8 -0
- package/lib/typescript/theme/tokens/assertPalette.d.ts +10 -0
- package/lib/typescript/theme/tokens/brands/emerald/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/lavender/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/meadow/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/radiant/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/rosewood/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/skyline/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/slate/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/storefront/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/brands/zinc/palette.light.d.ts +4 -3
- package/lib/typescript/theme/tokens/builders/finalizePalette.d.ts +4 -0
- package/lib/typescript/theme/tokens/builders/liftToContrast.d.ts +9 -0
- package/lib/typescript/theme/tokens/builders/placeholderInk.d.ts +13 -0
- package/lib/typescript/theme/tokens/builders/semanticText.d.ts +4 -0
- package/lib/typescript/theme/tokens/builders/surfaceRungs.d.ts +12 -0
- package/lib/typescript/theme/tokens/index.d.ts +5 -0
- package/lib/typescript/theme/tokens/roles/index.d.ts +1 -0
- package/lib/typescript/theme/tokens/types.d.ts +8 -7
- package/package.json +10 -2
- package/registry.json +5 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# button-group/ — a segmented single-choice control
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
segments — NOT a row of standalone `Button`s. One component owns the whole
|
|
5
|
-
`radio-group/`: each segment carries its own `accessibilityRole="radio"`; the
|
|
6
|
-
`accessibilityRole="radiogroup"` so assistive tech announces the grouping without
|
|
7
|
-
individually-focusable segments into one. The
|
|
8
|
-
the container) so it can be selectively omitted where it touches the selected segment — see
|
|
9
|
-
**1.4.11** below.
|
|
3
|
+
Segments sit on one shared tonal container fill (`bg.raised`) with a hairline divider between
|
|
4
|
+
adjacent unselected segments — NOT a row of standalone `Button`s. One component owns the whole
|
|
5
|
+
group, same shape as `radio-group/`: each segment carries its own `accessibilityRole="radio"`; the
|
|
6
|
+
container carries `accessibilityRole="radiogroup"` so assistive tech announces the grouping without
|
|
7
|
+
collapsing the individually-focusable segments into one. The divider is drawn PER SEGMENT (never
|
|
8
|
+
once on the container) so it can be selectively omitted where it touches the selected segment — see
|
|
9
|
+
**1.4.11** below. There is no outer frame border any more (Wave 5 tonal restyle) — the container's
|
|
10
|
+
own fill carries the group's shape.
|
|
10
11
|
|
|
11
12
|
## Files
|
|
12
13
|
|
|
@@ -65,18 +66,12 @@ appearances. The selected fill is always `accent.solid`; the shared outline/divi
|
|
|
65
66
|
canvas (resting) and `bg.sunken` (pressed) — NOT `bg.hover`, whose saturated mid-tone was measured
|
|
66
67
|
to drop the brand-tinted label below 4.5:1 on several brands, the same class of bug Button's
|
|
67
68
|
"neutral" tone and RadioGroup's pressed row document fixing the same way.
|
|
68
|
-
- **1.4.11** — the shared `outline` token (`border.interactive`)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
touches the selected segment; any edge that does gets `transparent` instead of `outline`, and the
|
|
75
|
-
boundary there is served instead by the selected fill's own contrast against the canvas —
|
|
76
|
-
`accent.solid` clears 3:1 against `bg.canvas` on all 16 brand × mode combinations (worst case
|
|
77
|
-
3.24:1, emerald light) — the same mechanism every other solid-fill component in this library
|
|
78
|
-
already relies on. `ButtonGroup.test.ts` measures every actually-rendered boundary pairing (not
|
|
79
|
-
just the easy outline-vs-canvas one) for first/middle/last selected × all 8 brands × both modes.
|
|
69
|
+
- **1.4.11** — the shared `outline` token (`border.interactive`) is now only ever drawn as the
|
|
70
|
+
divider between two adjacent unselected segments; any edge touching the selected segment gets
|
|
71
|
+
`transparent` instead, and the boundary there is served by `accent.solid` (`selectedFill`) against
|
|
72
|
+
the group's own `containerFill` (`bg.raised`) — measured ≥ 3:1 on all 16 brand × mode combinations
|
|
73
|
+
(worst case 3.31:1, rosewood light). `ButtonGroup.test.ts` measures every actually-rendered
|
|
74
|
+
boundary for first/middle/last selected × all 8 brands × both modes.
|
|
80
75
|
- **2.1.1 (keyboard) — roving tabindex.** `accessibilityRole="radio"` per segment means ARIA requires
|
|
81
76
|
the group to be ONE tab stop whose arrows both move and select. `tabIndex` is `0` on exactly one
|
|
82
77
|
segment and `-1` on the rest; arrows move and select (wrapping), Home/End jump to the ends
|
|
@@ -92,8 +87,8 @@ appearances. The selected fill is always `accent.solid`; the shared outline/divi
|
|
|
92
87
|
offsets inside the segment instead; `ButtonGroup.render.test.tsx` asserts both halves — that the
|
|
93
88
|
container really clips, and that every ring edge is a positive inset that therefore survives it.
|
|
94
89
|
Segments also carry `focusable={!disabled}`, since RN's `Pressable` stays focusable when disabled.
|
|
95
|
-
- **2.3.3** — n/a
|
|
96
|
-
|
|
90
|
+
- **2.3.3** — n/a for selection (conditional fill, not a slide). Segment presses use `usePressState`
|
|
91
|
+
(scale + state-layer overlay), which snaps under reduce motion — same gating as `Button`.
|
|
97
92
|
- Disabled segments are exempt from the contrast minimum (WCAG 1.4.3), so the uniform `opacity: 0.5`
|
|
98
93
|
dim is correct, same as Button/RadioGroup.
|
|
99
94
|
|
|
@@ -105,15 +100,12 @@ appearances. The selected fill is always `accent.solid`; the shared outline/divi
|
|
|
105
100
|
and — per edge, per segment — `outline` vs `transparent`) is resolved by `resolveButtonGroupColors`
|
|
106
101
|
/ `resolveButtonGroupSegmentEdgeColors` from role tokens and applied inline over the structural
|
|
107
102
|
style.
|
|
108
|
-
2. **One connected control, not N buttons —
|
|
109
|
-
The container
|
|
110
|
-
|
|
111
|
-
structurally carries its own
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
container-wide border could never be selectively omitted per segment (one colour for its whole
|
|
115
|
-
perimeter), which is exactly why 1.4.11 shipped broken the first time — moving the border onto the
|
|
116
|
-
segments is what makes the WCAG fix possible at all.
|
|
103
|
+
2. **One connected control, not N buttons — the divider lives on the segments, the shape on the
|
|
104
|
+
container.** The container clips (`overflow: 'hidden'` + `borderRadius`) AND carries the tonal
|
|
105
|
+
`containerFill`; it clips a filled end segment's square corner into the shared rounded shape.
|
|
106
|
+
Every segment but the last structurally carries its own right border, the divider between it and
|
|
107
|
+
its neighbour; a single container-wide border could never be selectively omitted per segment (one
|
|
108
|
+
colour for its whole perimeter), which is why the divider still lives on the segments.
|
|
117
109
|
3. **Pure, testable resolvers** in `ButtonGroup.variants.ts` (no React) so the WCAG + behaviour
|
|
118
110
|
contract is unit-tested against the real palettes — never eyeballed.
|
|
119
111
|
4. **No `{...rest}`, `style` once on the outermost node**, no icon (per spec), no import from
|
|
@@ -148,6 +140,9 @@ an `if (dark)` branch. Worst case now 3.08:1 (rosewood light); the unselected la
|
|
|
148
140
|
|
|
149
141
|
Wrapped in `React.memo` (repo-wide re-render audit, 2026-07-17 — see root `CLAUDE.md`) — renamed to `ButtonGroupImpl` internally, exported as `ButtonGroup = memo(ButtonGroupImpl)`. The `options.map()` hands every per-row prop to host elements (`Pressable`/`Text`/`View`), never a library child component, so no `useCallback`/`useMemo` was needed.
|
|
150
142
|
|
|
143
|
+
Android segments carry `android_ripple` (mirrors Button/RadioGroup), gated off while
|
|
144
|
+
`disabled || selected` since a selected segment already reads via its fill.
|
|
145
|
+
|
|
151
146
|
## Modernization (v1.0.7)
|
|
152
147
|
|
|
153
148
|
- Theme imports decoupled to `theme/hooks`; optional peers (reanimated, gesture-handler, flash-list) load at runtime.
|
|
@@ -1,42 +1,140 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Card — a plain container for grouping content
|
|
5
|
-
*
|
|
6
|
-
* nothing here for `accessibilityRole` to announce — the container is intentionally invisible to
|
|
7
|
-
* assistive tech and its children carry their own semantics, exactly like a plain `View` would.
|
|
4
|
+
* Card — a plain container for grouping content, optionally pressable. When `onPress` is absent the
|
|
5
|
+
* root is a plain `View` with no press hook or animated values. Children carry their own semantics.
|
|
8
6
|
*/
|
|
9
7
|
|
|
10
|
-
import { memo, useMemo } from "react";
|
|
11
|
-
import { View } from "react-native";
|
|
8
|
+
import { memo, useCallback, useMemo } from "react";
|
|
9
|
+
import { Platform, Pressable, StyleSheet, View } from "react-native";
|
|
10
|
+
import Animated from "react-native-reanimated";
|
|
11
|
+
import { usePressState } from "../../core/motion/usePressState.js";
|
|
12
|
+
import { elevation, floatingBackground, floatingSurfaceStyle, highlight } from "../../theme/platform/index.js";
|
|
13
|
+
import { elevation as elevationTokens } from "../../theme/tokens/primitives/index.js";
|
|
14
|
+
import { rippleColor, stateLayerScrim } from "../../theme/platform/stateLayer.native.js";
|
|
12
15
|
import { useTheme } from "../../theme/hooks.js";
|
|
13
16
|
import { cardStructure, resolveCardVariant } from "./Card.variants.js";
|
|
14
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
|
-
function
|
|
16
|
-
variant = "elevated",
|
|
17
|
-
children,
|
|
18
|
-
style,
|
|
19
|
-
testID
|
|
20
|
-
}) {
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
function useCardStyles(variant, style) {
|
|
21
19
|
const theme = useTheme();
|
|
22
|
-
|
|
20
|
+
return useMemo(() => {
|
|
23
21
|
const variantColors = resolveCardVariant(theme.colors, variant);
|
|
22
|
+
const elevated = variant === "elevated";
|
|
23
|
+
highlight("subtle", theme.mode);
|
|
24
|
+
elevation(elevationTokens.sm);
|
|
25
|
+
const elevatedBg = elevated ? floatingBackground(theme, "sm") : variantColors.background;
|
|
24
26
|
return [cardStructure(theme, {
|
|
25
27
|
variant
|
|
26
28
|
}), {
|
|
27
|
-
backgroundColor:
|
|
29
|
+
backgroundColor: elevatedBg,
|
|
30
|
+
borderCurve: "continuous"
|
|
28
31
|
}, variantColors.border !== undefined && {
|
|
29
32
|
borderColor: variantColors.border
|
|
30
|
-
},
|
|
33
|
+
}, elevated && floatingSurfaceStyle(theme, "sm"), style];
|
|
31
34
|
}, [theme, variant, style]);
|
|
35
|
+
}
|
|
36
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
37
|
+
function StaticCard({
|
|
38
|
+
variant,
|
|
39
|
+
children,
|
|
40
|
+
style,
|
|
41
|
+
testID
|
|
42
|
+
}) {
|
|
43
|
+
const rootStyle = useCardStyles(variant, style);
|
|
32
44
|
return /*#__PURE__*/_jsx(View, {
|
|
33
45
|
testID: testID,
|
|
34
46
|
style: rootStyle,
|
|
35
47
|
children: children
|
|
36
48
|
});
|
|
37
49
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
function PressableCard({
|
|
51
|
+
variant,
|
|
52
|
+
children,
|
|
53
|
+
style,
|
|
54
|
+
testID,
|
|
55
|
+
onPress,
|
|
56
|
+
onLongPress,
|
|
57
|
+
disabled = false
|
|
58
|
+
}) {
|
|
59
|
+
const theme = useTheme();
|
|
60
|
+
const blocked = disabled;
|
|
61
|
+
const press = usePressState(blocked);
|
|
62
|
+
const rootStyle = useCardStyles(variant, style);
|
|
63
|
+
const overlayStaticStyle = useMemo(() => ({
|
|
64
|
+
backgroundColor: stateLayerScrim(theme.mode),
|
|
65
|
+
borderRadius: theme.radii.lg,
|
|
66
|
+
borderCurve: "continuous"
|
|
67
|
+
}), [theme.mode, theme.radii.lg]);
|
|
68
|
+
const handlePressOut = useCallback(() => {
|
|
69
|
+
press.handlers.onPressOut();
|
|
70
|
+
}, [press.handlers]);
|
|
71
|
+
const androidRipple = useMemo(() => {
|
|
72
|
+
if (Platform.OS !== "android" || blocked) return undefined;
|
|
73
|
+
return {
|
|
74
|
+
color: rippleColor(theme.mode),
|
|
75
|
+
borderless: false
|
|
76
|
+
};
|
|
77
|
+
}, [blocked, theme.mode]);
|
|
78
|
+
return /*#__PURE__*/_jsx(AnimatedPressable, {
|
|
79
|
+
testID: testID,
|
|
80
|
+
accessibilityRole: "button",
|
|
81
|
+
disabled: blocked,
|
|
82
|
+
onPress: blocked ? undefined : onPress,
|
|
83
|
+
onLongPress: blocked ? undefined : onLongPress,
|
|
84
|
+
onPressIn: press.handlers.onPressIn,
|
|
85
|
+
onPressOut: handlePressOut,
|
|
86
|
+
onLayout: press.onLayout,
|
|
87
|
+
android_ripple: androidRipple,
|
|
88
|
+
style: [rootStyle, press.animatedStyle, blocked && styles.dimmed, {
|
|
89
|
+
overflow: "hidden"
|
|
90
|
+
}],
|
|
91
|
+
children: /*#__PURE__*/_jsxs(View, {
|
|
92
|
+
style: styles.rippleClip,
|
|
93
|
+
pointerEvents: "box-none",
|
|
94
|
+
children: [/*#__PURE__*/_jsx(Animated.View, {
|
|
95
|
+
pointerEvents: "none",
|
|
96
|
+
testID: testID === undefined ? undefined : `${testID}-press-overlay`,
|
|
97
|
+
style: [StyleSheet.absoluteFill, overlayStaticStyle, press.overlayStyle]
|
|
98
|
+
}), children]
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function CardImpl({
|
|
103
|
+
variant = "elevated",
|
|
104
|
+
children,
|
|
105
|
+
onPress,
|
|
106
|
+
onLongPress,
|
|
107
|
+
disabled = false,
|
|
108
|
+
style,
|
|
109
|
+
testID
|
|
110
|
+
}) {
|
|
111
|
+
if (onPress === undefined) {
|
|
112
|
+
return /*#__PURE__*/_jsx(StaticCard, {
|
|
113
|
+
variant: variant,
|
|
114
|
+
style: style,
|
|
115
|
+
testID: testID,
|
|
116
|
+
children: children
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return /*#__PURE__*/_jsx(PressableCard, {
|
|
120
|
+
variant: variant,
|
|
121
|
+
style: style,
|
|
122
|
+
testID: testID,
|
|
123
|
+
onPress: onPress,
|
|
124
|
+
onLongPress: onLongPress,
|
|
125
|
+
disabled: disabled,
|
|
126
|
+
children: children
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
const styles = StyleSheet.create({
|
|
130
|
+
dimmed: {
|
|
131
|
+
opacity: 0.5
|
|
132
|
+
},
|
|
133
|
+
rippleClip: {
|
|
134
|
+
flex: 1,
|
|
135
|
+
overflow: "hidden",
|
|
136
|
+
borderRadius: 0
|
|
137
|
+
}
|
|
138
|
+
});
|
|
41
139
|
export const Card = /*#__PURE__*/memo(CardImpl);
|
|
42
140
|
//# sourceMappingURL=Card.js.map
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
# card/ — a plain, variant-driven container
|
|
2
2
|
|
|
3
3
|
`Card` groups content with a themed background, optional border, and optional elevation. It takes
|
|
4
|
-
no icon
|
|
4
|
+
no icon and renders no text of its own — `children` is ordinary composition. When `onPress` is
|
|
5
|
+
provided the root becomes a pressable surface with scale + state-layer feedback; otherwise it stays
|
|
6
|
+
a plain `View` with no press hook.
|
|
5
7
|
|
|
6
8
|
## Files
|
|
7
9
|
|
|
8
10
|
| File | Role |
|
|
9
11
|
|------|------|
|
|
10
|
-
| `Card.tsx` | The component. Resolves
|
|
12
|
+
| `Card.tsx` | The component. Resolves variant colours + `floatingSurfaceStyle` for `elevated`, applies inline over structure, `style` last. |
|
|
11
13
|
| `Card.variants.ts` | Pure resolver (`resolveCardVariant`) + the themed structural variant resolver `cardStructure`. No React. |
|
|
12
14
|
| `index.ts` | Public surface: `Card`, `CardProps`, `CardVariant`. |
|
|
13
15
|
| `__tests__/Card.test.ts` | Pure: WCAG 1.4.11 (outline border, all brands × modes) + variant→colour resolution. |
|
|
@@ -18,6 +20,9 @@ no icon, no press handler, and renders no text of its own — `children` is ordi
|
|
|
18
20
|
| Prop | Type | Default | Notes |
|
|
19
21
|
|------|------|---------|-------|
|
|
20
22
|
| `variant` | `elevated \| outline \| flat` | `elevated` | Closed union — see below. |
|
|
23
|
+
| `onPress` | `() => void` | — | When set, root is `Pressable` with `usePressState` feedback. |
|
|
24
|
+
| `onLongPress` | `(event) => void` | — | Only when `onPress` is set. |
|
|
25
|
+
| `disabled` | `boolean` | `false` | Only when `onPress` is set. |
|
|
21
26
|
| `children` | `ReactNode` | — | Ordinary composition, not a prop spread. |
|
|
22
27
|
| `style` | `LayoutStyle` | — | Layout-only, outermost, applied exactly once, last. |
|
|
23
28
|
| `testID` | `string` | — | Forwarded to the outermost `View`. |
|
|
@@ -28,7 +33,7 @@ no icon, no press handler, and renders no text of its own — `children` is ordi
|
|
|
28
33
|
|---------|-----------|--------|-----------|
|
|
29
34
|
| `flat` | `bg.surface` | none | none |
|
|
30
35
|
| `outline` | `bg.surface` | `border.interactive`, `borderWidths.thin` | none |
|
|
31
|
-
| `elevated` (default) | `
|
|
36
|
+
| `elevated` (default) | `floatingBackground(sm)` in dark | none | `floatingSurfaceStyle(sm)` — `elevation` + `highlight` + `borderCurve` |
|
|
32
37
|
|
|
33
38
|
Padding (`theme.space[4]`) and radius (`theme.radii.lg`) are shared across all three variants via
|
|
34
39
|
`cardStructure`; only border WIDTH varies by variant there (colour is resolved separately and
|
|
@@ -49,17 +54,15 @@ edge. `elevated` additionally separates itself with a shadow, not a colour jump.
|
|
|
49
54
|
|
|
50
55
|
## Accessibility contract (WCAG)
|
|
51
56
|
|
|
52
|
-
- **No `accessibilityRole
|
|
53
|
-
|
|
54
|
-
*correct* role (rule 8) is none, exactly like an unstyled `View`. Children carry their own
|
|
55
|
-
semantics.
|
|
57
|
+
- **No `accessibilityRole` when not pressable.** Plain grouping container — children carry semantics.
|
|
58
|
+
When `onPress` is set, `accessibilityRole="button"`.
|
|
56
59
|
- **1.4.11** — the only rendered non-text boundary (`outline`'s border) clears ≥ 3:1 against
|
|
57
60
|
`bg.canvas`, measured for all 8 brands × both modes (`Card.test.ts`).
|
|
58
61
|
- **1.4.3** — N/A. Card renders no text; contrast for whatever a consumer places in `children` is
|
|
59
62
|
that content's own responsibility, same as `Button.test.ts` only measures what Button itself
|
|
60
63
|
renders.
|
|
61
|
-
- **2.3.3 (reduced motion)** —
|
|
62
|
-
- **Touch target (2.5.x)** — N/A
|
|
64
|
+
- **2.3.3 (reduced motion)** — press feedback respects `usePressState` / `useMotion` when interactive.
|
|
65
|
+
- **Touch target (2.5.x)** — N/A unless `onPress` is set; the card's padded area is the target.
|
|
63
66
|
|
|
64
67
|
## Patterns copied from `button/` (the reference module)
|
|
65
68
|
|
|
@@ -74,7 +77,7 @@ edge. `elevated` additionally separates itself with a shadow, not a colour jump.
|
|
|
74
77
|
|
|
75
78
|
## Known gaps
|
|
76
79
|
|
|
77
|
-
None
|
|
80
|
+
None.
|
|
78
81
|
|
|
79
82
|
## Performance
|
|
80
83
|
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { memo, useCallback, useMemo, useState } from "react";
|
|
4
|
-
import { Pressable, StyleSheet, View } from "react-native";
|
|
4
|
+
import { Platform, Pressable, StyleSheet, View } from "react-native";
|
|
5
5
|
import Svg, { Circle, Line, Path, Rect, Text as SvgText } from "react-native-svg";
|
|
6
|
+
import { useDeviceTier } from "../../core/device/index.js";
|
|
7
|
+
import { rippleColor } from "../../theme/platform/stateLayer.native.js";
|
|
6
8
|
import { useTheme } from "../../theme/hooks.js";
|
|
7
9
|
import { ChartLegend } from "./ChartLegend.js";
|
|
8
|
-
import { BAR_MARKER_MIN_SPAN, BAR_MARKER_RADIUS, categoricalColorAt, defaultNumberFormatter, describeMarker, finiteOrZero, hitSlopFor, niceScale, resolveBarChartDomain, resolveBarLayout, resolveBarX, resolveChartAxisColors, scaleValue, seriesShapeAt, summarizeBarChart } from "./Charts.variants.js";
|
|
10
|
+
import { BAR_MARKER_MIN_SPAN, BAR_MARKER_RADIUS, categoricalColorAt, decimateCategories, defaultNumberFormatter, describeMarker, finiteOrZero, hitSlopFor, maxRenderedCategories, niceScale, resolveBarChartDomain, resolveBarLayout, resolveBarX, resolveChartAxisColors, scaleValue, seriesShapeAt, summarizeBarChart } from "./Charts.variants.js";
|
|
9
11
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
12
|
const Y_AXIS_WIDTH = 40;
|
|
11
13
|
const X_AXIS_HEIGHT = 24;
|
|
@@ -22,7 +24,8 @@ const BarPressTarget = /*#__PURE__*/memo(function BarPressTarget({
|
|
|
22
24
|
height,
|
|
23
25
|
label,
|
|
24
26
|
testID,
|
|
25
|
-
onPress
|
|
27
|
+
onPress,
|
|
28
|
+
androidRipple
|
|
26
29
|
}) {
|
|
27
30
|
const press = useCallback(() => onPress(categoryIndex, seriesIndex), [onPress, categoryIndex, seriesIndex]);
|
|
28
31
|
const box = useMemo(() => ({
|
|
@@ -30,7 +33,8 @@ const BarPressTarget = /*#__PURE__*/memo(function BarPressTarget({
|
|
|
30
33
|
left: x,
|
|
31
34
|
top,
|
|
32
35
|
width,
|
|
33
|
-
height
|
|
36
|
+
height,
|
|
37
|
+
overflow: "hidden"
|
|
34
38
|
}), [x, top, width, height]);
|
|
35
39
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
36
40
|
testID: testID,
|
|
@@ -38,6 +42,7 @@ const BarPressTarget = /*#__PURE__*/memo(function BarPressTarget({
|
|
|
38
42
|
accessibilityLabel: label,
|
|
39
43
|
hitSlop: hitSlopFor(width, height),
|
|
40
44
|
onPress: press,
|
|
45
|
+
android_ripple: androidRipple,
|
|
41
46
|
style: box
|
|
42
47
|
});
|
|
43
48
|
});
|
|
@@ -57,23 +62,28 @@ export const BarChart = /*#__PURE__*/memo(function BarChart({
|
|
|
57
62
|
const theme = useTheme();
|
|
58
63
|
const axisColors = useMemo(() => resolveChartAxisColors(theme.colors), [theme.colors]);
|
|
59
64
|
const [width, setWidth] = useState(0);
|
|
65
|
+
const tier = useDeviceTier();
|
|
60
66
|
const onLayout = event => {
|
|
61
67
|
setWidth(event.nativeEvent.layout.width);
|
|
62
68
|
};
|
|
63
69
|
const plotWidth = Math.max(0, width - Y_AXIS_WIDTH);
|
|
64
70
|
const plotHeight = Math.max(0, height - X_AXIS_HEIGHT - PLOT_TOP);
|
|
65
|
-
|
|
66
|
-
|
|
71
|
+
|
|
72
|
+
// An unbounded `data` array otherwise means unbounded svg nodes — one bar, one label and one
|
|
73
|
+
// press target per category. Below the cap this is the same array reference as `data` itself.
|
|
74
|
+
const renderedData = useMemo(() => decimateCategories(data, maxRenderedCategories(tier)), [data, tier]);
|
|
75
|
+
const summary = useMemo(() => summarizeBarChart(renderedData, yAxisFormatter), [renderedData, yAxisFormatter]);
|
|
76
|
+
const seriesCount = useMemo(() => Math.max(1, renderedData.reduce((max, datum) => Math.max(max, datum.values.length), 0)), [renderedData]);
|
|
67
77
|
const {
|
|
68
78
|
bars,
|
|
69
79
|
ticks,
|
|
70
80
|
categories
|
|
71
81
|
} = useMemo(() => {
|
|
72
|
-
const domain = resolveBarChartDomain(
|
|
82
|
+
const domain = resolveBarChartDomain(renderedData, stacked);
|
|
73
83
|
const scale = niceScale(domain.min, domain.max, TICK_COUNT);
|
|
74
|
-
const layout = resolveBarLayout(
|
|
84
|
+
const layout = resolveBarLayout(renderedData.length, seriesCount, plotWidth, stacked);
|
|
75
85
|
const zeroY = scaleValue(0, scale.min, scale.max, plotHeight, 0);
|
|
76
|
-
const resolvedBars =
|
|
86
|
+
const resolvedBars = renderedData.flatMap((datum, categoryIndex) => {
|
|
77
87
|
let stackTop = 0;
|
|
78
88
|
return datum.values.map((rawValue, seriesIndex) => {
|
|
79
89
|
const value = finiteOrZero(rawValue);
|
|
@@ -120,16 +130,16 @@ export const BarChart = /*#__PURE__*/memo(function BarChart({
|
|
|
120
130
|
y: PLOT_TOP + scaleValue(tick, scale.min, scale.max, plotHeight, 0),
|
|
121
131
|
text: yAxisFormatter(tick)
|
|
122
132
|
})),
|
|
123
|
-
categories:
|
|
133
|
+
categories: renderedData.map((datum, categoryIndex) => ({
|
|
124
134
|
x: Y_AXIS_WIDTH + categoryIndex * layout.bandWidth + layout.bandWidth / 2,
|
|
125
135
|
label: datum.label
|
|
126
136
|
}))
|
|
127
137
|
};
|
|
128
|
-
}, [
|
|
138
|
+
}, [renderedData, series, stacked, seriesCount, plotWidth, plotHeight, theme.colors, yAxisFormatter]);
|
|
129
139
|
const pressBar = useCallback((categoryIndex, seriesIndex) => {
|
|
130
|
-
const datum =
|
|
140
|
+
const datum = renderedData[categoryIndex];
|
|
131
141
|
if (datum !== undefined) onPressBar?.(datum, seriesIndex);
|
|
132
|
-
}, [
|
|
142
|
+
}, [renderedData, onPressBar]);
|
|
133
143
|
const legendEntries = useMemo(() => showLegend && seriesCount > 1 ? Array.from({
|
|
134
144
|
length: seriesCount
|
|
135
145
|
}, (_, index) => ({
|
|
@@ -140,6 +150,10 @@ export const BarChart = /*#__PURE__*/memo(function BarChart({
|
|
|
140
150
|
const plotStyle = useMemo(() => ({
|
|
141
151
|
height
|
|
142
152
|
}), [height]);
|
|
153
|
+
const androidRipple = useMemo(() => Platform.OS === "android" ? {
|
|
154
|
+
color: rippleColor(theme.mode),
|
|
155
|
+
borderless: false
|
|
156
|
+
} : undefined, [theme.mode]);
|
|
143
157
|
return /*#__PURE__*/_jsxs(View, {
|
|
144
158
|
testID: testID,
|
|
145
159
|
style: style,
|
|
@@ -229,7 +243,8 @@ export const BarChart = /*#__PURE__*/memo(function BarChart({
|
|
|
229
243
|
width: bar.width,
|
|
230
244
|
height: bar.height,
|
|
231
245
|
label: bar.label,
|
|
232
|
-
onPress: pressBar
|
|
246
|
+
onPress: pressBar,
|
|
247
|
+
androidRipple: androidRipple
|
|
233
248
|
}, `press-${bar.categoryIndex}-${bar.seriesIndex}`))
|
|
234
249
|
})]
|
|
235
250
|
}), /*#__PURE__*/_jsx(ChartLegend, {
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { memo, useCallback, useMemo } from "react";
|
|
4
4
|
import { Pressable, StyleSheet, Text, View } from "react-native";
|
|
5
|
+
import { VirtualList } from "../../core/list/index.js";
|
|
5
6
|
import { useTheme } from "../../theme/hooks.js";
|
|
6
|
-
import { barListHeaderStructure, barListRowStructure, barListStructure, barListTrackStructure, resolveBarListColors } from "./Charts.variants.js";
|
|
7
|
+
import { BAR_LIST_ROW_HEIGHT, barListHeaderStructure, barListRowStructure, barListStructure, barListTrackStructure, resolveBarListColors } from "./Charts.variants.js";
|
|
7
8
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
9
|
function barFraction(value, max) {
|
|
9
10
|
if (!Number.isFinite(value) || !Number.isFinite(max) || max <= 0) return 0;
|
|
@@ -97,25 +98,37 @@ export const BarList = /*#__PURE__*/memo(function BarList({
|
|
|
97
98
|
const item = items[index];
|
|
98
99
|
if (item !== undefined) onPressItem?.(item, index);
|
|
99
100
|
}, [items, onPressItem]);
|
|
101
|
+
const contentContainerStyle = useMemo(() => barListStructure(theme), [theme]);
|
|
102
|
+
const keyExtractor = useCallback(row => row.key, []);
|
|
103
|
+
const renderItem = useCallback(({
|
|
104
|
+
item,
|
|
105
|
+
index
|
|
106
|
+
}) => /*#__PURE__*/_jsx(BarListRow, {
|
|
107
|
+
testID: testID === undefined ? undefined : `${testID}-item-${index}`,
|
|
108
|
+
index: index,
|
|
109
|
+
label: item.label,
|
|
110
|
+
value: item.value,
|
|
111
|
+
icon: item.icon,
|
|
112
|
+
fillWidth: item.fillWidth,
|
|
113
|
+
fillColor: item.fillColor,
|
|
114
|
+
trackColor: colors.track,
|
|
115
|
+
rowStyle: rowStyle,
|
|
116
|
+
headerStyle: headerStyle,
|
|
117
|
+
trackStyle: trackStyle,
|
|
118
|
+
labelTextStyle: labelTextStyle,
|
|
119
|
+
valueTextStyle: valueTextStyle,
|
|
120
|
+
onPress: onPressItem === undefined ? undefined : pressItem
|
|
121
|
+
}), [testID, colors.track, rowStyle, headerStyle, trackStyle, labelTextStyle, valueTextStyle, onPressItem, pressItem]);
|
|
100
122
|
return /*#__PURE__*/_jsx(View, {
|
|
101
123
|
testID: testID,
|
|
102
|
-
style:
|
|
103
|
-
children:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
fillColor: row.fillColor,
|
|
111
|
-
trackColor: colors.track,
|
|
112
|
-
rowStyle: rowStyle,
|
|
113
|
-
headerStyle: headerStyle,
|
|
114
|
-
trackStyle: trackStyle,
|
|
115
|
-
labelTextStyle: labelTextStyle,
|
|
116
|
-
valueTextStyle: valueTextStyle,
|
|
117
|
-
onPress: onPressItem === undefined ? undefined : pressItem
|
|
118
|
-
}, row.key))
|
|
124
|
+
style: style,
|
|
125
|
+
children: /*#__PURE__*/_jsx(VirtualList, {
|
|
126
|
+
data: rows,
|
|
127
|
+
renderItem: renderItem,
|
|
128
|
+
keyExtractor: keyExtractor,
|
|
129
|
+
itemHeight: BAR_LIST_ROW_HEIGHT,
|
|
130
|
+
contentContainerStyle: contentContainerStyle
|
|
131
|
+
})
|
|
119
132
|
});
|
|
120
133
|
});
|
|
121
134
|
const styles = StyleSheet.create({
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import { createThemedVariants } from "../../core/style/index.js";
|
|
9
9
|
export const BAR_LIST_TRACK_HEIGHT = 6;
|
|
10
|
+
|
|
11
|
+
/** Header text (`fontSizes.sm` line height) + row gap (`space[1]`) + track — a floor, not a hard
|
|
12
|
+
* clip, so `VirtualList`'s `itemHeight` gets a real offset hint without constraining content. */
|
|
13
|
+
export const BAR_LIST_ROW_HEIGHT = 30;
|
|
10
14
|
export function resolveBarListColors(colors) {
|
|
11
15
|
return {
|
|
12
16
|
label: colors.fg.default,
|
|
@@ -39,7 +43,8 @@ export const barListStructure = createThemedVariants(theme => ({
|
|
|
39
43
|
}));
|
|
40
44
|
export const barListRowStructure = createThemedVariants(theme => ({
|
|
41
45
|
base: {
|
|
42
|
-
rowGap: theme.space[1]
|
|
46
|
+
rowGap: theme.space[1],
|
|
47
|
+
minHeight: BAR_LIST_ROW_HEIGHT
|
|
43
48
|
}
|
|
44
49
|
}));
|
|
45
50
|
export const barListHeaderStructure = createThemedVariants(theme => ({
|
|
@@ -242,6 +247,46 @@ export function resolveBarChartDomain(data, stacked) {
|
|
|
242
247
|
max
|
|
243
248
|
};
|
|
244
249
|
}
|
|
250
|
+
|
|
251
|
+
/** Per-`useDeviceTier()` cap on rendered categories — scaled down from `MAX_RENDERED_POINTS` (200)
|
|
252
|
+
* since each `BarChart` category costs THREE svg nodes (bar, label, press target) against a line
|
|
253
|
+
* series' one-per-sample, so the same node budget affords fewer categories on the low tiers. */
|
|
254
|
+
export const MAX_RENDERED_CATEGORIES_LOW = 60;
|
|
255
|
+
export const MAX_RENDERED_CATEGORIES_MID = 120;
|
|
256
|
+
export const MAX_RENDERED_CATEGORIES_HIGH = 200;
|
|
257
|
+
export function maxRenderedCategories(tier) {
|
|
258
|
+
switch (tier) {
|
|
259
|
+
case "low":
|
|
260
|
+
return MAX_RENDERED_CATEGORIES_LOW;
|
|
261
|
+
case "high":
|
|
262
|
+
return MAX_RENDERED_CATEGORIES_HIGH;
|
|
263
|
+
default:
|
|
264
|
+
return MAX_RENDERED_CATEGORIES_MID;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Evenly-spaced stride sampling down to `maxCategories`, first and last category always kept.
|
|
270
|
+
* Unlike `decimateSeries`' min/max bucketing (built for a numeric y-value), a category has no
|
|
271
|
+
* "extreme" to preserve — only its label and position — so an even stride keeps the *shown*
|
|
272
|
+
* categories representative of the full range instead of clustering at one end. Below the cap the
|
|
273
|
+
* input array is returned as-is (same reference), so a typical chart is byte-identical to before.
|
|
274
|
+
*/
|
|
275
|
+
export function decimateCategories(data, maxCategories) {
|
|
276
|
+
if (data.length <= maxCategories) return data;
|
|
277
|
+
if (maxCategories <= 1) return data.length === 0 ? [] : [data[0]];
|
|
278
|
+
const lastIndex = data.length - 1;
|
|
279
|
+
const result = [];
|
|
280
|
+
let lastPushedIndex = -1;
|
|
281
|
+
for (let i = 0; i < maxCategories; i++) {
|
|
282
|
+
const index = Math.round(i * lastIndex / (maxCategories - 1));
|
|
283
|
+
if (index !== lastPushedIndex) {
|
|
284
|
+
result.push(data[index]);
|
|
285
|
+
lastPushedIndex = index;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
245
290
|
/** "Bar chart, 4 categories, highest Revenue at 1,200" — the accessibility label IS the chart for
|
|
246
291
|
* a screen reader, so it names the count and the single tallest bar drawn, across every series. */
|
|
247
292
|
export function summarizeBarChart(data, formatter) {
|
|
@@ -285,9 +330,28 @@ export function resolveLineDomain(series) {
|
|
|
285
330
|
}
|
|
286
331
|
|
|
287
332
|
/** Above this sample count, line/sparkline series are decimated before any geometry is built —
|
|
288
|
-
* one svg node per sample is what makes a 5,000-point series unusable on a mid-tier phone.
|
|
333
|
+
* one svg node per sample is what makes a 5,000-point series unusable on a mid-tier phone. Equal
|
|
334
|
+
* to `maxRenderedPoints("high")` — kept as a named export since it's also `decimateSeries`'
|
|
335
|
+
* default `maxPoints`, for a caller that decimates without a device tier in hand. */
|
|
289
336
|
export const MAX_RENDERED_POINTS = 200;
|
|
290
337
|
|
|
338
|
+
/** Per-`useDeviceTier()` cap on rendered line/sparkline points. A point costs ONE svg node versus a
|
|
339
|
+
* `BarChart` category's three (bar, label, press target), so the same low/mid-tier node budget
|
|
340
|
+
* affords more points than `MAX_RENDERED_CATEGORIES` at the same tier. */
|
|
341
|
+
export const MAX_RENDERED_POINTS_LOW = 80;
|
|
342
|
+
export const MAX_RENDERED_POINTS_MID = 140;
|
|
343
|
+
export const MAX_RENDERED_POINTS_HIGH = MAX_RENDERED_POINTS;
|
|
344
|
+
export function maxRenderedPoints(tier) {
|
|
345
|
+
switch (tier) {
|
|
346
|
+
case "low":
|
|
347
|
+
return MAX_RENDERED_POINTS_LOW;
|
|
348
|
+
case "high":
|
|
349
|
+
return MAX_RENDERED_POINTS_HIGH;
|
|
350
|
+
default:
|
|
351
|
+
return MAX_RENDERED_POINTS_MID;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
291
355
|
/**
|
|
292
356
|
* Min/max bucket decimation down to ~`maxPoints`: both endpoints are kept, and the interior is
|
|
293
357
|
* split into equal buckets that each contribute their lowest and highest sample, in original
|
|
@@ -5,7 +5,7 @@ import { StyleSheet, Text, View } from "react-native";
|
|
|
5
5
|
import Svg, { Circle, G } from "react-native-svg";
|
|
6
6
|
import { useTheme } from "../../theme/hooks.js";
|
|
7
7
|
import { ChartLegend } from "./ChartLegend.js";
|
|
8
|
-
import { DONUT_SEGMENT_GAP_RATIO, resolveDonutChartColors } from "./Charts.variants.js";
|
|
8
|
+
import { DONUT_SEGMENT_GAP_RATIO, resolveDonutChartColors, seriesShapeAt } from "./Charts.variants.js";
|
|
9
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
10
|
export const DonutChart = /*#__PURE__*/memo(function DonutChart({
|
|
11
11
|
segments,
|
|
@@ -53,9 +53,14 @@ export const DonutChart = /*#__PURE__*/memo(function DonutChart({
|
|
|
53
53
|
dashoffset: -arc.start * circumference - gap / 2
|
|
54
54
|
};
|
|
55
55
|
}), [arcs, circumference]);
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
// Segment colour is consumer-supplied with no shared ramp to key off, but each segment's own
|
|
58
|
+
// position in `arcs` is stable index identity — the same thing `seriesShapeAt` already keys off
|
|
59
|
+
// for `PieChart`'s legend, reused here rather than reinvented.
|
|
60
|
+
const legendEntries = useMemo(() => showLegend && arcs.length > 1 ? arcs.map((arc, index) => ({
|
|
57
61
|
color: arc.color,
|
|
58
|
-
label: arc.label
|
|
62
|
+
label: arc.label,
|
|
63
|
+
shape: seriesShapeAt(index)
|
|
59
64
|
})) : [], [arcs, showLegend]);
|
|
60
65
|
const ringSize = useMemo(() => ({
|
|
61
66
|
width: size,
|
|
@@ -116,7 +121,7 @@ export const DonutChart = /*#__PURE__*/memo(function DonutChart({
|
|
|
116
121
|
})]
|
|
117
122
|
}), /*#__PURE__*/_jsx(ChartLegend, {
|
|
118
123
|
entries: legendEntries,
|
|
119
|
-
glyph: "
|
|
124
|
+
glyph: "mark",
|
|
120
125
|
testID: testID ? `${testID}-legend` : undefined
|
|
121
126
|
})]
|
|
122
127
|
});
|