@telus-uds/components-base 3.28.1 → 3.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,9 +1,18 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Fri, 20 Feb 2026 23:53:11 GMT and should not be manually modified.
3
+ This log was last generated on Tue, 03 Mar 2026 23:02:55 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.28.2
8
+
9
+ Tue, 03 Mar 2026 23:02:55 GMT
10
+
11
+ ### Patches
12
+
13
+ - `Carousel`: inverse variant navigation arrows fixed by always using raised style even in the inverse state (josue.higueros@telus.com)
14
+ - `Autocomplete`: add the ability to show all values and filter them (josue.higueroscalderon@telus.com)
15
+
7
16
  ## 3.28.1
8
17
 
9
18
  Fri, 20 Feb 2026 23:53:11 GMT
@@ -51,22 +51,36 @@ const highlightAllMatches = function (str) {
51
51
  tokens: {
52
52
  color: resultsTextColor
53
53
  },
54
- children: matchIndexes.reduce((acc, matchIndex, index) => [...acc,
55
- // Add a piece of the string up to the first occurrence of the substring
56
- index === 0 && (str.slice(0, matchIndex) ?? ''),
57
- /*#__PURE__*/
58
- // Unbold the occurrence of the substring (while keeping the original casing)
59
- (0, _jsxRuntime.jsx)(_Typography.default, {
60
- variant: {
61
- bold: true
62
- },
63
- tokens: {
64
- color: resultsTextColor
65
- },
66
- children: str.slice(matchIndex, matchIndex + substring.length)
67
- }, matchIndex),
68
- // Add the rest of the string until the next occurrence or the end of it
69
- str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length)], [])
54
+ children: matchIndexes.reduce((acc, matchIndex, index) => {
55
+ const prefix = index === 0 ? str.slice(0, matchIndex) : null;
56
+ const match = str.slice(matchIndex, matchIndex + substring.length);
57
+ const suffix = str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length);
58
+ return [...acc, prefix ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
59
+ variant: {
60
+ bold: false
61
+ },
62
+ tokens: {
63
+ color: resultsTextColor
64
+ },
65
+ children: prefix
66
+ }, `pre-${matchIndex}`) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
67
+ variant: {
68
+ bold: true
69
+ },
70
+ tokens: {
71
+ color: resultsTextColor
72
+ },
73
+ children: match
74
+ }, matchIndex), suffix ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
75
+ variant: {
76
+ bold: false
77
+ },
78
+ tokens: {
79
+ color: resultsTextColor
80
+ },
81
+ children: suffix
82
+ }, `post-${matchIndex}`) : null];
83
+ }, []).filter(Boolean)
70
84
  })
71
85
  );
72
86
  };
@@ -100,12 +114,14 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
100
114
  isLoading = false,
101
115
  items,
102
116
  maxSuggestions = _constants.DEFAULT_MAX_SUGGESTIONS,
117
+ maxDropdownHeight = _constants.DEFAULT_MAX_DROPDOWN_HEIGHT,
103
118
  minToSuggestion = _constants.DEFAULT_MIN_TO_SUGGESTION,
104
119
  noResults,
105
120
  onChange,
106
121
  onClear,
107
122
  onSelect,
108
123
  readOnly,
124
+ showOptionsOnFocus = false,
109
125
  validation,
110
126
  value,
111
127
  helpText = '',
@@ -154,7 +170,7 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
154
170
  hint,
155
171
  label: inputLabel
156
172
  } = supportsProps;
157
- const hintExpansionEnabled = isFocused && helpText && !currentValue;
173
+ const hintExpansionEnabled = isFocused && !!helpText && !currentValue;
158
174
  const {
159
175
  overlaidPosition,
160
176
  sourceRef: inputRef,
@@ -208,9 +224,10 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
208
224
  }
209
225
  };
