@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
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ // Returns true if there are no duplicate values of the fields listed
9
+ // in the `fields` array across the objects in the `items` array, false
10
+ // otherwise.
11
+ // Note that if a value of a field in an item is not set, it will be
12
+ // excluded from comparison.
13
+ const containUniqueFields = (items, fields) => {
14
+ const map = [];
15
+ const itemsHaveDuplicateFields = items.some(item => fields.some(field => {
16
+ if (!map[field]) {
17
+ map[field] = [];
18
+ }
19
+
20
+ if (!item[field]) {
21
+ // We exclude empty values from comparison
22
+ return false;
23
+ } // Duplicate found!
24
+
25
+
26
+ if (map[field][item[field]]) return true;
27
+ map[field][item[field]] = true;
28
+ return false;
29
+ }));
30
+ return !itemsHaveDuplicateFields;
31
+ };
32
+
33
+ var _default = containUniqueFields;
34
+ exports.default = _default;
@@ -10,7 +10,8 @@ var _exportNames = {
10
10
  useSpacingScale: true,
11
11
  useResponsiveProp: true,
12
12
  useUniqueId: true,
13
- withLinkRouter: true
13
+ withLinkRouter: true,
14
+ containUniqueFields: true
14
15
  };
15
16
  Object.defineProperty(exports, "info", {
16
17
  enumerable: true,
@@ -54,6 +55,12 @@ Object.defineProperty(exports, "withLinkRouter", {
54
55
  return _withLinkRouter.default;
55
56
  }
56
57
  });
58
+ Object.defineProperty(exports, "containUniqueFields", {
59
+ enumerable: true,
60
+ get: function () {
61
+ return _containUniqueFields.default;
62
+ }
63
+ });
57
64
 
58
65
  var _a11y = require("./a11y");
59
66
 
@@ -179,6 +186,8 @@ Object.keys(_ssr).forEach(function (key) {
179
186
  });
180
187
  });
181
188
 
189
+ var _containUniqueFields = _interopRequireDefault(require("./containUniqueFields"));
190
+
182
191
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
183
192
 
184
193
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.textInputHandlerProps = exports.focusHandlerProps = void 0;
7
+
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+
10
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
+
12
+ const focusHandlerProps = {
13
+ types: {
14
+ /**
15
+ * onBlur handler
16
+ */
17
+ onBlur: _propTypes.default.func,
18
+
19
+ /**
20
+ * onFocus handler
21
+ */
22
+ onFocus: _propTypes.default.func
23
+ },
24
+ select: ({
25
+ onBlur,
26
+ onFocus
27
+ }) => ({
28
+ onBlur,
29
+ onFocus
30
+ })
31
+ };
32
+ exports.focusHandlerProps = focusHandlerProps;
33
+ const textInputHandlerProps = {
34
+ types: {
35
+ /**
36
+ * onChange handler
37
+ */
38
+ onChange: _propTypes.default.func,
39
+
40
+ /**
41
+ * onChangeText handler
42
+ */
43
+ onChangeText: _propTypes.default.func,
44
+
45
+ /**
46
+ * onSubmit handler
47
+ */
48
+ onSubmit: _propTypes.default.func,
49
+
50
+ /**
51
+ * onSubmitEditing handler
52
+ */
53
+ onSubmitEditing: _propTypes.default.func
54
+ },
55
+ select: ({
56
+ onChange,
57
+ onChangeText,
58
+ onSubmit,
59
+ onSubmitEditing
60
+ }) => ({
61
+ onChange,
62
+ onChangeText,
63
+ onSubmit,
64
+ onSubmitEditing
65
+ })
66
+ };
67
+ exports.textInputHandlerProps = textInputHandlerProps;
68
+ var _default = {
69
+ focusHandlerProps,
70
+ textInputHandlerProps
71
+ };
72
+ exports.default = _default;
@@ -125,6 +125,20 @@ Object.keys(_tokens).forEach(function (key) {
125
125
  });
126
126
  });
127
127
 
