@telus-uds/components-base 1.3.1 → 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.
Files changed (105) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/.turbo/turbo-lint.log +13 -0
  3. package/CHANGELOG.json +142 -1
  4. package/CHANGELOG.md +51 -2
  5. package/__tests__/FlexGrid/Row.test.jsx +100 -25
  6. package/__tests__/utils/containUniqueFields.test.js +25 -0
  7. package/component-docs.json +50 -15
  8. package/lib/Button/ButtonBase.js +1 -1
  9. package/lib/Button/ButtonGroup.js +20 -12
  10. package/lib/Card/PressableCardBase.js +1 -1
  11. package/lib/Checkbox/Checkbox.js +27 -16
  12. package/lib/Checkbox/CheckboxGroup.js +19 -5
  13. package/lib/ExpandCollapse/Panel.js +10 -10
  14. package/lib/FlexGrid/Col/Col.js +13 -3
  15. package/lib/FlexGrid/Row/Row.js +8 -2
  16. package/lib/HorizontalScroll/HorizontalScroll.js +0 -1
  17. package/lib/HorizontalScroll/HorizontalScrollButton.js +23 -49
  18. package/lib/InputLabel/InputLabel.js +27 -25
  19. package/lib/Link/LinkBase.js +19 -6
  20. package/lib/Modal/Modal.js +18 -18
  21. package/lib/Notification/Notification.js +5 -6
  22. package/lib/Radio/Radio.js +23 -12
  23. package/lib/Radio/RadioGroup.js +12 -3
  24. package/lib/RadioCard/RadioCard.js +1 -1
  25. package/lib/RadioCard/RadioCardGroup.js +11 -2
  26. package/lib/Select/Select.js +2 -3
  27. package/lib/Tags/Tags.js +23 -17
  28. package/lib/TextInput/TextArea.js +2 -2
  29. package/lib/TextInput/TextInput.js +12 -2
  30. package/lib/TextInput/TextInputBase.js +1 -1
  31. package/lib/TextInput/propTypes.js +8 -1
  32. package/lib/ToggleSwitch/ToggleSwitch.js +5 -2
  33. package/lib/ToggleSwitch/ToggleSwitchGroup.js +20 -12
  34. package/lib/utils/containUniqueFields.js +34 -0
  35. package/lib/utils/index.js +10 -1
  36. package/lib/utils/props/handlerProps.js +72 -0
  37. package/lib/utils/props/index.js +14 -0
  38. package/lib/utils/props/inputSupportsProps.js +3 -5
  39. package/lib-module/Button/ButtonBase.js +2 -2
  40. package/lib-module/Button/ButtonGroup.js +15 -6
  41. package/lib-module/Card/PressableCardBase.js +2 -2
  42. package/lib-module/Checkbox/Checkbox.js +28 -17
  43. package/lib-module/Checkbox/CheckboxGroup.js +20 -7
  44. package/lib-module/ExpandCollapse/Panel.js +10 -10
  45. package/lib-module/FlexGrid/Col/Col.js +13 -3
  46. package/lib-module/FlexGrid/Row/Row.js +8 -2
  47. package/lib-module/HorizontalScroll/HorizontalScroll.js +0 -1
  48. package/lib-module/HorizontalScroll/HorizontalScrollButton.js +24 -49
  49. package/lib-module/InputLabel/InputLabel.js +28 -25
  50. package/lib-module/Link/LinkBase.js +19 -6
  51. package/lib-module/Modal/Modal.js +19 -19
  52. package/lib-module/Notification/Notification.js +6 -6
  53. package/lib-module/Radio/Radio.js +24 -13
  54. package/lib-module/Radio/RadioGroup.js +13 -4
  55. package/lib-module/RadioCard/RadioCard.js +2 -2
  56. package/lib-module/RadioCard/RadioCardGroup.js +12 -3
  57. package/lib-module/Select/Select.js +2 -3
  58. package/lib-module/Tags/Tags.js +18 -11
  59. package/lib-module/TextInput/TextArea.js +3 -3
  60. package/lib-module/TextInput/TextInput.js +11 -3
  61. package/lib-module/TextInput/TextInputBase.js +2 -2
  62. package/lib-module/TextInput/propTypes.js +7 -1
  63. package/lib-module/ToggleSwitch/ToggleSwitch.js +6 -3
  64. package/lib-module/ToggleSwitch/ToggleSwitchGroup.js +15 -6
  65. package/lib-module/utils/containUniqueFields.js +26 -0
  66. package/lib-module/utils/index.js +2 -1
  67. package/lib-module/utils/props/handlerProps.js +59 -0
  68. package/lib-module/utils/props/index.js +1 -0
  69. package/lib-module/utils/props/inputSupportsProps.js +3 -5
  70. package/package.json +5 -5
  71. package/src/Button/ButtonBase.jsx +8 -2
  72. package/src/Button/ButtonGroup.jsx +51 -34
  73. package/src/Card/PressableCardBase.jsx +6 -1
  74. package/src/Checkbox/Checkbox.jsx +35 -23
  75. package/src/Checkbox/CheckboxGroup.jsx +52 -22
  76. package/src/ExpandCollapse/Panel.jsx +9 -9
  77. package/src/FlexGrid/Col/Col.jsx +11 -2
  78. package/src/FlexGrid/Row/Row.jsx +8 -2
  79. package/src/HorizontalScroll/HorizontalScroll.jsx +1 -1
  80. package/src/HorizontalScroll/HorizontalScrollButton.jsx +21 -58
  81. package/src/InputLabel/InputLabel.jsx +36 -27
  82. package/src/Link/LinkBase.jsx +20 -4
  83. package/src/Modal/Modal.jsx +30 -26
  84. package/src/Notification/Notification.jsx +7 -4
  85. package/src/Radio/Radio.jsx +26 -14
  86. package/src/Radio/RadioGroup.jsx +39 -21
  87. package/src/RadioCard/RadioCard.jsx +6 -1
  88. package/src/RadioCard/RadioCardGroup.jsx +17 -1
  89. package/src/Select/Select.jsx +2 -2
  90. package/src/Tags/Tags.jsx +23 -9
  91. package/src/TextInput/TextArea.jsx +5 -1
  92. package/src/TextInput/TextInput.jsx +13 -3
  93. package/src/TextInput/TextInputBase.jsx +6 -1
  94. package/src/TextInput/propTypes.js +7 -1
  95. package/src/ToggleSwitch/ToggleSwitch.jsx +11 -2
  96. package/src/ToggleSwitch/ToggleSwitchGroup.jsx +19 -6
  97. package/src/utils/containUniqueFields.js +32 -0
  98. package/src/utils/index.js +1 -0
  99. package/src/utils/props/handlerProps.js +47 -0
  100. package/src/utils/props/index.js +1 -0
  101. package/src/utils/props/inputSupportsProps.js +3 -4
  102. package/stories/InputLabel/InputLabel.stories.jsx +25 -28
  103. package/stories/Modal/Modal.stories.jsx +25 -0
  104. package/stories/Search/Search.stories.jsx +4 -1
  105. package/stories/TextInput/TextInput.stories.jsx +40 -2
