@telus-uds/components-base 3.7.1 → 3.9.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 (54) hide show
  1. package/CHANGELOG.md +34 -2
  2. package/lib/cjs/ActivityIndicator/FullScreenIndicator.js +89 -0
  3. package/lib/cjs/ActivityIndicator/InlineIndicator.js +64 -0
  4. package/lib/cjs/ActivityIndicator/OverlayIndicator.js +156 -0
  5. package/lib/cjs/ActivityIndicator/RenderActivityIndicator.js +88 -0
  6. package/lib/cjs/ActivityIndicator/index.js +91 -23
  7. package/lib/cjs/ActivityIndicator/shared.js +12 -1
  8. package/lib/cjs/ActivityIndicator/sharedProptypes.js +67 -0
  9. package/lib/cjs/Card/Card.js +38 -45
  10. package/lib/cjs/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
  11. package/lib/cjs/List/ListItemMark.js +13 -2
  12. package/lib/cjs/MultiSelectFilter/ModalOverlay.js +19 -5
  13. package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +22 -9
  14. package/lib/cjs/ToggleSwitch/ToggleSwitch.js +13 -2
  15. package/lib/cjs/Validator/Validator.js +135 -64
  16. package/lib/cjs/utils/index.js +9 -1
  17. package/lib/cjs/utils/useDetectOutsideClick.js +39 -0
  18. package/lib/cjs/utils/useVariants.js +46 -0
  19. package/lib/esm/ActivityIndicator/FullScreenIndicator.js +82 -0
  20. package/lib/esm/ActivityIndicator/InlineIndicator.js +57 -0
  21. package/lib/esm/ActivityIndicator/OverlayIndicator.js +149 -0
  22. package/lib/esm/ActivityIndicator/RenderActivityIndicator.js +83 -0
  23. package/lib/esm/ActivityIndicator/index.js +89 -23
  24. package/lib/esm/ActivityIndicator/shared.js +11 -0
  25. package/lib/esm/ActivityIndicator/sharedProptypes.js +61 -0
  26. package/lib/esm/Card/Card.js +38 -45
  27. package/lib/esm/ExpandCollapseMini/ExpandCollapseMiniControl.js +1 -1
  28. package/lib/esm/List/ListItemMark.js +13 -2
  29. package/lib/esm/MultiSelectFilter/ModalOverlay.js +19 -5
  30. package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +22 -9
  31. package/lib/esm/ToggleSwitch/ToggleSwitch.js +13 -2
  32. package/lib/esm/Validator/Validator.js +135 -64
  33. package/lib/esm/utils/index.js +2 -1
  34. package/lib/esm/utils/useDetectOutsideClick.js +31 -0
  35. package/lib/esm/utils/useVariants.js +41 -0
  36. package/lib/package.json +2 -2
  37. package/package.json +2 -2
  38. package/src/ActivityIndicator/FullScreenIndicator.jsx +65 -0
  39. package/src/ActivityIndicator/InlineIndicator.jsx +47 -0
  40. package/src/ActivityIndicator/OverlayIndicator.jsx +140 -0
  41. package/src/ActivityIndicator/RenderActivityIndicator.jsx +82 -0
  42. package/src/ActivityIndicator/index.jsx +113 -32
  43. package/src/ActivityIndicator/shared.js +11 -0
  44. package/src/ActivityIndicator/sharedProptypes.js +62 -0
  45. package/src/Card/Card.jsx +51 -54
  46. package/src/ExpandCollapseMini/ExpandCollapseMiniControl.jsx +1 -1
  47. package/src/List/ListItemMark.jsx +18 -2
  48. package/src/MultiSelectFilter/ModalOverlay.jsx +18 -5
  49. package/src/MultiSelectFilter/MultiSelectFilter.jsx +21 -10
  50. package/src/ToggleSwitch/ToggleSwitch.jsx +17 -2
  51. package/src/Validator/Validator.jsx +172 -85
  52. package/src/utils/index.js +1 -0
  53. package/src/utils/useDetectOutsideClick.js +35 -0
  54. package/src/utils/useVariants.js +44 -0
@@ -133,6 +133,7 @@ const Card = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
133
133
  const selected = interactiveCard?.variant?.selected;