128
+ var _handlerProps = require("./handlerProps");
129
+
130
+ Object.keys(_handlerProps).forEach(function (key) {
131
+ if (key === "default" || key === "__esModule") return;
132
+ if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
133
+ if (key in exports && exports[key] === _handlerProps[key]) return;
134
+ Object.defineProperty(exports, key, {
135
+ enumerable: true,
136
+ get: function () {
137
+ return _handlerProps[key];
138
+ }
139
+ });
140
+ });
141
+
128
142
  var _a11yProps = _interopRequireDefault(require("./a11yProps"));
129
143
 
130
144
  var _clickProps = _interopRequireDefault(require("./clickProps"));
@@ -48,18 +48,16 @@ var _default = {
48
48
  hintPosition,
49
49
  feedback,
50
50
  tooltip,
51
- validation,
52
- ...rest
51
+ validation
53
52
  }) => ({
54
- props: {
53
+ supportsProps: {
55
54
  label,
56
55
  hint,
57
56
  hintPosition,
58
57
  feedback,
59
58
  tooltip,
60
59
  validation
61
- },
62
- ...rest
60
+ }
63
61
  })
64
62
  };
65
63
  exports.default = _default;
@@ -6,9 +6,9 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
6
6
  import Platform from "react-native-web/dist/exports/Platform";
7
7
  import { applyTextStyles, applyShadowToken, applyOuterBorder } from '../ThemeProvider/utils';
8
8
  import buttonPropTypes from './propTypes';
9
- import { a11yProps, getCursorStyle, clickProps, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, viewProps, wrapStringsInText, withLinkRouter } from '../utils';
9
+ import { a11yProps, clickProps, focusHandlerProps, getCursorStyle, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, viewProps, wrapStringsInText, withLinkRouter } from '../utils';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
- const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps]);
11
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, linkProps, viewProps]);
12
12
 
