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
|
@@ -35,11 +35,14 @@
|
|
|
35
35
|
|
|
36
36
|
import { memo, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
|
37
37
|
import { Animated, Modal, Platform, Pressable, StyleSheet, Text, TextInput, View } from "react-native";
|
|
38
|
+
import Reanimated, { FadeInDown, ReduceMotion } from "react-native-reanimated";
|
|
38
39
|
import { useAnnounce } from "../../core/a11y/index.js";
|
|
39
40
|
import { useDismissOnEscape, useFocusTrap, useSpaceActivation } from "../../core/a11y/keyboard";
|
|
40
41
|
import { Icon } from "../../core/icon/index.js";
|
|
41
42
|
import { VirtualList } from "../../core/list/index.js";
|
|
42
43
|
import { useMotion, usePressMotion, useReveal } from "../../core/motion/index.js";
|
|
44
|
+
import { elevation, floatingBackground, floatingSurfaceStyle, highlight, rippleColor } from "../../theme/platform/index.js";
|
|
45
|
+
import { elevation as elevationTokens } from "../../theme/tokens/primitives/index.js";
|
|
43
46
|
import { useTheme } from "../../theme/hooks.js";
|
|
44
47
|
import { ModalPortalContext } from "../modal/ModalPortalContext.js";
|
|
45
48
|
import { renderWebPortal } from "../modal/renderWebPortal";
|
|
@@ -109,6 +112,10 @@ const ComboboxOptionRow = /*#__PURE__*/memo(function ComboboxOptionRow({
|
|
|
109
112
|
backgroundColor: pressed || active ? rowColors.pressedRow : rowColors.background
|
|
110
113
|
}, rowDisabled && styles.dimmed], [rowColors.pressedRow, rowColors.background, rowDisabled, active]);
|
|
111
114
|
const contentStyle = useMemo(() => [comboboxRowStructure(theme), press.style], [theme, press.style]);
|
|
115
|
+
const androidRipple = useMemo(() => Platform.OS === "android" && !rowDisabled ? {
|
|
116
|
+
color: rippleColor(theme.mode),
|
|
117
|
+
borderless: false
|
|
118
|
+
} : undefined, [rowDisabled, theme.mode]);
|
|
112
119
|
const textWrapStyle = useMemo(() => comboboxRowTextStructure(theme), [theme]);
|
|
113
120
|
const labelStyle = useMemo(() => [theme.fontStyleForWeight(theme.fontWeights.regular), {
|
|
114
121
|
fontSize: theme.fontSizes.md,
|
|
@@ -134,6 +141,7 @@ const ComboboxOptionRow = /*#__PURE__*/memo(function ComboboxOptionRow({
|
|
|
134
141
|
onPress: handlePress,
|
|
135
142
|
onPressIn: press.onPressIn,
|
|
136
143
|
onPressOut: press.onPressOut,
|
|
144
|
+
android_ripple: androidRipple,
|
|
137
145
|
style: pressableStyle,
|
|
138
146
|
children: /*#__PURE__*/_jsxs(Animated.View, {
|
|
139
147
|
testID: testID ? `${testID}-option-${option.value}-content` : undefined,
|
|
@@ -373,7 +381,17 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
373
381
|
const fieldStyle = useMemo(() => [comboboxFieldStructure(theme), {
|
|
374
382
|
backgroundColor: triggerColors.background,
|
|
375
383
|
borderColor: triggerColors.border
|
|
384
|
+
}, {
|
|
385
|
+
overflow: "hidden"
|
|
376
386
|
}, disabled && styles.dimmed], [theme, triggerColors.background, triggerColors.border, disabled]);
|
|
387
|
+
const triggerRipple = useMemo(() => Platform.OS === "android" && !disabled ? {
|
|
388
|
+
color: rippleColor(theme.mode),
|
|
389
|
+
borderless: false
|
|
390
|
+
} : undefined, [disabled, theme.mode]);
|
|
391
|
+
const clearButtonRipple = useMemo(() => Platform.OS === "android" ? {
|
|
392
|
+
color: rippleColor(theme.mode),
|
|
393
|
+
borderless: false
|
|
394
|
+
} : undefined, [theme.mode]);
|
|
377
395
|
const focusRingStyle = useMemo(() => ({
|
|
378
396
|
position: "absolute",
|
|
379
397
|
top: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
|
|
@@ -382,7 +400,8 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
382
400
|
bottom: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
|
|
383
401
|
borderWidth: FOCUS_RING_WIDTH,
|
|
384
402
|
borderColor: theme.colors.border.focus,
|
|
385
|
-
borderRadius: theme.radii.
|
|
403
|
+
borderRadius: theme.radii.md + FOCUS_RING_GAP + FOCUS_RING_WIDTH,
|
|
404
|
+
borderCurve: "continuous"
|
|
386
405
|
}), [theme]);
|
|
387
406
|
const fieldValueStyle = useMemo(() => comboboxFieldValueStructure(theme), [theme]);
|
|
388
407
|
const summaryStyle = useMemo(() => [theme.fontStyleForWeight(theme.fontWeights.regular), {
|
|
@@ -390,7 +409,9 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
390
409
|
fontSize: COMBOBOX_FIELD_FONT_SIZE,
|
|
391
410
|
color: isPlaceholder ? triggerColors.placeholder : triggerColors.text
|
|
392
411
|
}], [theme, isPlaceholder, triggerColors.placeholder, triggerColors.text]);
|
|
393
|
-
const clearButtonStyle = useMemo(() => comboboxClearButtonStructure(theme),
|
|
412
|
+
const clearButtonStyle = useMemo(() => [comboboxClearButtonStructure(theme), {
|
|
413
|
+
overflow: "hidden"
|
|
414
|
+
}], [theme]);
|
|
394
415
|
const errorTextStyle = useMemo(() => [theme.fontStyleForWeight(theme.fontWeights.regular), {
|
|
395
416
|
fontSize: theme.fontSizes.xs,
|
|
396
417
|
color: resolveComboboxErrorTextColor(theme.colors),
|
|
@@ -400,10 +421,18 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
400
421
|
backgroundColor: BACKDROP_SCRIM
|
|
401
422
|
}], []);
|
|
402
423
|
const overlayStyle = useMemo(() => comboboxOverlayStructure(theme), [theme]);
|
|
403
|
-
const
|
|
404
|
-
|
|
424
|
+
const sheetFloating = useMemo(() => {
|
|
425
|
+
highlight("subtle", theme.mode);
|
|
426
|
+
elevation(elevationTokens.md);
|
|
427
|
+
void theme.elevatedSurfaces;
|
|
428
|
+
return {
|
|
429
|
+
backgroundColor: floatingBackground(theme, "md"),
|
|
430
|
+
...floatingSurfaceStyle(theme, "md")
|
|
431
|
+
};
|
|
432
|
+
}, [theme]);
|
|
433
|
+
const sheetSurfaceStyle = useMemo(() => [comboboxSheetStructure(theme), sheetFloating, {
|
|
405
434
|
maxHeight
|
|
406
|
-
}], [theme, maxHeight]);
|
|
435
|
+
}], [theme, sheetFloating, maxHeight]);
|
|
407
436
|
const sheetStyle = useMemo(() => [sheetSurfaceStyle, reveal.style], [sheetSurfaceStyle, reveal.style]);
|
|
408
437
|
const searchRowStyle = useMemo(() => [comboboxSearchRowStructure(theme), {
|
|
409
438
|
borderBottomColor: theme.colors.border.default
|
|
@@ -432,60 +461,63 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
432
461
|
}), /*#__PURE__*/_jsx(View, {
|
|
433
462
|
style: overlayStyle,
|
|
434
463
|
pointerEvents: "box-none",
|
|
435
|
-
children: /*#__PURE__*/
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
style:
|
|
440
|
-
children: [/*#__PURE__*/
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
464
|
+
children: /*#__PURE__*/_jsx(Reanimated.View, {
|
|
465
|
+
entering: FadeInDown.springify().reduceMotion(ReduceMotion.System),
|
|
466
|
+
children: /*#__PURE__*/_jsxs(Animated.View, {
|
|
467
|
+
ref: sheetRef,
|
|
468
|
+
style: sheetStyle,
|
|
469
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
470
|
+
style: searchRowStyle,
|
|
471
|
+
children: [/*#__PURE__*/_jsx(Icon, {
|
|
472
|
+
name: "search",
|
|
473
|
+
size: COMBOBOX_FIELD_ICON_SIZE,
|
|
474
|
+
color: rowColors.icon,
|
|
475
|
+
strokeWidth: ICON_STROKE
|
|
476
|
+
}), /*#__PURE__*/_jsx(TextInput, {
|
|
477
|
+
ref: searchInputRef,
|
|
478
|
+
testID: testID ? `${testID}-search` : undefined,
|
|
479
|
+
value: query,
|
|
480
|
+
onChangeText: handleQueryChange,
|
|
481
|
+
placeholder: searchPlaceholder,
|
|
482
|
+
placeholderTextColor: rowColors.placeholder,
|
|
483
|
+
accessibilityLabel: searchPlaceholder
|
|
484
|
+
// Hyphenated JSX attributes are not type-checked at all, which is exactly why the id
|
|
485
|
+
// comes from `comboboxOptionNativeId` and is never interpolated here.
|
|
486
|
+
,
|
|
487
|
+
"aria-activedescendant": activeOptionId,
|
|
488
|
+
autoFocus: true,
|
|
489
|
+
autoCapitalize: "none",
|
|
490
|
+
autoCorrect: false,
|
|
491
|
+
autoComplete: "off",
|
|
492
|
+
importantForAutofill: "no",
|
|
493
|
+
style: searchInputStyle
|
|
494
|
+
})]
|
|
495
|
+
}), loading ? /*#__PURE__*/_jsx(View, {
|
|
496
|
+
style: listStateStyle,
|
|
497
|
+
children: /*#__PURE__*/_jsx(Spinner, {
|
|
498
|
+
size: "md",
|
|
499
|
+
tone: "neutral",
|
|
500
|
+
testID: testID ? `${testID}-spinner` : undefined
|
|
501
|
+
})
|
|
502
|
+
}) : filteredOptions.length === 0 ? /*#__PURE__*/_jsx(View, {
|
|
503
|
+
style: listStateStyle,
|
|
504
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
505
|
+
accessibilityLiveRegion: Platform.OS === "android" ? "polite" : undefined,
|
|
506
|
+
style: emptyTextStyle,
|
|
507
|
+
children: emptyMessage
|
|
508
|
+
})
|
|
509
|
+
}) : /*#__PURE__*/_jsx(VirtualList, {
|
|
510
|
+
data: filteredOptions,
|
|
511
|
+
keyExtractor: keyExtractor,
|
|
512
|
+
renderItem: renderRow,
|
|
513
|
+
itemHeight: uniformRowHeight ? COMBOBOX_ROW_MIN_HEIGHT : undefined,
|
|
514
|
+
accessibilityRole: COMBOBOX_LISTBOX_ROLE
|
|
515
|
+
// The search field holds focus while the sheet is open, so the default `"never"`
|
|
516
|
+
// spends the first tap on any row dismissing the keyboard instead of selecting.
|
|
455
517
|
,
|
|
456
|
-
"
|
|
457
|
-
autoFocus: true,
|
|
458
|
-
autoCapitalize: "none",
|
|
459
|
-
autoCorrect: false,
|
|
460
|
-
autoComplete: "off",
|
|
461
|
-
importantForAutofill: "no",
|
|
462
|
-
style: searchInputStyle
|
|
518
|
+
keyboardShouldPersistTaps: "handled"
|
|
463
519
|
})]
|
|
464
|
-
})
|
|
465
|
-
style: listStateStyle,
|
|
466
|
-
children: /*#__PURE__*/_jsx(Spinner, {
|
|
467
|
-
size: "md",
|
|
468
|
-
tone: "neutral",
|
|
469
|
-
testID: testID ? `${testID}-spinner` : undefined
|
|
470
|
-
})
|
|
471
|
-
}) : filteredOptions.length === 0 ? /*#__PURE__*/_jsx(View, {
|
|
472
|
-
style: listStateStyle,
|
|
473
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
474
|
-
accessibilityLiveRegion: Platform.OS === "android" ? "polite" : undefined,
|
|
475
|
-
style: emptyTextStyle,
|
|
476
|
-
children: emptyMessage
|
|
477
|
-
})
|
|
478
|
-
}) : /*#__PURE__*/_jsx(VirtualList, {
|
|
479
|
-
data: filteredOptions,
|
|
480
|
-
keyExtractor: keyExtractor,
|
|
481
|
-
renderItem: renderRow,
|
|
482
|
-
itemHeight: uniformRowHeight ? COMBOBOX_ROW_MIN_HEIGHT : undefined,
|
|
483
|
-
accessibilityRole: COMBOBOX_LISTBOX_ROLE
|
|
484
|
-
// The search field holds focus while the sheet is open, so the default `"never"`
|
|
485
|
-
// spends the first tap on any row dismissing the keyboard instead of selecting.
|
|
486
|
-
,
|
|
487
|
-
keyboardShouldPersistTaps: "handled"
|
|
488
|
-
})]
|
|
520
|
+
})
|
|
489
521
|
})
|
|
490
522
|
})]
|
|
491
523
|
}) : null;
|
|
@@ -499,6 +531,8 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
499
531
|
}), portalContainer) : null : /*#__PURE__*/_jsx(Modal, {
|
|
500
532
|
visible: open,
|
|
501
533
|
transparent: true,
|
|
534
|
+
statusBarTranslucent: true,
|
|
535
|
+
navigationBarTranslucent: true,
|
|
502
536
|
animationType: "none",
|
|
503
537
|
onRequestClose: closeSheet
|
|
504
538
|
// `autoFocus` on the search TextInput alone is timing-flaky inside a native Modal on iOS
|
|
@@ -525,6 +559,7 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
525
559
|
onFocus: handleFocus,
|
|
526
560
|
onBlur: handleBlur,
|
|
527
561
|
hitSlop: COMBOBOX_FIELD_HIT_SLOP,
|
|
562
|
+
android_ripple: triggerRipple,
|
|
528
563
|
style: fieldStyle,
|
|
529
564
|
children: [showFocusRing && /*#__PURE__*/_jsx(View, {
|
|
530
565
|
pointerEvents: "none",
|
|
@@ -548,6 +583,7 @@ export const Combobox = /*#__PURE__*/memo(function Combobox(props) {
|
|
|
548
583
|
accessibilityLabel: "Clear",
|
|
549
584
|
onPress: handleClear,
|
|
550
585
|
hitSlop: COMBOBOX_CLEAR_BUTTON_HIT_SLOP,
|
|
586
|
+
android_ripple: clearButtonRipple,
|
|
551
587
|
style: clearButtonStyle,
|
|
552
588
|
children: /*#__PURE__*/_jsx(Icon, {
|
|
553
589
|
name: "x",
|
|
@@ -78,6 +78,16 @@ export function normalizeForSearch(value) {
|
|
|
78
78
|
*/
|
|
79
79
|
export const COMBOBOX_LISTBOX_ROLE = "listbox";
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Each option row's role. `aria-selected` is only valid ARIA on `option`/`row`/`tab`/`gridcell`/
|
|
83
|
+
* `treeitem` — the row sits inside a `COMBOBOX_LISTBOX_ROLE` container, so `option` is the
|
|
84
|
+
* textbook-correct pairing (2026-08 sweep fixed the row from the invalid `menuitem`+`aria-selected`
|
|
85
|
+
* combination — a followup to `select/Select.tsx`'s identical fix, both listbox/option/aria-selected
|
|
86
|
+
* per the ARIA 1.2 combobox-with-listbox-popup pattern). Same type gap as `COMBOBOX_LISTBOX_ROLE`:
|
|
87
|
+
* RN 0.86's `AccessibilityRole` union has no `option` either.
|
|
88
|
+
*/
|
|
89
|
+
export const COMBOBOX_OPTION_ROLE = "option";
|
|
90
|
+
|
|
81
91
|
/**
|
|
82
92
|
* The DOM id of one option row. `aria-activedescendant` and `nativeID` must agree exactly, and
|
|
83
93
|
* every `aria-*` prop is UNCHECKED by TypeScript on an RN component (hyphenated JSX attributes are
|
|
@@ -133,7 +143,7 @@ export function resolveComboboxTriggerColors(colors, state) {
|
|
|
133
143
|
background: colors.bg.surface,
|
|
134
144
|
border: state.error ? colors.status.danger.solid : colors.border.interactive,
|
|
135
145
|
text: colors.fg.default,
|
|
136
|
-
placeholder: colors.fg.
|
|
146
|
+
placeholder: colors.fg.placeholder,
|
|
137
147
|
icon: colors.fg.muted
|
|
138
148
|
};
|
|
139
149
|
}
|
|
@@ -148,6 +158,7 @@ export function resolveComboboxRowColors(colors) {
|
|
|
148
158
|
background: colors.bg.surface,
|
|
149
159
|
text: colors.fg.default,
|
|
150
160
|
muted: colors.fg.muted,
|
|
161
|
+
placeholder: colors.fg.placeholder,
|
|
151
162
|
icon: colors.fg.muted,
|
|
152
163
|
checkIcon: colors.fg.default,
|
|
153
164
|
pressedRow: colors.bg.sunken
|
|
@@ -167,13 +178,15 @@ export function resolveComboboxAccessibility(input) {
|
|
|
167
178
|
};
|
|
168
179
|
}
|
|
169
180
|
/**
|
|
170
|
-
* Every row is `
|
|
171
|
-
*
|
|
172
|
-
*
|
|
181
|
+
* Every row is `option` (2026-08 sweep — was `menuitem`, which made `aria-selected` invalid ARIA;
|
|
182
|
+
* the row sits inside `COMBOBOX_LISTBOX_ROLE`, so `option` is the textbook-correct pairing), in BOTH
|
|
183
|
+
* single and multiple mode: this module's `aria-activedescendant` pattern is one listbox regardless
|
|
184
|
+
* of mode, unlike `MultiSelect`'s own separate `checkbox` rows. Selection state rides `aria-selected`,
|
|
185
|
+
* never `aria-checked`.
|
|
173
186
|
*/
|
|
174
187
|
export function resolveComboboxRowAccessibility(input) {
|
|
175
188
|
return {
|
|
176
|
-
accessibilityRole:
|
|
189
|
+
accessibilityRole: COMBOBOX_OPTION_ROLE,
|
|
177
190
|
"aria-selected": input.selected,
|
|
178
191
|
"aria-disabled": input.disabled,
|
|
179
192
|
disabled: input.disabled
|
|
@@ -191,7 +204,8 @@ export const comboboxFieldStructure = createThemedVariants(theme => ({
|
|
|
191
204
|
columnGap: theme.space[2],
|
|
192
205
|
height: COMBOBOX_FIELD_HEIGHT,
|
|
193
206
|
paddingHorizontal: theme.space[4],
|
|
194
|
-
borderRadius: theme.radii.
|
|
207
|
+
borderRadius: theme.radii.md,
|
|
208
|
+
borderCurve: "continuous",
|
|
195
209
|
borderWidth: theme.borderWidths.thin
|
|
196
210
|
}
|
|
197
211
|
}));
|
|
@@ -230,7 +244,8 @@ export const comboboxOverlayStructure = createThemedVariants(theme => ({
|
|
|
230
244
|
* default `DEFAULT_MAX_HEIGHT`) and is applied inline over this at the component boundary. */
|
|
231
245
|
export const comboboxSheetStructure = createThemedVariants(theme => ({
|
|
232
246
|
base: {
|
|
233
|
-
borderRadius: theme.radii.
|
|
247
|
+
borderRadius: theme.radii.md,
|
|
248
|
+
borderCurve: "continuous",
|
|
234
249
|
...theme.elevation.lg
|
|
235
250
|
}
|
|
236
251
|
}));
|
|
@@ -61,10 +61,14 @@ through the same collapsing rule): 0 → placeholder, 1 → that option's label,
|
|
|
61
61
|
## Accessibility contract (WCAG)
|
|
62
62
|
|
|
63
63
|
- **4.1.2** — the field is `accessibilityRole="combobox"` with flat `aria-expanded` tracking the
|
|
64
|
-
sheet. Rows are `accessibilityRole="
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
sheet. Rows are `accessibilityRole="option"` (in BOTH single and multiple mode — this module's own
|
|
65
|
+
spec, unlike `MultiSelect`'s `checkbox` rows) with flat `aria-selected` / `aria-disabled`. Flat,
|
|
66
|
+
never `accessibilityState={{…}}`: react-native-web discards the object form — see
|
|
67
|
+
`docs/PLATFORM-A11Y-PROPS.md`. **2026-08 sweep:** rows were `accessibilityRole="menuitem"`, which
|
|
68
|
+
made `aria-selected` invalid ARIA (only valid on `option`/`row`/`tab`/`gridcell`/`treeitem`); rows
|
|
69
|
+
sit inside `COMBOBOX_LISTBOX_ROLE` (`"listbox"`), so `option` + `aria-selected` is the
|
|
70
|
+
textbook-correct ARIA listbox pattern — the same fix `select/Select.tsx`'s identical bug got, only
|
|
71
|
+
the row's `accessibilityRole` changed.
|
|
68
72
|
- **2.5.x target size** — the field reaches ≥ 44dp via `hitSlop`; the clear button — nested inside
|
|
69
73
|
the field `Pressable`, same structure as `DatePicker`'s — reaches 44×44 the same way; option rows
|
|
70
74
|
have a 44dp `minHeight` directly.
|
|
@@ -181,3 +185,9 @@ Via `core/motion` only — `opacity`/`transform`, native driver, all reduce-moti
|
|
|
181
185
|
- Theme imports decoupled to `theme/hooks`; optional peers (reanimated, gesture-handler, flash-list) load at runtime.
|
|
182
186
|
- List-heavy surfaces use `VirtualList` with device-tier window sizing where applicable.
|
|
183
187
|
- `React.memo` + stable callbacks retained; render-item/key-extractor hoisted per ESLint perf rules.
|
|
188
|
+
|
|
189
|
+
- **Round 2 visual** — radii retarget (`radii.md`/`lg`/`xl`/`full`), `borderCurve: continuous` on md+ corners; floating surfaces wire platform elevation/highlight where applicable.
|
|
190
|
+
- **Round 5 (Android parity)** — `android_ripple` (`borderless: false`) added to the trigger field
|
|
191
|
+
(gated `!disabled`), the clear button, and each option row (gated `!rowDisabled`). The trigger
|
|
192
|
+
field and clear button also gained `overflow: "hidden"` so their ripple clips to the field/button
|
|
193
|
+
shape instead of escaping it.
|
|
@@ -13,6 +13,7 @@ import { memo, useCallback, useEffect, useMemo, useRef } from "react";
|
|
|
13
13
|
import { ActivityIndicator, Animated, Platform, Pressable, StyleSheet, TextInput, View } from "react-native";
|
|
14
14
|
import { Icon } from "../../core/icon/index.js";
|
|
15
15
|
import { useAnimatedValue, useMotion } from "../../core/motion/index.js";
|
|
16
|
+
import { rippleColor } from "../../theme/platform/stateLayer.native.js";
|
|
16
17
|
import { useTheme } from "../../theme/hooks.js";
|
|
17
18
|
import { composerFieldStructure, composerInputStructure, composerSendStructure, composerStructure } from "./Composer.variants.js";
|
|
18
19
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -32,6 +33,10 @@ const ComposerSend = /*#__PURE__*/memo(function ComposerSend({
|
|
|
32
33
|
const sendStyle = useMemo(() => [composerSendStructure(theme), {
|
|
33
34
|
backgroundColor: canSend ? theme.colors.accent.solid : theme.colors.bg.sunken
|
|
34
35
|
}], [theme, canSend]);
|
|
36
|
+
const androidRipple = useMemo(() => Platform.OS === "android" && canSend ? {
|
|
37
|
+
color: rippleColor(theme.mode),
|
|
38
|
+
borderless: true
|
|
39
|
+
} : undefined, [canSend, theme.mode]);
|
|
35
40
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
36
41
|
testID: testID,
|
|
37
42
|
accessibilityRole: "button",
|
|
@@ -39,6 +44,7 @@ const ComposerSend = /*#__PURE__*/memo(function ComposerSend({
|
|
|
39
44
|
"aria-disabled": !canSend,
|
|
40
45
|
disabled: !canSend,
|
|
41
46
|
onPress: onPress,
|
|
47
|
+
android_ripple: androidRipple,
|
|
42
48
|
style: sendStyle,
|
|
43
49
|
children: sending ? /*#__PURE__*/_jsx(ActivityIndicator, {
|
|
44
50
|
color: theme.colors.accent.onSolid
|
|
@@ -110,7 +116,8 @@ export const Composer = /*#__PURE__*/memo(function Composer({
|
|
|
110
116
|
bottom: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
|
|
111
117
|
borderWidth: FOCUS_RING_WIDTH,
|
|
112
118
|
borderColor: theme.colors.border.focus,
|
|
113
|
-
borderRadius: theme.radii.lg + FOCUS_RING_GAP + FOCUS_RING_WIDTH
|
|
119
|
+
borderRadius: theme.radii.lg + FOCUS_RING_GAP + FOCUS_RING_WIDTH,
|
|
120
|
+
borderCurve: "continuous"
|
|
114
121
|
}), [theme]);
|
|
115
122
|
return /*#__PURE__*/_jsxs(View, {
|
|
116
123
|
testID: testID,
|
|
@@ -128,7 +135,7 @@ export const Composer = /*#__PURE__*/memo(function Composer({
|
|
|
128
135
|
value: value,
|
|
129
136
|
onChangeText: onChangeText,
|
|
130
137
|
placeholder: placeholder,
|
|
131
|
-
placeholderTextColor: theme.colors.fg.
|
|
138
|
+
placeholderTextColor: theme.colors.fg.placeholder,
|
|
132
139
|
editable: editable,
|
|
133
140
|
accessibilityLabel: accessibilityLabel ?? placeholder,
|
|
134
141
|
"aria-disabled": !editable,
|
|
@@ -26,6 +26,7 @@ export const composerInputStructure = createThemedVariants(theme => ({
|
|
|
26
26
|
paddingHorizontal: theme.space[3],
|
|
27
27
|
paddingVertical: theme.space[2],
|
|
28
28
|
borderRadius: theme.radii.lg,
|
|
29
|
+
borderCurve: "continuous",
|
|
29
30
|
borderWidth: theme.borderWidths.thin,
|
|
30
31
|
fontSize: theme.fontSizes.md
|
|
31
32
|
}
|
|
@@ -35,6 +36,7 @@ export const composerSendStructure = createThemedVariants(theme => ({
|
|
|
35
36
|
width: 40,
|
|
36
37
|
height: 40,
|
|
37
38
|
borderRadius: theme.radii.full,
|
|
39
|
+
borderCurve: "continuous",
|
|
38
40
|
alignItems: "center",
|
|
39
41
|
justifyContent: "center"
|
|
40
42
|
}
|
|
@@ -68,3 +68,8 @@ controlled), so:
|
|
|
68
68
|
fresh literal per keystroke would defeat the memo above. `aria-disabled={!canSend}` is a primitive,
|
|
69
69
|
not an object, so it needs no memo of its own.
|
|
70
70
|
- `ComposerSend` reads `useTheme()` itself rather than taking a `theme` prop.
|
|
71
|
+
|
|
72
|
+
- **Round 2 visual** — radii retarget (`radii.md`/`lg`/`xl`/`full`), `borderCurve: continuous` on md+ corners; floating surfaces wire platform elevation/highlight where applicable.
|
|
73
|
+
- **Round 5 (Android parity)** — the round send button now gets `android_ripple` (`borderless: true`,
|
|
74
|
+
matching its circular shape), gated on `Platform.OS === "android" && canSend` so a disabled send
|
|
75
|
+
button shows no ripple.
|
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
9
|
-
import { AccessibilityInfo, Animated, Pressable, Text, View } from "react-native";
|
|
9
|
+
import { AccessibilityInfo, Animated, Platform, Pressable, Text, View } from "react-native";
|
|
10
10
|
import { Icon } from "../../core/icon/index.js";
|
|
11
11
|
import { usePressMotion } from "../../core/motion/index.js";
|
|
12
|
+
import { rippleColor } from "../../theme/platform/stateLayer.native.js";
|
|
12
13
|
import { useTheme } from "../../theme/hooks.js";
|
|
13
14
|
import { COPY_BUTTON_SIZES, copyButtonMenuRowStructure, copyButtonOutlineStructure, COPY_FEEDBACK_MS, resolveCopyButtonColors, writeClipboard } from "./CopyButton.variants.js";
|
|
14
15
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -65,8 +66,9 @@ export const CopyButton = /*#__PURE__*/memo(function CopyButton({
|
|
|
65
66
|
bottom: -(FOCUS_RING_GAP + FOCUS_RING_WIDTH),
|
|
66
67
|
borderWidth: FOCUS_RING_WIDTH,
|
|
67
68
|
borderColor: theme.colors.border.focus,
|
|
68
|
-
borderRadius: theme.radii.
|
|
69
|
-
|
|
69
|
+
borderRadius: theme.radii.md + FOCUS_RING_GAP + FOCUS_RING_WIDTH,
|
|
70
|
+
borderCurve: "continuous"
|
|
71
|
+
}), [theme.colors.border.focus, theme.radii.md]);
|
|
70
72
|
const spec = COPY_BUTTON_SIZES[size];
|
|
71
73
|
const iconName = status === "copied" ? "check" : status === "failed" ? "triangle-alert" : "link";
|
|
72
74
|
const ink = status === "copied" ? colors.success : status === "failed" ? colors.danger : colors.default;
|
|
@@ -83,9 +85,15 @@ export const CopyButton = /*#__PURE__*/memo(function CopyButton({
|
|
|
83
85
|
onPress: handlePress,
|
|
84
86
|
onFocus: onFocus,
|
|
85
87
|
onBlur: onBlur,
|
|
88
|
+
android_ripple: Platform.OS === "android" ? {
|
|
89
|
+
color: rippleColor(theme.mode),
|
|
90
|
+
borderless: false
|
|
91
|
+
} : undefined,
|
|
86
92
|
style: ({
|
|
87
93
|
pressed
|
|
88
|
-
}) => [copyButtonMenuRowStructure(theme),
|
|
94
|
+
}) => [copyButtonMenuRowStructure(theme), {
|
|
95
|
+
overflow: "hidden"
|
|
96
|
+
}, pressed ? {
|
|
89
97
|
backgroundColor: theme.colors.bg.sunken
|
|
90
98
|
} : null, style],
|
|
91
99
|
children: [focusRing, /*#__PURE__*/_jsx(Icon, {
|
|
@@ -110,9 +118,15 @@ export const CopyButton = /*#__PURE__*/memo(function CopyButton({
|
|
|
110
118
|
onPress: handlePress,
|
|
111
119
|
onFocus: onFocus,
|
|
112
120
|
onBlur: onBlur,
|
|
121
|
+
android_ripple: Platform.OS === "android" ? {
|
|
122
|
+
color: rippleColor(theme.mode),
|
|
123
|
+
borderless: false
|
|
124
|
+
} : undefined,
|
|
113
125
|
style: ({
|
|
114
126
|
pressed
|
|
115
127
|
}) => [copyButtonOutlineStructure(theme), {
|
|
128
|
+
overflow: "hidden"
|
|
129
|
+
}, {
|
|
116
130
|
borderColor: status === "copied" ? colors.success : status === "failed" ? colors.danger : colors.border,
|
|
117
131
|
backgroundColor: pressed ? theme.colors.bg.sunken : theme.colors.bg.surface
|
|
118
132
|
}, style],
|
|
@@ -140,6 +154,10 @@ export const CopyButton = /*#__PURE__*/memo(function CopyButton({
|
|
|
140
154
|
onFocus: onFocus,
|
|
141
155
|
onBlur: onBlur,
|
|
142
156
|
hitSlop: spec.hitSlop,
|
|
157
|
+
android_ripple: Platform.OS === "android" ? {
|
|
158
|
+
color: rippleColor(theme.mode),
|
|
159
|
+
borderless: true
|
|
160
|
+
} : undefined,
|
|
143
161
|
style: style,
|
|
144
162
|
children: [focusRing, /*#__PURE__*/_jsx(Animated.View, {
|
|
145
163
|
testID: "copy-button-glyph",
|
|
@@ -42,7 +42,8 @@ export const copyButtonMenuRowStructure = createThemedVariants(theme => ({
|
|
|
42
42
|
columnGap: theme.space[2],
|
|
43
43
|
paddingHorizontal: theme.space[3],
|
|
44
44
|
paddingVertical: theme.space[2],
|
|
45
|
-
borderRadius: theme.radii.
|
|
45
|
+
borderRadius: theme.radii.md,
|
|
46
|
+
borderCurve: "continuous"
|
|
46
47
|
}
|
|
47
48
|
}));
|
|
48
49
|
export const copyButtonOutlineStructure = createThemedVariants(theme => ({
|
|
@@ -53,7 +54,8 @@ export const copyButtonOutlineStructure = createThemedVariants(theme => ({
|
|
|
53
54
|
columnGap: theme.space[1],
|
|
54
55
|
paddingHorizontal: theme.space[3],
|
|
55
56
|
paddingVertical: theme.space[2],
|
|
56
|
-
borderRadius: theme.radii.
|
|
57
|
+
borderRadius: theme.radii.md,
|
|
58
|
+
borderCurve: "continuous",
|
|
57
59
|
borderWidth: theme.borderWidths.thin
|
|
58
60
|
}
|
|
59
61
|
}));
|
|
@@ -71,3 +71,8 @@ variant) until the user retries.
|
|
|
71
71
|
## Performance
|
|
72
72
|
|
|
73
73
|
Wrapped in `React.memo` (repo-wide re-render audit, 2026-07-17 — see root `CLAUDE.md`).
|
|
74
|
+
|
|
75
|
+
- **Round 2 visual** — radii retarget (`radii.md`/`lg`/`xl`/`full`), `borderCurve: continuous` on md+ corners; floating surfaces wire platform elevation/highlight where applicable.
|
|
76
|
+
- **Round 5 (Android parity)** — all three variants get `android_ripple`: `icon` (round, icon-only)
|
|
77
|
+
is `borderless: true`; `button` and `menu-item` are `borderless: false` and also gained
|
|
78
|
+
`overflow: "hidden"` so the ripple clips to the row/outline shape.
|
|
@@ -13,9 +13,12 @@
|
|
|
13
13
|
|
|
14
14
|
import { memo, useCallback, useMemo, useState } from "react";
|
|
15
15
|
import { Platform, Pressable, ScrollView, StyleSheet, Text, View } from "react-native";
|
|
16
|
+
import Animated from "react-native-reanimated";
|
|
16
17
|
import { HEADING_LEVEL, HeadingView } from "../../core/heading/index.js";
|
|
17
18
|
import { Icon } from "../../core/icon/index.js";
|
|
19
|
+
import { usePressState } from "../../core/motion/usePressState.js";
|
|
18
20
|
import { VirtualList } from "../../core/list/index.js";
|
|
21
|
+
import { rippleColor, stateLayerScrim } from "../../theme/platform/stateLayer.native.js";
|
|
19
22
|
import { useTheme } from "../../theme/hooks.js";
|
|
20
23
|
import { Checkbox } from "../checkbox/index.js";
|
|
21
24
|
import { EmptyState } from "../empty-state/index.js";
|
|
@@ -23,6 +26,7 @@ import { Skeleton } from "../skeleton/index.js";
|
|
|
23
26
|
import { DATA_TABLE_DEFAULT_ROW_HEIGHT, DATA_TABLE_HEADER_HEIGHT, DATA_TABLE_SKELETON_CELL_HEIGHT, DATA_TABLE_SKELETON_ROW_COUNT, DATA_TABLE_SORT_ICON_SIZE, dataTableCellStructure, dataTableFocusRingStructure, dataTableHeaderRowStructure, dataTableRowStructure, dataTableSelectCellStructure, nextSortDirection, resolveColumnWidth, resolveDataTableColors, resolveDefaultCellText, resolveRowBackground, resolveSelectAllSelection, resolveSelectAllState, resolveSortAccessibilityLabel, resolveSortIcon, resolveTotalWidth, rowTouchSlop, toggleSelectionKey } from "./DataTable.variants.js";
|
|
24
27
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
25
28
|
const ICON_STROKE = 2;
|
|
29
|
+
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
|
26
30
|
const EMPTY_SELECTION = [];
|
|
27
31
|
const SKELETON_ROW_INDICES = Array.from({
|
|
28
32
|
length: DATA_TABLE_SKELETON_ROW_COUNT
|
|
@@ -396,7 +400,7 @@ function DataTableRowInner({
|
|
|
396
400
|
specs,
|
|
397
401
|
rowStyle,
|
|
398
402
|
background,
|
|
399
|
-
pressedBackground,
|
|
403
|
+
pressedBackground: _pressedBackground,
|
|
400
404
|
textStyle,
|
|
401
405
|
focusRingStyle,
|
|
402
406
|
selectable,
|
|
@@ -406,7 +410,8 @@ function DataTableRowInner({
|
|
|
406
410
|
hitSlop,
|
|
407
411
|
testID
|
|
408
412
|
}) {
|
|
409
|
-
|
|
413
|
+
const theme = useTheme();
|
|
414
|
+
const press = usePressState(onPress === undefined);
|
|
410
415
|
const [focused, setFocused] = useState(false);
|
|
411
416
|
const handleToggle = useCallback(() => onToggleSelect(rowKey), [onToggleSelect, rowKey]);
|
|
412
417
|
const handlePress = useCallback(() => onPress?.(row, index), [onPress, row, index]);
|
|
@@ -415,11 +420,15 @@ function DataTableRowInner({
|
|
|
415
420
|
const staticStyle = useMemo(() => [rowStyle, {
|
|
416
421
|
backgroundColor: background
|
|
417
422
|
}], [rowStyle, background]);
|
|
418
|
-
const pressableStyle =
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
+
const pressableStyle = useMemo(() => [rowStyle, {
|
|
424
|
+
backgroundColor: background,
|
|
425
|
+
overflow: "hidden"
|
|
426
|
+
}, press.animatedStyle], [rowStyle, background, press.animatedStyle]);
|
|
427
|
+
const overlayStaticStyle = useMemo(() => ({
|
|
428
|
+
backgroundColor: stateLayerScrim(theme.mode),
|
|
429
|
+
borderRadius: theme.radii.md,
|
|
430
|
+
borderCurve: "continuous"
|
|
431
|
+
}), [theme.mode, theme.radii.md]);
|
|
423
432
|
const cells = /*#__PURE__*/_jsxs(_Fragment, {
|
|
424
433
|
children: [selectable && /*#__PURE__*/_jsx(View, {
|
|
425
434
|
style: SELECT_CELL_STRUCTURE,
|
|
@@ -444,15 +453,25 @@ function DataTableRowInner({
|
|
|
444
453
|
children: cells
|
|
445
454
|
});
|
|
446
455
|
}
|
|
447
|
-
return /*#__PURE__*/_jsxs(
|
|
456
|
+
return /*#__PURE__*/_jsxs(AnimatedPressable, {
|
|
448
457
|
testID: testID,
|
|
449
458
|
accessibilityRole: "button",
|
|
450
459
|
hitSlop: hitSlop,
|
|
451
460
|
onPress: handlePress,
|
|
461
|
+
onPressIn: press.handlers.onPressIn,
|
|
462
|
+
onPressOut: press.handlers.onPressOut,
|
|
463
|
+
onLayout: press.onLayout,
|
|
452
464
|
onFocus: handleFocus,
|
|
453
465
|
onBlur: handleBlur,
|
|
466
|
+
android_ripple: Platform.OS === "android" ? {
|
|
467
|
+
color: rippleColor(theme.mode),
|
|
468
|
+
borderless: false
|
|
469
|
+
} : undefined,
|
|
454
470
|
style: pressableStyle,
|
|
455
|
-
children: [
|
|
471
|
+
children: [/*#__PURE__*/_jsx(Animated.View, {
|
|
472
|
+
pointerEvents: "none",
|
|
473
|
+
style: [StyleSheet.absoluteFill, overlayStaticStyle, press.overlayStyle]
|
|
474
|
+
}), focused && /*#__PURE__*/_jsx(View, {
|
|
456
475
|
pointerEvents: "none",
|
|
457
476
|
testID: testID === undefined ? undefined : `${testID}-focus-ring`,
|
|
458
477
|
style: focusRingStyle
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { StyleSheet } from "react-native";
|
|
3
4
|
/**
|
|
4
5
|
* DataTable's style + behaviour resolution — the same split every sibling module copies
|
|
5
6
|
* (see `Select.variants.ts` / `Menu.variants.ts`):
|
|
@@ -129,12 +130,12 @@ export const dataTableRowStructure = createVariants({
|
|
|
129
130
|
alignItems: "stretch"
|
|
130
131
|
}
|
|
131
132
|
});
|
|
132
|
-
export const dataTableHeaderRowStructure = createThemedVariants(
|
|
133
|
+
export const dataTableHeaderRowStructure = createThemedVariants(_theme => ({
|
|
133
134
|
base: {
|
|
134
135
|
flexDirection: "row",
|
|
135
136
|
alignItems: "stretch",
|
|
136
137
|
height: DATA_TABLE_HEADER_HEIGHT,
|
|
137
|
-
borderBottomWidth:
|
|
138
|
+
borderBottomWidth: StyleSheet.hairlineWidth
|
|
138
139
|
}
|
|
139
140
|
}));
|
|
140
141
|
export const dataTableCellStructure = createThemedVariants(theme => ({
|
|
@@ -118,6 +118,7 @@ never sorts `data` itself and never owns `selectedKeys` — it reports the next
|
|
|
118
118
|
- **Row press vs. the selection checkbox** — the checkbox is its own nested `Pressable`; RN's
|
|
119
119
|
responder system lets the innermost element claim a touch, so pressing the checkbox never also
|
|
120
120
|
fires `onRowPress` (the standard, well-established RN pattern for a checkbox-in-row).
|
|
121
|
+
- **Row press feedback** — `usePressState` (scale + state-layer overlay) when `onRowPress` is set.
|
|
121
122
|
- **Default cell text** reads `row[column.key]` through a narrow, documented `unknown` escape —
|
|
122
123
|
`T` is intentionally unconstrained so any row shape works without a `render`.
|
|
123
124
|
|