134
134
  const inactive = interactiveCard?.variant?.inactive;
135
135
  const selectionType = interactiveCard?.selectionType;
136
+ const isControl = interactiveCard?.variant?.isControl === true;
136
137
  const getThemeTokens = (0, _ThemeProvider.useThemeTokensCallback)('Card', interactiveCard?.tokens, {
137
138
  interactive: true,
138
139
  ...(interactiveCard?.variant || {})
@@ -200,6 +201,9 @@ const Card = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
200
201
  cardStyles = themeTokens;
201
202
  }
202
203
  const renderInputPerSelectionType = props => {
204
+ if (!isControl) {
205
+ return null;
206
+ }
203
207
  switch (selectionType) {
204
208
  case SelectionType.Checkbox:
205
209
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
@@ -227,17 +231,8 @@ const Card = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
227
231
  return null;
228
232
  }
229
233
  };
230
- const renderNoSelectionView = () => /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
231
- style: {
232
- paddingTop,
233
- paddingBottom,
234
- paddingLeft,
235
- paddingRight
236
- },
237
- children: children
238
- });
239
234
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
240
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardBase.default, {
235
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_CardBase.default, {
241
236
  ref: ref,
242
237
  tokens: interactiveCard?.body ? restOfTokens : cardStyles,
243
238
  backgroundImage: backgroundImage,
@@ -245,41 +240,39 @@ const Card = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
245
240
  media: mediaIds
246
241
  },
247
242
  ...selectProps(rest),
248
- children: interactiveCard?.body ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
249
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_PressableCardBase.default, {
250
- ref: ref,
251
- tokens: getThemeTokens,
252
- dataSet: dataSet,
253
- onPress: onPress,
254
- href: interactiveCard?.href,
255
- hrefAttrs: interactiveCard?.hrefAttrs,
256
- ...selectProps(rest),
257
- children: cardState => {
258
- const {
259
- iconColor: checkColor,
260
- inputBackgroundColor: boxBackgroundColor,
261
- iconBackgroundColor: checkBackgroundColor
262
- } = getThemeTokens({
263
- ...cardState,
264
- selected,
265
- interactive: true,
266
- isControl: true
267
- }, interactiveCard?.tokens);
268
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
269
- children: [renderInputPerSelectionType(getInputProps({
270
- id,
271
- checkColor,
272
- boxBackgroundColor,
273
- checkBackgroundColor,
274
- isControlled: true,
275
- isChecked: selected || cardState?.hover,
276
- isInactive: inactive,
277
- onPress
278
- })), typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body]
279
- });
280
- }
281
- }), children && selectionType !== SelectionType.None ? renderNoSelectionView() : null]
282
- }) : children
243
+ children: [interactiveCard?.body && /*#__PURE__*/(0, _jsxRuntime.jsx)(_PressableCardBase.default, {
244
+ ref: ref,
245
+ tokens: getThemeTokens,
246
+ dataSet: dataSet,
247
+ onPress: onPress,
248
+ href: interactiveCard?.href,
249
+ hrefAttrs: interactiveCard?.hrefAttrs,
250
+ ...selectProps(rest),
251
+ children: cardState => {
252
+ const {
253
+ iconColor: checkColor,
254
+ inputBackgroundColor: boxBackgroundColor,
255
+ iconBackgroundColor: checkBackgroundColor
256
+ } = getThemeTokens({
257
+ ...cardState,
258
+ selected,
259
+ interactive: true,
260
+ isControl
261
+ }, interactiveCard?.tokens);
262
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
263
+ children: [renderInputPerSelectionType(getInputProps({
264
+ id,
265
+ checkColor,
266
+ boxBackgroundColor,
267
+ checkBackgroundColor,
268
+ isControlled: true,
269
+ isChecked: selected || cardState?.hover,
270
+ isInactive: inactive,
271
+ onPress
272
+ })), typeof interactiveCard?.body === 'function' ? interactiveCard.body(cardState) : interactiveCard.body]
273
+ });
274
+ }
275
+ }), children]
283
276
  })
284
277
  });
285
278
  });
