@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
|
@@ -2,12 +2,13 @@ import React, { forwardRef } from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { useViewport } from '../ViewportProvider';
|
|
4
4
|
import { useThemeTokens } from '../ThemeProvider';
|
|
5
|
-
import { a11yProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
5
|
+
import { a11yProps, containUniqueFields, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
6
6
|
import StackView, { StackWrap } from '../StackView';
|
|
7
7
|
import RadioCard from './RadioCard';
|
|
8
8
|
import Fieldset from '../Fieldset';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
10
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
11
|
+
const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
|
|
11
12
|
/**
|
|
12
13
|
* A group of Cards that behave as a radio button group. Use when users select a single choice from mutually
|
|
13
14
|
* exclusive options with need to show additional information for each option. The whole cards are each
|
|
@@ -98,6 +99,12 @@ const RadioCardGroup = /*#__PURE__*/forwardRef(({
|
|
|
98
99
|
// and also needs 'radiogroup' role on fieldset for correct description on focusing the set.
|
|
99
100
|
// TODO: test this on more web screen readers.
|
|
100
101
|
|
|
102
|
+
const uniqueFields = ['id'];
|
|
103
|
+
|
|
104
|
+
if (!containUniqueFields(items, uniqueFields)) {
|
|
105
|
+
throw new Error(`RadioCardGroup items must have unique ${uniqueFields.join(', ')}`);
|
|
106
|
+
}
|
|
107
|
+
|
|
101
108
|
return /*#__PURE__*/_jsx(Fieldset, {
|
|
102
109
|
ref: ref,
|
|
103
110
|
name: inputGroupName,
|
|
@@ -117,7 +124,8 @@ const RadioCardGroup = /*#__PURE__*/forwardRef(({
|
|
|
117
124
|
title,
|
|
118
125
|
content,
|
|
119
126
|
id,
|
|
120
|
-
onChange: itemOnChange
|
|
127
|
+
onChange: itemOnChange,
|
|
128
|
+
...itemRest
|
|
121
129
|
}, index) => {
|
|
122
130
|
const cardId = id || `RadioCard[${index}]`;
|
|
123
131
|
|
|
@@ -136,6 +144,7 @@ const RadioCardGroup = /*#__PURE__*/forwardRef(({
|
|
|
136
144
|
tokens: radioCardTokens,
|
|
137
145
|
variant: variant,
|
|
138
146
|
readOnly: readOnly,
|
|
147
|
+
...selectItemProps(itemRest),
|
|
139
148
|
...props,
|
|
140
149
|
children: content
|
|
141
150
|
}, cardId);
|
|
@@ -164,7 +173,7 @@ RadioCardGroup.propTypes = { ...selectedSystemPropTypes,
|
|
|
164
173
|
/**
|
|
165
174
|
* Array of objects containing specifics for each RadioCard to be rendered in the group.
|
|
166
175
|
*/
|
|
167
|
-
items: PropTypes.arrayOf(PropTypes.exact({
|
|
176
|
+
items: PropTypes.arrayOf(PropTypes.exact({ ...selectedItemPropTypes,
|
|
168
177
|
title: PropTypes.string,
|
|
169
178
|
content: PropTypes.node,
|
|
170
179
|
id: PropTypes.string,
|
|
@@ -197,7 +197,7 @@ const Select = /*#__PURE__*/forwardRef(({
|
|
|
197
197
|
const handleMouseOut = () => setIsHovered(false);
|
|
198
198
|
|
|
199
199
|
const {
|
|
200
|
-
|
|
200
|
+
supportsProps,
|
|
201
201
|
...selectedProps
|
|
202
202
|
} = selectProps(rest);
|
|
203
203
|
const themeTokens = useThemeTokens('Select', tokens, variant, {
|
|
@@ -238,8 +238,7 @@ const Select = /*#__PURE__*/forwardRef(({
|
|
|
238
238
|
}), ValidationIconComponent && /*#__PURE__*/_jsx(View, {
|
|
239
239
|
pointerEvents: "none",
|
|
240
240
|
style: [staticStyles.iconContainer, selectValidationIconContainerStyles(themeTokens)],
|
|
241
|
-
children: /*#__PURE__*/_jsx(ValidationIconComponent, {
|
|
242
|
-
tokens: selectValidationIconTokens(themeTokens)
|
|
241
|
+
children: /*#__PURE__*/_jsx(ValidationIconComponent, { ...selectValidationIconTokens(themeTokens)
|
|
243
242
|
})
|
|
244
243
|
}), IconComponent && Platform.OS !== 'android' &&
|
|
245
244
|
/*#__PURE__*/
|
package/lib-module/Tags/Tags.js
CHANGED
|
@@ -9,11 +9,11 @@ import Icon from '../Icon';
|
|
|
9
9
|
import { StackWrap, getStackedContent } from '../StackView';
|
|
10
10
|
import { useViewport } from '../ViewportProvider';
|
|
11
11
|
import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider';
|
|
12
|
-
import { a11yProps, getTokensPropType, pressProps, selectSystemProps, selectTokens, variantProp, viewProps } from '../utils
|
|
13
|
-
import { useMultipleInputValues } from '../utils/input';
|
|
12
|
+
import { a11yProps, containUniqueFields, focusHandlerProps, getTokensPropType, pressProps, selectSystemProps, selectTokens, useMultipleInputValues, variantProp, viewProps } from '../utils';
|
|
14
13
|
import { getPressHandlersWithArgs } from '../utils/pressability';
|
|
15
14
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps,
|
|
15
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
16
|
+
const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, pressProps, viewProps]);
|
|
17
17
|
|
|
18
18
|
const selectIconTextTokens = ({
|
|
19
19
|
icon,
|
|
@@ -95,6 +95,12 @@ const Tags = /*#__PURE__*/forwardRef(({
|
|
|
95
95
|
...rest
|
|
96
96
|
});
|
|
97
97
|
const itemA11yRole = 'checkbox';
|
|
98
|
+
const uniqueFields = ['id', 'label'];
|
|
99
|
+
|
|
100
|
+
if (!containUniqueFields(items, uniqueFields)) {
|
|
101
|
+
throw new Error(`Tags items must have unique ${uniqueFields.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
98
104
|
return /*#__PURE__*/_jsx(StackWrap, {
|
|
99
105
|
ref: ref,
|
|
100
106
|
...selectedProps,
|
|
@@ -104,8 +110,8 @@ const Tags = /*#__PURE__*/forwardRef(({
|
|
|
104
110
|
children: items.map(({
|
|
105
111
|
label,
|
|
106
112
|
id = label,
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
ref: itemRef,
|
|
114
|
+
...itemRest
|
|
109
115
|
}, index) => {
|
|
110
116
|
const isSelected = currentValues.includes(id); // Pass an object of relevant component state as first argument for any passed-in press handlers
|
|
111
117
|
|
|
@@ -116,17 +122,17 @@ const Tags = /*#__PURE__*/forwardRef(({
|
|
|
116
122
|
}]);
|
|
117
123
|
|
|
118
124
|
const handlePress = event => {
|
|
119
|
-
if (pressHandlers.onPress) pressHandlers.onPress();
|
|
125
|
+
if (pressHandlers.onPress) pressHandlers.onPress(event);
|
|
120
126
|
toggleOneValue(id, event);
|
|
121
127
|
};
|
|
122
128
|
|
|
123
|
-
const
|
|
129
|
+
const itemProps = {
|
|
124
130
|
accessibilityState: {
|
|
125
131
|
checked: isSelected
|
|
126
132
|
},
|
|
127
133
|
accessibilityRole: itemA11yRole,
|
|
128
|
-
|
|
129
|
-
...
|
|
134
|
+
...a11yProps.getPositionInSet(items.length, index),
|
|
135
|
+
...selectItemProps(itemRest)
|
|
130
136
|
};
|
|
131
137
|
return /*#__PURE__*/_jsx(ButtonBase, {
|
|
132
138
|
ref: itemRef,
|
|
@@ -135,7 +141,7 @@ const Tags = /*#__PURE__*/forwardRef(({
|
|
|
135
141
|
tokens: getButtonTokens,
|
|
136
142
|
selected: isSelected,
|
|
137
143
|
inactive: inactive,
|
|
138
|
-
...
|
|
144
|
+
...itemProps,
|
|
139
145
|
children: ({
|
|
140
146
|
textStyles,
|
|
141
147
|
...buttonState
|
|
@@ -188,7 +194,8 @@ Tags.propTypes = { ...selectedSystemPropTypes,
|
|
|
188
194
|
/**
|
|
189
195
|
* The options a user may select
|
|
190
196
|
*/
|
|
191
|
-
items: PropTypes.arrayOf(PropTypes.shape({
|
|
197
|
+
items: PropTypes.arrayOf(PropTypes.shape({ ...selectedItemPropTypes,
|
|
198
|
+
|
|
192
199
|
/**
|
|
193
200
|
* The text displayed to the user in the button, describing this option,
|
|
194
201
|
* passed to the button as its child.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { forwardRef, useState } from 'react';
|
|
2
2
|
import Platform from "react-native-web/dist/exports/Platform";
|
|
3
|
-
import { a11yProps, getTokensPropType, inputSupportsProps, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
3
|
+
import { a11yProps, focusHandlerProps, getTokensPropType, inputSupportsProps, selectSystemProps, textInputHandlerProps, variantProp, viewProps } from '../utils';
|
|
4
4
|
import InputSupports from '../InputSupports';
|
|
5
5
|
import TextInputBase from './TextInputBase';
|
|
6
6
|
import { useThemeTokens } from '../ThemeProvider';
|
|
7
7
|
import textInputPropTypes from './propTypes';
|
|
8
8
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, inputSupportsProps, viewProps]);
|
|
9
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, inputSupportsProps, textInputHandlerProps, viewProps]);
|
|
10
10
|
/**
|
|
11
11
|
* Use to collect long-form information such as product feedback or support queries.
|
|
12
12
|
* Due to React Native's implementation of `TextInput` it's not possible to access the current value by passing a ref.
|
|
@@ -54,7 +54,7 @@ const TextArea = /*#__PURE__*/forwardRef(({
|
|
|
54
54
|
};
|
|
55
55
|
|
|
56
56
|
const {
|
|
57
|
-
|
|
57
|
+
supportsProps,
|
|
58
58
|
...selectedProps
|
|
59
59
|
} = selectProps(rest);
|
|
60
60
|
const inputProps = { ...selectedProps,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react';
|
|
2
|
-
import
|
|
2
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
3
|
+
import { a11yProps, focusHandlerProps, getTokensPropType, inputSupportsProps, selectSystemProps, textInputHandlerProps, variantProp, viewProps } from '../utils';
|
|
3
4
|
import InputSupports from '../InputSupports';
|
|
4
5
|
import TextInputBase from './TextInputBase';
|
|
5
6
|
import textInputPropTypes from './propTypes';
|
|
6
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, inputSupportsProps, viewProps]);
|
|
8
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, inputSupportsProps, textInputHandlerProps, viewProps]);
|
|
8
9
|
/**
|
|
9
10
|
* A basic text input component. Use in forms or individually to receive user's input.
|
|
10
11
|
* Due to React Native's implementation of `TextInput` it's not possible to access the current value by passing a ref.
|
|
@@ -27,10 +28,17 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, inp
|
|
|
27
28
|
const TextInput = /*#__PURE__*/forwardRef(({
|
|
28
29
|
tokens,
|
|
29
30
|
variant = {},
|
|
31
|
+
pattern,
|
|
30
32
|
...rest
|
|
31
33
|
}, ref) => {
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
if (Platform.OS === 'web' && pattern && ref.current) {
|
|
36
|
+
// eslint-disable-next-line no-param-reassign
|
|
37
|
+
ref.current.pattern = pattern;
|
|
38
|
+
}
|
|
39
|
+
}, [ref, pattern]);
|
|
32
40
|
const {
|
|
33
|
-
|
|
41
|
+
supportsProps,
|
|
34
42
|
...selectedProps
|
|
35
43
|
} = selectProps(rest);
|
|
36
44
|
const inputProps = { ...selectedProps,
|
|
@@ -5,10 +5,10 @@ import NativeTextInput from "react-native-web/dist/exports/TextInput";
|
|
|
5
5
|
import View from "react-native-web/dist/exports/View";
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
7
|
import { applyTextStyles, useThemeTokens, applyOuterBorder } from '../ThemeProvider';
|
|
8
|
-
import { a11yProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
8
|
+
import { a11yProps, getTokensPropType, selectSystemProps, textInputHandlerProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
10
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
11
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, textInputHandlerProps, viewProps]);
|
|
12
12
|
|
|
13
13
|
const selectInputStyles = ({
|
|
14
14
|
backgroundColor,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
2
3
|
const textInputPropTypes = {
|
|
3
4
|
/**
|
|
4
5
|
* If the input's state is to be controlled by a parent component, use this prop
|
|
@@ -26,6 +27,11 @@ const textInputPropTypes = {
|
|
|
26
27
|
* Use to react upon input's value changes. Required when the `value` prop is set.
|
|
27
28
|
* Will receive the input's value as an argument.
|
|
28
29
|
*/
|
|
29
|
-
onChange: PropTypes.func
|
|
30
|
+
onChange: PropTypes.func,
|
|
31
|
+
...Platform.select({
|
|
32
|
+
web: {
|
|
33
|
+
pattern: PropTypes.string
|
|
34
|
+
}
|
|
35
|
+
})
|
|
30
36
|
};
|
|
31
37
|
export default textInputPropTypes;
|
|
@@ -7,11 +7,11 @@ import InputLabel from '../InputLabel';
|
|
|
7
7
|
import ButtonBase from '../Button/ButtonBase';
|
|
8
8
|
import StackView from '../StackView';
|
|
9
9
|
import { useThemeTokensCallback, applyShadowToken } from '../ThemeProvider';
|
|
10
|
-
import { a11yProps, getTokensPropType, selectTokens, pressProps, selectSystemProps, useUniqueId, variantProp, viewProps } from '../utils';
|
|
10
|
+
import { a11yProps, focusHandlerProps, getTokensPropType, selectTokens, pressProps, selectSystemProps, useUniqueId, variantProp, viewProps } from '../utils';
|
|
11
11
|
import { useInputValue } from '../utils/input';
|
|
12
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, pressProps, viewProps]);
|
|
14
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, pressProps, viewProps]);
|
|
15
15
|
|
|
16
16
|
const selectButtonTokens = tokens => selectTokens('Button', { ...tokens,
|
|
17
17
|
// Width tokens are applied to our inner track. Disable Button width token so it wraps our track width.
|
|
@@ -117,7 +117,7 @@ const ToggleSwitch = /*#__PURE__*/forwardRef(({
|
|
|
117
117
|
space: 2,
|
|
118
118
|
direction: "row",
|
|
119
119
|
children: [Boolean(label) && /*#__PURE__*/_jsx(View, {
|
|
120
|
-
style: selectLabelStyles(themeTokens),
|
|
120
|
+
style: [selectLabelStyles(themeTokens), staticStyles.containText],
|
|
121
121
|
children: /*#__PURE__*/_jsx(InputLabel, {
|
|
122
122
|
forId: inputId,
|
|
123
123
|
label: label,
|
|
@@ -219,6 +219,9 @@ const staticStyles = StyleSheet.create({
|
|
|
219
219
|
switch: {
|
|
220
220
|
alignItems: 'center',
|
|
221
221
|
justifyContent: 'center'
|
|
222
|
+
},
|
|
223
|
+
containText: {
|
|
224
|
+
flexShrink: 1
|
|
222
225
|
}
|
|
223
226
|
});
|
|
224
227
|
export default ToggleSwitch;
|
|
@@ -7,10 +7,10 @@ import Fieldset from '../Fieldset';
|
|
|
7
7
|
import { getStackedContent } from '../StackView';
|
|
8
8
|
import { useViewport } from '../ViewportProvider';
|
|
9
9
|
import { useThemeTokens } from '../ThemeProvider';
|
|
10
|
-
import { a11yProps,
|
|
11
|
-
import { useMultipleInputValues } from '../utils/input';
|
|
10
|
+
import { a11yProps, containUniqueFields, focusHandlerProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps } from '../utils';
|
|
12
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps,
|
|
12
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
13
|
+
const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
|
|
14
14
|
const ToggleSwitchGroup = /*#__PURE__*/forwardRef(({
|
|
15
15
|
variant,
|
|
16
16
|
tokens,
|
|
@@ -57,13 +57,20 @@ const ToggleSwitchGroup = /*#__PURE__*/forwardRef(({
|
|
|
57
57
|
...rest
|
|
58
58
|
});
|
|
59
59
|
const itemA11yRole = selectedProps.accessibilityRole === 'radiogroup' ? 'radio' : 'switch';
|
|
60
|
+
const uniqueFields = ['id', 'label'];
|
|
61
|
+
|
|
62
|
+
if (!containUniqueFields(items, uniqueFields)) {
|
|
63
|
+
throw new Error(`ToggleSwitchGroup items must have unique ${uniqueFields.join(', ')}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
60
66
|
const toggleSwitches = items.map(({
|
|
61
67
|
label,
|
|
62
68
|
id = label,
|
|
63
69
|
accessibilityLabel = label,
|
|
64
70
|
onChange: itemOnChange,
|
|
65
71
|
ref: itemRef,
|
|
66
|
-
tooltip: itemTooltip
|
|
72
|
+
tooltip: itemTooltip,
|
|
73
|
+
...itemRest
|
|
67
74
|
}, index) => {
|
|
68
75
|
const isSelected = currentValues.includes(id);
|
|
69
76
|
|
|
@@ -89,7 +96,8 @@ const ToggleSwitchGroup = /*#__PURE__*/forwardRef(({
|
|
|
89
96
|
inactive: inactive,
|
|
90
97
|
label: label,
|
|
91
98
|
tooltip: itemTooltip,
|
|
92
|
-
...itemA11y
|
|
99
|
+
...itemA11y,
|
|
100
|
+
...selectItemProps(itemRest)
|
|
93
101
|
}, id);
|
|
94
102
|
});
|
|
95
103
|
return /*#__PURE__*/_jsx(Fieldset, {
|
|
@@ -123,7 +131,8 @@ ToggleSwitchGroup.propTypes = { ...selectedSystemPropTypes,
|
|
|
123
131
|
/**
|
|
124
132
|
* The options a user may select
|
|
125
133
|
*/
|
|
126
|
-
items: PropTypes.arrayOf(PropTypes.shape({
|
|
134
|
+
items: PropTypes.arrayOf(PropTypes.shape({ ...selectedItemPropTypes,
|
|
135
|
+
|
|
127
136
|
/**
|
|
128
137
|
* The text displayed to the user on the label.
|
|
129
138
|
*/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Returns true if there are no duplicate values of the fields listed
|
|
2
|
+
// in the `fields` array across the objects in the `items` array, false
|
|
3
|
+
// otherwise.
|
|
4
|
+
// Note that if a value of a field in an item is not set, it will be
|
|
5
|
+
// excluded from comparison.
|
|
6
|
+
const containUniqueFields = (items, fields) => {
|
|
7
|
+
const map = [];
|
|
8
|
+
const itemsHaveDuplicateFields = items.some(item => fields.some(field => {
|
|
9
|
+
if (!map[field]) {
|
|
10
|
+
map[field] = [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!item[field]) {
|
|
14
|
+
// We exclude empty values from comparison
|
|
15
|
+
return false;
|
|
16
|
+
} // Duplicate found!
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if (map[field][item[field]]) return true;
|
|
20
|
+
map[field][item[field]] = true;
|
|
21
|
+
return false;
|
|
22
|
+
}));
|
|
23
|
+
return !itemsHaveDuplicateFields;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default containUniqueFields;
|
|
@@ -12,4 +12,5 @@ export { default as useResponsiveProp } from './useResponsiveProp';
|
|
|
12
12
|
export * from './useResponsiveProp';
|
|
13
13
|
export { default as useUniqueId } from './useUniqueId';
|
|
14
14
|
export { default as withLinkRouter } from './withLinkRouter';
|
|
15
|
-
export * from './ssr';
|
|
15
|
+
export * from './ssr';
|
|
16
|
+
export { default as containUniqueFields } from './containUniqueFields';
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
export const focusHandlerProps = {
|
|
3
|
+
types: {
|
|
4
|
+
/**
|
|
5
|
+
* onBlur handler
|
|
6
|
+
*/
|
|
7
|
+
onBlur: PropTypes.func,
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* onFocus handler
|
|
11
|
+
*/
|
|
12
|
+
onFocus: PropTypes.func
|
|
13
|
+
},
|
|
14
|
+
select: ({
|
|
15
|
+
onBlur,
|
|
16
|
+
onFocus
|
|
17
|
+
}) => ({
|
|
18
|
+
onBlur,
|
|
19
|
+
onFocus
|
|
20
|
+
})
|
|
21
|
+
};
|
|
22
|
+
export const textInputHandlerProps = {
|
|
23
|
+
types: {
|
|
24
|
+
/**
|
|
25
|
+
* onChange handler
|
|
26
|
+
*/
|
|
27
|
+
onChange: PropTypes.func,
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* onChangeText handler
|
|
31
|
+
*/
|
|
32
|
+
onChangeText: PropTypes.func,
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* onSubmit handler
|
|
36
|
+
*/
|
|
37
|
+
onSubmit: PropTypes.func,
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* onSubmitEditing handler
|
|
41
|
+
*/
|
|
42
|
+
onSubmitEditing: PropTypes.func
|
|
43
|
+
},
|
|
44
|
+
select: ({
|
|
45
|
+
onChange,
|
|
46
|
+
onChangeText,
|
|
47
|
+
onSubmit,
|
|
48
|
+
onSubmitEditing
|
|
49
|
+
}) => ({
|
|
50
|
+
onChange,
|
|
51
|
+
onChangeText,
|
|
52
|
+
onSubmit,
|
|
53
|
+
onSubmitEditing
|
|
54
|
+
})
|
|
55
|
+
};
|
|
56
|
+
export default {
|
|
57
|
+
focusHandlerProps,
|
|
58
|
+
textInputHandlerProps
|
|
59
|
+
};
|
|
@@ -38,17 +38,15 @@ export default {
|
|
|
38
38
|
hintPosition,
|
|
39
39
|
feedback,
|
|
40
40
|
tooltip,
|
|
41
|
-
validation
|
|
42
|
-
...rest
|
|
41
|
+
validation
|
|
43
42
|
}) => ({
|
|
44
|
-
|
|
43
|
+
supportsProps: {
|
|
45
44
|
label,
|
|
46
45
|
hint,
|
|
47
46
|
hintPosition,
|
|
48
47
|
feedback,
|
|
49
48
|
tooltip,
|
|
50
49
|
validation
|
|
51
|
-
}
|
|
52
|
-
...rest
|
|
50
|
+
}
|
|
53
51
|
})
|
|
54
52
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telus-uds/components-base",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Base components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"base"
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test": "jest",
|
|
25
|
-
"lint": "
|
|
26
|
-
"lint:fix": "
|
|
25
|
+
"lint": "yarn --cwd ../.. lint:path --color packages/components-base",
|
|
26
|
+
"lint:fix": "yarn --cwd ../.. lint:path --fix packages/components-base",
|
|
27
27
|
"format": "prettier --write .",
|
|
28
28
|
"build": "yarn build:code && yarn build:docs",
|
|
29
29
|
"build:main": "babel src -d lib",
|
|
30
30
|
"build:module": "babel src -d lib-module --env-name module",
|
|
31
31
|
"build:code": "yarn build:main && yarn build:module",
|
|
32
|
-
"build:docs": "babel-node --plugins
|
|
32
|
+
"build:docs": "babel-node --plugins=@nearform/babel-plugin-react-docgen generate-component-docs.js",
|
|
33
33
|
"storybook": "start-storybook",
|
|
34
34
|
"dev": "yarn build:code --watch",
|
|
35
35
|
"release": "standard-version"
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"dependencies": {
|
|
60
60
|
"airbnb-prop-types": "^2.16.0",
|
|
61
61
|
"@telus-uds/system-constants": "^1.0.2",
|
|
62
|
-
"@telus-uds/system-theme-tokens": "^1.
|
|
62
|
+
"@telus-uds/system-theme-tokens": "^1.5.0",
|
|
63
63
|
"lodash.debounce": "^4.0.8",
|
|
64
64
|
"lodash.merge": "^4.6.2",
|
|
65
65
|
"prop-types": "^15.7.2",
|
|
@@ -6,8 +6,9 @@ import { applyTextStyles, applyShadowToken, applyOuterBorder } from '../ThemePro
|
|
|
6
6
|
import buttonPropTypes from './propTypes'
|
|
7
7
|
import {
|
|
8
8
|
a11yProps,
|
|
9
|
-
getCursorStyle,
|
|
10
9
|
clickProps,
|
|
10
|
+
focusHandlerProps,
|
|
11
|
+
getCursorStyle,
|
|
11
12
|
linkProps,
|
|
12
13
|
resolvePressableState,
|
|
13
14
|
resolvePressableTokens,
|
|
@@ -17,7 +18,12 @@ import {
|
|
|
17
18
|
withLinkRouter
|
|
18
19
|
} from '../utils'
|
|
19
20
|
|
|
20
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
21
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
22
|
+
a11yProps,
|
|
23
|
+
focusHandlerProps,
|
|
24
|
+
linkProps,
|
|
25
|
+
viewProps
|
|
26
|
+
])
|
|
21
27
|
|
|
22
28
|
const getOuterBorderOffset = ({ outerBorderGap = 0, outerBorderWidth = 0 }) =>
|
|
23
29
|
outerBorderGap + outerBorderWidth
|
|
@@ -9,17 +9,25 @@ import { useViewport } from '../ViewportProvider'
|
|
|
9
9
|
import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider'
|
|
10
10
|
import {
|
|
11
11
|
a11yProps,
|
|
12
|
+
containUniqueFields,
|
|
13
|
+
focusHandlerProps,
|
|
12
14
|
pressProps,
|
|
13
15
|
getTokensPropType,
|
|
14
16
|
selectSystemProps,
|
|
15
17
|
selectTokens,
|
|
18
|
+
useMultipleInputValues,
|
|
16
19
|
variantProp,
|
|
17
20
|
viewProps
|
|
18
|
-
} from '../utils
|
|
19
|
-
import { useMultipleInputValues } from '../utils/input'
|
|
21
|
+
} from '../utils'
|
|
20
22
|
import { getPressHandlersWithArgs } from '../utils/pressability'
|
|
21
23
|
|
|
22
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps,
|
|
24
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
25
|
+
const [selectItemProps, selectedItemPropTypes] = selectSystemProps([
|
|
26
|
+
a11yProps,
|
|
27
|
+
focusHandlerProps,
|
|
28
|
+
pressProps,
|
|
29
|
+
viewProps
|
|
30
|
+
])
|
|
23
31
|
|
|
24
32
|
const ButtonGroup = forwardRef(
|
|
25
33
|
(
|
|
@@ -61,6 +69,11 @@ const ButtonGroup = forwardRef(
|
|
|
61
69
|
})
|
|
62
70
|
const itemA11yRole = systemProps.accessibilityRole === 'radiogroup' ? 'radio' : 'checkbox'
|
|
63
71
|
|
|
72
|
+
const uniqueFields = ['id', 'label']
|
|
73
|
+
if (!containUniqueFields(items, uniqueFields)) {
|
|
74
|
+
throw new Error(`ButtonGroup items must have unique ${uniqueFields.join(', ')}`)
|
|
75
|
+
}
|
|
76
|
+
|
|
64
77
|
return (
|
|
65
78
|
<StackWrap
|
|
66
79
|
{...systemProps}
|
|
@@ -69,41 +82,44 @@ const ButtonGroup = forwardRef(
|
|
|
69
82
|
tokens={stackTokens}
|
|
70
83
|
ref={ref}
|
|
71
84
|
>
|
|
72
|
-
{items.map(
|
|
73
|
-
|
|
85
|
+
{items.map(
|
|
86
|
+
({ label, id = label, accessibilityLabel, ref: itemRef, ...itemRest }, index) => {
|
|
87
|
+
const isSelected = currentValues.includes(id)
|
|
74
88
|
|
|
75
|
-
|
|
76
|
-
|
|
89
|
+
// Pass an object of relevant component state as first argument for any passed-in press handlers
|
|
90
|
+
const pressHandlers = getPressHandlersWithArgs(rest, [{ id, label, currentValues }])
|
|
77
91
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
92
|
+
const handlePress = (event) => {
|
|
93
|
+
if (pressHandlers.onPress) pressHandlers.onPress(event)
|
|
94
|
+
toggleOneValue(id, event)
|
|
95
|
+
}
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
97
|
+
const itemA11y = {
|
|
98
|
+
accessibilityState: { checked: isSelected },
|
|
99
|
+
accessibilityRole: itemA11yRole,
|
|
100
|
+
accessibilityLabel,
|
|
101
|
+
...a11yProps.getPositionInSet(items.length, index)
|
|
102
|
+
}
|
|
89
103
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
// Ensure button is direct child of group as MacOS voiceover only applies "X of Y" to
|
|
105
|
+
// "radio" if it's a direct child of "radiogroup", even if aria-posinset etc exists
|
|
106
|
+
return (
|
|
107
|
+
<ButtonBase
|
|
108
|
+
ref={itemRef}
|
|
109
|
+
key={id}
|
|
110
|
+
{...pressHandlers}
|
|
111
|
+
onPress={handlePress}
|
|
112
|
+
tokens={getButtonTokens}
|
|
113
|
+
selected={isSelected}
|
|
114
|
+
inactive={inactive}
|
|
115
|
+
{...itemA11y}
|
|
116
|
+
{...selectItemProps(itemRest)}
|
|
117
|
+
>
|
|
118
|
+
{label}
|
|
119
|
+
</ButtonBase>
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
)}
|
|
107
123
|
</StackWrap>
|
|
108
124
|
)
|
|
109
125
|
}
|
|
@@ -124,6 +140,7 @@ ButtonGroup.propTypes = {
|
|
|
124
140
|
*/
|
|
125
141
|
items: PropTypes.arrayOf(
|
|
126
142
|
PropTypes.shape({
|
|
143
|
+
...selectedItemPropTypes,
|
|
127
144
|
/**
|
|
128
145
|
* The text displayed to the user in the button, describing this option,
|
|
129
146
|
* passed to the button as its child.
|
|
@@ -7,6 +7,7 @@ import { applyOuterBorder, validateThemeTokens } from '../ThemeProvider'
|
|
|
7
7
|
import {
|
|
8
8
|
a11yProps,
|
|
9
9
|
clickProps,
|
|
10
|
+
focusHandlerProps,
|
|
10
11
|
getTokenNames,
|
|
11
12
|
getTokensSetPropType,
|
|
12
13
|
linkProps,
|
|
@@ -20,7 +21,11 @@ import {
|
|
|
20
21
|
} from '../utils'
|
|
21
22
|
import CardBase from './CardBase'
|
|
22
23
|
|
|
23
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
24
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
25
|
+
a11yProps,
|
|
26
|
+
focusHandlerProps,
|
|
27
|
+
viewProps
|
|
28
|
+
])
|
|
24
29
|
|
|
25
30
|
const tokenKeys = [
|
|
26
31
|
...getTokenNames('Card'),
|