@fangxinyan/lumina 0.4.0 → 0.5.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/dist/{Slider-X4PVA65R.css → Slider-3JKA5EW6.css} +44 -25
- package/dist/Slider.cjs +2 -2
- package/dist/Slider.d.cts +8 -5
- package/dist/Slider.d.ts +8 -5
- package/dist/Slider.js +1 -1
- package/dist/chunk-2TZ2R7L2.js +235 -0
- package/dist/chunk-2TZ2R7L2.js.map +1 -0
- package/dist/chunk-N6ZLZUBF.cjs +257 -0
- package/dist/chunk-N6ZLZUBF.cjs.map +1 -0
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/styles.css +38 -25
- package/docs/llms/form.md +26 -0
- package/docs/llms/slider.md +13 -2
- package/docs/llms.md +3 -3
- package/package.json +1 -1
- package/dist/chunk-B5JH7NRZ.cjs +0 -133
- package/dist/chunk-B5JH7NRZ.cjs.map +0 -1
- package/dist/chunk-QJGKI2BD.js +0 -111
- package/dist/chunk-QJGKI2BD.js.map +0 -1
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
/* ============ Slider ============ */
|
|
2
2
|
.slider {
|
|
3
3
|
position: relative;
|
|
4
|
-
height: 36px;
|
|
5
4
|
width: 100%;
|
|
6
5
|
display: flex;
|
|
7
6
|
align-items: center;
|
|
7
|
+
gap: 10px;
|
|
8
8
|
cursor: pointer;
|
|
9
|
+
min-height: 36px;
|
|
9
10
|
}
|
|
10
11
|
.slider.has-marks { padding-bottom: 26px; }
|
|
11
12
|
.slider.disabled { opacity: 0.5; cursor: not-allowed; }
|
|
13
|
+
|
|
14
|
+
/* Rail: positioning context for track + thumbs + marks */
|
|
15
|
+
.slider-rail {
|
|
16
|
+
position: relative;
|
|
17
|
+
flex: 1 1 0%;
|
|
18
|
+
height: 36px;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
.slider-track {
|
|
13
24
|
position: relative;
|
|
14
25
|
width: 100%;
|
|
@@ -16,8 +27,10 @@
|
|
|
16
27
|
border-radius: 999px;
|
|
17
28
|
background: var(--bg);
|
|
18
29
|
box-shadow: var(--neu-in-sm);
|
|
19
|
-
|
|
30
|
+
touch-action: none;
|
|
31
|
+
z-index: 1;
|
|
20
32
|
}
|
|
33
|
+
|
|
21
34
|
.slider-fill {
|
|
22
35
|
position: absolute;
|
|
23
36
|
top: 0; bottom: 0;
|
|
@@ -25,7 +38,9 @@
|
|
|
25
38
|
box-shadow: 0 0 12px var(--accent-glow);
|
|
26
39
|
border-radius: 999px;
|
|
27
40
|
transition: left var(--dur-fast) var(--ease), right var(--dur-fast) var(--ease);
|
|
41
|
+
pointer-events: none;
|
|
28
42
|
}
|
|
43
|
+
|
|
29
44
|
.slider-thumb {
|
|
30
45
|
position: absolute;
|
|
31
46
|
top: 50%;
|
|
@@ -36,43 +51,45 @@
|
|
|
36
51
|
transform: translate(-50%, -50%);
|
|
37
52
|
transition: all var(--dur-fast) var(--ease);
|
|
38
53
|
display: grid; place-items: center;
|
|
39
|
-
|
|
54
|
+
z-index: 3;
|
|
55
|
+
outline: none;
|
|
56
|
+
touch-action: none;
|
|
40
57
|
}
|
|
41
|
-
.slider.has-marks .slider-thumb { top: calc(50% - 13px); }
|
|
42
|
-
.slider.has-marks .slider-track { margin-top: -26px; }
|
|
43
58
|
.slider-thumb::after {
|
|
44
59
|
content: "";
|
|
45
60
|
width: 6px; height: 6px;
|
|
46
61
|
border-radius: 999px;
|
|
47
|
-
background: var(--accent);
|
|
62
|
+
background: var(--slider-thumb-color, var(--accent));
|
|
63
|
+
}
|
|
64
|
+
.slider-thumb:focus-visible {
|
|
65
|
+
box-shadow: var(--neu-out-sm), 0 0 0 3px var(--accent-glow);
|
|
48
66
|
}
|
|
49
67
|
.slider:hover .slider-thumb { transform: translate(-50%, -50%) scale(1.08); }
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
pointer-events: auto;
|
|
68
|
+
|
|
69
|
+
.slider-value {
|
|
70
|
+
font-family: var(--font-mono);
|
|
71
|
+
font-size: 12px;
|
|
72
|
+
color: var(--accent-ink);
|
|
73
|
+
flex-shrink: 0;
|
|
74
|
+
white-space: nowrap;
|
|
58
75
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.slider
|
|
62
|
-
.slider.has-marks input[type="range"] { height: calc(100% - 26px); }
|
|
63
|
-
.slider-value { font-family: var(--font-mono); font-size: 12px; color: var(--accent-ink); margin-left: 10px; }
|
|
76
|
+
|
|
77
|
+
/* Tone variants */
|
|
78
|
+
.slider.success .slider-thumb { --slider-thumb-color: var(--success); }
|
|
64
79
|
.slider.success .slider-fill { background: linear-gradient(90deg, color-mix(in oklch, var(--success) 70%, white), var(--success)); box-shadow: 0 0 10px color-mix(in oklch, var(--success) 35%, transparent); }
|
|
65
|
-
.slider.success .slider-thumb
|
|
80
|
+
.slider.success .slider-thumb:focus-visible { box-shadow: var(--neu-out-sm), 0 0 0 3px color-mix(in oklch, var(--success) 35%, transparent); }
|
|
81
|
+
.slider.warning .slider-thumb { --slider-thumb-color: var(--warning); }
|
|
66
82
|
.slider.warning .slider-fill { background: linear-gradient(90deg, color-mix(in oklch, var(--warning) 70%, white), var(--warning)); box-shadow: 0 0 10px color-mix(in oklch, var(--warning) 35%, transparent); }
|
|
67
|
-
.slider.warning .slider-thumb
|
|
83
|
+
.slider.warning .slider-thumb:focus-visible { box-shadow: var(--neu-out-sm), 0 0 0 3px color-mix(in oklch, var(--warning) 35%, transparent); }
|
|
84
|
+
.slider.danger .slider-thumb { --slider-thumb-color: var(--danger); }
|
|
68
85
|
.slider.danger .slider-fill { background: linear-gradient(90deg, color-mix(in oklch, var(--danger) 70%, white), var(--danger)); box-shadow: 0 0 10px color-mix(in oklch, var(--danger) 35%, transparent); }
|
|
69
|
-
.slider.danger .slider-thumb
|
|
86
|
+
.slider.danger .slider-thumb:focus-visible { box-shadow: var(--neu-out-sm), 0 0 0 3px color-mix(in oklch, var(--danger) 35%, transparent); }
|
|
70
87
|
|
|
71
88
|
/* Marks */
|
|
72
89
|
.slider-marks {
|
|
73
90
|
position: absolute;
|
|
74
91
|
left: 0; right: 0;
|
|
75
|
-
bottom:
|
|
92
|
+
bottom: -26px;
|
|
76
93
|
height: 22px;
|
|
77
94
|
pointer-events: none;
|
|
78
95
|
}
|
|
@@ -94,8 +111,10 @@
|
|
|
94
111
|
border-radius: 999px;
|
|
95
112
|
background: var(--bg);
|
|
96
113
|
box-shadow: var(--neu-in-sm);
|
|
97
|
-
|
|
98
|
-
|
|
114
|
+
position: absolute;
|
|
115
|
+
top: -12px;
|
|
116
|
+
left: 50%;
|
|
117
|
+
transform: translateX(-50%);
|
|
99
118
|
z-index: 1;
|
|
100
119
|
}
|
|
101
120
|
.slider-mark.active .slider-mark-dot { background: var(--accent); box-shadow: 0 0 6px var(--accent-glow); }
|
package/dist/Slider.cjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkN6ZLZUBF_cjs = require('./chunk-N6ZLZUBF.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Object.defineProperty(exports, "Slider", {
|
|
8
8
|
enumerable: true,
|
|
9
|
-
get: function () { return
|
|
9
|
+
get: function () { return chunkN6ZLZUBF_cjs.Slider; }
|
|
10
10
|
});
|
|
11
11
|
//# sourceMappingURL=Slider.cjs.map
|
|
12
12
|
//# sourceMappingURL=Slider.cjs.map
|
package/dist/Slider.d.cts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
type SliderSingleValue = number;
|
|
4
3
|
type SliderRangeValue = [number, number];
|
|
5
|
-
type SliderValue =
|
|
4
|
+
type SliderValue = number | SliderRangeValue;
|
|
6
5
|
interface SliderBaseProps {
|
|
7
6
|
min?: number;
|
|
8
7
|
max?: number;
|
|
@@ -10,6 +9,8 @@ interface SliderBaseProps {
|
|
|
10
9
|
disabled?: boolean;
|
|
11
10
|
showValue?: boolean;
|
|
12
11
|
tone?: "accent" | "success" | "warning" | "danger";
|
|
12
|
+
/** Custom gradient colors mapped from min→max. Overrides `tone` for fill & thumb. */
|
|
13
|
+
colors?: string[];
|
|
13
14
|
/** Tick marks with labels. Clicking a mark snaps to it. */
|
|
14
15
|
marks?: Record<number, React.ReactNode>;
|
|
15
16
|
className?: string;
|
|
@@ -27,7 +28,9 @@ interface SliderRangeProps extends SliderBaseProps {
|
|
|
27
28
|
onChange?: (value: SliderRangeValue) => void;
|
|
28
29
|
}
|
|
29
30
|
type SliderProps = SliderSingleProps | SliderRangeProps;
|
|
30
|
-
/** `Slider` — neumorphic range input with grooved track.
|
|
31
|
-
|
|
31
|
+
/** `Slider` — neumorphic range input with grooved track.
|
|
32
|
+
* @example <Slider defaultValue={40} showValue />
|
|
33
|
+
*/
|
|
34
|
+
declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLDivElement>>;
|
|
32
35
|
|
|
33
|
-
export { Slider, type SliderProps, type SliderRangeProps, type SliderRangeValue, type SliderSingleProps, type
|
|
36
|
+
export { Slider, type SliderProps, type SliderRangeProps, type SliderRangeValue, type SliderSingleProps, type SliderValue };
|
package/dist/Slider.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
type SliderSingleValue = number;
|
|
4
3
|
type SliderRangeValue = [number, number];
|
|
5
|
-
type SliderValue =
|
|
4
|
+
type SliderValue = number | SliderRangeValue;
|
|
6
5
|
interface SliderBaseProps {
|
|
7
6
|
min?: number;
|
|
8
7
|
max?: number;
|
|
@@ -10,6 +9,8 @@ interface SliderBaseProps {
|
|
|
10
9
|
disabled?: boolean;
|
|
11
10
|
showValue?: boolean;
|
|
12
11
|
tone?: "accent" | "success" | "warning" | "danger";
|
|
12
|
+
/** Custom gradient colors mapped from min→max. Overrides `tone` for fill & thumb. */
|
|
13
|
+
colors?: string[];
|
|
13
14
|
/** Tick marks with labels. Clicking a mark snaps to it. */
|
|
14
15
|
marks?: Record<number, React.ReactNode>;
|
|
15
16
|
className?: string;
|
|
@@ -27,7 +28,9 @@ interface SliderRangeProps extends SliderBaseProps {
|
|
|
27
28
|
onChange?: (value: SliderRangeValue) => void;
|
|
28
29
|
}
|
|
29
30
|
type SliderProps = SliderSingleProps | SliderRangeProps;
|
|
30
|
-
/** `Slider` — neumorphic range input with grooved track.
|
|
31
|
-
|
|
31
|
+
/** `Slider` — neumorphic range input with grooved track.
|
|
32
|
+
* @example <Slider defaultValue={40} showValue />
|
|
33
|
+
*/
|
|
34
|
+
declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLDivElement>>;
|
|
32
35
|
|
|
33
|
-
export { Slider, type SliderProps, type SliderRangeProps, type SliderRangeValue, type SliderSingleProps, type
|
|
36
|
+
export { Slider, type SliderProps, type SliderRangeProps, type SliderRangeValue, type SliderSingleProps, type SliderValue };
|
package/dist/Slider.js
CHANGED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import './tokens-BIIUTPKN.css';
|
|
2
|
+
import './shared-NJHRNLRH.css';
|
|
3
|
+
import './Slider-3JKA5EW6.css';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
// src/components/Slider/Slider.tsx
|
|
8
|
+
function clamp(v, lo, hi) {
|
|
9
|
+
return Math.max(lo, Math.min(hi, v));
|
|
10
|
+
}
|
|
11
|
+
function snap(raw, step, min) {
|
|
12
|
+
return Math.round((raw - min) / step) * step + min;
|
|
13
|
+
}
|
|
14
|
+
function lerpColor(colors, t) {
|
|
15
|
+
const pos = Math.max(0, Math.min(1, t)) * (colors.length - 1);
|
|
16
|
+
const i = Math.min(Math.floor(pos), colors.length - 2);
|
|
17
|
+
const frac = pos - i;
|
|
18
|
+
if (frac === 0) return colors[i];
|
|
19
|
+
return `color-mix(in oklch, ${colors[i + 1]} ${Math.round(frac * 100)}%, ${colors[i]})`;
|
|
20
|
+
}
|
|
21
|
+
var Slider = React.forwardRef(
|
|
22
|
+
(props, ref) => {
|
|
23
|
+
const {
|
|
24
|
+
min = 0,
|
|
25
|
+
max = 100,
|
|
26
|
+
step = 1,
|
|
27
|
+
disabled,
|
|
28
|
+
showValue,
|
|
29
|
+
tone = "accent",
|
|
30
|
+
colors,
|
|
31
|
+
marks,
|
|
32
|
+
className = ""
|
|
33
|
+
} = props;
|
|
34
|
+
const range = props.range === true;
|
|
35
|
+
const controlled = props.value;
|
|
36
|
+
const defaultVal = props.defaultValue;
|
|
37
|
+
const onChange = props.onChange;
|
|
38
|
+
const initRef = React.useRef(
|
|
39
|
+
defaultVal !== void 0 ? Array.isArray(defaultVal) ? [...defaultVal] : [defaultVal] : range ? [min, max] : [min]
|
|
40
|
+
);
|
|
41
|
+
const [inner, setInner] = React.useState(initRef.current);
|
|
42
|
+
const isControlled = controlled !== void 0;
|
|
43
|
+
const vals = isControlled ? Array.isArray(controlled) ? controlled : [controlled] : inner;
|
|
44
|
+
const valsRef = React.useRef(vals);
|
|
45
|
+
valsRef.current = vals;
|
|
46
|
+
const trackRef = React.useRef(null);
|
|
47
|
+
const thumbEls = React.useRef([]);
|
|
48
|
+
const dragging = React.useRef(null);
|
|
49
|
+
const pct = (n) => (n - min) / (max - min) * 100;
|
|
50
|
+
const commit = React.useCallback(
|
|
51
|
+
(next) => {
|
|
52
|
+
if (!isControlled) setInner(next);
|
|
53
|
+
if (range) {
|
|
54
|
+
onChange?.([next[0], next[1]]);
|
|
55
|
+
} else {
|
|
56
|
+
onChange?.(next[0]);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
[isControlled, range, onChange]
|
|
60
|
+
);
|
|
61
|
+
const setAt = React.useCallback(
|
|
62
|
+
(index, raw) => {
|
|
63
|
+
const snapped = snap(clamp(raw, min, max), step, min);
|
|
64
|
+
const clamped = clamp(snapped, min, max);
|
|
65
|
+
const out = [...valsRef.current];
|
|
66
|
+
out[index] = clamped;
|
|
67
|
+
if (range && out.length === 2 && out[0] > out[1]) out.sort((a, b) => a - b);
|
|
68
|
+
commit(out);
|
|
69
|
+
},
|
|
70
|
+
[min, max, step, range, commit]
|
|
71
|
+
);
|
|
72
|
+
const valFromX = React.useCallback(
|
|
73
|
+
(clientX) => {
|
|
74
|
+
const rect = trackRef.current?.getBoundingClientRect();
|
|
75
|
+
if (!rect) return min;
|
|
76
|
+
const ratio = clamp((clientX - rect.left) / rect.width, 0, 1);
|
|
77
|
+
return min + ratio * (max - min);
|
|
78
|
+
},
|
|
79
|
+
[min, max]
|
|
80
|
+
);
|
|
81
|
+
const closerIndex = React.useCallback(
|
|
82
|
+
(target) => {
|
|
83
|
+
const v = valsRef.current;
|
|
84
|
+
if (!range || v.length < 2) return 0;
|
|
85
|
+
const d0 = Math.abs(v[0] - target);
|
|
86
|
+
const d1 = Math.abs(v[1] - target);
|
|
87
|
+
if (d0 === d1) return target < v[0] ? 0 : 1;
|
|
88
|
+
return d0 < d1 ? 0 : 1;
|
|
89
|
+
},
|
|
90
|
+
[range]
|
|
91
|
+
);
|
|
92
|
+
const onPointerDown = React.useCallback(
|
|
93
|
+
(e) => {
|
|
94
|
+
if (disabled) return;
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
const val = valFromX(e.clientX);
|
|
97
|
+
const idx = closerIndex(val);
|
|
98
|
+
dragging.current = idx;
|
|
99
|
+
setAt(idx, val);
|
|
100
|
+
trackRef.current?.setPointerCapture(e.pointerId);
|
|
101
|
+
thumbEls.current[idx]?.focus();
|
|
102
|
+
},
|
|
103
|
+
[disabled, valFromX, closerIndex, setAt]
|
|
104
|
+
);
|
|
105
|
+
const onPointerMove = React.useCallback(
|
|
106
|
+
(e) => {
|
|
107
|
+
if (dragging.current === null) return;
|
|
108
|
+
setAt(dragging.current, valFromX(e.clientX));
|
|
109
|
+
},
|
|
110
|
+
[valFromX, setAt]
|
|
111
|
+
);
|
|
112
|
+
const onPointerUp = React.useCallback(() => {
|
|
113
|
+
dragging.current = null;
|
|
114
|
+
}, []);
|
|
115
|
+
const handleKey = React.useCallback(
|
|
116
|
+
(index, e) => {
|
|
117
|
+
if (disabled) return;
|
|
118
|
+
let delta = 0;
|
|
119
|
+
if (e.key === "ArrowRight" || e.key === "ArrowUp") delta = step;
|
|
120
|
+
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") delta = -step;
|
|
121
|
+
else if (e.key === "Home") {
|
|
122
|
+
setAt(index, min);
|
|
123
|
+
return;
|
|
124
|
+
} else if (e.key === "End") {
|
|
125
|
+
setAt(index, max);
|
|
126
|
+
return;
|
|
127
|
+
} else return;
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
setAt(index, valsRef.current[index] + delta);
|
|
130
|
+
},
|
|
131
|
+
[disabled, step, min, max, setAt]
|
|
132
|
+
);
|
|
133
|
+
const handleMarkClick = React.useCallback(
|
|
134
|
+
(mark) => {
|
|
135
|
+
if (disabled) return;
|
|
136
|
+
setAt(closerIndex(mark), mark);
|
|
137
|
+
},
|
|
138
|
+
[disabled, closerIndex, setAt]
|
|
139
|
+
);
|
|
140
|
+
const fillLeft = range ? pct(Math.min(vals[0], vals[1])) : 0;
|
|
141
|
+
const fillRight = range ? 100 - pct(Math.max(vals[0], vals[1])) : 100 - pct(vals[0]);
|
|
142
|
+
const hasGradient = colors && colors.length >= 2;
|
|
143
|
+
const fillStyle = {
|
|
144
|
+
left: `${fillLeft}%`,
|
|
145
|
+
right: `${fillRight}%`
|
|
146
|
+
};
|
|
147
|
+
if (hasGradient) {
|
|
148
|
+
const w = 100 - fillLeft - fillRight;
|
|
149
|
+
if (w > 0) {
|
|
150
|
+
const stops = colors.map((c, i) => {
|
|
151
|
+
const orig = i / (colors.length - 1) * 100;
|
|
152
|
+
return `${c} ${((orig - fillLeft) / w * 100).toFixed(2)}%`;
|
|
153
|
+
}).join(", ");
|
|
154
|
+
fillStyle.background = `linear-gradient(to right, ${stops})`;
|
|
155
|
+
fillStyle.boxShadow = "none";
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return /* @__PURE__ */ jsxs(
|
|
159
|
+
"div",
|
|
160
|
+
{
|
|
161
|
+
ref,
|
|
162
|
+
className: `slider ${range ? "range" : ""} ${hasGradient ? "gradient" : tone} ${disabled ? "disabled" : ""} ${marks ? "has-marks" : ""} ${className}`,
|
|
163
|
+
children: [
|
|
164
|
+
/* @__PURE__ */ jsxs("div", { className: "slider-rail", children: [
|
|
165
|
+
/* @__PURE__ */ jsx(
|
|
166
|
+
"div",
|
|
167
|
+
{
|
|
168
|
+
className: "slider-track",
|
|
169
|
+
ref: trackRef,
|
|
170
|
+
onPointerDown,
|
|
171
|
+
onPointerMove,
|
|
172
|
+
onPointerUp,
|
|
173
|
+
children: /* @__PURE__ */ jsx("div", { className: "slider-fill", style: fillStyle })
|
|
174
|
+
}
|
|
175
|
+
),
|
|
176
|
+
vals.map((n, i) => {
|
|
177
|
+
const thumbStyle = { left: `${pct(n)}%` };
|
|
178
|
+
if (hasGradient) {
|
|
179
|
+
thumbStyle["--slider-thumb-color"] = lerpColor(colors, (n - min) / (max - min));
|
|
180
|
+
}
|
|
181
|
+
return /* @__PURE__ */ jsx(
|
|
182
|
+
"div",
|
|
183
|
+
{
|
|
184
|
+
ref: (el) => {
|
|
185
|
+
thumbEls.current[i] = el;
|
|
186
|
+
},
|
|
187
|
+
className: "slider-thumb",
|
|
188
|
+
style: thumbStyle,
|
|
189
|
+
role: "slider",
|
|
190
|
+
tabIndex: disabled ? -1 : 0,
|
|
191
|
+
"aria-valuemin": min,
|
|
192
|
+
"aria-valuemax": max,
|
|
193
|
+
"aria-valuenow": n,
|
|
194
|
+
"aria-disabled": disabled || void 0,
|
|
195
|
+
onKeyDown: (e) => handleKey(i, e),
|
|
196
|
+
onPointerDown: (e) => {
|
|
197
|
+
if (disabled) return;
|
|
198
|
+
e.preventDefault();
|
|
199
|
+
e.stopPropagation();
|
|
200
|
+
dragging.current = i;
|
|
201
|
+
trackRef.current?.setPointerCapture(e.pointerId);
|
|
202
|
+
e.currentTarget.focus();
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
i
|
|
206
|
+
);
|
|
207
|
+
}),
|
|
208
|
+
marks && /* @__PURE__ */ jsx("div", { className: "slider-marks", children: Object.entries(marks).map(([k, label]) => {
|
|
209
|
+
const n = Number(k);
|
|
210
|
+
const active = range ? n >= Math.min(vals[0], vals[1]) && n <= Math.max(vals[0], vals[1]) : n <= vals[0];
|
|
211
|
+
return /* @__PURE__ */ jsxs(
|
|
212
|
+
"span",
|
|
213
|
+
{
|
|
214
|
+
className: `slider-mark ${active ? "active" : ""}`,
|
|
215
|
+
style: { left: `${pct(n)}%` },
|
|
216
|
+
onClick: () => handleMarkClick(n),
|
|
217
|
+
children: [
|
|
218
|
+
/* @__PURE__ */ jsx("span", { className: "slider-mark-dot" }),
|
|
219
|
+
/* @__PURE__ */ jsx("span", { className: "slider-mark-label", children: label })
|
|
220
|
+
]
|
|
221
|
+
},
|
|
222
|
+
k
|
|
223
|
+
);
|
|
224
|
+
}) })
|
|
225
|
+
] }),
|
|
226
|
+
showValue && /* @__PURE__ */ jsx("span", { className: "slider-value", children: range ? `${vals[0]} \u2013 ${vals[1]}` : vals[0] })
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
export { Slider };
|
|
234
|
+
//# sourceMappingURL=chunk-2TZ2R7L2.js.map
|
|
235
|
+
//# sourceMappingURL=chunk-2TZ2R7L2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","file":"chunk-2TZ2R7L2.js","sourcesContent":["import \"../../styles/tokens.css\";\nimport \"../../styles/shared.css\";\nimport \"./Slider.css\";\nimport * as React from \"react\";\n\nexport type SliderRangeValue = [number, number];\nexport type SliderValue = number | SliderRangeValue;\n\ninterface SliderBaseProps {\n min?: number;\n max?: number;\n step?: number;\n disabled?: boolean;\n showValue?: boolean;\n tone?: \"accent\" | \"success\" | \"warning\" | \"danger\";\n /** Custom gradient colors mapped from min→max. Overrides `tone` for fill & thumb. */\n colors?: string[];\n /** Tick marks with labels. Clicking a mark snaps to it. */\n marks?: Record<number, React.ReactNode>;\n className?: string;\n}\n\nexport interface SliderSingleProps extends SliderBaseProps {\n range?: false;\n value?: number;\n defaultValue?: number;\n onChange?: (value: number) => void;\n}\n\nexport interface SliderRangeProps extends SliderBaseProps {\n range: true;\n value?: SliderRangeValue;\n defaultValue?: SliderRangeValue;\n onChange?: (value: SliderRangeValue) => void;\n}\n\nexport type SliderProps = SliderSingleProps | SliderRangeProps;\n\nfunction clamp(v: number, lo: number, hi: number) {\n return Math.max(lo, Math.min(hi, v));\n}\n\nfunction snap(raw: number, step: number, min: number) {\n return Math.round((raw - min) / step) * step + min;\n}\n\nfunction lerpColor(colors: string[], t: number): string {\n const pos = Math.max(0, Math.min(1, t)) * (colors.length - 1);\n const i = Math.min(Math.floor(pos), colors.length - 2);\n const frac = pos - i;\n if (frac === 0) return colors[i];\n return `color-mix(in oklch, ${colors[i + 1]} ${Math.round(frac * 100)}%, ${colors[i]})`;\n}\n\n/** `Slider` — neumorphic range input with grooved track.\n * @example <Slider defaultValue={40} showValue />\n */\nexport const Slider = React.forwardRef<HTMLDivElement, SliderProps>(\n (props, ref) => {\n const {\n min = 0,\n max = 100,\n step = 1,\n disabled,\n showValue,\n tone = \"accent\",\n colors,\n marks,\n className = \"\",\n } = props;\n\n const range = (props as SliderRangeProps).range === true;\n const controlled = (props as { value?: SliderValue }).value;\n const defaultVal = (props as { defaultValue?: SliderValue }).defaultValue;\n const onChange = (props as { onChange?: (v: any) => void }).onChange;\n\n const initRef = React.useRef<number[]>(\n defaultVal !== undefined\n ? Array.isArray(defaultVal)\n ? [...defaultVal]\n : [defaultVal]\n : range\n ? [min, max]\n : [min]\n );\n const [inner, setInner] = React.useState<number[]>(initRef.current);\n\n const isControlled = controlled !== undefined;\n const vals = isControlled\n ? Array.isArray(controlled)\n ? controlled\n : [controlled]\n : inner;\n\n const valsRef = React.useRef(vals);\n valsRef.current = vals;\n\n const trackRef = React.useRef<HTMLDivElement>(null);\n const thumbEls = React.useRef<(HTMLDivElement | null)[]>([]);\n const dragging = React.useRef<number | null>(null);\n\n const pct = (n: number) => ((n - min) / (max - min)) * 100;\n\n const commit = React.useCallback(\n (next: number[]) => {\n if (!isControlled) setInner(next);\n if (range) {\n onChange?.([next[0], next[1]] as SliderRangeValue);\n } else {\n onChange?.(next[0]);\n }\n },\n [isControlled, range, onChange]\n );\n\n const setAt = React.useCallback(\n (index: number, raw: number) => {\n const snapped = snap(clamp(raw, min, max), step, min);\n const clamped = clamp(snapped, min, max);\n const out = [...valsRef.current];\n out[index] = clamped;\n if (range && out.length === 2 && out[0] > out[1]) out.sort((a, b) => a - b);\n commit(out);\n },\n [min, max, step, range, commit]\n );\n\n const valFromX = React.useCallback(\n (clientX: number) => {\n const rect = trackRef.current?.getBoundingClientRect();\n if (!rect) return min;\n const ratio = clamp((clientX - rect.left) / rect.width, 0, 1);\n return min + ratio * (max - min);\n },\n [min, max]\n );\n\n const closerIndex = React.useCallback(\n (target: number) => {\n const v = valsRef.current;\n if (!range || v.length < 2) return 0;\n const d0 = Math.abs(v[0] - target);\n const d1 = Math.abs(v[1] - target);\n if (d0 === d1) return target < v[0] ? 0 : 1;\n return d0 < d1 ? 0 : 1;\n },\n [range]\n );\n\n const onPointerDown = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (disabled) return;\n e.preventDefault();\n const val = valFromX(e.clientX);\n const idx = closerIndex(val);\n dragging.current = idx;\n setAt(idx, val);\n trackRef.current?.setPointerCapture(e.pointerId);\n thumbEls.current[idx]?.focus();\n },\n [disabled, valFromX, closerIndex, setAt]\n );\n\n const onPointerMove = React.useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (dragging.current === null) return;\n setAt(dragging.current, valFromX(e.clientX));\n },\n [valFromX, setAt]\n );\n\n const onPointerUp = React.useCallback(() => {\n dragging.current = null;\n }, []);\n\n const handleKey = React.useCallback(\n (index: number, e: React.KeyboardEvent) => {\n if (disabled) return;\n let delta = 0;\n if (e.key === \"ArrowRight\" || e.key === \"ArrowUp\") delta = step;\n else if (e.key === \"ArrowLeft\" || e.key === \"ArrowDown\") delta = -step;\n else if (e.key === \"Home\") { setAt(index, min); return; }\n else if (e.key === \"End\") { setAt(index, max); return; }\n else return;\n e.preventDefault();\n setAt(index, valsRef.current[index] + delta);\n },\n [disabled, step, min, max, setAt]\n );\n\n const handleMarkClick = React.useCallback(\n (mark: number) => {\n if (disabled) return;\n setAt(closerIndex(mark), mark);\n },\n [disabled, closerIndex, setAt]\n );\n\n const fillLeft = range ? pct(Math.min(vals[0], vals[1])) : 0;\n const fillRight = range\n ? 100 - pct(Math.max(vals[0], vals[1]))\n : 100 - pct(vals[0]);\n\n const hasGradient = colors && colors.length >= 2;\n\n const fillStyle: React.CSSProperties = {\n left: `${fillLeft}%`,\n right: `${fillRight}%`,\n };\n if (hasGradient) {\n const w = 100 - fillLeft - fillRight;\n if (w > 0) {\n const stops = colors.map((c, i) => {\n const orig = (i / (colors.length - 1)) * 100;\n return `${c} ${((orig - fillLeft) / w * 100).toFixed(2)}%`;\n }).join(\", \");\n fillStyle.background = `linear-gradient(to right, ${stops})`;\n fillStyle.boxShadow = \"none\";\n }\n }\n\n return (\n <div\n ref={ref}\n className={`slider ${range ? \"range\" : \"\"} ${hasGradient ? \"gradient\" : tone} ${disabled ? \"disabled\" : \"\"} ${marks ? \"has-marks\" : \"\"} ${className}`}\n >\n <div className=\"slider-rail\">\n <div\n className=\"slider-track\"\n ref={trackRef}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerUp={onPointerUp}\n >\n <div className=\"slider-fill\" style={fillStyle} />\n </div>\n\n {vals.map((n, i) => {\n const thumbStyle: React.CSSProperties = { left: `${pct(n)}%` };\n if (hasGradient) {\n (thumbStyle as any)[\"--slider-thumb-color\"] = lerpColor(colors, (n - min) / (max - min));\n }\n return (\n <div\n key={i}\n ref={(el) => { thumbEls.current[i] = el; }}\n className=\"slider-thumb\"\n style={thumbStyle}\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={n}\n aria-disabled={disabled || undefined}\n onKeyDown={(e) => handleKey(i, e)}\n onPointerDown={(e) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n dragging.current = i;\n trackRef.current?.setPointerCapture(e.pointerId);\n e.currentTarget.focus();\n }}\n />\n );\n })}\n\n {marks && (\n <div className=\"slider-marks\">\n {Object.entries(marks).map(([k, label]) => {\n const n = Number(k);\n const active = range\n ? n >= Math.min(vals[0], vals[1]) && n <= Math.max(vals[0], vals[1])\n : n <= vals[0];\n return (\n <span\n key={k}\n className={`slider-mark ${active ? \"active\" : \"\"}`}\n style={{ left: `${pct(n)}%` }}\n onClick={() => handleMarkClick(n)}\n >\n <span className=\"slider-mark-dot\" />\n <span className=\"slider-mark-label\">{label}</span>\n </span>\n );\n })}\n </div>\n )}\n </div>\n\n {showValue && (\n <span className=\"slider-value\">\n {range ? `${vals[0]} – ${vals[1]}` : vals[0]}\n </span>\n )}\n </div>\n );\n }\n);\n"]}
|