@telus-uds/components-base 1.4.0 → 1.6.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/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-lint.log +13 -0
- package/CHANGELOG.json +140 -1
- package/CHANGELOG.md +42 -2
- package/__tests__/FlexGrid/Row.test.jsx +100 -25
- package/__tests__/utils/containUniqueFields.test.js +25 -0
- package/component-docs.json +94 -16
- package/generate-component-docs.js +20 -7
- package/lib/Button/ButtonBase.js +1 -1
- package/lib/Button/ButtonGroup.js +20 -12
- package/lib/Card/PressableCardBase.js +1 -1
- package/lib/Checkbox/Checkbox.js +27 -16
- package/lib/Checkbox/CheckboxGroup.js +19 -5
- package/lib/ExpandCollapse/Panel.js +10 -10
- package/lib/FlexGrid/Col/Col.js +13 -3
- package/lib/FlexGrid/Row/Row.js +8 -2
- package/lib/HorizontalScroll/HorizontalScroll.js +0 -1
- package/lib/HorizontalScroll/HorizontalScrollButton.js +23 -49
- package/lib/InputLabel/InputLabel.js +27 -25
- package/lib/Link/LinkBase.js +19 -6
- package/lib/Link/TextButton.js +1 -10
- package/lib/Modal/Modal.js +18 -18
- package/lib/Radio/Radio.js +23 -12
- package/lib/Radio/RadioGroup.js +12 -3
- package/lib/RadioCard/RadioCard.js +1 -1
- package/lib/RadioCard/RadioCardGroup.js +11 -2
- package/lib/Select/Select.js +2 -3
- package/lib/Tags/Tags.js +23 -17
- package/lib/TextInput/TextArea.js +2 -2
- package/lib/TextInput/TextInput.js +12 -2
- package/lib/TextInput/TextInputBase.js +1 -1
- package/lib/TextInput/propTypes.js +8 -1
- package/lib/ToggleSwitch/ToggleSwitch.js +5 -2
- package/lib/ToggleSwitch/ToggleSwitchGroup.js +20 -12
- package/lib/utils/containUniqueFields.js +34 -0
- package/lib/utils/index.js +10 -1
- package/lib/utils/props/handlerProps.js +72 -0
- package/lib/utils/props/index.js +14 -0
- package/lib/utils/props/inputSupportsProps.js +3 -5
- package/lib/utils/props/linkProps.js +3 -7
- package/lib-module/Button/ButtonBase.js +2 -2
- package/lib-module/Button/ButtonGroup.js +15 -6
- package/lib-module/Card/PressableCardBase.js +2 -2
- package/lib-module/Checkbox/Checkbox.js +28 -17
- package/lib-module/Checkbox/CheckboxGroup.js +20 -7
- package/lib-module/ExpandCollapse/Panel.js +10 -10
- package/lib-module/FlexGrid/Col/Col.js +13 -3
- package/lib-module/FlexGrid/Row/Row.js +8 -2
- package/lib-module/HorizontalScroll/HorizontalScroll.js +0 -1
- package/lib-module/HorizontalScroll/HorizontalScrollButton.js +24 -49
- package/lib-module/InputLabel/InputLabel.js +28 -25
- package/lib-module/Link/LinkBase.js +19 -6
- package/lib-module/Link/TextButton.js +1 -10
- package/lib-module/Modal/Modal.js +19 -19
- package/lib-module/Radio/Radio.js +24 -13
- package/lib-module/Radio/RadioGroup.js +13 -4
- package/lib-module/RadioCard/RadioCard.js +2 -2
- package/lib-module/RadioCard/RadioCardGroup.js +12 -3
- package/lib-module/Select/Select.js +2 -3
- package/lib-module/Tags/Tags.js +18 -11
- package/lib-module/TextInput/TextArea.js +3 -3
- package/lib-module/TextInput/TextInput.js +11 -3
- package/lib-module/TextInput/TextInputBase.js +2 -2
- package/lib-module/TextInput/propTypes.js +7 -1
- package/lib-module/ToggleSwitch/ToggleSwitch.js +6 -3
- package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +15 -6
- package/lib-module/utils/containUniqueFields.js +26 -0
- package/lib-module/utils/index.js +2 -1
- package/lib-module/utils/props/handlerProps.js +59 -0
- package/lib-module/utils/props/index.js +1 -0
- package/lib-module/utils/props/inputSupportsProps.js +3 -5
- package/lib-module/utils/props/linkProps.js +3 -7
- package/package.json +5 -5
- package/src/Button/ButtonBase.jsx +8 -2
- package/src/Button/ButtonGroup.jsx +51 -34
- package/src/Card/PressableCardBase.jsx +6 -1
- package/src/Checkbox/Checkbox.jsx +35 -23
- package/src/Checkbox/CheckboxGroup.jsx +52 -22
- package/src/ExpandCollapse/Panel.jsx +9 -9
- package/src/FlexGrid/Col/Col.jsx +11 -2
- package/src/FlexGrid/Row/Row.jsx +8 -2
- package/src/HorizontalScroll/HorizontalScroll.jsx +1 -1
- package/src/HorizontalScroll/HorizontalScrollButton.jsx +21 -58
- package/src/InputLabel/InputLabel.jsx +36 -27
- package/src/Link/LinkBase.jsx +20 -4
- package/src/Link/TextButton.jsx +1 -19
- package/src/Modal/Modal.jsx +30 -26
- package/src/Radio/Radio.jsx +26 -14
- package/src/Radio/RadioGroup.jsx +39 -21
- package/src/RadioCard/RadioCard.jsx +6 -1
- package/src/RadioCard/RadioCardGroup.jsx +17 -1
- package/src/Select/Select.jsx +2 -2
- package/src/Tags/Tags.jsx +23 -9
- package/src/TextInput/TextArea.jsx +5 -1
- package/src/TextInput/TextInput.jsx +13 -3
- package/src/TextInput/TextInputBase.jsx +6 -1
- package/src/TextInput/propTypes.js +7 -1
- package/src/ToggleSwitch/ToggleSwitch.jsx +11 -2
- package/src/ToggleSwitch/ToggleSwitchGroup.jsx +19 -6
- package/src/utils/containUniqueFields.js +32 -0
- package/src/utils/index.js +1 -0
- package/src/utils/props/handlerProps.js +47 -0
- package/src/utils/props/index.js +1 -0
- package/src/utils/props/inputSupportsProps.js +3 -4
- package/src/utils/props/linkProps.js +3 -6
- package/stories/InputLabel/InputLabel.stories.jsx +25 -28
- package/stories/Modal/Modal.stories.jsx +25 -0
- package/stories/Search/Search.stories.jsx +4 -1
- package/stories/TextInput/TextInput.stories.jsx +40 -2
- package/__tests__/Link/LinkBase.test.jsx +0 -22
|
@@ -4,11 +4,27 @@ import ABBPropTypes from 'airbnb-prop-types'
|
|
|
4
4
|
|
|
5
5
|
import { useViewport } from '../ViewportProvider'
|
|
6
6
|
import { useThemeTokens } from '../ThemeProvider'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
a11yProps,
|
|
9
|
+
containUniqueFields,
|
|
10
|
+
focusHandlerProps,
|
|
11
|
+
getTokensPropType,
|
|
12
|
+
selectSystemProps,
|
|
13
|
+
useMultipleInputValues,
|
|
14
|
+
variantProp,
|
|
15
|
+
viewProps
|
|
16
|
+
} from '../utils'
|
|
8
17
|
import { getStackedContent } from '../StackView'
|
|
9
18
|
import Checkbox from './Checkbox'
|
|
10
19
|
import Fieldset from '../Fieldset'
|
|
11
20
|
|
|
21
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
22
|
+
const [selectItemProps, selectedItemPropTypes] = selectSystemProps([
|
|
23
|
+
a11yProps,
|
|
24
|
+
focusHandlerProps,
|
|
25
|
+
viewProps
|
|
26
|
+
])
|
|
27
|
+
|
|
12
28
|
/**
|
|
13
29
|
* A group of Checkboxs that behave as a fieldset. Use when users select any number of choices from options.
|
|
14
30
|
*
|
|
@@ -73,7 +89,8 @@ const CheckboxGroup = forwardRef(
|
|
|
73
89
|
onChange,
|
|
74
90
|
readOnly,
|
|
75
91
|
name: inputGroupName,
|
|
76
|
-
inactive
|
|
92
|
+
inactive,
|
|
93
|
+
...rest
|
|
77
94
|
},
|
|
78
95
|
ref
|
|
79
96
|
) => {
|
|
@@ -89,27 +106,37 @@ const CheckboxGroup = forwardRef(
|
|
|
89
106
|
onChange,
|
|
90
107
|
readOnly: readOnly || inactive
|
|
91
108
|
})
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
109
|
+
|
|
110
|
+
const uniqueFields = ['id', 'label']
|
|
111
|
+
if (!containUniqueFields(items, uniqueFields)) {
|
|
112
|
+
throw new Error(`CheckboxGroup items must have unique ${uniqueFields.join(', ')}`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const checkboxes = items.map(
|
|
116
|
+
({ label, id, onChange: itemOnChange, ref: itemRef, ...itemRest }, index) => {
|
|
117
|
+
const checkboxId = id || `Checkbox[${index}]`
|
|
118
|
+
const handleChange = (newCheckedState, event) => {
|
|
119
|
+
if (typeof itemOnChange === 'function') itemOnChange(newCheckedState, event)
|
|
120
|
+
toggleOneValue(checkboxId, event)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<Checkbox
|
|
125
|
+
ref={itemRef}
|
|
126
|
+
key={checkboxId}
|
|
127
|
+
id={checkboxId}
|
|
128
|
+
checked={currentValues.includes(checkboxId)}
|
|
129
|
+
onChange={handleChange}
|
|
130
|
+
inactive={inactive}
|
|
131
|
+
label={label}
|
|
132
|
+
name={inputGroupName}
|
|
133
|
+
tokens={radioTokens}
|
|
134
|
+
variant={variant}
|
|
135
|
+
{...selectItemProps(itemRest)}
|
|
136
|
+
/>
|
|
137
|
+
)
|
|
97
138
|
}
|
|
98
|
-
|
|
99
|
-
<Checkbox
|
|
100
|
-
ref={itemRef}
|
|
101
|
-
key={checkboxId}
|
|
102
|
-
id={checkboxId}
|
|
103
|
-
checked={currentValues.includes(checkboxId)}
|
|
104
|
-
onChange={handleChange}
|
|
105
|
-
inactive={inactive}
|
|
106
|
-
label={label}
|
|
107
|
-
name={inputGroupName}
|
|
108
|
-
tokens={radioTokens}
|
|
109
|
-
variant={variant}
|
|
110
|
-
/>
|
|
111
|
-
)
|
|
112
|
-
})
|
|
139
|
+
)
|
|
113
140
|
|
|
114
141
|
return (
|
|
115
142
|
<Fieldset
|
|
@@ -122,6 +149,7 @@ const CheckboxGroup = forwardRef(
|
|
|
122
149
|
feedback={feedback}
|
|
123
150
|
inactive={inactive}
|
|
124
151
|
validation={validation}
|
|
152
|
+
{...selectProps(rest)}
|
|
125
153
|
>
|
|
126
154
|
{getStackedContent(checkboxes, { space, direction: 'column' })}
|
|
127
155
|
</Fieldset>
|
|
@@ -131,6 +159,7 @@ const CheckboxGroup = forwardRef(
|
|
|
131
159
|
CheckboxGroup.displayName = 'CheckboxGroup'
|
|
132
160
|
|
|
133
161
|
CheckboxGroup.propTypes = {
|
|
162
|
+
...selectedSystemPropTypes,
|
|
134
163
|
/**
|
|
135
164
|
* Optional theme token overrides for the outer CheckboxGroup component
|
|
136
165
|
*/
|
|
@@ -148,6 +177,7 @@ CheckboxGroup.propTypes = {
|
|
|
148
177
|
*/
|
|
149
178
|
items: PropTypes.arrayOf(
|
|
150
179
|
PropTypes.exact({
|
|
180
|
+
...selectedItemPropTypes,
|
|
151
181
|
label: PropTypes.string,
|
|
152
182
|
id: PropTypes.string,
|
|
153
183
|
onChange: PropTypes.func,
|
|
@@ -74,8 +74,8 @@ const ExpandCollapsePanel = forwardRef(
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
const onContainerLayout = (event) => {
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
const { layout: { height = 0 } = {} } = event.nativeEvent
|
|
78
|
+
if (Platform.OS === 'web' || (Platform.OS !== 'web' && containerHeight === null)) {
|
|
79
79
|
setContainerHeight(height)
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -104,14 +104,14 @@ const ExpandCollapsePanel = forwardRef(
|
|
|
104
104
|
>
|
|
105
105
|
{control}
|
|
106
106
|
</ExpandCollapseControl>
|
|
107
|
-
<View
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
>
|
|
107
|
+
<Animated.View
|
|
108
|
+
style={[overflowContainerStyles, animatedStyles, staticStyles.itemsContainer]}
|
|
109
|
+
{...focusabilityProps}
|
|
110
|
+
>
|
|
111
|
+
<View onLayout={onContainerLayout}>
|
|
112
112
|
<View style={selectContainerStyles(themeTokens)}>{children}</View>
|
|
113
|
-
</
|
|
114
|
-
</View>
|
|
113
|
+
</View>
|
|
114
|
+
</Animated.View>
|
|
115
115
|
</View>
|
|
116
116
|
)
|
|
117
117
|
}
|
package/src/FlexGrid/Col/Col.jsx
CHANGED
|
@@ -23,6 +23,7 @@ const Col = forwardRef(
|
|
|
23
23
|
mdOffset,
|
|
24
24
|
lgOffset,
|
|
25
25
|
xlOffset,
|
|
26
|
+
flex,
|
|
26
27
|
...viewProps
|
|
27
28
|
},
|
|
28
29
|
ref
|
|
@@ -106,7 +107,10 @@ const Col = forwardRef(
|
|
|
106
107
|
|
|
107
108
|
let hidingStyles = {}
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
// TODO: consider setting this to always 'flex' in a major release.
|
|
111
|
+
// `display: block` is invalid in native apps.
|
|
112
|
+
// See https://telusdigital.atlassian.net/browse/UDS1-92
|
|
113
|
+
const shown = !flex && Platform.OS === 'web' ? 'block' : 'flex'
|
|
110
114
|
|
|
111
115
|
if (viewPort === viewports.xs) {
|
|
112
116
|
hidingStyles = {
|
|
@@ -267,7 +271,12 @@ Col.propTypes = {
|
|
|
267
271
|
*/
|
|
268
272
|
horizontalAlign: responsiveProps.getTypeOptionallyByViewport(
|
|
269
273
|
PropTypes.oneOf(['left', 'center', 'right'])
|
|
270
|
-
)
|
|
274
|
+
),
|
|
275
|
+
/**
|
|
276
|
+
* (web only) Stretches the column to fill vertical space using `display: flex`.
|
|
277
|
+
* In native apps, FlexGrid.Col behaves as if this is always true (as do all `View`s).
|
|
278
|
+
*/
|
|
279
|
+
flex: PropTypes.bool
|
|
271
280
|
}
|
|
272
281
|
|
|
273
282
|
export default Col
|
package/src/FlexGrid/Row/Row.jsx
CHANGED
|
@@ -72,21 +72,27 @@ const Row = forwardRef(
|
|
|
72
72
|
const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse])
|
|
73
73
|
|
|
74
74
|
let flexDirection = ''
|
|
75
|
+
let flexWrap = ''
|
|
75
76
|
|
|
76
77
|
if (viewPort === viewports.xs) {
|
|
77
78
|
flexDirection = reverseLevel[0] ? 'row-reverse' : 'row'
|
|
79
|
+
flexWrap = reverseLevel[0] ? 'wrap-reverse' : 'wrap'
|
|
78
80
|
}
|
|
79
81
|
if (viewPort === viewports.sm) {
|
|
80
82
|
flexDirection = reverseLevel[1] ? 'row-reverse' : 'row'
|
|
83
|
+
flexWrap = reverseLevel[1] ? 'wrap-reverse' : 'wrap'
|
|
81
84
|
}
|
|
82
85
|
if (viewPort === viewports.md) {
|
|
83
86
|
flexDirection = reverseLevel[2] ? 'row-reverse' : 'row'
|
|
87
|
+
flexWrap = reverseLevel[2] ? 'wrap-reverse' : 'wrap'
|
|
84
88
|
}
|
|
85
89
|
if (viewPort === viewports.lg) {
|
|
86
90
|
flexDirection = reverseLevel[3] ? 'row-reverse' : 'row'
|
|
91
|
+
flexWrap = reverseLevel[3] ? 'wrap-reverse' : 'wrap'
|
|
87
92
|
}
|
|
88
93
|
if (viewPort === viewports.xl) {
|
|
89
94
|
flexDirection = reverseLevel[4] ? 'row-reverse' : 'row'
|
|
95
|
+
flexWrap = reverseLevel[4] ? 'wrap-reverse' : 'wrap'
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
return (
|
|
@@ -97,6 +103,7 @@ const Row = forwardRef(
|
|
|
97
103
|
styles.row,
|
|
98
104
|
{
|
|
99
105
|
flexDirection,
|
|
106
|
+
flexWrap,
|
|
100
107
|
...horizontalAlignStyles(horizontalAlign),
|
|
101
108
|
...verticalAlignStyles(verticalAlign),
|
|
102
109
|
...distributeStyles(distribute)
|
|
@@ -118,8 +125,7 @@ const styles = StyleSheet.create({
|
|
|
118
125
|
flexGrow: 0,
|
|
119
126
|
flexShrink: 1,
|
|
120
127
|
flexBasis: 'auto',
|
|
121
|
-
flexDirection: 'row'
|
|
122
|
-
flexWrap: 'wrap'
|
|
128
|
+
flexDirection: 'row'
|
|
123
129
|
}
|
|
124
130
|
})
|
|
125
131
|
|
|
@@ -129,7 +129,7 @@ const HorizontalScroll = forwardRef(
|
|
|
129
129
|
showsHorizontalScrollIndicator={false}
|
|
130
130
|
contentContainerStyle={[
|
|
131
131
|
staticStyles.scrollContainer,
|
|
132
|
-
{
|
|
132
|
+
{ borderBottomWidth, borderBottomColor }
|
|
133
133
|
]}
|
|
134
134
|
{...selectProps(rest)}
|
|
135
135
|
>
|
|
@@ -1,35 +1,14 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
resolvePressableTokens,
|
|
8
|
-
selectTokens,
|
|
9
|
-
variantProp,
|
|
10
|
-
getTokensPropType,
|
|
11
|
-
useCopy,
|
|
12
|
-
copyPropTypes,
|
|
13
|
-
a11yProps
|
|
14
|
-
} from '../utils'
|
|
15
|
-
import Icon from '../Icon'
|
|
16
|
-
import Typography from '../Typography'
|
|
3
|
+
import { StyleSheet, View } from 'react-native'
|
|
4
|
+
import { variantProp, getTokensPropType, useCopy, copyPropTypes, a11yProps } from '../utils'
|
|
5
|
+
import { useThemeTokens } from '../ThemeProvider'
|
|
6
|
+
import IconButton from '../IconButton'
|
|
17
7
|
import dictionary from './dictionary'
|
|
18
8
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
) => [
|
|
23
|
-
staticStyles.absolute,
|
|
24
|
-
staticStyles[direction],
|
|
25
|
-
{
|
|
26
|
-
borderRadius,
|
|
27
|
-
backgroundColor,
|
|
28
|
-
borderColor,
|
|
29
|
-
borderWidth,
|
|
30
|
-
padding
|
|
31
|
-
}
|
|
32
|
-
]
|
|
9
|
+
const selectContainerStyles = ({ offset }) => ({
|
|
10
|
+
marginTop: offset ? -offset : 0
|
|
11
|
+
})
|
|
33
12
|
|
|
34
13
|
/**
|
|
35
14
|
* Button within a Tabs component showing users that content is available to the left or
|
|
@@ -40,41 +19,25 @@ const selectButtonStyles = (
|
|
|
40
19
|
* @TODO when IconButton is complete and stable revisit this and update interaction state styles.
|
|
41
20
|
*/
|
|
42
21
|
const HorizontalScrollButton = forwardRef(
|
|
43
|
-
({ direction = 'next', icon,
|
|
44
|
-
const
|
|
45
|
-
const resolveButtonTokens = (pressableState) =>
|
|
46
|
-
resolvePressableTokens(getTokens, pressableState)
|
|
47
|
-
const getPressableStyle = (pressableState) => [
|
|
48
|
-
selectButtonStyles(resolveButtonTokens(pressableState), direction),
|
|
49
|
-
{ marginTop: -1 * (offset || 0) }
|
|
50
|
-
]
|
|
51
|
-
|
|
22
|
+
({ direction = 'next', icon, offset, onPress, variant, tokens, copy }, ref) => {
|
|
23
|
+
const themeTokens = useThemeTokens('HorizontalScrollButton', tokens, variant)
|
|
52
24
|
const getCopy = useCopy({ dictionary, copy })
|
|
53
25
|
const label = direction === 'previous' ? getCopy('previousText') : getCopy('nextText')
|
|
54
26
|
|
|
55
27
|
return (
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
style={getPressableStyle}
|
|
59
|
-
onPress={onPress}
|
|
60
|
-
accessibilityLabel={label}
|
|
61
|
-
accessibilityRole="button"
|
|
62
|
-
// For keyboard-tab or screenreader-swipe navigation, users can just go through all items
|
|
63
|
-
{...a11yProps.nonFocusableProps}
|
|
28
|
+
<View
|
|
29
|
+
style={[staticStyles.absolute, staticStyles[direction], selectContainerStyles({ offset })]}
|
|
64
30
|
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
)
|
|
76
|
-
}}
|
|
77
|
-
</Pressable>
|
|
31
|
+
<IconButton
|
|
32
|
+
accessibilityLabel={label}
|
|
33
|
+
icon={icon}
|
|
34
|
+
onPress={onPress}
|
|
35
|
+
ref={ref}
|
|
36
|
+
tokens={themeTokens}
|
|
37
|
+
variant={variant}
|
|
38
|
+
{...a11yProps.nonFocusableProps}
|
|
39
|
+
/>
|
|
40
|
+
</View>
|
|
78
41
|
)
|
|
79
42
|
}
|
|
80
43
|
)
|
|
@@ -47,35 +47,46 @@ const InputLabel = forwardRef(
|
|
|
47
47
|
const isHintInline = hintPosition === 'inline'
|
|
48
48
|
|
|
49
49
|
return (
|
|
50
|
-
|
|
51
|
-
ref={ref}
|
|
52
|
-
style={[staticStyles.container, !isHintInline && staticStyles.containerWithHintBelow]}
|
|
53
|
-
{...selectProps(rest)}
|
|
54
|
-
>
|
|
55
|
-
<Text
|
|
56
|
-
style={[selectLabelStyles(themeTokens), selectGapStyles(themeTokens), staticStyles.label]}
|
|
57
|
-
>
|
|
58
|
-
<LabelContent forId={forId}>{label}</LabelContent>
|
|
59
|
-
</Text>
|
|
60
|
-
{hint && isHintInline && (
|
|
50
|
+
<>
|
|
51
|
+
<View ref={ref} style={staticStyles.container} {...selectProps(rest)}>
|
|
61
52
|
<Text
|
|
62
|
-
style={[
|
|
63
|
-
|
|
53
|
+
style={[
|
|
54
|
+
selectLabelStyles(themeTokens),
|
|
55
|
+
selectGapStyles(themeTokens),
|
|
56
|
+
staticStyles.label
|
|
57
|
+
]}
|
|
64
58
|
>
|
|
65
|
-
{
|
|
59
|
+
<LabelContent forId={forId}>{label}</LabelContent>
|
|
66
60
|
</Text>
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
{hint && isHintInline && (
|
|
62
|
+
<Text
|
|
63
|
+
style={[
|
|
64
|
+
selectHintStyles(themeTokens),
|
|
65
|
+
hasTooltip && selectGapStyles(themeTokens),
|
|
66
|
+
staticStyles.label
|
|
67
|
+
]}
|
|
68
|
+
nativeID={hintId}
|
|
69
|
+
>
|
|
70
|
+
{hint}
|
|
71
|
+
</Text>
|
|
72
|
+
)}
|
|
73
|
+
{hasTooltip && (
|
|
74
|
+
<View
|
|
75
|
+
style={[
|
|
76
|
+
staticStyles.tooltipAlign,
|
|
77
|
+
{ height: themeTokens.fontSize * themeTokens.lineHeight }
|
|
78
|
+
]}
|
|
79
|
+
>
|
|
80
|
+
<Tooltip content={tooltip} />
|
|
81
|
+
</View>
|
|
82
|
+
)}
|
|
83
|
+
</View>
|
|
73
84
|
{hint && !isHintInline && (
|
|
74
85
|
<Text style={[selectHintStyles(themeTokens), staticStyles.hintBelow]} nativeID={hintId}>
|
|
75
86
|
{hint}
|
|
76
87
|
</Text>
|
|
77
88
|
)}
|
|
78
|
-
|
|
89
|
+
</>
|
|
79
90
|
)
|
|
80
91
|
}
|
|
81
92
|
)
|
|
@@ -115,21 +126,19 @@ export default InputLabel
|
|
|
115
126
|
|
|
116
127
|
const staticStyles = StyleSheet.create({
|
|
117
128
|
container: {
|
|
118
|
-
|
|
129
|
+
flexShrink: 1,
|
|
119
130
|
flexDirection: 'row',
|
|
120
131
|
alignItems: 'baseline'
|
|
121
132
|
},
|
|
122
|
-
containerWithHintBelow: {
|
|
123
|
-
flexWrap: 'wrap'
|
|
124
|
-
},
|
|
125
133
|
label: {
|
|
126
|
-
flexShrink:
|
|
134
|
+
flexShrink: 1
|
|
127
135
|
},
|
|
128
136
|
hintBelow: {
|
|
129
137
|
flexBasis: '100%',
|
|
130
138
|
flexShrink: 0
|
|
131
139
|
},
|
|
132
140
|
tooltipAlign: {
|
|
133
|
-
alignSelf: '
|
|
141
|
+
alignSelf: 'flex-start',
|
|
142
|
+
justifyContent: 'center'
|
|
134
143
|
}
|
|
135
144
|
})
|
package/src/Link/LinkBase.jsx
CHANGED
|
@@ -45,10 +45,8 @@ const selectOuterBorderStyles = ({
|
|
|
45
45
|
}
|
|
46
46
|
: {}
|
|
47
47
|
|
|
48
|
-
const selectTextStyles = ({ color
|
|
48
|
+
const selectTextStyles = ({ color }) => ({
|
|
49
49
|
color,
|
|
50
|
-
textDecorationLine: textLine,
|
|
51
|
-
textDecorationStyle: textLineStyle,
|
|
52
50
|
...Platform.select({
|
|
53
51
|
web: {
|
|
54
52
|
// TODO: https://github.com/telus/universal-design-system/issues/487
|
|
@@ -65,6 +63,18 @@ const selectBlockStyles = ({ blockFontWeight, blockFontSize, blockLineHeight, bl
|
|
|
65
63
|
fontName: blockFontName
|
|
66
64
|
})
|
|
67
65
|
|
|
66
|
+
const selectDecorationStyles = ({ color, textLine, textLineStyle }) => ({
|
|
67
|
+
color,
|
|
68
|
+
textDecorationLine: textLine,
|
|
69
|
+
textDecorationStyle: textLineStyle,
|
|
70
|
+
...Platform.select({
|
|
71
|
+
web: {
|
|
72
|
+
// TODO: https://github.com/telus/universal-design-system/issues/487
|
|
73
|
+
transition: 'color 200ms'
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
68
78
|
const selectIconTokens = ({ color, iconSize, iconTranslateX, iconTranslateY }) => ({
|
|
69
79
|
color,
|
|
70
80
|
translateX: iconTranslateX,
|
|
@@ -132,8 +142,14 @@ const LinkBase = forwardRef(
|
|
|
132
142
|
style={(linkState) => {
|
|
133
143
|
const themeTokens = resolveLinkTokens(linkState)
|
|
134
144
|
const outerBorderStyles = selectOuterBorderStyles(themeTokens)
|
|
145
|
+
const decorationStyles = selectDecorationStyles(themeTokens)
|
|
135
146
|
const hasIcon = Boolean(icon || themeTokens.icon)
|
|
136
|
-
return [
|
|
147
|
+
return [
|
|
148
|
+
outerBorderStyles,
|
|
149
|
+
blockLeftStyle,
|
|
150
|
+
decorationStyles,
|
|
151
|
+
hasIcon && staticStyles.rowContainer
|
|
152
|
+
]
|
|
137
153
|
}}
|
|
138
154
|
>
|
|
139
155
|
{(linkState) => {
|
package/src/Link/TextButton.jsx
CHANGED
|
@@ -10,19 +10,7 @@ import LinkBase from './LinkBase'
|
|
|
10
10
|
* take place on the current page, or for navigation within an app.
|
|
11
11
|
*/
|
|
12
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
|
-
) => {
|
|
13
|
+
({ onPress, children, variant, tokens, accessibilityRole = 'button', ...linkProps }, ref) => {
|
|
26
14
|
const getTokens = useThemeTokensCallback('Link', tokens, variant)
|
|
27
15
|
return (
|
|
28
16
|
<LinkBase
|
|
@@ -44,10 +32,4 @@ TextButton.propTypes = {
|
|
|
44
32
|
onPress: PropTypes.func.isRequired
|
|
45
33
|
}
|
|
46
34
|
|
|
47
|
-
// Remove incompatible Link prop (if this build includes propTypes)
|
|
48
|
-
// TODO: test if this works with web navigation in omniplatform React Navigation
|
|
49
|
-
// https://github.com/telus/universal-design-system/issues/665
|
|
50
|
-
// eslint-disable-next-line react/forbid-foreign-prop-types
|
|
51
|
-
if (TextButton.propTypes?.href) delete TextButton.propTypes.href
|
|
52
|
-
|
|
53
35
|
export default TextButton
|
package/src/Modal/Modal.jsx
CHANGED
|
@@ -16,10 +16,11 @@ import {
|
|
|
16
16
|
selectSystemProps,
|
|
17
17
|
useCopy,
|
|
18
18
|
variantProp,
|
|
19
|
-
viewProps
|
|
19
|
+
viewProps,
|
|
20
|
+
selectTokens
|
|
20
21
|
} from '../utils'
|
|
21
22
|
import { useViewport } from '../ViewportProvider'
|
|
22
|
-
import
|
|
23
|
+
import IconButton from '../IconButton'
|
|
23
24
|
import dictionary from './dictionary'
|
|
24
25
|
|
|
25
26
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
@@ -70,11 +71,6 @@ const selectCloseButtonContainerStyles = ({ paddingRight, paddingTop }) => ({
|
|
|
70
71
|
paddingTop
|
|
71
72
|
})
|
|
72
73
|
|
|
73
|
-
const selectCloseIconProps = ({ closeIconSize, closeIconColor }) => ({
|
|
74
|
-
size: closeIconSize,
|
|
75
|
-
color: closeIconColor
|
|
76
|
-
})
|
|
77
|
-
|
|
78
74
|
/**
|
|
79
75
|
* A modal window is a secondary window that opens on top of the main one.
|
|
80
76
|
* Users have to interact with it before they can carry out their task and return to the main window.
|
|
@@ -90,7 +86,7 @@ const selectCloseIconProps = ({ closeIconSize, closeIconColor }) => ({
|
|
|
90
86
|
* - Don’t use modals consecutively
|
|
91
87
|
*/
|
|
92
88
|
const Modal = forwardRef(
|
|
93
|
-
({ children, isOpen, onClose, maxWidth, tokens, variant, copy, ...rest }, ref) => {
|
|
89
|
+
({ children, isOpen, onClose, maxWidth, tokens, variant, copy, closeButton, ...rest }, ref) => {
|
|
94
90
|
const viewport = useViewport()
|
|
95
91
|
const themeTokens = useThemeTokens('Modal', tokens, variant, { viewport, maxWidth })
|
|
96
92
|
|
|
@@ -107,11 +103,14 @@ const Modal = forwardRef(
|
|
|
107
103
|
if (event.key === 'Escape') onClose()
|
|
108
104
|
}
|
|
109
105
|
|
|
106
|
+
// Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
|
|
107
|
+
// Hide the close button if `closeButton` is `null`.
|
|
108
|
+
const showCloseButton = closeButton !== null
|
|
109
|
+
|
|
110
110
|
if (!isOpen) {
|
|
111
111
|
return null
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
// TODO: replace the close button with IconButton when implemented (https://github.com/telus/universal-design-system/issues/281)
|
|
115
114
|
return (
|
|
116
115
|
<NativeModal transparent {...selectProps(rest)}>
|
|
117
116
|
<View style={[staticStyles.positioningContainer]}>
|
|
@@ -124,23 +123,24 @@ const Modal = forwardRef(
|
|
|
124
123
|
style={[staticStyles.modal, selectModalStyles(themeTokens)]}
|
|
125
124
|
onKeyUp={handleKeyUp}
|
|
126
125
|
>
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
<ButtonBase
|
|
134
|
-
onPress={handleClose}
|
|
135
|
-
accessibilityRole="button"
|
|
136
|
-
accessibilityLabel={closeLabel}
|
|
126
|
+
{showCloseButton && (
|
|
127
|
+
<View
|
|
128
|
+
style={[
|
|
129
|
+
staticStyles.closeButtonContainer,
|
|
130
|
+
selectCloseButtonContainerStyles(themeTokens)
|
|
131
|
+
]}
|
|
137
132
|
>
|
|
138
|
-
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
133
|
+
{closeButton || (
|
|
134
|
+
<IconButton
|
|
135
|
+
onPress={handleClose}
|
|
136
|
+
icon={CloseIconComponent}
|
|
137
|
+
accessibilityRole="button"
|
|
138
|
+
accessibilityLabel={closeLabel}
|
|
139
|
+
tokens={selectTokens('IconButton', themeTokens, 'close')}
|
|
140
|
+
/>
|
|
141
|
+
)}
|
|
142
|
+
</View>
|
|
143
|
+
)}
|
|
144
144
|
{children}
|
|
145
145
|
</View>
|
|
146
146
|
</View>
|
|
@@ -164,7 +164,11 @@ Modal.propTypes = {
|
|
|
164
164
|
onClose: PropTypes.func,
|
|
165
165
|
maxWidth: PropTypes.bool,
|
|
166
166
|
tokens: getTokensPropType('Modal'),
|
|
167
|
-
variant: variantProp.propType
|
|
167
|
+
variant: variantProp.propType,
|
|
168
|
+
/**
|
|
169
|
+
* Pass a react node to override the default close button or pass `null` to hide the close button.
|
|
170
|
+
*/
|
|
171
|
+
closeButton: PropTypes.node
|
|
168
172
|
}
|
|
169
173
|
|
|
170
174
|
export default Modal
|