@carbon/react 1.98.0 → 1.99.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.
@@ -45,8 +45,41 @@ const getSeparators = locale => {
45
45
  const numberWithGroupAndDecimal = 1234567.89;
46
46
  const formatted = new Intl.NumberFormat(locale).format(numberWithGroupAndDecimal);
47
47
 
48
- // Extract separators using regex
49
- const match = formatted.match(/(\D+)\d{3}(\D+)\d{2}$/);
48
+ // Comprehensive Unicode digit pattern that includes all common numeral systems
49
+ // supported by Intl.NumberFormat across different locales
50
+ const digitPattern = '[' + '\\u0030-\\u0039' +
51
+ // Western
52
+ '\\u0660-\\u0669' +
53
+ // Eastern Arabic
54
+ '\\u0966-\\u096F' +
55
+ // Devanagari
56
+ '\\u09E6-\\u09EF' +
57
+ // Bengali
58
+ '\\uFF10-\\uFF19' +
59
+ // Fullwidth Japanese 0-9
60
+ '一二三四五六七八九〇零' +
61
+ // Kanji digits
62
+ ']';
63
+
64
+ // Non-digit pattern that excludes ALL digit types (not just ASCII 0-9)
65
+ const nonDigitPattern = '[^' + '\\u0030-\\u0039' +
66
+ // Western
67
+ '\\u0660-\\u0669' +
68
+ // Eastern Arabic
69
+ '\\u0966-\\u096F' +
70
+ // Devanagari
71
+ '\\u09E6-\\u09EF' +
72
+ // Bengali
73
+ '\\uFF10-\\uFF19' +
74
+ // Fullwidth Japanese 0-9
75
+ '一二三四五六七八九〇零' +
76
+ // Kanji digits
77
+ ']+';
78
+
79
+ // Extract separators using regex that handles all numeral systems
80
+ // Use nonDigitPattern instead of \D+ to correctly identify separators
81
+ const regex = new RegExp(`(${nonDigitPattern})${digitPattern}{3}(${nonDigitPattern})${digitPattern}{2}$`);
82
+ const match = formatted.match(regex);
50
83
  if (match) {
51
84
  const groupSeparator = match[1];
52
85
  const decimalSeparator = match[2];
@@ -61,11 +94,116 @@ const getSeparators = locale => {
61
94
  };
62
95
  }
63
96
  };
