@telus-uds/components-base 1.5.0 → 1.6.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/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-lint.log +13 -0
- package/CHANGELOG.json +98 -1
- package/CHANGELOG.md +24 -2
- package/__tests__/FlexGrid/Row.test.jsx +100 -25
- package/__tests__/utils/containUniqueFields.test.js +25 -0
- package/component-docs.json +18 -2
- 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/InputLabel/InputLabel.js +27 -25
- package/lib/Link/LinkBase.js +19 -6
- 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-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/InputLabel/InputLabel.js +28 -25
- package/lib-module/Link/LinkBase.js +19 -6
- 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/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/InputLabel/InputLabel.jsx +36 -27
- package/src/Link/LinkBase.jsx +20 -4
- 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/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
|
@@ -9,6 +9,7 @@ import StackView from '../StackView'
|
|
|
9
9
|
import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider'
|
|
10
10
|
import {
|
|
11
11
|
a11yProps,
|
|
12
|
+
focusHandlerProps,
|
|
12
13
|
getTokensPropType,
|
|
13
14
|
selectSystemProps,
|
|
14
15
|
useInputValue,
|
|
@@ -17,7 +18,11 @@ import {
|
|
|
17
18
|
} from '../utils'
|
|
18
19
|
import useUniqueId from '../utils/useUniqueId'
|
|
19
20
|
|
|
20
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
21
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
22
|
+
a11yProps,
|
|
23
|
+
focusHandlerProps,
|
|
24
|
+
viewProps
|
|
25
|
+
])
|
|
21
26
|
|
|
22
27
|
const selectInputStyles = (
|
|
23
28
|
{
|
|
@@ -179,32 +184,38 @@ const Checkbox = forwardRef(
|
|
|
179
184
|
{({ focused: focus, hovered: hover, pressed }) => {
|
|
180
185
|
const { icon: IconComponent, ...stateTokens } = getTokens({ focus, hover, pressed })
|
|
181
186
|
const iconTokens = selectIconTokens(stateTokens)
|
|
187
|
+
const labelStyles = selectLabelStyles(stateTokens)
|
|
188
|
+
const alignWithLabel = label
|
|
189
|
+
? [staticStyles.alignWithLabel, { height: labelStyles.lineHeight }]
|
|
190
|
+
: null
|
|
182
191
|
|
|
183
192
|
return (
|
|
184
193
|
<View style={staticStyles.container}>
|
|
185
|
-
<View
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
194
|
+
<View style={alignWithLabel}>
|
|
195
|
+
<View
|
|
196
|
+
style={[
|
|
197
|
+
staticStyles.defaultInputStyles,
|
|
198
|
+
selectInputStyles(stateTokens, isChecked)
|
|
199
|
+
]}
|
|
200
|
+
testID="Checkbox-Input"
|
|
201
|
+
>
|
|
202
|
+
{/* Add a real input on Web, skip on native platforms */}
|
|
203
|
+
<CheckboxInput
|
|
204
|
+
checked={isChecked}
|
|
205
|
+
defaultChecked={defaultChecked}
|
|
206
|
+
disabled={inactive}
|
|
207
|
+
id={inputId}
|
|
208
|
+
isControlled={isControlled}
|
|
209
|
+
name={name}
|
|
210
|
+
value={value}
|
|
211
|
+
/>
|
|
212
|
+
{isChecked && IconComponent && (
|
|
213
|
+
<IconComponent {...iconTokens} testID="Checkbox-Icon" />
|
|
214
|
+
)}
|
|
215
|
+
</View>
|
|
205
216
|
</View>
|
|
206
217
|
{Boolean(label) && (
|
|
207
|
-
<Text style={
|
|
218
|
+
<Text style={labelStyles}>
|
|
208
219
|
<CheckboxLabel forId={inputId}>{label}</CheckboxLabel>
|
|
209
220
|
</Text>
|
|
210
221
|
)}
|
|
@@ -285,5 +296,6 @@ export default Checkbox
|
|
|
285
296
|
const staticStyles = StyleSheet.create({
|
|
286
297
|
wrapper: { backgroundColor: 'transparent' },
|
|
287
298
|
container: { flexDirection: 'row', alignItems: 'center' },
|
|
288
|
-
defaultInputStyles: { alignItems: 'center', justifyContent: 'center' }
|
|
299
|
+
defaultInputStyles: { alignItems: 'center', justifyContent: 'center' },
|
|
300
|
+
alignWithLabel: { alignSelf: 'flex-start', justifyContent: 'center' }
|
|
289
301
|
})
|
|
@@ -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
|
|
|
@@ -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/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
|
package/src/Radio/Radio.jsx
CHANGED
|
@@ -7,6 +7,7 @@ import RadioButton, { selectRadioButtonTokens } from './RadioButton'
|
|
|
7
7
|
import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider'
|
|
8
8
|
import {
|
|
9
9
|
a11yProps,
|
|
10
|
+
focusHandlerProps,
|
|
10
11
|
getTokensPropType,
|
|
11
12
|
selectSystemProps,
|
|
12
13
|
useInputValue,
|
|
@@ -16,7 +17,11 @@ import {
|
|
|
16
17
|
} from '../utils'
|
|
17
18
|
import StackView from '../StackView'
|
|
18
19
|
|
|
19
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
20
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
21
|
+
a11yProps,
|
|
22
|
+
focusHandlerProps,
|
|
23
|
+
viewProps
|
|
24
|
+
])
|
|
20
25
|
|
|
21
26
|
const selectContainerStyles = ({
|
|
22
27
|
containerBackgroundColor,
|
|
@@ -154,23 +159,29 @@ const Radio = forwardRef(
|
|
|
154
159
|
>
|
|
155
160
|
{({ focused: focus, hovered: hover, pressed }) => {
|
|
156
161
|
const stateTokens = getTokens({ focus, hover, pressed })
|
|
162
|
+
const labelStyles = selectLabelStyles(stateTokens)
|
|
163
|
+
const alignWithLabel = label
|
|
164
|
+
? [staticStyles.alignWithLabel, { height: labelStyles.lineHeight }]
|
|
165
|
+
: null
|
|
157
166
|
|
|
158
167
|
return (
|
|
159
168
|
<StackView space={0}>
|
|
160
169
|
<View style={[staticStyles.container, selectContainerStyles(stateTokens)]}>
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
<View style={alignWithLabel}>
|
|
171
|
+
<RadioButton
|
|
172
|
+
tokens={selectRadioButtonTokens(stateTokens)}
|
|
173
|
+
isControlled={isControlled}
|
|
174
|
+
isChecked={isChecked}
|
|
175
|
+
inactive={inactive}
|
|
176
|
+
defaultChecked={defaultChecked}
|
|
177
|
+
inputId={inputId}
|
|
178
|
+
handleChange={handleChange}
|
|
179
|
+
name={inputName}
|
|
180
|
+
value={value}
|
|
181
|
+
/>
|
|
182
|
+
</View>
|
|
172
183
|
{Boolean(label) && (
|
|
173
|
-
<Text style={
|
|
184
|
+
<Text style={labelStyles}>
|
|
174
185
|
<RadioLabel forId={inputId}>{label}</RadioLabel>
|
|
175
186
|
</Text>
|
|
176
187
|
)}
|
|
@@ -242,5 +253,6 @@ Radio.propTypes = {
|
|
|
242
253
|
export default Radio
|
|
243
254
|
|
|
244
255
|
const staticStyles = StyleSheet.create({
|
|
245
|
-
container: { flexDirection: 'row', alignItems: 'center' }
|
|
256
|
+
container: { flexDirection: 'row', alignItems: 'center' },
|
|
257
|
+
alignWithLabel: { alignSelf: 'flex-start', justifyContent: 'center' }
|
|
246
258
|
})
|