@telus-uds/components-base 0.0.2-prerelease.4 → 0.0.2-prerelease.8
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/.ultra.cache.json +1 -0
- package/CHANGELOG.md +76 -0
- package/__fixtures__/Accessible.js +33 -0
- package/__fixtures__/Accessible.native.js +32 -0
- package/__fixtures__/testTheme.js +940 -54
- package/__tests__/ActivityIndicator/ActivityIndicator.test.jsx +1 -1
- package/__tests__/Button/ButtonBase.test.jsx +3 -32
- package/__tests__/Button/ButtonGroup.test.jsx +2 -2
- package/__tests__/Checkbox/Checkbox.test.jsx +94 -0
- package/__tests__/Checkbox/CheckboxGroup.test.jsx +247 -0
- package/__tests__/Divider/Divider.test.jsx +26 -5
- package/__tests__/Feedback/Feedback.test.jsx +42 -0
- package/__tests__/Icon/Icon.test.jsx +3 -3
- package/__tests__/InputSupports/InputSupports.test.jsx +50 -0
- package/__tests__/List/List.test.jsx +60 -0
- 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 +87 -0
- package/__tests__/Radio/RadioGroup.test.jsx +221 -0
- package/__tests__/RadioCard/RadioCard.test.jsx +87 -0
- package/__tests__/RadioCard/RadioCardGroup.test.jsx +247 -0
- package/__tests__/Search/Search.test.jsx +72 -0
- package/__tests__/Select/Select.test.jsx +93 -0
- package/__tests__/Skeleton/Skeleton.test.jsx +61 -0
- package/__tests__/Spacer/Spacer.test.jsx +63 -0
- package/__tests__/StackView/StackView.test.jsx +216 -0
- package/__tests__/StackView/StackWrap.test.jsx +47 -0
- package/__tests__/StackView/getStackedContent.test.jsx +295 -0
- package/__tests__/StepTracker/StepTracker.test.jsx +94 -0
- package/__tests__/Tabs/Tabs.test.jsx +200 -0
- package/__tests__/Tags/Tags.test.jsx +328 -0
- package/__tests__/TextInput/TextArea.test.jsx +34 -0
- package/__tests__/TextInput/TextInputBase.test.jsx +120 -0
- package/__tests__/Tooltip/Tooltip.test.jsx +65 -0
- package/__tests__/Tooltip/getTooltipPosition.test.js +79 -0
- package/__tests__/utils/input.test.js +58 -0
- package/__tests__/utils/useCopy.test.js +42 -0
- package/__tests__/utils/useResponsiveProp.test.jsx +202 -0
- package/__tests__/utils/{spacing.test.jsx → useSpacingScale.test.jsx} +1 -1
- package/__tests__/utils/useUniqueId.test.js +31 -0
- package/babel.config.js +20 -0
- package/jest.config.js +8 -2
- package/lib/A11yInfoProvider/index.js +54 -26
- package/lib/A11yText/index.js +37 -14
- package/lib/ActivityIndicator/Spinner.js +78 -0
- package/lib/ActivityIndicator/Spinner.native.js +121 -87
- 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 +56 -28
- package/lib/Box/index.js +13 -2
- package/lib/Button/Button.js +38 -10
- package/lib/Button/ButtonBase.js +120 -109
- package/lib/Button/ButtonGroup.js +98 -99
- package/lib/Button/ButtonLink.js +41 -13
- package/lib/Button/index.js +31 -4
- package/lib/Button/propTypes.js +32 -9
- package/lib/Card/Card.js +36 -41
- package/lib/Card/CardBase.js +78 -0
- package/lib/Card/PressableCardBase.js +137 -0
- package/lib/Card/index.js +40 -2
- package/lib/Checkbox/Checkbox.js +344 -0
- package/lib/Checkbox/CheckboxGroup.js +231 -0
- package/lib/Checkbox/CheckboxInput.js +74 -0
- package/lib/Checkbox/CheckboxInput.native.js +14 -0
- package/lib/Checkbox/index.js +21 -0
- package/lib/Divider/Divider.js +81 -17
- package/lib/Divider/index.js +13 -2
- package/lib/ExpandCollapse/Accordion.js +20 -7
- package/lib/ExpandCollapse/Control.js +50 -27
- package/lib/ExpandCollapse/ExpandCollapse.js +41 -24
- package/lib/ExpandCollapse/Panel.js +75 -37
- package/lib/ExpandCollapse/index.js +25 -7
- package/lib/Feedback/Feedback.js +161 -0
- package/lib/Feedback/index.js +13 -0
- package/lib/Fieldset/Fieldset.js +160 -0
- package/lib/Fieldset/FieldsetContainer.js +41 -0
- package/lib/Fieldset/FieldsetContainer.native.js +33 -0
- package/lib/Fieldset/Legend.js +33 -0
- package/lib/Fieldset/Legend.native.js +43 -0
- package/lib/Fieldset/cssReset.js +21 -0
- package/lib/Fieldset/index.js +13 -0
- package/lib/FlexGrid/Col/Col.js +67 -38
- package/lib/FlexGrid/Col/index.js +13 -2
- package/lib/FlexGrid/FlexGrid.js +70 -45
- package/lib/FlexGrid/Row/Row.js +48 -27
- 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/Icon/Icon.js +52 -47
- package/lib/Icon/IconText.js +100 -0
- package/lib/Icon/index.js +31 -3
- package/lib/InputLabel/InputLabel.js +122 -0
- package/lib/InputLabel/LabelContent.js +31 -0
- package/lib/InputLabel/LabelContent.native.js +16 -0
- package/lib/InputLabel/index.js +13 -0
- package/lib/InputSupports/InputSupports.js +104 -0
- package/lib/InputSupports/index.js +13 -0
- package/lib/InputSupports/propTypes.js +66 -0
- package/lib/InputSupports/useInputSupports.js +41 -0
- package/lib/Link/ChevronLink.js +57 -15
- package/lib/Link/InlinePressable.js +50 -0
- package/lib/Link/InlinePressable.native.js +101 -0
- package/lib/Link/Link.js +30 -13
- package/lib/Link/LinkBase.js +121 -146
- package/lib/Link/TextButton.js +47 -17
- package/lib/Link/index.js +39 -4
- package/lib/List/List.js +80 -0
- package/lib/List/ListItem.js +237 -0
- package/lib/List/index.js +13 -0
- package/lib/Modal/Modal.js +226 -0
- package/lib/Modal/dictionary.js +16 -0
- package/lib/Modal/index.js +13 -0
- package/lib/Notification/Notification.js +200 -0
- package/lib/Notification/dictionary.js +15 -0
- package/lib/Notification/index.js +13 -0
- package/lib/Pagination/PageButton.js +45 -46
- package/lib/Pagination/Pagination.js +70 -40
- package/lib/Pagination/SideButton.js +74 -58
- 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 +99 -0
- package/lib/Progress/ProgressBar.js +146 -0
- package/lib/Progress/ProgressBarBackground.js +57 -0
- package/lib/Progress/index.js +16 -0
- package/lib/Radio/Radio.js +292 -0
- package/lib/Radio/RadioButton.js +141 -0
- package/lib/Radio/RadioGroup.js +233 -0
- package/lib/Radio/RadioInput.js +76 -0
- package/lib/Radio/RadioInput.native.js +14 -0
- package/lib/Radio/index.js +21 -0
- package/lib/RadioCard/RadioCard.js +240 -0
- package/lib/RadioCard/RadioCardGroup.js +251 -0
- package/lib/RadioCard/index.js +21 -0
- package/lib/Search/Search.js +243 -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 +25 -0
- package/lib/Select/Item.js +29 -0
- package/lib/Select/Item.native.js +19 -0
- package/lib/Select/Picker.js +79 -0
- package/lib/Select/Picker.native.js +115 -0
- package/lib/Select/Select.js +300 -0
- package/lib/Select/index.js +19 -0
- package/lib/SideNav/Item.js +54 -33
- package/lib/SideNav/ItemContent.js +41 -15
- package/lib/SideNav/ItemsGroup.js +46 -27
- package/lib/SideNav/SideNav.js +92 -69
- package/lib/SideNav/index.js +15 -1
- package/lib/Skeleton/Skeleton.js +137 -0
- package/lib/Skeleton/index.js +13 -0
- 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 +117 -0
- package/lib/Spacer/index.js +13 -0
- package/lib/StackView/StackView.js +129 -0
- package/lib/StackView/StackWrap.js +55 -0
- package/lib/StackView/StackWrap.native.js +14 -0
- package/lib/StackView/StackWrapBox.js +112 -0
- package/lib/StackView/StackWrapGap.js +71 -0
- package/lib/StackView/common.js +45 -0
- package/lib/StackView/getStackedContent.js +141 -0
- package/lib/StackView/index.js +29 -0
- package/lib/StepTracker/Step.js +245 -0
- package/lib/StepTracker/StepTracker.js +197 -0
- package/lib/StepTracker/dictionary.js +17 -0
- package/lib/StepTracker/index.js +13 -0
- package/lib/Tabs/HorizontalScroll.js +199 -0
- package/lib/Tabs/ScrollViewEnd.js +66 -0
- package/lib/Tabs/ScrollViewEnd.native.js +41 -0
- package/lib/Tabs/Tabs.js +117 -0
- package/lib/Tabs/TabsItem.js +234 -0
- package/lib/Tabs/TabsScrollButton.js +121 -0
- package/lib/Tabs/dictionary.js +18 -0
- package/lib/Tabs/index.js +13 -0
- package/lib/Tabs/itemPositions.js +128 -0
- package/lib/Tags/Tags.js +250 -0
- package/lib/Tags/index.js +13 -0
- package/lib/TextInput/TextArea.js +109 -0
- package/lib/TextInput/TextInput.js +75 -0
- package/lib/TextInput/TextInputBase.js +252 -0
- package/lib/TextInput/index.js +23 -0
- package/lib/TextInput/propTypes.js +42 -0
- package/lib/ThemeProvider/ThemeProvider.js +38 -14
- package/lib/ThemeProvider/index.js +61 -6
- package/lib/ThemeProvider/useSetTheme.js +14 -5
- package/lib/ThemeProvider/useTheme.js +13 -4
- package/lib/ThemeProvider/useThemeTokens.js +86 -19
- package/lib/ThemeProvider/utils/index.js +31 -2
- package/lib/ThemeProvider/utils/styles.js +52 -16
- package/lib/ThemeProvider/utils/theme-tokens.js +94 -16
- package/lib/ToggleSwitch/ToggleSwitch.js +76 -52
- package/lib/ToggleSwitch/index.js +13 -2
- package/lib/Tooltip/Backdrop.js +56 -0
- package/lib/Tooltip/Backdrop.native.js +59 -0
- package/lib/Tooltip/Tooltip.js +357 -0
- package/lib/Tooltip/dictionary.js +15 -0
- package/lib/Tooltip/getTooltipPosition.js +172 -0
- package/lib/Tooltip/index.js +13 -0
- package/lib/TooltipButton/TooltipButton.js +83 -0
- package/lib/TooltipButton/index.js +13 -0
- package/lib/Typography/Typography.js +58 -47
- package/lib/Typography/index.js +13 -2
- package/lib/ViewportProvider/ViewportProvider.js +46 -0
- package/lib/ViewportProvider/index.js +22 -38
- package/lib/ViewportProvider/useViewport.js +15 -0
- package/lib/ViewportProvider/useViewportListener.js +57 -0
- package/lib/index.js +509 -19
- package/lib/utils/a11y/index.js +18 -0
- package/lib/utils/a11y/textSize.js +49 -0
- package/lib/utils/animation/index.js +15 -2
- package/lib/utils/animation/useVerticalExpandAnimation.js +28 -11
- package/lib/utils/children.js +87 -0
- package/lib/utils/index.js +163 -4
- package/lib/utils/info/index.js +19 -0
- package/lib/utils/info/platform/index.js +23 -0
- package/lib/utils/info/platform/platform.android.js +8 -0
- package/lib/utils/info/platform/platform.ios.js +8 -0
- package/lib/utils/info/platform/platform.js +8 -0
- package/lib/utils/info/platform/platform.native.js +11 -0
- package/lib/utils/info/versions.js +16 -0
- package/lib/utils/input.js +54 -34
- package/lib/utils/pressability.js +120 -0
- package/lib/utils/propTypes.js +269 -108
- package/lib/utils/useCopy.js +51 -0
- package/lib/utils/useHash.js +48 -0
- package/lib/utils/useHash.native.js +15 -0
- package/lib/utils/useResponsiveProp.js +59 -0
- package/lib/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +45 -12
- package/lib/utils/useUniqueId.js +21 -0
- package/package.json +11 -8
- package/release-context.json +4 -4
- package/src/ActivityIndicator/{Spinner.web.jsx → Spinner.jsx} +0 -0
- package/src/Box/Box.jsx +13 -4
- package/src/Button/Button.jsx +9 -5
- package/src/Button/ButtonBase.jsx +74 -86
- package/src/Button/ButtonGroup.jsx +24 -41
- package/src/Button/ButtonLink.jsx +14 -4
- package/src/Button/propTypes.js +12 -2
- package/src/Card/Card.jsx +4 -30
- package/src/Card/CardBase.jsx +57 -0
- package/src/Card/PressableCardBase.jsx +112 -0
- package/src/Card/index.js +3 -0
- package/src/Checkbox/Checkbox.jsx +274 -0
- package/src/Checkbox/CheckboxGroup.jsx +196 -0
- package/src/Checkbox/CheckboxInput.jsx +55 -0
- package/src/Checkbox/CheckboxInput.native.jsx +6 -0
- package/src/Checkbox/index.js +5 -0
- package/src/Divider/Divider.jsx +38 -3
- package/src/ExpandCollapse/Control.jsx +1 -1
- package/src/Feedback/Feedback.jsx +108 -0
- package/src/Feedback/index.js +3 -0
- package/src/Fieldset/Fieldset.jsx +129 -0
- package/src/Fieldset/FieldsetContainer.jsx +22 -0
- package/src/Fieldset/FieldsetContainer.native.jsx +16 -0
- package/src/Fieldset/Legend.jsx +16 -0
- package/src/Fieldset/Legend.native.jsx +22 -0
- package/src/Fieldset/cssReset.js +14 -0
- package/src/Fieldset/index.js +3 -0
- package/src/Icon/Icon.jsx +23 -27
- package/src/Icon/IconText.jsx +63 -0
- package/src/Icon/index.js +3 -2
- package/src/InputLabel/InputLabel.jsx +106 -0
- package/src/InputLabel/LabelContent.jsx +13 -0
- package/src/InputLabel/LabelContent.native.jsx +6 -0
- package/src/InputLabel/index.js +3 -0
- package/src/InputSupports/InputSupports.jsx +75 -0
- package/src/InputSupports/index.js +3 -0
- package/src/InputSupports/propTypes.js +44 -0
- package/src/InputSupports/useInputSupports.js +30 -0
- package/src/Link/ChevronLink.jsx +28 -7
- package/src/Link/InlinePressable.jsx +37 -0
- package/src/Link/InlinePressable.native.jsx +73 -0
- package/src/Link/Link.jsx +17 -13
- package/src/Link/LinkBase.jsx +71 -146
- package/src/Link/TextButton.jsx +25 -11
- package/src/Link/index.js +2 -1
- package/src/List/List.jsx +47 -0
- package/src/List/ListItem.jsx +187 -0
- package/src/List/index.js +3 -0
- package/src/Modal/Modal.jsx +185 -0
- package/src/Modal/dictionary.js +9 -0
- package/src/Modal/index.js +3 -0
- package/src/Notification/Notification.jsx +149 -0
- package/src/Notification/dictionary.js +8 -0
- package/src/Notification/index.js +3 -0
- package/src/Pagination/PageButton.jsx +3 -17
- package/src/Pagination/SideButton.jsx +27 -38
- package/src/Progress/Progress.jsx +77 -0
- package/src/Progress/ProgressBar.jsx +110 -0
- package/src/Progress/ProgressBarBackground.jsx +34 -0
- package/src/Progress/index.js +6 -0
- package/src/Radio/Radio.jsx +233 -0
- package/src/Radio/RadioButton.jsx +131 -0
- package/src/Radio/RadioGroup.jsx +198 -0
- package/src/Radio/RadioInput.jsx +57 -0
- package/src/Radio/RadioInput.native.jsx +6 -0
- package/src/Radio/index.js +5 -0
- package/src/RadioCard/RadioCard.jsx +191 -0
- package/src/RadioCard/RadioCardGroup.jsx +211 -0
- package/src/RadioCard/index.js +5 -0
- package/src/Search/Search.jsx +204 -0
- package/src/Search/dictionary.js +12 -0
- package/src/Search/index.js +3 -0
- package/src/Select/Group.jsx +15 -0
- package/src/Select/Group.native.jsx +14 -0
- package/src/Select/Item.jsx +11 -0
- package/src/Select/Item.native.jsx +10 -0
- package/src/Select/Picker.jsx +67 -0
- package/src/Select/Picker.native.jsx +95 -0
- package/src/Select/Select.jsx +255 -0
- package/src/Select/index.js +8 -0
- package/src/SideNav/Item.jsx +2 -2
- package/src/Skeleton/Skeleton.jsx +98 -0
- package/src/Skeleton/index.js +3 -0
- 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 +91 -0
- package/src/Spacer/index.js +3 -0
- package/src/StackView/StackView.jsx +111 -0
- package/src/StackView/StackWrap.jsx +41 -0
- package/src/StackView/StackWrap.native.jsx +4 -0
- package/src/StackView/StackWrapBox.jsx +94 -0
- package/src/StackView/StackWrapGap.jsx +49 -0
- package/src/StackView/common.jsx +28 -0
- package/src/StackView/getStackedContent.jsx +112 -0
- package/src/StackView/index.js +6 -0
- package/src/StepTracker/Step.jsx +202 -0
- package/src/StepTracker/StepTracker.jsx +163 -0
- package/src/StepTracker/dictionary.js +10 -0
- package/src/StepTracker/index.js +3 -0
- package/src/Tabs/HorizontalScroll.jsx +165 -0
- package/src/Tabs/ScrollViewEnd.jsx +53 -0
- package/src/Tabs/ScrollViewEnd.native.jsx +24 -0
- package/src/Tabs/Tabs.jsx +89 -0
- package/src/Tabs/TabsItem.jsx +204 -0
- package/src/Tabs/TabsScrollButton.jsx +100 -0
- package/src/Tabs/dictionary.js +11 -0
- package/src/Tabs/index.js +3 -0
- package/src/Tabs/itemPositions.js +101 -0
- package/src/Tags/Tags.jsx +207 -0
- package/src/Tags/index.js +3 -0
- package/src/TextInput/TextArea.jsx +78 -0
- package/src/TextInput/TextInput.jsx +52 -0
- package/src/TextInput/TextInputBase.jsx +210 -0
- package/src/TextInput/index.js +4 -0
- package/src/TextInput/propTypes.js +29 -0
- package/src/ThemeProvider/useThemeTokens.js +56 -5
- package/src/ThemeProvider/utils/styles.js +18 -5
- package/src/ThemeProvider/utils/theme-tokens.js +46 -5
- package/src/ToggleSwitch/ToggleSwitch.jsx +3 -4
- package/src/Tooltip/Backdrop.jsx +60 -0
- package/src/Tooltip/Backdrop.native.jsx +33 -0
- package/src/Tooltip/Tooltip.jsx +294 -0
- package/src/Tooltip/dictionary.js +8 -0
- package/src/Tooltip/getTooltipPosition.js +161 -0
- package/src/Tooltip/index.js +3 -0
- package/src/TooltipButton/TooltipButton.jsx +49 -0
- package/src/TooltipButton/index.js +3 -0
- package/src/Typography/Typography.jsx +10 -24
- package/src/ViewportProvider/ViewportProvider.jsx +21 -0
- package/src/ViewportProvider/index.jsx +2 -41
- package/src/ViewportProvider/useViewport.js +5 -0
- package/src/ViewportProvider/useViewportListener.js +43 -0
- package/src/index.js +34 -2
- package/src/utils/a11y/index.js +1 -0
- package/src/utils/a11y/textSize.js +30 -0
- package/src/utils/children.jsx +66 -0
- package/src/utils/index.js +11 -1
- package/src/utils/info/index.js +8 -0
- package/src/utils/info/platform/index.js +11 -0
- package/src/utils/info/platform/platform.android.js +1 -0
- package/src/utils/info/platform/platform.ios.js +1 -0
- package/src/utils/info/platform/platform.js +1 -0
- package/src/utils/info/platform/platform.native.js +4 -0
- package/src/utils/info/versions.js +6 -0
- package/src/utils/input.js +22 -13
- package/src/utils/pressability.js +96 -0
- package/src/utils/propTypes.js +195 -47
- package/src/utils/useCopy.js +39 -0
- package/src/utils/useHash.js +34 -0
- package/src/utils/useHash.native.js +6 -0
- package/src/utils/useResponsiveProp.js +50 -0
- package/src/utils/{spacing/useSpacingScale.js → useSpacingScale.js} +25 -10
- package/src/utils/useUniqueId.js +14 -0
- package/stories/A11yText/A11yText.stories.jsx +15 -13
- package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
- package/stories/Box/Box.stories.jsx +29 -2
- package/stories/Button/Button.stories.jsx +21 -20
- package/stories/Button/ButtonGroup.stories.jsx +2 -1
- package/stories/Button/ButtonLink.stories.jsx +6 -4
- package/stories/Card/Card.stories.jsx +13 -1
- package/stories/Checkbox/Checkbox.stories.jsx +94 -0
- package/stories/Divider/Divider.stories.jsx +26 -2
- package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
- package/stories/Feedback/Feedback.stories.jsx +96 -0
- package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
- package/stories/Icon/Icon.stories.jsx +15 -6
- package/stories/InputLabel/InputLabel.stories.jsx +42 -0
- package/stories/Link/ChevronLink.stories.jsx +20 -4
- package/stories/Link/Link.stories.jsx +39 -3
- package/stories/Link/TextButton.stories.jsx +24 -2
- package/stories/List/List.stories.jsx +117 -0
- package/stories/Modal/Modal.stories.jsx +29 -0
- package/stories/Notification/Notification.stories.jsx +82 -0
- package/stories/Pagination/Pagination.stories.jsx +28 -14
- package/stories/Progress/Progress.stories.jsx +93 -0
- package/stories/Radio/Radio.stories.jsx +100 -0
- package/stories/RadioCard/RadioCard.stories.jsx +98 -0
- package/stories/Search/Search.stories.jsx +16 -0
- package/stories/Select/Select.stories.jsx +55 -0
- package/stories/SideNav/SideNav.stories.jsx +17 -2
- package/stories/Skeleton/Skeleton.stories.jsx +36 -0
- package/stories/Spacer/Spacer.stories.jsx +38 -0
- package/stories/StackView/StackView.stories.jsx +75 -0
- package/stories/StackView/StackWrap.stories.jsx +64 -0
- package/stories/StepTracker/StepTracker.stories.jsx +71 -0
- package/stories/Tabs/Tabs.stories.jsx +97 -0
- package/stories/Tags/Tags.stories.jsx +69 -0
- package/stories/TextInput/TextArea.stories.jsx +100 -0
- package/stories/TextInput/TextInput.stories.jsx +103 -0
- package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
- package/stories/Tooltip/Tooltip.stories.jsx +81 -0
- package/stories/TooltipButton/TooltipButton.stories.jsx +11 -0
- package/stories/Typography/Typography.stories.jsx +12 -3
- package/stories/{platform-supports.web.jsx → platform-supports.jsx} +1 -1
- package/stories/supports.jsx +110 -14
- package/__fixtures__/accessible.icon.svg +0 -6
- package/babel.config.json +0 -8
- package/lib/ActivityIndicator/Spinner.web.js +0 -55
- package/lib/Pagination/useCopy.js +0 -10
- package/lib/config/svgr-icons-web.js +0 -9
- package/lib/config/svgr-icons.js +0 -52
- package/lib/utils/spacing/index.js +0 -2
- package/lib/utils/spacing/utils.js +0 -32
- package/src/Pagination/useCopy.js +0 -7
- package/src/config/svgr-icons-web.js +0 -11
- package/src/config/svgr-icons.js +0 -46
- package/src/utils/spacing/index.js +0 -3
- package/src/utils/spacing/utils.js +0 -28
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fireEvent, render } from '@testing-library/react-native'
|
|
3
|
+
|
|
4
|
+
import { Text } from 'react-native'
|
|
5
|
+
import { Tooltip } from '../../src'
|
|
6
|
+
|
|
7
|
+
import Theme from '../../__fixtures__/Theme'
|
|
8
|
+
import Viewport from '../../__fixtures__/Viewport'
|
|
9
|
+
|
|
10
|
+
const wrapper = ({ children }) => (
|
|
11
|
+
<Theme>
|
|
12
|
+
<Viewport>{children}</Viewport>
|
|
13
|
+
</Theme>
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
const content = 'tooltip content'
|
|
17
|
+
|
|
18
|
+
describe('Tooltip', () => {
|
|
19
|
+
it('renders content after control is pressed', () => {
|
|
20
|
+
const { queryByText, getByA11yRole } = render(<Tooltip content={content} />, { wrapper })
|
|
21
|
+
|
|
22
|
+
expect(queryByText(content)).toBeFalsy()
|
|
23
|
+
|
|
24
|
+
fireEvent.press(getByA11yRole('button'))
|
|
25
|
+
|
|
26
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it("renders custom control, and renders content after it's pressed", () => {
|
|
30
|
+
const { queryByTestId, getByA11yRole, queryByText } = render(
|
|
31
|
+
<Tooltip content={content}>
|
|
32
|
+
<Text testID="control" />
|
|
33
|
+
</Tooltip>,
|
|
34
|
+
{ wrapper }
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
expect(queryByTestId('control')).not.toBeFalsy()
|
|
38
|
+
|
|
39
|
+
expect(queryByText(content)).toBeFalsy()
|
|
40
|
+
|
|
41
|
+
fireEvent.press(getByA11yRole('button'))
|
|
42
|
+
|
|
43
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it("renders custom control render function, and renders content after it's pressed", () => {
|
|
47
|
+
const { queryByTestId, getByA11yRole, queryByText } = render(
|
|
48
|
+
<Tooltip content={content} variant={{ inverse: true }}>
|
|
49
|
+
{(pressableState, variant) => (
|
|
50
|
+
<Text testID="control">{variant.inverse ? 'Inverse' : 'Default'}</Text>
|
|
51
|
+
)}
|
|
52
|
+
</Tooltip>,
|
|
53
|
+
{ wrapper }
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
expect(queryByTestId('control')).not.toBeFalsy()
|
|
57
|
+
expect(queryByText('Inverse')).not.toBeFalsy()
|
|
58
|
+
|
|
59
|
+
expect(queryByText(content)).toBeFalsy()
|
|
60
|
+
|
|
61
|
+
fireEvent.press(getByA11yRole('button'))
|
|
62
|
+
|
|
63
|
+
expect(queryByText(content)).not.toBeFalsy()
|
|
64
|
+
})
|
|
65
|
+
})
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import getTooltipPosition from '../../lib/Tooltip/getTooltipPosition'
|
|
2
|
+
|
|
3
|
+
const windowDimensions = {
|
|
4
|
+
width: 320,
|
|
5
|
+
height: 400
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const tooltipDimensions = {
|
|
9
|
+
width: 200,
|
|
10
|
+
height: 40
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('getTooltipPosition()', () => {
|
|
14
|
+
it('automatically places the tooltip within viewport', () => {
|
|
15
|
+
const controlLayout = {
|
|
16
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
17
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
18
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
19
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
23
|
+
const result = getTooltipPosition('auto', {
|
|
24
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
25
|
+
tooltipDimensions,
|
|
26
|
+
windowDimensions
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
expect(result.position).toBe(position)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('places the tooltip in the position from prop if that fits within viewport', () => {
|
|
34
|
+
const controlLayout = {
|
|
35
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
36
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
37
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
38
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
42
|
+
const positionProp = position // this would normally come from the component's prop
|
|
43
|
+
|
|
44
|
+
const result = getTooltipPosition(positionProp, {
|
|
45
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
46
|
+
tooltipDimensions,
|
|
47
|
+
windowDimensions
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
expect(result.position).toBe(position)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
it("places the tooltip in a different position if prop wouldn't fit in the viewport", () => {
|
|
55
|
+
const controlLayout = {
|
|
56
|
+
right: { x: 20, y: 20 }, // control in top-left corner
|
|
57
|
+
left: { x: windowDimensions.width - 20, y: 20 }, // control in top-right corner
|
|
58
|
+
above: { x: windowDimensions.width / 2, y: windowDimensions.height - 20 }, // control in bottom center
|
|
59
|
+
below: { x: windowDimensions.width / 2, y: 20 } // control in top center
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const positionProp = {
|
|
63
|
+
right: 'left',
|
|
64
|
+
left: 'right',
|
|
65
|
+
above: 'below',
|
|
66
|
+
below: 'above'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
Object.keys(controlLayout).forEach((position) => {
|
|
70
|
+
const result = getTooltipPosition(positionProp[position], {
|
|
71
|
+
controlLayout: { width: 20, height: 20, ...controlLayout[position] },
|
|
72
|
+
tooltipDimensions,
|
|
73
|
+
windowDimensions
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
expect(result.position).toBe(position)
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
})
|
|
@@ -90,6 +90,17 @@ describe('useInputValue (uncontrolled)', () => {
|
|
|
90
90
|
expect(result.current.currentValue).toBe('some value')
|
|
91
91
|
})
|
|
92
92
|
|
|
93
|
+
it('Changes currentValue based on old value when `setValue` is passed a function', () => {
|
|
94
|
+
const { result } = renderHook(() => useInputValue({ initialValue: 1 }))
|
|
95
|
+
expect(result.current.currentValue).toBe(1)
|
|
96
|
+
|
|
97
|
+
act(() => result.current.setValue((oldValue) => oldValue + 1))
|
|
98
|
+
expect(result.current.currentValue).toBe(2)
|
|
99
|
+
|
|
100
|
+
act(() => result.current.setValue((oldValue) => oldValue + 2))
|
|
101
|
+
expect(result.current.currentValue).toBe(4)
|
|
102
|
+
})
|
|
103
|
+
|
|
93
104
|
it('Sets currentValue to initialValue if provided, which may be changed', () => {
|
|
94
105
|
const { result } = renderHook(() => useInputValue({ initialValue: 'first value' }))
|
|
95
106
|
expect(result.current.currentValue).toBe('first value')
|
|
@@ -210,6 +221,29 @@ describe('useMultipleInputValues (uncontrolled)', () => {
|
|
|
210
221
|
expect(result.current.currentValues).toEqual(['second value', 'third value'])
|
|
211
222
|
})
|
|
212
223
|
|
|
224
|
+
it('Replaces values on calling setValues', () => {
|
|
225
|
+
const { result } = renderHook(() =>
|
|
226
|
+
useMultipleInputValues({
|
|
227
|
+
initialValues: ['first value', 'second value', 'third value']
|
|
228
|
+
})
|
|
229
|
+
)
|
|
230
|
+
act(() => result.current.setValues(['new value', 'another value']))
|
|
231
|
+
expect(result.current.currentValues).toEqual(['new value', 'another value'])
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('Replaces values based on old values on passing function to setValues', () => {
|
|
235
|
+
const { result } = renderHook(() =>
|
|
236
|
+
useMultipleInputValues({
|
|
237
|
+
initialValues: [1, 2, 3, 4]
|
|
238
|
+
})
|
|
239
|
+
)
|
|
240
|
+
act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 1)))
|
|
241
|
+
expect(result.current.currentValues).toEqual([2, 3, 4, 5])
|
|
242
|
+
|
|
243
|
+
act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 2)))
|
|
244
|
+
expect(result.current.currentValues).toEqual([4, 5, 6, 7])
|
|
245
|
+
})
|
|
246
|
+
|
|
213
247
|
it('Empties values on calling unsetValues', () => {
|
|
214
248
|
const { result } = renderHook(() =>
|
|
215
249
|
useMultipleInputValues({
|
|
@@ -237,6 +271,18 @@ describe('useInputValue (controlled)', () => {
|
|
|
237
271
|
expect(onChange.mock.calls[0][0]).toEqual('second value')
|
|
238
272
|
})
|
|
239
273
|
|
|
274
|
+
it('Calls `onChange` with result from old value when `setValue` is passed a function', () => {
|
|
275
|
+
const onChange = jest.fn((arg) => arg)
|
|
276
|
+
const { result } = renderHook(() => useInputValue({ value: 1, onChange }))
|
|
277
|
+
expect(result.current.currentValue).toBe(1)
|
|
278
|
+
expect(onChange).toHaveBeenCalledTimes(0)
|
|
279
|
+
|
|
280
|
+
act(() => result.current.setValue((oldValue) => oldValue + 1))
|
|
281
|
+
expect(result.current.currentValue).toBe(1)
|
|
282
|
+
expect(onChange).toHaveBeenCalledTimes(1)
|
|
283
|
+
expect(onChange.mock.calls[0][0]).toEqual(2)
|
|
284
|
+
})
|
|
285
|
+
|
|
240
286
|
it('Returns updated `currentValue` when non-undefined `value` prop changes', () => {
|
|
241
287
|
const onChange = () => {}
|
|
242
288
|
const { result, rerender } = renderHook(({ value }) => useInputValue({ value, onChange }), {
|
|
@@ -296,6 +342,18 @@ describe('useMultipleInputValues (controlled)', () => {
|
|
|
296
342
|
expect(onChange.mock.calls[0][0]).toEqual(['second value', 'third value'])
|
|
297
343
|
})
|
|
298
344
|
|
|
345
|
+
it('Calls `onChange` with results from old values when `setValues` is passed a function', () => {
|
|
346
|
+
const onChange = jest.fn((arg) => arg)
|
|
347
|
+
const { result } = renderHook(() => useMultipleInputValues({ values: [1, 2, 3, 4], onChange }))
|
|
348
|
+
expect(result.current.currentValues).toEqual([1, 2, 3, 4])
|
|
349
|
+
expect(onChange).toHaveBeenCalledTimes(0)
|
|
350
|
+
|
|
351
|
+
act(() => result.current.setValues((oldValues) => oldValues.map((value) => value + 1)))
|
|
352
|
+
expect(result.current.currentValues).toEqual([1, 2, 3, 4])
|
|
353
|
+
expect(onChange).toHaveBeenCalledTimes(1)
|
|
354
|
+
expect(onChange.mock.calls[0][0]).toEqual([2, 3, 4, 5])
|
|
355
|
+
})
|
|
356
|
+
|
|
299
357
|
it('Calls onChange with an empty array on calling unsetValues', () => {
|
|
300
358
|
const onChange = jest.fn((arg) => arg)
|
|
301
359
|
const { result, rerender } = renderHook(
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
2
|
+
import useCopy from '../../lib/utils/useCopy'
|
|
3
|
+
|
|
4
|
+
const dictionary = {
|
|
5
|
+
en: {
|
|
6
|
+
'translation key': 'english version'
|
|
7
|
+
},
|
|
8
|
+
fr: {
|
|
9
|
+
'translation key': 'french version'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
describe('useCopy hook', () => {
|
|
14
|
+
it('returns a correct english translation', () => {
|
|
15
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
|
|
16
|
+
|
|
17
|
+
const getCopy = result.current
|
|
18
|
+
expect(getCopy('translation key')).toBe('english version')
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
it('returns a correct french translation', () => {
|
|
22
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'fr' }))
|
|
23
|
+
|
|
24
|
+
const getCopy = result.current
|
|
25
|
+
expect(getCopy('translation key')).toBe('french version')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('returns undefined when no translation is found', () => {
|
|
29
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: 'en' }))
|
|
30
|
+
|
|
31
|
+
const getCopy = result.current
|
|
32
|
+
expect(getCopy('non-existing key')).toBe(undefined)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('allows for overriding the entire dictionary with a copy object (ignoring the dictionary argument)', () => {
|
|
36
|
+
const { result } = renderHook(() => useCopy({ dictionary, copy: dictionary.en }))
|
|
37
|
+
|
|
38
|
+
const getCopy = result.current
|
|
39
|
+
expect(getCopy('non-existing key')).toBe(undefined)
|
|
40
|
+
expect(getCopy('translation key')).toBe('english version')
|
|
41
|
+
})
|
|
42
|
+
})
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
3
|
+
import useResponsiveProp from '../../src/utils/useResponsiveProp'
|
|
4
|
+
import Viewport from '../../__fixtures__/Viewport'
|
|
5
|
+
|
|
6
|
+
const wrapper = ({ children, viewport }) => <Viewport viewport={viewport}>{children}</Viewport>
|
|
7
|
+
|
|
8
|
+
describe('useResponsiveProp', () => {
|
|
9
|
+
it('returns viewport indexes that explicitly match current value', () => {
|
|
10
|
+
const responsiveProp = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }
|
|
11
|
+
const { rerender, result } = renderHook((args) => useResponsiveProp(args.responsiveProp), {
|
|
12
|
+
wrapper,
|
|
13
|
+
initialProps: { viewport: 'xs', responsiveProp }
|
|
14
|
+
})
|
|
15
|
+
expect(result.current).toBe(1)
|
|
16
|
+
rerender({ viewport: 'sm', responsiveProp })
|
|
17
|
+
expect(result.current).toBe(2)
|
|
18
|
+
rerender({ viewport: 'md', responsiveProp })
|
|
19
|
+
expect(result.current).toBe(3)
|
|
20
|
+
rerender({ viewport: 'lg', responsiveProp })
|
|
21
|
+
expect(result.current).toBe(4)
|
|
22
|
+
rerender({ viewport: 'xl', responsiveProp })
|
|
23
|
+
expect(result.current).toBe(5)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('returns viewport indexes that implicitly match current value', () => {
|
|
27
|
+
const responsiveProp = { sm: 2, lg: 4 }
|
|
28
|
+
const { rerender, result } = renderHook((args) => useResponsiveProp(args.responsiveProp), {
|
|
29
|
+
wrapper,
|
|
30
|
+
initialProps: { viewport: 'xs', responsiveProp }
|
|
31
|
+
})
|
|
32
|
+
expect(result.current).toBe(undefined)
|
|
33
|
+
rerender({ viewport: 'sm', responsiveProp })
|
|
34
|
+
expect(result.current).toBe(2)
|
|
35
|
+
rerender({ viewport: 'md', responsiveProp })
|
|
36
|
+
expect(result.current).toBe(2)
|
|
37
|
+
rerender({ viewport: 'lg', responsiveProp })
|
|
38
|
+
expect(result.current).toBe(4)
|
|
39
|
+
rerender({ viewport: 'xl', responsiveProp })
|
|
40
|
+
expect(result.current).toBe(4)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('returns provided defaultValue where there is no match', () => {
|
|
44
|
+
const responsiveProp = { md: 2, lg: 4 }
|
|
45
|
+
const defaultValue = 'some default value'
|
|
46
|
+
const { rerender, result } = renderHook(
|
|
47
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
48
|
+
{
|
|
49
|
+
wrapper,
|
|
50
|
+
initialProps: { viewport: 'xs', responsiveProp, defaultValue }
|
|
51
|
+
}
|
|
52
|
+
)
|
|
53
|
+
expect(result.current).toBe(defaultValue)
|
|
54
|
+
rerender({ viewport: 'sm', responsiveProp, defaultValue })
|
|
55
|
+
expect(result.current).toBe(defaultValue)
|
|
56
|
+
rerender({ viewport: 'md', responsiveProp, defaultValue })
|
|
57
|
+
expect(result.current).toBe(2)
|
|
58
|
+
rerender({ viewport: 'lg', responsiveProp, defaultValue })
|
|
59
|
+
expect(result.current).toBe(4)
|
|
60
|
+
rerender({ viewport: 'xl', responsiveProp, defaultValue })
|
|
61
|
+
expect(result.current).toBe(4)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('applies falsy values appropriately (replacing `undefined` with default value)', () => {
|
|
65
|
+
const responsiveProp = { sm: '', md: null, lg: false, xl: undefined }
|
|
66
|
+
const defaultValue = 0
|
|
67
|
+
const { rerender, result } = renderHook(
|
|
68
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
69
|
+
{
|
|
70
|
+
wrapper,
|
|
71
|
+
initialProps: { viewport: 'xs', responsiveProp, defaultValue }
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
expect(result.current).toBe(0)
|
|
75
|
+
rerender({ viewport: 'sm', responsiveProp, defaultValue })
|
|
76
|
+
expect(result.current).toBe('')
|
|
77
|
+
rerender({ viewport: 'md', responsiveProp, defaultValue })
|
|
78
|
+
expect(result.current).toBe(null)
|
|
79
|
+
rerender({ viewport: 'lg', responsiveProp, defaultValue })
|
|
80
|
+
expect(result.current).toBe(false)
|
|
81
|
+
rerender({ viewport: 'xl', responsiveProp, defaultValue })
|
|
82
|
+
expect(result.current).toBe(false)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('returns a non-object prop unchanged', () => {
|
|
86
|
+
const exactFn = () => {}
|
|
87
|
+
const defaultValue = 'some value'
|
|
88
|
+
const { rerender, result } = renderHook(
|
|
89
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
90
|
+
{
|
|
91
|
+
wrapper,
|
|
92
|
+
initialProps: { viewport: 'xs', responsiveProp: exactFn, defaultValue }
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
expect(result.current).toBe(exactFn)
|
|
96
|
+
rerender({ viewport: 'sm', responsiveProp: exactFn, defaultValue })
|
|
97
|
+
expect(result.current).toBe(exactFn)
|
|
98
|
+
rerender({ viewport: 'md', responsiveProp: exactFn, defaultValue })
|
|
99
|
+
expect(result.current).toBe(exactFn)
|
|
100
|
+
rerender({ viewport: 'lg', responsiveProp: exactFn, defaultValue })
|
|
101
|
+
expect(result.current).toBe(exactFn)
|
|
102
|
+
rerender({ viewport: 'xl', responsiveProp: exactFn, defaultValue })
|
|
103
|
+
expect(result.current).toBe(exactFn)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('returns a falsy value including explicit null unchanged, default value if undefined', () => {
|
|
107
|
+
const defaultValue = 'some value'
|
|
108
|
+
const { rerender, result } = renderHook(
|
|
109
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
110
|
+
{
|
|
111
|
+
wrapper,
|
|
112
|
+
initialProps: { viewport: 'xs', responsiveProp: null, defaultValue }
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
expect(result.current).toBe(null)
|
|
116
|
+
rerender({ viewport: 'sm', responsiveProp: false, defaultValue })
|
|
117
|
+
expect(result.current).toBe(false)
|
|
118
|
+
rerender({ viewport: 'md', responsiveProp: 0, defaultValue })
|
|
119
|
+
expect(result.current).toBe(0)
|
|
120
|
+
rerender({ viewport: 'lg', responsiveProp: '', defaultValue })
|
|
121
|
+
expect(result.current).toBe('')
|
|
122
|
+
rerender({ viewport: 'xl', responsiveProp: undefined, defaultValue })
|
|
123
|
+
expect(result.current).toBe(defaultValue)
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('returns a non-responsive object unchanged, rather than the default value', () => {
|
|
127
|
+
const nonresponsiveProp = { a: 1, b: 2 }
|
|
128
|
+
const defaultValue = 'some value'
|
|
129
|
+
const { rerender, result } = renderHook(
|
|
130
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
131
|
+
{
|
|
132
|
+
wrapper,
|
|
133
|
+
initialProps: { viewport: 'xs', responsiveProp: nonresponsiveProp, defaultValue }
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
expect(result.current).toBe(nonresponsiveProp)
|
|
137
|
+
rerender({ viewport: 'sm', responsiveProp: nonresponsiveProp, defaultValue })
|
|
138
|
+
expect(result.current).toBe(nonresponsiveProp)
|
|
139
|
+
rerender({ viewport: 'md', responsiveProp: nonresponsiveProp, defaultValue })
|
|
140
|
+
expect(result.current).toBe(nonresponsiveProp)
|
|
141
|
+
rerender({ viewport: 'lg', responsiveProp: nonresponsiveProp, defaultValue })
|
|
142
|
+
expect(result.current).toBe(nonresponsiveProp)
|
|
143
|
+
rerender({ viewport: 'xl', responsiveProp: nonresponsiveProp, defaultValue })
|
|
144
|
+
expect(result.current).toBe(nonresponsiveProp)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('returns the smallest viewport property if current viewport value is missing', () => {
|
|
148
|
+
const responsiveProp = { xl: 5, lg: 4, md: 3 }
|
|
149
|
+
const defaultValue = 'some value'
|
|
150
|
+
const { result } = renderHook(
|
|
151
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
152
|
+
{
|
|
153
|
+
initialProps: { responsiveProp, defaultValue }
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
expect(result.current).toBe(3)
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
it('treats a responsive prop with extra non-responsive properties as responsive', () => {
|
|
160
|
+
const responsiveProp = { md: 3, lg: 4, options: { a: 1, b: 2 } }
|
|
161
|
+
const defaultValue = 'some value'
|
|
162
|
+
const { rerender, result } = renderHook(
|
|
163
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
164
|
+
{
|
|
165
|
+
wrapper,
|
|
166
|
+
initialProps: { viewport: 'xs', responsiveProp, defaultValue }
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
expect(result.current).toBe(defaultValue)
|
|
170
|
+
rerender({ viewport: 'sm', responsiveProp, defaultValue })
|
|
171
|
+
expect(result.current).toBe(defaultValue)
|
|
172
|
+
rerender({ viewport: 'md', responsiveProp, defaultValue })
|
|
173
|
+
expect(result.current).toBe(3)
|
|
174
|
+
rerender({ viewport: 'lg', responsiveProp, defaultValue })
|
|
175
|
+
expect(result.current).toBe(4)
|
|
176
|
+
rerender({ viewport: 'xl', responsiveProp, defaultValue })
|
|
177
|
+
expect(result.current).toBe(4)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it('treats an object with only explicitly-undefined viewport properties as responsive', () => {
|
|
181
|
+
// For example, if some logic generates the values for each viewport of a responsive prop,
|
|
182
|
+
// and in a certain case, they happen to all come out as `undefined`.
|
|
183
|
+
const responsiveProp = { sm: undefined, lg: undefined, options: { a: 1, b: 2 } }
|
|
184
|
+
const defaultValue = 'some value'
|
|
185
|
+
const { rerender, result } = renderHook(
|
|
186
|
+
(args) => useResponsiveProp(args.responsiveProp, args.defaultValue),
|
|
187
|
+
{
|
|
188
|
+
wrapper,
|
|
189
|
+
initialProps: { viewport: 'xs', responsiveProp, defaultValue }
|
|
190
|
+
}
|
|
191
|
+
)
|
|
192
|
+
expect(result.current).toBe(defaultValue)
|
|
193
|
+
rerender({ viewport: 'sm', responsiveProp, defaultValue })
|
|
194
|
+
expect(result.current).toBe(defaultValue)
|
|
195
|
+
rerender({ viewport: 'md', responsiveProp, defaultValue })
|
|
196
|
+
expect(result.current).toBe(defaultValue)
|
|
197
|
+
rerender({ viewport: 'lg', responsiveProp, defaultValue })
|
|
198
|
+
expect(result.current).toBe(defaultValue)
|
|
199
|
+
rerender({ viewport: 'xl', responsiveProp, defaultValue })
|
|
200
|
+
expect(result.current).toBe(defaultValue)
|
|
201
|
+
})
|
|
202
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { renderHook } from '@testing-library/react-hooks'
|
|
3
|
-
import { useSpacingScale } from '../../src/utils
|
|
3
|
+
import { useSpacingScale } from '../../src/utils'
|
|
4
4
|
import Theme from '../../__fixtures__/Theme'
|
|
5
5
|
import Viewport from '../../__fixtures__/Viewport'
|
|
6
6
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
2
|
+
import useUniqueId from '../../lib/utils/useUniqueId'
|
|
3
|
+
|
|
4
|
+
describe('useUniqueId hook', () => {
|
|
5
|
+
it('returns the same id for each re-render, but a different id for a new instance', () => {
|
|
6
|
+
const { result, rerender } = renderHook(() => useUniqueId('prefix'))
|
|
7
|
+
|
|
8
|
+
expect(result.current).toBe('prefix-1')
|
|
9
|
+
|
|
10
|
+
rerender()
|
|
11
|
+
|
|
12
|
+
expect(result.current).toBe('prefix-1')
|
|
13
|
+
|
|
14
|
+
// has to be done within the same test case, as we can't ensure order in which tests are being run in parallel
|
|
15
|
+
const { result: result2, rerender: rerender2 } = renderHook(() => useUniqueId('prefix'))
|
|
16
|
+
|
|
17
|
+
expect(result.current).toBe('prefix-1')
|
|
18
|
+
expect(result2.current).toBe('prefix-2')
|
|
19
|
+
|
|
20
|
+
// ensure that instances' rerendering doesn't affect one another
|
|
21
|
+
rerender2()
|
|
22
|
+
|
|
23
|
+
expect(result.current).toBe('prefix-1')
|
|
24
|
+
expect(result2.current).toBe('prefix-2')
|
|
25
|
+
|
|
26
|
+
rerender()
|
|
27
|
+
|
|
28
|
+
expect(result.current).toBe('prefix-1')
|
|
29
|
+
expect(result2.current).toBe('prefix-2')
|
|
30
|
+
})
|
|
31
|
+
})
|
package/babel.config.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
env: {
|
|
3
|
+
/*
|
|
4
|
+
* we actually want this setup to be used whenever we're not in `test` but
|
|
5
|
+
* babel merges plugins array rather than replacing so we can't set it as a
|
|
6
|
+
* default. However the default BABEL_ENV value is development (jest sets it
|
|
7
|
+
* to test)
|
|
8
|
+
*/
|
|
9
|
+
development: {
|
|
10
|
+
presets: ['@babel/preset-env', ['@babel/preset-react', { runtime: 'automatic' }]],
|
|
11
|
+
plugins: [['react-native-web', { commonjs: true }]]
|
|
12
|
+
},
|
|
13
|
+
/*
|
|
14
|
+
* jest is testing for just ios at the moment, use a preset which best matches that env
|
|
15
|
+
*/
|
|
16
|
+
test: {
|
|
17
|
+
presets: ['module:metro-react-native-babel-preset']
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/jest.config.js
CHANGED
|
@@ -13,11 +13,17 @@ module.exports = {
|
|
|
13
13
|
// __dirname here tells babel to look in components-base for babel root when running from monorepo root
|
|
14
14
|
'\\.(js|jsx)$': ['babel-jest', { cwd: __dirname }]
|
|
15
15
|
},
|
|
16
|
-
setupFilesAfterEnv: [
|
|
16
|
+
setupFilesAfterEnv: [
|
|
17
|
+
'@testing-library/jest-native/extend-expect',
|
|
18
|
+
// Fail tests that use console.error or console.warn
|
|
19
|
+
'<rootDir>/../../jest-no-console'
|
|
20
|
+
],
|
|
17
21
|
moduleNameMapper: {
|
|
18
22
|
'.+\\.(otf|svg|png|jpg)$': 'identity-obj-proxy'
|
|
19
23
|
},
|
|
20
|
-
transformIgnorePatterns:
|
|
24
|
+
transformIgnorePatterns: [
|
|
25
|
+
'node_modules/(?!(jest-)?react-native|@react-native|@react-native-community|@react-native-picker)'
|
|
26
|
+
],
|
|
21
27
|
// Count everything in src when calculating coverage
|
|
22
28
|
collectCoverageFrom: ['src/**/*.{js,jsx}']
|
|
23
29
|
}
|
|
@@ -1,58 +1,86 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useA11yInfo = exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
|
|
10
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
+
|
|
12
|
+
var _AccessibilityInfo = _interopRequireDefault(require("react-native-web/dist/cjs/exports/AccessibilityInfo"));
|
|
13
|
+
|
|
14
|
+
var _Platform = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Platform"));
|
|
15
|
+
|
|
16
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
21
|
+
|
|
22
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
23
|
+
|
|
24
|
+
const ScreenReaderContext = /*#__PURE__*/(0, _react.createContext)(false);
|
|
25
|
+
const ReducedMotionContext = /*#__PURE__*/(0, _react.createContext)(false);
|
|
6
26
|
|
|
7
27
|
const A11yInfoProvider = ({
|
|
8
28
|
children
|
|
9
29
|
}) => {
|
|
10
|
-
const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false);
|
|
11
|
-
const [screenReaderEnabled, setScreenReaderEnabled] = useState(false);
|
|
12
|
-
useEffect(() => {
|
|
30
|
+
const [reduceMotionEnabled, setReduceMotionEnabled] = (0, _react.useState)(false);
|
|
31
|
+
const [screenReaderEnabled, setScreenReaderEnabled] = (0, _react.useState)(false);
|
|
32
|
+
(0, _react.useEffect)(() => {
|
|
13
33
|
if (process.env.NODE_ENV === 'test') {
|
|
14
34
|
// On Jest these effects do nothing but can cause `act` state change warnings
|
|
15
35
|
// and "...after the Jest environment has been torn down" errors, so skip them.
|
|
16
36
|
return () => {};
|
|
17
37
|
}
|
|
18
38
|
|
|
19
|
-
|
|
20
|
-
|
|
39
|
+
_AccessibilityInfo.default.addEventListener('reduceMotionChanged', setReduceMotionEnabled);
|
|
40
|
+
|
|
41
|
+
_AccessibilityInfo.default.addEventListener('screenReaderChanged', setScreenReaderEnabled);
|
|
21
42
|
|
|
22
43
|
const setInitialA11yInfo = async () => {
|
|
23
|
-
const [initialReduceMotionEnabled, initialScreenReaderEnabled] = await Promise.all([
|
|
44
|
+
const [initialReduceMotionEnabled, initialScreenReaderEnabled] = await Promise.all([_AccessibilityInfo.default.isReduceMotionEnabled(), _AccessibilityInfo.default.isScreenReaderEnabled()]); // Browsers can't detect screen readers; in RNW isScreenReaderEnabled() is always `true`
|
|
24
45
|
// https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/AccessibilityInfo/index.js#L14
|
|
25
46
|
|
|
26
|
-
setScreenReaderEnabled(
|
|
47
|
+
setScreenReaderEnabled(_Platform.default.OS !== 'web' && !!initialScreenReaderEnabled); // RNW does support isReduceMotionEnabled looking for 'prefers-reduced-motion' state
|
|
27
48
|
|
|
28
49
|
setReduceMotionEnabled(!!initialReduceMotionEnabled);
|
|
29
50
|
};
|
|
30
51
|
|
|
31
|
-
if (
|
|
52
|
+
if (_AccessibilityInfo.default.isReduceMotionEnabled && _AccessibilityInfo.default.isScreenReaderEnabled) {
|
|
32
53
|
setInitialA11yInfo();
|
|
33
54
|
}
|
|
34
55
|
|
|
35
56
|
return () => {
|
|
36
|
-
|
|
37
|
-
|
|
57
|
+
_AccessibilityInfo.default.removeEventListener('reduceMotionChanged', setReduceMotionEnabled);
|
|
58
|
+
|
|
59
|
+
_AccessibilityInfo.default.removeEventListener('screenReaderChanged', setScreenReaderEnabled);
|
|
38
60
|
};
|
|
39
61
|
}, []);
|
|
40
|
-
return /*#__PURE__*/
|
|
41
|
-
value: reduceMotionEnabled
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
62
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ReducedMotionContext.Provider, {
|
|
63
|
+
value: reduceMotionEnabled,
|
|
64
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(ScreenReaderContext.Provider, {
|
|
65
|
+
value: screenReaderEnabled,
|
|
66
|
+
children: children
|
|
67
|
+
})
|
|
68
|
+
});
|
|
45
69
|
};
|
|
46
70
|
|
|
47
71
|
A11yInfoProvider.propTypes = {
|
|
48
|
-
children:
|
|
72
|
+
children: _propTypes.default.node.isRequired
|
|
49
73
|
};
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
74
|
+
var _default = A11yInfoProvider;
|
|
75
|
+
exports.default = _default;
|
|
76
|
+
|
|
77
|
+
const useA11yInfo = () => {
|
|
78
|
+
const screenReaderEnabled = (0, _react.useContext)(ScreenReaderContext);
|
|
79
|
+
const reduceMotionEnabled = (0, _react.useContext)(ReducedMotionContext);
|
|
54
80
|
return {
|
|
55
81
|
reduceMotionEnabled,
|
|
56
82
|
screenReaderEnabled
|
|
57
83
|
};
|
|
58
|
-
};
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
exports.useA11yInfo = useA11yInfo;
|