@ambientcss/components 1.2.1 → 2.0.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/index.cjs +97 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +97 -28
- package/dist/index.js.map +1 -1
- package/dist/styles.css +311 -66
- package/package.json +2 -2
- package/src/components/AmbientButton.tsx +27 -4
- package/src/components/AmbientFader.tsx +3 -7
- package/src/components/AmbientKnob.tsx +95 -9
- package/src/components/AmbientSlider.tsx +3 -9
- package/src/components/AmbientSwitch.tsx +5 -2
- package/src/index.ts +2 -2
- package/src/styles.css +311 -66
package/dist/index.js
CHANGED
|
@@ -52,18 +52,34 @@ function AmbientPanel({ className, material = "matte", ...props }) {
|
|
|
52
52
|
|
|
53
53
|
// src/components/AmbientButton.tsx
|
|
54
54
|
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
55
|
-
function AmbientButton({
|
|
55
|
+
function AmbientButton({
|
|
56
|
+
className,
|
|
57
|
+
children,
|
|
58
|
+
material = "matte",
|
|
59
|
+
shape = "pill",
|
|
60
|
+
...props
|
|
61
|
+
}) {
|
|
56
62
|
return /* @__PURE__ */ jsx3(
|
|
57
63
|
"button",
|
|
58
64
|
{
|
|
59
65
|
type: "button",
|
|
60
66
|
className: cn(
|
|
61
|
-
"
|
|
62
|
-
|
|
67
|
+
"amb-button amb-groove ambx-button",
|
|
68
|
+
shape === "round" && "amb-button-round",
|
|
69
|
+
shape === "square" && "amb-button-square",
|
|
63
70
|
className
|
|
64
71
|
),
|
|
65
72
|
...props,
|
|
66
|
-
children
|
|
73
|
+
children: /* @__PURE__ */ jsx3(
|
|
74
|
+
"span",
|
|
75
|
+
{
|
|
76
|
+
className: cn(
|
|
77
|
+
"amb-button-cap ambient amb-chamfer amb-surface amb-heading-3",
|
|
78
|
+
material === "matte" ? "amb-mat-matte" : material === "shiny" ? "amb-mat-shiny" : "amb-mat-glass"
|
|
79
|
+
),
|
|
80
|
+
children
|
|
81
|
+
}
|
|
82
|
+
)
|
|
67
83
|
}
|
|
68
84
|
);
|
|
69
85
|
}
|
|
@@ -95,8 +111,8 @@ function AmbientSwitch({
|
|
|
95
111
|
"aria-checked": active,
|
|
96
112
|
"aria-labelledby": label ? labelId : props["aria-labelledby"],
|
|
97
113
|
className: cn(
|
|
98
|
-
"
|
|
99
|
-
active
|
|
114
|
+
"amb-switch",
|
|
115
|
+
active && "amb-switch-on",
|
|
100
116
|
"ambx-switch",
|
|
101
117
|
`ambx-switch-${size}`,
|
|
102
118
|
className
|
|
@@ -116,6 +132,7 @@ function AmbientSwitch({
|
|
|
116
132
|
style: typeof led === "string" ? { "--amb-led-color": led } : void 0
|
|
117
133
|
}
|
|
118
134
|
) : null,
|
|
135
|
+
/* @__PURE__ */ jsx4("span", { className: "amb-switch-track amb-groove", children: /* @__PURE__ */ jsx4("span", { className: "amb-switch-pill ambient amb-fillet amb-surface-convex" }) }),
|
|
119
136
|
children
|
|
120
137
|
]
|
|
121
138
|
}
|
|
@@ -130,6 +147,47 @@ function AmbientSwitch({
|
|
|
130
147
|
// src/components/AmbientKnob.tsx
|
|
131
148
|
import { useId as useId2, useRef } from "react";
|
|
132
149
|
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
150
|
+
var KNURLS = {
|
|
151
|
+
/* 36 ribs — the grounded referent knob (dot and line variants) */
|
|
152
|
+
standard: { teeth: 36, root: 0.468, rise: 0.12, fall: [0.5, 0.62] },
|
|
153
|
+
/* 14 broad flutes with deeper roots (OP-Z-style flute variant) */
|
|
154
|
+
flute: { teeth: 14, root: 0.44, rise: 0.08, fall: [0.72, 0.8] },
|
|
155
|
+
/* 48-rib fine knurl, shallower (cap and wheel variants) */
|
|
156
|
+
fine: { teeth: 48, root: 0.476, rise: 0.12, fall: [0.5, 0.62] }
|
|
157
|
+
};
|
|
158
|
+
function knurlPath({ teeth, root, rise, fall }) {
|
|
159
|
+
const outer = 0.5;
|
|
160
|
+
const pitch = Math.PI * 2 / teeth;
|
|
161
|
+
const pts = [];
|
|
162
|
+
for (let i = 0; i < teeth; i++) {
|
|
163
|
+
const a = i * pitch;
|
|
164
|
+
const tooth = [
|
|
165
|
+
[0, root],
|
|
166
|
+
[rise, outer],
|
|
167
|
+
[fall[0], outer],
|
|
168
|
+
[fall[1], root]
|
|
169
|
+
];
|
|
170
|
+
for (const [frac, radius] of tooth) {
|
|
171
|
+
const t = a + frac * pitch;
|
|
172
|
+
pts.push(
|
|
173
|
+
`${(0.5 + radius * Math.cos(t)).toFixed(4)} ${(0.5 + radius * Math.sin(t)).toFixed(4)}`
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return `M${pts.join(" L")} Z`;
|
|
178
|
+
}
|
|
179
|
+
var KNURL_PATHS = {
|
|
180
|
+
standard: knurlPath(KNURLS.standard),
|
|
181
|
+
flute: knurlPath(KNURLS.flute),
|
|
182
|
+
fine: knurlPath(KNURLS.fine)
|
|
183
|
+
};
|
|
184
|
+
var VARIANT_FAMILY = {
|
|
185
|
+
dot: "standard",
|
|
186
|
+
line: "standard",
|
|
187
|
+
flute: "flute",
|
|
188
|
+
cap: "fine",
|
|
189
|
+
wheel: "fine"
|
|
190
|
+
};
|
|
133
191
|
function clamp(value, min, max) {
|
|
134
192
|
return Math.min(max, Math.max(min, value));
|
|
135
193
|
}
|
|
@@ -140,14 +198,17 @@ function AmbientKnob({
|
|
|
140
198
|
step = 1,
|
|
141
199
|
label,
|
|
142
200
|
material,
|
|
201
|
+
variant = "dot",
|
|
143
202
|
onChange,
|
|
144
203
|
className,
|
|
145
204
|
...props
|
|
146
205
|
}) {
|
|
147
206
|
const id = useId2();
|
|
207
|
+
const clipId = `amb-knurl-${id.replace(/:/g, "")}`;
|
|
148
208
|
const draggingRef = useRef(false);
|
|
149
209
|
const knobRef = useRef(null);
|
|
150
210
|
const safeStep = step > 0 ? step : 1;
|
|
211
|
+
const family = VARIANT_FAMILY[variant];
|
|
151
212
|
const percent = (value - min) / (max - min || 1);
|
|
152
213
|
const rotation = percent * 270 - 135;
|
|
153
214
|
const pointerToValue = (event) => {
|
|
@@ -203,11 +264,11 @@ function AmbientKnob({
|
|
|
203
264
|
}
|
|
204
265
|
};
|
|
205
266
|
return /* @__PURE__ */ jsxs2("div", { className: cn("ambx-stack", className), ...props, children: [
|
|
206
|
-
/* @__PURE__ */
|
|
267
|
+
/* @__PURE__ */ jsxs2(
|
|
207
268
|
"div",
|
|
208
269
|
{
|
|
209
270
|
ref: knobRef,
|
|
210
|
-
className:
|
|
271
|
+
className: "amb-knob ambx-knob",
|
|
211
272
|
role: "slider",
|
|
212
273
|
"aria-label": label,
|
|
213
274
|
"aria-valuemin": min,
|
|
@@ -231,11 +292,28 @@ function AmbientKnob({
|
|
|
231
292
|
draggingRef.current = false;
|
|
232
293
|
},
|
|
233
294
|
onKeyDown,
|
|
234
|
-
children:
|
|
235
|
-
/* @__PURE__ */ jsx5("
|
|
236
|
-
/* @__PURE__ */ jsx5("span", { className: "amb-
|
|
237
|
-
/* @__PURE__ */
|
|
238
|
-
|
|
295
|
+
children: [
|
|
296
|
+
/* @__PURE__ */ jsx5("svg", { width: 0, height: 0, style: { position: "absolute" }, "aria-hidden": true, focusable: false, children: /* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsx5("clipPath", { id: clipId, clipPathUnits: "objectBoundingBox", children: /* @__PURE__ */ jsx5("path", { d: KNURL_PATHS[family] }) }) }) }),
|
|
297
|
+
/* @__PURE__ */ jsx5("span", { className: "amb-knob-body ambient amb-thickness-2 amb-surface" }),
|
|
298
|
+
/* @__PURE__ */ jsxs2(
|
|
299
|
+
"div",
|
|
300
|
+
{
|
|
301
|
+
className: cn(
|
|
302
|
+
"ambx-knob-rotation amb-knob-face",
|
|
303
|
+
family === "flute" && "amb-knob-face-flute",
|
|
304
|
+
family === "fine" && "amb-knob-face-fine",
|
|
305
|
+
variant === "cap" && "amb-knob-face-cap",
|
|
306
|
+
material && `amb-mat-${material}`
|
|
307
|
+
),
|
|
308
|
+
style: { transform: `rotate(${rotation}deg)`, clipPath: `url(#${clipId})` },
|
|
309
|
+
children: [
|
|
310
|
+
variant === "dot" ? /* @__PURE__ */ jsx5("span", { className: "amb-knob-indicator-dot" }) : null,
|
|
311
|
+
variant === "line" ? /* @__PURE__ */ jsx5("span", { className: "amb-knob-indicator-line" }) : null,
|
|
312
|
+
variant === "flute" ? /* @__PURE__ */ jsx5("span", { className: "amb-knob-indicator-dot amb-knob-indicator-dot-center" }) : null
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
]
|
|
239
317
|
}
|
|
240
318
|
),
|
|
241
319
|
label ? /* @__PURE__ */ jsx5("span", { id, className: "ambx-label", children: label }) : null
|
|
@@ -317,7 +395,7 @@ function AmbientFader({
|
|
|
317
395
|
/* @__PURE__ */ jsx6(
|
|
318
396
|
"div",
|
|
319
397
|
{
|
|
320
|
-
className: "amb-fader ambx-fader",
|
|
398
|
+
className: "amb-fader amb-groove ambx-fader",
|
|
321
399
|
ref: trackRef,
|
|
322
400
|
role: "slider",
|
|
323
401
|
"aria-label": label,
|
|
@@ -336,13 +414,9 @@ function AmbientFader({
|
|
|
336
414
|
children: /* @__PURE__ */ jsx6(
|
|
337
415
|
"div",
|
|
338
416
|
{
|
|
339
|
-
className: cn("amb-fader-thumb ambient amb-fillet
|
|
417
|
+
className: cn("amb-fader-thumb ambient amb-fillet ambx-fader-thumb", material !== "glass" && "amb-surface-concave", material && `amb-mat-${material}`),
|
|
340
418
|
style: { top: `${100 - percent}%` },
|
|
341
|
-
children: /* @__PURE__ */
|
|
342
|
-
/* @__PURE__ */ jsx6("span", { className: "amb-fader-dot" }),
|
|
343
|
-
/* @__PURE__ */ jsx6("span", { className: "amb-fader-dot" }),
|
|
344
|
-
/* @__PURE__ */ jsx6("span", { className: "amb-fader-dot" })
|
|
345
|
-
] })
|
|
419
|
+
children: /* @__PURE__ */ jsx6("span", { className: "amb-fader-gripline" })
|
|
346
420
|
}
|
|
347
421
|
)
|
|
348
422
|
}
|
|
@@ -426,7 +500,7 @@ function AmbientSlider({
|
|
|
426
500
|
/* @__PURE__ */ jsx7(
|
|
427
501
|
"div",
|
|
428
502
|
{
|
|
429
|
-
className: "amb-slider ambx-slider",
|
|
503
|
+
className: "amb-slider amb-groove ambx-slider",
|
|
430
504
|
ref: trackRef,
|
|
431
505
|
role: "slider",
|
|
432
506
|
"aria-label": label,
|
|
@@ -445,13 +519,8 @@ function AmbientSlider({
|
|
|
445
519
|
children: /* @__PURE__ */ jsx7(
|
|
446
520
|
"div",
|
|
447
521
|
{
|
|
448
|
-
className: cn("amb-slider-thumb ambient amb-fillet
|
|
449
|
-
style: { left: `${percent}%` }
|
|
450
|
-
children: /* @__PURE__ */ jsxs4("div", { className: "amb-slider-grip", children: [
|
|
451
|
-
/* @__PURE__ */ jsx7("span", { className: "amb-fader-dot" }),
|
|
452
|
-
/* @__PURE__ */ jsx7("span", { className: "amb-fader-dot" }),
|
|
453
|
-
/* @__PURE__ */ jsx7("span", { className: "amb-fader-dot" })
|
|
454
|
-
] })
|
|
522
|
+
className: cn("amb-slider-thumb ambient amb-fillet ambx-slider-thumb", material !== "glass" && "amb-surface-convex", material && `amb-mat-${material}`),
|
|
523
|
+
style: { left: `${percent}%` }
|
|
455
524
|
}
|
|
456
525
|
)
|
|
457
526
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/AmbientProvider.tsx","../src/lib/cn.ts","../src/components/AmbientPanel.tsx","../src/components/AmbientButton.tsx","../src/components/AmbientSwitch.tsx","../src/components/AmbientKnob.tsx","../src/components/AmbientFader.tsx","../src/components/AmbientSlider.tsx"],"sourcesContent":["import type { CSSProperties, PropsWithChildren } from \"react\";\n\nexport type AmbientTheme = {\n lightX?: number;\n lightY?: number;\n keyLight?: number;\n fillLight?: number;\n lightHue?: number;\n lightSaturation?: number;\n highlightColor?: string;\n lumeHue?: number;\n};\n\nexport type AmbientProviderProps = PropsWithChildren<{\n className?: string;\n style?: CSSProperties;\n theme?: AmbientTheme;\n}>;\n\nconst VAR_MAP: Record<string, keyof AmbientTheme> = {\n \"--amb-light-x\": \"lightX\",\n \"--amb-light-y\": \"lightY\",\n \"--amb-key-light-intensity\": \"keyLight\",\n \"--amb-fill-light-intensity\": \"fillLight\",\n \"--amb-light-hue\": \"lightHue\",\n \"--amb-light-saturation\": \"lightSaturation\",\n \"--amb-highlight-color\": \"highlightColor\",\n \"--amb-lume-hue\": \"lumeHue\",\n};\n\nexport function AmbientProvider({ children, className, style, theme }: AmbientProviderProps) {\n const themeVars: Record<string, string> = {};\n for (const [varName, key] of Object.entries(VAR_MAP)) {\n const value = theme?.[key];\n if (value !== undefined) {\n themeVars[varName] = key === \"lightSaturation\" ? `${value}%` : String(value);\n }\n }\n // Derived variables must be re-declared here so they recompute using the\n // overridden input variables on this element rather than inheriting the\n // already-resolved values from :root.\n themeVars[\"--amb-lume\"] = [\n \"color-mix(in oklab,\",\n \"hsl(var(--amb-lume-hue) 100% 74%) calc(clamp(0, (0.5 - var(--amb-key-light-intensity)) / 0.2, 1) * 100%),\",\n \"hsl(var(--amb-light-hue) var(--amb-light-saturation)\",\n \"calc((1 - sign(var(--amb-key-light-intensity) - 0.5)) * 50% + 25%)))\",\n ].join(\" \");\n themeVars[\"--amb-label\"] =\n \"hsl(var(--amb-light-hue) var(--amb-light-saturation) calc((1 - var(--amb-key-light-intensity)) * 60% + 20%))\";\n const mergedStyle = { ...themeVars, ...style } as CSSProperties;\n\n return (\n <div className={className} style={mergedStyle}>\n {children}\n </div>\n );\n}\n","export function cn(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(\" \");\n}\n","import type { HTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface AmbientPanelProps extends HTMLAttributes<HTMLDivElement> {\n material?: \"matte\" | \"shiny\" | \"glass\";\n}\n\nexport function AmbientPanel({ className, material = \"matte\", ...props }: AmbientPanelProps) {\n return (\n <div\n className={cn(\n \"ambient amb-surface amb-chamfer amb-elevation-2 ambx-panel\",\n material === \"matte\" ? \"amb-mat-matte\" : material === \"shiny\" ? \"amb-mat-shiny\" : \"amb-mat-glass\",\n className\n )}\n {...props}\n />\n );\n}\n","import type { ButtonHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface AmbientButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n material?: \"matte\" | \"shiny\" | \"glass\";\n}\n\nexport function AmbientButton({ className, children, material = \"matte\", ...props }: AmbientButtonProps) {\n return (\n <button\n type=\"button\"\n className={cn(\n \"ambient amb-button amb-chamfer amb-elevation-1 ambx-button amb-heading-3\",\n material === \"matte\" ? \"amb-mat-matte\" : material === \"shiny\" ? \"amb-mat-shiny\" : \"amb-mat-glass\",\n className\n )}\n {...props}\n >\n {children}\n </button>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ButtonHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientSwitchSize = \"sm\" | \"md\" | \"lg\";\n\nexport type AmbientSwitchProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\"> & {\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n size?: AmbientSwitchSize;\n label?: string;\n /** Show a small LED indicator that lights up when the switch is on. Pass `true` for default green or a CSS color string. */\n led?: boolean | string;\n};\n\nexport function AmbientSwitch({\n className,\n checked,\n defaultChecked,\n onCheckedChange,\n onClick,\n size = \"md\",\n label,\n led,\n children,\n ...props\n}: AmbientSwitchProps) {\n const labelId = useId();\n const isControlled = checked !== undefined;\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const active = isControlled ? (checked ?? false) : internalChecked;\n\n const button = (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={active}\n aria-labelledby={label ? labelId : props[\"aria-labelledby\"]}\n className={cn(\n \"ambient amb-switch amb-chamfer amb-elevation-1 amb-heading-3\",\n active ? \"amb-surface-convex amb-switch-on\" : \"amb-surface-concave\",\n \"ambx-switch\",\n `ambx-switch-${size}`,\n className\n )}\n onClick={(event) => {\n const next = !active;\n if (!isControlled) setInternalChecked(next);\n onCheckedChange?.(next);\n onClick?.(event);\n }}\n {...props}\n >\n {led ? (\n <span\n className={cn(\"amb-led\", !active && \"amb-led-off\")}\n style={typeof led === \"string\" ? { \"--amb-led-color\": led } as React.CSSProperties : undefined}\n />\n ) : null}\n {children}\n </button>\n );\n\n if (!label) return button;\n\n return (\n <div className=\"ambx-stack\">\n {button}\n <span id={labelId} className=\"ambx-label\">\n {label}\n </span>\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientKnobProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientKnob({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n onChange,\n className,\n ...props\n}: AmbientKnobProps) {\n const id = useId();\n const draggingRef = useRef(false);\n const knobRef = useRef<HTMLDivElement>(null);\n const safeStep = step > 0 ? step : 1;\n\n const percent = (value - min) / (max - min || 1);\n const rotation = percent * 270 - 135;\n\n // Convert pointer position to a knob angle in [-180, 180] where 0 = up,\n // positive = clockwise. The knob's active range is [-135, 135] (270°),\n // with the dead zone at the bottom (~135° to ~225° i.e. past ±135°).\n const pointerToValue = (event: PointerEvent<HTMLDivElement>) => {\n const rect = knobRef.current!.getBoundingClientRect();\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n // atan2 with screen coords: 0=right, 90=down; add 90 to rotate so 0=up\n const atan2Deg = Math.atan2(event.clientY - cy, event.clientX - cx) * (180 / Math.PI);\n let angle = atan2Deg + 90;\n // Normalize to [-180, 180]\n if (angle > 180) angle -= 360;\n\n // Clamp dead zone based on current value position\n if (angle < -135 || angle > 135) {\n angle = percent >= 0.5 ? 135 : -135;\n }\n\n const range = max - min;\n const raw = min + ((angle + 135) / 270) * range;\n const snapped = Math.round(raw / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n ref={knobRef}\n className={cn(\"ambient amb-knob amb-chamfer amb-elevation-2 amb-surface ambx-knob\", material && `amb-mat-${material}`)}\n role=\"slider\"\n aria-label={label}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-labelledby={label ? id : undefined}\n aria-orientation=\"vertical\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n draggingRef.current = true;\n pointerToValue(event);\n }}\n onPointerMove={(event) => {\n if (draggingRef.current) pointerToValue(event);\n }}\n onPointerUp={() => {\n draggingRef.current = false;\n }}\n onPointerCancel={() => {\n draggingRef.current = false;\n }}\n onKeyDown={onKeyDown}\n >\n <div className=\"ambx-knob-rotation\" style={{ transform: `rotate(${rotation}deg)` }}>\n <div className=\"amb-knob-indicator\">\n <div className=\"amb-knob-grip\">\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n </div>\n </div>\n </div>\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientFaderProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientFader({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n onChange,\n className,\n ...props\n}: AmbientFaderProps) {\n const id = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n const safeStep = step > 0 ? step : 1;\n\n const percent = ((value - min) / (max - min || 1)) * 100;\n\n const updateFromClientY = (clientY: number) => {\n const track = trackRef.current;\n if (!track) return;\n\n const rect = track.getBoundingClientRect();\n const ratio = 1 - (clientY - rect.top) / rect.height;\n const nextValue = min + clamp(ratio, 0, 1) * (max - min);\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.buttons !== 1) return;\n updateFromClientY(event.clientY);\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n className=\"amb-fader ambx-fader\"\n ref={trackRef}\n role=\"slider\"\n aria-label={label}\n aria-labelledby={label ? id : undefined}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-orientation=\"vertical\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n updateFromClientY(event.clientY);\n }}\n onPointerMove={onPointerMove}\n onKeyDown={onKeyDown}\n >\n <div\n className={cn(\"amb-fader-thumb ambient amb-fillet amb-elevation-1 ambx-fader-thumb\", material !== \"glass\" && \"amb-surface-concave\", material && `amb-mat-${material}`)}\n style={{ top: `${100 - percent}%` }}\n >\n <div className=\"amb-fader-grip\">\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n </div>\n </div>\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientSliderProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientSlider({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n onChange,\n className,\n ...props\n}: AmbientSliderProps) {\n const id = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n const safeStep = step > 0 ? step : 1;\n\n const percent = ((value - min) / (max - min || 1)) * 100;\n\n const updateFromClientX = (clientX: number) => {\n const track = trackRef.current;\n if (!track) return;\n\n const rect = track.getBoundingClientRect();\n const ratio = (clientX - rect.left) / rect.width;\n const nextValue = min + clamp(ratio, 0, 1) * (max - min);\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowRight\":\n case \"ArrowUp\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowLeft\":\n case \"ArrowDown\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.buttons !== 1) return;\n updateFromClientX(event.clientX);\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n className=\"amb-slider ambx-slider\"\n ref={trackRef}\n role=\"slider\"\n aria-label={label}\n aria-labelledby={label ? id : undefined}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-orientation=\"horizontal\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n updateFromClientX(event.clientX);\n }}\n onPointerMove={onPointerMove}\n onKeyDown={onKeyDown}\n >\n <div\n className={cn(\"amb-slider-thumb ambient amb-fillet amb-elevation-1 ambx-slider-thumb\", material !== \"glass\" && \"amb-surface-concave-h\", material && `amb-mat-${material}`)}\n style={{ left: `${percent}%` }}\n >\n <div className=\"amb-slider-grip\">\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n <span className=\"amb-fader-dot\" />\n </div>\n </div>\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","useId","jsx","jsxs","useId","useId","useRef","jsx","jsxs","clamp","useId","useRef","useId","useRef","jsx","jsxs","clamp","useId","useRef"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/AmbientProvider.tsx","../src/lib/cn.ts","../src/components/AmbientPanel.tsx","../src/components/AmbientButton.tsx","../src/components/AmbientSwitch.tsx","../src/components/AmbientKnob.tsx","../src/components/AmbientFader.tsx","../src/components/AmbientSlider.tsx"],"sourcesContent":["import type { CSSProperties, PropsWithChildren } from \"react\";\n\nexport type AmbientTheme = {\n lightX?: number;\n lightY?: number;\n keyLight?: number;\n fillLight?: number;\n lightHue?: number;\n lightSaturation?: number;\n highlightColor?: string;\n lumeHue?: number;\n};\n\nexport type AmbientProviderProps = PropsWithChildren<{\n className?: string;\n style?: CSSProperties;\n theme?: AmbientTheme;\n}>;\n\nconst VAR_MAP: Record<string, keyof AmbientTheme> = {\n \"--amb-light-x\": \"lightX\",\n \"--amb-light-y\": \"lightY\",\n \"--amb-key-light-intensity\": \"keyLight\",\n \"--amb-fill-light-intensity\": \"fillLight\",\n \"--amb-light-hue\": \"lightHue\",\n \"--amb-light-saturation\": \"lightSaturation\",\n \"--amb-highlight-color\": \"highlightColor\",\n \"--amb-lume-hue\": \"lumeHue\",\n};\n\nexport function AmbientProvider({ children, className, style, theme }: AmbientProviderProps) {\n const themeVars: Record<string, string> = {};\n for (const [varName, key] of Object.entries(VAR_MAP)) {\n const value = theme?.[key];\n if (value !== undefined) {\n themeVars[varName] = key === \"lightSaturation\" ? `${value}%` : String(value);\n }\n }\n // Derived variables must be re-declared here so they recompute using the\n // overridden input variables on this element rather than inheriting the\n // already-resolved values from :root.\n themeVars[\"--amb-lume\"] = [\n \"color-mix(in oklab,\",\n \"hsl(var(--amb-lume-hue) 100% 74%) calc(clamp(0, (0.5 - var(--amb-key-light-intensity)) / 0.2, 1) * 100%),\",\n \"hsl(var(--amb-light-hue) var(--amb-light-saturation)\",\n \"calc((1 - sign(var(--amb-key-light-intensity) - 0.5)) * 50% + 25%)))\",\n ].join(\" \");\n themeVars[\"--amb-label\"] =\n \"hsl(var(--amb-light-hue) var(--amb-light-saturation) calc((1 - var(--amb-key-light-intensity)) * 60% + 20%))\";\n const mergedStyle = { ...themeVars, ...style } as CSSProperties;\n\n return (\n <div className={className} style={mergedStyle}>\n {children}\n </div>\n );\n}\n","export function cn(...values: Array<string | false | null | undefined>): string {\n return values.filter(Boolean).join(\" \");\n}\n","import type { HTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport interface AmbientPanelProps extends HTMLAttributes<HTMLDivElement> {\n material?: \"matte\" | \"shiny\" | \"glass\";\n}\n\nexport function AmbientPanel({ className, material = \"matte\", ...props }: AmbientPanelProps) {\n return (\n <div\n className={cn(\n \"ambient amb-surface amb-chamfer amb-elevation-2 ambx-panel\",\n material === \"matte\" ? \"amb-mat-matte\" : material === \"shiny\" ? \"amb-mat-shiny\" : \"amb-mat-glass\",\n className\n )}\n {...props}\n />\n );\n}\n","import type { ButtonHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/* Cap silhouettes from the referent lineup (ambient3d/generate.py):\n - \"pill\": the default wide stadium key (transport-key style)\n - \"round\": a circular key — pair with material=\"shiny\" for the\n machined metal-button look\n - \"square\": a squarer, flatter pad (EP-133-style, tighter corners,\n lower cap) */\nexport type AmbientButtonShape = \"pill\" | \"round\" | \"square\";\n\nexport interface AmbientButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n material?: \"matte\" | \"shiny\" | \"glass\";\n shape?: AmbientButtonShape;\n}\n\nexport function AmbientButton({\n className,\n children,\n material = \"matte\",\n shape = \"pill\",\n ...props\n}: AmbientButtonProps) {\n return (\n <button\n type=\"button\"\n className={cn(\n \"amb-button amb-groove ambx-button\",\n shape === \"round\" && \"amb-button-round\",\n shape === \"square\" && \"amb-button-square\",\n className\n )}\n {...props}\n >\n <span\n className={cn(\n \"amb-button-cap ambient amb-chamfer amb-surface amb-heading-3\",\n material === \"matte\" ? \"amb-mat-matte\" : material === \"shiny\" ? \"amb-mat-shiny\" : \"amb-mat-glass\"\n )}\n >\n {children}\n </span>\n </button>\n );\n}\n","import { useId, useState } from \"react\";\nimport type { ButtonHTMLAttributes } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientSwitchSize = \"sm\" | \"md\" | \"lg\";\n\nexport type AmbientSwitchProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, \"onChange\"> & {\n checked?: boolean;\n defaultChecked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n size?: AmbientSwitchSize;\n label?: string;\n /** Show a small LED indicator that lights up when the switch is on. Pass `true` for default green or a CSS color string. */\n led?: boolean | string;\n};\n\nexport function AmbientSwitch({\n className,\n checked,\n defaultChecked,\n onCheckedChange,\n onClick,\n size = \"md\",\n label,\n led,\n children,\n ...props\n}: AmbientSwitchProps) {\n const labelId = useId();\n const isControlled = checked !== undefined;\n const [internalChecked, setInternalChecked] = useState(defaultChecked ?? false);\n const active = isControlled ? (checked ?? false) : internalChecked;\n\n const button = (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={active}\n aria-labelledby={label ? labelId : props[\"aria-labelledby\"]}\n className={cn(\n \"amb-switch\",\n active && \"amb-switch-on\",\n \"ambx-switch\",\n `ambx-switch-${size}`,\n className\n )}\n onClick={(event) => {\n const next = !active;\n if (!isControlled) setInternalChecked(next);\n onCheckedChange?.(next);\n onClick?.(event);\n }}\n {...props}\n >\n {led ? (\n <span\n className={cn(\"amb-led\", !active && \"amb-led-off\")}\n style={typeof led === \"string\" ? { \"--amb-led-color\": led } as React.CSSProperties : undefined}\n />\n ) : null}\n <span className=\"amb-switch-track amb-groove\">\n <span className=\"amb-switch-pill ambient amb-fillet amb-surface-convex\" />\n </span>\n {children}\n </button>\n );\n\n if (!label) return button;\n\n return (\n <div className=\"ambx-stack\">\n {button}\n <span id={labelId} className=\"ambx-label\">\n {label}\n </span>\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\n/* Straight-knurled silhouettes for the rotating face, in\n objectBoundingBox units so the clip scales with the component. Each\n variant family mirrors its referent's rib section\n (ambient3d/ground_components.py): trapezoid teeth between the outer\n radius and the tooth-root radius. The circular body underneath keeps\n the smooth drop shadow. */\ntype KnurlSpec = {\n teeth: number; // rib count\n root: number; // tooth-root radius (bounding-box units; outer is 0.5)\n rise: number; // fraction of the pitch spent climbing to the crest\n fall: [number, number]; // crest-end and root-return pitch fractions\n};\n\nconst KNURLS: Record<\"standard\" | \"flute\" | \"fine\", KnurlSpec> = {\n /* 36 ribs — the grounded referent knob (dot and line variants) */\n standard: { teeth: 36, root: 0.468, rise: 0.12, fall: [0.5, 0.62] },\n /* 14 broad flutes with deeper roots (OP-Z-style flute variant) */\n flute: { teeth: 14, root: 0.44, rise: 0.08, fall: [0.72, 0.8] },\n /* 48-rib fine knurl, shallower (cap and wheel variants) */\n fine: { teeth: 48, root: 0.476, rise: 0.12, fall: [0.5, 0.62] }\n};\n\nfunction knurlPath({ teeth, root, rise, fall }: KnurlSpec): string {\n const outer = 0.5;\n const pitch = (Math.PI * 2) / teeth;\n const pts: string[] = [];\n for (let i = 0; i < teeth; i++) {\n const a = i * pitch;\n const tooth: Array<[number, number]> = [\n [0, root],\n [rise, outer],\n [fall[0], outer],\n [fall[1], root]\n ];\n for (const [frac, radius] of tooth) {\n const t = a + frac * pitch;\n pts.push(\n `${(0.5 + radius * Math.cos(t)).toFixed(4)} ${(0.5 + radius * Math.sin(t)).toFixed(4)}`\n );\n }\n }\n return `M${pts.join(\" L\")} Z`;\n}\n\nconst KNURL_PATHS = {\n standard: knurlPath(KNURLS.standard),\n flute: knurlPath(KNURLS.flute),\n fine: knurlPath(KNURLS.fine)\n};\n\n/* Knob types from the referent lineup (ambient3d/generate.py):\n - \"dot\": the grounded referent — 36-rib knurl, offset indicator dot\n - \"line\": same body with a radial indicator line (classic pot)\n - \"flute\": 14 broad flutes, centered dot (OP-Z-style encoder)\n - \"cap\": fine knurl under a smooth accent top disc (OP-1-style)\n - \"wheel\": bare fine knurl, no indicator (machined wheel — pair with\n material=\"shiny\") */\nexport type AmbientKnobVariant = \"dot\" | \"line\" | \"flute\" | \"cap\" | \"wheel\";\n\nconst VARIANT_FAMILY: Record<AmbientKnobVariant, keyof typeof KNURL_PATHS> = {\n dot: \"standard\",\n line: \"standard\",\n flute: \"flute\",\n cap: \"fine\",\n wheel: \"fine\"\n};\n\nexport type AmbientKnobProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n variant?: AmbientKnobVariant;\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientKnob({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n variant = \"dot\",\n onChange,\n className,\n ...props\n}: AmbientKnobProps) {\n const id = useId();\n const clipId = `amb-knurl-${id.replace(/:/g, \"\")}`;\n const draggingRef = useRef(false);\n const knobRef = useRef<HTMLDivElement>(null);\n const safeStep = step > 0 ? step : 1;\n const family = VARIANT_FAMILY[variant];\n\n const percent = (value - min) / (max - min || 1);\n const rotation = percent * 270 - 135;\n\n // Convert pointer position to a knob angle in [-180, 180] where 0 = up,\n // positive = clockwise. The knob's active range is [-135, 135] (270°),\n // with the dead zone at the bottom (~135° to ~225° i.e. past ±135°).\n const pointerToValue = (event: PointerEvent<HTMLDivElement>) => {\n const rect = knobRef.current!.getBoundingClientRect();\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n // atan2 with screen coords: 0=right, 90=down; add 90 to rotate so 0=up\n const atan2Deg = Math.atan2(event.clientY - cy, event.clientX - cx) * (180 / Math.PI);\n let angle = atan2Deg + 90;\n // Normalize to [-180, 180]\n if (angle > 180) angle -= 360;\n\n // Clamp dead zone based on current value position\n if (angle < -135 || angle > 135) {\n angle = percent >= 0.5 ? 135 : -135;\n }\n\n const range = max - min;\n const raw = min + ((angle + 135) / 270) * range;\n const snapped = Math.round(raw / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n ref={knobRef}\n className=\"amb-knob ambx-knob\"\n role=\"slider\"\n aria-label={label}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-labelledby={label ? id : undefined}\n aria-orientation=\"vertical\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n draggingRef.current = true;\n pointerToValue(event);\n }}\n onPointerMove={(event) => {\n if (draggingRef.current) pointerToValue(event);\n }}\n onPointerUp={() => {\n draggingRef.current = false;\n }}\n onPointerCancel={() => {\n draggingRef.current = false;\n }}\n onKeyDown={onKeyDown}\n >\n <svg width={0} height={0} style={{ position: \"absolute\" }} aria-hidden focusable={false}>\n <defs>\n <clipPath id={clipId} clipPathUnits=\"objectBoundingBox\">\n <path d={KNURL_PATHS[family]} />\n </clipPath>\n </defs>\n </svg>\n <span className=\"amb-knob-body ambient amb-thickness-2 amb-surface\" />\n <div\n className={cn(\n \"ambx-knob-rotation amb-knob-face\",\n family === \"flute\" && \"amb-knob-face-flute\",\n family === \"fine\" && \"amb-knob-face-fine\",\n variant === \"cap\" && \"amb-knob-face-cap\",\n material && `amb-mat-${material}`\n )}\n style={{ transform: `rotate(${rotation}deg)`, clipPath: `url(#${clipId})` }}\n >\n {variant === \"dot\" ? <span className=\"amb-knob-indicator-dot\" /> : null}\n {variant === \"line\" ? <span className=\"amb-knob-indicator-line\" /> : null}\n {variant === \"flute\" ? (\n <span className=\"amb-knob-indicator-dot amb-knob-indicator-dot-center\" />\n ) : null}\n </div>\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientFaderProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientFader({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n onChange,\n className,\n ...props\n}: AmbientFaderProps) {\n const id = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n const safeStep = step > 0 ? step : 1;\n\n const percent = ((value - min) / (max - min || 1)) * 100;\n\n const updateFromClientY = (clientY: number) => {\n const track = trackRef.current;\n if (!track) return;\n\n const rect = track.getBoundingClientRect();\n const ratio = 1 - (clientY - rect.top) / rect.height;\n const nextValue = min + clamp(ratio, 0, 1) * (max - min);\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowUp\":\n case \"ArrowRight\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowDown\":\n case \"ArrowLeft\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.buttons !== 1) return;\n updateFromClientY(event.clientY);\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n className=\"amb-fader amb-groove ambx-fader\"\n ref={trackRef}\n role=\"slider\"\n aria-label={label}\n aria-labelledby={label ? id : undefined}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-orientation=\"vertical\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n updateFromClientY(event.clientY);\n }}\n onPointerMove={onPointerMove}\n onKeyDown={onKeyDown}\n >\n <div\n className={cn(\"amb-fader-thumb ambient amb-fillet ambx-fader-thumb\", material !== \"glass\" && \"amb-surface-concave\", material && `amb-mat-${material}`)}\n style={{ top: `${100 - percent}%` }}\n >\n <span className=\"amb-fader-gripline\" />\n </div>\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n","import { useId, useRef } from \"react\";\nimport type { HTMLAttributes, KeyboardEvent, PointerEvent } from \"react\";\nimport { cn } from \"../lib/cn\";\n\nexport type AmbientSliderProps = Omit<HTMLAttributes<HTMLDivElement>, \"onChange\"> & {\n value: number;\n min?: number;\n max?: number;\n step?: number;\n label?: string;\n material?: \"matte\" | \"shiny\" | \"glass\";\n onChange?: (nextValue: number) => void;\n};\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n\nexport function AmbientSlider({\n value,\n min = 0,\n max = 100,\n step = 1,\n label,\n material,\n onChange,\n className,\n ...props\n}: AmbientSliderProps) {\n const id = useId();\n const trackRef = useRef<HTMLDivElement | null>(null);\n const safeStep = step > 0 ? step : 1;\n\n const percent = ((value - min) / (max - min || 1)) * 100;\n\n const updateFromClientX = (clientX: number) => {\n const track = trackRef.current;\n if (!track) return;\n\n const rect = track.getBoundingClientRect();\n const ratio = (clientX - rect.left) / rect.width;\n const nextValue = min + clamp(ratio, 0, 1) * (max - min);\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const setValue = (nextValue: number) => {\n const snapped = Math.round(nextValue / safeStep) * safeStep;\n onChange?.(clamp(snapped, min, max));\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const pageStep = safeStep * 10;\n switch (event.key) {\n case \"ArrowRight\":\n case \"ArrowUp\":\n event.preventDefault();\n setValue(value + safeStep);\n break;\n case \"ArrowLeft\":\n case \"ArrowDown\":\n event.preventDefault();\n setValue(value - safeStep);\n break;\n case \"PageUp\":\n event.preventDefault();\n setValue(value + pageStep);\n break;\n case \"PageDown\":\n event.preventDefault();\n setValue(value - pageStep);\n break;\n case \"Home\":\n event.preventDefault();\n setValue(min);\n break;\n case \"End\":\n event.preventDefault();\n setValue(max);\n break;\n default:\n break;\n }\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.buttons !== 1) return;\n updateFromClientX(event.clientX);\n };\n\n return (\n <div className={cn(\"ambx-stack\", className)} {...props}>\n <div\n className=\"amb-slider amb-groove ambx-slider\"\n ref={trackRef}\n role=\"slider\"\n aria-label={label}\n aria-labelledby={label ? id : undefined}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={value}\n aria-orientation=\"horizontal\"\n tabIndex={0}\n onPointerDown={(event) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n updateFromClientX(event.clientX);\n }}\n onPointerMove={onPointerMove}\n onKeyDown={onKeyDown}\n >\n <div\n className={cn(\"amb-slider-thumb ambient amb-fillet ambx-slider-thumb\", material !== \"glass\" && \"amb-surface-convex\", material && `amb-mat-${material}`)}\n style={{ left: `${percent}%` }}\n />\n </div>\n {label ? (\n <span id={id} className=\"ambx-label\">\n {label}\n </span>\n ) : null}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","useId","jsx","jsxs","useId","useId","useRef","jsx","jsxs","clamp","useId","useRef","useId","useRef","jsx","jsxs","clamp","useId","useRef"]}
|