@@ -45,7 +45,7 @@ const ExpandCollapseMiniControl = /*#__PURE__*/_react.default.forwardRef((_ref,
45
45
  const isFocusVisible = _Platform.default.OS === 'web' ? focus && !pressed && !hover : expanded;
46
46
  const linkTokens = (0, _ThemeProvider.useThemeTokens)('Link', {}, {
47
47
  ...variant,
48
- quiet: expanded ?? quiet
48
+ quiet
49
49
  }, {
50
50
  focus: isFocusVisible,
51
51
  hover,
@@ -9,6 +9,7 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
9
9
  var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
10
  var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
11
  var _Icon = _interopRequireDefault(require("../Icon"));
12
+ var _utils = require("../utils");
12
13
  var _jsxRuntime = require("react/jsx-runtime");
13
14
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
14
15
  const tokenTypes = exports.tokenTypes = {
@@ -60,6 +61,7 @@ const selectBulletContainerStyles = _ref4 => {
60
61
  alignItems: itemBulletContainerAlign
61
62
  };
62
63
  };
64
+ const getIconColorVariants = iconVariants => iconVariants?.filter(variant => variant[0] === 'color').map(variant => variant[1]);
63
65
 
64
66
  /**
65
67
  * Subcomponent used within ListItem and similar components for rendering bullets or icons
@@ -78,6 +80,10 @@ const ListItemMark = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
78
80
  const themeTokens = typeof tokens === 'function' ? tokens() : tokens;
79
81
  const sideItemContainerStyles = selectSideItemContainerStyles(themeTokens);
80
82
  const bulletContainerStyles = selectBulletContainerStyles(themeTokens);
83
+
84
+ // TODO: Remove it when iconColor custom colors are deprecated.
85
+ const iconVariants = (0, _utils.useVariants)('Icon');
86
+ const iconColorVariants = getIconColorVariants(iconVariants);
81
87
  if (icon) {
82
88
  const iconTokens = selectItemIconTokens(themeTokens);
83
89
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
@@ -85,10 +91,15 @@ const ListItemMark = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
85
91
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
86
92
  icon: icon,
87
93
  tokens: {
88
- size: iconSize ?? iconTokens.size
94
+ size: iconSize ?? iconTokens.size,
95
+ ...((iconColor && !iconColorVariants?.includes(iconColor) || !iconColor) && {
96
+ color: iconColor && !iconColorVariants?.includes(iconColor) ? iconColor : iconTokens.color
97
+ })
89
98
  },
90
99
  variant: {
91
- color: iconColor ?? iconTokens.color
100
+ ...(iconColorVariants?.includes(iconColor) && {
101
+ color: iconColor
102
+ })
92
103
  }
93
104
  })
94
105
  });
@@ -16,6 +16,7 @@ var _ThemeProvider = require("../ThemeProvider");
16
16
  var _dictionary = _interopRequireDefault(require("./dictionary"));
17
17
  var _Card = _interopRequireDefault(require("../Card"));
18
18
  var _IconButton = _interopRequireDefault(require("../IconButton"));
19
+ var _useDetectOutsideClick = _interopRequireDefault(require("../utils/useDetectOutsideClick"));
19
20
  var _jsxRuntime = require("react/jsx-runtime");
20
21
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
22
  const staticStyles = _StyleSheet.default.create({
@@ -62,6 +63,7 @@ const staticStyles = _StyleSheet.default.create({
62
63
  });
63
64
  const selectContainerStyle = (enableFullscreen, themeTokens) => ({
64
65
  borderColor: themeTokens.borderColor,
66
+ backgroundColor: themeTokens.backgroundColor,
65
67
  ..._Platform.default.select({
66
68
  web: {
67
69
  position: enableFullscreen ? 'fixed' : 'absolute'
@@ -96,13 +98,16 @@ const ModalOverlay = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
96
98
  tokens,
97
99
  copy,
98
100
  onClose,
99
- enableFullscreen = false
101
+ enableFullscreen = false,
102
+ dismissWhenPressedOutside = false
100
103
  } = _ref2;
101
104
  const viewport = (0, _ViewportProvider.useViewport)();
102
105
  const themeTokens = (0, _ThemeProvider.useThemeTokens)('Modal', tokens, variant, {
103
106
  viewport,
104
107
  maxWidth: false
105
108
  });
109
+ const containerRef = _react.default.useRef(ref || null);
110
+ (0, _useDetectOutsideClick.default)(containerRef, onClose, dismissWhenPressedOutside);
106
111
  const containerWidthHeight = {
107
112
  minWidth: tokens.maxWidth ? maxWidthSize : minWidth,
108
113
  minHeight: maxHeight ? maxHeightSize : minHeight,
@@ -110,7 +115,8 @@ const ModalOverlay = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
110
115
  maxHeight: maxHeightSize
111
116
  };
112
117
  const {
113
- closeIcon: CloseIconComponent
118
+ closeIcon: CloseIconComponent,
119
+ backgroundColor
114
120
  } = themeTokens;
115
121
  const getCopy = (0, _utils.useCopy)({
116
122
  dictionary: _dictionary.default,
@@ -119,11 +125,14 @@ const ModalOverlay = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
119
125
  const closeLabel = getCopy('closeButton');
120
126
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_portal.Portal, {
121
127
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
122
- ref: ref,
128
+ ref: containerRef,
123
129
  onLayout: onLayout,
124
130
  style: [overlaidPosition, containerWidthHeight, staticStyles.positioner, !isReady && staticStyles.hidden, selectContainerStyle(enableFullscreen, themeTokens)],
125
131
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Card.default, {
126
- tokens: staticStyles.card,
132
+ tokens: {
133
+ ...staticStyles.card,
134
+ backgroundColor
135
+ },
127
136
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
128
137
  style: [staticStyles.closeButtonContainer, selectCloseButtonContainerStyles(themeTokens)],
129
138
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_IconButton.default, {
@@ -157,6 +166,11 @@ ModalOverlay.propTypes = {
157
166
  tokens: (0, _utils.getTokensPropType)('Modal'),
158
167
  copy: _utils.copyPropTypes,
159
168
  onClose: _propTypes.default.func,
160
- enableFullscreen: _propTypes.default.bool
169
+ enableFullscreen: _propTypes.default.bool,
170
+ /**
171
+ * If true, clicking outside the content will trigger the a close callback, dismissing the content.
172
+ * @deprecated This parameter will be removed in the next major release; detection will be always enabled by default.
173
+ */
174
+ dismissWhenPressedOutside: _propTypes.default.bool
161
175
  };
162
176
  var _default = exports.default = ModalOverlay;
@@ -92,6 +92,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
92
92
  inactive = false,
93
93
  rowLimit = 12,
94
94
  dictionary = _dictionary.default,
95
+ dismissWhenPressedOutside = false,
95
96
  ...rest
96
97
  } = _ref3;
97
98
  const viewport = (0, _ViewportProvider.useViewport)();
@@ -141,6 +142,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
141
142
  buttonBackgroundColor,
142
143
  iconColorSelected,
143
144
  buttonBackgroundColorSelected,
145
+ containerBorderColor,
144
146
  ...restTokens
145
147
  } = (0, _ThemeProvider.useThemeTokens)('MultiSelectFilter', tokens, {
146
148
  ...variant,
@@ -286,7 +288,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
286
288
  ...headerStyles,
287
289
  lineHeight: headerLineHeight
288
290
  },
289
- children: getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label.toLowerCase())
291
+ children: getCopy('filterByLabel').replace(/%\{filterCategory\}/g, label)
290
292
  })
