@edux-design/buttons 0.1.4 → 0.2.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.
- package/CHANGELOG.md +4 -9
- package/README.md +62 -50
- package/dist/chevron-EVM4GL6D.svg +4 -0
- package/dist/chunk-M47FNL4P.mjs +10 -0
- package/dist/elements/Button.js +39 -0
- package/dist/elements/Button.mjs +6 -0
- package/dist/index.d.mts +29 -15
- package/dist/index.d.ts +29 -15
- package/dist/index.js +110 -63
- package/dist/index.mjs +88 -40
- package/package.json +4 -9
- package/src/demo/Button.stories.jsx +103 -0
- package/src/demo/ButtonCompatibility.stories.jsx +115 -0
- package/src/demo/ButtonCounter.stories.jsx +101 -0
- package/src/demo/ButtonGroup.stories.jsx +67 -0
- package/src/elements/Button.a11y.test.jsx +60 -0
- package/src/elements/Button.jsx +127 -0
- package/src/elements/Button.test.jsx +120 -0
- package/src/elements/ButtonCounter.jsx +356 -0
- package/src/elements/ButtonCounter.test.jsx +121 -0
- package/src/elements/ButtonGroup.jsx +404 -0
- package/src/elements/ButtonGroup.test.jsx +130 -0
- package/src/elements/ButtonGroupItem.jsx +8 -0
- package/src/elements/IconButton.jsx +115 -0
- package/src/elements/IconButton.test.jsx +62 -0
- package/src/elements/MenuButton.jsx +68 -0
- package/src/elements/MenuButton.test.jsx +40 -0
- package/src/elements/testA11y.js +14 -0
- package/src/index.js +6 -0
- package/src/util/MenuButtonContext.jsx +3 -0
- package/tsconfig.json +12 -0
package/dist/index.js
CHANGED
|
@@ -65,12 +65,20 @@ var IconButton = (0, import_react.forwardRef)(
|
|
|
65
65
|
"[IconButton]: Multiple variant props passed. Using the highest priority only."
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
|
+
const hasAccessibleName = Boolean(
|
|
69
|
+
props["aria-label"] || props["aria-labelledby"]
|
|
70
|
+
);
|
|
71
|
+
if (!hasAccessibleName) {
|
|
72
|
+
console.warn(
|
|
73
|
+
"[IconButton]: Provide an accessible name with aria-label or aria-labelledby."
|
|
74
|
+
);
|
|
75
|
+
}
|
|
68
76
|
}
|
|
69
77
|
const defaults = "flex justify-center items-center focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out rounded-full cursor-pointer";
|
|
70
78
|
const sizes = {
|
|
71
|
-
small: "
|
|
72
|
-
medium: "
|
|
73
|
-
large: "
|
|
79
|
+
small: "size-control-sm text-sm",
|
|
80
|
+
medium: "size-control-md text-base",
|
|
81
|
+
large: "size-control-lg text-lg"
|
|
74
82
|
};
|
|
75
83
|
const variants = {
|
|
76
84
|
primary: "border-2 border-border-primary-emphasis bg-bg-primary-base text-white hover:bg-border-focus hover:text-fg-focus hover:border-border-emphasis hover:shadow-md active:bg-border-focus active:bg-bg-focus-overlay active:text-fg-focus",
|
|
@@ -173,13 +181,7 @@ var Button = (0, import_react2.forwardRef)(
|
|
|
173
181
|
);
|
|
174
182
|
|
|
175
183
|
// src/elements/MenuButton.jsx
|
|
176
|
-
var import_react4 = __toESM(require("react"));
|
|
177
|
-
|
|
178
|
-
// src/util/MenuButtonContext.jsx
|
|
179
184
|
var import_react3 = __toESM(require("react"));
|
|
180
|
-
var MenuButtonContext = (0, import_react3.createContext)();
|
|
181
|
-
|
|
182
|
-
// src/elements/MenuButton.jsx
|
|
183
185
|
var import_utils3 = require("@edux-design/utils");
|
|
184
186
|
|
|
185
187
|
// ../icons/dist/index.mjs
|
|
@@ -208,22 +210,41 @@ var Chevron_default = SvgChevron;
|
|
|
208
210
|
|
|
209
211
|
// src/elements/MenuButton.jsx
|
|
210
212
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
var MenuButton = (0, import_react3.forwardRef)(function MenuButton2({
|
|
214
|
+
children,
|
|
215
|
+
caret,
|
|
216
|
+
size = "medium",
|
|
217
|
+
className,
|
|
218
|
+
type = "button",
|
|
219
|
+
"aria-haspopup": ariaHasPopup = "menu",
|
|
220
|
+
...props
|
|
221
|
+
}, ref) {
|
|
222
|
+
const styles = (0, import_utils3.cx)(
|
|
223
|
+
"inline-flex items-center justify-center gap-8 rounded-lg border-2 border-border-primary-base bg-bg-base px-16 text-fg-primary-emphasis transition-all duration-300 ease-in-out outline-none focus:shadow-focus focus-visible:shadow-focus disabled:cursor-not-allowed disabled:border-border-subtle disabled:bg-bg-inactive disabled:text-fg-inactive",
|
|
224
|
+
{
|
|
225
|
+
"min-h-control-sm text-sm": size === "small",
|
|
226
|
+
"min-h-control-md text-base": size === "medium"
|
|
227
|
+
},
|
|
228
|
+
className
|
|
229
|
+
);
|
|
230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
231
|
+
"button",
|
|
214
232
|
{
|
|
215
|
-
|
|
216
|
-
|
|
233
|
+
...props,
|
|
234
|
+
ref,
|
|
235
|
+
type,
|
|
236
|
+
"aria-haspopup": ariaHasPopup,
|
|
237
|
+
className: styles,
|
|
238
|
+
children: [
|
|
239
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children }) : null,
|
|
240
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { "aria-hidden": "true", className: "flex items-center text-current", children: caret ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chevron_default, {}) })
|
|
241
|
+
]
|
|
217
242
|
}
|
|
218
243
|
);
|
|
219
|
-
|
|
220
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: SPLIT_BUTTON_STYLES, children }),
|
|
221
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Chevron_default, {})
|
|
222
|
-
] });
|
|
223
|
-
}
|
|
244
|
+
});
|
|
224
245
|
|
|
225
246
|
// src/elements/ButtonGroup.jsx
|
|
226
|
-
var
|
|
247
|
+
var import_react4 = __toESM(require("react"));
|
|
227
248
|
var import_utils4 = require("@edux-design/utils");
|
|
228
249
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
229
250
|
var SIZE_STYLES = {
|
|
@@ -238,8 +259,8 @@ var SIZE_STYLES = {
|
|
|
238
259
|
}
|
|
239
260
|
};
|
|
240
261
|
var isBrowser = typeof window !== "undefined";
|
|
241
|
-
var useIsomorphicLayoutEffect = isBrowser ?
|
|
242
|
-
var ButtonGroup = (0,
|
|
262
|
+
var useIsomorphicLayoutEffect = isBrowser ? import_react4.useLayoutEffect : import_react4.useEffect;
|
|
263
|
+
var ButtonGroup = (0, import_react4.forwardRef)(function ButtonGroup2({
|
|
243
264
|
value,
|
|
244
265
|
defaultValue,
|
|
245
266
|
onChange,
|
|
@@ -249,7 +270,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
249
270
|
children,
|
|
250
271
|
...rest
|
|
251
272
|
}, forwardedRef) {
|
|
252
|
-
const normalizedOptions = (0,
|
|
273
|
+
const normalizedOptions = (0, import_react4.useMemo)(() => {
|
|
253
274
|
const childItems = (0, import_utils4.filterChildrenByDisplayName)(children, "ButtonGroupItem");
|
|
254
275
|
return childItems.map((child, index) => {
|
|
255
276
|
const props = child.props || {};
|
|
@@ -264,30 +285,30 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
264
285
|
}, [children]);
|
|
265
286
|
const sizeStyles = SIZE_STYLES[size] ?? SIZE_STYLES.medium;
|
|
266
287
|
const initialValue = value ?? defaultValue ?? (normalizedOptions.length ? normalizedOptions[0].value : void 0);
|
|
267
|
-
const [internalValue, setInternalValue] = (0,
|
|
288
|
+
const [internalValue, setInternalValue] = (0, import_react4.useState)(initialValue);
|
|
268
289
|
const isControlled = value !== void 0;
|
|
269
290
|
const selectedValue = isControlled ? value : internalValue;
|
|
270
|
-
(0,
|
|
291
|
+
(0, import_react4.useEffect)(() => {
|
|
271
292
|
if (!isControlled && defaultValue !== void 0) {
|
|
272
293
|
setInternalValue(defaultValue);
|
|
273
294
|
}
|
|
274
295
|
}, [defaultValue, isControlled]);
|
|
275
|
-
(0,
|
|
296
|
+
(0, import_react4.useEffect)(() => {
|
|
276
297
|
if (isControlled) return;
|
|
277
298
|
if (normalizedOptions.length && !normalizedOptions.some((option) => option.value === internalValue)) {
|
|
278
299
|
setInternalValue(normalizedOptions[0].value);
|
|
279
300
|
}
|
|
280
301
|
}, [internalValue, isControlled, normalizedOptions]);
|
|
281
|
-
const buttonRefs = (0,
|
|
282
|
-
const containerRef = (0,
|
|
283
|
-
const indicatorRef = (0,
|
|
284
|
-
const [indicator, setIndicator] = (0,
|
|
302
|
+
const buttonRefs = (0, import_react4.useRef)(/* @__PURE__ */ new Map());
|
|
303
|
+
const containerRef = (0, import_react4.useRef)(null);
|
|
304
|
+
const indicatorRef = (0, import_react4.useRef)({ width: 0, height: 0, x: 0, y: 0 });
|
|
305
|
+
const [indicator, setIndicator] = (0, import_react4.useState)({
|
|
285
306
|
width: 0,
|
|
286
307
|
height: 0,
|
|
287
308
|
x: 0,
|
|
288
309
|
y: 0
|
|
289
310
|
});
|
|
290
|
-
const setContainerRef = (0,
|
|
311
|
+
const setContainerRef = (0, import_react4.useCallback)(
|
|
291
312
|
(node) => {
|
|
292
313
|
containerRef.current = node;
|
|
293
314
|
if (typeof forwardedRef === "function") {
|
|
@@ -298,7 +319,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
298
319
|
},
|
|
299
320
|
[forwardedRef]
|
|
300
321
|
);
|
|
301
|
-
const registerButtonRef = (0,
|
|
322
|
+
const registerButtonRef = (0, import_react4.useCallback)((optionValue) => {
|
|
302
323
|
return (node) => {
|
|
303
324
|
if (!buttonRefs.current) return;
|
|
304
325
|
if (node) {
|
|
@@ -308,7 +329,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
308
329
|
}
|
|
309
330
|
};
|
|
310
331
|
}, []);
|
|
311
|
-
const updateIndicator = (0,
|
|
332
|
+
const updateIndicator = (0, import_react4.useCallback)(() => {
|
|
312
333
|
const container = containerRef.current;
|
|
313
334
|
const target = buttonRefs.current.get(selectedValue);
|
|
314
335
|
if (!container || !target) {
|
|
@@ -335,13 +356,13 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
335
356
|
useIsomorphicLayoutEffect(() => {
|
|
336
357
|
updateIndicator();
|
|
337
358
|
}, [updateIndicator, normalizedOptions.length, size]);
|
|
338
|
-
(0,
|
|
359
|
+
(0, import_react4.useEffect)(() => {
|
|
339
360
|
if (!isBrowser) return;
|
|
340
361
|
const handleResize = () => updateIndicator();
|
|
341
362
|
window.addEventListener("resize", handleResize);
|
|
342
363
|
return () => window.removeEventListener("resize", handleResize);
|
|
343
364
|
}, [updateIndicator]);
|
|
344
|
-
(0,
|
|
365
|
+
(0, import_react4.useEffect)(() => {
|
|
345
366
|
if (!isBrowser) return;
|
|
346
367
|
const node = containerRef.current;
|
|
347
368
|
if (!node || typeof ResizeObserver === "undefined") return;
|
|
@@ -351,13 +372,13 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
351
372
|
observer.observe(node);
|
|
352
373
|
return () => observer.disconnect();
|
|
353
374
|
}, [updateIndicator]);
|
|
354
|
-
const focusOption = (0,
|
|
375
|
+
const focusOption = (0, import_react4.useCallback)((option) => {
|
|
355
376
|
const node = buttonRefs.current.get(option.value);
|
|
356
377
|
if (node) {
|
|
357
378
|
node.focus();
|
|
358
379
|
}
|
|
359
380
|
}, []);
|
|
360
|
-
const handleSelect = (0,
|
|
381
|
+
const handleSelect = (0, import_react4.useCallback)(
|
|
361
382
|
(option) => {
|
|
362
383
|
if (option.disabled || option.value === selectedValue) {
|
|
363
384
|
return;
|
|
@@ -371,7 +392,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
371
392
|
},
|
|
372
393
|
[isControlled, onChange, selectedValue]
|
|
373
394
|
);
|
|
374
|
-
const getNextEnabledIndex = (0,
|
|
395
|
+
const getNextEnabledIndex = (0, import_react4.useCallback)(
|
|
375
396
|
(startIndex, direction) => {
|
|
376
397
|
if (!normalizedOptions.length) return -1;
|
|
377
398
|
let nextIndex = startIndex;
|
|
@@ -385,10 +406,10 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
385
406
|
},
|
|
386
407
|
[normalizedOptions]
|
|
387
408
|
);
|
|
388
|
-
const findFirstEnabledIndex = (0,
|
|
409
|
+
const findFirstEnabledIndex = (0, import_react4.useCallback)(() => {
|
|
389
410
|
return normalizedOptions.findIndex((option) => !option.disabled);
|
|
390
411
|
}, [normalizedOptions]);
|
|
391
|
-
const findLastEnabledIndex = (0,
|
|
412
|
+
const findLastEnabledIndex = (0, import_react4.useCallback)(() => {
|
|
392
413
|
for (let i = normalizedOptions.length - 1; i >= 0; i -= 1) {
|
|
393
414
|
if (!normalizedOptions[i].disabled) {
|
|
394
415
|
return i;
|
|
@@ -397,8 +418,15 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
397
418
|
return -1;
|
|
398
419
|
}, [normalizedOptions]);
|
|
399
420
|
const indicatorVisible = indicator.width > 0 && indicator.height > 0;
|
|
421
|
+
const selectedIndex = normalizedOptions.findIndex(
|
|
422
|
+
(option) => option.value === selectedValue && !option.disabled
|
|
423
|
+
);
|
|
424
|
+
const firstEnabledIndex = normalizedOptions.findIndex(
|
|
425
|
+
(option) => !option.disabled
|
|
426
|
+
);
|
|
427
|
+
const activeTabStopIndex = selectedIndex >= 0 ? selectedIndex : firstEnabledIndex;
|
|
400
428
|
const rootClasses = (0, import_utils4.cx)(
|
|
401
|
-
"inline-flex h-
|
|
429
|
+
"inline-flex h-control-md rounded-lg border-2 border-border-subtle bg-bg-base/90 p-2 shadow-inner",
|
|
402
430
|
isStretched ? "w-full" : "w-auto",
|
|
403
431
|
className
|
|
404
432
|
);
|
|
@@ -407,7 +435,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
407
435
|
!isStretched && "w-auto"
|
|
408
436
|
);
|
|
409
437
|
const buttonBaseClasses = (0, import_utils4.cx)(
|
|
410
|
-
"relative z-10 h-
|
|
438
|
+
"relative z-10 h-control-sm inline-flex items-center justify-center gap-2 whitespace-nowrap font-semibold tracking-tight transition-colors duration-200 ease-out focus-visible:outline-none focus-visible:shadow-focus motion-reduce:duration-0",
|
|
411
439
|
sizeStyles.button,
|
|
412
440
|
isStretched ? "flex-1" : "w-auto"
|
|
413
441
|
);
|
|
@@ -417,6 +445,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
417
445
|
...rest,
|
|
418
446
|
ref: setContainerRef,
|
|
419
447
|
role: "radiogroup",
|
|
448
|
+
"aria-orientation": "horizontal",
|
|
420
449
|
className: rootClasses,
|
|
421
450
|
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: trackClasses, children: [
|
|
422
451
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -424,13 +453,13 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
424
453
|
{
|
|
425
454
|
"aria-hidden": "true",
|
|
426
455
|
className: (0, import_utils4.cx)(
|
|
427
|
-
"pointer-events-none h-
|
|
456
|
+
"pointer-events-none h-control-md absolute rounded-md border-2 border-border-primary-emphasis bg-bg-base shadow-[0_8px_20px_rgb(22_92_131/0.18)] transition-[transform,width,height] duration-300 ease-out motion-reduce:duration-0",
|
|
428
457
|
!indicatorVisible && "opacity-0"
|
|
429
458
|
),
|
|
430
459
|
style: {
|
|
431
460
|
width: indicator.width || void 0,
|
|
432
461
|
height: indicator.height || void 0,
|
|
433
|
-
transform: `translate(${indicator.x - 4}px`
|
|
462
|
+
transform: `translate(${indicator.x - 4}px, ${indicator.y - 4}px)`
|
|
434
463
|
}
|
|
435
464
|
}
|
|
436
465
|
),
|
|
@@ -488,6 +517,7 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
488
517
|
type: "button",
|
|
489
518
|
role: "radio",
|
|
490
519
|
"aria-checked": isActive,
|
|
520
|
+
tabIndex: option.disabled ? -1 : index === activeTabStopIndex ? 0 : -1,
|
|
491
521
|
disabled: option.disabled,
|
|
492
522
|
className: buttonClasses,
|
|
493
523
|
onClick: () => handleSelect(option),
|
|
@@ -522,17 +552,17 @@ var ButtonGroup = (0, import_react5.forwardRef)(function ButtonGroup2({
|
|
|
522
552
|
});
|
|
523
553
|
|
|
524
554
|
// src/elements/ButtonGroupItem.jsx
|
|
525
|
-
var
|
|
555
|
+
var import_react5 = __toESM(require("react"));
|
|
526
556
|
function ButtonGroupItem(_props) {
|
|
527
557
|
return null;
|
|
528
558
|
}
|
|
529
559
|
ButtonGroupItem.displayName = "ButtonGroupItem";
|
|
530
560
|
|
|
531
561
|
// src/elements/ButtonCounter.jsx
|
|
532
|
-
var
|
|
562
|
+
var import_react6 = __toESM(require("react"));
|
|
533
563
|
var import_utils5 = require("@edux-design/utils");
|
|
534
564
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
535
|
-
var ButtonCounter = (0,
|
|
565
|
+
var ButtonCounter = (0, import_react6.forwardRef)(function ButtonCounter2({
|
|
536
566
|
value,
|
|
537
567
|
defaultValue = 1,
|
|
538
568
|
onChange,
|
|
@@ -555,16 +585,17 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
555
585
|
decrementButtonProps,
|
|
556
586
|
incrementButtonProps,
|
|
557
587
|
className,
|
|
588
|
+
"aria-label": ariaLabel,
|
|
558
589
|
...rest
|
|
559
590
|
}, ref) {
|
|
560
591
|
const isControlled = value !== void 0;
|
|
561
|
-
const [internalValue, setInternalValue] = (0,
|
|
592
|
+
const [internalValue, setInternalValue] = (0, import_react6.useState)(defaultValue);
|
|
562
593
|
const currentValue = isControlled ? value : internalValue;
|
|
563
|
-
const clampedValue = (0,
|
|
594
|
+
const clampedValue = (0, import_react6.useMemo)(() => {
|
|
564
595
|
const safe = Number.isFinite(currentValue) ? currentValue : defaultValue;
|
|
565
596
|
return Math.min(max, Math.max(min, safe));
|
|
566
597
|
}, [currentValue, defaultValue, max, min]);
|
|
567
|
-
const commitValue = (0,
|
|
598
|
+
const commitValue = (0, import_react6.useCallback)(
|
|
568
599
|
(next) => {
|
|
569
600
|
const clamped = Math.min(max, Math.max(min, next));
|
|
570
601
|
if (!isControlled) setInternalValue(clamped);
|
|
@@ -600,16 +631,16 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
600
631
|
}
|
|
601
632
|
const CONTROL_SIZES = {
|
|
602
633
|
small: {
|
|
603
|
-
button: "
|
|
604
|
-
display: "h-
|
|
634
|
+
button: "size-control-sm text-sm",
|
|
635
|
+
display: "h-control-sm min-w-[48px] px-12 text-sm"
|
|
605
636
|
},
|
|
606
637
|
medium: {
|
|
607
|
-
button: "
|
|
608
|
-
display: "h-
|
|
638
|
+
button: "size-control-md text-base",
|
|
639
|
+
display: "h-control-md min-w-[56px] px-12 text-base"
|
|
609
640
|
},
|
|
610
641
|
large: {
|
|
611
|
-
button: "
|
|
612
|
-
display: "h-
|
|
642
|
+
button: "size-control-lg text-lg",
|
|
643
|
+
display: "h-control-lg min-w-[72px] px-16 text-lg"
|
|
613
644
|
}
|
|
614
645
|
};
|
|
615
646
|
const defaultsButton = "flex justify-center items-center focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out cursor-pointer";
|
|
@@ -667,14 +698,17 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
667
698
|
);
|
|
668
699
|
const effectiveDecrementIcon = decrementIcon ?? startIcon ?? "-";
|
|
669
700
|
const effectiveIncrementIcon = incrementIcon ?? endIcon ?? "+";
|
|
670
|
-
const
|
|
671
|
-
const
|
|
672
|
-
const
|
|
673
|
-
(0,
|
|
701
|
+
const generatedValueId = (0, import_react6.useId)();
|
|
702
|
+
const valueElementId = (inputProps == null ? void 0 : inputProps.id) ?? generatedValueId;
|
|
703
|
+
const valueAriaLabel = (inputProps == null ? void 0 : inputProps["aria-label"]) ?? ariaLabel ?? "Value";
|
|
704
|
+
const [draftValue, setDraftValue] = (0, import_react6.useState)(String(clampedValue));
|
|
705
|
+
const [isEditing, setIsEditing] = (0, import_react6.useState)(false);
|
|
706
|
+
const inputRef = (0, import_react6.useRef)(null);
|
|
707
|
+
(0, import_react6.useEffect)(() => {
|
|
674
708
|
if (isEditing) return;
|
|
675
709
|
setDraftValue(String(clampedValue));
|
|
676
710
|
}, [clampedValue, isEditing]);
|
|
677
|
-
const commitDraft = (0,
|
|
711
|
+
const commitDraft = (0, import_react6.useCallback)(() => {
|
|
678
712
|
const trimmed = String(draftValue).trim();
|
|
679
713
|
if (trimmed === "") {
|
|
680
714
|
setDraftValue(String(clampedValue));
|
|
@@ -700,6 +734,7 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
700
734
|
...decrementButtonProps,
|
|
701
735
|
type: "button",
|
|
702
736
|
"aria-label": (decrementButtonProps == null ? void 0 : decrementButtonProps["aria-label"]) ?? "Decrease",
|
|
737
|
+
"aria-controls": valueElementId,
|
|
703
738
|
"aria-disabled": decrementDisabled,
|
|
704
739
|
disabled: decrementDisabled,
|
|
705
740
|
className: (0, import_utils5.cx)(
|
|
@@ -723,8 +758,9 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
723
758
|
ref: inputRef,
|
|
724
759
|
type: "number",
|
|
725
760
|
inputMode: "numeric",
|
|
761
|
+
id: valueElementId,
|
|
726
762
|
disabled: !!disabled,
|
|
727
|
-
"aria-label":
|
|
763
|
+
"aria-label": valueAriaLabel,
|
|
728
764
|
className: (0, import_utils5.cx)(
|
|
729
765
|
displayStyles,
|
|
730
766
|
"w-[44px] text-center outline-none bg-transparent text-fg-base",
|
|
@@ -765,13 +801,24 @@ var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
|
765
801
|
}
|
|
766
802
|
}
|
|
767
803
|
}
|
|
768
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
804
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
805
|
+
"output",
|
|
806
|
+
{
|
|
807
|
+
id: valueElementId,
|
|
808
|
+
"aria-label": valueAriaLabel,
|
|
809
|
+
"aria-live": "polite",
|
|
810
|
+
"aria-atomic": "true",
|
|
811
|
+
className: (0, import_utils5.cx)(displayStyles, "select-none"),
|
|
812
|
+
children: children ?? clampedValue
|
|
813
|
+
}
|
|
814
|
+
),
|
|
769
815
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
770
816
|
"button",
|
|
771
817
|
{
|
|
772
818
|
...incrementButtonProps,
|
|
773
819
|
type: "button",
|
|
774
820
|
"aria-label": (incrementButtonProps == null ? void 0 : incrementButtonProps["aria-label"]) ?? "Increase",
|
|
821
|
+
"aria-controls": valueElementId,
|
|
775
822
|
"aria-disabled": incrementDisabled,
|
|
776
823
|
disabled: incrementDisabled,
|
|
777
824
|
className: (0, import_utils5.cx)(
|