210
226
  const handleChange = newValue => {
211
- onChange?.(newValue || '');
227
+ onChange?.(newValue);
212
228
  setCurrentValue(newValue);
213
- setIsExpanded(newValue?.length >= minToSuggestion);
229
+ const shouldExpand = newValue?.length >= minToSuggestion || showOptionsOnFocus && isFocused && newValue?.length === 0;
230
+ setIsExpanded(shouldExpand);
214
231
  if (!isControlled && initialItems !== undefined) {
215
232
  setCurrentItems(initialItems.filter(_ref3 => {
216
233
  let {
@@ -222,25 +239,29 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
222
239
  };
223
240
  const handleSelect = selectedId => {
224
241
  onSelect?.(selectedId);
225
- const {
226
- label: newValue,
227
- nested,
228
- title
229
- } = (isControlled ? items : currentItems)?.find(_ref4 => {
242
+ const selectedItem = (isControlled ? items : currentItems)?.find(_ref4 => {
230
243
  let {
231
244
  id
232
245
  } = _ref4;
233
246
  return id === selectedId;
234
247
  });
248
+ const {
249
+ label,
250
+ nested,
251
+ title
252
+ } = selectedItem;
235
253
  if (title) return;
236
254
  if (!nested) {
237
255
  setNestedSelectedValue(null);
238
- onChange?.(newValue);
256
+ onChange?.(label);
239
257
  setIsExpanded(false);
258
+ setCurrentValue(label);
259
+ }
260
+ if (!isControlled && inputRef?.current) inputRef.current.value = label;
261
+ if (nested) {
262
+ setNestedSelectedValue(label);
263
+ setCurrentValue(label);
240
264
  }
241
- setCurrentValue(newValue);
242
- if (!isControlled && inputRef?.current) inputRef.current.value = newValue;
243
- if (nested) setNestedSelectedValue(newValue);
244
265
  inputRef.current.focus();
245
266
  };
246
267
 
@@ -288,15 +309,33 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
288
309
  };
289
310
  }, [inputRef]);
290
311
  const handleClose = event => {
291
- if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27') || event.type === 'click' && !openOverlayRef?.current?.contains(event.target) || event.type === 'touchstart' && openOverlayRef?.current && event.touches[0].target && !openOverlayRef?.current?.contains(event.touches[0].target)) {
312
+ if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) {
292
313
  setIsExpanded(false);
293
314
  setNestedSelectedValue(null);
294
- } else if (event.type === 'keydown' && (event.key === 'ArrowDown' || event.key === 'Tab') && isExpanded && !isLoading && targetRef?.current) {
315
+ return;
316
+ }
317
+ if (event.type === 'keydown' && (event.key === 'ArrowDown' || event.key === 'Tab') && isExpanded && !isLoading && targetRef?.current) {
295
318
  event.preventDefault();
296
319
  targetRef.current.focus();
320
+ return;
321
+ }
322
+ if (event.type === 'click' || event.type === 'touchstart') {
323
+ const clickTarget = event.type === 'click' ? event.target : event.touches[0]?.target;
324
+ const isOutsideOverlay = openOverlayRef?.current && !openOverlayRef.current.contains(clickTarget);
325
+ const isOutsideInput = inputRef?.current && !inputRef.current.contains(clickTarget);
326
+ if (isOutsideOverlay && isOutsideInput) {
327
+ setIsExpanded(false);
328
+ setNestedSelectedValue(null);
329
+ }
297
330
  }
298
331
  };
299
- const itemsToShow = currentValue ? itemsToSuggest(highlight(isControlled ? items : currentItems, currentValue, resultsTextColor)) : [];
332
+ // Calculate items to show based on current state
333
+ let itemsToShow = [];
334
+ if (currentValue?.length > 0) {
335
+ itemsToShow = itemsToSuggest(highlight(isControlled ? items : currentItems, currentValue, resultsTextColor));
336
+ } else if (showOptionsOnFocus && isFocused) {
337
+ itemsToShow = itemsToSuggest(isControlled ? items : currentItems || initialItems);
338
+ }
300
339
  const helpTextToShow = isFocused && !currentValue ? helpText : noResults ?? getCopy('noResults');
301
340
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
302
341
  style: staticStyles.container,
@@ -333,9 +372,15 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
333
372
  onChange: handleChange,
334
373
  onFocus: () => {
335
374
  setisFocused(true);
375
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
376
+ setIsExpanded(true);
377
+ }
336
378
  },
337
379
  onBlur: () => {
338
380
  setisFocused(false);
381
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
382
+ setIsExpanded(false);
383
+ }
339
384
  },
340
385
  onClear: onClear,
341
386
  onKeyPress: handleClose,
@@ -367,12 +412,13 @@ const Autocomplete = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
367
412
  })
368
413
  });
369
414
  }
370
- }), (isExpanded || hintExpansionEnabled) && isInputVisible && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
415
+ }), (isExpanded || hintExpansionEnabled) && isInputVisible && (itemsToShow.length > 0 || isExpanded || hintExpansionEnabled) && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
371
416
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Listbox.default.Overlay, {
372
417
  overlaidPosition: overlaidPosition,
373
418
  isReady: isReady,
374
419
  minWidth: fullWidth ? inputWidth : _constants.MIN_LISTBOX_WIDTH,
375
420
  maxWidth: inputWidth,
421
+ maxHeight: maxDropdownHeight,
376
422
  onLayout: handleMeasure,
377
423
  tokens: restOfTokens,
378
424
  ref: openOverlayRef,
@@ -456,6 +502,10 @@ Autocomplete.propTypes = {
456
502
  * Maximum number of suggestions provided at the same time
457
503
  */
458
504
  maxSuggestions: _propTypes.default.number,
505
+ /**
506
+ * Maximum height (in pixels) of the dropdown before scrolling is enabled
507
+ */
508
+ maxDropdownHeight: _propTypes.default.number,
459
509
  /**
460
510
  * Text or JSX to render when no results are available
461
511
  */
@@ -476,6 +526,10 @@ Autocomplete.propTypes = {
476
526
  * Callback function to be called when an item is selected from the list
477
527
  */
478
528
  onSelect: _propTypes.default.func,
529
+ /**
530
+ * When true, displays all available options when the input receives focus (even without typing)
531
+ */
532
+ showOptionsOnFocus: _propTypes.default.bool,
479
533
  /**
480
534
  * Input value for controlled usage
481
535
  */
@@ -3,8 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.MIN_LISTBOX_WIDTH = exports.INPUT_LEFT_PADDING = exports.DEFAULT_MIN_TO_SUGGESTION = exports.DEFAULT_MAX_SUGGESTIONS = void 0;
6
+ exports.MIN_LISTBOX_WIDTH = exports.INPUT_LEFT_PADDING = exports.DEFAULT_MIN_TO_SUGGESTION = exports.DEFAULT_MAX_SUGGESTIONS = exports.DEFAULT_MAX_DROPDOWN_HEIGHT = void 0;
7
7
  const DEFAULT_MIN_TO_SUGGESTION = exports.DEFAULT_MIN_TO_SUGGESTION = 1;
8
8
  const DEFAULT_MAX_SUGGESTIONS = exports.DEFAULT_MAX_SUGGESTIONS = 5;
9
+ const DEFAULT_MAX_DROPDOWN_HEIGHT = exports.DEFAULT_MAX_DROPDOWN_HEIGHT = 336; // Approximately 7 items (48px each)
9
10
  const INPUT_LEFT_PADDING = exports.INPUT_LEFT_PADDING = 16;
10
11
  const MIN_LISTBOX_WIDTH = exports.MIN_LISTBOX_WIDTH = 288;
@@ -924,8 +924,7 @@ const Carousel = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
924
924
  // Related discussion - https://github.com/telus/universal-design-system/issues/1549
925
925
  const previousNextIconButtonVariants = {
926
926
  size: previousNextIconSize,
927
- raised: !variant?.inverse && true,
928
- inverse: variant?.inverse
927
+ raised: true
929
928
  };
930
929
  const getCopyWithPlaceholders = _react.default.useCallback(copyKey => {
931
930
  const copyText = getCopy(copyKey).replace(/%\{title\}/g, title).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, totalItems);
@@ -35,6 +35,7 @@ const DropdownOverlay = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
35
35
  isReady = false,
36
36
  overlaidPosition,
37
37
  maxWidth,
38
+ maxHeight,
38
39
  minWidth,
39
40
  onLayout,
40
41
  tokens,
@@ -50,12 +51,16 @@ const DropdownOverlay = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
50
51
  maxWidth,
51
52
  minWidth
52
53
  }, staticStyles.positioner, !isReady && staticStyles.hidden],
54
+ onMouseDown: e => {
55
+ e.preventDefault();
56
+ },
53
57
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Card.default, {
54
58
  tokens: {
55
59
  shadow: systemTokens.shadow,
56
60
  borderRadius: systemTokens.borderRadius,
57
61
  ...(_Platform.default.OS === 'web' && {
58
- overflowY: 'hidden'
62
+ maxHeight,
63
+ overflowY: 'auto'
59
64
  }),
60
65
  paddingBottom: paddingVertical,
61
66
  paddingTop: paddingVertical,
@@ -85,6 +90,7 @@ DropdownOverlay.propTypes = {
85
90
  width: _propTypes.default.number
86
91
  }),
87
92
  maxWidth: _propTypes.default.number,
93
+ maxHeight: _propTypes.default.number,
88
94
  minWidth: _propTypes.default.number,
89
95
  onLayout: _propTypes.default.func,
90
96
  tokens: _propTypes.default.object,
@@ -129,9 +129,9 @@ const PressableItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
129
129
  onPress(event);
130
130
  },
131
131
  children: pressableState => {
132
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Text.default, {
132
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
133
133
  style: selectTextStyles(resolveButtonTokens(pressableState)),
134
- children: [children, " "]
134
+ children: children
135
135
  });
136
136
  }
137
137
  });
