@bubo-squared/ui-framework 0.1.97 → 0.1.99
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/dist/index.cjs +115 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -14
- package/dist/index.d.ts +13 -14
- package/dist/index.js +115 -71
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2349,10 +2349,16 @@ SearchInput.displayName = "SearchInput";
|
|
|
2349
2349
|
var React29 = __toESM(require("react"), 1);
|
|
2350
2350
|
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2351
2351
|
var wrapperBase2 = "flex flex-col gap-2 items-start";
|
|
2352
|
+
var isRangeProps = (props) => {
|
|
2353
|
+
return Array.isArray(props.value) || Array.isArray(props.defaultValue);
|
|
2354
|
+
};
|
|
2355
|
+
var toArray = (value) => {
|
|
2356
|
+
if (value === void 0) return void 0;
|
|
2357
|
+
return Array.isArray(value) ? value : [value];
|
|
2358
|
+
};
|
|
2352
2359
|
var Slider = (props) => {
|
|
2353
2360
|
const {
|
|
2354
2361
|
display = "flat",
|
|
2355
|
-
type = "single",
|
|
2356
2362
|
tooltipPlacement = "top",
|
|
2357
2363
|
tooltipFormatter,
|
|
2358
2364
|
showPercentage = true,
|
|
@@ -2362,11 +2368,11 @@ var Slider = (props) => {
|
|
|
2362
2368
|
disabled = false,
|
|
2363
2369
|
value,
|
|
2364
2370
|
defaultValue,
|
|
2365
|
-
onValueChange,
|
|
2366
2371
|
className
|
|
2367
2372
|
} = props;
|
|
2373
|
+
const isRange = isRangeProps(props);
|
|
2368
2374
|
const isControlled = value !== void 0;
|
|
2369
|
-
const expectedLength =
|
|
2375
|
+
const expectedLength = isRange ? 2 : 1;
|
|
2370
2376
|
const normalizeArray = React29.useCallback(
|
|
2371
2377
|
(arr, fallback) => {
|
|
2372
2378
|
if (!arr || arr.length === 0) return fallback;
|
|
@@ -2380,22 +2386,25 @@ var Slider = (props) => {
|
|
|
2380
2386
|
[expectedLength, max]
|
|
2381
2387
|
);
|
|
2382
2388
|
const defaultInternal = React29.useMemo(() => {
|
|
2383
|
-
|
|
2384
|
-
if (
|
|
2389
|
+
const defaultValueArray = toArray(defaultValue);
|
|
2390
|
+
if (defaultValueArray) return normalizeArray(defaultValueArray, []);
|
|
2391
|
+
if (isRange) return [min, Math.min(min + (max - min) / 4, max)];
|
|
2385
2392
|
return [min + (max - min) / 3];
|
|
2386
|
-
}, [defaultValue, min, max,
|
|
2393
|
+
}, [defaultValue, min, max, isRange, normalizeArray]);
|
|
2387
2394
|
const [internalValue, setInternalValue] = React29.useState(
|
|
2388
|
-
() => normalizeArray(isControlled ? value : defaultInternal, defaultInternal)
|
|
2395
|
+
() => normalizeArray(isControlled ? toArray(value) : defaultInternal, defaultInternal)
|
|
2389
2396
|
);
|
|
2390
2397
|
React29.useEffect(() => {
|
|
2391
2398
|
if (isControlled) {
|
|
2392
2399
|
setInternalValue(
|
|
2393
|
-
(current2) => normalizeArray(value, current2.length ? current2 : defaultInternal)
|
|
2400
|
+
(current2) => normalizeArray(toArray(value), current2.length ? current2 : defaultInternal)
|
|
2394
2401
|
);
|
|
2395
2402
|
}
|
|
2396
2403
|
}, [isControlled, value, normalizeArray, defaultInternal]);
|
|
2397
2404
|
const current = internalValue;
|
|
2398
2405
|
const trackRef = React29.useRef(null);
|
|
2406
|
+
const [draggingThumbIndex, setDraggingThumbIndex] = React29.useState(null);
|
|
2407
|
+
const [hoveredThumbIndex, setHoveredThumbIndex] = React29.useState(null);
|
|
2399
2408
|
const clamp = (val) => {
|
|
2400
2409
|
if (val < min) return min;
|
|
2401
2410
|
if (val > max) return max;
|
|
@@ -2405,13 +2414,13 @@ var Slider = (props) => {
|
|
|
2405
2414
|
if (!isControlled) {
|
|
2406
2415
|
setInternalValue((prev) => {
|
|
2407
2416
|
const clamped = prev.map((v) => clamp(v));
|
|
2408
|
-
if (
|
|
2417
|
+
if (isRange && clamped.length === 2 && step > 0) {
|
|
2409
2418
|
return enforceMinGap(clamped, prev);
|
|
2410
2419
|
}
|
|
2411
2420
|
return clamped;
|
|
2412
2421
|
});
|
|
2413
2422
|
}
|
|
2414
|
-
}, [isControlled, min, max]);
|
|
2423
|
+
}, [isControlled, min, max, isRange]);
|
|
2415
2424
|
const snap = (val) => {
|
|
2416
2425
|
const range = max - min;
|
|
2417
2426
|
if (range <= 0 || step <= 0) return clamp(val);
|
|
@@ -2419,7 +2428,7 @@ var Slider = (props) => {
|
|
|
2419
2428
|
return clamp(min + stepsFromMin * step);
|
|
2420
2429
|
};
|
|
2421
2430
|
const enforceMinGap = (next, prev) => {
|
|
2422
|
-
if (
|
|
2431
|
+
if (!isRange || next.length !== 2 || step <= 0) return next;
|
|
2423
2432
|
let [low, high] = next;
|
|
2424
2433
|
const [prevLow, prevHigh] = prev.length === 2 ? prev : next;
|
|
2425
2434
|
if (low > high) {
|
|
@@ -2444,13 +2453,17 @@ var Slider = (props) => {
|
|
|
2444
2453
|
};
|
|
2445
2454
|
const updateValue = (next) => {
|
|
2446
2455
|
let normalized = normalizeArray(next, current);
|
|
2447
|
-
if (
|
|
2456
|
+
if (isRange && normalized.length === 2) {
|
|
2448
2457
|
normalized = enforceMinGap(normalized, current);
|
|
2449
2458
|
}
|
|
2450
2459
|
if (!isControlled) {
|
|
2451
2460
|
setInternalValue(normalized);
|
|
2452
2461
|
}
|
|
2453
|
-
|
|
2462
|
+
if (isRangeProps(props)) {
|
|
2463
|
+
props.onValueChange?.([normalized[0] ?? min, normalized[1] ?? max]);
|
|
2464
|
+
} else {
|
|
2465
|
+
props.onValueChange?.(normalized[0] ?? min);
|
|
2466
|
+
}
|
|
2454
2467
|
};
|
|
2455
2468
|
const getSnappedValueFromClientX = (clientX, track) => {
|
|
2456
2469
|
const rect = track.getBoundingClientRect();
|
|
@@ -2463,10 +2476,11 @@ var Slider = (props) => {
|
|
|
2463
2476
|
if (disabled) return;
|
|
2464
2477
|
const track = trackRef.current;
|
|
2465
2478
|
if (!track) return;
|
|
2479
|
+
setDraggingThumbIndex(thumbIndex);
|
|
2466
2480
|
const handlePointerMove = (event) => {
|
|
2467
2481
|
if (disabled) return;
|
|
2468
2482
|
const snapped = getSnappedValueFromClientX(event.clientX, track);
|
|
2469
|
-
if (
|
|
2483
|
+
if (isRange && current.length === 2) {
|
|
2470
2484
|
const [a, b] = current;
|
|
2471
2485
|
if (thumbIndex === 0) {
|
|
2472
2486
|
updateValue([snapped, b]);
|
|
@@ -2480,9 +2494,11 @@ var Slider = (props) => {
|
|
|
2480
2494
|
const handlePointerUp = () => {
|
|
2481
2495
|
window.removeEventListener("pointermove", handlePointerMove);
|
|
2482
2496
|
window.removeEventListener("pointerup", handlePointerUp);
|
|
2497
|
+
window.removeEventListener("pointercancel", handlePointerUp);
|
|
2498
|
+
setDraggingThumbIndex(null);
|
|
2483
2499
|
};
|
|
2484
2500
|
const initialSnapped = getSnappedValueFromClientX(clientX, track);
|
|
2485
|
-
if (
|
|
2501
|
+
if (isRange && current.length === 2) {
|
|
2486
2502
|
const [a, b] = current;
|
|
2487
2503
|
if (thumbIndex === 0) {
|
|
2488
2504
|
updateValue([initialSnapped, b]);
|
|
@@ -2494,6 +2510,7 @@ var Slider = (props) => {
|
|
|
2494
2510
|
}
|
|
2495
2511
|
window.addEventListener("pointermove", handlePointerMove);
|
|
2496
2512
|
window.addEventListener("pointerup", handlePointerUp);
|
|
2513
|
+
window.addEventListener("pointercancel", handlePointerUp);
|
|
2497
2514
|
};
|
|
2498
2515
|
const handleTrackPointerDown = (event) => {
|
|
2499
2516
|
if (disabled) return;
|
|
@@ -2502,7 +2519,7 @@ var Slider = (props) => {
|
|
|
2502
2519
|
if (!track) return;
|
|
2503
2520
|
const snapped = getSnappedValueFromClientX(event.clientX, track);
|
|
2504
2521
|
let thumbIndex = 0;
|
|
2505
|
-
if (
|
|
2522
|
+
if (isRange && current.length === 2) {
|
|
2506
2523
|
const [a, b] = current;
|
|
2507
2524
|
const distToA = Math.abs(snapped - a);
|
|
2508
2525
|
const distToB = Math.abs(snapped - b);
|
|
@@ -2540,7 +2557,7 @@ var Slider = (props) => {
|
|
|
2540
2557
|
event.preventDefault();
|
|
2541
2558
|
}
|
|
2542
2559
|
};
|
|
2543
|
-
const [primary, secondary] =
|
|
2560
|
+
const [primary, secondary] = isRange && current.length === 2 ? [current[0], current[1]] : [current[0], void 0];
|
|
2544
2561
|
const valueToPercent = (val) => {
|
|
2545
2562
|
if (val === void 0) return 0;
|
|
2546
2563
|
if (max === min) return 0;
|
|
@@ -2573,7 +2590,7 @@ var Slider = (props) => {
|
|
|
2573
2590
|
return formatNumber(value2);
|
|
2574
2591
|
};
|
|
2575
2592
|
const formatNumericLabel = () => {
|
|
2576
|
-
if (
|
|
2593
|
+
if (isRange && secondary !== void 0) {
|
|
2577
2594
|
if (!tooltipFormatter && showPercentage && display === "numeric") {
|
|
2578
2595
|
const first = formatNumber(valueToPercent(primary));
|
|
2579
2596
|
const second = formatNumber(valueToPercent(secondary));
|
|
@@ -2586,10 +2603,14 @@ var Slider = (props) => {
|
|
|
2586
2603
|
const trackHeight = 32;
|
|
2587
2604
|
const thumbWidth = 18;
|
|
2588
2605
|
const thumbRadius = thumbWidth / 2;
|
|
2589
|
-
const renderTooltipBubble = (key, percent, labelText) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2606
|
+
const renderTooltipBubble = (key, percent, labelText, isVisible) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2590
2607
|
"div",
|
|
2591
2608
|
{
|
|
2592
|
-
className:
|
|
2609
|
+
className: cn(
|
|
2610
|
+
"absolute -translate-x-1/2 flex flex-col items-center",
|
|
2611
|
+
"transition-[opacity,transform] duration-150",
|
|
2612
|
+
isVisible ? "opacity-100 scale-100 pointer-events-auto" : "opacity-0 scale-95 pointer-events-none"
|
|
2613
|
+
),
|
|
2593
2614
|
style: {
|
|
2594
2615
|
left: `${percent}%`,
|
|
2595
2616
|
bottom: isTooltipAbove ? "100%" : void 0,
|
|
@@ -2600,17 +2621,14 @@ var Slider = (props) => {
|
|
|
2600
2621
|
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
2601
2622
|
"div",
|
|
2602
2623
|
{
|
|
2603
|
-
className: cn(
|
|
2604
|
-
"relative rounded-4 shadow-card-md px-(--space-8) py-(--space-4)",
|
|
2605
|
-
disabled ? "bg-(--background-primary-disabled)" : "bg-(--background-neutral)"
|
|
2606
|
-
),
|
|
2624
|
+
className: cn("relative rounded-4 shadow-card-md px-(--space-8) py-(--space-4) bg-(--background-tooltip)"),
|
|
2607
2625
|
children: [
|
|
2608
2626
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2609
2627
|
"p",
|
|
2610
2628
|
{
|
|
2611
2629
|
className: cn(
|
|
2612
2630
|
"paragraph-s",
|
|
2613
|
-
disabled ? "text-
|
|
2631
|
+
disabled ? "text-secondary" : "text-primary"
|
|
2614
2632
|
),
|
|
2615
2633
|
children: labelText
|
|
2616
2634
|
}
|
|
@@ -2619,8 +2637,7 @@ var Slider = (props) => {
|
|
|
2619
2637
|
"div",
|
|
2620
2638
|
{
|
|
2621
2639
|
className: cn(
|
|
2622
|
-
"absolute left-1/2 -translate-x-1/2 w-2 h-2 rotate-45",
|
|
2623
|
-
disabled ? "bg-(--background-primary-disabled)" : "bg-(--background-neutral)",
|
|
2640
|
+
"absolute left-1/2 -translate-x-1/2 w-2 h-2 rotate-45 bg-(--background-tooltip)",
|
|
2624
2641
|
isTooltipAbove ? "-bottom-1" : "-top-1"
|
|
2625
2642
|
)
|
|
2626
2643
|
}
|
|
@@ -2633,6 +2650,7 @@ var Slider = (props) => {
|
|
|
2633
2650
|
);
|
|
2634
2651
|
const renderHandle = (index, percent, ariaValueText) => {
|
|
2635
2652
|
const val = index === 0 ? primary : secondary;
|
|
2653
|
+
const isDragging = draggingThumbIndex === index;
|
|
2636
2654
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2637
2655
|
"button",
|
|
2638
2656
|
{
|
|
@@ -2646,12 +2664,21 @@ var Slider = (props) => {
|
|
|
2646
2664
|
tabIndex: disabled ? -1 : 0,
|
|
2647
2665
|
className: cn(
|
|
2648
2666
|
"absolute -translate-x-1/2 flex items-center justify-center",
|
|
2649
|
-
"h-8 w-
|
|
2667
|
+
"h-8 w-4.5 rounded-4",
|
|
2668
|
+
"transition-shadow duration-150",
|
|
2669
|
+
!disabled && (isDragging ? "shadow-[0_0_0_12px_var(--slider-halo-color)]" : "hover:shadow-[0_0_0_8px_var(--slider-halo-color)]"),
|
|
2650
2670
|
disabled ? "bg-(--icon-primary-disabled) cursor-default" : "bg-(--icon-primary-hover) outline-none focus-visible:shadow-[0_0_0_var(--focus-ring-spread)_var(--focus-primary)] cursor-pointer"
|
|
2651
2671
|
),
|
|
2652
2672
|
style: {
|
|
2653
2673
|
left: `${percent}%`,
|
|
2654
|
-
top: `calc(50% - ${trackHeight / 2}px)
|
|
2674
|
+
top: `calc(50% - ${trackHeight / 2}px)`,
|
|
2675
|
+
["--slider-halo-color"]: "color-mix(in srgb, var(--color-brand) 10%, transparent)"
|
|
2676
|
+
},
|
|
2677
|
+
onPointerEnter: () => {
|
|
2678
|
+
setHoveredThumbIndex(index);
|
|
2679
|
+
},
|
|
2680
|
+
onPointerLeave: () => {
|
|
2681
|
+
setHoveredThumbIndex((prev) => prev === index ? null : prev);
|
|
2655
2682
|
},
|
|
2656
2683
|
onPointerDown: (event) => {
|
|
2657
2684
|
if (disabled) return;
|
|
@@ -2664,51 +2691,68 @@ var Slider = (props) => {
|
|
|
2664
2691
|
index
|
|
2665
2692
|
);
|
|
2666
2693
|
};
|
|
2667
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
{
|
|
2674
|
-
|
|
2675
|
-
"
|
|
2676
|
-
|
|
2694
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2695
|
+
"div",
|
|
2696
|
+
{
|
|
2697
|
+
className: wrapperBase2,
|
|
2698
|
+
style: { marginInline: `${thumbRadius}px` },
|
|
2699
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: cn("w-full flex flex-col gap-1", className), children: [
|
|
2700
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "relative w-full", children: [
|
|
2701
|
+
showTooltip && primary !== void 0 && renderTooltipBubble(
|
|
2702
|
+
"primary",
|
|
2703
|
+
primaryPercent,
|
|
2704
|
+
formatDisplayValue(primary),
|
|
2705
|
+
hoveredThumbIndex === 0 || draggingThumbIndex === 0
|
|
2677
2706
|
),
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2707
|
+
showTooltip && isRange && secondary !== void 0 && renderTooltipBubble(
|
|
2708
|
+
"secondary",
|
|
2709
|
+
secondaryPercent,
|
|
2710
|
+
formatDisplayValue(secondary),
|
|
2711
|
+
hoveredThumbIndex === 1 || draggingThumbIndex === 1
|
|
2712
|
+
),
|
|
2713
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(
|
|
2714
|
+
"div",
|
|
2715
|
+
{
|
|
2716
|
+
className: cn(
|
|
2717
|
+
"relative w-full flex items-center rounded-4",
|
|
2718
|
+
disabled ? "bg-(--background-primary-disabled) cursor-default" : "bg-(--background-secondary) cursor-pointer"
|
|
2719
|
+
),
|
|
2720
|
+
style: { height: `${trackHeight}px` },
|
|
2721
|
+
ref: trackRef,
|
|
2722
|
+
onPointerDown: handleTrackPointerDown,
|
|
2723
|
+
children: [
|
|
2724
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2725
|
+
"div",
|
|
2726
|
+
{
|
|
2727
|
+
className: cn(
|
|
2728
|
+
"absolute h-full rounded-4",
|
|
2729
|
+
disabled ? "bg-(--background-primary-disabled)" : "bg-(--background-secondary)"
|
|
2730
|
+
),
|
|
2731
|
+
style: {
|
|
2732
|
+
width: `calc(100% + ${thumbWidth}px)`,
|
|
2733
|
+
left: `-${thumbRadius}px`
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2688
2736
|
),
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2737
|
+
renderHandle(0, primaryPercent, formatDisplayValue(primary)),
|
|
2738
|
+
isRange && secondary !== void 0 && renderHandle(1, secondaryPercent, formatDisplayValue(secondary))
|
|
2739
|
+
]
|
|
2740
|
+
}
|
|
2741
|
+
)
|
|
2742
|
+
] }),
|
|
2743
|
+
showNumeric && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2744
|
+
"p",
|
|
2745
|
+
{
|
|
2746
|
+
className: cn(
|
|
2747
|
+
"paragraph-s text-primary",
|
|
2748
|
+
disabled && "text-primary-disabled"
|
|
2694
2749
|
),
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
showNumeric && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
2702
|
-
"p",
|
|
2703
|
-
{
|
|
2704
|
-
className: cn(
|
|
2705
|
-
"paragraph-s text-primary",
|
|
2706
|
-
disabled && "text-primary-disabled"
|
|
2707
|
-
),
|
|
2708
|
-
children: formatNumericLabel()
|
|
2709
|
-
}
|
|
2710
|
-
)
|
|
2711
|
-
] }) });
|
|
2750
|
+
children: formatNumericLabel()
|
|
2751
|
+
}
|
|
2752
|
+
)
|
|
2753
|
+
] })
|
|
2754
|
+
}
|
|
2755
|
+
);
|
|
2712
2756
|
};
|
|
2713
2757
|
Slider.displayName = "Slider";
|
|
2714
2758
|
|