@fab1o978/react-ui 0.1.5 → 0.1.7

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.
@@ -0,0 +1,266 @@
1
+ import { useState, useRef, useCallback, useEffect } from 'react';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+
4
+ // src/components/SliderControl/SliderControl.tsx
5
+
6
+ // src/components/SliderControl/SliderControl.module.scss
7
+ var SliderControl_module_default = {
8
+ wrapper: "SliderControl_module_wrapper3",
9
+ disabled: "SliderControl_module_disabled3",
10
+ icon: "SliderControl_module_icon3",
11
+ trackArea: "SliderControl_module_trackArea3",
12
+ groove: "SliderControl_module_groove3",
13
+ rail: "SliderControl_module_rail3",
14
+ fill: "SliderControl_module_fill3",
15
+ thumb: "SliderControl_module_thumb3",
16
+ thumbDragging: "SliderControl_module_thumbDragging3",
17
+ tooltip: "SliderControl_module_tooltip3",
18
+ tooltipVisible: "SliderControl_module_tooltipVisible3"
19
+ };
20
+
21
+ // src/utils/color.ts
22
+ function hexToHsl(hex) {
23
+ const r = parseInt(hex.slice(1, 3), 16) / 255;
24
+ const g = parseInt(hex.slice(3, 5), 16) / 255;
25
+ const b = parseInt(hex.slice(5, 7), 16) / 255;
26
+ const max = Math.max(r, g, b);
27
+ const min = Math.min(r, g, b);
28
+ const l = (max + min) / 2;
29
+ let h = 0;
30
+ let s = 0;
31
+ if (max !== min) {
32
+ const d = max - min;
33
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
34
+ switch (max) {
35
+ case r:
36
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
37
+ break;
38
+ case g:
39
+ h = ((b - r) / d + 2) / 6;
40
+ break;
41
+ case b:
42
+ h = ((r - g) / d + 4) / 6;
43
+ break;
44
+ }
45
+ }
46
+ return [h * 360, s * 100, l * 100];
47
+ }
48
+ function hslToHex(h, s, l) {
49
+ const sl = s / 100;
50
+ const ll = l / 100;
51
+ const a = sl * Math.min(ll, 1 - ll);
52
+ const f = (n) => {
53
+ const k = (n + h / 30) % 12;
54
+ const color = ll - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
55
+ return Math.round(255 * color).toString(16).padStart(2, "0");
56
+ };
57
+ return `#${f(0)}${f(8)}${f(4)}`;
58
+ }
59
+ function hslToRgb(h, s, l) {
60
+ const sl = s / 100;
61
+ const ll = l / 100;
62
+ const a = sl * Math.min(ll, 1 - ll);
63
+ const f = (n) => {
64
+ const k = (n + h / 30) % 12;
65
+ return Math.round(255 * (ll - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)));
66
+ };
67
+ return { r: f(0), g: f(8), b: f(4) };
68
+ }
69
+ function hslToRgba(h, s, l, alpha) {
70
+ const { r, g, b } = hslToRgb(h, s, l);
71
+ return `rgba(${r}, ${g}, ${b}, ${alpha})`;
72
+ }
73
+ function deriveAccent(hex) {
74
+ const [h, s, l] = hexToHsl(hex);
75
+ return {
76
+ base: hex,
77
+ dot: hslToHex(h, s, Math.min(l + 12, 95)),
78
+ track: hex,
79
+ ring: hex,
80
+ glow: hslToRgba(h, s, l, 0.3),
81
+ light: hslToHex(h, Math.max(s - 20, 0), Math.min(l + 45, 96))
82
+ };
83
+ }
84
+ function accentToCssVars(tokens, prefix) {
85
+ return {
86
+ [`--${prefix}-accent`]: tokens.base,
87
+ [`--${prefix}-accent-dot`]: tokens.dot,
88
+ [`--${prefix}-accent-track`]: tokens.track,
89
+ [`--${prefix}-accent-ring`]: tokens.ring,
90
+ [`--${prefix}-accent-glow`]: tokens.glow,
91
+ [`--${prefix}-accent-light`]: tokens.light
92
+ };
93
+ }
94
+ function clamp(v, min, max) {
95
+ return Math.min(Math.max(v, min), max);
96
+ }
97
+ function snapToStep(v, min, step) {
98
+ return Math.round((v - min) / step) * step + min;
99
+ }
100
+ var SliderControl = ({
101
+ value: controlledValue,
102
+ defaultValue = 50,
103
+ min = 0,
104
+ max = 100,
105
+ step = 1,
106
+ onChange,
107
+ showTooltip = "drag",
108
+ leftIcon,
109
+ rightIcon,
110
+ railBackground,
111
+ accent,
112
+ className,
113
+ disabled = false
114
+ }) => {
115
+ const isControlled = controlledValue !== void 0;
116
+ const [internalValue, setInternalValue] = useState(defaultValue);
117
+ const [isDragging, setIsDragging] = useState(false);
118
+ const [isFocused, setIsFocused] = useState(false);
119
+ const trackRef = useRef(null);
120
+ const thumbRef = useRef(null);
121
+ const value = isControlled ? controlledValue : internalValue;
122
+ const pct = (clamp(value, min, max) - min) / (max - min);
123
+ const accentVars = accent ? accentToCssVars(deriveAccent(accent), "slider") : {};
124
+ const setValue = useCallback(
125
+ (next) => {
126
+ const snapped = clamp(snapToStep(next, min, step), min, max);
127
+ if (!isControlled) setInternalValue(snapped);
128
+ onChange?.(snapped);
129
+ },
130
+ [isControlled, min, max, step, onChange]
131
+ );
132
+ const valueFromPointer = useCallback(
133
+ (e) => {
134
+ const rect = trackRef.current.getBoundingClientRect();
135
+ const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
136
+ return min + ratio * (max - min);
137
+ },
138
+ [min, max]
139
+ );
140
+ const handlePointerDown = useCallback(
141
+ (e) => {
142
+ if (disabled) return;
143
+ e.currentTarget.setPointerCapture(e.pointerId);
144
+ setIsDragging(true);
145
+ thumbRef.current?.focus();
146
+ setValue(valueFromPointer(e.nativeEvent));
147
+ },
148
+ [disabled, setValue, valueFromPointer]
149
+ );
150
+ const handlePointerMove = useCallback(
151
+ (e) => {
152
+ if (!isDragging || disabled) return;
153
+ setValue(valueFromPointer(e.nativeEvent));
154
+ },
155
+ [isDragging, disabled, setValue, valueFromPointer]
156
+ );
157
+ const handlePointerUp = useCallback(() => {
158
+ setIsDragging(false);
159
+ thumbRef.current?.blur();
160
+ }, []);
161
+ useEffect(() => {
162
+ const el = trackRef.current;
163
+ if (!el) return;
164
+ const onWheel = (e) => {
165
+ if (disabled) return;
166
+ e.preventDefault();
167
+ setValue(value + (e.deltaY < 0 ? step : -step));
168
+ };
169
+ el.addEventListener("wheel", onWheel, { passive: false });
170
+ return () => el.removeEventListener("wheel", onWheel);
171
+ }, [disabled, value, step, setValue]);
172
+ const handleKeyDown = useCallback(
173
+ (e) => {
174
+ if (disabled) return;
175
+ const map = {
176
+ ArrowRight: step,
177
+ ArrowUp: step,
178
+ ArrowLeft: -step,
179
+ ArrowDown: -step,
180
+ PageUp: step * 10,
181
+ PageDown: -step * 10
182
+ };
183
+ if (e.key === "Home") {
184
+ setValue(min);
185
+ e.preventDefault();
186
+ return;
187
+ }
188
+ if (e.key === "End") {
189
+ setValue(max);
190
+ e.preventDefault();
191
+ return;
192
+ }
193
+ if (map[e.key] !== void 0) {
194
+ setValue(value + map[e.key]);
195
+ e.preventDefault();
196
+ }
197
+ },
198
+ [disabled, step, min, max, value, setValue]
199
+ );
200
+ const tooltipVisible = showTooltip === "always" || showTooltip === "drag" && (isDragging || isFocused);
201
+ const displayValue = `${Math.round(value)}%`;
202
+ const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;
203
+ return /* @__PURE__ */ jsxs(
204
+ "div",
205
+ {
206
+ className: [SliderControl_module_default.wrapper, disabled ? SliderControl_module_default.disabled : "", className ?? ""].filter(Boolean).join(" "),
207
+ style: accentVars,
208
+ children: [
209
+ leftIcon !== null && leftIcon !== void 0 && /* @__PURE__ */ jsx("span", { className: SliderControl_module_default.icon, children: leftIcon }),
210
+ /* @__PURE__ */ jsxs(
211
+ "div",
212
+ {
213
+ ref: trackRef,
214
+ className: SliderControl_module_default.trackArea,
215
+ onPointerDown: handlePointerDown,
216
+ onPointerMove: handlePointerMove,
217
+ onPointerUp: handlePointerUp,
218
+ onPointerCancel: handlePointerUp,
219
+ children: [
220
+ /* @__PURE__ */ jsx("div", { className: SliderControl_module_default.groove, children: /* @__PURE__ */ jsx(
221
+ "div",
222
+ {
223
+ className: SliderControl_module_default.rail,
224
+ style: railBackground ? { background: railBackground } : void 0,
225
+ children: !railBackground && /* @__PURE__ */ jsx("div", { className: SliderControl_module_default.fill, style: { width: `${pct * 100}%` } })
226
+ }
227
+ ) }),
228
+ /* @__PURE__ */ jsx(
229
+ "div",
230
+ {
231
+ ref: thumbRef,
232
+ role: "slider",
233
+ tabIndex: disabled ? -1 : 0,
234
+ "aria-valuenow": Math.round(value),
235
+ "aria-valuemin": min,
236
+ "aria-valuemax": max,
237
+ "aria-disabled": disabled,
238
+ className: [SliderControl_module_default.thumb, isDragging ? SliderControl_module_default.thumbDragging : ""].filter(Boolean).join(" "),
239
+ style: { left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` },
240
+ onKeyDown: handleKeyDown,
241
+ onFocus: () => setIsFocused(true),
242
+ onBlur: () => setIsFocused(false)
243
+ }
244
+ ),
245
+ /* @__PURE__ */ jsx(
246
+ "div",
247
+ {
248
+ className: [SliderControl_module_default.tooltip, tooltipVisible ? SliderControl_module_default.tooltipVisible : ""].filter(Boolean).join(" "),
249
+ style: { left: tooltipOffset },
250
+ "aria-hidden": "true",
251
+ children: displayValue
252
+ }
253
+ )
254
+ ]
255
+ }
256
+ ),
257
+ rightIcon !== null && rightIcon !== void 0 && /* @__PURE__ */ jsx("span", { className: SliderControl_module_default.icon, children: rightIcon })
258
+ ]
259
+ }
260
+ );
261
+ };
262
+ SliderControl.displayName = "SliderControl";
263
+
264
+ export { SliderControl };
265
+ //# sourceMappingURL=index.js.map
266
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/SliderControl/SliderControl.module.scss","../../../src/utils/color.ts","../../../src/components/SliderControl/SliderControl.tsx"],"names":["wrapper","disabled","icon","trackArea","groove","rail","fill","thumb","thumbDragging","tooltip","tooltipVisible"],"mappings":"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","file":"index.js","sourcesContent":["@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap\");\n:root {\n --accent: #3b82f6;\n --accent-dot: rgb(82.52, 145, 247.08);\n --accent-track: #3b82f6;\n --accent-ring: #3b82f6;\n --accent-glow: rgba(59, 130, 246, 0.3);\n --accent-light: rgb(157.485, 188.725, 239.765);\n --color-primary-50: rgb(169.3455, 194.6925, 236.1045);\n --color-primary-100: rgb(149.4545, 184.4575, 241.6455);\n --color-primary-400: rgb(82.52, 145, 247.08);\n --color-primary-500: #3b82f6;\n --color-primary-600: rgb(29.8390243902, 111.4024390244, 244.6609756098);\n --color-primary-700: rgb(10.712195122, 95.2195121951, 233.287804878);\n --color-neutral-0: #ffffff;\n --color-neutral-100: #f3f4f6;\n --color-neutral-200: #e5e7eb;\n --color-neutral-400: #9ca3af;\n --color-neutral-600: #4b5563;\n --color-neutral-900: #111827;\n --color-success-500: #22c55e;\n --color-success-600: #16a34a;\n --color-danger-500: #ef4444;\n --color-danger-600: #dc2626;\n --color-warning-500: #f59e0b;\n --color-warning-600: #d97706;\n --font-family-base: \"Inter\", system-ui, -apple-system, sans-serif;\n --font-size-xs: 0.75rem;\n --font-size-sm: 0.875rem;\n --font-size-md: 1rem;\n --font-size-lg: 1.125rem;\n --spacing-1: 0.25rem;\n --spacing-2: 0.5rem;\n --spacing-3: 0.75rem;\n --spacing-4: 1rem;\n --radius-sm: 0.25rem;\n --radius-md: 0.375rem;\n --radius-lg: 0.5rem;\n --radius-full: 9999px;\n --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);\n --transition-fast: 150ms ease;\n --color-surface: #ffffff;\n --color-surface-elevated: #ffffff;\n}\n\n[data-theme=dark] {\n --color-neutral-0: #0f172a;\n --color-neutral-100: #1e293b;\n --color-neutral-200: #334155;\n --color-neutral-400: #94a3b8;\n --color-neutral-600: #cbd5e1;\n --color-neutral-900: #f8fafc;\n --color-surface: #1e293b;\n --color-surface-elevated: #273549;\n --color-primary-50: #172554;\n --color-primary-100: #1e3a8a;\n --accent-light: #172554;\n --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.4);\n --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.5), 0 2px 4px -2px rgb(0 0 0 / 0.4);\n}\n\n.wrapper {\n display: flex;\n align-items: center;\n gap: 10px;\n font-family: var(--font-family-base);\n user-select: none;\n -webkit-user-select: none;\n}\n\n.disabled {\n opacity: 0.45;\n pointer-events: none;\n}\n\n.icon {\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--color-neutral-400);\n flex-shrink: 0;\n line-height: 0;\n}\n\n.trackArea {\n position: relative;\n flex: 1;\n height: 36px;\n display: flex;\n align-items: center;\n cursor: pointer;\n}\n\n.groove {\n position: relative;\n width: 100%;\n height: 22px;\n border-radius: var(--radius-full);\n background: var(--color-neutral-300);\n display: flex;\n align-items: center;\n box-shadow: inset 0 4px 8px rgba(0, 0, 0, 0.14), inset 0 2px 4px rgba(0, 0, 0, 0.06), inset 0 -2px 3px rgba(255, 255, 255, 0.1);\n}\n\n.rail {\n position: absolute;\n left: 8px;\n right: 8px;\n height: 6px;\n border-radius: var(--radius-full);\n background: var(--color-neutral-400);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(0, 0, 0, 0.18);\n overflow: hidden;\n}\n\n.fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n background: var(--slider-accent-track, var(--accent-track));\n border-radius: var(--radius-full);\n transition: width 60ms linear;\n}\n\n.thumb {\n position: absolute;\n top: 50%;\n width: 18px;\n height: 18px;\n border-radius: 50%;\n transform: translate(-50%, -50%);\n background: #dde0e6;\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22);\n cursor: grab;\n transition: box-shadow 120ms ease, transform 120ms ease;\n outline: none;\n z-index: 2;\n}\n\n.thumb:focus-visible {\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.22), 0 0 0 3px var(--slider-accent-ring, var(--accent-ring));\n}\n\n.thumbDragging {\n cursor: grabbing;\n transform: translate(-50%, -50%) scale(1.08);\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28), 0 0 0 3px var(--slider-accent-ring, var(--accent-ring)), 0 0 0 6px var(--slider-accent-glow, var(--accent-glow));\n}\n\n.tooltip {\n position: absolute;\n bottom: calc(100% + 6px);\n transform: translateX(-50%);\n background: rgba(18, 18, 26, 0.85);\n backdrop-filter: blur(6px);\n -webkit-backdrop-filter: blur(6px);\n color: #fff;\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n padding: 3px 8px;\n border-radius: 6px;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity 120ms ease;\n z-index: 10;\n}\n.tooltip::after {\n content: \"\";\n position: absolute;\n top: 100%;\n left: 50%;\n transform: translateX(-50%);\n border: 4px solid transparent;\n border-top-color: rgba(18, 18, 26, 0.85);\n}\n\n.tooltipVisible {\n opacity: 1;\n}\n\n[data-theme=dark] .groove {\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), inset 0 3px 7px rgba(0, 0, 0, 0.32), inset 0 1px 3px rgba(0, 0, 0, 0.22), inset 0 -2px 3px rgba(255, 255, 255, 0.04);\n}\n[data-theme=dark] .thumb {\n background: #4a4f5c;\n border-color: rgba(255, 255, 255, 0.08);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);\n}\n[data-theme=dark] .thumbDragging {\n box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5), 0 0 0 3px var(--slider-accent-ring, var(--accent-ring)), 0 0 0 6px var(--slider-accent-glow, var(--accent-glow));\n}\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3N0eWxlcy90b2tlbnMuc2NzcyIsIlNsaWRlckNvbnRyb2wubW9kdWxlLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRVE7QUFLUjtFQUVFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBQ0E7RUFDQTtFQUdBO0VBQ0E7RUFDQTtFQUNBO0VBR0E7RUFDQTtFQUdBO0VBR0E7RUFDQTs7O0FBUUY7RUFFRTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFHQTtFQUNBO0VBR0E7RUFDQTtFQUlBO0VBR0E7RUFDQTs7O0FDeEZGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFO0VBQ0E7OztBQUdGO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFJRjtFQUNFO0VBQ0E7RUFDQSxRQTdCYztFQThCZDtFQUNBO0VBQ0E7OztBQUlGO0VBQ0U7RUFDQTtFQUNBLFFBMUNjO0VBMkNkO0VBQ0E7RUFDQTtFQUNBO0VBRUEsWUFDRTs7O0FBTUo7RUFDRTtFQUNBO0VBQ0E7RUFDQSxRQTFEZTtFQTJEZjtFQUNBO0VBQ0EsWUFDRTtFQUVGOzs7QUFJRjtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0EsWUE5RWE7RUErRWI7RUFDQTs7O0FBSUY7RUFDRTtFQUNBO0VBQ0EsT0FqRmM7RUFrRmQsUUFsRmM7RUFtRmQ7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFHRjtFQUNFLFlBQ0U7OztBQUlKO0VBQ0U7RUFDQTtFQUNBLFlBQ0U7OztBQU1KO0VBQ0U7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTs7QUFFQTtFQUNFO0VBQ0E7RUFDQTtFQUNBO0VBQ0E7RUFDQTtFQUNBOzs7QUFJSjtFQUNFOzs7QUFLQTtFQUNFLFlBQ0U7O0FBTUo7RUFDRTtFQUNBO0VBQ0E7O0FBR0Y7RUFDRSxZQUNFIiwic291cmNlc0NvbnRlbnQiOlsiQHVzZSBcInNhc3M6Y29sb3JcIjtcblxuQGltcG9ydCB1cmwoXCJodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2NzczI/ZmFtaWx5PUludGVyOndnaHRANDAwOzUwMDs2MDAmZGlzcGxheT1zd2FwXCIpO1xuXG4vLyBBY2NlbnQgZGkgZGVmYXVsdCDigJQgY2FtYmlhIHF1aSBwZXIgYWdnaW9ybmFyZSB0dXR0YSBsYSBsaWJyZXJpYVxuJGFjY2VudDogIzNiODJmNjtcblxuOnJvb3Qge1xuICAvLyBBY2NlbnQgc2NhbGUg4oCUIGRlcml2YXRhIGRhICRhY2NlbnQgYSBjb21waWxlIHRpbWVcbiAgLS1hY2NlbnQ6ICAgICAgICAjeyRhY2NlbnR9O1xuICAtLWFjY2VudC1kb3Q6ICAgICN7Y29sb3Iuc2NhbGUoJGFjY2VudCwgJGxpZ2h0bmVzczogMTIlKX07XG4gIC0tYWNjZW50LXRyYWNrOiAgI3skYWNjZW50fTtcbiAgLS1hY2NlbnQtcmluZzogICAjeyRhY2NlbnR9O1xuICAtLWFjY2VudC1nbG93OiAgICN7Y29sb3IuY2hhbmdlKCRhY2NlbnQsICRhbHBoYTogMC4zKX07XG4gIC0tYWNjZW50LWxpZ2h0OiAgI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiA0NSUsICRzYXR1cmF0aW9uOiAtMjAlKX07XG5cbiAgLy8gUHJpbWFyeSBzY2FsZSAobWFudGVudXRhIHBlciByZXRyb2NvbXBhdGliaWxpdMOgIGNvbiBCdXR0b24sIEJhZGdlLCBJbnB1dClcbiAgLS1jb2xvci1wcmltYXJ5LTUwOiAgI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiA0OSUsICRzYXR1cmF0aW9uOiAtMzAlKX07XG4gIC0tY29sb3ItcHJpbWFyeS0xMDA6ICN7Y29sb3Iuc2NhbGUoJGFjY2VudCwgJGxpZ2h0bmVzczogNDIlLCAkc2F0dXJhdGlvbjogLTE1JSl9O1xuICAtLWNvbG9yLXByaW1hcnktNDAwOiAje2NvbG9yLnNjYWxlKCRhY2NlbnQsICRsaWdodG5lc3M6IDEyJSl9O1xuICAtLWNvbG9yLXByaW1hcnktNTAwOiAjeyRhY2NlbnR9O1xuICAtLWNvbG9yLXByaW1hcnktNjAwOiAje2NvbG9yLnNjYWxlKCRhY2NlbnQsICRsaWdodG5lc3M6IC0xMCUpfTtcbiAgLS1jb2xvci1wcmltYXJ5LTcwMDogI3tjb2xvci5zY2FsZSgkYWNjZW50LCAkbGlnaHRuZXNzOiAtMjAlKX07XG5cbiAgLy8gTmV1dHJhbFxuICAtLWNvbG9yLW5ldXRyYWwtMDogICAjZmZmZmZmO1xuICAtLWNvbG9yLW5ldXRyYWwtMTAwOiAjZjNmNGY2O1xuICAtLWNvbG9yLW5ldXRyYWwtMjAwOiAjZTVlN2ViO1xuICAtLWNvbG9yLW5ldXRyYWwtNDAwOiAjOWNhM2FmO1xuICAtLWNvbG9yLW5ldXRyYWwtNjAwOiAjNGI1NTYzO1xuICAtLWNvbG9yLW5ldXRyYWwtOTAwOiAjMTExODI3O1xuXG4gIC8vIFNlbWFudGljXG4gIC0tY29sb3Itc3VjY2Vzcy01MDA6ICMyMmM1NWU7XG4gIC0tY29sb3Itc3VjY2Vzcy02MDA6ICMxNmEzNGE7XG4gIC0tY29sb3ItZGFuZ2VyLTUwMDogICNlZjQ0NDQ7XG4gIC0tY29sb3ItZGFuZ2VyLTYwMDogICNkYzI2MjY7XG4gIC0tY29sb3Itd2FybmluZy01MDA6ICNmNTllMGI7XG4gIC0tY29sb3Itd2FybmluZy02MDA6ICNkOTc3MDY7XG5cbiAgLy8gVHlwb2dyYXBoeVxuICAtLWZvbnQtZmFtaWx5LWJhc2U6IFwiSW50ZXJcIiwgc3lzdGVtLXVpLCAtYXBwbGUtc3lzdGVtLCBzYW5zLXNlcmlmO1xuICAtLWZvbnQtc2l6ZS14czogMC43NXJlbTtcbiAgLS1mb250LXNpemUtc206IDAuODc1cmVtO1xuICAtLWZvbnQtc2l6ZS1tZDogMXJlbTtcbiAgLS1mb250LXNpemUtbGc6IDEuMTI1cmVtO1xuXG4gIC8vIFNwYWNpbmdcbiAgLS1zcGFjaW5nLTE6IDAuMjVyZW07XG4gIC0tc3BhY2luZy0yOiAwLjVyZW07XG4gIC0tc3BhY2luZy0zOiAwLjc1cmVtO1xuICAtLXNwYWNpbmctNDogMXJlbTtcblxuICAvLyBSYWRpdXNcbiAgLS1yYWRpdXMtc206ICAgMC4yNXJlbTtcbiAgLS1yYWRpdXMtbWQ6ICAgMC4zNzVyZW07XG4gIC0tcmFkaXVzLWxnOiAgIDAuNXJlbTtcbiAgLS1yYWRpdXMtZnVsbDogOTk5OXB4O1xuXG4gIC8vIFNoYWRvd3NcbiAgLS1zaGFkb3ctc206IDAgMXB4IDJweCAwIHJnYigwIDAgMCAvIDAuMDUpO1xuICAtLXNoYWRvdy1tZDogMCA0cHggNnB4IC0xcHggcmdiKDAgMCAwIC8gMC4xKSwgMCAycHggNHB4IC0ycHggcmdiKDAgMCAwIC8gMC4xKTtcblxuICAvLyBUcmFuc2l0aW9uc1xuICAtLXRyYW5zaXRpb24tZmFzdDogMTUwbXMgZWFzZTtcblxuICAvLyBTdXJmYWNlIChiYWNrZ3JvdW5kIGRpIGNhcmQvcGFuZWwpXG4gIC0tY29sb3Itc3VyZmFjZTogICAgICAgICAgI2ZmZmZmZjtcbiAgLS1jb2xvci1zdXJmYWNlLWVsZXZhdGVkOiAjZmZmZmZmO1xufVxuXG4vLyDilIDilIDilIAgRGFyayB0aGVtZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbi8vIEFwcGxpY2F0byB2aWEgZGF0YS10aGVtZT1cImRhcmtcIiBzdWxsJ2VsZW1lbnRvIHJvb3QgKGdlc3RpdG8gZGEgU3Rvcnlib29rIGRlY29yYXRvclxuLy8gZSBkYWxsJ2FwcCBjb25zdW1lcikuIEkgY29tcG9uZW50aSBub24gZGV2b25vIGZhcmUgbnVsbGEgZGkgc3BlY2lhbGU6IGJhc3RhIGNoZVxuLy8gdXNpbm8gaSB0b2tlbiB2YXIoKSBlIHJpY2V2ZXJhbm5vIGF1dG9tYXRpY2FtZW50ZSBpIHZhbG9yaSBkYXJrLlxuXG5bZGF0YS10aGVtZT1cImRhcmtcIl0ge1xuICAvLyBOZXV0cmFsIChzY2FsYSBpbnZlcnRpdGEpXG4gIC0tY29sb3ItbmV1dHJhbC0wOiAgICMwZjE3MmE7XG4gIC0tY29sb3ItbmV1dHJhbC0xMDA6ICMxZTI5M2I7XG4gIC0tY29sb3ItbmV1dHJhbC0yMDA6ICMzMzQxNTU7XG4gIC0tY29sb3ItbmV1dHJhbC00MDA6ICM5NGEzYjg7XG4gIC0tY29sb3ItbmV1dHJhbC02MDA6ICNjYmQ1ZTE7XG4gIC0tY29sb3ItbmV1dHJhbC05MDA6ICNmOGZhZmM7XG5cbiAgLy8gU3VyZmFjZVxuICAtLWNvbG9yLXN1cmZhY2U6ICAgICAgICAgICMxZTI5M2I7XG4gIC0tY29sb3Itc3VyZmFjZS1lbGV2YXRlZDogIzI3MzU0OTtcblxuICAvLyBQcmltYXJ5IHNjYWxlIGRhcmsgKHBlciBpbCBkZWZhdWx0IGFjY2VudCBibHUg4oCUIGxlIHNmdW1hdHVyZSBjaGlhcmUgZGl2ZW50YW5vIHNjdXJlKVxuICAtLWNvbG9yLXByaW1hcnktNTA6ICAjMTcyNTU0O1xuICAtLWNvbG9yLXByaW1hcnktMTAwOiAjMWUzYThhO1xuICAvLyA0MDAgLyA1MDAgLyA2MDAgLyA3MDAgcmltYW5nb25vIGludmFyaWF0aSAoYWJiYXN0YW56YSBzYXR1cmkgc3UgYmcgc2N1cm8pXG5cbiAgLy8gQWNjZW50IGxpZ2h0OiB2YXJpYW50ZSBzY3VyYVxuICAtLWFjY2VudC1saWdodDogIzE3MjU1NDtcblxuICAvLyBTaGFkb3dzIChwacO5IGZvcnRpIHN1IGJnIHNjdXJvKVxuICAtLXNoYWRvdy1zbTogMCAxcHggMnB4IDAgcmdiKDAgMCAwIC8gMC40KTtcbiAgLS1zaGFkb3ctbWQ6IDAgNHB4IDZweCAtMXB4IHJnYigwIDAgMCAvIDAuNSksIDAgMnB4IDRweCAtMnB4IHJnYigwIDAgMCAvIDAuNCk7XG59XG4iLCJAdXNlIFwiLi4vLi4vc3R5bGVzL3Rva2Vuc1wiIGFzICo7XG5cbiRhY2NlbnQtdHJhY2s6IHZhcigtLXNsaWRlci1hY2NlbnQtdHJhY2ssIHZhcigtLWFjY2VudC10cmFjaykpO1xuJGFjY2VudC1yaW5nOiAgdmFyKC0tc2xpZGVyLWFjY2VudC1yaW5nLCAgdmFyKC0tYWNjZW50LXJpbmcpKTtcbiRhY2NlbnQtZ2xvdzogIHZhcigtLXNsaWRlci1hY2NlbnQtZ2xvdywgIHZhcigtLWFjY2VudC1nbG93KSk7XG5cbiRncm9vdmUtaGVpZ2h0OiAyMnB4O1xuJHJhaWwtaGVpZ2h0OiAgICA2cHg7XG4kdGh1bWItc2l6ZTogICAgMThweDtcbiRoaXQtem9uZTogICAgICAzNnB4O1xuXG4ud3JhcHBlciB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGdhcDogMTBweDtcbiAgZm9udC1mYW1pbHk6IHZhcigtLWZvbnQtZmFtaWx5LWJhc2UpO1xuICB1c2VyLXNlbGVjdDogbm9uZTtcbiAgLXdlYmtpdC11c2VyLXNlbGVjdDogbm9uZTtcbn1cblxuLmRpc2FibGVkIHtcbiAgb3BhY2l0eTogMC40NTtcbiAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG59XG5cbi5pY29uIHtcbiAgZGlzcGxheTogZmxleDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gIGNvbG9yOiB2YXIoLS1jb2xvci1uZXV0cmFsLTQwMCk7XG4gIGZsZXgtc2hyaW5rOiAwO1xuICBsaW5lLWhlaWdodDogMDtcbn1cblxuLy8g4pSA4pSAIEhpdCB6b25lIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLnRyYWNrQXJlYSB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgZmxleDogMTtcbiAgaGVpZ2h0OiAkaGl0LXpvbmU7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gIGN1cnNvcjogcG9pbnRlcjtcbn1cblxuLy8g4pSA4pSAIEdyb292ZSDigJQgdGhlIGNhcnZlZCBjaGFubmVsLCA+PSB0aHVtYiBzaXplIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLmdyb292ZSB7XG4gIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgd2lkdGg6IDEwMCU7XG4gIGhlaWdodDogJGdyb292ZS1oZWlnaHQ7XG4gIGJvcmRlci1yYWRpdXM6IHZhcigtLXJhZGl1cy1mdWxsKTtcbiAgYmFja2dyb3VuZDogdmFyKC0tY29sb3ItbmV1dHJhbC0zMDApO1xuICBkaXNwbGF5OiBmbGV4O1xuICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAvLyBwdXJlbHkgaW5zZXQ6IG5vIG91dGVyIHNoYWRvd1xuICBib3gtc2hhZG93OlxuICAgIGluc2V0IDAgNHB4IDhweCByZ2JhKDAsIDAsIDAsIDAuMTQpLFxuICAgIGluc2V0IDAgMnB4IDRweCByZ2JhKDAsIDAsIDAsIDAuMDYpLFxuICAgIGluc2V0IDAgLTJweCAzcHggcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjEwKTtcbn1cblxuLy8g4pSA4pSAIFJhaWwg4oCUIHRoaW4gbGluZSBpbnNpZGUgdGhlIGdyb292ZSB3aGVyZSBmaWxsIHJ1bnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4ucmFpbCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgbGVmdDogOHB4O1xuICByaWdodDogOHB4O1xuICBoZWlnaHQ6ICRyYWlsLWhlaWdodDtcbiAgYm9yZGVyLXJhZGl1czogdmFyKC0tcmFkaXVzLWZ1bGwpO1xuICBiYWNrZ3JvdW5kOiB2YXIoLS1jb2xvci1uZXV0cmFsLTQwMCk7XG4gIGJveC1zaGFkb3c6XG4gICAgaW5zZXQgMCAxcHggM3B4IHJnYmEoMCwgMCwgMCwgMC4zMCksXG4gICAgaW5zZXQgMCAxcHggMXB4IHJnYmEoMCwgMCwgMCwgMC4xOCk7XG4gIG92ZXJmbG93OiBoaWRkZW47XG59XG5cbi8vIOKUgOKUgCBGaWxsIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuLmZpbGwge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogMDtcbiAgbGVmdDogMDtcbiAgaGVpZ2h0OiAxMDAlO1xuICBiYWNrZ3JvdW5kOiAkYWNjZW50LXRyYWNrO1xuICBib3JkZXItcmFkaXVzOiB2YXIoLS1yYWRpdXMtZnVsbCk7XG4gIHRyYW5zaXRpb246IHdpZHRoIDYwbXMgbGluZWFyO1xufVxuXG4vLyDilIDilIAgVGh1bWIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4udGh1bWIge1xuICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gIHRvcDogNTAlO1xuICB3aWR0aDogJHRodW1iLXNpemU7XG4gIGhlaWdodDogJHRodW1iLXNpemU7XG4gIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gIGJhY2tncm91bmQ6ICNkZGUwZTY7XG4gIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC4xMCk7XG4gIGJveC1zaGFkb3c6IDAgMXB4IDNweCByZ2JhKDAsIDAsIDAsIDAuMjIpO1xuICBjdXJzb3I6IGdyYWI7XG4gIHRyYW5zaXRpb246IGJveC1zaGFkb3cgMTIwbXMgZWFzZSwgdHJhbnNmb3JtIDEyMG1zIGVhc2U7XG4gIG91dGxpbmU6IG5vbmU7XG4gIHotaW5kZXg6IDI7XG59XG5cbi50aHVtYjpmb2N1cy12aXNpYmxlIHtcbiAgYm94LXNoYWRvdzpcbiAgICAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjIyKSxcbiAgICAwIDAgMCAzcHggJGFjY2VudC1yaW5nO1xufVxuXG4udGh1bWJEcmFnZ2luZyB7XG4gIGN1cnNvcjogZ3JhYmJpbmc7XG4gIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUsIC01MCUpIHNjYWxlKDEuMDgpO1xuICBib3gtc2hhZG93OlxuICAgIDAgMXB4IDRweCByZ2JhKDAsIDAsIDAsIDAuMjgpLFxuICAgIDAgMCAwIDNweCAkYWNjZW50LXJpbmcsXG4gICAgMCAwIDAgNnB4ICRhY2NlbnQtZ2xvdztcbn1cblxuLy8g4pSA4pSAIFRvb2x0aXAg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4udG9vbHRpcCB7XG4gIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgYm90dG9tOiBjYWxjKDEwMCUgKyA2cHgpO1xuICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoLTUwJSk7XG4gIGJhY2tncm91bmQ6IHJnYmEoMTgsIDE4LCAyNiwgMC44NSk7XG4gIGJhY2tkcm9wLWZpbHRlcjogYmx1cig2cHgpO1xuICAtd2Via2l0LWJhY2tkcm9wLWZpbHRlcjogYmx1cig2cHgpO1xuICBjb2xvcjogI2ZmZjtcbiAgZm9udC1zaXplOiAxMXB4O1xuICBmb250LXdlaWdodDogNjAwO1xuICBsZXR0ZXItc3BhY2luZzogMC4wMmVtO1xuICBwYWRkaW5nOiAzcHggOHB4O1xuICBib3JkZXItcmFkaXVzOiA2cHg7XG4gIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gIHBvaW50ZXItZXZlbnRzOiBub25lO1xuICBvcGFjaXR5OiAwO1xuICB0cmFuc2l0aW9uOiBvcGFjaXR5IDEyMG1zIGVhc2U7XG4gIHotaW5kZXg6IDEwO1xuXG4gICY6OmFmdGVyIHtcbiAgICBjb250ZW50OiBcIlwiO1xuICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICB0b3A6IDEwMCU7XG4gICAgbGVmdDogNTAlO1xuICAgIHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtNTAlKTtcbiAgICBib3JkZXI6IDRweCBzb2xpZCB0cmFuc3BhcmVudDtcbiAgICBib3JkZXItdG9wLWNvbG9yOiByZ2JhKDE4LCAxOCwgMjYsIDAuODUpO1xuICB9XG59XG5cbi50b29sdGlwVmlzaWJsZSB7XG4gIG9wYWNpdHk6IDE7XG59XG5cbi8vIOKUgOKUgCBEYXJrIG1vZGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5bZGF0YS10aGVtZT1cImRhcmtcIl0ge1xuICAuZ3Jvb3ZlIHtcbiAgICBib3gtc2hhZG93OlxuICAgICAgaW5zZXQgMCAxcHggMCByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMDcpLFxuICAgICAgaW5zZXQgMCAzcHggN3B4IHJnYmEoMCwgMCwgMCwgMC4zMiksXG4gICAgICBpbnNldCAwIDFweCAzcHggcmdiYSgwLCAwLCAwLCAwLjIyKSxcbiAgICAgIGluc2V0IDAgLTJweCAzcHggcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA0KTtcbiAgfVxuXG4gIC50aHVtYiB7XG4gICAgYmFja2dyb3VuZDogIzRhNGY1YztcbiAgICBib3JkZXItY29sb3I6IHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wOCk7XG4gICAgYm94LXNoYWRvdzogMCAxcHggM3B4IHJnYmEoMCwgMCwgMCwgMC40NSk7XG4gIH1cblxuICAudGh1bWJEcmFnZ2luZyB7XG4gICAgYm94LXNoYWRvdzpcbiAgICAgIDAgMXB4IDRweCByZ2JhKDAsIDAsIDAsIDAuNSksXG4gICAgICAwIDAgMCAzcHggJGFjY2VudC1yaW5nLFxuICAgICAgMCAwIDAgNnB4ICRhY2NlbnQtZ2xvdztcbiAgfVxufVxuIl19 */","export function hexToHsl(hex: string): [number, number, number] {\n const r = parseInt(hex.slice(1, 3), 16) / 255;\n const g = parseInt(hex.slice(3, 5), 16) / 255;\n const b = parseInt(hex.slice(5, 7), 16) / 255;\n\n const max = Math.max(r, g, b);\n const min = Math.min(r, g, b);\n const l = (max + min) / 2;\n let h = 0;\n let s = 0;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r: h = ((g - b) / d + (g < b ? 6 : 0)) / 6; break;\n case g: h = ((b - r) / d + 2) / 6; break;\n case b: h = ((r - g) / d + 4) / 6; break;\n }\n }\n\n return [h * 360, s * 100, l * 100];\n}\n\nexport function hslToHex(h: number, s: number, l: number): string {\n const sl = s / 100;\n const ll = l / 100;\n const a = sl * Math.min(ll, 1 - ll);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n const color = ll - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);\n return Math.round(255 * color).toString(16).padStart(2, \"0\");\n };\n return `#${f(0)}${f(8)}${f(4)}`;\n}\n\nexport function hslToRgb(h: number, s: number, l: number): { r: number; g: number; b: number } {\n const sl = s / 100;\n const ll = l / 100;\n const a = sl * Math.min(ll, 1 - ll);\n const f = (n: number) => {\n const k = (n + h / 30) % 12;\n return Math.round(255 * (ll - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)));\n };\n return { r: f(0), g: f(8), b: f(4) };\n}\n\nexport function rgbToHsl(r: number, g: number, b: number): [number, number, number] {\n const rr = r / 255, gg = g / 255, bb = b / 255;\n const max = Math.max(rr, gg, bb);\n const min = Math.min(rr, gg, bb);\n const l = (max + min) / 2;\n let h = 0, s = 0;\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case rr: h = ((gg - bb) / d + (gg < bb ? 6 : 0)) / 6; break;\n case gg: h = ((bb - rr) / d + 2) / 6; break;\n case bb: h = ((rr - gg) / d + 4) / 6; break;\n }\n }\n return [h * 360, s * 100, l * 100];\n}\n\nfunction hslToRgba(h: number, s: number, l: number, alpha: number): string {\n const { r, g, b } = hslToRgb(h, s, l);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nexport interface AccentTokens {\n base: string;\n dot: string;\n track: string;\n ring: string;\n glow: string;\n light: string;\n}\n\nexport interface ColorValue {\n hex: string;\n hexa: string;\n hsl: string;\n hsla: string;\n rgb: string;\n rgba: string;\n h: number;\n s: number;\n l: number;\n a: number;\n}\n\nexport function buildColorValue(h: number, s: number, l: number, a: number): ColorValue {\n const { r, g, b } = hslToRgb(h, s, l);\n const hex = hslToHex(h, s, l);\n const alphaHex = Math.round(a * 255).toString(16).padStart(2, \"0\");\n const hR = Math.round(h), sR = Math.round(s), lR = Math.round(l);\n const aR = Math.round(a * 100) / 100;\n return {\n hex,\n hexa: `${hex}${alphaHex}`,\n hsl: `hsl(${hR}, ${sR}%, ${lR}%)`,\n hsla: `hsla(${hR}, ${sR}%, ${lR}%, ${aR})`,\n rgb: `rgb(${r}, ${g}, ${b})`,\n rgba: `rgba(${r}, ${g}, ${b}, ${aR})`,\n h, s, l, a,\n };\n}\n\nexport function deriveAccent(hex: string): AccentTokens {\n const [h, s, l] = hexToHsl(hex);\n return {\n base: hex,\n dot: hslToHex(h, s, Math.min(l + 12, 95)),\n track: hex,\n ring: hex,\n glow: hslToRgba(h, s, l, 0.3),\n light: hslToHex(h, Math.max(s - 20, 0), Math.min(l + 45, 96)),\n };\n}\n\nexport function accentToCssVars(\n tokens: AccentTokens,\n prefix: string\n): Record<string, string> {\n return {\n [`--${prefix}-accent`]: tokens.base,\n [`--${prefix}-accent-dot`]: tokens.dot,\n [`--${prefix}-accent-track`]: tokens.track,\n [`--${prefix}-accent-ring`]: tokens.ring,\n [`--${prefix}-accent-glow`]: tokens.glow,\n [`--${prefix}-accent-light`]: tokens.light,\n };\n}\n","import React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport styles from \"./SliderControl.module.scss\";\nimport { deriveAccent, accentToCssVars } from \"../../utils/color\";\n\nexport const VolumeDownIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M2 6h2l3-3v10L4 10H2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M10 5.5a3 3 0 0 1 0 5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport const VolumeUpIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M2 6h2l3-3v10L4 10H2a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1Z\"\n fill=\"currentColor\"\n />\n <path\n d=\"M10 5.5a3 3 0 0 1 0 5M12 3.5a6 6 0 0 1 0 9\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n);\n\nexport interface SliderControlProps {\n value?: number;\n defaultValue?: number;\n min?: number;\n max?: number;\n step?: number;\n onChange?: (value: number) => void;\n showTooltip?: \"always\" | \"drag\" | \"never\";\n leftIcon?: React.ReactNode;\n rightIcon?: React.ReactNode;\n /** CSS background value applied to the rail — replaces the fill with a full-width gradient */\n railBackground?: string;\n accent?: string;\n className?: string;\n disabled?: boolean;\n}\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.min(Math.max(v, min), max);\n}\n\nfunction snapToStep(v: number, min: number, step: number) {\n return Math.round((v - min) / step) * step + min;\n}\n\nexport const SliderControl: React.FC<SliderControlProps> = ({\n value: controlledValue,\n defaultValue = 50,\n min = 0,\n max = 100,\n step = 1,\n onChange,\n showTooltip = \"drag\",\n leftIcon,\n rightIcon,\n railBackground,\n accent,\n className,\n disabled = false,\n}) => {\n const isControlled = controlledValue !== undefined;\n const [internalValue, setInternalValue] = useState(defaultValue);\n const [isDragging, setIsDragging] = useState(false);\n const [isFocused, setIsFocused] = useState(false);\n const trackRef = useRef<HTMLDivElement>(null);\n const thumbRef = useRef<HTMLDivElement>(null);\n\n const value = isControlled ? controlledValue! : internalValue;\n const pct = (clamp(value, min, max) - min) / (max - min);\n\n const accentVars = accent\n ? accentToCssVars(deriveAccent(accent), \"slider\")\n : {};\n\n const setValue = useCallback(\n (next: number) => {\n const snapped = clamp(snapToStep(next, min, step), min, max);\n if (!isControlled) setInternalValue(snapped);\n onChange?.(snapped);\n },\n [isControlled, min, max, step, onChange]\n );\n\n const valueFromPointer = useCallback(\n (e: PointerEvent) => {\n const rect = trackRef.current!.getBoundingClientRect();\n const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);\n return min + ratio * (max - min);\n },\n [min, max]\n );\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (disabled) return;\n e.currentTarget.setPointerCapture(e.pointerId);\n setIsDragging(true);\n thumbRef.current?.focus();\n setValue(valueFromPointer(e.nativeEvent));\n },\n [disabled, setValue, valueFromPointer]\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent<HTMLDivElement>) => {\n if (!isDragging || disabled) return;\n setValue(valueFromPointer(e.nativeEvent));\n },\n [isDragging, disabled, setValue, valueFromPointer]\n );\n\n const handlePointerUp = useCallback(() => {\n setIsDragging(false);\n thumbRef.current?.blur();\n }, []);\n\n useEffect(() => {\n const el = trackRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n if (disabled) return;\n e.preventDefault();\n setValue(value + (e.deltaY < 0 ? step : -step));\n };\n el.addEventListener(\"wheel\", onWheel, { passive: false });\n return () => el.removeEventListener(\"wheel\", onWheel);\n }, [disabled, value, step, setValue]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return;\n const map: Record<string, number> = {\n ArrowRight: step,\n ArrowUp: step,\n ArrowLeft: -step,\n ArrowDown: -step,\n PageUp: step * 10,\n PageDown: -step * 10,\n };\n if (e.key === \"Home\") { setValue(min); e.preventDefault(); return; }\n if (e.key === \"End\") { setValue(max); e.preventDefault(); return; }\n if (map[e.key] !== undefined) {\n setValue(value + map[e.key]);\n e.preventDefault();\n }\n },\n [disabled, step, min, max, value, setValue]\n );\n\n const tooltipVisible =\n showTooltip === \"always\" ||\n (showTooltip === \"drag\" && (isDragging || isFocused));\n\n const displayValue = `${Math.round(value)}%`;\n\n // Clamp tooltip so it doesn't overflow the track edges\n const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;\n\n return (\n <div\n className={[styles.wrapper, disabled ? styles.disabled : \"\", className ?? \"\"].filter(Boolean).join(\" \")}\n style={accentVars as React.CSSProperties}\n >\n {leftIcon !== null && leftIcon !== undefined && (\n <span className={styles.icon}>{leftIcon}</span>\n )}\n\n <div\n ref={trackRef}\n className={styles.trackArea}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n <div className={styles.groove}>\n <div\n className={styles.rail}\n style={railBackground ? { background: railBackground } : undefined}\n >\n {!railBackground && (\n <div className={styles.fill} style={{ width: `${pct * 100}%` }} />\n )}\n </div>\n </div>\n\n <div\n ref={thumbRef}\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-valuenow={Math.round(value)}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-disabled={disabled}\n className={[styles.thumb, isDragging ? styles.thumbDragging : \"\"].filter(Boolean).join(\" \")}\n style={{ left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` }}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n />\n\n <div\n className={[styles.tooltip, tooltipVisible ? styles.tooltipVisible : \"\"].filter(Boolean).join(\" \")}\n style={{ left: tooltipOffset }}\n aria-hidden=\"true\"\n >\n {displayValue}\n </div>\n </div>\n\n {rightIcon !== null && rightIcon !== undefined && (\n <span className={styles.icon}>{rightIcon}</span>\n )}\n </div>\n );\n};\n\nSliderControl.displayName = \"SliderControl\";\n"]}