@telus-uds/components-base 0.0.2-prerelease.7 → 1.0.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/.eslintrc.js +9 -0
- package/.ultra.cache.json +1 -1
- package/CHANGELOG.md +71 -0
- package/README.md +4 -2
- package/__fixtures__/Accessible.js +33 -0
- package/__fixtures__/Accessible.native.js +32 -0
- package/__fixtures__/test-utils.js +25 -0
- package/__fixtures__/testTheme.js +438 -31
- package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
- package/__tests__/Button/ButtonGroup.test.jsx +6 -7
- package/__tests__/Checkbox/Checkbox.test.jsx +2 -2
- package/__tests__/Checkbox/CheckboxGroup.test.jsx +246 -0
- package/__tests__/ExpandCollapse/ExpandCollapse.test.jsx +2 -2
- package/__tests__/HorizontalScroll/HorizontalScroll.test.jsx +164 -0
- package/__tests__/Icon/Icon.test.jsx +3 -3
- package/__tests__/IconButton/IconButton.test.jsx +52 -0
- package/__tests__/Link/LinkBase.test.jsx +0 -14
- package/__tests__/Modal/Modal.test.jsx +47 -0
- package/__tests__/Notification/Notification.test.jsx +20 -0
- package/__tests__/Pagination/Pagination.test.jsx +2 -2
- package/__tests__/Progress/Progress.test.jsx +79 -0
- package/__tests__/Radio/Radio.test.jsx +2 -2
- package/__tests__/Radio/RadioGroup.test.jsx +220 -0
- package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
- package/__tests__/RadioCard/RadioCardGroup.test.jsx +246 -0
- package/__tests__/Search/Search.test.jsx +73 -0
- package/__tests__/Select/Select.test.jsx +3 -2
- package/__tests__/Skeleton/Skeleton.test.jsx +1 -1
- package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
- package/__tests__/Tabs/Tabs.test.jsx +40 -0
- package/__tests__/Tags/Tags.test.jsx +5 -6
- package/__tests__/TextInput/TextArea.test.jsx +3 -2
- package/__tests__/TextInput/TextInputBase.test.jsx +10 -5
- package/__tests__/ThemeProvider/ThemeProvider.test.jsx +77 -0
- package/__tests__/ThemeProvider/useThemeTokens.test.jsx +9 -5
- package/__tests__/ThemeProvider/utils/theme-tokens.test.js +41 -0
- package/__tests__/ToggleSwitch/ToggleSwitch.test.jsx +3 -2
- package/__tests__/utils/children.test.jsx +128 -0
- package/__tests__/utils/input.test.js +59 -1
- package/__tests__/utils/semantics.test.jsx +43 -0
- package/__tests__/utils/useCopy.test.js +14 -3
- package/babel.config.js +20 -0
- package/jest.config.js +6 -3
- package/lib/A11yInfoProvider/index.js +54 -26
- package/lib/A11yText/index.js +45 -17
- package/lib/ActivityIndicator/Spinner.js +81 -0
- package/lib/ActivityIndicator/Spinner.native.js +129 -91
- package/lib/ActivityIndicator/index.js +28 -12
- package/lib/ActivityIndicator/shared.js +27 -12
- package/lib/BaseProvider/index.js +34 -11
- package/lib/Box/Box.js +153 -35
- package/lib/Box/index.js +13 -2
- package/lib/Button/Button.js +38 -16
- package/lib/Button/ButtonBase.js +93 -79
- package/lib/Button/ButtonGroup.js +112 -73
- package/lib/Button/ButtonLink.js +45 -19
- package/lib/Button/index.js +31 -4
- package/lib/Button/propTypes.js +32 -9
- package/lib/Card/Card.js +38 -41
- package/lib/Card/CardBase.js +86 -0
- package/lib/Card/PressableCardBase.js +141 -0
- package/lib/Card/index.js +40 -2
- package/lib/Checkbox/Checkbox.js +158 -111
- package/lib/Checkbox/CheckboxGroup.js +241 -0
- package/lib/Checkbox/CheckboxInput.js +74 -0
- package/lib/Checkbox/CheckboxInput.native.js +9 -1
- package/lib/Checkbox/index.js +21 -2
- package/lib/Divider/Divider.js +59 -28
- package/lib/Divider/index.js +13 -2
- package/lib/ExpandCollapse/Accordion.js +26 -7
- package/lib/ExpandCollapse/Control.js +60 -31
- package/lib/ExpandCollapse/ExpandCollapse.js +50 -28
- package/lib/ExpandCollapse/Panel.js +83 -44
- package/lib/ExpandCollapse/index.js +25 -7
- package/lib/Feedback/Feedback.js +77 -43
- package/lib/Feedback/index.js +13 -2
- package/lib/Fieldset/Fieldset.js +165 -0
- package/lib/Fieldset/FieldsetContainer.js +46 -0
- package/lib/Fieldset/FieldsetContainer.native.js +38 -0
- package/lib/Fieldset/Legend.js +38 -0
- package/lib/Fieldset/Legend.native.js +48 -0
- package/lib/Fieldset/cssReset.js +21 -0
- package/lib/Fieldset/index.js +13 -0
- package/lib/FlexGrid/Col/Col.js +73 -41
- package/lib/FlexGrid/Col/index.js +13 -2
- package/lib/FlexGrid/FlexGrid.js +99 -49
- package/lib/FlexGrid/Row/Row.js +58 -30
- package/lib/FlexGrid/Row/index.js +13 -2
- package/lib/FlexGrid/helpers/index.js +9 -1
- package/lib/FlexGrid/index.js +13 -2
- package/lib/FlexGrid/providers/GutterContext.js +15 -3
- package/lib/HorizontalScroll/HorizontalScroll.js +200 -0
- package/lib/HorizontalScroll/HorizontalScrollButton.js +127 -0
- package/lib/HorizontalScroll/ScrollViewEnd.js +66 -0
- package/lib/HorizontalScroll/ScrollViewEnd.native.js +41 -0
- package/lib/HorizontalScroll/dictionary.js +18 -0
- package/lib/HorizontalScroll/index.js +35 -0
- package/lib/HorizontalScroll/itemPositions.js +128 -0
- package/lib/Icon/Icon.js +57 -48
- package/lib/Icon/IconText.js +54 -25
- package/lib/Icon/index.js +31 -4
- package/lib/IconButton/IconButton.js +140 -0
- package/lib/IconButton/index.js +13 -0
- package/lib/InputLabel/InputLabel.js +102 -40
- package/lib/InputLabel/LabelContent.js +41 -0
- package/lib/InputLabel/LabelContent.native.js +32 -6
- package/lib/InputLabel/index.js +13 -2
- package/lib/InputSupports/InputSupports.js +71 -52
- package/lib/InputSupports/index.js +13 -2
- package/lib/InputSupports/propTypes.js +19 -8
- package/lib/InputSupports/useInputSupports.js +41 -0
- package/lib/Link/ChevronLink.js +44 -20
- package/lib/Link/InlinePressable.js +56 -0
- package/lib/Link/InlinePressable.native.js +39 -15
- package/lib/Link/Link.js +36 -13
- package/lib/Link/LinkBase.js +98 -61
- package/lib/Link/TextButton.js +41 -17
- package/lib/Link/index.js +39 -5
- package/lib/List/List.js +55 -26
- package/lib/List/ListItem.js +79 -41
- package/lib/List/index.js +13 -2
- package/lib/Modal/Modal.js +231 -0
- package/lib/Modal/dictionary.js +16 -0
- package/lib/Modal/index.js +13 -0
- package/lib/Notification/Notification.js +216 -0
- package/lib/Notification/dictionary.js +15 -0
- package/lib/Notification/index.js +13 -0
- package/lib/Pagination/PageButton.js +61 -28
- package/lib/Pagination/Pagination.js +78 -43
- package/lib/Pagination/SideButton.js +73 -42
- package/lib/Pagination/dictionary.js +9 -2
- package/lib/Pagination/index.js +13 -2
- package/lib/Pagination/usePagination.js +12 -2
- package/lib/Progress/Progress.js +104 -0
- package/lib/Progress/ProgressBar.js +157 -0
- package/lib/Progress/ProgressBarBackground.js +61 -0
- package/lib/Progress/index.js +16 -0
- package/lib/Radio/Radio.js +116 -114
- package/lib/Radio/RadioButton.js +152 -0
- package/lib/Radio/RadioGroup.js +244 -0
- package/lib/Radio/RadioInput.js +76 -0
- package/lib/Radio/RadioInput.native.js +9 -1
- package/lib/Radio/index.js +21 -2
- package/lib/RadioCard/RadioCard.js +244 -0
- package/lib/RadioCard/RadioCardGroup.js +252 -0
- package/lib/RadioCard/index.js +21 -0
- package/lib/Search/Search.js +254 -0
- package/lib/Search/dictionary.js +19 -0
- package/lib/Search/index.js +13 -0
- package/lib/Select/Group.js +33 -0
- package/lib/Select/Group.native.js +16 -5
- package/lib/Select/Item.js +29 -0
- package/lib/Select/Item.native.js +14 -4
- package/lib/Select/Picker.js +84 -0
- package/lib/Select/Picker.native.js +73 -30
- package/lib/Select/Select.js +155 -85
- package/lib/Select/index.js +19 -6
- package/lib/SideNav/Item.js +63 -37
- package/lib/SideNav/ItemContent.js +41 -15
- package/lib/SideNav/ItemsGroup.js +55 -31
- package/lib/SideNav/SideNav.js +100 -73
- package/lib/SideNav/index.js +15 -1
- package/lib/Skeleton/Skeleton.js +64 -46
- package/lib/Skeleton/index.js +13 -2
- package/lib/Skeleton/skeleton.constant.js +12 -0
- package/lib/Skeleton/skeletonWebAnimation.js +27 -0
- package/lib/Skeleton/useSkeletonNativeAnimation.js +37 -0
- package/lib/Spacer/Spacer.js +49 -18
- package/lib/Spacer/index.js +13 -2
- package/lib/StackView/StackView.js +72 -31
- package/lib/StackView/StackWrap.js +43 -13
- package/lib/StackView/StackWrap.native.js +13 -2
- package/lib/StackView/StackWrapBox.js +77 -29
- package/lib/StackView/StackWrapGap.js +56 -26
- package/lib/StackView/common.js +23 -6
- package/lib/StackView/getStackedContent.js +47 -17
- package/lib/StackView/index.js +29 -5
- package/lib/StepTracker/Step.js +245 -0
- package/lib/StepTracker/StepTracker.js +202 -0
- package/lib/StepTracker/dictionary.js +17 -0
- package/lib/StepTracker/index.js +13 -0
- package/lib/Tabs/Tabs.js +124 -0
- package/lib/Tabs/TabsItem.js +238 -0
- package/lib/Tabs/index.js +13 -0
- package/lib/Tags/Tags.js +148 -99
- package/lib/Tags/index.js +13 -2
- package/lib/TextInput/TextArea.js +57 -28
- package/lib/TextInput/TextInput.js +50 -23
- package/lib/TextInput/TextInputBase.js +90 -63
- package/lib/TextInput/index.js +23 -3
- package/lib/TextInput/propTypes.js +18 -7
- package/lib/ThemeProvider/ThemeProvider.js +46 -18
- package/lib/ThemeProvider/index.js +61 -6
- package/lib/ThemeProvider/useSetTheme.js +19 -5
- package/lib/ThemeProvider/useTheme.js +13 -4
- package/lib/ThemeProvider/useThemeTokens.js +32 -16
- package/lib/ThemeProvider/utils/index.js +31 -2
- package/lib/ThemeProvider/utils/styles.js +50 -14
- package/lib/ThemeProvider/utils/theme-tokens.js +121 -12
- package/lib/ToggleSwitch/ToggleSwitch.js +85 -56
- package/lib/ToggleSwitch/index.js +13 -2
- package/lib/Tooltip/{Backdrop.web.js → Backdrop.js} +20 -8
- package/lib/Tooltip/Backdrop.native.js +39 -15
- package/lib/Tooltip/Tooltip.js +117 -74
- package/lib/Tooltip/dictionary.js +9 -2
- package/lib/Tooltip/getTooltipPosition.js +9 -1
- package/lib/Tooltip/index.js +13 -2
- package/lib/TooltipButton/TooltipButton.js +57 -38
- package/lib/TooltipButton/index.js +13 -2
- package/lib/Typography/Typography.js +87 -41
- package/lib/Typography/index.js +13 -2
- package/lib/ViewportProvider/ViewportProvider.js +34 -13
- package/lib/ViewportProvider/index.js +28 -3
- package/lib/ViewportProvider/useViewport.js +15 -3
- package/lib/ViewportProvider/useViewportListener.js +24 -10
- package/lib/index.js +539 -33
- package/lib/utils/a11y/index.js +31 -1
- package/lib/utils/a11y/semantics.js +173 -0
- package/lib/utils/a11y/textSize.js +23 -7
- package/lib/utils/animation/index.js +15 -2
- package/lib/utils/animation/useVerticalExpandAnimation.js +27 -10
- package/lib/utils/children.js +134 -0
- package/lib/utils/index.js +163 -10
- package/lib/utils/info/index.js +18 -6
- package/lib/utils/info/platform/index.js +19 -7
- package/lib/utils/info/platform/platform.android.js +8 -1
- package/lib/utils/info/platform/platform.ios.js +8 -1
- package/lib/utils/info/platform/platform.js +8 -0
- package/lib/utils/info/platform/platform.native.js +8 -1
- package/lib/utils/info/versions.js +15 -4
- package/lib/utils/input.js +53 -25
- package/lib/utils/pressability.js +38 -10
- package/lib/utils/propTypes.js +287 -141
- package/lib/utils/useCopy.js +40 -5
- package/lib/utils/useHash.js +52 -0
- package/lib/utils/useHash.native.js +15 -0
- package/lib/utils/useResponsiveProp.js +21 -9
- package/lib/utils/useSpacingScale.js +19 -9
- package/lib/utils/useUniqueId.js +12 -3
- package/package.json +14 -9
- package/release-context.json +4 -4
- package/src/A11yText/index.jsx +6 -4
- package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +5 -3
- package/src/ActivityIndicator/Spinner.native.jsx +5 -3
- package/src/Box/Box.jsx +132 -39
- package/src/Button/Button.jsx +10 -6
- package/src/Button/ButtonBase.jsx +99 -99
- package/src/Button/ButtonGroup.jsx +81 -69
- package/src/Button/ButtonLink.jsx +21 -15
- package/src/Button/propTypes.js +12 -2
- package/src/Card/Card.jsx +5 -31
- package/src/Card/CardBase.jsx +59 -0
- package/src/Card/PressableCardBase.jsx +119 -0
- package/src/Card/index.js +3 -0
- package/src/Checkbox/Checkbox.jsx +121 -112
- package/src/Checkbox/CheckboxGroup.jsx +206 -0
- package/src/Checkbox/{CheckboxInput.web.jsx → CheckboxInput.jsx} +0 -0
- package/src/Checkbox/index.js +2 -0
- package/src/Divider/Divider.jsx +7 -4
- package/src/ExpandCollapse/Accordion.jsx +3 -2
- package/src/ExpandCollapse/Control.jsx +40 -43
- package/src/ExpandCollapse/ExpandCollapse.jsx +26 -23
- package/src/ExpandCollapse/Panel.jsx +69 -63
- package/src/Feedback/Feedback.jsx +36 -33
- package/src/Fieldset/Fieldset.jsx +136 -0
- package/src/Fieldset/FieldsetContainer.jsx +31 -0
- package/src/Fieldset/FieldsetContainer.native.jsx +19 -0
- package/src/Fieldset/Legend.jsx +21 -0
- package/src/Fieldset/Legend.native.jsx +27 -0
- package/src/Fieldset/cssReset.js +14 -0
- package/src/Fieldset/index.js +3 -0
- package/src/FlexGrid/Col/Col.jsx +139 -132
- package/src/FlexGrid/FlexGrid.jsx +79 -51
- package/src/FlexGrid/Row/Row.jsx +55 -48
- package/src/HorizontalScroll/HorizontalScroll.jsx +168 -0
- package/src/HorizontalScroll/HorizontalScrollButton.jsx +105 -0
- package/src/HorizontalScroll/ScrollViewEnd.jsx +53 -0
- package/src/HorizontalScroll/ScrollViewEnd.native.jsx +24 -0
- package/src/HorizontalScroll/dictionary.js +11 -0
- package/src/HorizontalScroll/index.js +17 -0
- package/src/HorizontalScroll/itemPositions.js +101 -0
- package/src/Icon/Icon.jsx +43 -50
- package/src/Icon/IconText.jsx +23 -18
- package/src/Icon/index.js +2 -2
- package/src/IconButton/IconButton.jsx +114 -0
- package/src/IconButton/index.js +3 -0
- package/src/InputLabel/InputLabel.jsx +57 -35
- package/src/InputLabel/LabelContent.jsx +21 -0
- package/src/InputLabel/LabelContent.native.jsx +11 -2
- package/src/InputSupports/InputSupports.jsx +29 -45
- package/src/InputSupports/useInputSupports.js +30 -0
- package/src/Link/ChevronLink.jsx +26 -16
- package/src/Link/{InlinePressable.web.jsx → InlinePressable.jsx} +5 -3
- package/src/Link/InlinePressable.native.jsx +5 -3
- package/src/Link/Link.jsx +22 -16
- package/src/Link/LinkBase.jsx +76 -65
- package/src/Link/TextButton.jsx +30 -23
- package/src/List/List.jsx +5 -4
- package/src/List/ListItem.jsx +77 -82
- package/src/Modal/Modal.jsx +190 -0
- package/src/Modal/dictionary.js +9 -0
- package/src/Modal/index.js +3 -0
- package/src/Notification/Notification.jsx +164 -0
- package/src/Notification/dictionary.js +8 -0
- package/src/Notification/index.js +3 -0
- package/src/Pagination/PageButton.jsx +42 -35
- package/src/Pagination/Pagination.jsx +88 -92
- package/src/Pagination/SideButton.jsx +44 -41
- package/src/Progress/Progress.jsx +78 -0
- package/src/Progress/ProgressBar.jsx +123 -0
- package/src/Progress/ProgressBarBackground.jsx +36 -0
- package/src/Progress/index.js +6 -0
- package/src/Radio/Radio.jsx +82 -112
- package/src/Radio/RadioButton.jsx +142 -0
- package/src/Radio/RadioGroup.jsx +209 -0
- package/src/Radio/{RadioInput.web.jsx → RadioInput.jsx} +0 -0
- package/src/Radio/index.js +2 -0
- package/src/RadioCard/RadioCard.jsx +198 -0
- package/src/RadioCard/RadioCardGroup.jsx +218 -0
- package/src/RadioCard/index.js +5 -0
- package/src/Search/Search.jsx +225 -0
- package/src/Search/dictionary.js +12 -0
- package/src/Search/index.js +3 -0
- package/src/Select/{Group.web.jsx → Group.jsx} +0 -0
- package/src/Select/{Item.web.jsx → Item.jsx} +0 -0
- package/src/Select/Picker.jsx +74 -0
- package/src/Select/Picker.native.jsx +56 -49
- package/src/Select/Select.jsx +125 -92
- package/src/SideNav/Item.jsx +54 -47
- package/src/SideNav/ItemsGroup.jsx +50 -43
- package/src/SideNav/SideNav.jsx +68 -60
- package/src/Skeleton/Skeleton.jsx +25 -32
- package/src/Skeleton/skeleton.constant.js +3 -0
- package/src/Skeleton/skeletonWebAnimation.js +13 -0
- package/src/Skeleton/useSkeletonNativeAnimation.js +27 -0
- package/src/Spacer/Spacer.jsx +11 -4
- package/src/StackView/StackView.jsx +54 -23
- package/src/StackView/StackWrap.jsx +16 -7
- package/src/StackView/StackWrapBox.jsx +63 -28
- package/src/StackView/StackWrapGap.jsx +46 -24
- package/src/StackView/common.jsx +3 -2
- package/src/StackView/getStackedContent.jsx +8 -2
- package/src/StepTracker/Step.jsx +202 -0
- package/src/StepTracker/StepTracker.jsx +174 -0
- package/src/StepTracker/dictionary.js +10 -0
- package/src/StepTracker/index.js +3 -0
- package/src/Tabs/Tabs.jsx +97 -0
- package/src/Tabs/TabsItem.jsx +212 -0
- package/src/Tabs/index.js +3 -0
- package/src/Tags/Tags.jsx +115 -102
- package/src/TextInput/TextArea.jsx +5 -4
- package/src/TextInput/TextInput.jsx +5 -4
- package/src/TextInput/TextInputBase.jsx +95 -98
- package/src/ThemeProvider/ThemeProvider.jsx +11 -7
- package/src/ThemeProvider/useSetTheme.js +4 -0
- package/src/ThemeProvider/useThemeTokens.js +2 -2
- package/src/ThemeProvider/utils/styles.js +18 -5
- package/src/ThemeProvider/utils/theme-tokens.js +74 -5
- package/src/ToggleSwitch/ToggleSwitch.jsx +50 -52
- package/src/Tooltip/{Backdrop.web.jsx → Backdrop.jsx} +0 -0
- package/src/Tooltip/Tooltip.jsx +135 -131
- package/src/TooltipButton/TooltipButton.jsx +23 -27
- package/src/Typography/Typography.jsx +71 -47
- package/src/index.js +23 -2
- package/src/utils/a11y/index.js +1 -0
- package/src/utils/a11y/semantics.js +162 -0
- package/src/utils/children.jsx +119 -0
- package/src/utils/index.js +3 -0
- package/src/utils/info/platform/platform.js +1 -0
- package/src/utils/info/versions.js +2 -2
- package/src/utils/input.js +36 -25
- package/src/utils/pressability.js +4 -0
- package/src/utils/propTypes.js +199 -72
- package/src/utils/useCopy.js +30 -4
- package/src/utils/useHash.js +39 -0
- package/src/utils/useHash.native.js +6 -0
- package/stories/A11yText/A11yText.stories.jsx +6 -10
- package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +1 -1
- package/stories/Box/Box.stories.jsx +1 -1
- package/stories/Button/Button.stories.jsx +2 -2
- package/stories/Button/ButtonGroup.stories.jsx +1 -1
- package/stories/Button/ButtonLink.stories.jsx +1 -1
- package/stories/Card/Card.stories.jsx +1 -1
- package/stories/Checkbox/Checkbox.stories.jsx +24 -1
- package/stories/Divider/Divider.stories.jsx +1 -1
- package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +2 -2
- package/stories/Feedback/Feedback.stories.jsx +1 -1
- package/stories/FlexGrid/01 FlexGrid.stories.jsx +1 -1
- package/stories/FlexGrid/02 Row.stories.jsx +1 -1
- package/stories/FlexGrid/03 Col.stories.jsx +1 -1
- package/stories/Icon/Icon.stories.jsx +27 -7
- package/stories/IconButton/IconButton.stories.jsx +50 -0
- package/stories/InputLabel/InputLabel.stories.jsx +1 -1
- package/stories/Link/ChevronLink.stories.jsx +1 -1
- package/stories/Link/Link.stories.jsx +17 -21
- package/stories/Link/TextButton.stories.jsx +1 -1
- package/stories/List/List.stories.jsx +1 -1
- package/stories/Modal/Modal.stories.jsx +29 -0
- package/stories/Notification/Notification.stories.jsx +82 -0
- package/stories/Pagination/Pagination.stories.jsx +1 -1
- package/stories/Progress/Progress.stories.jsx +93 -0
- package/stories/Radio/Radio.stories.jsx +23 -36
- package/stories/RadioCard/RadioCard.stories.jsx +98 -0
- package/stories/Search/Search.stories.jsx +16 -0
- package/stories/Select/Select.stories.jsx +1 -1
- package/stories/SideNav/SideNav.stories.jsx +1 -1
- package/stories/SideNav/SideNavItem.stories.jsx +1 -1
- package/stories/SideNav/SideNavItemsGroup.stories.jsx +1 -1
- package/stories/Skeleton/Skeleton.stories.jsx +2 -2
- package/stories/Spacer/Spacer.stories.jsx +1 -1
- package/stories/StackView/StackView.stories.jsx +1 -1
- package/stories/StackView/StackWrap.stories.jsx +1 -1
- package/stories/StepTracker/StepTracker.stories.jsx +71 -0
- package/stories/Tabs/Tabs.stories.jsx +97 -0
- package/stories/Tags/Tags.stories.jsx +1 -1
- package/stories/TextInput/TextArea.stories.jsx +1 -1
- package/stories/TextInput/TextInput.stories.jsx +1 -1
- package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +1 -1
- package/stories/Tooltip/Tooltip.stories.jsx +1 -1
- package/stories/TooltipButton/TooltipButton.stories.jsx +1 -1
- package/stories/Typography/Typography.stories.jsx +1 -1
- package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
- package/stories/supports.jsx +37 -3
- package/__fixtures__/accessible.icon.svg +0 -6
- package/babel.config.json +0 -8
- package/docs/Contributing.stories.mdx +0 -9
- package/docs/Fonts.stories.mdx +0 -104
- package/docs/Icons.stories.mdx +0 -144
- package/docs/Introduction.stories.mdx +0 -9
- package/lib/ActivityIndicator/Spinner.web.js +0 -55
- package/lib/Checkbox/CheckboxInput.web.js +0 -57
- package/lib/InputLabel/LabelContent.web.js +0 -17
- package/lib/Link/InlinePressable.web.js +0 -32
- package/lib/Radio/RadioInput.web.js +0 -59
- package/lib/Select/Group.web.js +0 -18
- package/lib/Select/Item.web.js +0 -15
- package/lib/Select/Picker.web.js +0 -63
- package/lib/config/svgr-icons-web.js +0 -9
- package/lib/config/svgr-icons.js +0 -52
- package/lib/utils/info/platform/platform.web.js +0 -1
- package/src/InputLabel/LabelContent.web.jsx +0 -13
- package/src/Select/Picker.web.jsx +0 -67
- package/src/config/svgr-icons-web.js +0 -11
- package/src/config/svgr-icons.js +0 -46
- package/src/utils/info/platform/platform.web.js +0 -1
package/src/Link/LinkBase.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { Text, Platform, StyleSheet } from 'react-native'
|
|
4
4
|
import {
|
|
@@ -11,27 +11,28 @@ import {
|
|
|
11
11
|
import { resolvePressableTokens } from '../utils/pressability'
|
|
12
12
|
|
|
13
13
|
import InlinePressable from './InlinePressable'
|
|
14
|
-
import { applyTextStyles } from '../ThemeProvider'
|
|
14
|
+
import { applyTextStyles, applyOuterBorder } from '../ThemeProvider'
|
|
15
15
|
import { IconText, iconComponentPropTypes } from '../Icon'
|
|
16
16
|
|
|
17
17
|
const selectOuterBorderStyles = ({
|
|
18
18
|
outerBorderColor,
|
|
19
19
|
outerBorderWidth,
|
|
20
20
|
outerBorderGap,
|
|
21
|
-
|
|
21
|
+
borderRadius,
|
|
22
22
|
outerBorderOutline
|
|
23
23
|
}) =>
|
|
24
24
|
// A view wrapper with a border on native messes up inline text alignment
|
|
25
25
|
// so for now make focus styles strictly web-only
|
|
26
26
|
Platform.OS === 'web'
|
|
27
27
|
? {
|
|
28
|
-
margin: -1 * (outerBorderGap + outerBorderWidth) || 0,
|
|
29
|
-
padding: outerBorderGap,
|
|
30
28
|
// Allow theme to define outline, or, turn off outline and use border if rounded corners required
|
|
31
29
|
outline: outerBorderOutline,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
...applyOuterBorder({
|
|
31
|
+
outerBorderColor,
|
|
32
|
+
outerBorderWidth,
|
|
33
|
+
outerBorderGap,
|
|
34
|
+
borderRadius
|
|
35
|
+
}),
|
|
35
36
|
// Stops focus ring stretching horizontally if parent has display: block
|
|
36
37
|
// width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
|
|
37
38
|
display: 'inline-flex'
|
|
@@ -87,68 +88,78 @@ const selectIconTokens = ({ color, iconSize, iconTranslateX, iconTranslateY }) =
|
|
|
87
88
|
* dropped in favour of investigating if a full-featured CSS-in-JS package could or
|
|
88
89
|
* should be used more widely (e.g. styled components)
|
|
89
90
|
*/
|
|
90
|
-
const LinkBase = (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
const LinkBase = forwardRef(
|
|
92
|
+
(
|
|
93
|
+
{
|
|
94
|
+
href,
|
|
95
|
+
onPress,
|
|
96
|
+
icon,
|
|
97
|
+
iconPosition = icon ? 'left' : undefined,
|
|
98
|
+
iconProps,
|
|
99
|
+
variant,
|
|
100
|
+
tokens = {},
|
|
101
|
+
children,
|
|
102
|
+
accessibilityRole = 'link',
|
|
103
|
+
dataSet,
|
|
104
|
+
...props
|
|
105
|
+
},
|
|
106
|
+
ref
|
|
107
|
+
) => {
|
|
108
|
+
const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
|
|
109
|
+
const linkPropSet = linkProps.select({
|
|
110
|
+
accessibilityRole,
|
|
111
|
+
href,
|
|
112
|
+
onPress: linkProps.handleHref({ href, onPress }),
|
|
113
|
+
hrefAttrs,
|
|
114
|
+
...rest
|
|
115
|
+
})
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
const resolveLinkTokens = (pressState) =>
|
|
118
|
+
resolvePressableTokens(tokens, pressState, { iconPosition })
|
|
112
119
|
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
// On web, this makes focus rings wrap only the link, not the entire block
|
|
121
|
+
const blockLeftStyle = Platform.OS === 'web' && staticStyles.blockLeft
|
|
115
122
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
123
|
+
return (
|
|
124
|
+
<InlinePressable
|
|
125
|
+
{...linkPropSet}
|
|
126
|
+
ref={ref}
|
|
127
|
+
dataSet={dataSet}
|
|
128
|
+
style={(linkState) => {
|
|
129
|
+
const themeTokens = resolveLinkTokens(linkState)
|
|
130
|
+
const outerBorderStyles = selectOuterBorderStyles(themeTokens)
|
|
131
|
+
const hasIcon = Boolean(icon || themeTokens.icon)
|
|
132
|
+
return [outerBorderStyles, blockLeftStyle, hasIcon && staticStyles.rowContainer]
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
{(linkState) => {
|
|
136
|
+
const themeTokens = resolveLinkTokens(linkState)
|
|
137
|
+
const textStyles = selectTextStyles(themeTokens)
|
|
138
|
+
const iconTokens = selectIconTokens(themeTokens)
|
|
130
139
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
// TODO: may need to apply some smarter text inheritance here if inline to avoid native
|
|
141
|
+
// issues like double-application of line heights breaking align-items: baseline
|
|
142
|
+
const blockTextStyles = selectBlockStyles(themeTokens)
|
|
134
143
|
|
|
135
|
-
|
|
136
|
-
|
|
144
|
+
const IconComponent = icon || themeTokens.icon
|
|
145
|
+
const { iconSpace } = themeTokens
|
|
137
146
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
147
|
+
return (
|
|
148
|
+
<IconText
|
|
149
|
+
icon={IconComponent}
|
|
150
|
+
iconPosition={iconPosition}
|
|
151
|
+
space={iconSpace}
|
|
152
|
+
iconProps={{ ...iconProps, tokens: iconTokens }}
|
|
153
|
+
>
|
|
154
|
+
<Text style={[textStyles, blockTextStyles, staticStyles.baseline]}>{children}</Text>
|
|
155
|
+
</IconText>
|
|
156
|
+
)
|
|
157
|
+
}}
|
|
158
|
+
</InlinePressable>
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
LinkBase.displayName = 'LinkBase'
|
|
152
163
|
|
|
153
164
|
LinkBase.propTypes = {
|
|
154
165
|
...a11yProps.types,
|
|
@@ -170,7 +181,7 @@ LinkBase.propTypes = {
|
|
|
170
181
|
iconPosition: PropTypes.oneOf(['left', 'right']),
|
|
171
182
|
/**
|
|
172
183
|
* On Web if href is passed, React Native Web maps this object's props to
|
|
173
|
-
* `rel`, `target` and
|
|
184
|
+
* `rel`, `target` and `download` attrs.
|
|
174
185
|
*/
|
|
175
186
|
hrefAttrs: PropTypes.shape(hrefAttrsProp.types)
|
|
176
187
|
}
|
package/src/Link/TextButton.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
|
|
4
4
|
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
@@ -9,28 +9,35 @@ import LinkBase from './LinkBase'
|
|
|
9
9
|
* Link but has the accessibility role of a `Button`. It should be used for actions that
|
|
10
10
|
* take place on the current page, or for navigation within an app.
|
|
11
11
|
*/
|
|
12
|
-
const TextButton = (
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
12
|
+
const TextButton = forwardRef(
|
|
13
|
+
(
|
|
14
|
+
{
|
|
15
|
+
onPress,
|
|
16
|
+
children,
|
|
17
|
+
variant,
|
|
18
|
+
tokens,
|
|
19
|
+
// TODO: this may need to use `link` role on Web in the case of being passed both `href` and
|
|
20
|
+
// `onPress` in an omniplatform app that uses React Navigation's useLinkProps for internal nav.
|
|
21
|
+
accessibilityRole = 'button',
|
|
22
|
+
...linkProps
|
|
23
|
+
},
|
|
24
|
+
ref
|
|
25
|
+
) => {
|
|
26
|
+
const getTokens = useThemeTokensCallback('Link', tokens, variant)
|
|
27
|
+
return (
|
|
28
|
+
<LinkBase
|
|
29
|
+
onPress={onPress}
|
|
30
|
+
accessibilityRole={accessibilityRole}
|
|
31
|
+
tokens={getTokens}
|
|
32
|
+
ref={ref}
|
|
33
|
+
{...linkProps}
|
|
34
|
+
>
|
|
35
|
+
{children}
|
|
36
|
+
</LinkBase>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
TextButton.displayName = 'TextButton'
|
|
34
41
|
|
|
35
42
|
TextButton.propTypes = {
|
|
36
43
|
...LinkBase.propTypes,
|
package/src/List/List.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { cloneElement, Children } from 'react'
|
|
1
|
+
import React, { cloneElement, forwardRef, Children } from 'react'
|
|
2
2
|
import { View, Platform } from 'react-native'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
import { getTokensPropType, variantProp, componentPropType } from '../utils'
|
|
@@ -9,7 +9,7 @@ import ListItem from './ListItem'
|
|
|
9
9
|
* A Unordered List component has a child a ListItem that
|
|
10
10
|
* allows icon, dividers and customized typography
|
|
11
11
|
*/
|
|
12
|
-
const List = ({ children, showDivider, tokens, variant, ...rest }) => {
|
|
12
|
+
const List = forwardRef(({ children, showDivider, tokens, variant, ...rest }, ref) => {
|
|
13
13
|
const accessibilityRole = Platform.select({ web: 'list', default: 'none' })
|
|
14
14
|
const a11y = a11yProps.select(rest)
|
|
15
15
|
const items = Children.map(children, (child, index) => {
|
|
@@ -25,11 +25,12 @@ const List = ({ children, showDivider, tokens, variant, ...rest }) => {
|
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
return (
|
|
28
|
-
<View accessibilityRole={accessibilityRole} {...a11y}>
|
|
28
|
+
<View ref={ref} accessibilityRole={accessibilityRole} {...a11y}>
|
|
29
29
|
{items}
|
|
30
30
|
</View>
|
|
31
31
|
)
|
|
32
|
-
}
|
|
32
|
+
})
|
|
33
|
+
List.displayName = 'List'
|
|
33
34
|
|
|
34
35
|
List.Item = ListItem
|
|
35
36
|
|
package/src/List/ListItem.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
2
|
import { View, Platform, Text, StyleSheet } from 'react-native'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
import { useThemeTokens, applyTextStyles } from '../ThemeProvider'
|
|
@@ -48,104 +48,96 @@ const selectDividerStyles = ({ dividerColor, dividerSize, interItemMarginWithDiv
|
|
|
48
48
|
/**
|
|
49
49
|
* ListItem is responsible for rendering icon or a bullet as side item
|
|
50
50
|
*/
|
|
51
|
-
const ListItem = (
|
|
52
|
-
tokens,
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const accessibilityRole = Platform.select({ web: 'listitem', default: 'item' })
|
|
71
|
-
|
|
72
|
-
const areChildrenStrings = () => {
|
|
73
|
-
if (Array.isArray(children)) {
|
|
74
|
-
return children.every((child) => typeof child === 'string')
|
|
51
|
+
const ListItem = forwardRef(
|
|
52
|
+
({ tokens, variant, icon, iconColor, iconSize, showDivider, children, isLastItem }, ref) => {
|
|
53
|
+
const themeTokens = useThemeTokens('List', tokens, variant)
|
|
54
|
+
|
|
55
|
+
const itemStyles = selectItemStyles(themeTokens)
|
|
56
|
+
const itemBlockStyles = selectItemBlockStyles(themeTokens)
|
|
57
|
+
const dividerStyles = selectDividerStyles(themeTokens)
|
|
58
|
+
const itemBulletContainerStyles = selectBulletContainerStyles(themeTokens)
|
|
59
|
+
const itemBulletStyles = selectBulletStyles(themeTokens)
|
|
60
|
+
const iconTokens = selectItemIconTokens(themeTokens)
|
|
61
|
+
const sideItemContainerStyles = selectSideItemContainerStyles(themeTokens)
|
|
62
|
+
const accessibilityRole = Platform.select({ web: 'listitem', default: 'item' })
|
|
63
|
+
|
|
64
|
+
const areChildrenStrings = () => {
|
|
65
|
+
if (Array.isArray(children)) {
|
|
66
|
+
return children.every((child) => typeof child === 'string')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return typeof children === 'string'
|
|
75
70
|
}
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (areChildrenStrings()) {
|
|
82
|
-
return <Text style={itemStyles}>{children}</Text>
|
|
83
|
-
}
|
|
72
|
+
const renderItem = () => {
|
|
73
|
+
if (areChildrenStrings()) {
|
|
74
|
+
return <Text style={itemStyles}>{children}</Text>
|
|
75
|
+
}
|
|
84
76
|
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Function responsible returning styling, in case the item is the last shouldn't
|
|
90
|
-
* add extra margin on the bottom, if "showDivider" is true it should add a divider
|
|
91
|
-
* and custom margin and padding, otherwise just adds a margin to the bottom
|
|
92
|
-
*/
|
|
93
|
-
const getContainerStyle = () => {
|
|
94
|
-
if (isLastItem) {
|
|
95
|
-
return undefined
|
|
77
|
+
return <View style={staticStyles.wrap}>{children}</View>
|
|
96
78
|
}
|
|
97
79
|
|
|
98
|
-
|
|
99
|
-
|
|
80
|
+
/**
|
|
81
|
+
* Function responsible returning styling, in case the item is the last shouldn't
|
|
82
|
+
* add extra margin on the bottom, if "showDivider" is true it should add a divider
|
|
83
|
+
* and custom margin and padding, otherwise just adds a margin to the bottom
|
|
84
|
+
*/
|
|
85
|
+
const getContainerStyle = () => {
|
|
86
|
+
if (isLastItem) {
|
|
87
|
+
return undefined
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (showDivider) {
|
|
91
|
+
return dividerStyles
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return itemBlockStyles
|
|
100
95
|
}
|
|
101
96
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
97
|
+
/**
|
|
98
|
+
* Renders item bullet or Icon in case it's defined
|
|
99
|
+
* in case children are string the icon is centered otherwise
|
|
100
|
+
* it will align itself at start of the container
|
|
101
|
+
*/
|
|
102
|
+
const renderMarker = () => {
|
|
103
|
+
const IconComponent = icon || <></>
|
|
104
|
+
|
|
105
|
+
if (icon) {
|
|
106
|
+
return (
|
|
107
|
+
<View
|
|
108
|
+
style={[
|
|
109
|
+
sideItemContainerStyles,
|
|
110
|
+
areChildrenStrings() ? staticStyles.centeredIcons : undefined
|
|
111
|
+
]}
|
|
112
|
+
>
|
|
113
|
+
<IconComponent
|
|
114
|
+
size={iconSize || iconTokens.size}
|
|
115
|
+
color={iconColor || iconTokens.color}
|
|
116
|
+
/>
|
|
117
|
+
</View>
|
|
118
|
+
)
|
|
119
|
+
}
|
|
112
120
|
|
|
113
|
-
if (icon) {
|
|
114
121
|
return (
|
|
115
|
-
<View
|
|
116
|
-
style={
|
|
117
|
-
sideItemContainerStyles,
|
|
118
|
-
areChildrenStrings() ? staticStyles.centeredIcons : undefined
|
|
119
|
-
]}
|
|
120
|
-
>
|
|
121
|
-
<IconComponent
|
|
122
|
-
tokens={{
|
|
123
|
-
...iconTokens,
|
|
124
|
-
size: iconSize || iconTokens.size,
|
|
125
|
-
color: iconColor || iconTokens.color
|
|
126
|
-
}}
|
|
127
|
-
/>
|
|
122
|
+
<View style={[sideItemContainerStyles, itemBulletContainerStyles]}>
|
|
123
|
+
<View style={itemBulletStyles} testID="unordered-item-bullet" />
|
|
128
124
|
</View>
|
|
129
125
|
)
|
|
130
126
|
}
|
|
131
127
|
|
|
132
128
|
return (
|
|
133
|
-
<View
|
|
134
|
-
|
|
129
|
+
<View
|
|
130
|
+
ref={ref}
|
|
131
|
+
style={[staticStyles.itemContainer, getContainerStyle()]}
|
|
132
|
+
accessibilityRole={accessibilityRole}
|
|
133
|
+
>
|
|
134
|
+
{renderMarker()}
|
|
135
|
+
{renderItem()}
|
|
135
136
|
</View>
|
|
136
137
|
)
|
|
137
138
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<View
|
|
141
|
-
style={[staticStyles.itemContainer, getContainerStyle()]}
|
|
142
|
-
accessibilityRole={accessibilityRole}
|
|
143
|
-
>
|
|
144
|
-
{renderMarker()}
|
|
145
|
-
{renderItem()}
|
|
146
|
-
</View>
|
|
147
|
-
)
|
|
148
|
-
}
|
|
139
|
+
)
|
|
140
|
+
ListItem.displayName = 'ListItem'
|
|
149
141
|
|
|
150
142
|
const staticStyles = StyleSheet.create({
|
|
151
143
|
itemContainer: {
|
|
@@ -153,6 +145,9 @@ const staticStyles = StyleSheet.create({
|
|
|
153
145
|
},
|
|
154
146
|
centeredIcons: {
|
|
155
147
|
justifyContent: 'center'
|
|
148
|
+
},
|
|
149
|
+
wrap: {
|
|
150
|
+
flex: 1
|
|
156
151
|
}
|
|
157
152
|
})
|
|
158
153
|
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
import {
|
|
3
|
+
StyleSheet,
|
|
4
|
+
TouchableWithoutFeedback,
|
|
5
|
+
View,
|
|
6
|
+
Modal as NativeModal,
|
|
7
|
+
Platform
|
|
8
|
+
} from 'react-native'
|
|
9
|
+
|
|
10
|
+
import PropTypes from 'prop-types'
|
|
11
|
+
import { applyShadowToken, useThemeTokens } from '../ThemeProvider'
|
|
12
|
+
import { getTokensPropType, useCopy, copyPropTypes, variantProp } from '../utils'
|
|
13
|
+
import { useViewport } from '../ViewportProvider'
|
|
14
|
+
import ButtonBase from '../Button/ButtonBase'
|
|
15
|
+
import dictionary from './dictionary'
|
|
16
|
+
|
|
17
|
+
const selectContainerStyles = ({
|
|
18
|
+
containerPaddingLeft,
|
|
19
|
+
containerPaddingRight,
|
|
20
|
+
containerPaddingTop,
|
|
21
|
+
containerPaddingBottom,
|
|
22
|
+
maxWidth,
|
|
23
|
+
height
|
|
24
|
+
}) => ({
|
|
25
|
+
height,
|
|
26
|
+
maxWidth,
|
|
27
|
+
paddingLeft: containerPaddingLeft,
|
|
28
|
+
paddingRight: containerPaddingRight,
|
|
29
|
+
paddingTop: containerPaddingTop,
|
|
30
|
+
paddingBottom: containerPaddingBottom
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const selectModalStyles = ({
|
|
34
|
+
backgroundColor,
|
|
35
|
+
borderRadius,
|
|
36
|
+
height,
|
|
37
|
+
paddingLeft,
|
|
38
|
+
paddingRight,
|
|
39
|
+
paddingTop,
|
|
40
|
+
paddingBottom,
|
|
41
|
+
shadow
|
|
42
|
+
}) => ({
|
|
43
|
+
backgroundColor,
|
|
44
|
+
borderRadius,
|
|
45
|
+
height,
|
|
46
|
+
paddingLeft,
|
|
47
|
+
paddingRight,
|
|
48
|
+
paddingTop,
|
|
49
|
+
paddingBottom,
|
|
50
|
+
...applyShadowToken(shadow)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
const selectBackdropStyles = ({ backdropColor, backdropOpacity }) => ({
|
|
54
|
+
backgroundColor: backdropColor,
|
|
55
|
+
opacity: backdropOpacity
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const selectCloseButtonContainerStyles = ({ paddingRight, paddingTop }) => ({
|
|
59
|
+
paddingRight,
|
|
60
|
+
paddingTop
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const selectCloseIconProps = ({ closeIconSize, closeIconColor }) => ({
|
|
64
|
+
size: closeIconSize,
|
|
65
|
+
color: closeIconColor
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A modal window is a secondary window that opens on top of the main one.
|
|
70
|
+
* Users have to interact with it before they can carry out their task and return to the main window.
|
|
71
|
+
* Use to reveal additional information to a user after they have performed an explicit interaction.
|
|
72
|
+
* They are a strongly discouraged pattern; it's preferred to have all relevant information within a page,
|
|
73
|
+
* and irrelevant information either linked externally or omitted.
|
|
74
|
+
*
|
|
75
|
+
* - Must only appear after a customer interaction, not on page load or any other circumstance
|
|
76
|
+
* - Open a modal based on explicit customer action e.g. clicking on a button/link/form field
|
|
77
|
+
* - Only one modal should be "current" at any time
|
|
78
|
+
* - Read [WebAIM's documentation](https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/dialog.html) to create accessible modals
|
|
79
|
+
* - Don’t use modals to reinforce or repeat information already available in the parent page or view
|
|
80
|
+
* - Don’t use modals consecutively
|
|
81
|
+
*/
|
|
82
|
+
const Modal = forwardRef(({ children, isOpen, onClose, maxWidth, tokens, variant, copy }, ref) => {
|
|
83
|
+
const viewport = useViewport()
|
|
84
|
+
const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth })
|
|
85
|
+
|
|
86
|
+
const { closeIcon: CloseIconComponent } = themeTokens
|
|
87
|
+
|
|
88
|
+
const getCopy = useCopy({ dictionary, copy })
|
|
89
|
+
const closeLabel = getCopy('closeButton')
|
|
90
|
+
|
|
91
|
+
const handleClose = () => {
|
|
92
|
+
if (typeof onClose === 'function') onClose()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const handleKeyUp = (event) => {
|
|
96
|
+
if (event.key === 'Escape') onClose()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!isOpen) {
|
|
100
|
+
return null
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// TODO: replace the close button with IconButton when implemented (https://github.com/telus/universal-design-system/issues/281)
|
|
104
|
+
return (
|
|
105
|
+
<NativeModal transparent>
|
|
106
|
+
<View style={[staticStyles.positioningContainer]}>
|
|
107
|
+
<View
|
|
108
|
+
style={[staticStyles.sizingContainer, selectContainerStyles(themeTokens)]}
|
|
109
|
+
pointerEvents="box-none" // don't capture backdrop press events
|
|
110
|
+
>
|
|
111
|
+
<View
|
|
112
|
+
ref={ref}
|
|
113
|
+
style={[staticStyles.modal, selectModalStyles(themeTokens)]}
|
|
114
|
+
onKeyUp={handleKeyUp}
|
|
115
|
+
>
|
|
116
|
+
<View
|
|
117
|
+
style={[
|
|
118
|
+
staticStyles.closeButtonContainer,
|
|
119
|
+
selectCloseButtonContainerStyles(themeTokens)
|
|
120
|
+
]}
|
|
121
|
+
>
|
|
122
|
+
<ButtonBase
|
|
123
|
+
onPress={handleClose}
|
|
124
|
+
accessibilityRole="button"
|
|
125
|
+
accessibilityLabel={closeLabel}
|
|
126
|
+
>
|
|
127
|
+
{
|
|
128
|
+
// TODO: add close button interactive states after IconButton is done
|
|
129
|
+
() => <CloseIconComponent {...selectCloseIconProps(themeTokens)} />
|
|
130
|
+
}
|
|
131
|
+
</ButtonBase>
|
|
132
|
+
</View>
|
|
133
|
+
{children}
|
|
134
|
+
</View>
|
|
135
|
+
</View>
|
|
136
|
+
{/* when a modal becomes open its first focusable element is being automatically focused */}
|
|
137
|
+
{/* and we prefer the close button over backdrop */}
|
|
138
|
+
<TouchableWithoutFeedback onPress={handleClose}>
|
|
139
|
+
<View style={[staticStyles.backdrop, selectBackdropStyles(themeTokens)]} />
|
|
140
|
+
</TouchableWithoutFeedback>
|
|
141
|
+
</View>
|
|
142
|
+
</NativeModal>
|
|
143
|
+
)
|
|
144
|
+
})
|
|
145
|
+
Modal.displayName = 'Modal'
|
|
146
|
+
|
|
147
|
+
Modal.propTypes = {
|
|
148
|
+
children: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
|
|
149
|
+
copy: copyPropTypes,
|
|
150
|
+
isOpen: PropTypes.bool,
|
|
151
|
+
onClose: PropTypes.func,
|
|
152
|
+
maxWidth: PropTypes.bool,
|
|
153
|
+
tokens: getTokensPropType('Modal'),
|
|
154
|
+
variant: variantProp.propType
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export default Modal
|
|
158
|
+
|
|
159
|
+
const staticStyles = StyleSheet.create({
|
|
160
|
+
backdrop: {
|
|
161
|
+
position: 'absolute',
|
|
162
|
+
top: 0,
|
|
163
|
+
left: 0,
|
|
164
|
+
right: 0,
|
|
165
|
+
bottom: 0,
|
|
166
|
+
zIndex: -1,
|
|
167
|
+
...Platform.select({
|
|
168
|
+
web: {
|
|
169
|
+
cursor: 'pointer'
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
},
|
|
173
|
+
positioningContainer: {
|
|
174
|
+
flexBasis: '100%',
|
|
175
|
+
alignItems: 'center',
|
|
176
|
+
justifyContent: 'center'
|
|
177
|
+
},
|
|
178
|
+
sizingContainer: {
|
|
179
|
+
maxHeight: '100%', // so that the container can expand up to the full viewport height
|
|
180
|
+
width: '100%' // ensure that the modal actually expands to the set maxWidth
|
|
181
|
+
},
|
|
182
|
+
modal: {
|
|
183
|
+
maxHeight: '100%' // so that the modal can expand vertically up to the sizing container's height (exclusive of its vertical padding)
|
|
184
|
+
},
|
|
185
|
+
closeButtonContainer: {
|
|
186
|
+
position: 'absolute',
|
|
187
|
+
top: 0,
|
|
188
|
+
right: 0
|
|
189
|
+
}
|
|
190
|
+
})
|