@schemavaults/ui 0.46.6 → 0.48.3

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,51 @@
1
+ import { type HTMLAttributes, type ReactElement, type ReactNode, type Ref } from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ export declare const comparisonSliderOrientations: ["horizontal", "vertical"];
4
+ export type ComparisonSliderOrientation = (typeof comparisonSliderOrientations)[number];
5
+ export declare const comparisonSliderHandleVariantIds: ["default", "minimal", "brand"];
6
+ export type ComparisonSliderHandleVariantId = (typeof comparisonSliderHandleVariantIds)[number];
7
+ declare const handleVariants: (props?: ({
8
+ orientation?: "horizontal" | "vertical" | null | undefined;
9
+ handleVariant?: "default" | "brand" | "minimal" | null | undefined;
10
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
11
+ export interface ComparisonSliderProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange">, VariantProps<typeof handleVariants> {
12
+ /** Content displayed on the "before" (left/top) side. */
13
+ before: ReactNode;
14
+ /** Content displayed on the "after" (right/bottom) side. */
15
+ after: ReactNode;
16
+ /** Optional accessible label announcing what is being compared (e.g. "Before and after photo"). */
17
+ label?: string;
18
+ /** Optional caption shown over the "before" content. */
19
+ beforeLabel?: ReactNode;
20
+ /** Optional caption shown over the "after" content. */
21
+ afterLabel?: ReactNode;
22
+ /** Controlled position (0-100). When provided, the component is controlled. */
23
+ position?: number;
24
+ /** Initial position (0-100) when uncontrolled. Defaults to 50. */
25
+ defaultPosition?: number;
26
+ /** Fires on every position change (drag / keyboard). */
27
+ onPositionChange?: (position: number) => void;
28
+ /** Step (in percent) applied to keyboard arrow keys. Defaults to 2. */
29
+ keyboardStep?: number;
30
+ /** Orientation of the divider. Horizontal slides left/right, vertical slides up/down. */
31
+ orientation?: ComparisonSliderOrientation;
32
+ /** Visual variant for the divider line and handle. */
33
+ handleVariant?: ComparisonSliderHandleVariantId;
34
+ /** Disable interaction. */
35
+ disabled?: boolean;
36
+ /** className passed to the root container. */
37
+ className?: string;
38
+ /** Imperative handle exposing setPosition / getPosition. Passed directly as a React 19 prop. */
39
+ ref?: Ref<ComparisonSliderRef>;
40
+ }
41
+ export interface ComparisonSliderRef {
42
+ /** Programmatically set the divider position (0-100). */
43
+ setPosition: (position: number) => void;
44
+ /** Returns the current divider position (0-100). */
45
+ getPosition: () => number;
46
+ }
47
+ export declare function ComparisonSlider({ before, after, label, beforeLabel, afterLabel, position, defaultPosition, onPositionChange, keyboardStep, orientation, handleVariant, disabled, className, ref, ...rest }: ComparisonSliderProps): ReactElement;
48
+ export declare namespace ComparisonSlider {
49
+ var displayName: string;
50
+ }
51
+ export default ComparisonSlider;
@@ -0,0 +1,194 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useId, useImperativeHandle, useRef, useState, } from "react";
4
+ import { cva } from "class-variance-authority";
5
+ import { cn } from "../../../lib/utils";
6
+ export const comparisonSliderOrientations = [
7
+ "horizontal",
8
+ "vertical",
9
+ ];
10
+ export const comparisonSliderHandleVariantIds = [
11
+ "default",
12
+ "minimal",
13
+ "brand",
14
+ ];
15
+ const dividerVariants = cva("pointer-events-none absolute z-10", {
16
+ variants: {
17
+ orientation: {
18
+ horizontal: "inset-y-0 w-px -translate-x-1/2",
19
+ vertical: "inset-x-0 h-px -translate-y-1/2",
20
+ },
21
+ handleVariant: {
22
+ default: "bg-foreground/80",
23
+ minimal: "bg-border",
24
+ brand: "bg-[var(--schemavaults-brand-blue)]",
25
+ },
26
+ },
27
+ defaultVariants: {
28
+ orientation: "horizontal",
29
+ handleVariant: "default",
30
+ },
31
+ });
32
+ const handleVariants = cva("absolute z-20 flex items-center justify-center rounded-full border-2 shadow-md transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50", {
33
+ variants: {
34
+ orientation: {
35
+ horizontal: "top-1/2 -translate-x-1/2 -translate-y-1/2 cursor-ew-resize",
36
+ vertical: "left-1/2 -translate-x-1/2 -translate-y-1/2 cursor-ns-resize",
37
+ },
38
+ handleVariant: {
39
+ default: "h-10 w-10 border-foreground/80 bg-background text-foreground hover:bg-accent",
40
+ minimal: "h-8 w-8 border-border bg-background text-muted-foreground hover:bg-muted",
41
+ brand: "h-10 w-10 border-[var(--schemavaults-brand-blue)] bg-background text-[var(--schemavaults-brand-blue)] hover:bg-[var(--schemavaults-brand-blue)]/10",
42
+ },
43
+ },
44
+ defaultVariants: {
45
+ orientation: "horizontal",
46
+ handleVariant: "default",
47
+ },
48
+ });
49
+ function clampPercentage(value) {
50
+ if (Number.isNaN(value))
51
+ return 50;
52
+ if (value < 0)
53
+ return 0;
54
+ if (value > 100)
55
+ return 100;
56
+ return value;
57
+ }
58
+ function HandleGlyph({ orientation, }) {
59
+ if (orientation === "horizontal") {
60
+ return (_jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("polyline", { points: "9 6 4 12 9 18" }), _jsx("polyline", { points: "15 6 20 12 15 18" })] }));
61
+ }
62
+ return (_jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", className: "h-4 w-4", fill: "none", stroke: "currentColor", strokeWidth: 2.5, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("polyline", { points: "6 9 12 4 18 9" }), _jsx("polyline", { points: "6 15 12 20 18 15" })] }));
63
+ }
64
+ export function ComparisonSlider({ before, after, label, beforeLabel, afterLabel, position, defaultPosition = 50, onPositionChange, keyboardStep = 2, orientation = "horizontal", handleVariant = "default", disabled = false, className, ref, ...rest }) {
65
+ const isControlled = typeof position === "number";
66
+ const [internalPosition, setInternalPosition] = useState(clampPercentage(defaultPosition));
67
+ const currentPosition = clampPercentage(isControlled ? position : internalPosition);
68
+ const containerRef = useRef(null);
69
+ const handleRef = useRef(null);
70
+ const draggingRef = useRef(false);
71
+ const headingId = useId();
72
+ const commitPosition = useCallback((nextValue) => {
73
+ const clamped = clampPercentage(nextValue);
74
+ if (!isControlled) {
75
+ setInternalPosition(clamped);
76
+ }
77
+ onPositionChange?.(clamped);
78
+ }, [isControlled, onPositionChange]);
79
+ useImperativeHandle(ref, () => ({
80
+ setPosition: (next) => commitPosition(next),
81
+ getPosition: () => currentPosition,
82
+ }), [commitPosition, currentPosition]);
83
+ const updateFromClientCoords = useCallback((clientX, clientY) => {
84
+ const container = containerRef.current;
85
+ if (!container)
86
+ return;
87
+ const rect = container.getBoundingClientRect();
88
+ if (orientation === "horizontal") {
89
+ if (rect.width <= 0)
90
+ return;
91
+ const next = ((clientX - rect.left) / rect.width) * 100;
92
+ commitPosition(next);
93
+ }
94
+ else {
95
+ if (rect.height <= 0)
96
+ return;
97
+ const next = ((clientY - rect.top) / rect.height) * 100;
98
+ commitPosition(next);
99
+ }
100
+ }, [commitPosition, orientation]);
101
+ const handlePointerDown = useCallback((event) => {
102
+ if (disabled)
103
+ return;
104
+ event.preventDefault();
105
+ draggingRef.current = true;
106
+ const target = event.currentTarget;
107
+ try {
108
+ target.setPointerCapture(event.pointerId);
109
+ }
110
+ catch {
111
+ // Some environments (e.g. RTL jsdom) may not support pointer capture; safe to ignore.
112
+ }
113
+ updateFromClientCoords(event.clientX, event.clientY);
114
+ handleRef.current?.focus({ preventScroll: true });
115
+ }, [disabled, updateFromClientCoords]);
116
+ const handlePointerMove = useCallback((event) => {
117
+ if (!draggingRef.current || disabled)
118
+ return;
119
+ updateFromClientCoords(event.clientX, event.clientY);
120
+ }, [disabled, updateFromClientCoords]);
121
+ const stopDragging = useCallback((event) => {
122
+ if (!draggingRef.current)
123
+ return;
124
+ draggingRef.current = false;
125
+ try {
126
+ event.currentTarget.releasePointerCapture(event.pointerId);
127
+ }
128
+ catch {
129
+ // ignore
130
+ }
131
+ }, []);
132
+ const handleKeyDown = useCallback((event) => {
133
+ if (disabled)
134
+ return;
135
+ const step = keyboardStep;
136
+ const decKeys = orientation === "horizontal"
137
+ ? ["ArrowLeft", "ArrowDown"]
138
+ : ["ArrowUp", "ArrowLeft"];
139
+ const incKeys = orientation === "horizontal"
140
+ ? ["ArrowRight", "ArrowUp"]
141
+ : ["ArrowDown", "ArrowRight"];
142
+ if (decKeys.includes(event.key)) {
143
+ event.preventDefault();
144
+ commitPosition(currentPosition - step);
145
+ }
146
+ else if (incKeys.includes(event.key)) {
147
+ event.preventDefault();
148
+ commitPosition(currentPosition + step);
149
+ }
150
+ else if (event.key === "Home") {
151
+ event.preventDefault();
152
+ commitPosition(0);
153
+ }
154
+ else if (event.key === "End") {
155
+ event.preventDefault();
156
+ commitPosition(100);
157
+ }
158
+ else if (event.key === "PageDown") {
159
+ event.preventDefault();
160
+ commitPosition(currentPosition - step * 5);
161
+ }
162
+ else if (event.key === "PageUp") {
163
+ event.preventDefault();
164
+ commitPosition(currentPosition + step * 5);
165
+ }
166
+ }, [commitPosition, currentPosition, disabled, keyboardStep, orientation]);
167
+ // Ensure dragging is cancelled if the pointer is released outside the slider.
168
+ useEffect(() => {
169
+ function handleWindowUp() {
170
+ draggingRef.current = false;
171
+ }
172
+ window.addEventListener("pointerup", handleWindowUp);
173
+ window.addEventListener("pointercancel", handleWindowUp);
174
+ return () => {
175
+ window.removeEventListener("pointerup", handleWindowUp);
176
+ window.removeEventListener("pointercancel", handleWindowUp);
177
+ };
178
+ }, []);
179
+ const clipStyle = orientation === "horizontal"
180
+ ? { clipPath: `inset(0 ${100 - currentPosition}% 0 0)` }
181
+ : { clipPath: `inset(0 0 ${100 - currentPosition}% 0)` };
182
+ const dividerStyle = orientation === "horizontal"
183
+ ? { left: `${currentPosition}%` }
184
+ : { top: `${currentPosition}%` };
185
+ const handleStyle = orientation === "horizontal"
186
+ ? { left: `${currentPosition}%` }
187
+ : { top: `${currentPosition}%` };
188
+ return (_jsxs("div", { ref: containerRef, className: cn("relative isolate w-full overflow-hidden rounded-md border border-border bg-background select-none", orientation === "horizontal" ? "aspect-video" : "aspect-square", disabled && "opacity-60", className), role: "group", "aria-labelledby": label ? headingId : undefined, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: stopDragging, onPointerCancel: stopDragging, ...rest, children: [label ? (_jsx("span", { id: headingId, className: "sr-only", children: label })) : null, _jsx("div", { className: "absolute inset-0 h-full w-full overflow-hidden", children: after }), _jsx("div", { className: "absolute inset-0 h-full w-full overflow-hidden", style: clipStyle, "aria-hidden": "false", children: before }), beforeLabel ? (_jsx("span", { className: cn("absolute z-10 rounded bg-foreground/70 px-2 py-0.5 text-xs font-medium text-background", orientation === "horizontal" ? "left-2 top-2" : "left-2 top-2"), children: beforeLabel })) : null, afterLabel ? (_jsx("span", { className: cn("absolute z-10 rounded bg-foreground/70 px-2 py-0.5 text-xs font-medium text-background", orientation === "horizontal"
189
+ ? "right-2 top-2"
190
+ : "left-2 bottom-2"), children: afterLabel })) : null, _jsx("div", { className: cn(dividerVariants({ orientation, handleVariant })), style: dividerStyle, "aria-hidden": "true" }), _jsx("button", { ref: handleRef, type: "button", className: cn(handleVariants({ orientation, handleVariant })), style: handleStyle, role: "slider", "aria-orientation": orientation, "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": Math.round(currentPosition), "aria-label": label ?? "Comparison slider position", "aria-disabled": disabled || undefined, tabIndex: disabled ? -1 : 0, disabled: disabled, onPointerDown: handlePointerDown, onPointerMove: handlePointerMove, onPointerUp: stopDragging, onPointerCancel: stopDragging, onKeyDown: handleKeyDown, children: _jsx(HandleGlyph, { orientation: orientation }) })] }));
191
+ }
192
+ ComparisonSlider.displayName = "ComparisonSlider";
193
+ export default ComparisonSlider;
194
+ //# sourceMappingURL=comparison-slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comparison-slider.js","sourceRoot":"","sources":["../../../../src/components/ui/comparison-slider/comparison-slider.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ComparisonSlider, comparisonSliderOrientations, comparisonSliderHandleVariantIds, } from "./comparison-slider";
2
+ export type * from "./comparison-slider";
3
+ export { ComparisonSlider as default } from "./comparison-slider";
@@ -0,0 +1,3 @@
1
+ export { ComparisonSlider, comparisonSliderOrientations, comparisonSliderHandleVariantIds, } from "./comparison-slider";
2
+ export { ComparisonSlider as default } from "./comparison-slider";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ui/comparison-slider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,4BAA4B,EAC5B,gCAAgC,GACjC,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,gBAAgB,IAAI,OAAO,EAAE,MAAM,qBAAqB,CAAC"}
@@ -154,3 +154,7 @@ export * from "./calendar-heatmap";
154
154
  export type * from "./calendar-heatmap";
