@fab1o978/react-ui 0.1.5 → 0.1.8
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/components/ColorPicker/index.cjs +207 -63
- package/dist/components/ColorPicker/index.cjs.map +1 -1
- package/dist/components/ColorPicker/index.css +200 -42
- package/dist/components/ColorPicker/index.css.map +1 -1
- package/dist/components/ColorPicker/index.js +207 -63
- package/dist/components/ColorPicker/index.js.map +1 -1
- package/dist/components/SliderControl/index.cjs +270 -0
- package/dist/components/SliderControl/index.cjs.map +1 -0
- package/dist/components/SliderControl/index.css +202 -0
- package/dist/components/SliderControl/index.css.map +1 -0
- package/dist/components/SliderControl/index.d.cts +22 -0
- package/dist/components/SliderControl/index.d.ts +22 -0
- package/dist/components/SliderControl/index.js +268 -0
- package/dist/components/SliderControl/index.js.map +1 -0
- package/dist/index.cjs +208 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +200 -42
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +208 -64
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,268 @@
|
|
|
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
|
+
showPercentage = false,
|
|
109
|
+
leftIcon,
|
|
110
|
+
rightIcon,
|
|
111
|
+
railBackground,
|
|
112
|
+
accent,
|
|
113
|
+
className,
|
|
114
|
+
disabled = false
|
|
115
|
+
}) => {
|
|
116
|
+
const isControlled = controlledValue !== void 0;
|
|
117
|
+
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
118
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
119
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
120
|
+
const trackRef = useRef(null);
|
|
121
|
+
const thumbRef = useRef(null);
|
|
122
|
+
const value = isControlled ? controlledValue : internalValue;
|
|
123
|
+
const pct = (clamp(value, min, max) - min) / (max - min);
|
|
124
|
+
const accentVars = accent ? accentToCssVars(deriveAccent(accent), "slider") : {};
|
|
125
|
+
const setValue = useCallback(
|
|
126
|
+
(next) => {
|
|
127
|
+
const snapped = clamp(snapToStep(next, min, step), min, max);
|
|
128
|
+
if (!isControlled) setInternalValue(snapped);
|
|
129
|
+
onChange?.(snapped);
|
|
130
|
+
},
|
|
131
|
+
[isControlled, min, max, step, onChange]
|
|
132
|
+
);
|
|
133
|
+
const valueFromPointer = useCallback(
|
|
134
|
+
(e) => {
|
|
135
|
+
const rect = trackRef.current.getBoundingClientRect();
|
|
136
|
+
const ratio = clamp((e.clientX - rect.left) / rect.width, 0, 1);
|
|
137
|
+
return min + ratio * (max - min);
|
|
138
|
+
},
|
|
139
|
+
[min, max]
|
|
140
|
+
);
|
|
141
|
+
const handlePointerDown = useCallback(
|
|
142
|
+
(e) => {
|
|
143
|
+
if (disabled) return;
|
|
144
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
145
|
+
setIsDragging(true);
|
|
146
|
+
thumbRef.current?.focus();
|
|
147
|
+
setValue(valueFromPointer(e.nativeEvent));
|
|
148
|
+
},
|
|
149
|
+
[disabled, setValue, valueFromPointer]
|
|
150
|
+
);
|
|
151
|
+
const handlePointerMove = useCallback(
|
|
152
|
+
(e) => {
|
|
153
|
+
if (!isDragging || disabled) return;
|
|
154
|
+
setValue(valueFromPointer(e.nativeEvent));
|
|
155
|
+
},
|
|
156
|
+
[isDragging, disabled, setValue, valueFromPointer]
|
|
157
|
+
);
|
|
158
|
+
const handlePointerUp = useCallback(() => {
|
|
159
|
+
setIsDragging(false);
|
|
160
|
+
thumbRef.current?.blur();
|
|
161
|
+
}, []);
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
const el = trackRef.current;
|
|
164
|
+
if (!el) return;
|
|
165
|
+
const onWheel = (e) => {
|
|
166
|
+
if (disabled) return;
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
setValue(value + (e.deltaY < 0 ? step : -step));
|
|
169
|
+
};
|
|
170
|
+
el.addEventListener("wheel", onWheel, { passive: false });
|
|
171
|
+
return () => el.removeEventListener("wheel", onWheel);
|
|
172
|
+
}, [disabled, value, step, setValue]);
|
|
173
|
+
const handleKeyDown = useCallback(
|
|
174
|
+
(e) => {
|
|
175
|
+
if (disabled) return;
|
|
176
|
+
const map = {
|
|
177
|
+
ArrowRight: step,
|
|
178
|
+
ArrowUp: step,
|
|
179
|
+
ArrowLeft: -step,
|
|
180
|
+
ArrowDown: -step,
|
|
181
|
+
PageUp: step * 10,
|
|
182
|
+
PageDown: -step * 10
|
|
183
|
+
};
|
|
184
|
+
if (e.key === "Home") {
|
|
185
|
+
setValue(min);
|
|
186
|
+
e.preventDefault();
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (e.key === "End") {
|
|
190
|
+
setValue(max);
|
|
191
|
+
e.preventDefault();
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (map[e.key] !== void 0) {
|
|
195
|
+
setValue(value + map[e.key]);
|
|
196
|
+
e.preventDefault();
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
[disabled, step, min, max, value, setValue]
|
|
200
|
+
);
|
|
201
|
+
const tooltipVisible = showTooltip === "always" || showTooltip === "drag" && (isDragging || isFocused);
|
|
202
|
+
const decimals = step < 1 ? Math.ceil(-Math.log10(step)) : 0;
|
|
203
|
+
const displayValue = showPercentage ? `${Math.round((value - min) / (max - min) * 100)}%` : value.toFixed(decimals);
|
|
204
|
+
const tooltipOffset = `calc(${pct * 100}% + ${(0.5 - pct) * 20}px)`;
|
|
205
|
+
return /* @__PURE__ */ jsxs(
|
|
206
|
+
"div",
|
|
207
|
+
{
|
|
208
|
+
className: [SliderControl_module_default.wrapper, disabled ? SliderControl_module_default.disabled : "", className ?? ""].filter(Boolean).join(" "),
|
|
209
|
+
style: accentVars,
|
|
210
|
+
children: [
|
|
211
|
+
leftIcon !== null && leftIcon !== void 0 && /* @__PURE__ */ jsx("span", { className: SliderControl_module_default.icon, children: leftIcon }),
|
|
212
|
+
/* @__PURE__ */ jsxs(
|
|
213
|
+
"div",
|
|
214
|
+
{
|
|
215
|
+
ref: trackRef,
|
|
216
|
+
className: SliderControl_module_default.trackArea,
|
|
217
|
+
onPointerDown: handlePointerDown,
|
|
218
|
+
onPointerMove: handlePointerMove,
|
|
219
|
+
onPointerUp: handlePointerUp,
|
|
220
|
+
onPointerCancel: handlePointerUp,
|
|
221
|
+
children: [
|
|
222
|
+
/* @__PURE__ */ jsx("div", { className: SliderControl_module_default.groove, children: /* @__PURE__ */ jsx(
|
|
223
|
+
"div",
|
|
224
|
+
{
|
|
225
|
+
className: SliderControl_module_default.rail,
|
|
226
|
+
style: railBackground ? { background: railBackground } : void 0,
|
|
227
|
+
children: !railBackground && /* @__PURE__ */ jsx("div", { className: SliderControl_module_default.fill, style: { width: `${pct * 100}%` } })
|
|
228
|
+
}
|
|
229
|
+
) }),
|
|
230
|
+
/* @__PURE__ */ jsx(
|
|
231
|
+
"div",
|
|
232
|
+
{
|
|
233
|
+
ref: thumbRef,
|
|
234
|
+
role: "slider",
|
|
235
|
+
tabIndex: disabled ? -1 : 0,
|
|
236
|
+
"aria-valuenow": Math.round(value),
|
|
237
|
+
"aria-valuemin": min,
|
|
238
|
+
"aria-valuemax": max,
|
|
239
|
+
"aria-disabled": disabled,
|
|
240
|
+
className: [SliderControl_module_default.thumb, isDragging ? SliderControl_module_default.thumbDragging : ""].filter(Boolean).join(" "),
|
|
241
|
+
style: { left: `calc(${pct * 100}% + ${(0.5 - pct) * 24}px)` },
|
|
242
|
+
onKeyDown: handleKeyDown,
|
|
243
|
+
onFocus: () => setIsFocused(true),
|
|
244
|
+
onBlur: () => setIsFocused(false)
|
|
245
|
+
}
|
|
246
|
+
),
|
|
247
|
+
/* @__PURE__ */ jsx(
|
|
248
|
+
"div",
|
|
249
|
+
{
|
|
250
|
+
className: [SliderControl_module_default.tooltip, tooltipVisible ? SliderControl_module_default.tooltipVisible : ""].filter(Boolean).join(" "),
|
|
251
|
+
style: { left: tooltipOffset },
|
|
252
|
+
"aria-hidden": "true",
|
|
253
|
+
children: displayValue
|
|
254
|
+
}
|
|
255
|
+
)
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
rightIcon !== null && rightIcon !== void 0 && /* @__PURE__ */ jsx("span", { className: SliderControl_module_default.icon, children: rightIcon })
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
);
|
|
263
|
+
};
|
|
264
|
+
SliderControl.displayName = "SliderControl";
|
|
265
|
+
|
|
266
|
+
export { SliderControl };
|
|
267
|
+
//# sourceMappingURL=index.js.map
|
|
268
|
+
//# 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 showPercentage?: boolean;\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 showPercentage = false,\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 decimals = step < 1 ? Math.ceil(-Math.log10(step)) : 0;\n const displayValue = showPercentage\n ? `${Math.round(((value - min) / (max - min)) * 100)}%`\n : value.toFixed(decimals);\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"]}
|