291
293
  })
292
294
  }), subtitle && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
@@ -307,6 +309,7 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
307
309
  style: styles.options,
308
310
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ScrollView.default, {
309
311
  onLayout: handleScrollViewLayout,
312
+ style: styles.scrollContainer,
310
313
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Row, {
311
314
  distribute: "between",
312
315
  onLayout: handleRowLayout,
@@ -325,12 +328,11 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
325
328
  })]
326
329
  });
327
330
  const controlsContent = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
328
- children: [isScrolling ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
331
+ children: [isScrolling && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
329
332
  tokens: {
330
333
  color: dividerColor
331
- },
332
- space: 4
333
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
334
+ }
335
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Spacer.default, {
334
336
  space: 4
335
337
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
336
338
  style: selectControlsTokens(restTokens),
@@ -387,7 +389,8 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
387
389
  minWidth: windowWidth,
388
390
  tokens: {
389
391
  ...tokens,
390
- maxWidth: true
392
+ maxWidth: true,
393
+ borderColor: containerBorderColor
391
394
  },
392
395
  copy: copy,
393
396
  isReady: isReady,
@@ -403,8 +406,9 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
403
406
  })]
404
407
  })
405
408
  }), isOpen && viewport !== 'xs' && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_ModalOverlay.default, {
406
- overlaidPosition: overlaidPosition,
409
+ dismissWhenPressedOutside: dismissWhenPressedOutside,
407
410
  onClose: onClose,
411
+ overlaidPosition: overlaidPosition,
408
412
  maxHeight: items.length > MAX_ITEMS_THRESHOLD ? true : maxHeight,
409
413
  maxHeightSize: maxHeightSize,
410
414
  maxWidthSize: maxWidthSize,
@@ -412,7 +416,8 @@ const MultiSelectFilter = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) =>
412
416
  minWidth: minWidth,