97
+
98
+ // Normalizes all Unicode minus variants to ASCII hyphen-minus (-)
99
+ const normalizeMinus = value => value.replace(/[\u2212\u2012\u2013\u2014\uFE63\uFF0D]/g, '-');
100
+ const normalizeNumericInput = value => value
101
+ // Remove bidi / direction control characters (Arabic keyboards)
102
+ .replace(/[\u061C\u200E\u200F\u202A-\u202E\u2066-\u2069]/g, '')
103
+ // Normalize Unicode minus variants to ASCII "-"
104
+ .replace(/[\u2212\u2012\u2013\u2014\uFE63\uFF0D]/g, '-');
105
+ /**
106
+ * Converts a string with any Unicode numeral system to a JavaScript number.
107
+ * Handles all numeral systems supported by Intl.NumberFormat.
108
+ *
109
+ * @param {string} input - The input string with numerals in any Unicode system
110
+ * @param {string} locale - The locale for parsing separators
111
+ * @returns {number} The parsed number, or NaN if invalid
112
+ */
113
+ const parseNumberWithLocale = (input, locale) => {
114
+ // Handle empty, null, or undefined inputs
115
+ if (input === '' || input === undefined || input === null) {
116
+ return NaN;
117
+ }
118
+ input = normalizeNumericInput(input);
119
+ const {
120
+ groupSeparator,
121
+ decimalSeparator
122
+ } = getSeparators(locale);
123
+
124
+ // Kanji digit map
125
+ const kanjiMap = {
126
+ 零: '0',
127
+ 〇: '0',
128
+ 一: '1',
129
+ 二: '2',
130
+ 三: '3',
131
+ 四: '4',
132
+ 五: '5',
133
+ 六: '6',
134
+ 七: '7',
135
+ 八: '8',
136
+ 九: '9'
137
+ };
138
+ const digitRanges = [{
139
+ start: 0x0030,
140
+ end: 0x0039,
141
+ base: 0x0030
142
+ }, {
143
+ start: 0x0660,
144
+ end: 0x0669,
145
+ base: 0x0660
146
+ }, {
147
+ start: 0x0966,
148
+ end: 0x096f,
149
+ base: 0x0966
150
+ }, {
151
+ start: 0x09e6,
152
+ end: 0x09ef,
153
+ base: 0x09e6
154
+ }, {
155
+ start: 0xff10,
156
+ end: 0xff19,
157
+ base: 0xff10
158
+ }];
159
+ let normalized = Array.from(input).map(char => {
160
+ // Preserve scientific notation characters
161
+ if (char === 'e' || char === 'E' || char === '+' || char === '-') {
162
+ return char;
163
+ }
164
+
165
+ // Check Kanji first
166
+ if (kanjiMap[char] !== undefined) {
167
+ return kanjiMap[char];
168
+ }
169
+ const code = char.charCodeAt(0);
170
+ for (const range of digitRanges) {
171
+ if (code >= range.start && code <= range.end) {
172
+ return String(code - range.start);
173
+ }
174
+ }
175
+ return char;
176
+ }).join('');
177
+
178
+ // Remove grouping separators
179
+ if (groupSeparator) {
180
+ if (groupSeparator?.trim() === '') {
181
+ normalized = normalized?.replace(/[\u00A0\u202F\s]/g, '');
182
+ } else {
183
+ if (decimalSeparator !== ',' && decimalSeparator !== '٬') {
184
+ normalized = normalized?.replace(/[,٬]/g, '');
185
+ }
186
+ if (groupSeparator !== ',' && groupSeparator !== '٬') {
187
+ const escaped = groupSeparator?.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
188
+ normalized = normalized?.replace(new RegExp(escaped, 'g'), '');
189
+ }
190
+ }
191
+ }
192
+ normalized = normalized.replace(/٫/g, '.');
193
+ if (decimalSeparator && decimalSeparator !== '.' && decimalSeparator !== '٫') {
194
+ const escaped = decimalSeparator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
195
+ normalized = normalized.replace(new RegExp(escaped, 'g'), '.');
196
+ }
197
+ normalized = normalizeMinus(normalized);
198
+ return Number(normalized);
199
+ };
64
200
  const validateNumberSeparators = (input, locale) => {
65
- // allow empty string
66
- if (input === '' || Number.isNaN(input)) {
201
+ if (input === '') {
67
202
  return true;
68
203
  }
204
+
205
+ // Normalize bidi marks + minus signs FIRST
206
+ input = normalizeNumericInput(input);
69
207
  const {
70
208
  groupSeparator,
71
209
  decimalSeparator
@@ -74,35 +212,54 @@ const validateNumberSeparators = (input, locale) => {
74
212
  return !isNaN(Number(input));
75
213
  }
76
214
  const esc = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
215
+ const digit = '[' + '\\u0030-\\u0039' + '\\u0660-\\u0669' + '\\u0966-\\u096F' + '\\u09E6-\\u09EF' + '\\uFF10-\\uFF19' + '一二三四五六七八九〇零' + ']';
216
+
217
+ // Group separator regex
77
218
  let group = '';
78
219
  if (groupSeparator) {
79
- if (groupSeparator.trim() === '') {
80
- group = '[\\u00A0\\u202F\\s]'; // handle NBSP, narrow NBSP, space
220
+ if (groupSeparator?.trim() === '') {
221
+ group = '[\\u00A0\\u202F\\s]';
222
+ } else if (groupSeparator === ',' || groupSeparator === '٬') {
223
+ group = '[,٬]';
81
224
  } else {
82
225
  group = esc(groupSeparator);
83
226
  }
84
227
  }
85
- const decimal = esc(decimalSeparator);
86
228
 
87
- // Regex for:
88
- // - integers (with/without grouping)
89
- // - optional decimal with 0+ digits after separator
90
- const regex = new RegExp(`^-?\\d{1,3}(${group}\\d{3})*(${decimal}\\d*)?$|^-?\\d+(${decimal}\\d*)?$`);
91
- if (!regex.test(input)) {
92
- return false;
229
+ // Decimal separator regex
230
+ let decimal = esc(decimalSeparator);
231
+ if (decimalSeparator === '.' || decimalSeparator === '٫') {
232
+ decimal = '[.٫]';
93
233
  }
234
+ const sign = '[\\-\\u2212]?';
235
+ const scientific = `([eE][+-]?${digit}+)?`;
94
236
 
95
- // Normalize
96
- let normalized = input;
97
- if (groupSeparator) {
98
- if (groupSeparator.trim() === '') {
99
- normalized = normalized?.replace(/[\u00A0\u202F\s]/g, '');
100
- } else {
101
- normalized = normalized?.split(groupSeparator).join('');
102
- }
237
+ // Detect if grouping is used AT ALL
238
+ const usesGrouping = group && (groupSeparator?.trim() === '' ? /[\u00A0\u202F\s]/.test(input) : groupSeparator === ',' || groupSeparator === '٬' ? /[,٬]/.test(input) : groupSeparator ? input.includes(groupSeparator) : false);
239
+ const scientificMatch = input?.match(/^([^eE]+)([eE][+-]?.*)?$/);
240
+ const baseNumber = scientificMatch ? scientificMatch[1] : input;
241
+
242
+ // Split integer part from the base number - handle both decimal separator variants
243
+ let integerPart;
244
+ if (decimalSeparator === '.' || decimalSeparator === '٫') {
245
+ // Split by either . or ٫
246
+ integerPart = baseNumber?.split(/[.,]/)[0];
247
+ } else {
248
+ integerPart = baseNumber?.split(decimalSeparator)[0];
103
249
  }
104
- normalized = normalized?.replace(decimalSeparator, '.');
105
- return !isNaN(Number(normalized));
250
+
251
+ // STEP 1: strict integer validation
252
+ // When grouping is used, we need to handle two cases:
253
+ // 1. Numbers with 1-3 digits (no separator required): 1, 12, 123
254
+ // 2. Numbers with 4+ digits (separator required): 1,234 or 12,345 or 123,456
255
+ const integerRegex = usesGrouping ? new RegExp(`^${sign}(${digit}{1,3}|${digit}{1,3}(${group}${digit}{3})+)$`) : new RegExp(`^${sign}${digit}+$`);
256
+ if (!integerRegex.test(integerPart)) {
257
+ return false;
258
+ }
259
+
260
+ // STEP 2: full number validation
261
+ const fullRegex = new RegExp(`^${sign}${digit}+` + (usesGrouping ? `(${group}${digit}{3})*` : '') + `(${decimal}${digit}+)?${scientific}$`);
262
+ return fullRegex.test(input);
106
263
  };
107
264
 
108
265
  // eslint-disable-next-line react/display-name -- https://github.com/carbon-design-system/carbon/issues/20452
@@ -128,6 +285,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
128
285
  max,
129
286
  min,
130
287
  onBlur,
288
+ onStepperBlur,
131
289
  onChange,
132
290
  onClick,
133
291
  onKeyUp,
@@ -293,8 +451,9 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
293
451
  }
294
452
  };
295
453
  const outerElementClasses = cx(`${prefix}--form-item`, {
296
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
297
- [customClassName]: !!customClassName,
454
+ ...(customClassName ? {
455
+ [customClassName]: true
456
+ } : {}),
298
457
  [`${prefix}--number-input--fluid--invalid`]: isFluid && normalizedProps.invalid,
299
458
  [`${prefix}--number-input--fluid--focus`]: isFluid && isFocused,
300
459
  [`${prefix}--number-input--fluid--disabled`]: isFluid && disabled
@@ -428,6 +587,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
428
587
  if (disableWheelProp) {
429
588
  e.target.removeEventListener('wheel', disableWheel);
430
589
  }
590
+ let parsedValueForBlur;
431
591
  if (type === 'text') {
432
592
  // When isControlled, the current inputValue needs re-parsed
433
593
  // because the consumer's onChange hasn't been called yet and
@@ -443,6 +603,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
443
603
  // causing the _numberValue to mismatch the formatted value in
444
604
  // the input. To avoid this, formattedValue is re-parsed.
445
605
  const parsedFormattedNewValue = numberParser.parse(formattedValue);
606
+ parsedValueForBlur = parsedFormattedNewValue;
446
607
  if (onChange && isValid) {
447
608
  const state = {
448
609
  value: parsedFormattedNewValue,
@@ -468,7 +629,12 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
468
629
  }
469
630
  }
470
631
  if (onBlur) {
471
- onBlur(e);
632
+ if (type === 'number') {
633
+ onBlur(e, value);
634
+ return;
635
+ }
636
+ const parsedTextValue = parsedValueForBlur ?? (isControlled ? numberParser.parse(inputValue) : numberValue);
637
+ onBlur(e, parsedTextValue);
472
638
  }
473
639
  },
474
640
  pattern: pattern,
@@ -488,7 +654,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
488
654
  className: `${prefix}--number__control-btn down-icon`,
489
655
  disabled: disabled || readOnly,
490
656
  onClick: event => handleStepperClick(event, 'down'),
491
- onBlur: onBlur,
657
+ onBlur: onStepperBlur,
492
658
  tabIndex: -1,
493
659
  title: decrementNumLabel || iconDescription,
494
660
  type: "button"
@@ -501,7 +667,7 @@ const NumberInput = /*#__PURE__*/React.forwardRef((props, forwardRef) => {
501
667
  className: `${prefix}--number__control-btn up-icon`,
502
668
  disabled: disabled || readOnly,
503
669
  onClick: event => handleStepperClick(event, 'up'),
504
- onBlur: onBlur,
670
+ onBlur: onStepperBlur,
505
671
  tabIndex: -1,
506
672
  title: incrementNumLabel || iconDescription,
507
673
  type: "button"
@@ -612,10 +778,14 @@ NumberInput.propTypes = {
612
778
  */
613
779
  stepStartValue: PropTypes.number,
614
780
  /**
615
- * Provide an optional handler that is called when the input or stepper
616
- * buttons are blurred.
781
+ * Provide an optional handler that is called when the input is blurred.
617
782
  */
618
783
  onBlur: PropTypes.func,
784
+ /**
785
+ * Provide an optional handler that is called when the stepper
786
+ * buttons are blurred.
787
+ */
788
+ onStepperBlur: PropTypes.func,
619
789
  /**
620
790
  * Provide an optional handler that is called when the internal state of
621
791
  * NumberInput changes. This handler is called with event and state info.
@@ -754,23 +924,33 @@ function getInputValidity({
754
924
  validate,
755
925
  locale
756
926
  }) {
757
- if (typeof validate === 'function') {
758
- const result = validate(value, locale);
759
- if (result === false) {
760
- return false; // immediate invalid
761
- }
762
- // If true or undefined, continue to further validations
763
- }
764
927
  if (invalid) {
765
928
  return false;
766
929
  }
767
- if (value === '') {
768
- return allowEmpty;
930
+
931
+ // Skip validation if value is empty and allowEmpty
932
+ if (value === '') return allowEmpty;
933
+
934
+ // Normalize the value
935
+ let numericValue;
936
+ if (typeof value === 'string') {
937
+ numericValue = parseNumberWithLocale(value, locale); // safe: handles Arabic, Kanji, etc.
938
+ } else {
939
+ numericValue = value;
769
940
  }
770
- if (value > max || value < min) {
771
- return false;
941
+
942
+ // Use custom validate ONLY for formatting, not numeric comparison
943
+ if (validate && typeof value === 'string') {
944
+ const isFormatValid = validate(value, locale);
945
+ if (isFormatValid === false) {
946
+ return false; // invalid format
947
+ }
772
948
  }
773
- return true;
949
+
950
+ // Check min/max bounds
951
+ if (max !== undefined && numericValue > max) return false;
952
+ if (min !== undefined && numericValue < min) return false;
953
+ return true; // valid
774
954
  }
775
955
 
776
956
  /**
@@ -792,4 +972,5 @@ function disableWheel(e) {
792
972
  }
793
973
 
794
974
  exports.NumberInput = NumberInput;
975
+ exports.parseNumberWithLocale = parseNumberWithLocale;
795
976
  exports.validateNumberSeparators = validateNumberSeparators;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright IBM Corp. 2016, 2025
2
+ * Copyright IBM Corp. 2016, 2026
3
3
  *
4
4
  * This source code is licensed under the Apache-2.0 license found in the
5
5
  * LICENSE file in the root directory of this source tree.
@@ -62,27 +62,41 @@ forwardRef) {
62
62
  const caretRef = React.useRef(null);
63
63
  const popover = React.useRef(null);
64
64
  const enableFloatingStyles = index.useFeatureFlag('enable-v12-dynamic-floating-styles') || autoAlign;
65
+ const lastClickWasInsidePopoverContent = React.useRef(false);
65
66
  let align = mapPopoverAlign.mapPopoverAlign(initialAlign);
66
67
 
68
+ // Tracks clicks inside PopoverContent to prevent it from closing when clicked, this handles an edge
69
+ // case where the popover will close when clicking non-focusable elements (e.g. text)
70
+ useEvent.useEvent(popover, 'mousedown', event => {
71
+ const target = event.target;
72
+ lastClickWasInsidePopoverContent.current = refs.floating.current?.contains(target) || false;
73
+
74
+ // reset flag
75
+ if (lastClickWasInsidePopoverContent.current) {
76
+ setTimeout(() => {
77
+ lastClickWasInsidePopoverContent.current = false;
78
+ }, 0);
79
+ }
80
+ });
81
+
67
82
  // The `Popover` should close whenever it and its children loses focus
68
83
  useEvent.useEvent(popover, 'focusout', event => {
69
84
  const relatedTarget = event.relatedTarget;
70
- if (isTabTip) {
71
- if (relatedTarget && !popover.current?.contains(relatedTarget)) {
72
- onRequestClose?.();
73
- }
74
- return;
75
- }
76
85
  if (!relatedTarget) {
86
+ // do not close if PopoverContent was clicked
87
+ if (lastClickWasInsidePopoverContent.current) {
88
+ lastClickWasInsidePopoverContent.current = false;
89
+ return;
90
+ }
77
91
  onRequestClose?.();
78
- return;
79
- }
80
- const isOutsideMainContainer = !popover.current?.contains(relatedTarget);
81
- const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
92
+ } else if (relatedTarget && !popover.current?.contains(relatedTarget)) {
93
+ const isOutsideFloating = enableFloatingStyles && refs.floating.current ? !refs.floating.current.contains(relatedTarget) : true;
94
+ const isFocusableWrapper = relatedTarget && popover.current && relatedTarget.contains(popover.current);
82
95
 
83
- // Only close if focus moved outside both containers
84
- if (isOutsideMainContainer && isOutsideFloating) {
85
- onRequestClose?.();
96
+ // Only close if focus moved outside both containers and not to an interactive parent wrapper
97
+ if (isOutsideFloating && !isFocusableWrapper) {
98
+ onRequestClose?.();
99
+ }
86
100
  }
87
101
  });
88
102
  useEvent.useWindowEvent('click', ({
@@ -888,7 +888,7 @@ const Tab = /*#__PURE__*/React.forwardRef(({
888
888
  })
889
889
  }, /*#__PURE__*/React.createElement("button", {
890
890
  type: "button",
891
- tabIndex: selectedIndex === index$1 && dismissable ? 0 : -1,
891
+ tabIndex: -1,
892
892
  "aria-disabled": disabled,
893
893
  "aria-hidden": selectedIndex === index$1 && dismissable ? 'false' : 'true',
894
894
  disabled: disabled,
@@ -206,8 +206,10 @@ const TextArea = frFn((props, forwardRef) => {
206
206
  }, labelText) : null;
207
207
  const counter = enableCounter && maxCount && (counterMode === 'character' || counterMode === 'word') ? /*#__PURE__*/React.createElement(Text.Text, {
208
208
  as: "div",
209
- className: counterClasses
209
+ className: counterClasses,
210
+ "aria-hidden": "true"
210
211
  }, `${textCount}/${maxCount}`) : null;
212
+ const counterDescriptionId = enableCounter && maxCount ? `${id}-counter-desc` : undefined;
211
213
  const helperId = !helperText ? undefined : `text-area-helper-text-${textAreaInstanceId}`;
212
214
  const helper = helperText ? /*#__PURE__*/React.createElement(Text.Text, {
213
215
  as: "div",
@@ -238,8 +240,13 @@ const TextArea = frFn((props, forwardRef) => {
238
240
  let ariaDescribedBy;
239
241
  if (invalid) {
240
242
  ariaDescribedBy = errorId;
241
- } else if (!invalid && !warn && !isFluid && helperText) {
242
- ariaDescribedBy = helperId;
243
+ } else if (warn && !isFluid) {
244
+ ariaDescribedBy = warnId;
245
+ } else {
246
+ const ids = [];
247
+ if (!isFluid && helperText && helperId) ids.push(helperId);
248
+ if (counterDescriptionId) ids.push(counterDescriptionId);
249
+ ariaDescribedBy = ids.length > 0 ? ids.join(' ') : undefined;
243
250
  }
244
251
  if (enableCounter) {
245
252
  // handle different counter mode
@@ -296,7 +303,10 @@ const TextArea = frFn((props, forwardRef) => {
296
303
  className: formItemClasses
297
304
  }, /*#__PURE__*/React.createElement("div", {
298
305
  className: `${prefix}--text-area__label-wrapper`
299
- }, label, counter), /*#__PURE__*/React.createElement("div", {
306
+ }, label, counter), enableCounter && maxCount && /*#__PURE__*/React.createElement("span", {
307
+ id: counterDescriptionId,
308
+ className: `${prefix}--visually-hidden`
309
+ }, counterMode === 'word' ? `Word limit ${maxCount}` : `Character limit ${maxCount}`), /*#__PURE__*/React.createElement("div", {
300
310
  ref: wrapperRef,
301
311
  className: textAreaWrapperClasses,
302
312
  "data-invalid": invalid || null
@@ -139,6 +139,7 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
139
139
  [`${prefix}--tooltip--${tooltipPosition}`]: tooltipPosition,
140
140
  [`${prefix}--tooltip--align-${tooltipAlignment}`]: tooltipAlignment
141
141
  });
142
+ const tooltipClasses = cx(`${prefix}--toggle-password-tooltip`, `${prefix}--icon-tooltip`);
142
143
  let align = undefined;
143
144
  if (tooltipPosition === 'top' || tooltipPosition === 'bottom') {
144
145
  if (tooltipAlignment === 'center') {
@@ -176,12 +177,12 @@ const PasswordInput = /*#__PURE__*/React.forwardRef(({
176
177
  className: `${prefix}--text-input__divider`
177
178
  }), /*#__PURE__*/React.createElement(Tooltip.Tooltip, {
178
179
  align: align,
179
- className: `${prefix}--toggle-password-tooltip`,
180
+ className: tooltipClasses,
180
181
  label: passwordIsVisible ? hidePasswordLabel : showPasswordLabel
181
182
  }, /*#__PURE__*/React.createElement("button", {
182
183
  type: "button",
183
184
  className: passwordVisibilityToggleClasses,
184
- disabled: disabled || readOnly,
185
+ disabled: disabled,
185
186
  onClick: handleTogglePasswordVisibility
186
187
  }, passwordVisibilityIcon)));
187
188
  React.useEffect(() => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@carbon/react",
3
3
  "description": "React components for the Carbon Design System",
4
- "version": "1.98.0",
4
+ "version": "1.99.0",
5
5
  "license": "Apache-2.0",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -53,9 +53,9 @@
53
53
  "dependencies": {
54
54
  "@babel/runtime": "^7.27.3",
55
55
  "@carbon/feature-flags": ">=0.32.0",
56
- "@carbon/icons-react": "^11.72.0",
57
- "@carbon/layout": "^11.45.0",
58
- "@carbon/styles": "^1.97.0",
56
+ "@carbon/icons-react": "^11.73.0",
57
+ "@carbon/layout": "^11.46.0",
58
+ "@carbon/styles": "^1.98.0",
59
59
  "@carbon/utilities": "^0.14.0",
60
60
  "@floating-ui/react": "^0.27.4",
61
61
  "@ibm/telemetry-js": "^1.5.0",
@@ -67,7 +67,6 @@
67
67
  "invariant": "^2.2.3",
68
68
  "prop-types": "^15.8.1",
69
69
  "react-fast-compare": "^3.2.2",
70
- "storybook-addon-accessibility-checker": "^9.2.0-rc.3",
71
70
  "tabbable": "^6.2.0"
72
71
  },
73
72
  "devDependencies": {
@@ -79,8 +78,8 @@
79
78
  "@babel/preset-env": "^7.27.2",
80
79
  "@babel/preset-react": "^7.27.1",
81
80
  "@babel/preset-typescript": "^7.27.1",
82
- "@carbon/test-utils": "^10.38.0",
83
- "@carbon/themes": "^11.65.0",
81
+ "@carbon/test-utils": "^10.39.0",
82
+ "@carbon/themes": "^11.66.0",
84
83
  "@figma/code-connect": "^1.3.5",
85
84
  "@rollup/plugin-babel": "^6.0.0",
86
85
  "@rollup/plugin-commonjs": "^28.0.3",
@@ -105,8 +104,8 @@
105
104
  "fs-extra": "^11.0.0",
106
105
  "process": "^0.11.10",
107
106
  "prop-types": "^15.8.1",
108
- "react": "^19.0.0",
109
- "react-dom": "^19.0.0",
107
+ "react": "^19.2.3",
108
+ "react-dom": "^19.2.3",
110
109
  "react-is": "^16.13.1 || ^17.0.2 || ^18.3.1 || ^19.0.0",
111
110
  "remark-gfm": "^4.0.0",
112
111
  "rimraf": "^6.0.1",
@@ -132,5 +131,5 @@
132
131
  "**/*.scss",
133
132
  "**/*.css"
134
133
  ],
135
- "gitHead": "57fdbc7bfad9349b5c4359c7d621e709cd4daa25"
134
+ "gitHead": "ce7846aab8a3a1afe9b03d2d07d267af6cdb6ac2"
136
135
  }
package/telemetry.yml CHANGED
@@ -465,6 +465,7 @@ collect:
465
465
  - notificationType
466
466
  # NumberInput
467
467
  - hideSteppers
468
+ - onStepperBlur
468
469
  - stepStartValue
469
470
  - validate
470
471
  # OrderedList