@telus-uds/components-base 1.18.1 → 1.20.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 (112) hide show
  1. package/CHANGELOG.md +42 -2
  2. package/__tests17__/ThemeProvider/ThemeProvider.test.jsx +2 -1
  3. package/component-docs.json +1035 -231
  4. package/jest.config-android.js +17 -0
  5. package/jest.config-ios.js +18 -0
  6. package/jest.config-web.js +31 -0
  7. package/lib/BaseProvider/index.js +2 -1
  8. package/lib/Box/Box.js +14 -1
  9. package/lib/Button/ButtonBase.js +6 -2
  10. package/lib/Button/ButtonDropdown.js +207 -0
  11. package/lib/Button/index.js +8 -0
  12. package/lib/Carousel/Carousel.js +34 -6
  13. package/lib/Carousel/CarouselItem/CarouselItem.js +7 -1
  14. package/lib/Carousel/CarouselTabs/CarouselTabsPanel.js +22 -14
  15. package/lib/FlexGrid/Col/Col.js +1 -3
  16. package/lib/FlexGrid/FlexGrid.js +3 -5
  17. package/lib/FlexGrid/Row/Row.js +3 -3
  18. package/lib/IconButton/IconButton.js +12 -4
  19. package/lib/MultiSelectFilter/MultiSelectFilter.js +276 -0
  20. package/lib/MultiSelectFilter/dictionary.js +19 -0
  21. package/lib/MultiSelectFilter/index.js +13 -0
  22. package/lib/Pagination/SideButton.js +6 -4
  23. package/lib/Responsive/Responsive.js +58 -0
  24. package/lib/Responsive/index.js +13 -0
  25. package/lib/Search/Search.js +33 -63
  26. package/lib/Select/Picker.native.js +16 -13
  27. package/lib/Select/Select.js +7 -1
  28. package/lib/Select/constants.js +15 -0
  29. package/lib/StepTracker/Step.js +2 -1
  30. package/lib/Tags/Tags.js +10 -4
  31. package/lib/TextInput/TextInput.js +9 -2
  32. package/lib/TextInput/TextInputBase.js +98 -20
  33. package/lib/TextInput/dictionary.js +15 -0
  34. package/lib/ThemeProvider/ThemeProvider.js +6 -1
  35. package/lib/index.js +18 -0
  36. package/lib/utils/BaseView/BaseView.js +64 -0
  37. package/lib/utils/BaseView/BaseView.native.js +16 -0
  38. package/lib/utils/BaseView/index.js +13 -0
  39. package/lib/utils/index.js +10 -1
  40. package/lib/utils/input.js +11 -3
  41. package/lib/utils/props/handlerProps.js +5 -0
  42. package/lib-module/BaseProvider/index.js +2 -1
  43. package/lib-module/Box/Box.js +14 -1
  44. package/lib-module/Button/ButtonBase.js +6 -2
  45. package/lib-module/Button/ButtonDropdown.js +181 -0
  46. package/lib-module/Button/index.js +2 -1
  47. package/lib-module/Carousel/Carousel.js +34 -6
  48. package/lib-module/Carousel/CarouselItem/CarouselItem.js +8 -2
  49. package/lib-module/Carousel/CarouselTabs/CarouselTabsPanel.js +24 -16
  50. package/lib-module/FlexGrid/Col/Col.js +2 -3
  51. package/lib-module/FlexGrid/FlexGrid.js +2 -3
  52. package/lib-module/FlexGrid/Row/Row.js +2 -2
  53. package/lib-module/IconButton/IconButton.js +14 -4
  54. package/lib-module/MultiSelectFilter/MultiSelectFilter.js +248 -0
  55. package/lib-module/MultiSelectFilter/dictionary.js +12 -0
  56. package/lib-module/MultiSelectFilter/index.js +2 -0
  57. package/lib-module/Pagination/SideButton.js +6 -4
  58. package/lib-module/Responsive/Responsive.js +45 -0
  59. package/lib-module/Responsive/index.js +2 -0
  60. package/lib-module/Search/Search.js +33 -61
  61. package/lib-module/Select/Picker.native.js +15 -13
  62. package/lib-module/Select/Select.js +6 -1
  63. package/lib-module/Select/constants.js +5 -0
  64. package/lib-module/StepTracker/Step.js +2 -1
  65. package/lib-module/Tags/Tags.js +10 -4
  66. package/lib-module/TextInput/TextInput.js +6 -0
  67. package/lib-module/TextInput/TextInputBase.js +96 -21
  68. package/lib-module/TextInput/dictionary.js +8 -0
  69. package/lib-module/ThemeProvider/ThemeProvider.js +6 -1
  70. package/lib-module/index.js +2 -0
  71. package/lib-module/utils/BaseView/BaseView.js +43 -0
  72. package/lib-module/utils/BaseView/BaseView.native.js +6 -0
  73. package/lib-module/utils/BaseView/index.js +2 -0
  74. package/lib-module/utils/index.js +2 -1
  75. package/lib-module/utils/input.js +11 -3
  76. package/lib-module/utils/props/handlerProps.js +5 -0
  77. package/package.json +6 -3
  78. package/src/BaseProvider/index.jsx +4 -1
  79. package/src/Box/Box.jsx +14 -1
  80. package/src/Button/ButtonBase.jsx +4 -2
  81. package/src/Button/ButtonDropdown.jsx +179 -0
  82. package/src/Button/index.js +2 -1
  83. package/src/Carousel/Carousel.jsx +48 -13
  84. package/src/Carousel/CarouselItem/CarouselItem.jsx +9 -2
  85. package/src/Carousel/CarouselTabs/CarouselTabsPanel.jsx +19 -15
  86. package/src/FlexGrid/Col/Col.jsx +4 -4
  87. package/src/FlexGrid/FlexGrid.jsx +11 -10
  88. package/src/FlexGrid/Row/Row.jsx +4 -3
  89. package/src/IconButton/IconButton.jsx +3 -1
  90. package/src/MultiSelectFilter/MultiSelectFilter.jsx +227 -0
  91. package/src/MultiSelectFilter/dictionary.js +12 -0
  92. package/src/MultiSelectFilter/index.js +3 -0
  93. package/src/Pagination/SideButton.jsx +5 -5
  94. package/src/Responsive/Responsive.jsx +33 -0
  95. package/src/Responsive/index.js +3 -0
  96. package/src/Search/Search.jsx +19 -33
  97. package/src/Select/Picker.native.jsx +29 -14
  98. package/src/Select/Select.jsx +7 -1
  99. package/src/Select/constants.js +5 -0
  100. package/src/StepTracker/Step.jsx +5 -1
  101. package/src/Tags/Tags.jsx +46 -33
  102. package/src/TextInput/TextInput.jsx +5 -0
  103. package/src/TextInput/TextInputBase.jsx +85 -20
  104. package/src/TextInput/dictionary.js +8 -0
  105. package/src/ThemeProvider/ThemeProvider.jsx +5 -1
  106. package/src/index.js +2 -0
  107. package/src/utils/BaseView/BaseView.jsx +38 -0
  108. package/src/utils/BaseView/BaseView.native.jsx +6 -0
  109. package/src/utils/BaseView/index.js +3 -0
  110. package/src/utils/index.js +1 -0
  111. package/src/utils/input.js +9 -4
  112. package/src/utils/props/handlerProps.js +4 -0