413
417
  tokens: {
414
418
  ...tokens,
415
- maxWidth: items.length > MAX_ITEMS_THRESHOLD ? true : maxWidth
419
+ maxWidth: items.length > MAX_ITEMS_THRESHOLD ? true : maxWidth,
420
+ borderColor: containerBorderColor
416
421
  },
417
422
  copy: copy,
418
423
  isReady: isReady,
@@ -440,6 +445,9 @@ const styles = _StyleSheet.default.create({
440
445
  },
441
446
  options: {
442
447
  flex: 1
448
+ },
449
+ scrollContainer: {
450
+ padding: 1
443
451
  }
444
452
  });
445
453
 
@@ -548,6 +556,11 @@ MultiSelectFilter.propTypes = {
548
556
  * Sets the maximum number of items in one column. If number of items are more
549
557
  * than the `rowLimit`, they will be rendered in 2 columns.
550
558
  */
551
- rowLimit: _propTypes.default.number
559
+ rowLimit: _propTypes.default.number,
560
+ /**
561
+ * If true, clicking outside the content will trigger the a close callback, dismissing the content.
562
+ * @deprecated This parameter will be removed in the next major release; detection will be always enabled by default.
563
+ */
564
+ dismissWhenPressedOutside: _propTypes.default.bool
552
565
  };
553
566
  var _default = exports.default = MultiSelectFilter;
@@ -101,6 +101,17 @@ const selectSwitchStyles = _ref6 => {
101
101
  })
102
102
  };
103
103
  };
104
+ const selectMobileTokens = tokens => ({
105
+ ..._Platform.default.select({
106
+ web: {},
107
+ default: {
108
+ switchSize: tokens?.mobileSwitchSize,
109
+ trackHeight: tokens?.mobileTrackHeight,
110
+ width: tokens?.mobileWidth,
111
+ trackBorderWidth: tokens?.mobileTrackBorderWidth
112
+ }
113
+ })
114
+ });
104
115
  const selectLabelStyles = _ref7 => {
105
116
  let {
106
117
  labelMarginLeft
@@ -153,7 +164,7 @@ const ToggleSwitch = /*#__PURE__*/_react.default.forwardRef((_ref9, ref) => {
153
164
  onChange
154
165
  });
155
166
  const handlePress = event => setValue(!currentValue, event);
156
- const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState), getTokens(themeTokens));
167
+ const getButtonTokens = buttonState => selectButtonTokens(getTokens(buttonState, selectMobileTokens(themeTokens)), getTokens(themeTokens, selectMobileTokens(themeTokens)));
157
168
  const uniqueId = (0, _utils.useUniqueId)('toggleSwitch');
158
169
  const inputId = id ?? uniqueId;
