@boyernick/standard-ui-react 0.4.2-canary.57 → 0.4.2-canary.58
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/package.json +5 -1
- package/src/glass.tsx +157 -0
- package/src/lib/liquidglass/NOTICE.md +10 -0
- package/src/lib/liquidglass/index.d.ts +45 -0
- package/src/lib/liquidglass/index.js +2830 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boyernick/standard-ui-react",
|
|
3
|
-
"version": "0.4.2-canary.
|
|
3
|
+
"version": "0.4.2-canary.58",
|
|
4
4
|
"description": "React components for StandardUI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"types": "./src/index.ts",
|
|
15
15
|
"default": "./src/index.ts"
|
|
16
16
|
},
|
|
17
|
+
"./glass": {
|
|
18
|
+
"types": "./src/glass.tsx",
|
|
19
|
+
"default": "./src/glass.tsx"
|
|
20
|
+
},
|
|
17
21
|
"./package.json": "./package.json"
|
|
18
22
|
},
|
|
19
23
|
"scripts": {
|
package/src/glass.tsx
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { GlassConfig } from "./lib/liquidglass/index.js";
|
|
5
|
+
import { cn } from "./lib/cn";
|
|
6
|
+
|
|
7
|
+
export type GlassState = "pending" | "live" | "off";
|
|
8
|
+
|
|
9
|
+
export interface GlassRootProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
10
|
+
/** Default LiquidGlass shader configuration shared by direct Glass children. */
|
|
11
|
+
defaults?: Partial<GlassConfig>;
|
|
12
|
+
/** Disable WebGL rendering while preserving the underlying DOM. */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Called when the LiquidGlass renderer changes state. */
|
|
15
|
+
onGlassStateChange?: (state: GlassState) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GlassProps extends React.ComponentPropsWithoutRef<"div"> {
|
|
19
|
+
/** Per-pane LiquidGlass shader configuration. */
|
|
20
|
+
config?: Partial<GlassConfig>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function setForwardedRef<T>(ref: React.ForwardedRef<T>, value: T | null) {
|
|
24
|
+
if (typeof ref === "function") {
|
|
25
|
+
ref(value);
|
|
26
|
+
} else if (ref) {
|
|
27
|
+
ref.current = value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A positioned rendering root for LiquidGlass.
|
|
33
|
+
*
|
|
34
|
+
* Glass panes must be direct children of this element. Background content must
|
|
35
|
+
* also live inside the root because LiquidGlass samples the root's children,
|
|
36
|
+
* not the root's own background.
|
|
37
|
+
*/
|
|
38
|
+
export const GlassRoot = React.forwardRef<HTMLDivElement, GlassRootProps>(
|
|
39
|
+
function GlassRoot(
|
|
40
|
+
{
|
|
41
|
+
className,
|
|
42
|
+
defaults,
|
|
43
|
+
disabled = false,
|
|
44
|
+
onGlassStateChange,
|
|
45
|
+
children,
|
|
46
|
+
...props
|
|
47
|
+
},
|
|
48
|
+
forwardedRef,
|
|
49
|
+
) {
|
|
50
|
+
const rootRef = React.useRef<HTMLDivElement | null>(null);
|
|
51
|
+
const stateCallbackRef = React.useRef(onGlassStateChange);
|
|
52
|
+
stateCallbackRef.current = onGlassStateChange;
|
|
53
|
+
|
|
54
|
+
// GlassConfig is a flat JSON-safe object. A serialized key means callers
|
|
55
|
+
// can pass an inline object without tearing down WebGL on every render.
|
|
56
|
+
const defaultsKey = JSON.stringify(defaults ?? {});
|
|
57
|
+
|
|
58
|
+
const setRootRef = React.useCallback(
|
|
59
|
+
(node: HTMLDivElement | null) => {
|
|
60
|
+
rootRef.current = node;
|
|
61
|
+
setForwardedRef(forwardedRef, node);
|
|
62
|
+
},
|
|
63
|
+
[forwardedRef],
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
React.useEffect(() => {
|
|
67
|
+
const root = rootRef.current;
|
|
68
|
+
const report = (state: GlassState) => {
|
|
69
|
+
root?.setAttribute("data-glass-state", state);
|
|
70
|
+
stateCallbackRef.current?.(state);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (!root || disabled) {
|
|
74
|
+
report("off");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const glassElements = Array.from(root.children).filter(
|
|
79
|
+
(element): element is HTMLElement =>
|
|
80
|
+
element instanceof HTMLElement && element.dataset.slot === "glass",
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
if (glassElements.length === 0) {
|
|
84
|
+
report("off");
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let cancelled = false;
|
|
89
|
+
let destroy: (() => void) | undefined;
|
|
90
|
+
|
|
91
|
+
report("pending");
|
|
92
|
+
|
|
93
|
+
void import("./lib/liquidglass/index.js")
|
|
94
|
+
.then(({ LiquidGlass }) =>
|
|
95
|
+
LiquidGlass.init({
|
|
96
|
+
root,
|
|
97
|
+
glassElements,
|
|
98
|
+
defaults: JSON.parse(defaultsKey) as Partial<GlassConfig>,
|
|
99
|
+
}),
|
|
100
|
+
)
|
|
101
|
+
.then((instance) => {
|
|
102
|
+
if (cancelled) {
|
|
103
|
+
instance.destroy();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
destroy = () => instance.destroy();
|
|
108
|
+
report("live");
|
|
109
|
+
})
|
|
110
|
+
.catch(() => {
|
|
111
|
+
if (!cancelled) report("off");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return () => {
|
|
115
|
+
cancelled = true;
|
|
116
|
+
destroy?.();
|
|
117
|
+
};
|
|
118
|
+
}, [defaultsKey, disabled]);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
ref={setRootRef}
|
|
123
|
+
data-slot="glass-root"
|
|
124
|
+
className={cn("relative", className)}
|
|
125
|
+
{...props}
|
|
126
|
+
>
|
|
127
|
+
{children}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* A LiquidGlass pane. It must be rendered as a direct child of GlassRoot.
|
|
135
|
+
* `config` maps directly to LiquidGlass's per-element `data-config` JSON.
|
|
136
|
+
*/
|
|
137
|
+
export const Glass = React.forwardRef<HTMLDivElement, GlassProps>(function Glass(
|
|
138
|
+
{ className, config, children, ...props },
|
|
139
|
+
ref,
|
|
140
|
+
) {
|
|
141
|
+
return (
|
|
142
|
+
<div
|
|
143
|
+
ref={ref}
|
|
144
|
+
data-slot="glass"
|
|
145
|
+
data-config={config ? JSON.stringify(config) : undefined}
|
|
146
|
+
className={cn("relative", className)}
|
|
147
|
+
{...props}
|
|
148
|
+
>
|
|
149
|
+
{children}
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
GlassRoot.displayName = "GlassRoot";
|
|
155
|
+
Glass.displayName = "Glass";
|
|
156
|
+
|
|
157
|
+
export type { GlassConfig } from "./lib/liquidglass/index.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# LiquidGlass
|
|
2
|
+
|
|
3
|
+
Vendored from `@ybouane/liquidglass@1.0.3`.
|
|
4
|
+
|
|
5
|
+
Source: https://github.com/ybouane/liquidglass
|
|
6
|
+
License: MIT (as declared by the upstream package).
|
|
7
|
+
|
|
8
|
+
`index.js` is the package's published bundled WebGL renderer. StandardUI
|
|
9
|
+
vendors the build because version 1.0.3 publishes a `postinstall`
|
|
10
|
+
command whose `patch-package` executable is not a runtime dependency.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type surface for the vendored @ybouane/liquidglass 1.0.3 renderer.
|
|
3
|
+
* Source: https://github.com/ybouane/liquidglass
|
|
4
|
+
* License: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface GlassConfig {
|
|
8
|
+
blurAmount: number;
|
|
9
|
+
refraction: number;
|
|
10
|
+
chromAberration: number;
|
|
11
|
+
edgeHighlight: number;
|
|
12
|
+
specular: number;
|
|
13
|
+
fresnel: number;
|
|
14
|
+
distortion: number;
|
|
15
|
+
cornerRadius: number;
|
|
16
|
+
zRadius: number;
|
|
17
|
+
opacity: number;
|
|
18
|
+
saturation: number;
|
|
19
|
+
tintStrength: number;
|
|
20
|
+
brightness: number;
|
|
21
|
+
shadowOpacity: number;
|
|
22
|
+
shadowSpread: number;
|
|
23
|
+
shadowOffsetY: number;
|
|
24
|
+
floating: boolean;
|
|
25
|
+
button: boolean;
|
|
26
|
+
bevelMode: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface LiquidGlassOptions {
|
|
30
|
+
root: HTMLElement;
|
|
31
|
+
glassElements?: NodeListOf<HTMLElement> | HTMLElement[];
|
|
32
|
+
defaults?: Partial<GlassConfig>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export declare class LiquidGlass {
|
|
36
|
+
static init(options: LiquidGlassOptions): Promise<LiquidGlass>;
|
|
37
|
+
readonly root: HTMLElement;
|
|
38
|
+
readonly defaults: GlassConfig;
|
|
39
|
+
fps: number;
|
|
40
|
+
destroy(): void;
|
|
41
|
+
markChanged(element?: HTMLElement): void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare const DEFAULTS: GlassConfig;
|
|
45
|
+
export declare function invalidateFontEmbedCache(): void;
|