@@ -278,8 +278,8 @@ const TextInputBase = /*#__PURE__*/_react.default.forwardRef((_ref8, ref) => {
278
278
  }
279
279
  }, [element, pattern]);
280
280
  const handleChangeText = event => {
281
- const text = event.nativeEvent?.text || event.target?.value;
282
- let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') : text;
281
+ const text = event.nativeEvent?.text ?? event.target?.value;
282
+ let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') || undefined : text;
283
283
  if (type === 'card' && filteredText) {
284
284
  const formattedValue = filteredText.replace(/[^a-zA-Z0-9]/g, '');
285
285
  const regex = new RegExp(`([a-zA-Z0-9]{4})(?=[a-zA-Z0-9])`, 'g');
@@ -14,7 +14,7 @@ import { TextInput } from '../TextInput';
14
14
  import InputSupports from '../InputSupports';
15
15
  import Loading from './Loading';
16
16
  import Suggestions from './Suggestions';
17
- import { DEFAULT_MAX_SUGGESTIONS, DEFAULT_MIN_TO_SUGGESTION, INPUT_LEFT_PADDING, MIN_LISTBOX_WIDTH } from './constants';
17
+ import { DEFAULT_MAX_SUGGESTIONS, DEFAULT_MIN_TO_SUGGESTION, DEFAULT_MAX_DROPDOWN_HEIGHT, INPUT_LEFT_PADDING, MIN_LISTBOX_WIDTH } from './constants';
18
18
  import dictionary from './dictionary';
19
19
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
20
20
  const staticStyles = StyleSheet.create({
@@ -44,22 +44,36 @@ const highlightAllMatches = function (str) {
44
44
  tokens: {
45
45
  color: resultsTextColor
46
46
  },
47
- children: matchIndexes.reduce((acc, matchIndex, index) => [...acc,
48
- // Add a piece of the string up to the first occurrence of the substring
49
- index === 0 && (str.slice(0, matchIndex) ?? ''),
50
- /*#__PURE__*/
51
- // Unbold the occurrence of the substring (while keeping the original casing)
52
- _jsx(Typography, {
53
- variant: {
54
- bold: true
55
- },
56
- tokens: {
57
- color: resultsTextColor
58
- },
59
- children: str.slice(matchIndex, matchIndex + substring.length)
60
- }, matchIndex),
61
- // Add the rest of the string until the next occurrence or the end of it
62
- str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length)], [])
47
+ children: matchIndexes.reduce((acc, matchIndex, index) => {
48
+ const prefix = index === 0 ? str.slice(0, matchIndex) : null;
49
+ const match = str.slice(matchIndex, matchIndex + substring.length);
50
+ const suffix = str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length);
51
+ return [...acc, prefix ? /*#__PURE__*/_jsx(Typography, {
52
+ variant: {
53
+ bold: false
54
+ },
55
+ tokens: {
56
+ color: resultsTextColor
57
+ },
58
+ children: prefix
59
+ }, `pre-${matchIndex}`) : null, /*#__PURE__*/_jsx(Typography, {
60
+ variant: {
61
+ bold: true
62
+ },
63
+ tokens: {
64
+ color: resultsTextColor
65
+ },
66
+ children: match
67
+ }, matchIndex), suffix ? /*#__PURE__*/_jsx(Typography, {
68
+ variant: {
69
+ bold: false
70
+ },
71
+ tokens: {
72
+ color: resultsTextColor
73
+ },
74
+ children: suffix
75
+ }, `post-${matchIndex}`) : null];
76
+ }, []).filter(Boolean)
63
77
  })
64
78
  );
65
79
  };
@@ -93,12 +107,14 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
93
107
  isLoading = false,