159
170
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
@@ -186,7 +197,7 @@ const ToggleSwitch = /*#__PURE__*/_react.default.forwardRef((_ref9, ref) => {
186
197
  onPress: handlePress,
187
198
  ...selectProps(rest),
188
199
  children: buttonState => {
189
- const stateTokens = getTokens(buttonState);
200
+ const stateTokens = getTokens(buttonState, selectMobileTokens(themeTokens));
190
201
  const IconComponent = stateTokens.icon;
191
202
  const switchStyles = selectSwitchStyles(stateTokens);
192
203
  const trackStyles = selectTrackStyles(stateTokens);
@@ -44,7 +44,7 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
44
44
  supportsProps
45
45
  } = selectProps(rest);
46
46
  const strValidation = supportsProps.validation;
47
- const [individualCodes, setIndividualCodes] = _react.default.useState({});
47
+ const [, setIndividualCodes] = _react.default.useState({});
48
48
  const [text, setText] = _react.default.useState(value);
49
49
  const validatorsLength = 6;
50
50
  const prefix = 'code';
@@ -62,64 +62,85 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
62
62
  const [codeReferences, singleCodes] = _react.default.useMemo(() => {
63
63
  const codes = [];
64
64
  const valueCodes = {};
65
- for (let i = 0; validatorsLength && i < validatorsLength; i += 1) {
65
+ Array.from({
66
+ length: validatorsLength
67
+ }, (_, i) => {
66
68
  codes[prefix + i] = /*#__PURE__*/_react.default.createRef();
67
69
  valueCodes[prefix + i] = '';
68
70
  valueCodes[prefix + i + sufixValidation] = '';
69
- }
71
+ return null;
72
+ });
70
73
  return [codes, valueCodes];
71
- }, []);
72
- const handleSingleCodes = (codeId, val, validation) => {
74
+ }, [validatorsLength, prefix, sufixValidation]);
75
+ const handleSingleCodes = _react.default.useCallback((codeId, val, validation) => {
73
76
  singleCodes[codeId] = val;
74
77
  singleCodes[codeId + sufixValidation] = validation;
75
- /* eslint-disable no-unused-expressions */
76
- setIndividualCodes({
77
- ...individualCodes,
78
+ setIndividualCodes(prev => ({
79
+ ...prev,
78
80
  [codeId]: val
79
- });
80
- };
81
- const changeDataMasking = boxElement => {
81
+ }));
82
+ }, [singleCodes, sufixValidation]);
83
+ const changeDataMasking = _react.default.useCallback(boxElement => {
82
84
  let charMasking = '';
83
85
  const element = boxElement;
84
- if (mask && mask.length === 1) charMasking = mask;else if (mask && mask.length > 1) charMasking = mask.substring(0, 1);
85
- if (charMasking) element.value = charMasking;
86
- };
87
- const handleChangeCode = () => {
88
- let code = '';
89
- for (let i = 0; i < validatorsLength; i += 1) code += singleCodes[prefix + i];
90
- if (typeof onChange === 'function') onChange(code, singleCodes);
91
- };
92
- const handleChangeCodeValues = (event, codeId, nextIndex) => {
86
+ if (mask && mask.length === 1) {
87
+ charMasking = mask;
88
+ } else if (mask && mask.length > 1) {
89
+ charMasking = mask.substring(0, 1);
90
+ }
91
+ if (charMasking && element) {
92
+ element.value = charMasking;
93
+ }
94
+ }, [mask]);
95
+ const handleChangeCode = _react.default.useCallback(() => {
96
+ const code = Array.from({
97
+ length: validatorsLength
98
+ }, (_, i) => singleCodes[prefix + i] || '').join('');
99
+ if (typeof onChange === 'function') {
100
+ onChange(code, singleCodes);
101
+ }
102
+ }, [validatorsLength, singleCodes, prefix, onChange]);
103
+ const handleChangeCodeValues = _react.default.useCallback((event, codeId, nextIndex) => {
93
104
  const codeElement = codeReferences[codeId]?.current;
94
105
  const val = event.nativeEvent?.value || event.target?.value;
95
- if (Number(val).toString() === 'NaN') {
96
- codeElement.value = singleCodes[codeId] ?? '';
97
- return;
106
+
107
+ // Only allow numeric characters and limit to single digit
108
+ const numericOnly = val.replace(/\D/g, '').substring(0, 1);
109
+ if (codeElement && codeElement.value) {
110
+ codeElement.value = numericOnly;
98
111
  }
99
- handleSingleCodes(codeId, codeElement?.value ?? singleCodes[codeId], 'success');
112
+ handleSingleCodes(codeId, numericOnly, numericOnly ? 'success' : '');
100
113
  handleChangeCode();
101
114
  if (nextIndex === validatorsLength) {
102
- codeElement.blur();
115
+ codeElement?.blur();
103
116
  changeDataMasking(codeElement);
104
117
  return;
105
118
  }
106
- if (codeElement?.value?.length > 0) {
107
- codeReferences[prefix + nextIndex].current.focus();
119
+ if (numericOnly.length > 0) {
120
+ const nextElement = codeReferences[prefix + nextIndex]?.current;
121
+ nextElement?.focus();
108
122
  changeDataMasking(codeElement);
109
123
  }
110
- };
124
+ }, [codeReferences, handleSingleCodes, handleChangeCode, validatorsLength, changeDataMasking, prefix]);
111
125
  const handleKeyPress = (event, currentIndex, previousIndex) => {
112
- if (!(event.keyCode === 8 || event.code === 'Backspace')) return;
126
+ if (!(event.keyCode === 8 || event.code === 'Backspace')) {
127
+ return;
128
+ }
113
129
  if (currentIndex > 0) {
114
- codeReferences[prefix + currentIndex].current.value = '';
115
- codeReferences[prefix + previousIndex].current.focus();
130
+ const currentElement = codeReferences[prefix + currentIndex]?.current;
131
+ const previousElement = codeReferences[prefix + previousIndex]?.current;
132
+ if (currentElement && currentElement.value) {
133
+ currentElement.value = '';
134
+ }
135
+ previousElement?.focus();
116
136
  }
117
137
  handleSingleCodes(prefix + currentIndex, '', '');
118
138
  handleChangeCode();
119
139
  };
120
140
  const getCodeComponents = () => {
121
- const components = [];
122
- for (let i = 0; validatorsLength && i < validatorsLength; i += 1) {
141
+ return Array.from({
142
+ length: validatorsLength
143
+ }, (_, i) => {
123
144
  const codeId = prefix + i;
124
145
  const codeInputProps = {
125
146
  nativeID: codeId,
@@ -127,65 +148,115 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
127
148
  ref: codeReferences[codeId] ?? null,
128
149
  validation: strValidation || singleCodes[codeId + sufixValidation],
129
150
  tokens: selectCodeTextInputTokens(themeTokens),
130
- onFocus: () => codeReferences[codeId]?.current?.select() ?? null,
151
+ onFocus: () => {
152
+ const element = codeReferences[codeId]?.current;
153
+ if (_Platform.default.OS === 'web' && element?.select) {
154
+ return element.select() ?? null;
155
+ }
156
+ if (element?.focus) {
157
+ return element.focus() ?? null;
158
+ }
159
+ return null;
160
+ },
131
161
  onKeyPress: event => handleKeyPress(event, i, i - 1),
132
162
  onMouseOver: handleMouseOver,
133
163
  onMouseOut: handleMouseOut,
134
164
  inactive
135
165
  };
136
- codeInputProps.validation || delete codeInputProps.validation;
137
- components.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
166
+ if (!codeInputProps.validation) {
167
+ delete codeInputProps.validation;
168
+ }
169
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
138
170
  style: staticStyles.codeInputWidth,
139
171
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_TextInput.TextInput, {
140
172
  ...codeInputProps
141
173
  })
142
- }, codeId));
143
- }
144
- return components;
174
+ }, codeId);
175
+ });
145
176
  };