@@ -0,0 +1,248 @@
1
+ import React, { forwardRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useThemeTokensCallback } from '../ThemeProvider';
4
+ import { containUniqueFields, getTokensPropType, getPressHandlersWithArgs, selectTokens, useCopy, useMultipleInputValues, variantProp } from '../utils';
5
+ import dictionary from './dictionary';
6
+ import Box from '../Box';
7
+ import { Button, ButtonDropdown } from '../Button';
8
+ import { CheckboxGroup } from '../Checkbox';
9
+ import Divider from '../Divider';
10
+ import FlexGrid from '../FlexGrid';
11
+ import Modal from '../Modal';
12
+ import Spacer from '../Spacer';
13
+ import StackView from '../StackView';
14
+ import Typography from '../Typography';
15
+ import { TextButton } from '../Link';
16
+ import { jsx as _jsx } from "react/jsx-runtime";
17
+ import { jsxs as _jsxs } from "react/jsx-runtime";
18
+ import { Fragment as _Fragment } from "react/jsx-runtime";
19
+ const {
20
+ Col,
21
+ Row
22
+ } = FlexGrid;
23
+ const MultiSelectFilter = /*#__PURE__*/forwardRef((_ref, ref) => {
24
+ let {
25
+ label,
26
+ id = label,
27
+ variant,
28
+ tokens,
29
+ items = [],
30
+ values,
31
+ initialValues,
32
+ maxValues,
33
+ onChange,
34
+ copy = 'en',
35
+ readOnly = false,
36
+ inactive = false,
37
+ rowLimit = 12,
38
+ ...rest
39
+ } = _ref;
40
+ const {
41
+ currentValues,
42
+ setValues
43
+ } = useMultipleInputValues({
44
+ initialValues,
45
+ values,
46
+ maxValues,
47
+ onChange,
48
+ readOnly
49
+ });
50
+ const getItemTokens = useThemeTokensCallback('ButtonDropdown', tokens, variant);
51
+
52
+ const getButtonTokens = buttonState => selectTokens('Button', getItemTokens(buttonState));
53
+
54
+ const getCopy = useCopy({
55
+ dictionary,
56
+ copy
57
+ });
58
+ const [isOpen, setIsOpen] = useState(false);
59
+ const [checkedIds, setCheckedIds] = useState(currentValues !== null && currentValues !== void 0 ? currentValues : []);
60
+ const colSize = items.length > rowLimit ? 2 : 1;
61
+ const isSelected = currentValues.length > 0;
62
+ const uniqueFields = ['id', 'label'];
63
+
64
+ if (!containUniqueFields(items, uniqueFields)) {
65
+ throw new Error("MultiSelectFilter items must have unique ".concat(uniqueFields.join(', ')));
66
+ } // Pass an object of relevant component state as first argument for any passed-in press handlers
67
+
68
+
69
+ const pressHandlers = getPressHandlersWithArgs(rest, [{
70
+ id,
71
+ label,
72
+ currentValues
73
+ }]);
74
+
75
+ const handleChange = event => {
76
+ if (pressHandlers.onPress) pressHandlers === null || pressHandlers === void 0 ? void 0 : pressHandlers.onPress(event);
77
+ setIsOpen(true);
78
+ };
79
+
80
+ const onApply = e => {
81
+ setValues(e);
82
+ setIsOpen(false);
83
+ };
84
+
85
+ return /*#__PURE__*/_jsxs(_Fragment, {
86
+ children: [/*#__PURE__*/_jsxs(Modal, {
87
+ isOpen: isOpen,
88
+ onClose: () => setIsOpen(false),
89
+ variant: {
90
+ width: colSize > 1 ? 'size576' : 's'
91
+ },
92
+ children: [/*#__PURE__*/_jsx(Row, {
93
+ children: /*#__PURE__*/_jsx(Typography, {
94
+ variant: {
95
+ size: 'h4'
96
+ },
97
+ children: getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label.toLowerCase())
98
+ })
99
+ }), /*#__PURE__*/_jsx(Spacer, {
100
+ space: 4
101
+ }), /*#__PURE__*/_jsx(Spacer, {
102
+ space: 1
103
+ }), /*#__PURE__*/_jsx(Box, {
104
+ scroll: true,
105
+ children: /*#__PURE__*/_jsx(Row, {
106
+ distribute: "between",
107
+ children: [...Array(colSize).keys()].map(i => /*#__PURE__*/_jsxs(Col, {
108
+ xs: 12 / colSize,
109
+ children: [/*#__PURE__*/_jsx(CheckboxGroup, {
110
+ items: items.slice(i * rowLimit, (i + 1) * rowLimit),
111
+ checkedIds: checkedIds,
112
+ onChange: e => setCheckedIds(e, i)
113
+ }), /*#__PURE__*/_jsx(Spacer, {
114
+ size: 4
115
+ })]
116
+ }, i))
117
+ })
118
+ }), /*#__PURE__*/_jsx(Divider, {
119
+ variant: {
120
+ width: 'full',
121
+ color: 'E3E6E8',
122
+ decorative: true,
123
+ weight: 'thin'
124
+ },
125
+ space: 4
126
+ }), /*#__PURE__*/_jsx(Row, {
127
+ children: /*#__PURE__*/_jsxs(StackView, {
128
+ direction: "row",
129
+ space: 3,
130
+ tokens: {
131
+ alignItems: 'center'
132
+ },
133
+ children: [/*#__PURE__*/_jsx(Button, {
134
+ onPress: () => onApply(checkedIds),
135
+ variant: {
136
+ size: 'small',
137
+ priority: 'high'
138
+ },
139
+ children: getCopy('applyButtonLabel')
140
+ }), /*#__PURE__*/_jsx(Box, {
141
+ children: /*#__PURE__*/_jsx(TextButton, {
142
+ onPress: () => setCheckedIds([]),
143
+ children: getCopy('clearButtonLabel')
144
+ })
145
+ })]
146
+ })
147
+ })]
148
+ }), /*#__PURE__*/_jsx(ButtonDropdown, {
149
+ ref: ref,
150
+ ...pressHandlers,
151
+ value: isOpen,
152
+ selected: isSelected,
153
+ label: label,
154
+ onChange: handleChange,
155
+ tokens: getButtonTokens,
156
+ inactive: inactive
157
+ }, id)]
158
+ });
159
+ });
160
+ MultiSelectFilter.displayName = 'MultiSelectFilter';
161
+ MultiSelectFilter.propTypes = {
162
+ /**
163
+ * The text displayed to the user in a ButtonDropdown.
164
+ */
165
+ label: PropTypes.string.isRequired,
166
+
167
+ /**
168
+ * An optional unique string may be provided to identify the ButtonDropdown.
169
+ * If not provided, the label is used.
170
+ */
171
+ id: PropTypes.string,
172
+
173
+ /**
174
+ * Sets the variant for ButtonDropdown element.
175
+ */
176
+ variant: variantProp.propType,
177
+
178
+ /**
179
+ * Sets the tokens for ButtonDropdown element.
180
+ */
181
+ tokens: getTokensPropType('ButtonDropdown'),
182
+
183
+ /**
184
+ * The options a user may select.
185
+ */
186
+ items: PropTypes.arrayOf(PropTypes.shape({
187
+ /**
188
+ * The text displayed to the user with a checkbox, describing this option.
189
+ */
190
+ label: PropTypes.string.isRequired,
191
+
192
+ /**
193
+ * An optional unique string may be provided to identify this option.
194
+ * If not provided, the label is used.
195
+ */
196
+ id: PropTypes.string
197
+ })),
198
+
199
+ /**
200
+ * If the selected item(s) in the checkbox group(s) are to be controlled externally by
201
+ * a parent component, pass an array of strings as well as an `onChange` handler.
202
+ * Passing an array for "values" makes the MultiSelectFilter a "controlled" component that
203
+ * expects its state to be handled via `onChange` and so doesn't handle it itself.
204
+ */
205
+ values: PropTypes.arrayOf(PropTypes.string),
206
+
207
+ /**
208
+ * If `values` is not passed, making the MultiSelectFilter an "uncontrolled" component
209
+ * managing its own selected state, a default set of selections may be provided.
210
+ * Changing the `initialValues` does not change the user's selections.
211
+ */
212
+ initialValues: PropTypes.arrayOf(PropTypes.string),
213
+
214
+ /**
215
+ * If provided, sets a maximum number of items a user may select at once.
216
+ */
217
+ maxValues: PropTypes.number,
218
+
219
+ /**
220
+ * If provided, this function is called when the current selection is changed
221
+ * and is passed an array of the `id`s of all currently selected `items`.
222
+ */
223
+ onChange: PropTypes.func,
224
+
225
+ /**
226
+ * Select English or French copy for the accessible label.
227
+ */
228
+ copy: PropTypes.oneOf(['en', 'fr']),
229
+
230
+ /**
231
+ * If true, the ButtonDropdown cannot be selected by the user and simply show their current state.
232
+ */
233
+ readOnly: PropTypes.string,
234
+
235
+ /**
236
+ * If true, the MultiSelectFilter cannot be interacted with, ButtonDropdown is
237
+ * set as `disabled` and if the theme supports `inactive` appearances rules, these
238
+ * are applied.
239
+ */
240
+ inactive: PropTypes.string,
241
+
242
+ /**
243
+ * Sets the maximum number of items in one column. If number of items are more
244
+ * than the `rowLimit`, they will be rendered in 2 columns.
245
+ */
246
+ rowLimit: PropTypes.number
247
+ };
248
+ export default MultiSelectFilter;
@@ -0,0 +1,12 @@
1
+ export default {
2
+ en: {
3
+ filterByLabel: 'Filter by %{filterCategory}:',
4
+ applyButtonLabel: 'Apply',
5
+ clearButtonLabel: 'Clear'
6
+ },
7
+ fr: {
8
+ filterByLabel: 'Filtrer par %{filterCategory}:',
9
+ applyButtonLabel: 'Appliquer',
10
+ clearButtonLabel: 'Effacer'
11
+ }
12
+ };
@@ -0,0 +1,2 @@
1
+ import MultiSelectFilter from './MultiSelectFilter';
2
+ export default MultiSelectFilter;
@@ -8,13 +8,15 @@ import { useViewport } from '../ViewportProvider';
8
8
  import { copyPropTypes, hrefAttrsProp, linkProps, selectTokens, withLinkRouter } from '../utils';