94
108
  items,
95
109
  maxSuggestions = DEFAULT_MAX_SUGGESTIONS,
110
+ maxDropdownHeight = DEFAULT_MAX_DROPDOWN_HEIGHT,
96
111
  minToSuggestion = DEFAULT_MIN_TO_SUGGESTION,
97
112
  noResults,
98
113
  onChange,
99
114
  onClear,
100
115
  onSelect,
101
116
  readOnly,
117
+ showOptionsOnFocus = false,
102
118
  validation,
103
119
  value,
104
120
  helpText = '',
@@ -147,7 +163,7 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
147
163
  hint,
148
164
  label: inputLabel
149
165
  } = supportsProps;
150
- const hintExpansionEnabled = isFocused && helpText && !currentValue;
166
+ const hintExpansionEnabled = isFocused && !!helpText && !currentValue;
151
167
  const {
152
168
  overlaidPosition,
153
169
  sourceRef: inputRef,
@@ -201,9 +217,10 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
201
217
  }
202
218
  };
203
219
  const handleChange = newValue => {
204
- onChange?.(newValue || '');
220
+ onChange?.(newValue);
205
221
  setCurrentValue(newValue);
206
- setIsExpanded(newValue?.length >= minToSuggestion);
222
+ const shouldExpand = newValue?.length >= minToSuggestion || showOptionsOnFocus && isFocused && newValue?.length === 0;
223
+ setIsExpanded(shouldExpand);
207
224
  if (!isControlled && initialItems !== undefined) {
208
225
  setCurrentItems(initialItems.filter(_ref3 => {
209
226
  let {
@@ -215,25 +232,29 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
215
232
  };
216
233
  const handleSelect = selectedId => {
217
234
  onSelect?.(selectedId);
218
- const {
219
- label: newValue,
220
- nested,
221
- title
222
- } = (isControlled ? items : currentItems)?.find(_ref4 => {
235
+ const selectedItem = (isControlled ? items : currentItems)?.find(_ref4 => {
223
236
  let {
224
237
  id
225
238
  } = _ref4;
226
239
  return id === selectedId;
227
240
  });
241
+ const {
242
+ label,
243
+ nested,
244
+ title
245
+ } = selectedItem;
228
246
  if (title) return;
229
247
  if (!nested) {
230
248
  setNestedSelectedValue(null);
231
- onChange?.(newValue);
249
+ onChange?.(label);
232
250
  setIsExpanded(false);
251
+ setCurrentValue(label);
252
+ }
253
+ if (!isControlled && inputRef?.current) inputRef.current.value = label;
254
+ if (nested) {
255
+ setNestedSelectedValue(label);
256
+ setCurrentValue(label);
233
257
  }
234
- setCurrentValue(newValue);
235
- if (!isControlled && inputRef?.current) inputRef.current.value = newValue;
236
- if (nested) setNestedSelectedValue(newValue);
237
258
  inputRef.current.focus();
238
259
  };
239
260
 
@@ -281,15 +302,33 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
281
302
  };
282
303
  }, [inputRef]);
283
304
  const handleClose = event => {
284
- if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27') || event.type === 'click' && !openOverlayRef?.current?.contains(event.target) || event.type === 'touchstart' && openOverlayRef?.current && event.touches[0].target && !openOverlayRef?.current?.contains(event.touches[0].target)) {
305
+ if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) {
285
306
  setIsExpanded(false);
286
307
  setNestedSelectedValue(null);
287
- } else if (event.type === 'keydown' && (event.key === 'ArrowDown' || event.key === 'Tab') && isExpanded && !isLoading && targetRef?.current) {
308
+ return;
309
+ }
310
+ if (event.type === 'keydown' && (event.key === 'ArrowDown' || event.key === 'Tab') && isExpanded && !isLoading && targetRef?.current) {
288
311
  event.preventDefault();
289
312
  targetRef.current.focus();
313
+ return;
314
+ }
315
+ if (event.type === 'click' || event.type === 'touchstart') {
316
+ const clickTarget = event.type === 'click' ? event.target : event.touches[0]?.target;
317
+ const isOutsideOverlay = openOverlayRef?.current && !openOverlayRef.current.contains(clickTarget);
318
+ const isOutsideInput = inputRef?.current && !inputRef.current.contains(clickTarget);
319
+ if (isOutsideOverlay && isOutsideInput) {
320
+ setIsExpanded(false);
321
+ setNestedSelectedValue(null);
322
+ }
290
323
  }
291
324
  };
292
- const itemsToShow = currentValue ? itemsToSuggest(highlight(isControlled ? items : currentItems, currentValue, resultsTextColor)) : [];
325
+ // Calculate items to show based on current state
326
+ let itemsToShow = [];
327
+ if (currentValue?.length > 0) {
328
+ itemsToShow = itemsToSuggest(highlight(isControlled ? items : currentItems, currentValue, resultsTextColor));
329
+ } else if (showOptionsOnFocus && isFocused) {
330
+ itemsToShow = itemsToSuggest(isControlled ? items : currentItems || initialItems);
331
+ }
293
332
  const helpTextToShow = isFocused && !currentValue ? helpText : noResults ?? getCopy('noResults');
294
333
  return /*#__PURE__*/_jsxs(View, {
295
334
  style: staticStyles.container,
@@ -326,9 +365,15 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
326
365
  onChange: handleChange,
327
366
  onFocus: () => {
328
367
  setisFocused(true);
368
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
369
+ setIsExpanded(true);
370
+ }
329
371
  },
330
372
  onBlur: () => {
331
373
  setisFocused(false);
374
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
375
+ setIsExpanded(false);
376
+ }
332
377
  },
333
378
  onClear: onClear,
334
379
  onKeyPress: handleClose,
@@ -360,12 +405,13 @@ const Autocomplete = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
360
405
  })
361
406
  });