155
155
  export * from "./pie-chart";
156
156
  export type * from "./pie-chart";
157
+ export * from "./comparison-slider";
158
+ export type * from "./comparison-slider";
159
+ export * from "./theme-selector";
160
+ export type * from "./theme-selector";
@@ -76,4 +76,6 @@ export * from "./aspect-ratio";
76
76
  export * from "./color-swatch";
77
77
  export * from "./calendar-heatmap";
78
78
  export * from "./pie-chart";
79
+ export * from "./comparison-slider";
80
+ export * from "./theme-selector";
79
81
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AAGzB,cAAc,aAAa,CAAC;AAG5B,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,SAAS,CAAC;AAGxB,cAAc,mBAAmB,CAAC;AAGlC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,UAAU,CAAC;AAGzB,cAAc,SAAS,CAAC;AAGxB,cAAc,kBAAkB,CAAC;AAGjC,cAAc,aAAa,CAAC;AAG5B,cAAc,kCAAkC,CAAC;AAGjD,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAExB,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,aAAa,CAAC;AAG5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,WAAW,CAAC;AAG1B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,UAAU,CAAC;AAGzB,cAAc,WAAW,CAAC;AAG1B,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,SAAS,CAAC;AAGxB,cAAc,aAAa,CAAC;AAG5B,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,cAAc,YAAY,CAAC;AAG3B,cAAc,2BAA2B,CAAC;AAG1C,cAAc,kBAAkB,CAAC;AAGjC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,eAAe,CAAC;AAG9B,cAAc,WAAW,CAAC;AAG1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,UAAU,CAAC;AAGzB,cAAc,eAAe,CAAC;AAG9B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC;AAG7B,cAAc,OAAO,CAAC;AAGtB,cAAc,eAAe,CAAC;AAG9B,cAAc,WAAW,CAAC;AAG1B,cAAc,UAAU,CAAC;AAGzB,cAAc,eAAe,CAAC;AAG9B,cAAc,aAAa,CAAC;AAG5B,cAAc,YAAY,CAAC;AAG3B,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,WAAW,CAAC;AAG1B,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AAGvB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,aAAa,CAAC;AAG5B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/ui/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AAGzB,cAAc,aAAa,CAAC;AAG5B,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,SAAS,CAAC;AAGxB,cAAc,mBAAmB,CAAC;AAGlC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,UAAU,CAAC;AAGzB,cAAc,SAAS,CAAC;AAGxB,cAAc,kBAAkB,CAAC;AAGjC,cAAc,aAAa,CAAC;AAG5B,cAAc,kCAAkC,CAAC;AAGjD,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,SAAS,CAAC;AAExB,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,aAAa,CAAC;AAG5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,WAAW,CAAC;AAG1B,cAAc,mBAAmB,CAAC;AAGlC,cAAc,UAAU,CAAC;AAGzB,cAAc,WAAW,CAAC;AAG1B,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,SAAS,CAAC;AAGxB,cAAc,aAAa,CAAC;AAG5B,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,cAAc,YAAY,CAAC;AAG3B,cAAc,2BAA2B,CAAC;AAG1C,cAAc,kBAAkB,CAAC;AAGjC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,eAAe,CAAC;AAG9B,cAAc,WAAW,CAAC;AAG1B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,UAAU,CAAC;AAGzB,cAAc,eAAe,CAAC;AAG9B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AAGnC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,QAAQ,CAAC;AAGvB,cAAc,QAAQ,CAAC;AAGvB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC;AAG7B,cAAc,OAAO,CAAC;AAGtB,cAAc,eAAe,CAAC;AAG9B,cAAc,WAAW,CAAC;AAG1B,cAAc,UAAU,CAAC;AAGzB,cAAc,eAAe,CAAC;AAG9B,cAAc,aAAa,CAAC;AAG5B,cAAc,YAAY,CAAC;AAG3B,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,eAAe,CAAC;AAG9B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,WAAW,CAAC;AAG1B,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AAGvB,cAAc,cAAc,CAAC;AAG7B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,aAAa,CAAC;AAG5B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,gBAAgB,CAAC;AAG/B,cAAc,oBAAoB,CAAC;AAGnC,cAAc,aAAa,CAAC;AAG5B,cAAc,qBAAqB,CAAC;AAGpC,cAAc,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { ThemeSelector, ThemeSelector as default, themeSelectorOptionIds, themeSelectorSizeIds, } from "./theme-selector";
2
+ export type { ThemeSelectorProps, ThemeSelectorOptionId, ThemeSelectorSizeId, } from "./theme-selector";
@@ -0,0 +1,2 @@
1
+ export { ThemeSelector, ThemeSelector as default, themeSelectorOptionIds, themeSelectorSizeIds, } from "./theme-selector";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/ui/theme-selector/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,aAAa,IAAI,OAAO,EACxB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type HTMLAttributes, type ReactElement } from "react";
2
+ export declare const themeSelectorOptionIds: readonly ["light", "system", "dark"];
3
+ export type ThemeSelectorOptionId = (typeof themeSelectorOptionIds)[number];
4
+ export declare const themeSelectorSizeIds: readonly ["sm", "default", "lg"];
5
+ export type ThemeSelectorSizeId = (typeof themeSelectorSizeIds)[number];
6
+ export interface ThemeSelectorProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "defaultValue"> {
7
+ /** Size of the underlying SegmentedControl. */
8
+ size?: ThemeSelectorSizeId;
9
+ /** Render only the icons, hiding the text labels. */
10
+ iconOnly?: boolean;
11
+ /** Disable interaction with every option. */
12
+ disabled?: boolean;
13
+ }
14
+ /**
15
+ * A brightness theme switcher driven by {@link useBrightnessTheme}, built on
16
+ * top of the {@link SegmentedControl} component.
17
+ *
18
+ * Must be rendered inside a `<BrightnessThemeProvider />`. The theme-aware UI
19
+ * is wrapped in a `<Suspense>` boundary that renders an inert, unselected
20
+ * SegmentedControl fallback until the client has hydrated — this avoids the
21
+ * next-themes server/client hydration mismatch without any mounted-flag state.
22
+ *
23
+ * @see BrightnessThemeProvider
24
+ * @see useBrightnessTheme
25
+ * @see SegmentedControl
26
+ */
27
+ export declare function ThemeSelector({ className, size, iconOnly, disabled, ...rest }: ThemeSelectorProps): ReactElement;
28
+ export declare namespace ThemeSelector {
29
+ var displayName: string;
30
+ }
31
+ export default ThemeSelector;
@@ -0,0 +1,81 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Monitor, Moon, Sun } from "lucide-react";
4
+ import { Suspense, use, } from "react";
5
+ import { cn } from "../../../lib/utils";
6
+ import { SegmentedControl, SegmentedControlItem, } from "../../ui/segmented-control";
7
+ import { useBrightnessTheme } from "../../../providers/brightness-theme";
8
+ export const themeSelectorOptionIds = [
9
+ "light",
10
+ "system",
11
+ "dark",
12
+ ];
13
+ export const themeSelectorSizeIds = [
14
+ "sm",
15
+ "default",
16
+ "lg",
17
+ ];
18
+ const themeOptions = [
19
+ { id: "light", label: "Light", icon: Sun },
20
+ { id: "system", label: "System", icon: Monitor },
21
+ { id: "dark", label: "Dark", icon: Moon },
22
+ ];
23
+ const iconSizeBySize = {
24
+ sm: "h-3.5 w-3.5",
25
+ default: "h-4 w-4",
26
+ lg: "h-[1.125rem] w-[1.125rem]",
27
+ };
28
+ function renderThemeItems(size, iconOnly) {
29
+ return themeOptions.map((option) => {
30
+ const Icon = option.icon;
31
+ return (_jsxs(SegmentedControlItem, { value: option.id, "aria-label": option.label, children: [_jsx(Icon, { className: cn(iconSizeBySize[size]), "aria-hidden": "true" }), iconOnly ? null : _jsx("span", { children: option.label })] }, option.id));
32
+ });
33
+ }
34
+ /**
35
+ * A promise used to suspend {@link ThemeSelector} until the app has hydrated on
36
+ * the client. On the server it never settles, so React renders the Suspense
37
+ * fallback into the SSR output (and the client hydrates that same fallback,
38
+ * avoiding the next-themes server/client mismatch). On the client it resolves
39
+ * once, on the macrotask after the first render, after which the real
40
+ * theme-aware UI takes over. The single cached promise is shared by every
41
+ * instance so the gate only opens once per page.
42
+ */
43
+ let hydrationPromise = null;
44
+ function getHydrationPromise() {
45
+ if (typeof window === "undefined") {
46
+ return new Promise(() => { });
47
+ }
48
+ if (!hydrationPromise) {
49
+ hydrationPromise = new Promise((resolve) => {
50
+ setTimeout(resolve);
51
+ });
52
+ }
53
+ return hydrationPromise;
54
+ }
55
+ function ThemeSelectorContent({ size, iconOnly, disabled, className, rest, }) {
56
+ use(getHydrationPromise());
57
+ const { theme, setTheme } = useBrightnessTheme();
58
+ return (_jsx(SegmentedControl, { value: theme ?? "", onValueChange: setTheme, variant: "outline", size: size, disabled: disabled, "aria-label": "Color theme", className: className, ...rest, children: renderThemeItems(size, iconOnly) }));
59
+ }
60
+ function ThemeSelectorFallback({ size, iconOnly, className, }) {
61
+ return (_jsx(SegmentedControl, { value: "", variant: "outline", size: size, disabled: true, "aria-hidden": "true", className: className, children: renderThemeItems(size, iconOnly) }));
62
+ }
63
+ /**
64
+ * A brightness theme switcher driven by {@link useBrightnessTheme}, built on
65
+ * top of the {@link SegmentedControl} component.
66
+ *
67
+ * Must be rendered inside a `<BrightnessThemeProvider />`. The theme-aware UI
68
+ * is wrapped in a `<Suspense>` boundary that renders an inert, unselected
69
+ * SegmentedControl fallback until the client has hydrated — this avoids the
70
+ * next-themes server/client hydration mismatch without any mounted-flag state.
71
+ *
72
+ * @see BrightnessThemeProvider
73
+ * @see useBrightnessTheme
74
+ * @see SegmentedControl
75
+ */
76
+ export function ThemeSelector({ className, size = "default", iconOnly = false, disabled = false, ...rest }) {
77
+ return (_jsx(Suspense, { fallback: _jsx(ThemeSelectorFallback, { size: size, iconOnly: iconOnly, className: className }), children: _jsx(ThemeSelectorContent, { size: size, iconOnly: iconOnly, disabled: disabled, className: className, rest: rest }) }));
78
+ }
79
+ ThemeSelector.displayName = "ThemeSelector";
80
+ export default ThemeSelector;
81
+ //# sourceMappingURL=theme-selector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-selector.js","sourceRoot":"","sources":["../../../../src/components/ui/theme-selector/theme-selector.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ThemeProvider as NextThemesProvider, useTheme as useBrightnessTheme } from "next-themes";
1
+ import { ThemeProvider as NextThemesProvider, useTheme as useBrightnessTheme, type UseThemeProps as UseBrightnessThemeReturn } from "next-themes";
2
2
  export type BrightnessThemeProviderProps = Parameters<typeof NextThemesProvider>[0];