9
9
  import dictionary from './dictionary';
10
10
  import useCopy from '../utils/useCopy'; // We need to drop the icon here since it gets rendered via children and not
11
- // `ButtonBase` in order to tap into the state of the button
11
+ // `ButtonBase` in order to tap into the state of the button; `displayLabel` flag
12
+ // is also not needed
12
13
 
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
14
15
 
15
16
  const selectButtonTokens = _ref => {
16
17
  let {
17
18
  icon: _,
19
+ displayLabel: __,
18
20
  ...rest
19
21
  } = _ref;
20
22
  return selectTokens('Button', rest);
@@ -59,7 +61,8 @@ const SideButton = /*#__PURE__*/forwardRef((_ref3, ref) => {
59
61
  copy
60
62
  });
61
63
  const {
62
- icon
64
+ icon,
65
+ displayLabel
63
66
  } = getTokens(tokens, buttonVariant);
64
67
 
65
68
  const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState));
@@ -67,7 +70,6 @@ const SideButton = /*#__PURE__*/forwardRef((_ref3, ref) => {
67
70
  const getIconTokens = buttonState => selectIconTokens(getTokens(buttonState), direction);
68
71
 
69
72
  const label = direction === 'previous' ? getCopy('previousText') : getCopy('nextText');
70
- const showLabel = viewport !== 'sm' && viewport !== 'xs';
71
73
  const accessibilityLabel = direction === 'previous' ? getCopy('previousLabel') : getCopy('nextLabel');
72
74
  const accessibilityRole = href !== undefined ? 'link' : 'button';
73
75
  const {
@@ -99,7 +101,7 @@ const SideButton = /*#__PURE__*/forwardRef((_ref3, ref) => {
99
101
  space: 1,
100
102
  iconPosition: directionToSide[direction],
101
103
  iconProps: iconProps,
102
- children: showLabel && /*#__PURE__*/_jsx(Text, {
104
+ children: displayLabel && /*#__PURE__*/_jsx(Text, {
103
105
  style: textStyles,
104
106
  children: label
105
107
  })
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { viewports } from '@telus-uds/system-constants';
4
+ import { useResponsiveProp } from '../utils';
5
+ /**
6
+ * Responsive conditionally renders children based on whether the viewport matches the provided
7
+ * min and max viewports.
8
+ *
9
+ * In SSR, like other viewport utilities, it treats the viewport as `xs` both in SSR itself and
10
+ * during first hydration on the client side; then if the viewport is not `xs`, it re-renders
11
+ * after hydration. This may cause a layout shift on devices other than the narrowest.
12
+ */
13
+
14
+ import { Fragment as _Fragment } from "react/jsx-runtime";
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+
17
+ const Responsive = _ref => {
18
+ let {
19
+ min = 'xs',
20
+ max,
21
+ children
22
+ } = _ref;
23
+ // Start returning children at the 'min' viewport or greater
24
+ const byViewports = {
25
+ [min]: children
26
+ };
27
+
28
+ if (max && max !== 'xl') {
29
+ // Stop returning children at the viewport one above 'max' or greater
30
+ const maxIndex = viewports.keys.indexOf(max);
31
+ const maxPlusOne = maxIndex >= 0 ? viewports.keys[maxIndex + 1] : null;
32
+ if (maxPlusOne) byViewports[maxPlusOne] = null;
33
+ }
34
+
35
+ return /*#__PURE__*/_jsx(_Fragment, {
36
+ children: useResponsiveProp(byViewports, null)
37
+ });
38
+ };
39
+
40
+ Responsive.propTypes = {
41
+ min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
42
+ max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
43
+ children: PropTypes.node.isRequired
44
+ };
45
+ export default Responsive;
@@ -0,0 +1,2 @@
1
+ import Responsive from './Responsive';
2
+ export default Responsive;
@@ -1,16 +1,13 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import View from "react-native-web/dist/exports/View";
3
- import StyleSheet from "react-native-web/dist/exports/StyleSheet";
4
3
  import PropTypes from 'prop-types';
5
4
  import { useThemeTokens, useThemeTokensCallback } from '../ThemeProvider';
6
5
  import { a11yProps, getTokensPropType, selectSystemProps, selectTokens, useInputValue, useSpacingScale, textInputHandlerProps, textInputProps, variantProp, viewProps } from '../utils';
7
6
  import TextInputBase from '../TextInput/TextInputBase';
8
7
  import ButtonBase from '../Button/ButtonBase';
9
- import StackView from '../StackView';
10
8
  import useCopy from '../utils/useCopy';
11
9
  import dictionary from './dictionary';
12
10
  import { jsx as _jsx } from "react/jsx-runtime";
13
- import { jsxs as _jsxs } from "react/jsx-runtime";
14
11
  const [selectContainerProps, selectedContainerPropTypes] = selectSystemProps([a11yProps, viewProps]);
15
12
  const [selectInputProps, selectedInputPropTypes] = selectSystemProps([textInputHandlerProps, textInputProps]);
16
13
 
@@ -39,20 +36,11 @@ const selectInputTokens = _ref => {
39
36
 
40
37
  const selectButtonTokens = tokens => selectTokens('Button', tokens);
41
38
 
42
- const selectIconsContainerStyle = _ref2 => {
43
- let {
44
- paddingRight
45
- } = _ref2;
46
- return {
47
- paddingRight
48
- };
49
- };
50
-
51
- const selectIconTokens = _ref3 => {
39
+ const selectIconTokens = _ref2 => {
52
40
  let {
53
41
  iconSize,
54
42
  iconColor
55
- } = _ref3;
43
+ } = _ref2;
56
44
  return {
57
45
  color: iconColor,
58
46
  size: iconSize
@@ -73,7 +61,7 @@ const selectIconTokens = _ref3 => {
73
61
  */
74
62
 
75
63
 
76
- const Search = /*#__PURE__*/forwardRef((_ref4, ref) => {
64
+ const Search = /*#__PURE__*/forwardRef((_ref3, ref) => {
77
65
  let {
78
66
  initialValue,
79
67
  value,
@@ -88,7 +76,7 @@ const Search = /*#__PURE__*/forwardRef((_ref4, ref) => {
88
76
  tokens,
89
77
  variant,
90
78
  ...rest
91
- } = _ref4;
79
+ } = _ref3;
92
80
  const {
93
81
  currentValue = '',
94
82
  setValue
@@ -122,8 +110,11 @@ const Search = /*#__PURE__*/forwardRef((_ref4, ref) => {
122
110
  };
123
111
 
124
112
  const handleClear = event => {
113
+ var _ref$current;
114
+
125
115
  setValue('', event);
126
- if (onClear !== undefined) onClear('', event);
116
+ onClear === null || onClear === void 0 ? void 0 : onClear('', event);
117
+ ref === null || ref === void 0 ? void 0 : (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.focus();
127
118
  };
128
119
 
129
120
  const handleFocus = event => {
@@ -140,10 +131,8 @@ const Search = /*#__PURE__*/forwardRef((_ref4, ref) => {
140
131
  testID,
141
132
  ...containerProps
142
133
  } = selectContainerProps(rest);
143
- return /*#__PURE__*/_jsxs(View, {
144
- style: staticStyles.container,
145
- ...containerProps,
146
- children: [/*#__PURE__*/_jsx(TextInputBase, {
134
+ return /*#__PURE__*/_jsx(View, { ...containerProps,
135
+ children: /*#__PURE__*/_jsx(TextInputBase, {
147
136
  nativeID: nativeID,
148
137
  testID: testID,
149
138
  ...selectInputProps(rest),
@@ -163,35 +152,29 @@ const Search = /*#__PURE__*/forwardRef((_ref4, ref) => {
163
152
  onChange: setValue,
164
153
  onSubmitEditing: handleSubmit,
165
154
  onFocus: handleFocus,
166
- accessibilityLabel: a11yLabelText
167
- }), /*#__PURE__*/_jsx(View, {
168
- style: [staticStyles.iconsContainer, selectIconsContainerStyle(themeTokens)],
169
- children: /*#__PURE__*/_jsxs(StackView, {
170
- direction: "row",
171
- space: buttonsGap,
172
- children: [ClearButtonIcon && !isEmpty && /*#__PURE__*/_jsx(ButtonBase, {
173
- onPress: handleClear,
174
- inactive: inactive,
175
- accessibilityRole: "button",
176
- accessibilityLabel: getCopy('clearButtonAccessibilityLabel'),
177
- tokens: appearances => selectButtonTokens(getButtonTokens(appearances)),
178
- children: buttonState => /*#__PURE__*/_jsx(ClearButtonIcon, { ...selectIconTokens(getButtonTokens(buttonState))
179
- })
180
- }), SubmitButtonIcon && /*#__PURE__*/_jsx(ButtonBase, {
181
- onPress: handleSubmit,
182
- inactive: inactive,
183
- accessibilityRole: "button",
184
- accessibilityLabel: getCopy('submitButtonAccessibilityLabel'),
185
- tokens: buttonState => selectButtonTokens(getButtonTokens({ ...buttonState,
155
+ accessibilityLabel: a11yLabelText,
156
+ buttons: [ClearButtonIcon && !isEmpty && /*#__PURE__*/_jsx(ButtonBase, {
157
+ accessibilityLabel: getCopy('clearButtonAccessibilityLabel'),
158
+ accessibilityRole: "button",
159
+ inactive: inactive,
160
+ onPress: handleClear,
161
+ tokens: appearances => selectButtonTokens(getButtonTokens(appearances)),
162
+ children: buttonState => /*#__PURE__*/_jsx(ClearButtonIcon, { ...selectIconTokens(getButtonTokens(buttonState))
163
+ })
164
+ }, "clear"), SubmitButtonIcon && /*#__PURE__*/_jsx(ButtonBase, {
165
+ accessibilityLabel: getCopy('submitButtonAccessibilityLabel'),
166
+ accessibilityRole: "button",
167
+ inactive: inactive,
168
+ onPress: handleSubmit,
169
+ tokens: buttonState => selectButtonTokens(getButtonTokens({ ...buttonState,
170
+ priority: 'high'
171
+ })),
172
+ children: buttonState => /*#__PURE__*/_jsx(SubmitButtonIcon, { ...selectIconTokens(getButtonTokens({ ...buttonState,
186
173
  priority: 'high'
187
- })),
188
- children: buttonState => /*#__PURE__*/_jsx(SubmitButtonIcon, { ...selectIconTokens(getButtonTokens({ ...buttonState,
189
- priority: 'high'
190
- }))
191
- })
192
- })]
193
- })
194
- })]
174
+ }))
175
+ })
176
+ }, "submit")]
177
+ })
195
178
  });
196
179
  });
197
180
  Search.displayName = 'Search';
@@ -255,15 +238,4 @@ Search.propTypes = { ...selectedContainerPropTypes,
255
238
  tokens: getTokensPropType('Search'),
256
239
  variant: variantProp.propType
257
240
  };
258
- export default Search;
259
- const staticStyles = StyleSheet.create({
260
- container: {// No styles needed here except the View defaults (position: relative etc)
261
- },
262
- iconsContainer: {
263
- position: 'absolute',
264
- right: 0,
265
- top: 0,
266
- bottom: 0,
267
- justifyContent: 'center'
268
- }
269
- });
241
+ export default Search;
@@ -4,7 +4,8 @@ import View from "react-native-web/dist/exports/View";
4
4
  import Platform from "react-native-web/dist/exports/Platform";
5
5
  import NativePicker from 'react-native-picker-select';
6
6
  import { a11yProps, componentPropType } from '../utils';
7
- import Group from './Group'; // styling of the native input is very limited, most of the styles have to be applied to an additional View
7
+ import Group from './Group';
8
+ import { ANDROID_HEIGHT_OFFSET, ANDROID_HORIZONTAL_PADDING_OFFSET, ANDROID_DEFAULT_PADDING } from './constants'; // Styling of the native input is very limited, most of the styles have to be applied to an additional View
8
9
 
9
10
  import { jsx as _jsx } from "react/jsx-runtime";
10
11
  import { Fragment as _Fragment } from "react/jsx-runtime";
@@ -12,28 +13,29 @@ import { Fragment as _Fragment } from "react/jsx-runtime";
12
13
  const selectAndroidInputStyles = _ref => {
13
14
  let {
14
15
  height = 0,
15
- paddingBottom = 0,
16
- paddingTop = 0,
17
- borderWidth = 0,
18
16
  color
19
17
  } = _ref;
20
18
  return {
21
- height: height - paddingTop - paddingBottom - 2 * borderWidth,
19
+ height,
20
+ paddingBottom: 0,
21
+ paddingTop: 0,
22
22
  color
23
23
  };
24
- }; // the native input has a side padding of 8px, which can't be adjusted, so we have to account for that in the container
24
+ }; // The native input has a side padding of 8px, which can't be adjusted, so we have to account for that in the container
25
25
 
26
26
 
27
27
  const selectAndroidContainerStyles = _ref2 => {
28
28
  let {
29
- paddingLeft = 0,
30
- paddingRight = 0,
29
+ paddingLeft = ANDROID_DEFAULT_PADDING,
30
+ paddingRight = ANDROID_DEFAULT_PADDING,
31
31
  ...rest
32
32
  } = _ref2;
33
- return {
34
- paddingLeft: paddingLeft > 8 ? paddingLeft - 8 : 0,
35
- paddingRight: paddingRight > 8 ? paddingRight - 8 : 0,
36
- ...rest
33
+ return { ...rest,
34
+ paddingLeft: paddingLeft > ANDROID_HORIZONTAL_PADDING_OFFSET ? paddingLeft - ANDROID_HORIZONTAL_PADDING_OFFSET : ANDROID_DEFAULT_PADDING,
35
+ paddingRight: paddingRight > ANDROID_HORIZONTAL_PADDING_OFFSET ? paddingRight - ANDROID_HORIZONTAL_PADDING_OFFSET : ANDROID_DEFAULT_PADDING,
36
+ paddingBottom: ANDROID_DEFAULT_PADDING,
37
+ paddingTop: ANDROID_DEFAULT_PADDING,
38
+ height: rest.height + ANDROID_HEIGHT_OFFSET
37
39
  };
38
40
  };
39
41
 
@@ -49,7 +51,7 @@ const Picker = /*#__PURE__*/forwardRef((_ref3, ref) => {
49
51
  placeholder,
50
52
  ...rest
51
53
  } = _ref3;
52
- // ungroup items, since there's no way to support groups on native
54
+ // Ungroup items, since there's no way to support groups on native
53
55
  const flatChildren = Children.toArray(children).flatMap(child => {
54
56
  if (child.type === Group) {
55
57
  return child.props.children;
@@ -7,6 +7,7 @@ import { applyTextStyles, useThemeTokens, applyOuterBorder, useTheme } from '../
7
7
  import { a11yProps, componentPropType, getTokensPropType, inputSupportsProps, selectSystemProps, useInputValue, variantProp, viewProps } from '../utils';
8
8
  import Picker from './Picker';
9
9
  import InputSupports from '../InputSupports';
10
+ import { ANDROID_VALIDATION_ICON_CONTAINER_OFFSET } from './constants';
10
11
  import { jsx as _jsx } from "react/jsx-runtime";
11
12
  import { jsxs as _jsxs } from "react/jsx-runtime";
12
13
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, inputSupportsProps, viewProps]);
@@ -142,7 +143,11 @@ const selectValidationIconContainerStyles = _ref6 => {
142
143
  } = _ref6;
143
144
  return {
144
145
  paddingRight: icon ? paddingRight + iconSize : paddingRight,
145
- paddingBottom
146
+ ...(Platform.OS === 'android' ? {
147
+ paddingBottom: paddingBottom + ANDROID_VALIDATION_ICON_CONTAINER_OFFSET
148
+ } : {
149
+ paddingBottom
150
+ })
146
151
  };
147
152
  };
148
153
  /**
@@ -0,0 +1,5 @@
1
+ // Because Android
2
+ export const ANDROID_VALIDATION_ICON_CONTAINER_OFFSET = 5;
3
+ export const ANDROID_HEIGHT_OFFSET = 12;
4
+ export const ANDROID_HORIZONTAL_PADDING_OFFSET = 8;
5
+ export const ANDROID_DEFAULT_PADDING = 0;
@@ -185,7 +185,8 @@ const Step = _ref7 => {
185
185
  space: 0,
186
186
  tokens: {
187
187
  alignItems: 'center',
188
- flexGrow: 0
188
+ flexGrow: 0,
189
+ justifyContent: 'center'
189
190
  },
190
191
  children: [/*#__PURE__*/_jsx(View, {
191
192
  style: [staticStyles.connector, !isFirst && selectConnectorStyles(themeTokens, isActive)]
@@ -15,7 +15,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
15
15
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
16
16
  const [selectItemProps, selectedItemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, pressProps, viewProps]);
17
17
 
18
- const selectIconTextTokens = _ref => {
18
+ const separateIconTextTokens = (_ref, returnRest) => {
19
19
  let {
20
20
  icon,
21
21
  iconPosition,
@@ -27,9 +27,10 @@ const selectIconTextTokens = _ref => {
27
27
  iconAlignSelf,
28
28
  iconPadding,
29
29
  iconTranslateX,
30
- iconTranslateY
30
+ iconTranslateY,
31
+ ...rest
31
32
  } = _ref;
32
- return {
33
+ return returnRest ? rest : {
33
34
  icon,
34
35
  iconPosition,
35
36
  iconSpace,
@@ -54,6 +55,10 @@ const selectIconTextTokens = _ref => {
54
55
  };
55
56
  };
56
57
 
58
+ const selectIconTextTokens = tokens => separateIconTextTokens(tokens, false);
59
+
60
+ const selectNonIconTextTokens = tokens => separateIconTextTokens(tokens, true);
61
+
57
62
  const Tags = /*#__PURE__*/forwardRef((_ref2, ref) => {
58
63
  let {
59
64
  variant,
@@ -82,7 +87,8 @@ const Tags = /*#__PURE__*/forwardRef((_ref2, ref) => {
82
87
  } = themeTokens;
83
88
  const getItemTokens = useThemeTokensCallback('TagsItem', tokens, variant);
84
89
 
85
- const getButtonTokens = buttonState => selectTokens('Button', getItemTokens(buttonState));
90
+ const getButtonTokens = buttonState => // Remove icon-text-related tokens, since we want to handle them ourselves, not use ButtonBase's handling
91
+ selectTokens('Button', selectNonIconTextTokens(getItemTokens(buttonState)));
86
92
 
87
93
  const {
88
94
  currentValues,
@@ -1,4 +1,5 @@
1
1
  import React, { forwardRef } from 'react';
2
+ import PropTypes from 'prop-types';
2
3
  import { a11yProps, focusHandlerProps, getTokensPropType, inputSupportsProps, selectSystemProps, textInputHandlerProps, textInputProps, variantProp, viewProps } from '../utils';
3
4
  import InputSupports from '../InputSupports';
4
5
  import TextInputBase from './TextInputBase';
@@ -61,6 +62,11 @@ const TextInput = /*#__PURE__*/forwardRef((_ref, ref) => {
61
62
  TextInput.displayName = 'TextInput';
62
63
  TextInput.propTypes = { ...selectedSystemPropTypes,
63
64
  ...textInputPropTypes,
65
+
66
+ /**
67
+ * A callback which if provided will get a clear button rendered and will be called whenever that button gets pressed.
68
+ */
69
+ onClear: PropTypes.func,
64
70
  tokens: getTokensPropType('TextInput'),
65
71
  variant: variantProp.propType
66
72
  };