13
13
  const getOuterBorderOffset = ({
14
14
  outerBorderGap = 0,
@@ -6,11 +6,11 @@ import ButtonBase from './ButtonBase';
6
6
  import { StackWrap } from '../StackView';
7
7
  import { useViewport } from '../ViewportProvider';
8
8
  import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider';
9
- import { a11yProps, pressProps, getTokensPropType, selectSystemProps, selectTokens, variantProp, viewProps } from '../utils/props';
10
- import { useMultipleInputValues } from '../utils/input';
9
+ import { a11yProps, containUniqueFields, focusHandlerProps, pressProps, getTokensPropType, selectSystemProps, selectTokens, useMultipleInputValues, variantProp, viewProps } from '../utils';
11
10
  import { getPressHandlersWithArgs } from '../utils/pressability';
12
11
  import { jsx as _jsx } from "react/jsx-runtime";
13
- const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, pressProps, viewProps]);
12
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
13
+ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, pressProps, viewProps]);
14
14
  const ButtonGroup = /*#__PURE__*/forwardRef(({
15
15
  variant,
16
16
  tokens,
@@ -53,6 +53,12 @@ const ButtonGroup = /*#__PURE__*/forwardRef(({
53
53
  ...rest
54
54
  });
55
55
  const itemA11yRole = systemProps.accessibilityRole === 'radiogroup' ? 'radio' : 'checkbox';
56
+ const uniqueFields = ['id', 'label'];
57
+
58
+ if (!containUniqueFields(items, uniqueFields)) {
59
+ throw new Error(`ButtonGroup items must have unique ${uniqueFields.join(', ')}`);
60
+ }
61
+
56
62
  return /*#__PURE__*/_jsx(StackWrap, { ...systemProps,
57
63
  space: space,
58
64
  direction: direction,
@@ -62,7 +68,8 @@ const ButtonGroup = /*#__PURE__*/forwardRef(({
62
68
  label,
63
69
  id = label,
64
70
  accessibilityLabel,
65
- ref: itemRef
71
+ ref: itemRef,
72
+ ...itemRest
66
73
  }, index) => {
67
74
  const isSelected = currentValues.includes(id); // Pass an object of relevant component state as first argument for any passed-in press handlers
68
75
 
@@ -73,7 +80,7 @@ const ButtonGroup = /*#__PURE__*/forwardRef(({
73
80
  }]);
74
81
 
75
82
  const handlePress = event => {
76
- if (pressHandlers.onPress) pressHandlers.onPress();
83
+ if (pressHandlers.onPress) pressHandlers.onPress(event);
77
84
  toggleOneValue(id, event);
78
85
  };
79
86
 
@@ -95,6 +102,7 @@ const ButtonGroup = /*#__PURE__*/forwardRef(({
95
102
  selected: isSelected,
96
103
  inactive: inactive,
97
104
  ...itemA11y,
105
+ ...selectItemProps(itemRest),
98
106
  children: label
99
107
  }, id);
100
108
  })
@@ -114,7 +122,8 @@ ButtonGroup.propTypes = { ...selectedSystemPropTypes,
114
122
  /**
115
123
  * The options a user may select
116
124
  */
117
- items: PropTypes.arrayOf(PropTypes.shape({
125
+ items: PropTypes.arrayOf(PropTypes.shape({ ...selectedItemPropTypes,
126
+
118
127
  /**
119
128
  * The text displayed to the user in the button, describing this option,
120
129
  * passed to the button as its child.
@@ -4,10 +4,10 @@ import Pressable from "react-native-web/dist/exports/Pressable";
4
4
  import Platform from "react-native-web/dist/exports/Platform";
5
5
  import { useViewport } from '../ViewportProvider';
6
6
  import { applyOuterBorder, validateThemeTokens } from '../ThemeProvider';
7
- import { a11yProps, clickProps, getTokenNames, getTokensSetPropType, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, selectTokens, variantProp, viewProps, withLinkRouter } from '../utils';
7
+ import { a11yProps, clickProps, focusHandlerProps, getTokenNames, getTokensSetPropType, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, selectTokens, variantProp, viewProps, withLinkRouter } from '../utils';
8
8
  import CardBase from './CardBase';
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
10
- const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
10
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
11
11
  const tokenKeys = [...getTokenNames('Card'), // Outer border tokens. TODO: centralise common token sets like these as part of
12
12
  // https://github.com/telus/universal-design-system/issues/782
13
13
  'outerBorderColor', 'outerBorderWidth', 'outerBorderGap'];
@@ -10,11 +10,11 @@ import CheckboxLabel from '../InputLabel/LabelContent';
10
10
  import Feedback from '../Feedback';
11
11
  import StackView from '../StackView';
12
12
  import { applyShadowToken, applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
13
- import { a11yProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
13
+ import { a11yProps, focusHandlerProps, getTokensPropType, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
14
14
  import useUniqueId from '../utils/useUniqueId';
15
15
  import { jsx as _jsx } from "react/jsx-runtime";
16
16
  import { jsxs as _jsxs } from "react/jsx-runtime";
17
- const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
17
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
18
18
 
19
19
  const selectInputStyles = ({
20
20
  iconBackgroundColor,
@@ -204,24 +204,31 @@ const Checkbox = /*#__PURE__*/forwardRef(({
204
204
  pressed
205
205
  });
206
206
  const iconTokens = selectIconTokens(stateTokens);
207
+ const labelStyles = selectLabelStyles(stateTokens);
208
+ const alignWithLabel = label ? [staticStyles.alignWithLabel, {
209
+ height: labelStyles.lineHeight
210
+ }] : null;
207
211
  return /*#__PURE__*/_jsxs(View, {
208
212
  style: staticStyles.container,
209
- children: [/*#__PURE__*/_jsxs(View, {
210
- style: StyleSheet.flatten([staticStyles.defaultInputStyles, selectInputStyles(stateTokens, isChecked)]),
211
- testID: "Checkbox-Input",
212
- children: [/*#__PURE__*/_jsx(CheckboxInput, {
213
- checked: isChecked,
214
- defaultChecked: defaultChecked,
215
- disabled: inactive,
216
- id: inputId,
217
- isControlled: isControlled,
218
- name: name,
219
- value: value
220
- }), isChecked && IconComponent && /*#__PURE__*/_jsx(IconComponent, { ...iconTokens,
221
- testID: "Checkbox-Icon"
222
- })]
213
+ children: [/*#__PURE__*/_jsx(View, {
214
+ style: alignWithLabel,
215
+ children: /*#__PURE__*/_jsxs(View, {
216
+ style: [staticStyles.defaultInputStyles, selectInputStyles(stateTokens, isChecked)],
217
+ testID: "Checkbox-Input",
218
+ children: [/*#__PURE__*/_jsx(CheckboxInput, {
219
+ checked: isChecked,
220
+ defaultChecked: defaultChecked,
221
+ disabled: inactive,
222
+ id: inputId,
223
+ isControlled: isControlled,
224
+ name: name,
225
+ value: value
226
+ }), isChecked && IconComponent && /*#__PURE__*/_jsx(IconComponent, { ...iconTokens,
227
+ testID: "Checkbox-Icon"
228
+ })]
229
+ })
223
230
  }), Boolean(label) && /*#__PURE__*/_jsx(Text, {
224
- style: selectLabelStyles(stateTokens),
231
+ style: labelStyles,
225
232
  children: /*#__PURE__*/_jsx(CheckboxLabel, {
226
233
  forId: inputId,
227
234
  children: label
@@ -317,5 +324,9 @@ const staticStyles = StyleSheet.create({
317
324
  defaultInputStyles: {
318
325
  alignItems: 'center',
319
326
  justifyContent: 'center'
327
+ },
328
+ alignWithLabel: {
329
+ alignSelf: 'flex-start',
330
+ justifyContent: 'center'
320
331
  }
321
332
  });
@@ -3,10 +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 { getTokensPropType, useMultipleInputValues, variantProp } from '../utils';
6
+ import { a11yProps, containUniqueFields, focusHandlerProps, getTokensPropType, selectSystemProps, useMultipleInputValues, variantProp, viewProps } from '../utils';
7
7
  import { getStackedContent } from '../StackView';
8
8
  import Checkbox from './Checkbox';
9
9
  import Fieldset from '../Fieldset';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
12
+ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, viewProps]);
10
13
  /**
11
14
  * A group of Checkboxs that behave as a fieldset. Use when users select any number of choices from options.
12
15
  *
@@ -55,7 +58,6 @@ import Fieldset from '../Fieldset';
55
58
  * ```
56
59
  */
57
60
 
58
- import { jsx as _jsx } from "react/jsx-runtime";
59
61
  const CheckboxGroup = /*#__PURE__*/forwardRef(({
60
62
  tokens,
61
63
  radioTokens,
@@ -71,7 +73,8 @@ const CheckboxGroup = /*#__PURE__*/forwardRef(({
71
73
  onChange,
72
74
  readOnly,
73
75
  name: inputGroupName,
74
- inactive
76
+ inactive,
77
+ ...rest
75
78
  }, ref) => {
76
79
  const viewport = useViewport();
77
80
  const {
@@ -89,11 +92,18 @@ const CheckboxGroup = /*#__PURE__*/forwardRef(({
89
92
  onChange,
90
93
  readOnly: readOnly || inactive
91
94
  });
95
+ const uniqueFields = ['id', 'label'];
96
+
97
+ if (!containUniqueFields(items, uniqueFields)) {
98
+ throw new Error(`CheckboxGroup items must have unique ${uniqueFields.join(', ')}`);
99
+ }
100
+
92
101
  const checkboxes = items.map(({
93
102
  label,
94
103
  id,
95
104
  onChange: itemOnChange,
96
- ref: itemRef
105
+ ref: itemRef,
106
+ ...itemRest
97
107
  }, index) => {
98
108
  const checkboxId = id || `Checkbox[${index}]`;
99
109
 
@@ -111,7 +121,8 @@ const CheckboxGroup = /*#__PURE__*/forwardRef(({
111
121
  label: label,
112
122
  name: inputGroupName,
113
123
  tokens: radioTokens,
114
- variant: variant
124
+ variant: variant,
125
+ ...selectItemProps(itemRest)
115
126
  }, checkboxId);
116
127
  });
117
128
  return /*#__PURE__*/_jsx(Fieldset, {
@@ -124,6 +135,7 @@ const CheckboxGroup = /*#__PURE__*/forwardRef(({
124
135
  feedback: feedback,
125
136
  inactive: inactive,
126
137
  validation: validation,
138
+ ...selectProps(rest),
127
139
  children: getStackedContent(checkboxes, {
128
140
  space,
129
141
  direction: 'column'
@@ -131,7 +143,8 @@ const CheckboxGroup = /*#__PURE__*/forwardRef(({
131
143
  });
132
144
  });
133
145
  CheckboxGroup.displayName = 'CheckboxGroup';
134
- CheckboxGroup.propTypes = {
146
+ CheckboxGroup.propTypes = { ...selectedSystemPropTypes,
147
+
135
148
  /**
136
149
  * Optional theme token overrides for the outer CheckboxGroup component
137
150
  */
@@ -150,7 +163,7 @@ CheckboxGroup.propTypes = {
150
163
  /**
151
164
  * Array of objects containing specifics for each Checkbox to be rendered in the group.
152
165
  */
153
- items: PropTypes.arrayOf(PropTypes.exact({
166
+ items: PropTypes.arrayOf(PropTypes.exact({ ...selectedItemPropTypes,
154
167
  label: PropTypes.string,
155
168
  id: PropTypes.string,
156
169
  onChange: PropTypes.func,
@@ -64,12 +64,13 @@ const ExpandCollapsePanel = /*#__PURE__*/forwardRef(({
64
64
  };
65
65
 
66
66
  const onContainerLayout = event => {
67
- if (containerHeight === null) {
68
- const {
69
- layout: {
70
- height = 0
71
- } = {}
72
- } = event.nativeEvent;
67
+ const {
68
+ layout: {
69
+ height = 0
70
+ } = {}
71
+ } = event.nativeEvent;
72
+
73
+ if (Platform.OS === 'web' || Platform.OS !== 'web' && containerHeight === null) {
73
74
  setContainerHeight(height);
74
75
  }
75
76
  };
@@ -94,12 +95,11 @@ const ExpandCollapsePanel = /*#__PURE__*/forwardRef(({
94
95
  tokens: controlTokens,
95
96
  onPress: handleControlPress,
96
97
  children: control
97
- }), /*#__PURE__*/_jsx(View, {
98
- style: overflowContainerStyles,
98
+ }), /*#__PURE__*/_jsx(Animated.View, {
99
+ style: [overflowContainerStyles, animatedStyles, staticStyles.itemsContainer],
99
100
  ...focusabilityProps,
100
- children: /*#__PURE__*/_jsx(Animated.View, {
101
+ children: /*#__PURE__*/_jsx(View, {
101
102
  onLayout: onContainerLayout,
102
- style: [staticStyles.itemsContainer, animatedStyles],
103
103
  children: /*#__PURE__*/_jsx(View, {
104
104
  style: selectContainerStyles(themeTokens),
105
105
  children: children
@@ -22,6 +22,7 @@ const Col = /*#__PURE__*/forwardRef(({
22
22
  mdOffset,
23
23
  lgOffset,
24
24
  xlOffset,
25
+ flex,
25
26
  ...viewProps
26
27
  }, ref) => {
27
28
  const gutter = useContext(GutterContext);
@@ -95,8 +96,11 @@ const Col = /*#__PURE__*/forwardRef(({
95
96
  paddingLeft: gutter ? 16 : 0,
96
97
  paddingRight: gutter ? 16 : 0
97
98
  };
98
- let hidingStyles = {};
99
- const shown = Platform.OS === 'web' ? 'block' : 'flex';
99
+ let hidingStyles = {}; // TODO: consider setting this to always 'flex' in a major release.
100
+ // `display: block` is invalid in native apps.
101
+ // See https://telusdigital.atlassian.net/browse/UDS1-92
102
+
103
+ const shown = !flex && Platform.OS === 'web' ? 'block' : 'flex';
100
104
 
101
105
  if (viewPort === viewports.xs) {
102
106
  hidingStyles = {
@@ -260,6 +264,12 @@ Col.propTypes = {
260
264
  *
261
265
  * Accepts a `PropType.string` following the [responsive prop](#/Layout?id=responsive) structure.
262
266
  */
263
- horizontalAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['left', 'center', 'right']))
267
+ horizontalAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(['left', 'center', 'right'])),
268
+
269
+ /**
270
+ * (web only) Stretches the column to fill vertical space using `display: flex`.
271
+ * In native apps, FlexGrid.Col behaves as if this is always true (as do all `View`s).
272
+ */
273
+ flex: PropTypes.bool
264
274
  };
265
275
  export default Col;
@@ -86,25 +86,31 @@ const Row = /*#__PURE__*/forwardRef(({
86
86
  const viewPort = useViewport();
87
87
  const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse]);
88
88
  let flexDirection = '';
89
+ let flexWrap = '';
89
90
 
90
91
  if (viewPort === viewports.xs) {
91
92
  flexDirection = reverseLevel[0] ? 'row-reverse' : 'row';
93
+ flexWrap = reverseLevel[0] ? 'wrap-reverse' : 'wrap';
92
94
  }
93
95
 
94
96
  if (viewPort === viewports.sm) {
95
97
  flexDirection = reverseLevel[1] ? 'row-reverse' : 'row';
98
+ flexWrap = reverseLevel[1] ? 'wrap-reverse' : 'wrap';
96
99
  }
97
100
 
98
101
  if (viewPort === viewports.md) {
99
102
  flexDirection = reverseLevel[2] ? 'row-reverse' : 'row';
103
+ flexWrap = reverseLevel[2] ? 'wrap-reverse' : 'wrap';
100
104
  }
101
105
 
102
106
  if (viewPort === viewports.lg) {
103
107
  flexDirection = reverseLevel[3] ? 'row-reverse' : 'row';
108
+ flexWrap = reverseLevel[3] ? 'wrap-reverse' : 'wrap';
104
109
  }
105
110
 
106
111
  if (viewPort === viewports.xl) {
107
112
  flexDirection = reverseLevel[4] ? 'row-reverse' : 'row';
113
+ flexWrap = reverseLevel[4] ? 'wrap-reverse' : 'wrap';
108
114
  }
109
115
 
110
116
  return /*#__PURE__*/_jsx(View, {
@@ -112,6 +118,7 @@ const Row = /*#__PURE__*/forwardRef(({
112
118
  ...rest,
113
119
  style: [styles.row, {
114
120
  flexDirection,
121
+ flexWrap,
115
122
  ...horizontalAlignStyles(horizontalAlign),
116
123
  ...verticalAlignStyles(verticalAlign),
117
124
  ...distributeStyles(distribute)
@@ -128,8 +135,7 @@ const styles = StyleSheet.create({
128
135
  flexGrow: 0,
129
136
  flexShrink: 1,
130
137
  flexBasis: 'auto',
131
- flexDirection: 'row',
132
- flexWrap: 'wrap'
138
+ flexDirection: 'row'
133
139
  }
134
140
  });
135
141
  Row.propTypes = {
@@ -129,7 +129,6 @@ const HorizontalScroll = /*#__PURE__*/forwardRef(({
129
129
  onLayout: handleContainerLayout,
130
130
  showsHorizontalScrollIndicator: false,
131
131
  contentContainerStyle: [staticStyles.scrollContainer, {
132
- marginBottom: gutter,
133
132
  borderBottomWidth,
134
133
  borderBottomColor
135
134
  }],
@@ -1,27 +1,18 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import Pressable from "react-native-web/dist/exports/Pressable";
4
3
  import StyleSheet from "react-native-web/dist/exports/StyleSheet";
5
- import { useThemeTokensCallback } from '../ThemeProvider';
6
- import { resolvePressableTokens, selectTokens, variantProp, getTokensPropType, useCopy, copyPropTypes, a11yProps } from '../utils';
7
- import Icon from '../Icon';
8
- import Typography from '../Typography';
4
+ import View from "react-native-web/dist/exports/View";
5
+ import { variantProp, getTokensPropType, useCopy, copyPropTypes, a11yProps } from '../utils';
6
+ import { useThemeTokens } from '../ThemeProvider';
7
+ import IconButton from '../IconButton';
9
8
  import dictionary from './dictionary';
10
9
  import { jsx as _jsx } from "react/jsx-runtime";
11
10
 
12
- const selectButtonStyles = ({
13
- borderRadius,
14
- backgroundColor,
15
- borderColor,
16
- borderWidth,
17
- padding
18
- }, direction) => [staticStyles.absolute, staticStyles[direction], {
19
- borderRadius,
20
- backgroundColor,
21
- borderColor,
22
- borderWidth,
23
- padding
24
- }];
11
+ const selectContainerStyles = ({
12
+ offset
13
+ }) => ({
14
+ marginTop: offset ? -offset : 0
15
+ });
25
16
  /**
26
17
  * Button within a Tabs component showing users that content is available to the left or
27
18
  * right, scrolling a screen's worth of content left or right when pressed.
@@ -35,47 +26,31 @@ const selectButtonStyles = ({
35
26
  const HorizontalScrollButton = /*#__PURE__*/forwardRef(({
36
27
  direction = 'next',
37
28
  icon,
38
- onPress,
39
29
  offset,
30
+ onPress,
40
31
  variant,
41
32
  tokens,
42
33
  copy
43
34
  }, ref) => {
44
- const getTokens = useThemeTokensCallback('HorizontalScrollButton', tokens, variant);
45
-
46
- const resolveButtonTokens = pressableState => resolvePressableTokens(getTokens, pressableState);
47
-
48
- const getPressableStyle = pressableState => [selectButtonStyles(resolveButtonTokens(pressableState), direction), {
49
- marginTop: -1 * (offset || 0)
50
- }];
51
-
35
+ const themeTokens = useThemeTokens('HorizontalScrollButton', tokens, variant);
52
36
  const getCopy = useCopy({
53
37
  dictionary,
54
38
  copy
55
39
  });
56
40
  const label = direction === 'previous' ? getCopy('previousText') : getCopy('nextText');
57
- return /*#__PURE__*/_jsx(Pressable, {
58
- ref: ref,
59
- style: getPressableStyle,
60
- onPress: onPress,
61
- accessibilityLabel: label,
62
- accessibilityRole: "button" // For keyboard-tab or screenreader-swipe navigation, users can just go through all items
63
- ,
64
- ...a11yProps.nonFocusableProps,
65
- children: pressableState => {
66
- const iconTokens = selectTokens('Icon', resolveButtonTokens(pressableState), 'icon');
67
- return icon ? /*#__PURE__*/_jsx(Icon, {
68
- icon: icon,
69
- tokens: iconTokens
70
- }) : /*#__PURE__*/_jsx(Typography, {
71
- tokens: {
72
- fontSize: iconTokens.size,
73
- lineHeight: 1,
74
- color: iconTokens.color
75
- },
76
- children: direction === 'next' ? '→' : '←'
77
- });
78
- }
41
+ return /*#__PURE__*/_jsx(View, {
42
+ style: [staticStyles.absolute, staticStyles[direction], selectContainerStyles({
43
+ offset
44
+ })],
45
+ children: /*#__PURE__*/_jsx(IconButton, {
46
+ accessibilityLabel: label,
47
+ icon: icon,
48
+ onPress: onPress,
49
+ ref: ref,
50
+ tokens: themeTokens,
51
+ variant: variant,
52
+ ...a11yProps.nonFocusableProps
53
+ })
79
54
  });
80
55
  });
81
56
  HorizontalScrollButton.displayName = 'HorizontalScrollButton';