362
407
  }
363
- }), (isExpanded || hintExpansionEnabled) && isInputVisible && /*#__PURE__*/_jsxs(_Fragment, {
408
+ }), (isExpanded || hintExpansionEnabled) && isInputVisible && (itemsToShow.length > 0 || isExpanded || hintExpansionEnabled) && /*#__PURE__*/_jsxs(_Fragment, {
364
409
  children: [/*#__PURE__*/_jsx(Listbox.Overlay, {
365
410
  overlaidPosition: overlaidPosition,
366
411
  isReady: isReady,
367
412
  minWidth: fullWidth ? inputWidth : MIN_LISTBOX_WIDTH,
368
413
  maxWidth: inputWidth,
414
+ maxHeight: maxDropdownHeight,
369
415
  onLayout: handleMeasure,
370
416
  tokens: restOfTokens,
371
417
  ref: openOverlayRef,
@@ -449,6 +495,10 @@ Autocomplete.propTypes = {
449
495
  * Maximum number of suggestions provided at the same time
450
496
  */
451
497
  maxSuggestions: PropTypes.number,
498
+ /**
499
+ * Maximum height (in pixels) of the dropdown before scrolling is enabled
500
+ */
501
+ maxDropdownHeight: PropTypes.number,
452
502
  /**
453
503
  * Text or JSX to render when no results are available
454
504
  */
@@ -469,6 +519,10 @@ Autocomplete.propTypes = {
469
519
  * Callback function to be called when an item is selected from the list
470
520
  */
471
521
  onSelect: PropTypes.func,
522
+ /**
523
+ * When true, displays all available options when the input receives focus (even without typing)
524
+ */
525
+ showOptionsOnFocus: PropTypes.bool,
472
526
  /**
473
527
  * Input value for controlled usage
474
528
  */
@@ -1,4 +1,5 @@
1
1
  export const DEFAULT_MIN_TO_SUGGESTION = 1;
2
2
  export const DEFAULT_MAX_SUGGESTIONS = 5;
3
+ export const DEFAULT_MAX_DROPDOWN_HEIGHT = 336; // Approximately 7 items (48px each)
3
4
  export const INPUT_LEFT_PADDING = 16;
4
5
  export const MIN_LISTBOX_WIDTH = 288;
@@ -917,8 +917,7 @@ const Carousel = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
917
917
  // Related discussion - https://github.com/telus/universal-design-system/issues/1549
918
918
  const previousNextIconButtonVariants = {
919
919
  size: previousNextIconSize,
920
- raised: !variant?.inverse && true,
921
- inverse: variant?.inverse
920
+ raised: true
922
921
  };
923
922
  const getCopyWithPlaceholders = React.useCallback(copyKey => {
924
923
  const copyText = getCopy(copyKey).replace(/%\{title\}/g, title).replace(/%\{itemLabel\}/g, itemLabel).replace(/%\{stepNumber\}/g, activeIndex + 1).replace(/%\{stepCount\}/g, totalItems);
@@ -28,6 +28,7 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
28
28
  isReady = false,
29
29
  overlaidPosition,
30
30
  maxWidth,
31
+ maxHeight,
31
32
  minWidth,
32
33
  onLayout,
33
34
  tokens,
@@ -43,12 +44,16 @@ const DropdownOverlay = /*#__PURE__*/React.forwardRef((_ref, ref) => {
43
44
  maxWidth,
44
45
  minWidth
45
46
  }, staticStyles.positioner, !isReady && staticStyles.hidden],
47
+ onMouseDown: e => {
48
+ e.preventDefault();
49
+ },
46
50
  children: /*#__PURE__*/_jsx(Card, {
47
51
  tokens: {
48
52
  shadow: systemTokens.shadow,
49
53
  borderRadius: systemTokens.borderRadius,
50
54
  ...(Platform.OS === 'web' && {
51
- overflowY: 'hidden'
55
+ maxHeight,
56
+ overflowY: 'auto'
52
57
  }),
53
58
  paddingBottom: paddingVertical,
54
59
  paddingTop: paddingVertical,
@@ -78,6 +83,7 @@ DropdownOverlay.propTypes = {
78
83
  width: PropTypes.number
79
84
  }),
80
85
  maxWidth: PropTypes.number,
86
+ maxHeight: PropTypes.number,
81
87
  minWidth: PropTypes.number,
82
88
  onLayout: PropTypes.func,
83
89
  tokens: PropTypes.object,
@@ -4,7 +4,7 @@ import Pressable from "react-native-web/dist/exports/Pressable";
4
4
  import Text from "react-native-web/dist/exports/Text";
5
5
  import { selectSystemProps, resolvePressableTokens, htmlAttrs } from '../utils';
6
6
  import { useListboxContext } from './ListboxContext';
7
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
8
  const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
9
9
  const getItemStyles = _ref => {
10
10
  let {
@@ -122,9 +122,9 @@ const PressableItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
122
122
  onPress(event);
123
123
  },
124
124
  children: pressableState => {
125
- return /*#__PURE__*/_jsxs(Text, {
125
+ return /*#__PURE__*/_jsx(Text, {
126
126
  style: selectTextStyles(resolveButtonTokens(pressableState)),
127
- children: [children, " "]
127
+ children: children
128
128
  });
129
129
  }
130
130
  });
@@ -271,8 +271,8 @@ const TextInputBase = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
271
271
  }
272
272
  }, [element, pattern]);
273
273
  const handleChangeText = event => {
274
- const text = event.nativeEvent?.text || event.target?.value;
275
- let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') : text;
274
+ const text = event.nativeEvent?.text ?? event.target?.value;
275
+ let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') || undefined : text;
276
276
  if (type === 'card' && filteredText) {
277
277
  const formattedValue = filteredText.replace(/[^a-zA-Z0-9]/g, '');
278
278
  const regex = new RegExp(`([a-zA-Z0-9]{4})(?=[a-zA-Z0-9])`, 'g');
package/lib/package.json CHANGED
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.28.1",
87
+ "version": "3.28.2",
88
88
  "types": "types/index.d.ts"
89
89
  }
package/package.json CHANGED
@@ -84,6 +84,6 @@
84
84
  "standard-engine": {
85
85
  "skip": true
86
86
  },
87
- "version": "3.28.1",
87
+ "version": "3.28.2",
88
88
  "types": "types/index.d.ts"
89
89
  }
@@ -24,6 +24,7 @@ import Suggestions from './Suggestions'
24
24
  import {
25
25
  DEFAULT_MAX_SUGGESTIONS,
26
26
  DEFAULT_MIN_TO_SUGGESTION,
27
+ DEFAULT_MAX_DROPDOWN_HEIGHT,
27
28
  INPUT_LEFT_PADDING,
28
29
  MIN_LISTBOX_WIDTH
29
30
  } from './constants'
@@ -51,20 +52,44 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([
51
52
  const highlightAllMatches = (str, substring = '', matchIndexes = [], resultsTextColor) => (
52
53
  // Wrapping all in bold
53
54
  <Typography variant={{ bold: false }} tokens={{ color: resultsTextColor }}>
54
- {matchIndexes.reduce(
55
- (acc, matchIndex, index) => [
56
- ...acc,
57
- // Add a piece of the string up to the first occurrence of the substring
58
- index === 0 && (str.slice(0, matchIndex) ?? ''),
59
- // Unbold the occurrence of the substring (while keeping the original casing)
60
- <Typography key={matchIndex} variant={{ bold: true }} tokens={{ color: resultsTextColor }}>
61
- {str.slice(matchIndex, matchIndex + substring.length)}
62
- </Typography>,
63
- // Add the rest of the string until the next occurrence or the end of it
64
- str.slice(matchIndex + substring.length, matchIndexes[index + 1] ?? str.length)
65
- ],
66
- []
67
- )}
55
+ {matchIndexes
56
+ .reduce((acc, matchIndex, index) => {
57
+ const prefix = index === 0 ? str.slice(0, matchIndex) : null
58
+ const match = str.slice(matchIndex, matchIndex + substring.length)
59
+ const suffix = str.slice(
60
+ matchIndex + substring.length,
61
+ matchIndexes[index + 1] ?? str.length
62
+ )
63
+ return [
64
+ ...acc,
65
+ prefix ? (
66
+ <Typography
67
+ key={`pre-${matchIndex}`}
68
+ variant={{ bold: false }}
69
+ tokens={{ color: resultsTextColor }}
70
+ >
71
+ {prefix}
72
+ </Typography>
73
+ ) : null,
74
+ <Typography
75
+ key={matchIndex}
76
+ variant={{ bold: true }}
77
+ tokens={{ color: resultsTextColor }}
78
+ >
79
+ {match}
80
+ </Typography>,
81
+ suffix ? (
82
+ <Typography
83
+ key={`post-${matchIndex}`}
84
+ variant={{ bold: false }}
85
+ tokens={{ color: resultsTextColor }}
86
+ >
87
+ {suffix}
88
+ </Typography>
89
+ ) : null
90
+ ]
91
+ }, [])
92
+ .filter(Boolean)}
68
93
  </Typography>
69
94
  )
70
95
  const highlight = (items = [], text = '', color) =>
@@ -94,12 +119,14 @@ const Autocomplete = React.forwardRef(
94
119
  isLoading = false,
95
120
  items,
96
121
  maxSuggestions = DEFAULT_MAX_SUGGESTIONS,
122
+ maxDropdownHeight = DEFAULT_MAX_DROPDOWN_HEIGHT,
97
123
  minToSuggestion = DEFAULT_MIN_TO_SUGGESTION,
98
124
  noResults,
99
125
  onChange,
100
126
  onClear,
101
127
  onSelect,
102
128
  readOnly,
129
+ showOptionsOnFocus = false,
103
130
  validation,
104
131
  value,
105
132
  helpText = '',
@@ -144,7 +171,7 @@ const Autocomplete = React.forwardRef(
144
171
 
145
172
  const { supportsProps, ...selectedProps } = selectProps(rest)
146
173
  const { hint, label: inputLabel } = supportsProps
147
- const hintExpansionEnabled = isFocused && helpText && !currentValue
174
+ const hintExpansionEnabled = isFocused && !!helpText && !currentValue
148
175
  const {
149
176
  overlaidPosition,
150
177
  sourceRef: inputRef,
@@ -198,9 +225,12 @@ const Autocomplete = React.forwardRef(
198
225
  }
199
226
 
200
227
  const handleChange = (newValue) => {
201
- onChange?.(newValue || '')
228
+ onChange?.(newValue)
202
229
  setCurrentValue(newValue)
203
- setIsExpanded(newValue?.length >= minToSuggestion)
230
+ const shouldExpand =
231
+ newValue?.length >= minToSuggestion ||
232
+ (showOptionsOnFocus && isFocused && newValue?.length === 0)
233
+ setIsExpanded(shouldExpand)
204
234
  if (!isControlled && initialItems !== undefined) {
205
235
  setCurrentItems(
206
236
  initialItems.filter(({ label }) =>
@@ -211,21 +241,24 @@ const Autocomplete = React.forwardRef(
211
241
  }
212
242
  const handleSelect = (selectedId) => {
213
243
  onSelect?.(selectedId)
214
- const {
215
- label: newValue,
216
- nested,
217
- title
218
- } = (isControlled ? items : currentItems)?.find(({ id }) => id === selectedId)
244
+ const selectedItem = (isControlled ? items : currentItems)?.find(
245
+ ({ id }) => id === selectedId
246
+ )
247
+ const { label, nested, title } = selectedItem
248
+
219
249
  if (title) return
220
250
  if (!nested) {
221
251
  setNestedSelectedValue(null)
222
- onChange?.(newValue)
252
+ onChange?.(label)
223
253
  setIsExpanded(false)
254
+ setCurrentValue(label)
224
255
  }
225
- setCurrentValue(newValue)
226
- if (!isControlled && inputRef?.current) inputRef.current.value = newValue
256
+ if (!isControlled && inputRef?.current) inputRef.current.value = label
227
257
 
228
- if (nested) setNestedSelectedValue(newValue)
258
+ if (nested) {
259
+ setNestedSelectedValue(label)
260
+ setCurrentValue(label)
261
+ }
229
262
 
230
263
  inputRef.current.focus()
231
264
  }
@@ -278,17 +311,13 @@ const Autocomplete = React.forwardRef(
278
311
  }, [inputRef])
279
312
 
280
313
  const handleClose = (event) => {
281
- if (
282
- (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) ||
283
- (event.type === 'click' && !openOverlayRef?.current?.contains(event.target)) ||
284
- (event.type === 'touchstart' &&
285
- openOverlayRef?.current &&
286
- event.touches[0].target &&
287
- !openOverlayRef?.current?.contains(event.touches[0].target))
288
- ) {
314
+ if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) {
289
315
  setIsExpanded(false)
290
316
  setNestedSelectedValue(null)
291
- } else if (
317
+ return
318
+ }
319
+
320
+ if (
292
321
  event.type === 'keydown' &&
293
322
  (event.key === 'ArrowDown' || event.key === 'Tab') &&
294
323
  isExpanded &&
@@ -297,13 +326,30 @@ const Autocomplete = React.forwardRef(
297
326
  ) {
298
327
  event.preventDefault()
299
328
  targetRef.current.focus()
329
+ return
330
+ }
331
+
332
+ if (event.type === 'click' || event.type === 'touchstart') {
333
+ const clickTarget = event.type === 'click' ? event.target : event.touches[0]?.target
334
+ const isOutsideOverlay =
335
+ openOverlayRef?.current && !openOverlayRef.current.contains(clickTarget)
336
+ const isOutsideInput = inputRef?.current && !inputRef.current.contains(clickTarget)
337
+
338
+ if (isOutsideOverlay && isOutsideInput) {
339
+ setIsExpanded(false)
340
+ setNestedSelectedValue(null)
341
+ }
300
342
  }
301
343
  }
302
- const itemsToShow = currentValue
303
- ? itemsToSuggest(
304
- highlight(isControlled ? items : currentItems, currentValue, resultsTextColor)
305
- )
306
- : []
344
+ // Calculate items to show based on current state
345
+ let itemsToShow = []
346
+ if (currentValue?.length > 0) {
347
+ itemsToShow = itemsToSuggest(
348
+ highlight(isControlled ? items : currentItems, currentValue, resultsTextColor)
349
+ )
350
+ } else if (showOptionsOnFocus && isFocused) {
351
+ itemsToShow = itemsToSuggest(isControlled ? items : currentItems || initialItems)
352
+ }
307
353
  const helpTextToShow = isFocused && !currentValue ? helpText : noResults ?? getCopy('noResults')
308
354
 
309
355
  return (
@@ -337,9 +383,15 @@ const Autocomplete = React.forwardRef(
337
383
  onChange={handleChange}
338
384
  onFocus={() => {
339
385
  setisFocused(true)
386
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
387
+ setIsExpanded(true)
388
+ }
340
389
  }}
341
390
  onBlur={() => {
342
391
  setisFocused(false)
392
+ if (showOptionsOnFocus && (!currentValue || currentValue.length === 0)) {
393
+ setIsExpanded(false)
394
+ }
343
395
  }}
344
396
  onClear={onClear}
345
397
  onKeyPress={handleClose}
@@ -368,45 +420,50 @@ const Autocomplete = React.forwardRef(
368
420
  )
369
421
  }}
370
422
  </InputSupports>
371
- {(isExpanded || hintExpansionEnabled) && isInputVisible && (
372
- <>
373
- <Listbox.Overlay
374
- overlaidPosition={overlaidPosition}
375
- isReady={isReady}
376
- minWidth={fullWidth ? inputWidth : MIN_LISTBOX_WIDTH}
377
- maxWidth={inputWidth}
378
- onLayout={handleMeasure}
379
- tokens={restOfTokens}
380
- ref={openOverlayRef}
381
- >
382
- {isLoading ? (
383
- <Loading label={loadingLabel ?? getCopy('loading')} />
384
- ) : (
385
- <Suggestions
386
- hasResults={getCopy('hasResults')}
387
- id="autocomplete"
388
- items={
389
- nestedSelectedValue
390
- ? itemsToSuggest(highlight(otherItems, nestedSelectedValue, resultsTextColor))
391
- : itemsToShow
392
- }
393
- noResults={helpTextToShow}
394
- onClose={handleClose}
395
- onSelect={handleSelect}
396
- parentRef={inputRef}
397
- ref={targetRef}
423
+ {(isExpanded || hintExpansionEnabled) &&
424
+ isInputVisible &&
425
+ (itemsToShow.length > 0 || isExpanded || hintExpansionEnabled) && (
426
+ <>
427
+ <Listbox.Overlay
428
+ overlaidPosition={overlaidPosition}
429
+ isReady={isReady}
430
+ minWidth={fullWidth ? inputWidth : MIN_LISTBOX_WIDTH}
431
+ maxWidth={inputWidth}
432
+ maxHeight={maxDropdownHeight}
433
+ onLayout={handleMeasure}
434
+ tokens={restOfTokens}
435
+ ref={openOverlayRef}
436
+ >
437
+ {isLoading ? (
438
+ <Loading label={loadingLabel ?? getCopy('loading')} />
439
+ ) : (
440
+ <Suggestions
441
+ hasResults={getCopy('hasResults')}
442
+ id="autocomplete"
443
+ items={
444
+ nestedSelectedValue
445
+ ? itemsToSuggest(
446
+ highlight(otherItems, nestedSelectedValue, resultsTextColor)
447
+ )
448
+ : itemsToShow
449
+ }
450
+ noResults={helpTextToShow}
451
+ onClose={handleClose}
452
+ onSelect={handleSelect}
453
+ parentRef={inputRef}
454
+ ref={targetRef}
455
+ />
456
+ )}
457
+ </Listbox.Overlay>
458
+ {targetRef?.current && (
459
+ <View
460
+ // This catches and shifts focus to other interactive elements.
461
+ onFocus={() => targetRef?.current?.focus()}
462
+ tabIndex={0}
398
463
  />
399
464
  )}
400
- </Listbox.Overlay>
401
- {targetRef?.current && (
402
- <View
403
- // This catches and shifts focus to other interactive elements.
404
- onFocus={() => targetRef?.current?.focus()}
405
- tabIndex={0}
406
- />
407
- )}
408
- </>
409
- )}
465
+ </>
466
+ )}
410
467
  </View>
411
468
  )
412
469
  }
@@ -468,6 +525,10 @@ Autocomplete.propTypes = {
468
525
  * Maximum number of suggestions provided at the same time
469
526
  */
470
527
  maxSuggestions: PropTypes.number,
528
+ /**
529
+ * Maximum height (in pixels) of the dropdown before scrolling is enabled
530
+ */
531
+ maxDropdownHeight: PropTypes.number,
471
532
  /**
472
533
  * Text or JSX to render when no results are available
473
534
  */
@@ -488,6 +549,10 @@ Autocomplete.propTypes = {
488
549
  * Callback function to be called when an item is selected from the list
489
550
  */
490
551
  onSelect: PropTypes.func,
552
+ /**
553
+ * When true, displays all available options when the input receives focus (even without typing)
554
+ */
555
+ showOptionsOnFocus: PropTypes.bool,
491
556
  /**
492
557
  * Input value for controlled usage
493
558
  */
@@ -1,4 +1,5 @@
1
1
  export const DEFAULT_MIN_TO_SUGGESTION = 1
2
2
  export const DEFAULT_MAX_SUGGESTIONS = 5
3
+ export const DEFAULT_MAX_DROPDOWN_HEIGHT = 336 // Approximately 7 items (48px each)
3
4
  export const INPUT_LEFT_PADDING = 16
4
5
  export const MIN_LISTBOX_WIDTH = 288
@@ -1056,8 +1056,7 @@ const Carousel = React.forwardRef(
1056
1056
  // Related discussion - https://github.com/telus/universal-design-system/issues/1549
1057
1057
  const previousNextIconButtonVariants = {
1058
1058
  size: previousNextIconSize,
1059
- raised: !variant?.inverse && true,
1060
- inverse: variant?.inverse
1059
+ raised: true
1061
1060
  }
1062
1061
 
1063
1062
  const getCopyWithPlaceholders = React.useCallback(
@@ -28,6 +28,7 @@ const DropdownOverlay = React.forwardRef(
28
28
  isReady = false,
29
29
  overlaidPosition,
30
30
  maxWidth,
31
+ maxHeight,
31
32
  minWidth,
32
33
  onLayout,
33
34
  tokens,
@@ -50,12 +51,18 @@ const DropdownOverlay = React.forwardRef(
50
51
  staticStyles.positioner,
51
52
  !isReady && staticStyles.hidden
52
53
  ]}
54
+ onMouseDown={(e) => {
55
+ e.preventDefault()
56
+ }}
53
57
  >
54
58
  <Card
55
59
  tokens={{
56
60
  shadow: systemTokens.shadow,
57
61
  borderRadius: systemTokens.borderRadius,
58
- ...(Platform.OS === 'web' && { overflowY: 'hidden' }),
62
+ ...(Platform.OS === 'web' && {
63
+ maxHeight,
64
+ overflowY: 'auto'
65
+ }),
59
66
  paddingBottom: paddingVertical,
60
67
  paddingTop: paddingVertical,
61
68
  paddingLeft: paddingHorizontal,
@@ -89,6 +96,7 @@ DropdownOverlay.propTypes = {
89
96
  width: PropTypes.number
90
97
  }),
91
98
  maxWidth: PropTypes.number,
99
+ maxHeight: PropTypes.number,
92
100
  minWidth: PropTypes.number,
93
101
  onLayout: PropTypes.func,
94
102
  tokens: PropTypes.object,
@@ -120,7 +120,7 @@ const PressableItem = React.forwardRef(
120
120
  >
121
121
  {(pressableState) => {
122
122
  return (
123
- <Text style={selectTextStyles(resolveButtonTokens(pressableState))}>{children} </Text>
123
+ <Text style={selectTextStyles(resolveButtonTokens(pressableState))}>{children}</Text>
124
124
  )
125
125
  }}
126
126
  </Pressable>
@@ -255,8 +255,8 @@ const TextInputBase = React.forwardRef(
255
255
  }, [element, pattern])
256
256
 
257
257
  const handleChangeText = (event) => {
258
- const text = event.nativeEvent?.text || event.target?.value
259
- let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') : text
258
+ const text = event.nativeEvent?.text ?? event.target?.value
259
+ let filteredText = isNumeric ? text?.replace(/[^\d]/g, '') || undefined : text
260
260
  if (type === 'card' && filteredText) {
261
261
  const formattedValue = filteredText.replace(/[^a-zA-Z0-9]/g, '')
262
262
  const regex = new RegExp(`([a-zA-Z0-9]{4})(?=[a-zA-Z0-9])`, 'g')