146
177
  _react.default.useEffect(() => {
147
- /* eslint-disable no-unused-expressions */
148
- if (Number(value).toString() !== 'NaN') setText(value);
178
+ if (Number(value).toString() !== 'NaN') {
179
+ setText(value);
180
+ }
149
181
  }, [value]);
150
-
151
- /* eslint-disable react-hooks/exhaustive-deps */
152
182
  _react.default.useEffect(() => {
153
- for (let i = 0; i < validatorsLength; i += 1) {
154
- if (mask && text[i]) codeReferences[prefix + i].current.value = mask;else codeReferences[prefix + i].current.value = text[i] ?? '';
183
+ Array.from({
184
+ length: validatorsLength
185
+ }, (_, i) => {
186
+ const element = codeReferences[prefix + i]?.current;
187
+ if (element && element.value !== undefined) {
188
+ if (mask && text[i]) {
189
+ element.value = mask;
190
+ } else {
191
+ element.value = text[i] ?? '';
192
+ }
193
+ }
155
194
  handleSingleCodes(prefix + i, text[i] ?? '', text[i] ? 'success' : '');
156
- }
157
- }, [text]);
158
-
159
- /* eslint-disable react-hooks/exhaustive-deps */
195
+ return null;
196
+ });
197
+ }, [text, mask, validatorsLength, prefix, codeReferences, handleSingleCodes]);
160
198
  _react.default.useEffect(() => {
161
199
  const handlePasteCode = event => {
200
+ event.preventDefault();
201
+
202
+ // Clear current state first
162
203
  setText('');
204
+
205
+ // Clear all individual input fields and their state
206
+ Array.from({
207
+ length: validatorsLength
208
+ }, (_, i) => {
209
+ const element = codeReferences[prefix + i]?.current;
210
+ if (element && element.value !== undefined) {
211
+ element.value = '';
212
+ }
213
+ handleSingleCodes(prefix + i, '', '');
214
+ return null;
215
+ });
163
216
  const clipBoardText = event.clipboardData.getData('text');
164
- if (Number(clipBoardText).toString() !== 'NaN') setText(clipBoardText);
217
+
218
+ // Validate that input contains only digits and truncate to 6 characters
219
+ const numericOnly = clipBoardText.replace(/\D/g, '').substring(0, validatorsLength);
220
+ if (numericOnly.length > 0) {
221
+ setText(numericOnly);
222
+ }
165
223
  };
166
224
  const handleCopy = event => {
167
- let clipBoardText = '';
168
- for (let i = 0; i < validatorsLength; i += 1) singleCodes[prefix + i] && (clipBoardText += singleCodes[prefix + i]);
225
+ const clipBoardText = Array.from({
226
+ length: validatorsLength
227
+ }, (_, i) => singleCodes[prefix + i] || '').join('');
169
228
  event.clipboardData.setData('text/plain', clipBoardText);
170
229
  event.preventDefault();
171
230
  };
172
231
  if (_Platform.default.OS === 'web') {
173
- for (let i = 0; i < validatorsLength; i += 1) {
174
- codeReferences[prefix + i].current.addEventListener('paste', handlePasteCode);
175
- codeReferences[prefix + i].current.addEventListener('copy', handleCopy);
176
- codeReferences[prefix + i].current.addEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
177
- }
232
+ Array.from({
233
+ length: validatorsLength
234
+ }, (_, i) => {
235
+ const element = codeReferences[prefix + i]?.current;
236
+ if (element && typeof element.addEventListener === 'function') {
237
+ element.addEventListener('paste', handlePasteCode);
238
+ element.addEventListener('copy', handleCopy);
239
+ element.addEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
240
+ }
241
+ return null;
242
+ });
178
243
  }
179
244
  return () => {
180
- if (_Platform.default.oldValue === 'web') {
181
- for (let i = 0; i < validatorsLength; i += 1) {
182
- codeReferences[prefix + i]?.current?.removeEventListener('paste', handlePasteCode);
183
- codeReferences[prefix + i]?.current?.removeEventListener('copy', handleCopy);
184
- codeReferences[prefix + i]?.current?.removeEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
185
- }
245
+ if (_Platform.default.OS === 'web') {
246
+ Array.from({
247
+ length: validatorsLength
248
+ }, (_, i) => {
249
+ const element = codeReferences[prefix + i]?.current;
250
+ if (element && typeof element.removeEventListener === 'function') {
251
+ element.removeEventListener('paste', handlePasteCode);
252
+ element.removeEventListener('copy', handleCopy);
253
+ element.removeEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
254
+ }
255
+ return null;
256
+ });
186
257
  }
187
258
  };
188
- }, []);
259
+ }, [validatorsLength, prefix, codeReferences, handleChangeCodeValues, handleSingleCodes, singleCodes]);
189
260
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputSupports.default, {
190
261
  ...supportsProps,
191
262
  feedbackProps: {