3
3
  /**
4
4
  *
@@ -9,3 +9,4 @@ export type BrightnessThemeProviderProps = Parameters<typeof NextThemesProvider>
9
9
  export declare function BrightnessThemeProvider({ children, ...props }: BrightnessThemeProviderProps): import("react/jsx-runtime").JSX.Element;
10
10
  export default BrightnessThemeProvider;
11
11
  export { useBrightnessTheme };
12
+ export type { UseBrightnessThemeReturn };
@@ -1 +1 @@
1
- {"version":3,"file":"brightness-theme.js","sourceRoot":"","sources":["../../../src/providers/brightness-theme/brightness-theme.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,aAAa,IAAI,kBAAkB,EACnC,QAAQ,IAAI,kBAAkB,GAC/B,MAAM,aAAa,CAAC;AAMrB;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,GAAG,KAAK,EACqB;IAC7B,OAAO,KAAC,kBAAkB,OAAK,KAAK,YAAG,QAAQ,GAAsB,CAAC;AACxE,CAAC;AAED,eAAe,uBAAuB,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"brightness-theme.js","sourceRoot":"","sources":["../../../src/providers/brightness-theme/brightness-theme.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,aAAa,IAAI,kBAAkB,EACnC,QAAQ,IAAI,kBAAkB,GAE/B,MAAM,aAAa,CAAC;AAMrB;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EACR,GAAG,KAAK,EACqB;IAC7B,OAAO,KAAC,kBAAkB,OAAK,KAAK,YAAG,QAAQ,GAAsB,CAAC;AACxE,CAAC;AAED,eAAe,uBAAuB,CAAC;AAEvC,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,2 +1,2 @@
1
1
  export { BrightnessThemeProvider, BrightnessThemeProvider as default, useBrightnessTheme, } from "./brightness-theme";
2
- export type { BrightnessThemeProviderProps } from "./brightness-theme";
2
+ export type { BrightnessThemeProviderProps, UseBrightnessThemeReturn, } from "./brightness-theme";
@@ -1,4 +1,4 @@
1
1
  export { LazyFramerMotionProvider } from "./lazy_framer";
2
2
  export type { LazyFramerMotionProviderProps } from "./lazy_framer";
3
- export { BrightnessThemeProvider } from "./brightness-theme";
4
- export type { BrightnessThemeProviderProps } from "./brightness-theme";
3
+ export { BrightnessThemeProvider, useBrightnessTheme } from "./brightness-theme";
4
+ export type { BrightnessThemeProviderProps, UseBrightnessThemeReturn, } from "./brightness-theme";
@@ -1,4 +1,4 @@
1
1
  "use client";
2
2
  export { LazyFramerMotionProvider } from "./lazy_framer";
3
- export { BrightnessThemeProvider } from "./brightness-theme";
3
+ export { BrightnessThemeProvider, useBrightnessTheme } from "./brightness-theme";
4
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAGzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAGzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schemavaults/ui",
3
- "version": "0.46.6",
3
+ "version": "0.48.3",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "description": "React.js UI components for SchemaVaults frontend applications",