@telus-uds/components-base 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -2
- package/component-docs.json +933 -55
- package/lib/BaseProvider/index.js +7 -2
- package/lib/Button/ButtonBase.js +52 -19
- package/lib/Button/ButtonGroup.js +7 -0
- package/lib/Button/propTypes.js +18 -0
- package/lib/Carousel/Carousel.js +83 -58
- package/lib/Carousel/CarouselContext.js +22 -8
- package/lib/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +73 -0
- package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
- package/lib/Carousel/CarouselStepTracker/index.js +13 -0
- package/lib/Carousel/CarouselTabs/CarouselTabs.js +70 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +95 -0
- package/lib/Carousel/CarouselTabs/CarouselTabsPanelItem.js +148 -0
- package/lib/Carousel/CarouselTabs/index.js +13 -0
- package/lib/Carousel/CarouselThumbnail.js +99 -0
- package/lib/Carousel/CarouselThumbnailNavigation.js +87 -0
- package/lib/Carousel/dictionary.js +4 -2
- package/lib/Carousel/index.js +10 -1
- package/lib/Checkbox/Checkbox.js +7 -3
- package/lib/Checkbox/CheckboxGroup.js +8 -1
- package/lib/Feedback/Feedback.js +18 -10
- package/lib/Icon/IconText.js +6 -1
- package/lib/InputLabel/InputLabel.js +11 -5
- package/lib/Link/InlinePressable.js +1 -8
- package/lib/Link/LinkBase.js +13 -10
- package/lib/List/ListItem.js +8 -4
- package/lib/Notification/Notification.js +44 -24
- package/lib/Pagination/Pagination.js +7 -3
- package/lib/Radio/RadioGroup.js +8 -0
- package/lib/RadioCard/RadioCard.js +6 -1
- package/lib/RadioCard/RadioCardGroup.js +7 -0
- package/lib/Select/Select.js +7 -3
- package/lib/SkipLink/SkipLink.js +216 -0
- package/lib/SkipLink/index.js +13 -0
- package/lib/StepTracker/Step.js +8 -4
- package/lib/StepTracker/StepTracker.js +7 -3
- package/lib/Tabs/TabsItem.js +4 -0
- package/lib/TextInput/TextInputBase.js +7 -3
- package/lib/ThemeProvider/ThemeProvider.js +25 -3
- package/lib/ThemeProvider/utils/styles.js +8 -1
- package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib/Typography/Typography.js +6 -2
- package/lib/index.js +9 -0
- package/lib-module/BaseProvider/index.js +7 -2
- package/lib-module/Button/ButtonBase.js +41 -9
- package/lib-module/Button/ButtonGroup.js +7 -0
- package/lib-module/Button/propTypes.js +17 -0
- package/lib-module/Carousel/Carousel.js +80 -57
- package/lib-module/Carousel/CarouselContext.js +21 -8
- package/lib-module/Carousel/CarouselFirstFocus/CarouselFirstFocus.js +51 -0
- package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
- package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabs.js +50 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +76 -0
- package/lib-module/Carousel/CarouselTabs/CarouselTabsPanelItem.js +126 -0
- package/lib-module/Carousel/CarouselTabs/index.js +2 -0
- package/lib-module/Carousel/CarouselThumbnail.js +85 -0
- package/lib-module/Carousel/CarouselThumbnailNavigation.js +66 -0
- package/lib-module/Carousel/dictionary.js +4 -2
- package/lib-module/Carousel/index.js +2 -1
- package/lib-module/Checkbox/Checkbox.js +8 -4
- package/lib-module/Checkbox/CheckboxGroup.js +8 -1
- package/lib-module/Feedback/Feedback.js +19 -11
- package/lib-module/Icon/IconText.js +6 -1
- package/lib-module/InputLabel/InputLabel.js +12 -6
- package/lib-module/Link/InlinePressable.js +1 -8
- package/lib-module/Link/LinkBase.js +14 -11
- package/lib-module/List/ListItem.js +9 -5
- package/lib-module/Notification/Notification.js +46 -26
- package/lib-module/Pagination/Pagination.js +8 -4
- package/lib-module/Radio/RadioGroup.js +8 -0
- package/lib-module/RadioCard/RadioCard.js +7 -2
- package/lib-module/RadioCard/RadioCardGroup.js +7 -0
- package/lib-module/Select/Select.js +8 -4
- package/lib-module/SkipLink/SkipLink.js +188 -0
- package/lib-module/SkipLink/index.js +2 -0
- package/lib-module/StepTracker/Step.js +9 -5
- package/lib-module/StepTracker/StepTracker.js +8 -4
- package/lib-module/Tabs/TabsItem.js +5 -1
- package/lib-module/TextInput/TextInputBase.js +8 -4
- package/lib-module/ThemeProvider/ThemeProvider.js +24 -3
- package/lib-module/ThemeProvider/utils/styles.js +8 -1
- package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +7 -0
- package/lib-module/Typography/Typography.js +7 -3
- package/lib-module/index.js +1 -0
- package/package.json +46 -47
- package/src/BaseProvider/index.jsx +6 -3
- package/src/Button/ButtonBase.jsx +36 -12
- package/src/Button/ButtonGroup.jsx +6 -0
- package/src/Button/propTypes.js +14 -0
- package/src/Carousel/Carousel.jsx +91 -64
- package/src/Carousel/CarouselContext.jsx +29 -5
- package/src/Carousel/CarouselFirstFocus/CarouselFirstFocus.jsx +49 -0
- package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
- package/src/Carousel/CarouselStepTracker/index.js +3 -0
- package/src/Carousel/CarouselTabs/CarouselTabs.jsx +37 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +69 -0
- package/src/Carousel/CarouselTabs/CarouselTabsPanelItem.jsx +119 -0
- package/src/Carousel/CarouselTabs/index.js +3 -0
- package/src/Carousel/CarouselThumbnail.jsx +77 -0
- package/src/Carousel/CarouselThumbnailNavigation.jsx +53 -0
- package/src/Carousel/dictionary.js +4 -2
- package/src/Carousel/index.js +1 -0
- package/src/Checkbox/Checkbox.jsx +14 -11
- package/src/Checkbox/CheckboxGroup.jsx +8 -1
- package/src/Feedback/Feedback.jsx +14 -7
- package/src/Icon/IconText.jsx +3 -1
- package/src/InputLabel/InputLabel.jsx +13 -12
- package/src/Link/InlinePressable.jsx +2 -8
- package/src/Link/LinkBase.jsx +18 -21
- package/src/List/ListItem.jsx +10 -5
- package/src/Notification/Notification.jsx +40 -23
- package/src/Pagination/Pagination.jsx +6 -4
- package/src/Radio/RadioGroup.jsx +7 -0
- package/src/RadioCard/RadioCard.jsx +3 -2
- package/src/RadioCard/RadioCardGroup.jsx +6 -0
- package/src/Select/Select.jsx +12 -3
- package/src/SkipLink/SkipLink.jsx +179 -0
- package/src/SkipLink/index.js +3 -0
- package/src/StepTracker/Step.jsx +12 -4
- package/src/StepTracker/StepTracker.jsx +11 -10
- package/src/Tabs/TabsItem.jsx +3 -2
- package/src/TextInput/TextInputBase.jsx +11 -3
- package/src/ThemeProvider/ThemeProvider.jsx +22 -3
- package/src/ThemeProvider/utils/styles.js +9 -1
- package/src/ThemeProvider/utils/theme-tokens.js +1 -1
- package/src/ToggleSwitch/ToggleSwitchGroup.jsx +6 -0
- package/src/Typography/Typography.jsx +11 -12
- package/src/index.js +1 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { Pressable, Image } from 'react-native'
|
|
4
|
+
import { useCarousel } from './CarouselContext'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `Carousel.Thumbnail` is used to wrap the content of an individual slide and is suppsoed to be the
|
|
8
|
+
* only top-level component passed to the `Carousel`
|
|
9
|
+
*/
|
|
10
|
+
const CarouselThumbnail = ({ accessibilityLabel, alt, index, src }) => {
|
|
11
|
+
const { activeIndex, itemLabel, totalItems, getCopyWithPlaceholders, goTo, themeTokens } =
|
|
12
|
+
useCarousel()
|
|
13
|
+
const thumbnailTitle =
|
|
14
|
+
alt ??
|
|
15
|
+
getCopyWithPlaceholders('stepTrackerLabel')
|
|
16
|
+
.replace(/%\{itemLabel\}/g, itemLabel)
|
|
17
|
+
.replace(/%\{stepNumber\}/g, index)
|
|
18
|
+
.replace(/%\{stepCount\}/g, totalItems)
|
|
19
|
+
const handlePress = () => goTo(index)
|
|
20
|
+
const handleKeyDown = (event) => {
|
|
21
|
+
// Allow using the spacebar for navigation
|
|
22
|
+
if (event?.key === ' ') goTo(index)
|
|
23
|
+
}
|
|
24
|
+
const {
|
|
25
|
+
thumbnailBorderColor,
|
|
26
|
+
thumbnailBorderRadius,
|
|
27
|
+
thumbnailBorderWidth,
|
|
28
|
+
thumbnailMargin,
|
|
29
|
+
thumbnailPadding,
|
|
30
|
+
thumbnailSelectedBorderColor,
|
|
31
|
+
thumbnailSelectedBorderWidth,
|
|
32
|
+
thumbnailSize
|
|
33
|
+
} = themeTokens
|
|
34
|
+
const styles = {
|
|
35
|
+
pressable: {
|
|
36
|
+
borderColor: thumbnailBorderColor,
|
|
37
|
+
borderRadius: thumbnailBorderRadius,
|
|
38
|
+
borderWidth: thumbnailBorderWidth,
|
|
39
|
+
margin: thumbnailMargin,
|
|
40
|
+
padding: thumbnailPadding
|
|
41
|
+
},
|
|
42
|
+
image: {
|
|
43
|
+
height: thumbnailSize,
|
|
44
|
+
width: thumbnailSize
|
|
45
|
+
},
|
|
46
|
+
selected: {
|
|
47
|
+
borderColor: thumbnailSelectedBorderColor,
|
|
48
|
+
borderWidth: thumbnailSelectedBorderWidth,
|
|
49
|
+
padding: thumbnailPadding - thumbnailSelectedBorderWidth + thumbnailBorderWidth
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Pressable
|
|
55
|
+
key={src}
|
|
56
|
+
onKeyDown={handleKeyDown}
|
|
57
|
+
onPress={handlePress}
|
|
58
|
+
style={[styles.pressable, index === activeIndex && styles.selected]}
|
|
59
|
+
>
|
|
60
|
+
<Image
|
|
61
|
+
accessibilityIgnoresInvertColors
|
|
62
|
+
accessibilityLabel={accessibilityLabel ?? alt}
|
|
63
|
+
source={src}
|
|
64
|
+
style={styles.image}
|
|
65
|
+
title={thumbnailTitle}
|
|
66
|
+
/>
|
|
67
|
+
</Pressable>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
CarouselThumbnail.propTypes = {
|
|
71
|
+
accessibilityLabel: PropTypes.string,
|
|
72
|
+
alt: PropTypes.string,
|
|
73
|
+
index: PropTypes.number,
|
|
74
|
+
src: PropTypes.string
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default CarouselThumbnail
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { View } from 'react-native'
|
|
4
|
+
import { useCarousel } from './CarouselContext'
|
|
5
|
+
import CarouselThumbnail from './CarouselThumbnail'
|
|
6
|
+
import { StackWrap } from '../StackView'
|
|
7
|
+
|
|
8
|
+
const CarouselThumbnailNavigation = forwardRef(({ thumbnails = [] }, ref) => {
|
|
9
|
+
const { totalItems, themeTokens } = useCarousel()
|
|
10
|
+
if (thumbnails.length !== totalItems) {
|
|
11
|
+
throw new Error('Thumbnail set provided does not match the number of slides in the carousel')
|
|
12
|
+
}
|
|
13
|
+
const { thumbnailContainerPaddingTop, thumbnailMargin } = themeTokens
|
|
14
|
+
const stackWrapTokens = {
|
|
15
|
+
justifyContent: 'flex-start'
|
|
16
|
+
}
|
|
17
|
+
const containerStyles = {
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
paddingTop: thumbnailContainerPaddingTop - thumbnailMargin
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View style={containerStyles}>
|
|
25
|
+
<StackWrap direction="row" tokens={stackWrapTokens} ref={ref}>
|
|
26
|
+
{thumbnails.map(({ accessibilityLabel, alt, src }, index) => (
|
|
27
|
+
<CarouselThumbnail
|
|
28
|
+
accessibilityLabel={accessibilityLabel}
|
|
29
|
+
alt={alt}
|
|
30
|
+
index={index}
|
|
31
|
+
key={src}
|
|
32
|
+
src={src}
|
|
33
|
+
/>
|
|
34
|
+
))}
|
|
35
|
+
</StackWrap>
|
|
36
|
+
</View>
|
|
37
|
+
)
|
|
38
|
+
})
|
|
39
|
+
CarouselThumbnailNavigation.displayName = 'CarouselThumbnailNavigation'
|
|
40
|
+
CarouselThumbnailNavigation.propTypes = {
|
|
41
|
+
/**
|
|
42
|
+
* An array of objects containing information on the thumbnail images.
|
|
43
|
+
*/
|
|
44
|
+
thumbnails: PropTypes.arrayOf(
|
|
45
|
+
PropTypes.shape({
|
|
46
|
+
accessibilityLabel: PropTypes.string,
|
|
47
|
+
alt: PropTypes.string,
|
|
48
|
+
src: PropTypes.string
|
|
49
|
+
})
|
|
50
|
+
).isRequired
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default CarouselThumbnailNavigation
|
|
@@ -4,13 +4,15 @@ export default {
|
|
|
4
4
|
carouselLabel: '%{stepCount} items',
|
|
5
5
|
iconButtonLabel: 'Show %{itemLabel} %{targetStep} of %{stepCount}',
|
|
6
6
|
stepLabel: '%{itemLabel} %{stepNumber}',
|
|
7
|
-
stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}'
|
|
7
|
+
stepTrackerLabel: '%{itemLabel} %{stepNumber} of %{stepCount}',
|
|
8
|
+
skipLink: 'Skip %{title}'
|
|
8
9
|
},
|
|
9
10
|
fr: {
|
|
10
11
|
// TODO: French translations here
|
|
11
12
|
carouselLabel: '(fr) %{stepCount} items',
|
|
12
13
|
iconButtonLabel: '(fr) Show %{itemLabel} %{targetStep} of %{stepCount}',
|
|
13
14
|
stepLabel: '(fr) %{itemLabel} %{stepNumber}',
|
|
14
|
-
stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}'
|
|
15
|
+
stepTrackerLabel: '(fr) %{itemLabel} %{stepNumber} of %{stepCount}',
|
|
16
|
+
skipLink: '(fr) Skip %{title}'
|
|
15
17
|
}
|
|
16
18
|
}
|
package/src/Carousel/index.js
CHANGED
|
@@ -6,7 +6,12 @@ import CheckboxInput from './CheckboxInput'
|
|
|
6
6
|
import CheckboxLabel from '../InputLabel/LabelContent'
|
|
7
7
|
import Feedback from '../Feedback'
|
|
8
8
|
import StackView from '../StackView'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
applyShadowToken,
|
|
11
|
+
applyTextStyles,
|
|
12
|
+
useTheme,
|
|
13
|
+
useThemeTokensCallback
|
|
14
|
+
} from '../ThemeProvider'
|
|
10
15
|
import {
|
|
11
16
|
a11yProps,
|
|
12
17
|
focusHandlerProps,
|
|
@@ -54,21 +59,18 @@ const selectInputStyles = (
|
|
|
54
59
|
}
|
|
55
60
|
})
|
|
56
61
|
})
|
|
57
|
-
const selectLabelStyles = (
|
|
58
|
-
labelColor,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
labelFontWeight,
|
|
62
|
-
labelMarginLeft,
|
|
63
|
-
labelLineHeight
|
|
64
|
-
}) => ({
|
|
62
|
+
const selectLabelStyles = (
|
|
63
|
+
{ labelColor, labelFontName, labelFontSize, labelFontWeight, labelMarginLeft, labelLineHeight },
|
|
64
|
+
themeOptions
|
|
65
|
+
) => ({
|
|
65
66
|
marginLeft: labelMarginLeft,
|
|
66
67
|
...applyTextStyles({
|
|
67
68
|
color: labelColor,
|
|
68
69
|
fontName: labelFontName,
|
|
69
70
|
fontWeight: labelFontWeight,
|
|
70
71
|
fontSize: labelFontSize,
|
|
71
|
-
lineHeight: labelLineHeight
|
|
72
|
+
lineHeight: labelLineHeight,
|
|
73
|
+
themeOptions
|
|
72
74
|
})
|
|
73
75
|
})
|
|
74
76
|
const selectIconTokens = ({ icon, iconColor, iconSize }) => ({
|
|
@@ -172,6 +174,7 @@ const Checkbox = forwardRef(
|
|
|
172
174
|
}
|
|
173
175
|
const uniqueId = useUniqueId('checkbox')
|
|
174
176
|
const inputId = id ?? uniqueId
|
|
177
|
+
const { themeOptions } = useTheme()
|
|
175
178
|
|
|
176
179
|
return (
|
|
177
180
|
<View style={staticStyles.wrapper} ref={ref}>
|
|
@@ -187,7 +190,7 @@ const Checkbox = forwardRef(
|
|
|
187
190
|
{({ focused: focus, hovered: hover, pressed }) => {
|
|
188
191
|
const { icon: IconComponent, ...stateTokens } = getTokens({ focus, hover, pressed })
|
|
189
192
|
const iconTokens = selectIconTokens(stateTokens)
|
|
190
|
-
const labelStyles = selectLabelStyles(stateTokens)
|
|
193
|
+
const labelStyles = selectLabelStyles(stateTokens, themeOptions)
|
|
191
194
|
const alignWithLabel = label
|
|
192
195
|
? [staticStyles.alignWithLabel, { height: labelStyles.lineHeight }]
|
|
193
196
|
: null
|
|
@@ -61,7 +61,7 @@ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([
|
|
|
61
61
|
* @example
|
|
62
62
|
* ```jsx
|
|
63
63
|
* <CheckboxGroup
|
|
64
|
-
*
|
|
64
|
+
* initialCheckedIds="check1"
|
|
65
65
|
* items={[
|
|
66
66
|
* { label: 'Checkbox 1', id: 'check1' },
|
|
67
67
|
* { label: 'Checkbox 2', id: 'check2' },
|
|
@@ -82,6 +82,8 @@ const CheckboxGroup = forwardRef(
|
|
|
82
82
|
legend,
|
|
83
83
|
tooltip,
|
|
84
84
|
hint,
|
|
85
|
+
hintPosition = 'inline',
|
|
86
|
+
|
|
85
87
|
validation,
|
|
86
88
|
feedback,
|
|
87
89
|
initialCheckedIds,
|
|
@@ -145,6 +147,7 @@ const CheckboxGroup = forwardRef(
|
|
|
145
147
|
legend={legend}
|
|
146
148
|
tooltip={tooltip}
|
|
147
149
|
hint={hint}
|
|
150
|
+
hintPosition={hintPosition}
|
|
148
151
|
space={fieldSpace}
|
|
149
152
|
feedback={feedback}
|
|
150
153
|
inactive={inactive}
|
|
@@ -192,6 +195,10 @@ CheckboxGroup.propTypes = {
|
|
|
192
195
|
* Optional additional text giving more detail to help a user make a choice.
|
|
193
196
|
*/
|
|
194
197
|
hint: PropTypes.string,
|
|
198
|
+
/**
|
|
199
|
+
* Position of the hint relative to label. Use `below` to display a larger hint below the label.
|
|
200
|
+
*/
|
|
201
|
+
hintPosition: PropTypes.oneOf(['inline', 'below']),
|
|
195
202
|
/**
|
|
196
203
|
* Optional tooltip text content to include alongside the legend and hint.
|
|
197
204
|
*/
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import { StyleSheet, Text, View } from 'react-native'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
|
|
5
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
getTokensPropType,
|
|
@@ -17,10 +17,16 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
17
17
|
|
|
18
18
|
const selectStyles = (tokens) => selectTokens('Feedback', tokens)
|
|
19
19
|
|
|
20
|
-
const selectTitleTextStyles = ({ titleFontSize, ...tokens }) =>
|
|
21
|
-
applyTextStyles(
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
const selectTitleTextStyles = ({ titleFontSize, ...tokens }, themeOptions) =>
|
|
21
|
+
applyTextStyles({
|
|
22
|
+
...selectTokens('Typography', { ...tokens, fontSize: titleFontSize, themeOptions }),
|
|
23
|
+
themeOptions
|
|
24
|
+
})
|
|
25
|
+
const selectContentTextStyles = ({ contentFontSize, ...tokens }, themeOptions) =>
|
|
26
|
+
applyTextStyles({
|
|
27
|
+
...selectTokens('Typography', { ...tokens, fontSize: contentFontSize }),
|
|
28
|
+
themeOptions
|
|
29
|
+
})
|
|
24
30
|
|
|
25
31
|
const selectIconTokens = ({ iconSize, iconColor }) => ({
|
|
26
32
|
size: iconSize,
|
|
@@ -56,8 +62,9 @@ const Feedback = forwardRef(
|
|
|
56
62
|
|
|
57
63
|
const { icon: IconComponent } = themeTokens
|
|
58
64
|
|
|
59
|
-
const
|
|
60
|
-
const
|
|
65
|
+
const { themeOptions } = useTheme()
|
|
66
|
+
const titleTextStyles = selectTitleTextStyles(themeTokens, themeOptions)
|
|
67
|
+
const contentTextStyles = selectContentTextStyles(themeTokens, themeOptions)
|
|
61
68
|
|
|
62
69
|
const content =
|
|
63
70
|
typeof children === 'string' ? <Text style={contentTextStyles}>{children}</Text> : children
|
package/src/Icon/IconText.jsx
CHANGED
|
@@ -39,6 +39,7 @@ const IconText = forwardRef(
|
|
|
39
39
|
IconText.displayName = 'IconText'
|
|
40
40
|
|
|
41
41
|
IconText.propTypes = {
|
|
42
|
+
/* eslint-disable react/no-unused-prop-types */ // eslint is having hard time seeing these props through forwardRef
|
|
42
43
|
/**
|
|
43
44
|
* Amount of space to separate the text content and icon. Uses the themes's spacing scale
|
|
44
45
|
* (see useSpacingScale for more info).
|
|
@@ -51,7 +52,7 @@ IconText.propTypes = {
|
|
|
51
52
|
/**
|
|
52
53
|
* A valid UDS icon component imported from a UDS palette.
|
|
53
54
|
*/
|
|
54
|
-
icon: PropTypes.
|
|
55
|
+
icon: PropTypes.elementType,
|
|
55
56
|
/**
|
|
56
57
|
* Props that will be passed to the icon component. By default the icon's `scalesWithText`
|
|
57
58
|
* prop will be set as "true" so that the icon continues to match the size of the text
|
|
@@ -63,6 +64,7 @@ IconText.propTypes = {
|
|
|
63
64
|
* `<Typography>` component, or a component that renders `<Text>`.
|
|
64
65
|
*/
|
|
65
66
|
children: PropTypes.node
|
|
67
|
+
/* eslint-enable react/no-unused-prop-types */
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
export default IconText
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import { StyleSheet, Text, View } from 'react-native'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
4
|
|
|
5
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
getTokensPropType,
|
|
@@ -17,21 +17,20 @@ import Tooltip from '../Tooltip'
|
|
|
17
17
|
|
|
18
18
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
19
19
|
|
|
20
|
-
const selectLabelStyles = (tokens) =>
|
|
20
|
+
const selectLabelStyles = (tokens, themeOptions) =>
|
|
21
|
+
applyTextStyles({ ...selectTokens('Typography', tokens), themeOptions })
|
|
21
22
|
|
|
22
|
-
const selectHintStyles = (
|
|
23
|
-
hintColor,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
hintFontWeight,
|
|
27
|
-
hintLineHeight
|
|
28
|
-
}) =>
|
|
23
|
+
const selectHintStyles = (
|
|
24
|
+
{ hintColor, hintFontName, hintFontSize, hintFontWeight, hintLineHeight },
|
|
25
|
+
themeOptions
|
|
26
|
+
) =>
|
|
29
27
|
applyTextStyles({
|
|
30
28
|
color: hintColor,
|
|
31
29
|
fontName: hintFontName,
|
|
32
30
|
fontSize: hintFontSize,
|
|
33
31
|
fontWeight: hintFontWeight,
|
|
34
|
-
lineHeight: hintLineHeight
|
|
32
|
+
lineHeight: hintLineHeight,
|
|
33
|
+
themeOptions
|
|
35
34
|
})
|
|
36
35
|
|
|
37
36
|
const selectGapStyles = ({ gap }) => ({ marginRight: gap })
|
|
@@ -57,12 +56,14 @@ const InputLabel = forwardRef(
|
|
|
57
56
|
const hasTooltip = tooltip !== undefined
|
|
58
57
|
const isHintInline = hintPosition === 'inline'
|
|
59
58
|
|
|
59
|
+
const { themeOptions } = useTheme()
|
|
60
|
+
|
|
60
61
|
return (
|
|
61
62
|
<>
|
|
62
63
|
<View ref={ref} style={staticStyles.container} {...selectProps(rest)}>
|
|
63
64
|
<Text
|
|
64
65
|
style={[
|
|
65
|
-
selectLabelStyles(themeTokens),
|
|
66
|
+
selectLabelStyles(themeTokens, themeOptions),
|
|
66
67
|
selectGapStyles(themeTokens),
|
|
67
68
|
staticStyles.label
|
|
68
69
|
]}
|
|
@@ -72,7 +73,7 @@ const InputLabel = forwardRef(
|
|
|
72
73
|
{hint && isHintInline && (
|
|
73
74
|
<Text
|
|
74
75
|
style={[
|
|
75
|
-
selectHintStyles(themeTokens),
|
|
76
|
+
selectHintStyles(themeTokens, themeOptions),
|
|
76
77
|
hasTooltip && selectGapStyles(themeTokens),
|
|
77
78
|
staticStyles.label
|
|
78
79
|
]}
|
|
@@ -9,17 +9,15 @@ import { Pressable, StyleSheet } from 'react-native'
|
|
|
9
9
|
* InlinePressable is an alternative to React Native's Pressable that works better when nested
|
|
10
10
|
* inline inside Text. It accepts the same props as React Native's Pressable.
|
|
11
11
|
*
|
|
12
|
-
* On Web it simply passes its props to Pressable and defaults to `inline-flex` instead of `flex`.
|
|
13
|
-
*
|
|
14
12
|
* @param {PressableProps} PressableProps
|
|
15
13
|
*/
|
|
16
14
|
// React Native exports prop Types but not propTypes, use JSDoc types here rather than duplicate RN
|
|
17
15
|
// eslint-disable-next-line react/prop-types
|
|
18
|
-
const InlinePressable = forwardRef(({ children, style,
|
|
16
|
+
const InlinePressable = forwardRef(({ children, style, ...props }, ref) => (
|
|
19
17
|
<Pressable
|
|
20
18
|
ref={ref}
|
|
21
19
|
style={(pressState) => [
|
|
22
|
-
staticStyles
|
|
20
|
+
staticStyles.inline,
|
|
23
21
|
typeof style === 'function' ? style(pressState) : style
|
|
24
22
|
]}
|
|
25
23
|
{...props}
|
|
@@ -31,11 +29,7 @@ InlinePressable.displayName = 'InlinePressable'
|
|
|
31
29
|
|
|
32
30
|
const staticStyles = StyleSheet.create({
|
|
33
31
|
inline: {
|
|
34
|
-
// Stop Pressable defaulting to (block) flex
|
|
35
32
|
display: 'inline'
|
|
36
|
-
},
|
|
37
|
-
inlineFlex: {
|
|
38
|
-
display: 'inline-flex'
|
|
39
33
|
}
|
|
40
34
|
})
|
|
41
35
|
|
package/src/Link/LinkBase.jsx
CHANGED
|
@@ -15,18 +15,15 @@ import { resolvePressableTokens } from '../utils/pressability'
|
|
|
15
15
|
import { withLinkRouter } from '../utils'
|
|
16
16
|
|
|
17
17
|
import InlinePressable from './InlinePressable'
|
|
18
|
-
import { applyTextStyles, applyOuterBorder } from '../ThemeProvider'
|
|
18
|
+
import { applyTextStyles, applyOuterBorder, useTheme } from '../ThemeProvider'
|
|
19
19
|
import { IconText, iconComponentPropTypes } from '../Icon'
|
|
20
20
|
|
|
21
21
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps])
|
|
22
22
|
|
|
23
|
-
const selectOuterBorderStyles = (
|
|
24
|
-
outerBorderColor,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
borderRadius,
|
|
28
|
-
outerBorderOutline
|
|
29
|
-
}) =>
|
|
23
|
+
const selectOuterBorderStyles = (
|
|
24
|
+
{ outerBorderColor, outerBorderWidth, outerBorderGap, borderRadius, outerBorderOutline },
|
|
25
|
+
hasIcon
|
|
26
|
+
) =>
|
|
30
27
|
// A view wrapper with a border on native messes up inline text alignment
|
|
31
28
|
// so for now make focus styles strictly web-only
|
|
32
29
|
Platform.OS === 'web'
|
|
@@ -41,7 +38,7 @@ const selectOuterBorderStyles = ({
|
|
|
41
38
|
}),
|
|
42
39
|
// Stops focus ring stretching horizontally if parent has display: block
|
|
43
40
|
// width: fit-content isn't supported on Firefox; can't cascade props like CSS `width: fit-content; width: --moz-fit-content;`
|
|
44
|
-
display: 'inline-flex'
|
|
41
|
+
display: hasIcon ? 'inline-flex' : 'inline' // Stop Pressable defaulting to (block) flex
|
|
45
42
|
}
|
|
46
43
|
: {}
|
|
47
44
|
|
|
@@ -55,12 +52,16 @@ const selectTextStyles = ({ color }) => ({
|
|
|
55
52
|
})
|
|
56
53
|
})
|
|
57
54
|
|
|
58
|
-
const selectBlockStyles = (
|
|
55
|
+
const selectBlockStyles = (
|
|
56
|
+
{ blockFontWeight, blockFontSize, blockLineHeight, blockFontName },
|
|
57
|
+
themeOptions
|
|
58
|
+
) =>
|
|
59
59
|
applyTextStyles({
|
|
60
60
|
fontWeight: blockFontWeight,
|
|
61
61
|
fontSize: blockFontSize,
|
|
62
62
|
lineHeight: blockLineHeight,
|
|
63
|
-
fontName: blockFontName
|
|
63
|
+
fontName: blockFontName,
|
|
64
|
+
themeOptions
|
|
64
65
|
})
|
|
65
66
|
|
|
66
67
|
const selectDecorationStyles = ({ color, textLine, textLineStyle }) => ({
|
|
@@ -138,21 +139,17 @@ const LinkBase = forwardRef(
|
|
|
138
139
|
// On web, this makes focus rings wrap only the link, not the entire block
|
|
139
140
|
const blockLeftStyle = Platform.OS === 'web' && staticStyles.blockLeft
|
|
140
141
|
|
|
142
|
+
const { themeOptions } = useTheme()
|
|
143
|
+
|
|
141
144
|
return (
|
|
142
145
|
<InlinePressable
|
|
143
146
|
{...selectedProps}
|
|
144
|
-
inline={hasIcon} // assuming links without icons should be inline (even if they are long)
|
|
145
147
|
ref={ref}
|
|
146
148
|
style={(linkState) => {
|
|
147
149
|
const themeTokens = resolveLinkTokens(linkState)
|
|
148
|
-
const outerBorderStyles = selectOuterBorderStyles(themeTokens)
|
|
150
|
+
const outerBorderStyles = selectOuterBorderStyles(themeTokens, hasIcon)
|
|
149
151
|
const decorationStyles = selectDecorationStyles(themeTokens)
|
|
150
|
-
return [
|
|
151
|
-
outerBorderStyles,
|
|
152
|
-
blockLeftStyle,
|
|
153
|
-
decorationStyles,
|
|
154
|
-
hasIcon && staticStyles.rowContainer
|
|
155
|
-
]
|
|
152
|
+
return [outerBorderStyles, blockLeftStyle, decorationStyles, staticStyles.rowContainer]
|
|
156
153
|
}}
|
|
157
154
|
>
|
|
158
155
|
{(linkState) => {
|
|
@@ -162,7 +159,7 @@ const LinkBase = forwardRef(
|
|
|
162
159
|
|
|
163
160
|
// TODO: may need to apply some smarter text inheritance here if inline to avoid native
|
|
164
161
|
// issues like double-application of line heights breaking align-items: baseline
|
|
165
|
-
const blockTextStyles = selectBlockStyles(themeTokens)
|
|
162
|
+
const blockTextStyles = selectBlockStyles(themeTokens, themeOptions)
|
|
166
163
|
|
|
167
164
|
const IconComponent = icon || themeTokens.icon
|
|
168
165
|
const { iconSpace } = themeTokens
|
|
@@ -196,7 +193,7 @@ LinkBase.propTypes = {
|
|
|
196
193
|
* A function component for an SVG icon to render inside the link. Inherits size and color from
|
|
197
194
|
* the link and any Typography the link is nested inside.
|
|
198
195
|
*/
|
|
199
|
-
icon: PropTypes.
|
|
196
|
+
icon: PropTypes.elementType,
|
|
200
197
|
/**
|
|
201
198
|
* When `icon` is provided, use `iconPosition` to place the Icon to the left or right side of Link.
|
|
202
199
|
*/
|
package/src/List/ListItem.jsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import { View, Platform, StyleSheet } from 'react-native'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
|
-
import { useThemeTokens, applyTextStyles } from '../ThemeProvider'
|
|
4
|
+
import { useTheme, useThemeTokens, applyTextStyles } from '../ThemeProvider'
|
|
5
5
|
import {
|
|
6
6
|
a11yProps,
|
|
7
7
|
getTokensPropType,
|
|
@@ -41,12 +41,16 @@ const selectBulletPositioningStyles = ({ itemIconSize }) => ({
|
|
|
41
41
|
height: itemIconSize
|
|
42
42
|
})
|
|
43
43
|
|
|
44
|
-
const selectItemStyles = (
|
|
44
|
+
const selectItemStyles = (
|
|
45
|
+
{ itemFontWeight, itemFontSize, itemLineHeight, itemFontName },
|
|
46
|
+
themeOptions
|
|
47
|
+
) =>
|
|
45
48
|
applyTextStyles({
|
|
46
49
|
fontWeight: itemFontWeight,
|
|
47
50
|
fontSize: itemFontSize,
|
|
48
51
|
lineHeight: itemLineHeight,
|
|
49
|
-
fontName: itemFontName
|
|
52
|
+
fontName: itemFontName,
|
|
53
|
+
themeOptions
|
|
50
54
|
})
|
|
51
55
|
|
|
52
56
|
const selectItemBlockStyles = ({ interItemMargin }) => ({
|
|
@@ -80,8 +84,9 @@ const ListItem = forwardRef(
|
|
|
80
84
|
ref
|
|
81
85
|
) => {
|
|
82
86
|
const themeTokens = useThemeTokens('List', tokens, variant)
|
|
87
|
+
const { themeOptions } = useTheme()
|
|
83
88
|
|
|
84
|
-
const itemStyles = selectItemStyles(themeTokens)
|
|
89
|
+
const itemStyles = selectItemStyles(themeTokens, themeOptions)
|
|
85
90
|
const itemBlockStyles = selectItemBlockStyles(themeTokens)
|
|
86
91
|
const dividerStyles = selectDividerStyles(themeTokens)
|
|
87
92
|
const itemBulletContainerStyles = selectBulletContainerStyles(themeTokens)
|
|
@@ -175,7 +180,7 @@ ListItem.propTypes = {
|
|
|
175
180
|
/**
|
|
176
181
|
* Renders side item icon
|
|
177
182
|
*/
|
|
178
|
-
icon: PropTypes.
|
|
183
|
+
icon: PropTypes.elementType,
|
|
179
184
|
/**
|
|
180
185
|
* Will set display icon color
|
|
181
186
|
*/
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef, useState } from 'react'
|
|
|
2
2
|
import { StyleSheet, View } from 'react-native'
|
|
3
3
|
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider'
|
|
5
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider'
|
|
6
6
|
import {
|
|
7
7
|
a11yProps,
|
|
8
8
|
getTokensPropType,
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
selectTokens,
|
|
11
11
|
variantProp,
|
|
12
12
|
viewProps,
|
|
13
|
-
wrapStringsInText
|
|
13
|
+
wrapStringsInText,
|
|
14
|
+
useResponsiveProp
|
|
14
15
|
} from '../utils'
|
|
15
16
|
import ButtonBase from '../Button/ButtonBase'
|
|
16
17
|
import useCopy from '../utils/useCopy'
|
|
@@ -20,7 +21,8 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
20
21
|
|
|
21
22
|
const selectContainerStyles = (tokens) => ({ ...tokens })
|
|
22
23
|
|
|
23
|
-
const selectTextStyles = (tokens) =>
|
|
24
|
+
const selectTextStyles = (tokens, themeOptions) =>
|
|
25
|
+
applyTextStyles({ ...selectTokens('Typography', tokens), themeOptions })
|
|
24
26
|
|
|
25
27
|
const selectIconProps = ({ iconSize, iconColor }) => ({
|
|
26
28
|
size: iconSize,
|
|
@@ -40,6 +42,10 @@ const selectDismissButtonContainerStyles = ({ dismissButtonGap }) => ({
|
|
|
40
42
|
paddingLeft: dismissButtonGap
|
|
41
43
|
})
|
|
42
44
|
|
|
45
|
+
const selectContentContainerStyle = (maxWidth) => ({
|
|
46
|
+
width: maxWidth || '100%'
|
|
47
|
+
})
|
|
48
|
+
|
|
43
49
|
/**
|
|
44
50
|
* A banner that highlights important messages:
|
|
45
51
|
* - Status message to show there is an error or outage of services
|
|
@@ -96,12 +102,14 @@ const Notification = forwardRef(
|
|
|
96
102
|
const [isDismissed, setIsDismissed] = useState(false)
|
|
97
103
|
const themeTokens = useThemeTokens('Notification', tokens, variant, { system })
|
|
98
104
|
const getCopy = useCopy({ dictionary, copy })
|
|
105
|
+
const { themeOptions } = useTheme()
|
|
106
|
+
const contentMaxWidth = useResponsiveProp(themeOptions?.contentMaxWidth)
|
|
99
107
|
|
|
100
108
|
if (isDismissed) {
|
|
101
109
|
return null
|
|
102
110
|
}
|
|
103
111
|
|
|
104
|
-
const textStyles = selectTextStyles(themeTokens)
|
|
112
|
+
const textStyles = selectTextStyles(themeTokens, themeOptions)
|
|
105
113
|
|
|
106
114
|
const content = wrapStringsInText(
|
|
107
115
|
typeof children === 'function' ? children({ textStyles }) : children,
|
|
@@ -119,25 +127,27 @@ const Notification = forwardRef(
|
|
|
119
127
|
style={[staticStyles.container, selectContainerStyles(themeTokens)]}
|
|
120
128
|
{...selectProps(rest)}
|
|
121
129
|
>
|
|
122
|
-
{
|
|
123
|
-
<View style={
|
|
124
|
-
|
|
130
|
+
<View style={[staticStyles.content, selectContentContainerStyle(contentMaxWidth)]}>
|
|
131
|
+
<View style={staticStyles.contentContainer}>
|
|
132
|
+
{IconComponent && (
|
|
133
|
+
<View style={selectIconContainerStyles(themeTokens)}>
|
|
134
|
+
<IconComponent {...selectIconProps(themeTokens)} />
|
|
135
|
+
</View>
|
|
136
|
+
)}
|
|
137
|
+
{content && typeof content === 'function' ? content({ textStyles, variant }) : content}
|
|
125
138
|
</View>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
139
|
+
{dismissible && DismissIconComponent && (
|
|
140
|
+
<View style={selectDismissButtonContainerStyles(themeTokens)}>
|
|
141
|
+
<ButtonBase
|
|
142
|
+
onPress={onDismissPress}
|
|
143
|
+
accessibilityRole="button"
|
|
144
|
+
accessibilityLabel={getCopy('dismiss')}
|
|
145
|
+
>
|
|
146
|
+
{() => <DismissIconComponent {...selectDismissIconProps(themeTokens)} />}
|
|
147
|
+
</ButtonBase>
|
|
148
|
+
</View>
|
|
149
|
+
)}
|
|
129
150
|
</View>
|
|
130
|
-
{dismissible && DismissIconComponent && (
|
|
131
|
-
<View style={selectDismissButtonContainerStyles(themeTokens)}>
|
|
132
|
-
<ButtonBase
|
|
133
|
-
onPress={onDismissPress}
|
|
134
|
-
accessibilityRole="button"
|
|
135
|
-
accessibilityLabel={getCopy('dismiss')}
|
|
136
|
-
>
|
|
137
|
-
{() => <DismissIconComponent {...selectDismissIconProps(themeTokens)} />}
|
|
138
|
-
</ButtonBase>
|
|
139
|
-
</View>
|
|
140
|
-
)}
|
|
141
151
|
</View>
|
|
142
152
|
)
|
|
143
153
|
}
|
|
@@ -173,9 +183,16 @@ export default Notification
|
|
|
173
183
|
|
|
174
184
|
const staticStyles = StyleSheet.create({
|
|
175
185
|
container: {
|
|
176
|
-
flexDirection: 'row'
|
|
186
|
+
flexDirection: 'row',
|
|
187
|
+
justifyContent: 'center'
|
|
177
188
|
},
|
|
178
189
|
contentContainer: {
|
|
179
|
-
|
|
190
|
+
flexDirection: 'row',
|
|
191
|
+
flexShrink: 1
|
|
192
|
+
},
|
|
193
|
+
content: {
|
|
194
|
+
flexDirection: 'row',
|
|
195
|
+
flexShrink: 1,
|
|
196
|
+
justifyContent: 'space-between'
|
|
180
197
|
}
|
|
181
198
|
})
|