@@ -9,6 +9,7 @@ import LabelContent from './LabelContent';
9
9
  import Tooltip from '../Tooltip';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
+ import { Fragment as _Fragment } from "react/jsx-runtime";
12
13
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
13
14
 
14
15
  const selectLabelStyles = tokens => applyTextStyles(selectTokens('Typography', tokens));
@@ -47,25 +48,29 @@ const InputLabel = /*#__PURE__*/forwardRef(({
47
48
  const themeTokens = useThemeTokens('InputLabel', tokens, variant);
48
49
  const hasTooltip = tooltip !== undefined;
49
50
  const isHintInline = hintPosition === 'inline';
50
- return /*#__PURE__*/_jsxs(View, {
51
- ref: ref,
52
- style: [staticStyles.container, !isHintInline && staticStyles.containerWithHintBelow],
53
- ...selectProps(rest),
54
- children: [/*#__PURE__*/_jsx(Text, {
55
- style: [selectLabelStyles(themeTokens), selectGapStyles(themeTokens), staticStyles.label],
56
- children: /*#__PURE__*/_jsx(LabelContent, {
57
- forId: forId,
58
- children: label
59
- })
60
- }), hint && isHintInline && /*#__PURE__*/_jsx(Text, {
61
- style: [selectHintStyles(themeTokens), hasTooltip && selectGapStyles(themeTokens)],
62
- nativeID: hintId,
63
- children: hint
64
- }), hasTooltip && /*#__PURE__*/_jsx(View, {
65
- style: staticStyles.tooltipAlign,
66
- children: /*#__PURE__*/_jsx(Tooltip, {
67
- content: tooltip
68
- })
51
+ return /*#__PURE__*/_jsxs(_Fragment, {
52
+ children: [/*#__PURE__*/_jsxs(View, {
53
+ ref: ref,
54
+ style: staticStyles.container,
55
+ ...selectProps(rest),
56
+ children: [/*#__PURE__*/_jsx(Text, {
57
+ style: [selectLabelStyles(themeTokens), selectGapStyles(themeTokens), staticStyles.label],
58
+ children: /*#__PURE__*/_jsx(LabelContent, {
59
+ forId: forId,
60
+ children: label
61
+ })
62
+ }), hint && isHintInline && /*#__PURE__*/_jsx(Text, {
63
+ style: [selectHintStyles(themeTokens), hasTooltip && selectGapStyles(themeTokens), staticStyles.label],
64
+ nativeID: hintId,
65
+ children: hint
66
+ }), hasTooltip && /*#__PURE__*/_jsx(View, {
67
+ style: [staticStyles.tooltipAlign, {
68
+ height: themeTokens.fontSize * themeTokens.lineHeight
69
+ }],
70
+ children: /*#__PURE__*/_jsx(Tooltip, {
71
+ content: tooltip
72
+ })
73
+ })]
69
74
  }), hint && !isHintInline && /*#__PURE__*/_jsx(Text, {
70
75
  style: [selectHintStyles(themeTokens), staticStyles.hintBelow],
71
76
  nativeID: hintId,
@@ -111,21 +116,19 @@ InputLabel.propTypes = { ...selectedSystemPropTypes,
111
116
  export default InputLabel;
112
117
  const staticStyles = StyleSheet.create({
113
118
  container: {
114
- display: 'flex',
119
+ flexShrink: 1,
115
120
  flexDirection: 'row',
116
121
  alignItems: 'baseline'
117
122
  },
118
- containerWithHintBelow: {
119
- flexWrap: 'wrap'
120
- },
121
123
  label: {
122
- flexShrink: 0
124
+ flexShrink: 1
123
125
  },
124
126
  hintBelow: {
125
127
  flexBasis: '100%',
126
128
  flexShrink: 0
127
129
  },
128
130
  tooltipAlign: {
129
- alignSelf: 'center'
131
+ alignSelf: 'flex-start',
132
+ justifyContent: 'center'
130
133
  }
131
134
  });
@@ -35,13 +35,9 @@ Platform.OS === 'web' ? {
35
35
  } : {};
36
36
 
37
37
  const selectTextStyles = ({
38
- color,
39
- textLine,
40
- textLineStyle
38
+ color
41
39
  }) => ({
42
40
  color,
43
- textDecorationLine: textLine,
44
- textDecorationStyle: textLineStyle,
45
41
  ...Platform.select({
46
42
  web: {
47
43
  // TODO: https://github.com/telus/universal-design-system/issues/487
@@ -62,6 +58,22 @@ const selectBlockStyles = ({
62
58
  fontName: blockFontName
63
59
  });
64
60
 
61
+ const selectDecorationStyles = ({
62
+ color,
63
+ textLine,
64
+ textLineStyle
65
+ }) => ({
66
+ color,
67
+ textDecorationLine: textLine,
68
+ textDecorationStyle: textLineStyle,
69
+ ...Platform.select({
70
+ web: {
71
+ // TODO: https://github.com/telus/universal-design-system/issues/487
72
+ transition: 'color 200ms'
73
+ }
74
+ })
75
+ });
76
+
65
77
  const selectIconTokens = ({
66
78
  color,
67
79
  iconSize,
@@ -138,8 +150,9 @@ const LinkBase = /*#__PURE__*/forwardRef(({
138
150
  style: linkState => {
139
151
  const themeTokens = resolveLinkTokens(linkState);
140
152
  const outerBorderStyles = selectOuterBorderStyles(themeTokens);
153
+ const decorationStyles = selectDecorationStyles(themeTokens);
141
154
  const hasIcon = Boolean(icon || themeTokens.icon);
142
- return [outerBorderStyles, blockLeftStyle, hasIcon && staticStyles.rowContainer];
155
+ return [outerBorderStyles, blockLeftStyle, decorationStyles, hasIcon && staticStyles.rowContainer];
143
156
  },
144
157
  children: linkState => {
145
158
  const themeTokens = resolveLinkTokens(linkState);
@@ -6,9 +6,9 @@ import NativeModal from "react-native-web/dist/exports/Modal";
6
6
  import Platform from "react-native-web/dist/exports/Platform";
7
7
  import PropTypes from 'prop-types';
8
8
  import { applyShadowToken, useThemeTokens } from '../ThemeProvider';
9
- import { a11yProps, copyPropTypes, getTokensPropType, selectSystemProps, useCopy, variantProp, viewProps } from '../utils';
9
+ import { a11yProps, copyPropTypes, getTokensPropType, selectSystemProps, useCopy, variantProp, viewProps, selectTokens } from '../utils';
10
10
  import { useViewport } from '../ViewportProvider';
11
- import ButtonBase from '../Button/ButtonBase';
11
+ import IconButton from '../IconButton';
12
12
  import dictionary from './dictionary';
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
14
  import { jsxs as _jsxs } from "react/jsx-runtime";
@@ -65,14 +65,6 @@ const selectCloseButtonContainerStyles = ({
65
65
  paddingRight,
66
66
  paddingTop
67
67
  });
68
-
69
- const selectCloseIconProps = ({
70
- closeIconSize,
71
- closeIconColor
72
- }) => ({
73
- size: closeIconSize,
74
- color: closeIconColor
75
- });
76
68
  /**
77
69
  * A modal window is a secondary window that opens on top of the main one.
78
70
  * Users have to interact with it before they can carry out their task and return to the main window.
@@ -97,6 +89,7 @@ const Modal = /*#__PURE__*/forwardRef(({
97
89
  tokens,
98
90
  variant,
99
91
  copy,
92
+ closeButton,
100
93
  ...rest
101
94
  }, ref) => {
102
95
  const viewport = useViewport();
@@ -119,12 +112,15 @@ const Modal = /*#__PURE__*/forwardRef(({
119
112
 
120
113
  const handleKeyUp = event => {
121
114
  if (event.key === 'Escape') onClose();
122
- };
115
+ }; // Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
116
+ // Hide the close button if `closeButton` is `null`.
117
+
118
+
119
+ const showCloseButton = closeButton !== null;
123
120
 
124
121
  if (!isOpen) {
125
122
  return null;
126
- } // TODO: replace the close button with IconButton when implemented (https://github.com/telus/universal-design-system/issues/281)
127
-
123
+ }
128
124
 
129
125
  return /*#__PURE__*/_jsx(NativeModal, {
130
126
  transparent: true,
@@ -139,15 +135,14 @@ const Modal = /*#__PURE__*/forwardRef(({
139
135
  ref: ref,
140
136
  style: [staticStyles.modal, selectModalStyles(themeTokens)],
141
137
  onKeyUp: handleKeyUp,
142
- children: [/*#__PURE__*/_jsx(View, {
138
+ children: [showCloseButton && /*#__PURE__*/_jsx(View, {
143
139
  style: [staticStyles.closeButtonContainer, selectCloseButtonContainerStyles(themeTokens)],
144
- children: /*#__PURE__*/_jsx(ButtonBase, {
140
+ children: closeButton || /*#__PURE__*/_jsx(IconButton, {
145
141
  onPress: handleClose,
142
+ icon: CloseIconComponent,
146
143
  accessibilityRole: "button",
147
144
  accessibilityLabel: closeLabel,
148
- children: // TODO: add close button interactive states after IconButton is done
149
- () => /*#__PURE__*/_jsx(CloseIconComponent, { ...selectCloseIconProps(themeTokens)
150
- })
145
+ tokens: selectTokens('IconButton', themeTokens, 'close')
151
146
  })
152
147
  }), children]
153
148
  })
@@ -168,7 +163,12 @@ Modal.propTypes = { ...selectedSystemPropTypes,
168
163
  onClose: PropTypes.func,
169
164
  maxWidth: PropTypes.bool,
170
165
  tokens: getTokensPropType('Modal'),
171
- variant: variantProp.propType
166
+ variant: variantProp.propType,
167
+
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
172
172
  };
173
173
  export default Modal;
174
174
  const staticStyles = StyleSheet.create({
@@ -1,10 +1,9 @@
1
1
  import React, { forwardRef, useState } from 'react';
2
2
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
3
- import Text from "react-native-web/dist/exports/Text";
4
3
  import View from "react-native-web/dist/exports/View";
5
4
  import PropTypes from 'prop-types';
6
5
  import { applyTextStyles, useThemeTokens } from '../ThemeProvider';
7
- import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, variantProp, viewProps } from '../utils';
6
+ import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, variantProp, viewProps, wrapStringsInText } from '../utils';
8
7
  import ButtonBase from '../Button/ButtonBase';
9
8
  import useCopy from '../utils/useCopy';
10
9
  import dictionary from './dictionary';
@@ -120,10 +119,11 @@ const Notification = /*#__PURE__*/forwardRef(({
120
119
  }
121
120
 
122
121
  const textStyles = selectTextStyles(themeTokens);
123
- const content = typeof children === 'string' ? /*#__PURE__*/_jsx(Text, {
124
- style: textStyles,
125
- children: children
126
- }) : children;
122
+ const content = wrapStringsInText(typeof children === 'function' ? children({
123
+ textStyles
124
+ }) : children, {
125
+ style: textStyles
126
+ });
127
127
  const {
128
128
  icon: IconComponent,
129
129
  dismissIcon: DismissIconComponent
@@ -7,11 +7,11 @@ import View from "react-native-web/dist/exports/View";
7
7
  import RadioLabel from '../InputLabel/LabelContent';
8
8
  import RadioButton, { selectRadioButtonTokens } from './RadioButton';
9
9
  import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
10
- import { a11yProps, getTokensPropType, selectSystemProps, useInputValue, useUniqueId, variantProp, viewProps } from '../utils';
10
+ import { a11yProps, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, useUniqueId, variantProp, viewProps } from '../utils';
11
11
  import StackView from '../StackView';
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, viewProps]);
14
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
15
15
 
16
16
  const selectContainerStyles = ({
17
17
  containerBackgroundColor,
@@ -162,22 +162,29 @@ const Radio = /*#__PURE__*/forwardRef(({
162
162
  hover,
163
163
  pressed
164
164
  });
165
+ const labelStyles = selectLabelStyles(stateTokens);
166
+ const alignWithLabel = label ? [staticStyles.alignWithLabel, {
167
+ height: labelStyles.lineHeight
168
+ }] : null;
165
169
  return /*#__PURE__*/_jsxs(StackView, {
166
170
  space: 0,
167
171
  children: [/*#__PURE__*/_jsxs(View, {
168
172
  style: [staticStyles.container, selectContainerStyles(stateTokens)],
169
- children: [/*#__PURE__*/_jsx(RadioButton, {
170
- tokens: selectRadioButtonTokens(stateTokens),
171
- isControlled: isControlled,
172
- isChecked: isChecked,
173
- inactive: inactive,
174
- defaultChecked: defaultChecked,
175
- inputId: inputId,
176
- handleChange: handleChange,
177
- name: inputName,
178
- value: value
173
+ children: [/*#__PURE__*/_jsx(View, {
174
+ style: alignWithLabel,
175
+ children: /*#__PURE__*/_jsx(RadioButton, {
176
+ tokens: selectRadioButtonTokens(stateTokens),
177
+ isControlled: isControlled,
178
+ isChecked: isChecked,
179
+ inactive: inactive,
180
+ defaultChecked: defaultChecked,
181
+ inputId: inputId,
182
+ handleChange: handleChange,
183
+ name: inputName,
184
+ value: value
185
+ })
179
186
  }), Boolean(label) && /*#__PURE__*/_jsx(Text, {
180
- style: selectLabelStyles(stateTokens),
187
+ style: labelStyles,
181
188
  children: /*#__PURE__*/_jsx(RadioLabel, {
182
189
  forId: inputId,
183
190
  children: label
@@ -259,5 +266,9 @@ const staticStyles = StyleSheet.create({
259
266
  container: {
260
267
  flexDirection: 'row',
261
268
  alignItems: 'center'
269
+ },
270
+ alignWithLabel: {
271
+ alignSelf: 'flex-start',
272
+ justifyContent: 'center'
262
273
  }
263
274
  });
@@ -3,12 +3,13 @@ import PropTypes from 'prop-types';
3
3
  import ABBPropTypes from 'airbnb-prop-types';
4
4
  import { useViewport } from '../ViewportProvider';
5
5
  import { useThemeTokens } from '../ThemeProvider';
6
- import { a11yProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
6
+ import { a11yProps, containUniqueFields, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
7
7
  import { getStackedContent } from '../StackView';
8
8
  import Radio from './Radio';
9
9
  import Fieldset from '../Fieldset';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
12
+ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
12
13
  /**
13
14
  * A group of Radios that behave as a radio group. Use when users select a single choice from mutually
14
15
  * exclusive options.
@@ -92,11 +93,18 @@ const RadioGroup = /*#__PURE__*/forwardRef(({
92
93
  onChange,
93
94
  readOnly: readOnly || inactive
94
95
  });
96
+ const uniqueFields = ['id', 'label'];
97
+
98
+ if (!containUniqueFields(items, uniqueFields)) {
99
+ throw new Error(`RadioGroup items must have unique ${uniqueFields.join(', ')}`);
100
+ }
101
+
95
102
  const radios = items.map(({
96
103
  label,
97
104
  id,
98
105
  onChange: itemOnChange,
99
- ref: itemRef
106
+ ref: itemRef,
107
+ ...itemRest
100
108
  }, index) => {
101
109
  const radioId = id || `Radio[${index}]`;
102
110
  const isChecked = currentValue === radioId;
@@ -115,7 +123,8 @@ const RadioGroup = /*#__PURE__*/forwardRef(({
115
123
  label: label,
116
124
  name: inputGroupName,
117
125
  tokens: radioTokens,
118
- variant: variant
126
+ variant: variant,
127
+ ...selectItemProps(itemRest)
119
128
  }, radioId);
120
129
  });
121
130
  return /*#__PURE__*/_jsx(Fieldset, {
@@ -157,7 +166,7 @@ RadioGroup.propTypes = { ...selectedSystemPropTypes,
157
166
  /**
158
167
  * Array of objects containing specifics for each Radio to be rendered in the group.
159
168
  */
160
- items: PropTypes.arrayOf(PropTypes.exact({
169
+ items: PropTypes.arrayOf(PropTypes.exact({ ...selectedItemPropTypes,
161
170
  label: PropTypes.string,
162
171
  id: PropTypes.string,
163
172
  onChange: PropTypes.func,
@@ -4,13 +4,13 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
4
4
  import Text from "react-native-web/dist/exports/Text";
5
5
  import View from "react-native-web/dist/exports/View";
6
6
  import { useThemeTokensCallback, applyTextStyles } from '../ThemeProvider';
7
- import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, useInputValue, useUniqueId, variantProp, viewProps } from '../utils';
7
+ import { a11yProps, focusHandlerProps, getTokensPropType, selectSystemProps, selectTokens, useInputValue, useUniqueId, variantProp, viewProps } from '../utils';
8
8
  import { PressableCardBase, selectPressableCardTokens } from '../Card';
9
9
  import StackView from '../StackView';
10
10
  import RadioButton, { selectRadioButtonTokens } from '../Radio/RadioButton';
11
11
  import { jsx as _jsx } from "react/jsx-runtime";
12
12
  import { jsxs as _jsxs } from "react/jsx-runtime";
13
- const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
13
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
14
14
  /**
15
15
  * A Card that behaves like a radio button. Use when users select a single choice from mutually exclusive options
16
16
  * with need to show additional information for each option. The whole card is interactive as one item.
@@ -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
- props: supportsProps,
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__*/
@@ -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/props';
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, pressProps, viewProps]);
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
- accessibilityLabel,
108
- ref: itemRef
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 itemA11y = {
129
+ const itemProps = {
124
130
  accessibilityState: {
125
131
  checked: isSelected
126
132
  },
127
133
  accessibilityRole: itemA11yRole,
128
- accessibilityLabel,
129
- ...a11yProps.getPositionInSet(items.length, index)
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
- ...itemA11y,
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
- props: supportsProps,
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 { a11yProps, getTokensPropType, inputSupportsProps, selectSystemProps, variantProp, viewProps } from '../utils';
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
- props: supportsProps,
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;