@marcosdemik/liquidglass 1.0.13 → 1.1.1
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/README.md +61 -27
- package/dist/index.cjs +66 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +66 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,20 +51,46 @@ The component includes a `"use client"` directive, so it works out of the box wi
|
|
|
51
51
|
|
|
52
52
|
## Props
|
|
53
53
|
|
|
54
|
+
### Shape & Appearance
|
|
55
|
+
|
|
54
56
|
| Prop | Type | Default | Description |
|
|
55
57
|
|------|------|---------|-------------|
|
|
56
58
|
| `width` | `number` | `300` | Button width in pixels |
|
|
57
59
|
| `height` | `number` | `56` | Button height in pixels |
|
|
58
60
|
| `radius` | `number` | `60` | Border radius in pixels |
|
|
59
|
-
| `edgeSize` | `number` | `40` | Size of the glass edge refraction zone |
|
|
60
|
-
| `intensity` | `number` | `1.0` | Refraction intensity multiplier |
|
|
61
|
-
| `smoothness` | `number` | `1.0` | Blur applied to the displacement map (softens edges) |
|
|
62
|
-
| `distortion` | `number` | `15.0` | Normal map distortion scale |
|
|
63
|
-
| `chroma` | `number` | `3` | Chromatic aberration strength (RGB channel offset) |
|
|
64
61
|
| `glassColor` | `string` | `"rgba(255,255,255,0.05)"` | Background tint color of the glass |
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
|
|
63
|
+
### Glass Effect
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Default | Description |
|
|
66
|
+
|------|------|---------|-------------|
|
|
67
|
+
| `displacement` | `number` | `35` | How much the background refracts (feDisplacementMap scale) |
|
|
68
|
+
| `blur` | `number` | `2` | Gaussian blur applied to the background |
|
|
69
|
+
| `chroma` | `number` | `3` | Chromatic aberration strength (RGB channel offset) |
|
|
70
|
+
| `saturation` | `number` | `1.2` | Saturation boost on the final result (1 = normal) |
|
|
71
|
+
| `distortion` | `number` | `15` | Normal map distortion scale in the shader |
|
|
72
|
+
| `intensity` | `number` | `1.0` | Refraction intensity at the glass edge |
|
|
73
|
+
| `edgeSize` | `number` | `40` | Thickness of the glass edge refraction zone |
|
|
74
|
+
| `smoothness` | `number` | `1.0` | Blur on the displacement map (softens transitions) |
|
|
75
|
+
|
|
76
|
+
### Hover Animation
|
|
77
|
+
|
|
78
|
+
| Prop | Type | Default | Description |
|
|
79
|
+
|------|------|---------|-------------|
|
|
80
|
+
| `hoverScale` | `number` | `1.05` | Scale multiplier on hover |
|
|
81
|
+
| `hoverDisplacement` | `number` | `65` | Displacement scale on hover |
|
|
82
|
+
| `hoverBlur` | `number` | `4` | Blur amount on hover |
|
|
83
|
+
| `hoverChromaMultiplier` | `number` | `2.5` | Multiplier applied to `chroma` on hover |
|
|
84
|
+
| `hoverDuration` | `number` | `0.4` | Duration of hover animation in seconds |
|
|
85
|
+
| `disableAnimation` | `boolean` | `false` | Disable all GSAP animations |
|
|
86
|
+
|
|
87
|
+
### Standard HTML
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Description |
|
|
90
|
+
|------|------|-------------|
|
|
91
|
+
| `className` | `string` | Additional CSS classes |
|
|
92
|
+
| `style` | `CSSProperties` | Inline styles merged onto the button |
|
|
93
|
+
| `ref` | `Ref<HTMLButtonElement>` | Forwarded ref to the underlying button |
|
|
68
94
|
|
|
69
95
|
All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, etc.) are also supported.
|
|
70
96
|
|
|
@@ -78,14 +104,6 @@ All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, et
|
|
|
78
104
|
</LiquidGlassButton>
|
|
79
105
|
```
|
|
80
106
|
|
|
81
|
-
### Square Icon Button
|
|
82
|
-
|
|
83
|
-
```tsx
|
|
84
|
-
<LiquidGlassButton width={60} height={60} radius={16} className="text-xl">
|
|
85
|
-
+
|
|
86
|
-
</LiquidGlassButton>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
107
|
### Circle Button
|
|
90
108
|
|
|
91
109
|
```tsx
|
|
@@ -94,14 +112,6 @@ All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, et
|
|
|
94
112
|
</LiquidGlassButton>
|
|
95
113
|
```
|
|
96
114
|
|
|
97
|
-
### Wide Navigation Bar
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
<LiquidGlassButton width={400} height={48} radius={24}>
|
|
101
|
-
Navigation
|
|
102
|
-
</LiquidGlassButton>
|
|
103
|
-
```
|
|
104
|
-
|
|
105
115
|
### High Distortion
|
|
106
116
|
|
|
107
117
|
```tsx
|
|
@@ -109,6 +119,7 @@ All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, et
|
|
|
109
119
|
width={320}
|
|
110
120
|
height={60}
|
|
111
121
|
radius={60}
|
|
122
|
+
displacement={60}
|
|
112
123
|
distortion={30}
|
|
113
124
|
chroma={8}
|
|
114
125
|
intensity={2}
|
|
@@ -124,6 +135,8 @@ All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, et
|
|
|
124
135
|
width={320}
|
|
125
136
|
height={60}
|
|
126
137
|
radius={60}
|
|
138
|
+
displacement={15}
|
|
139
|
+
blur={1}
|
|
127
140
|
distortion={5}
|
|
128
141
|
chroma={1}
|
|
129
142
|
smoothness={3}
|
|
@@ -132,16 +145,33 @@ All standard `<button>` HTML attributes (`onClick`, `disabled`, `aria-label`, et
|
|
|
132
145
|
</LiquidGlassButton>
|
|
133
146
|
```
|
|
134
147
|
|
|
135
|
-
###
|
|
148
|
+
### No Hover Animation
|
|
136
149
|
|
|
137
150
|
```tsx
|
|
138
151
|
<LiquidGlassButton
|
|
139
152
|
width={200}
|
|
140
153
|
height={50}
|
|
141
154
|
radius={30}
|
|
142
|
-
|
|
155
|
+
disableAnimation
|
|
143
156
|
>
|
|
144
|
-
|
|
157
|
+
Static Glass
|
|
158
|
+
</LiquidGlassButton>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Custom Hover Behavior
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
<LiquidGlassButton
|
|
165
|
+
width={320}
|
|
166
|
+
height={60}
|
|
167
|
+
radius={60}
|
|
168
|
+
hoverScale={1.1}
|
|
169
|
+
hoverDisplacement={100}
|
|
170
|
+
hoverBlur={6}
|
|
171
|
+
hoverChromaMultiplier={4}
|
|
172
|
+
hoverDuration={0.6}
|
|
173
|
+
>
|
|
174
|
+
Strong Hover
|
|
145
175
|
</LiquidGlassButton>
|
|
146
176
|
```
|
|
147
177
|
|
|
@@ -168,6 +198,10 @@ The effect is built from three layers:
|
|
|
168
198
|
|
|
169
199
|
3. **GSAP Animations** - Pointer events drive GSAP tweens that animate displacement scale, blur, chromatic separation, and button scale. Filter attributes are mutated directly each frame for maximum performance.
|
|
170
200
|
|
|
201
|
+
## Visibility Note
|
|
202
|
+
|
|
203
|
+
This component returns `null` during SSR and until the displacement map is generated. It always renders at full `opacity: 1` - if you need show/hide behavior (e.g. appear on hover), wrap it in a container with `opacity` control. Use `opacity: 0.01` (not `0`) on the wrapper to keep the browser's GPU compositor layer warm for instant transitions.
|
|
204
|
+
|
|
171
205
|
## Accessibility
|
|
172
206
|
|
|
173
207
|
- Respects `prefers-reduced-motion` - all animations are automatically disabled
|
package/dist/index.cjs
CHANGED
|
@@ -172,22 +172,54 @@ function generateGlassMaps(opts) {
|
|
|
172
172
|
|
|
173
173
|
// src/liquid-glass-button.tsx
|
|
174
174
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
175
|
-
var CONFIG = {
|
|
176
|
-
initial: { scale: 1, displacement: 35, blur: 2, chroma: 3 },
|
|
177
|
-
hover: { scale: 1.05, displacement: 65, blur: 4, chroma: 10 },
|
|
178
|
-
click: { scaleDown: 0.95, scaleUp: 1.05 },
|
|
179
|
-
duration: { hover: 0.4, clickDown: 0.1, clickUp: 0.3 },
|
|
180
|
-
ease: {
|
|
181
|
-
hover: "power3.out",
|
|
182
|
-
hoverOut: "power2.out",
|
|
183
|
-
clickDown: "power2.in",
|
|
184
|
-
clickUp: "back.out(2)"
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
175
|
var PADDING_PCT = 50;
|
|
188
176
|
var LiquidGlassButton = (0, import_react.forwardRef)(
|
|
189
177
|
function LiquidGlassButton2(_a, ref) {
|
|
190
|
-
var _b = _a, {
|
|
178
|
+
var _b = _a, {
|
|
179
|
+
children,
|
|
180
|
+
className,
|
|
181
|
+
style,
|
|
182
|
+
width = 300,
|
|
183
|
+
height = 56,
|
|
184
|
+
radius = 60,
|
|
185
|
+
edgeSize,
|
|
186
|
+
intensity,
|
|
187
|
+
smoothness = 1,
|
|
188
|
+
distortion,
|
|
189
|
+
chroma = 3,
|
|
190
|
+
glassColor = "rgba(255,255,255,0.05)",
|
|
191
|
+
displacement = 35,
|
|
192
|
+
blur = 2,
|
|
193
|
+
saturation = 1.2,
|
|
194
|
+
hoverScale = 1.05,
|
|
195
|
+
hoverDisplacement = 65,
|
|
196
|
+
hoverBlur = 4,
|
|
197
|
+
hoverChromaMultiplier = 2.5,
|
|
198
|
+
hoverDuration = 0.4,
|
|
199
|
+
disableAnimation = false
|
|
200
|
+
} = _b, props = __objRest(_b, [
|
|
201
|
+
"children",
|
|
202
|
+
"className",
|
|
203
|
+
"style",
|
|
204
|
+
"width",
|
|
205
|
+
"height",
|
|
206
|
+
"radius",
|
|
207
|
+
"edgeSize",
|
|
208
|
+
"intensity",
|
|
209
|
+
"smoothness",
|
|
210
|
+
"distortion",
|
|
211
|
+
"chroma",
|
|
212
|
+
"glassColor",
|
|
213
|
+
"displacement",
|
|
214
|
+
"blur",
|
|
215
|
+
"saturation",
|
|
216
|
+
"hoverScale",
|
|
217
|
+
"hoverDisplacement",
|
|
218
|
+
"hoverBlur",
|
|
219
|
+
"hoverChromaMultiplier",
|
|
220
|
+
"hoverDuration",
|
|
221
|
+
"disableAnimation"
|
|
222
|
+
]);
|
|
191
223
|
const internalRef = (0, import_react.useRef)(null);
|
|
192
224
|
const buttonRef = ref != null ? ref : internalRef;
|
|
193
225
|
const blurRef = (0, import_react.useRef)(null);
|
|
@@ -210,11 +242,11 @@ var LiquidGlassButton = (0, import_react.forwardRef)(
|
|
|
210
242
|
}, [width, height, radius, edgeSize, intensity, distortion]);
|
|
211
243
|
(0, import_react.useEffect)(() => {
|
|
212
244
|
const button = buttonRef.current;
|
|
213
|
-
if (!button || !blurRef.current) return;
|
|
245
|
+
if (!button || !blurRef.current || disableAnimation) return;
|
|
214
246
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
215
247
|
const fx = {
|
|
216
|
-
displacement
|
|
217
|
-
blur
|
|
248
|
+
displacement,
|
|
249
|
+
blur,
|
|
218
250
|
chroma
|
|
219
251
|
};
|
|
220
252
|
const sync = () => {
|
|
@@ -228,31 +260,31 @@ var LiquidGlassButton = (0, import_react.forwardRef)(
|
|
|
228
260
|
const onEnter = () => {
|
|
229
261
|
import_gsap.default.killTweensOf([fx, button]);
|
|
230
262
|
import_gsap.default.to(fx, {
|
|
231
|
-
displacement:
|
|
232
|
-
blur:
|
|
233
|
-
chroma: chroma *
|
|
234
|
-
duration:
|
|
235
|
-
ease:
|
|
263
|
+
displacement: hoverDisplacement,
|
|
264
|
+
blur: hoverBlur,
|
|
265
|
+
chroma: chroma * hoverChromaMultiplier,
|
|
266
|
+
duration: hoverDuration,
|
|
267
|
+
ease: "power3.out",
|
|
236
268
|
onUpdate: sync
|
|
237
269
|
});
|
|
238
|
-
import_gsap.default.to(button, { scale:
|
|
270
|
+
import_gsap.default.to(button, { scale: hoverScale, duration: hoverDuration, ease: "power3.out" });
|
|
239
271
|
};
|
|
240
272
|
const onLeave = () => {
|
|
241
273
|
import_gsap.default.killTweensOf([fx, button]);
|
|
242
274
|
import_gsap.default.to(fx, {
|
|
243
|
-
displacement
|
|
244
|
-
blur
|
|
275
|
+
displacement,
|
|
276
|
+
blur,
|
|
245
277
|
chroma,
|
|
246
|
-
duration:
|
|
247
|
-
ease:
|
|
278
|
+
duration: hoverDuration,
|
|
279
|
+
ease: "power2.out",
|
|
248
280
|
onUpdate: sync
|
|
249
281
|
});
|
|
250
|
-
import_gsap.default.to(button, { scale:
|
|
282
|
+
import_gsap.default.to(button, { scale: 1, duration: hoverDuration, ease: "power2.out" });
|
|
251
283
|
};
|
|
252
284
|
const onClick = () => {
|
|
253
285
|
import_gsap.default.killTweensOf(button);
|
|
254
286
|
const cur = import_gsap.default.getProperty(button, "scale");
|
|
255
|
-
import_gsap.default.timeline().to(button, { scale: cur *
|
|
287
|
+
import_gsap.default.timeline().to(button, { scale: cur * 0.95, duration: 0.1, ease: "power2.in" }).to(button, { scale: hoverScale, duration: 0.3, ease: "back.out(2)" });
|
|
256
288
|
};
|
|
257
289
|
button.addEventListener("pointerenter", onEnter);
|
|
258
290
|
button.addEventListener("pointerleave", onLeave);
|
|
@@ -263,7 +295,7 @@ var LiquidGlassButton = (0, import_react.forwardRef)(
|
|
|
263
295
|
button.removeEventListener("click", onClick);
|
|
264
296
|
import_gsap.default.killTweensOf([button, fx]);
|
|
265
297
|
};
|
|
266
|
-
}, [buttonRef, maps, chroma]);
|
|
298
|
+
}, [buttonRef, maps, chroma, displacement, blur, hoverScale, hoverDisplacement, hoverBlur, hoverChromaMultiplier, hoverDuration, disableAnimation]);
|
|
267
299
|
if (!maps) return null;
|
|
268
300
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
269
301
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
@@ -292,18 +324,18 @@ var LiquidGlassButton = (0, import_react.forwardRef)(
|
|
|
292
324
|
})
|
|
293
325
|
),
|
|
294
326
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { style: { position: "absolute", width: 0, height: 0, pointerEvents: "none" }, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("filter", { id: filterId, x: `-${PADDING_PCT}%`, y: `-${PADDING_PCT}%`, width: `${100 + PADDING_PCT * 2}%`, height: `${100 + PADDING_PCT * 2}%`, colorInterpolationFilters: "sRGB", children: [
|
|
295
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feGaussianBlur", { ref: blurRef, in: "SourceGraphic", stdDeviation:
|
|
327
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feGaussianBlur", { ref: blurRef, in: "SourceGraphic", stdDeviation: blur, result: "blurred_bg", edgeMode: "duplicate" }),
|
|
296
328
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feImage", { href: maps.displacement, result: "disp_map", x: `${PADDING_PCT}%`, y: `${PADDING_PCT}%`, width: `${100}%`, height: `${100}%`, preserveAspectRatio: "none" }),
|
|
297
329
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feGaussianBlur", { in: "disp_map", stdDeviation: smoothness, result: "disp_blurred", edgeMode: "duplicate" }),
|
|
298
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerR, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerR, in: "blurred_bg", in2: "disp_blurred", scale: displacement + chroma, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_r" }),
|
|
299
331
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", { in: "displaced_r", type: "matrix", values: "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0", result: "red_channel" }),
|
|
300
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerG, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerG, in: "blurred_bg", in2: "disp_blurred", scale: displacement, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_g" }),
|
|
301
333
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", { in: "displaced_g", type: "matrix", values: "0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0", result: "green_channel" }),
|
|
302
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerB, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
334
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feDisplacementMap", { ref: displacerB, in: "blurred_bg", in2: "disp_blurred", scale: displacement - chroma, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_b" }),
|
|
303
335
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", { in: "displaced_b", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0", result: "blue_channel" }),
|
|
304
336
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feBlend", { in: "red_channel", in2: "green_channel", mode: "screen", result: "rg_channels" }),
|
|
305
337
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feBlend", { in: "rg_channels", in2: "blue_channel", mode: "screen", result: "rgb_channels" }),
|
|
306
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", { in: "rgb_channels", type: "saturate", values:
|
|
338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("feColorMatrix", { in: "rgb_channels", type: "saturate", values: saturation.toString(), result: "final" })
|
|
307
339
|
] }) }) })
|
|
308
340
|
] });
|
|
309
341
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/liquid-glass-button.tsx","../src/utils.ts","../src/generate-displacement-map.ts"],"sourcesContent":["export { LiquidGlassButton } from \"./liquid-glass-button\";\nexport type { LiquidGlassButtonProps } from \"./liquid-glass-button\";\nexport { generateGlassMaps } from \"./generate-displacement-map\";\nexport type { MapOptions } from \"./generate-displacement-map\";\nexport { cn } from \"./utils\";\n","import React, { useRef, useEffect, useState, useId, forwardRef } from \"react\";\nimport gsap from \"gsap\";\nimport { cn } from \"./utils\";\nimport { generateGlassMaps } from \"./generate-displacement-map\";\n\nconst CONFIG = {\n initial: { scale: 1, displacement: 35, blur: 2, chroma: 3 },\n hover: { scale: 1.05, displacement: 65, blur: 4, chroma: 10 },\n click: { scaleDown: 0.95, scaleUp: 1.05 },\n duration: { hover: 0.4, clickDown: 0.1, clickUp: 0.3 },\n ease: {\n hover: \"power3.out\",\n hoverOut: \"power2.out\",\n clickDown: \"power2.in\",\n clickUp: \"back.out(2)\",\n },\n} as const;\n\nconst PADDING_PCT = 50;\n\nexport interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n width?: number;\n height?: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n smoothness?: number;\n distortion?: number;\n chroma?: number;\n glassColor?: string;\n}\n\nexport const LiquidGlassButton = forwardRef<HTMLButtonElement, LiquidGlassButtonProps>(\n function LiquidGlassButton({ children, className, width = 300, height = 56, radius = 60, edgeSize, intensity, smoothness = 1, distortion, chroma = 3, glassColor = \"rgba(255,255,255,0.05)\", style, ...props }, ref) {\n const internalRef = useRef<HTMLButtonElement>(null);\n const buttonRef = (ref as React.RefObject<HTMLButtonElement>) ?? internalRef;\n\n const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n const displacerR = useRef<SVGFEDisplacementMapElement>(null);\n const displacerG = useRef<SVGFEDisplacementMapElement>(null);\n const displacerB = useRef<SVGFEDisplacementMapElement>(null);\n\n const filterId = \"lg\" + useId().replace(/:/g, \"\");\n\n const [maps, setMaps] = useState<ReturnType<typeof generateGlassMaps> | null>(null);\n\n // Generate displacement maps + pre-decode the PNG data URL\n useEffect(() => {\n let cancelled = false;\n const m = generateGlassMaps({ width, height, radius, edgeSize, intensity, distortion });\n const img = new Image();\n img.onload = () => {\n if (!cancelled) setMaps(m);\n };\n img.src = m.displacement;\n return () => { cancelled = true; };\n }, [width, height, radius, edgeSize, intensity, distortion]);\n\n useEffect(() => {\n const button = buttonRef.current;\n if (!button || !blurRef.current) return;\n\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n\n const fx = {\n displacement: CONFIG.initial.displacement,\n blur: CONFIG.initial.blur,\n chroma: chroma\n };\n\n const sync = () => {\n displacerR.current?.setAttribute(\"scale\", (fx.displacement + fx.chroma).toString());\n displacerG.current?.setAttribute(\"scale\", fx.displacement.toString());\n displacerB.current?.setAttribute(\"scale\", (fx.displacement - fx.chroma).toString());\n blurRef.current?.setAttribute(\"stdDeviation\", fx.blur.toString());\n };\n\n sync();\n\n const onEnter = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: CONFIG.hover.displacement,\n blur: CONFIG.hover.blur,\n chroma: chroma * 2.5,\n duration: CONFIG.duration.hover,\n ease: CONFIG.ease.hover,\n onUpdate: sync\n });\n gsap.to(button, { scale: CONFIG.hover.scale, duration: CONFIG.duration.hover, ease: CONFIG.ease.hover });\n };\n\n const onLeave = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: CONFIG.initial.displacement,\n blur: CONFIG.initial.blur,\n chroma: chroma,\n duration: CONFIG.duration.hover,\n ease: CONFIG.ease.hoverOut,\n onUpdate: sync\n });\n gsap.to(button, { scale: CONFIG.initial.scale, duration: CONFIG.duration.hover, ease: CONFIG.ease.hoverOut });\n };\n\n const onClick = () => {\n gsap.killTweensOf(button);\n const cur = gsap.getProperty(button, \"scale\") as number;\n gsap.timeline()\n .to(button, { scale: cur * CONFIG.click.scaleDown, duration: CONFIG.duration.clickDown, ease: CONFIG.ease.clickDown })\n .to(button, { scale: CONFIG.click.scaleUp, duration: CONFIG.duration.clickUp, ease: CONFIG.ease.clickUp });\n };\n\n button.addEventListener(\"pointerenter\", onEnter);\n button.addEventListener(\"pointerleave\", onLeave);\n button.addEventListener(\"click\", onClick);\n\n return () => {\n button.removeEventListener(\"pointerenter\", onEnter);\n button.removeEventListener(\"pointerleave\", onLeave);\n button.removeEventListener(\"click\", onClick);\n gsap.killTweensOf([button, fx]);\n };\n }, [buttonRef, maps, chroma]);\n\n // Server and first client render: null (no hydration mismatch)\n if (!maps) return null;\n\n // NO opacity/visibility management here - the CONSUMER controls show/hide.\n // This component always renders at full opacity so the browser's compositor\n // keeps the backdrop-filter layer warm at all times.\n return (\n <>\n <button\n ref={buttonRef}\n className={cn(\"relative overflow-hidden shadow-2xl shadow-black/20 cursor-pointer\", className)}\n style={{ width, height, borderRadius: radius, border: \"none\", background: glassColor, ...style }}\n {...props}\n >\n <div\n className=\"absolute inset-0 z-0\"\n style={{\n borderRadius: \"inherit\",\n backdropFilter: `url(#${filterId})`,\n WebkitBackdropFilter: `url(#${filterId})`,\n willChange: \"backdrop-filter\",\n transform: \"translateZ(0)\",\n }}\n />\n <div className=\"absolute inset-0 z-10 flex items-center justify-center font-bold text-white shadow-[inset_0_1px_1px_rgba(255,255,255,0.4)]\" style={{ background: \"linear-gradient(180deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.0) 100%)\", borderRadius: \"inherit\" }}>\n {children}\n </div>\n </button>\n\n <svg style={{ position: \"absolute\", width: 0, height: 0, pointerEvents: \"none\" }} aria-hidden=\"true\">\n <defs>\n <filter id={filterId} x={`-${PADDING_PCT}%`} y={`-${PADDING_PCT}%`} width={`${100 + PADDING_PCT * 2}%`} height={`${100 + PADDING_PCT * 2}%`} colorInterpolationFilters=\"sRGB\">\n <feGaussianBlur ref={blurRef} in=\"SourceGraphic\" stdDeviation={CONFIG.initial.blur} result=\"blurred_bg\" edgeMode=\"duplicate\" />\n\n <feImage href={maps.displacement} result=\"disp_map\" x={`${PADDING_PCT}%`} y={`${PADDING_PCT}%`} width={`${100}%`} height={`${100}%`} preserveAspectRatio=\"none\" />\n\n <feGaussianBlur in=\"disp_map\" stdDeviation={smoothness} result=\"disp_blurred\" edgeMode=\"duplicate\" />\n\n <feDisplacementMap ref={displacerR} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement + chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_r\" />\n <feColorMatrix in=\"displaced_r\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"red_channel\" />\n\n <feDisplacementMap ref={displacerG} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_g\" />\n <feColorMatrix in=\"displaced_g\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"green_channel\" />\n\n <feDisplacementMap ref={displacerB} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement - chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_b\" />\n <feColorMatrix in=\"displaced_b\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"blue_channel\" />\n\n <feBlend in=\"red_channel\" in2=\"green_channel\" mode=\"screen\" result=\"rg_channels\" />\n <feBlend in=\"rg_channels\" in2=\"blue_channel\" mode=\"screen\" result=\"rgb_channels\" />\n\n <feColorMatrix in=\"rgb_channels\" type=\"saturate\" values=\"1.2\" result=\"final\" />\n </filter>\n </defs>\n </svg>\n </>\n );\n }\n);\n","export function cn(...classes: (string | undefined | null | false)[]) {\n return classes.filter(Boolean).join(\" \");\n}\n","export interface MapOptions {\n width: number;\n height: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n distortion?: number;\n}\n\nconst VERT = `attribute vec4 position; void main(){ gl_Position = position; }`;\n\nconst FRAG = `\nprecision mediump float;\nuniform vec2 uRes;\nuniform float uRadius;\nuniform float uEdgeSize;\nuniform float uIntensity;\nuniform float uDistortion;\n\nfloat sdRoundedBox(vec2 p, vec2 b, float r){\n r = min(r, min(b.x, b.y));\n vec2 q = abs(p) - b + r;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;\n}\n\nfloat getHeight(vec2 p) {\n vec2 halfSize = uRes * 0.5 - 2.0;\n\n // Aumenta o tamanho base do box ligeiramente proporcinal ao edge\n halfSize += uEdgeSize * 0.2;\n\n float d = sdRoundedBox(p, halfSize, uRadius);\n\n float borderSoftness = uEdgeSize * uIntensity;\n d = max(d, -borderSoftness);\n return smoothstep(0.0, -borderSoftness, d);\n}\n\nvoid main(){\n vec2 p = gl_FragCoord.xy - uRes * 0.5;\n p.y = -p.y;\n\n // --- Displacement Map ---\n const vec2 e = vec2(1.0, 0.0);\n float hx = getHeight(p + e.xy) - getHeight(p - e.xy);\n float hy = getHeight(p + e.yx) - getHeight(p - e.yx);\n\n vec2 normal = vec2(-hx, -hy) * uDistortion;\n vec2 color = clamp(normal * 0.5 + 0.5, 0.0, 1.0);\n\n gl_FragColor = vec4(color.x, color.y, 0.5, 1.0);\n}\n`;\n\nfunction compile(gl: WebGLRenderingContext, type: number, src: string) {\n const s = gl.createShader(type)!;\n gl.shaderSource(s, src);\n gl.compileShader(s);\n return s;\n}\n\nlet _cachedProgram: { gl: WebGLRenderingContext; program: WebGLProgram; canvas: HTMLCanvasElement } | null = null;\n\nfunction getGL() {\n if (_cachedProgram) return _cachedProgram;\n\n const canvas = document.createElement(\"canvas\");\n const gl = canvas.getContext(\"webgl\", { preserveDrawingBuffer: true, premultipliedAlpha: false })!;\n\n const vs = compile(gl, gl.VERTEX_SHADER, VERT);\n const fs = compile(gl, gl.FRAGMENT_SHADER, FRAG);\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.useProgram(program);\n\n const buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const pos = gl.getAttribLocation(program, \"position\");\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n _cachedProgram = { gl, program, canvas };\n return _cachedProgram;\n}\n\nfunction render(width: number, height: number, radius: number, edgeSize: number, intensity: number, distortion: number): string {\n const { gl, program, canvas } = getGL();\n canvas.width = width;\n canvas.height = height;\n gl.viewport(0, 0, width, height);\n gl.clearColor(0.5, 0.5, 0.5, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.useProgram(program);\n\n gl.uniform2f(gl.getUniformLocation(program, \"uRes\"), width, height);\n gl.uniform1f(gl.getUniformLocation(program, \"uRadius\"), radius);\n gl.uniform1f(gl.getUniformLocation(program, \"uEdgeSize\"), edgeSize);\n gl.uniform1f(gl.getUniformLocation(program, \"uIntensity\"), intensity);\n gl.uniform1f(gl.getUniformLocation(program, \"uDistortion\"), distortion);\n\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n return canvas.toDataURL(\"image/png\");\n}\n\nexport function generateGlassMaps(opts: MapOptions): { displacement: string } {\n const { width, height, radius = 60, edgeSize = 40, intensity = 1.0, distortion = 15.0 } = opts;\n const r = Math.min(radius, width / 2, height / 2);\n\n return {\n displacement: render(width, height, r, edgeSize, intensity, distortion),\n };\n}\n"],"mappings":"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","names":["LiquidGlassButton","_a","_b","gsap"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/liquid-glass-button.tsx","../src/utils.ts","../src/generate-displacement-map.ts"],"sourcesContent":["export { LiquidGlassButton } from \"./liquid-glass-button\";\nexport type { LiquidGlassButtonProps } from \"./liquid-glass-button\";\nexport { generateGlassMaps } from \"./generate-displacement-map\";\nexport type { MapOptions } from \"./generate-displacement-map\";\nexport { cn } from \"./utils\";\n","import React, { useRef, useEffect, useState, useId, forwardRef } from \"react\";\nimport gsap from \"gsap\";\nimport { cn } from \"./utils\";\nimport { generateGlassMaps } from \"./generate-displacement-map\";\n\nconst PADDING_PCT = 50;\n\nexport interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Button width in px */\n width?: number;\n /** Button height in px */\n height?: number;\n /** Border radius in px */\n radius?: number;\n /** Edge thickness of the glass refraction (shader param) */\n edgeSize?: number;\n /** Edge intensity of the glass refraction (shader param) */\n intensity?: number;\n /** Blur applied to the displacement map (higher = softer transitions) */\n smoothness?: number;\n /** Normal scale in the shader (higher = more warped background) */\n distortion?: number;\n /** RGB channel separation - chromatic aberration amount */\n chroma?: number;\n /** Background color of the glass */\n glassColor?: string;\n /** feDisplacementMap scale - how much the background refracts */\n displacement?: number;\n /** Gaussian blur applied to the background */\n blur?: number;\n /** Saturation boost applied to the final result (1 = normal) */\n saturation?: number;\n /** Scale multiplier on hover */\n hoverScale?: number;\n /** Displacement scale on hover */\n hoverDisplacement?: number;\n /** Blur amount on hover */\n hoverBlur?: number;\n /** Chroma multiplier on hover (applied to chroma prop) */\n hoverChromaMultiplier?: number;\n /** Duration of hover animation in seconds */\n hoverDuration?: number;\n /** Disable all GSAP animations */\n disableAnimation?: boolean;\n}\n\nexport const LiquidGlassButton = forwardRef<HTMLButtonElement, LiquidGlassButtonProps>(\n function LiquidGlassButton({\n children, className, style,\n width = 300,\n height = 56,\n radius = 60,\n edgeSize,\n intensity,\n smoothness = 1,\n distortion,\n chroma = 3,\n glassColor = \"rgba(255,255,255,0.05)\",\n displacement = 35,\n blur = 2,\n saturation = 1.2,\n hoverScale = 1.05,\n hoverDisplacement = 65,\n hoverBlur = 4,\n hoverChromaMultiplier = 2.5,\n hoverDuration = 0.4,\n disableAnimation = false,\n ...props\n }, ref) {\n const internalRef = useRef<HTMLButtonElement>(null);\n const buttonRef = (ref as React.RefObject<HTMLButtonElement>) ?? internalRef;\n\n const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n const displacerR = useRef<SVGFEDisplacementMapElement>(null);\n const displacerG = useRef<SVGFEDisplacementMapElement>(null);\n const displacerB = useRef<SVGFEDisplacementMapElement>(null);\n\n const filterId = \"lg\" + useId().replace(/:/g, \"\");\n\n const [maps, setMaps] = useState<ReturnType<typeof generateGlassMaps> | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const m = generateGlassMaps({ width, height, radius, edgeSize, intensity, distortion });\n const img = new Image();\n img.onload = () => {\n if (!cancelled) setMaps(m);\n };\n img.src = m.displacement;\n return () => { cancelled = true; };\n }, [width, height, radius, edgeSize, intensity, distortion]);\n\n useEffect(() => {\n const button = buttonRef.current;\n if (!button || !blurRef.current || disableAnimation) return;\n\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n\n const fx = {\n displacement: displacement,\n blur: blur,\n chroma: chroma\n };\n\n const sync = () => {\n displacerR.current?.setAttribute(\"scale\", (fx.displacement + fx.chroma).toString());\n displacerG.current?.setAttribute(\"scale\", fx.displacement.toString());\n displacerB.current?.setAttribute(\"scale\", (fx.displacement - fx.chroma).toString());\n blurRef.current?.setAttribute(\"stdDeviation\", fx.blur.toString());\n };\n\n sync();\n\n const onEnter = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: hoverDisplacement,\n blur: hoverBlur,\n chroma: chroma * hoverChromaMultiplier,\n duration: hoverDuration,\n ease: \"power3.out\",\n onUpdate: sync\n });\n gsap.to(button, { scale: hoverScale, duration: hoverDuration, ease: \"power3.out\" });\n };\n\n const onLeave = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: displacement,\n blur: blur,\n chroma: chroma,\n duration: hoverDuration,\n ease: \"power2.out\",\n onUpdate: sync\n });\n gsap.to(button, { scale: 1, duration: hoverDuration, ease: \"power2.out\" });\n };\n\n const onClick = () => {\n gsap.killTweensOf(button);\n const cur = gsap.getProperty(button, \"scale\") as number;\n gsap.timeline()\n .to(button, { scale: cur * 0.95, duration: 0.1, ease: \"power2.in\" })\n .to(button, { scale: hoverScale, duration: 0.3, ease: \"back.out(2)\" });\n };\n\n button.addEventListener(\"pointerenter\", onEnter);\n button.addEventListener(\"pointerleave\", onLeave);\n button.addEventListener(\"click\", onClick);\n\n return () => {\n button.removeEventListener(\"pointerenter\", onEnter);\n button.removeEventListener(\"pointerleave\", onLeave);\n button.removeEventListener(\"click\", onClick);\n gsap.killTweensOf([button, fx]);\n };\n }, [buttonRef, maps, chroma, displacement, blur, hoverScale, hoverDisplacement, hoverBlur, hoverChromaMultiplier, hoverDuration, disableAnimation]);\n\n if (!maps) return null;\n\n return (\n <>\n <button\n ref={buttonRef}\n className={cn(\"relative overflow-hidden shadow-2xl shadow-black/20 cursor-pointer\", className)}\n style={{ width, height, borderRadius: radius, border: \"none\", background: glassColor, ...style }}\n {...props}\n >\n <div\n className=\"absolute inset-0 z-0\"\n style={{\n borderRadius: \"inherit\",\n backdropFilter: `url(#${filterId})`,\n WebkitBackdropFilter: `url(#${filterId})`,\n willChange: \"backdrop-filter\",\n transform: \"translateZ(0)\",\n }}\n />\n <div className=\"absolute inset-0 z-10 flex items-center justify-center font-bold text-white shadow-[inset_0_1px_1px_rgba(255,255,255,0.4)]\" style={{ background: \"linear-gradient(180deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.0) 100%)\", borderRadius: \"inherit\" }}>\n {children}\n </div>\n </button>\n\n <svg style={{ position: \"absolute\", width: 0, height: 0, pointerEvents: \"none\" }} aria-hidden=\"true\">\n <defs>\n <filter id={filterId} x={`-${PADDING_PCT}%`} y={`-${PADDING_PCT}%`} width={`${100 + PADDING_PCT * 2}%`} height={`${100 + PADDING_PCT * 2}%`} colorInterpolationFilters=\"sRGB\">\n <feGaussianBlur ref={blurRef} in=\"SourceGraphic\" stdDeviation={blur} result=\"blurred_bg\" edgeMode=\"duplicate\" />\n\n <feImage href={maps.displacement} result=\"disp_map\" x={`${PADDING_PCT}%`} y={`${PADDING_PCT}%`} width={`${100}%`} height={`${100}%`} preserveAspectRatio=\"none\" />\n\n <feGaussianBlur in=\"disp_map\" stdDeviation={smoothness} result=\"disp_blurred\" edgeMode=\"duplicate\" />\n\n <feDisplacementMap ref={displacerR} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement + chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_r\" />\n <feColorMatrix in=\"displaced_r\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"red_channel\" />\n\n <feDisplacementMap ref={displacerG} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_g\" />\n <feColorMatrix in=\"displaced_g\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"green_channel\" />\n\n <feDisplacementMap ref={displacerB} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement - chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_b\" />\n <feColorMatrix in=\"displaced_b\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"blue_channel\" />\n\n <feBlend in=\"red_channel\" in2=\"green_channel\" mode=\"screen\" result=\"rg_channels\" />\n <feBlend in=\"rg_channels\" in2=\"blue_channel\" mode=\"screen\" result=\"rgb_channels\" />\n\n <feColorMatrix in=\"rgb_channels\" type=\"saturate\" values={saturation.toString()} result=\"final\" />\n </filter>\n </defs>\n </svg>\n </>\n );\n }\n);\n","export function cn(...classes: (string | undefined | null | false)[]) {\n return classes.filter(Boolean).join(\" \");\n}\n","export interface MapOptions {\n width: number;\n height: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n distortion?: number;\n}\n\nconst VERT = `attribute vec4 position; void main(){ gl_Position = position; }`;\n\nconst FRAG = `\nprecision mediump float;\nuniform vec2 uRes;\nuniform float uRadius;\nuniform float uEdgeSize;\nuniform float uIntensity;\nuniform float uDistortion;\n\nfloat sdRoundedBox(vec2 p, vec2 b, float r){\n r = min(r, min(b.x, b.y));\n vec2 q = abs(p) - b + r;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;\n}\n\nfloat getHeight(vec2 p) {\n vec2 halfSize = uRes * 0.5 - 2.0;\n\n // Aumenta o tamanho base do box ligeiramente proporcinal ao edge\n halfSize += uEdgeSize * 0.2;\n\n float d = sdRoundedBox(p, halfSize, uRadius);\n\n float borderSoftness = uEdgeSize * uIntensity;\n d = max(d, -borderSoftness);\n return smoothstep(0.0, -borderSoftness, d);\n}\n\nvoid main(){\n vec2 p = gl_FragCoord.xy - uRes * 0.5;\n p.y = -p.y;\n\n // --- Displacement Map ---\n const vec2 e = vec2(1.0, 0.0);\n float hx = getHeight(p + e.xy) - getHeight(p - e.xy);\n float hy = getHeight(p + e.yx) - getHeight(p - e.yx);\n\n vec2 normal = vec2(-hx, -hy) * uDistortion;\n vec2 color = clamp(normal * 0.5 + 0.5, 0.0, 1.0);\n\n gl_FragColor = vec4(color.x, color.y, 0.5, 1.0);\n}\n`;\n\nfunction compile(gl: WebGLRenderingContext, type: number, src: string) {\n const s = gl.createShader(type)!;\n gl.shaderSource(s, src);\n gl.compileShader(s);\n return s;\n}\n\nlet _cachedProgram: { gl: WebGLRenderingContext; program: WebGLProgram; canvas: HTMLCanvasElement } | null = null;\n\nfunction getGL() {\n if (_cachedProgram) return _cachedProgram;\n\n const canvas = document.createElement(\"canvas\");\n const gl = canvas.getContext(\"webgl\", { preserveDrawingBuffer: true, premultipliedAlpha: false })!;\n\n const vs = compile(gl, gl.VERTEX_SHADER, VERT);\n const fs = compile(gl, gl.FRAGMENT_SHADER, FRAG);\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.useProgram(program);\n\n const buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const pos = gl.getAttribLocation(program, \"position\");\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n _cachedProgram = { gl, program, canvas };\n return _cachedProgram;\n}\n\nfunction render(width: number, height: number, radius: number, edgeSize: number, intensity: number, distortion: number): string {\n const { gl, program, canvas } = getGL();\n canvas.width = width;\n canvas.height = height;\n gl.viewport(0, 0, width, height);\n gl.clearColor(0.5, 0.5, 0.5, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.useProgram(program);\n\n gl.uniform2f(gl.getUniformLocation(program, \"uRes\"), width, height);\n gl.uniform1f(gl.getUniformLocation(program, \"uRadius\"), radius);\n gl.uniform1f(gl.getUniformLocation(program, \"uEdgeSize\"), edgeSize);\n gl.uniform1f(gl.getUniformLocation(program, \"uIntensity\"), intensity);\n gl.uniform1f(gl.getUniformLocation(program, \"uDistortion\"), distortion);\n\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n return canvas.toDataURL(\"image/png\");\n}\n\nexport function generateGlassMaps(opts: MapOptions): { displacement: string } {\n const { width, height, radius = 60, edgeSize = 40, intensity = 1.0, distortion = 15.0 } = opts;\n const r = Math.min(radius, width / 2, height / 2);\n\n return {\n displacement: render(width, height, r, edgeSize, intensity, distortion),\n };\n}\n"],"mappings":"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","names":["LiquidGlassButton","_a","_b","gsap"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
/** Button width in px */
|
|
4
5
|
width?: number;
|
|
6
|
+
/** Button height in px */
|
|
5
7
|
height?: number;
|
|
8
|
+
/** Border radius in px */
|
|
6
9
|
radius?: number;
|
|
10
|
+
/** Edge thickness of the glass refraction (shader param) */
|
|
7
11
|
edgeSize?: number;
|
|
12
|
+
/** Edge intensity of the glass refraction (shader param) */
|
|
8
13
|
intensity?: number;
|
|
14
|
+
/** Blur applied to the displacement map (higher = softer transitions) */
|
|
9
15
|
smoothness?: number;
|
|
16
|
+
/** Normal scale in the shader (higher = more warped background) */
|
|
10
17
|
distortion?: number;
|
|
18
|
+
/** RGB channel separation - chromatic aberration amount */
|
|
11
19
|
chroma?: number;
|
|
20
|
+
/** Background color of the glass */
|
|
12
21
|
glassColor?: string;
|
|
22
|
+
/** feDisplacementMap scale - how much the background refracts */
|
|
23
|
+
displacement?: number;
|
|
24
|
+
/** Gaussian blur applied to the background */
|
|
25
|
+
blur?: number;
|
|
26
|
+
/** Saturation boost applied to the final result (1 = normal) */
|
|
27
|
+
saturation?: number;
|
|
28
|
+
/** Scale multiplier on hover */
|
|
29
|
+
hoverScale?: number;
|
|
30
|
+
/** Displacement scale on hover */
|
|
31
|
+
hoverDisplacement?: number;
|
|
32
|
+
/** Blur amount on hover */
|
|
33
|
+
hoverBlur?: number;
|
|
34
|
+
/** Chroma multiplier on hover (applied to chroma prop) */
|
|
35
|
+
hoverChromaMultiplier?: number;
|
|
36
|
+
/** Duration of hover animation in seconds */
|
|
37
|
+
hoverDuration?: number;
|
|
38
|
+
/** Disable all GSAP animations */
|
|
39
|
+
disableAnimation?: boolean;
|
|
13
40
|
}
|
|
14
41
|
declare const LiquidGlassButton: React.ForwardRefExoticComponent<LiquidGlassButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
15
42
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,42 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
3
|
interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
/** Button width in px */
|
|
4
5
|
width?: number;
|
|
6
|
+
/** Button height in px */
|
|
5
7
|
height?: number;
|
|
8
|
+
/** Border radius in px */
|
|
6
9
|
radius?: number;
|
|
10
|
+
/** Edge thickness of the glass refraction (shader param) */
|
|
7
11
|
edgeSize?: number;
|
|
12
|
+
/** Edge intensity of the glass refraction (shader param) */
|
|
8
13
|
intensity?: number;
|
|
14
|
+
/** Blur applied to the displacement map (higher = softer transitions) */
|
|
9
15
|
smoothness?: number;
|
|
16
|
+
/** Normal scale in the shader (higher = more warped background) */
|
|
10
17
|
distortion?: number;
|
|
18
|
+
/** RGB channel separation - chromatic aberration amount */
|
|
11
19
|
chroma?: number;
|
|
20
|
+
/** Background color of the glass */
|
|
12
21
|
glassColor?: string;
|
|
22
|
+
/** feDisplacementMap scale - how much the background refracts */
|
|
23
|
+
displacement?: number;
|
|
24
|
+
/** Gaussian blur applied to the background */
|
|
25
|
+
blur?: number;
|
|
26
|
+
/** Saturation boost applied to the final result (1 = normal) */
|
|
27
|
+
saturation?: number;
|
|
28
|
+
/** Scale multiplier on hover */
|
|
29
|
+
hoverScale?: number;
|
|
30
|
+
/** Displacement scale on hover */
|
|
31
|
+
hoverDisplacement?: number;
|
|
32
|
+
/** Blur amount on hover */
|
|
33
|
+
hoverBlur?: number;
|
|
34
|
+
/** Chroma multiplier on hover (applied to chroma prop) */
|
|
35
|
+
hoverChromaMultiplier?: number;
|
|
36
|
+
/** Duration of hover animation in seconds */
|
|
37
|
+
hoverDuration?: number;
|
|
38
|
+
/** Disable all GSAP animations */
|
|
39
|
+
disableAnimation?: boolean;
|
|
13
40
|
}
|
|
14
41
|
declare const LiquidGlassButton: React.ForwardRefExoticComponent<LiquidGlassButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
15
42
|
|
package/dist/index.js
CHANGED
|
@@ -137,22 +137,54 @@ function generateGlassMaps(opts) {
|
|
|
137
137
|
|
|
138
138
|
// src/liquid-glass-button.tsx
|
|
139
139
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
140
|
-
var CONFIG = {
|
|
141
|
-
initial: { scale: 1, displacement: 35, blur: 2, chroma: 3 },
|
|
142
|
-
hover: { scale: 1.05, displacement: 65, blur: 4, chroma: 10 },
|
|
143
|
-
click: { scaleDown: 0.95, scaleUp: 1.05 },
|
|
144
|
-
duration: { hover: 0.4, clickDown: 0.1, clickUp: 0.3 },
|
|
145
|
-
ease: {
|
|
146
|
-
hover: "power3.out",
|
|
147
|
-
hoverOut: "power2.out",
|
|
148
|
-
clickDown: "power2.in",
|
|
149
|
-
clickUp: "back.out(2)"
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
140
|
var PADDING_PCT = 50;
|
|
153
141
|
var LiquidGlassButton = forwardRef(
|
|
154
142
|
function LiquidGlassButton2(_a, ref) {
|
|
155
|
-
var _b = _a, {
|
|
143
|
+
var _b = _a, {
|
|
144
|
+
children,
|
|
145
|
+
className,
|
|
146
|
+
style,
|
|
147
|
+
width = 300,
|
|
148
|
+
height = 56,
|
|
149
|
+
radius = 60,
|
|
150
|
+
edgeSize,
|
|
151
|
+
intensity,
|
|
152
|
+
smoothness = 1,
|
|
153
|
+
distortion,
|
|
154
|
+
chroma = 3,
|
|
155
|
+
glassColor = "rgba(255,255,255,0.05)",
|
|
156
|
+
displacement = 35,
|
|
157
|
+
blur = 2,
|
|
158
|
+
saturation = 1.2,
|
|
159
|
+
hoverScale = 1.05,
|
|
160
|
+
hoverDisplacement = 65,
|
|
161
|
+
hoverBlur = 4,
|
|
162
|
+
hoverChromaMultiplier = 2.5,
|
|
163
|
+
hoverDuration = 0.4,
|
|
164
|
+
disableAnimation = false
|
|
165
|
+
} = _b, props = __objRest(_b, [
|
|
166
|
+
"children",
|
|
167
|
+
"className",
|
|
168
|
+
"style",
|
|
169
|
+
"width",
|
|
170
|
+
"height",
|
|
171
|
+
"radius",
|
|
172
|
+
"edgeSize",
|
|
173
|
+
"intensity",
|
|
174
|
+
"smoothness",
|
|
175
|
+
"distortion",
|
|
176
|
+
"chroma",
|
|
177
|
+
"glassColor",
|
|
178
|
+
"displacement",
|
|
179
|
+
"blur",
|
|
180
|
+
"saturation",
|
|
181
|
+
"hoverScale",
|
|
182
|
+
"hoverDisplacement",
|
|
183
|
+
"hoverBlur",
|
|
184
|
+
"hoverChromaMultiplier",
|
|
185
|
+
"hoverDuration",
|
|
186
|
+
"disableAnimation"
|
|
187
|
+
]);
|
|
156
188
|
const internalRef = useRef(null);
|
|
157
189
|
const buttonRef = ref != null ? ref : internalRef;
|
|
158
190
|
const blurRef = useRef(null);
|
|
@@ -175,11 +207,11 @@ var LiquidGlassButton = forwardRef(
|
|
|
175
207
|
}, [width, height, radius, edgeSize, intensity, distortion]);
|
|
176
208
|
useEffect(() => {
|
|
177
209
|
const button = buttonRef.current;
|
|
178
|
-
if (!button || !blurRef.current) return;
|
|
210
|
+
if (!button || !blurRef.current || disableAnimation) return;
|
|
179
211
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
180
212
|
const fx = {
|
|
181
|
-
displacement
|
|
182
|
-
blur
|
|
213
|
+
displacement,
|
|
214
|
+
blur,
|
|
183
215
|
chroma
|
|
184
216
|
};
|
|
185
217
|
const sync = () => {
|
|
@@ -193,31 +225,31 @@ var LiquidGlassButton = forwardRef(
|
|
|
193
225
|
const onEnter = () => {
|
|
194
226
|
gsap.killTweensOf([fx, button]);
|
|
195
227
|
gsap.to(fx, {
|
|
196
|
-
displacement:
|
|
197
|
-
blur:
|
|
198
|
-
chroma: chroma *
|
|
199
|
-
duration:
|
|
200
|
-
ease:
|
|
228
|
+
displacement: hoverDisplacement,
|
|
229
|
+
blur: hoverBlur,
|
|
230
|
+
chroma: chroma * hoverChromaMultiplier,
|
|
231
|
+
duration: hoverDuration,
|
|
232
|
+
ease: "power3.out",
|
|
201
233
|
onUpdate: sync
|
|
202
234
|
});
|
|
203
|
-
gsap.to(button, { scale:
|
|
235
|
+
gsap.to(button, { scale: hoverScale, duration: hoverDuration, ease: "power3.out" });
|
|
204
236
|
};
|
|
205
237
|
const onLeave = () => {
|
|
206
238
|
gsap.killTweensOf([fx, button]);
|
|
207
239
|
gsap.to(fx, {
|
|
208
|
-
displacement
|
|
209
|
-
blur
|
|
240
|
+
displacement,
|
|
241
|
+
blur,
|
|
210
242
|
chroma,
|
|
211
|
-
duration:
|
|
212
|
-
ease:
|
|
243
|
+
duration: hoverDuration,
|
|
244
|
+
ease: "power2.out",
|
|
213
245
|
onUpdate: sync
|
|
214
246
|
});
|
|
215
|
-
gsap.to(button, { scale:
|
|
247
|
+
gsap.to(button, { scale: 1, duration: hoverDuration, ease: "power2.out" });
|
|
216
248
|
};
|
|
217
249
|
const onClick = () => {
|
|
218
250
|
gsap.killTweensOf(button);
|
|
219
251
|
const cur = gsap.getProperty(button, "scale");
|
|
220
|
-
gsap.timeline().to(button, { scale: cur *
|
|
252
|
+
gsap.timeline().to(button, { scale: cur * 0.95, duration: 0.1, ease: "power2.in" }).to(button, { scale: hoverScale, duration: 0.3, ease: "back.out(2)" });
|
|
221
253
|
};
|
|
222
254
|
button.addEventListener("pointerenter", onEnter);
|
|
223
255
|
button.addEventListener("pointerleave", onLeave);
|
|
@@ -228,7 +260,7 @@ var LiquidGlassButton = forwardRef(
|
|
|
228
260
|
button.removeEventListener("click", onClick);
|
|
229
261
|
gsap.killTweensOf([button, fx]);
|
|
230
262
|
};
|
|
231
|
-
}, [buttonRef, maps, chroma]);
|
|
263
|
+
}, [buttonRef, maps, chroma, displacement, blur, hoverScale, hoverDisplacement, hoverBlur, hoverChromaMultiplier, hoverDuration, disableAnimation]);
|
|
232
264
|
if (!maps) return null;
|
|
233
265
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
234
266
|
/* @__PURE__ */ jsxs(
|
|
@@ -257,18 +289,18 @@ var LiquidGlassButton = forwardRef(
|
|
|
257
289
|
})
|
|
258
290
|
),
|
|
259
291
|
/* @__PURE__ */ jsx("svg", { style: { position: "absolute", width: 0, height: 0, pointerEvents: "none" }, "aria-hidden": "true", children: /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("filter", { id: filterId, x: `-${PADDING_PCT}%`, y: `-${PADDING_PCT}%`, width: `${100 + PADDING_PCT * 2}%`, height: `${100 + PADDING_PCT * 2}%`, colorInterpolationFilters: "sRGB", children: [
|
|
260
|
-
/* @__PURE__ */ jsx("feGaussianBlur", { ref: blurRef, in: "SourceGraphic", stdDeviation:
|
|
292
|
+
/* @__PURE__ */ jsx("feGaussianBlur", { ref: blurRef, in: "SourceGraphic", stdDeviation: blur, result: "blurred_bg", edgeMode: "duplicate" }),
|
|
261
293
|
/* @__PURE__ */ jsx("feImage", { href: maps.displacement, result: "disp_map", x: `${PADDING_PCT}%`, y: `${PADDING_PCT}%`, width: `${100}%`, height: `${100}%`, preserveAspectRatio: "none" }),
|
|
262
294
|
/* @__PURE__ */ jsx("feGaussianBlur", { in: "disp_map", stdDeviation: smoothness, result: "disp_blurred", edgeMode: "duplicate" }),
|
|
263
|
-
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerR, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
295
|
+
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerR, in: "blurred_bg", in2: "disp_blurred", scale: displacement + chroma, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_r" }),
|
|
264
296
|
/* @__PURE__ */ jsx("feColorMatrix", { in: "displaced_r", type: "matrix", values: "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0", result: "red_channel" }),
|
|
265
|
-
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerG, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
297
|
+
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerG, in: "blurred_bg", in2: "disp_blurred", scale: displacement, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_g" }),
|
|
266
298
|
/* @__PURE__ */ jsx("feColorMatrix", { in: "displaced_g", type: "matrix", values: "0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0", result: "green_channel" }),
|
|
267
|
-
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerB, in: "blurred_bg", in2: "disp_blurred", scale:
|
|
299
|
+
/* @__PURE__ */ jsx("feDisplacementMap", { ref: displacerB, in: "blurred_bg", in2: "disp_blurred", scale: displacement - chroma, xChannelSelector: "R", yChannelSelector: "G", result: "displaced_b" }),
|
|
268
300
|
/* @__PURE__ */ jsx("feColorMatrix", { in: "displaced_b", type: "matrix", values: "0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0", result: "blue_channel" }),
|
|
269
301
|
/* @__PURE__ */ jsx("feBlend", { in: "red_channel", in2: "green_channel", mode: "screen", result: "rg_channels" }),
|
|
270
302
|
/* @__PURE__ */ jsx("feBlend", { in: "rg_channels", in2: "blue_channel", mode: "screen", result: "rgb_channels" }),
|
|
271
|
-
/* @__PURE__ */ jsx("feColorMatrix", { in: "rgb_channels", type: "saturate", values:
|
|
303
|
+
/* @__PURE__ */ jsx("feColorMatrix", { in: "rgb_channels", type: "saturate", values: saturation.toString(), result: "final" })
|
|
272
304
|
] }) }) })
|
|
273
305
|
] });
|
|
274
306
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/liquid-glass-button.tsx","../src/utils.ts","../src/generate-displacement-map.ts"],"sourcesContent":["import React, { useRef, useEffect, useState, useId, forwardRef } from \"react\";\nimport gsap from \"gsap\";\nimport { cn } from \"./utils\";\nimport { generateGlassMaps } from \"./generate-displacement-map\";\n\nconst CONFIG = {\n initial: { scale: 1, displacement: 35, blur: 2, chroma: 3 },\n hover: { scale: 1.05, displacement: 65, blur: 4, chroma: 10 },\n click: { scaleDown: 0.95, scaleUp: 1.05 },\n duration: { hover: 0.4, clickDown: 0.1, clickUp: 0.3 },\n ease: {\n hover: \"power3.out\",\n hoverOut: \"power2.out\",\n clickDown: \"power2.in\",\n clickUp: \"back.out(2)\",\n },\n} as const;\n\nconst PADDING_PCT = 50;\n\nexport interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n width?: number;\n height?: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n smoothness?: number;\n distortion?: number;\n chroma?: number;\n glassColor?: string;\n}\n\nexport const LiquidGlassButton = forwardRef<HTMLButtonElement, LiquidGlassButtonProps>(\n function LiquidGlassButton({ children, className, width = 300, height = 56, radius = 60, edgeSize, intensity, smoothness = 1, distortion, chroma = 3, glassColor = \"rgba(255,255,255,0.05)\", style, ...props }, ref) {\n const internalRef = useRef<HTMLButtonElement>(null);\n const buttonRef = (ref as React.RefObject<HTMLButtonElement>) ?? internalRef;\n\n const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n const displacerR = useRef<SVGFEDisplacementMapElement>(null);\n const displacerG = useRef<SVGFEDisplacementMapElement>(null);\n const displacerB = useRef<SVGFEDisplacementMapElement>(null);\n\n const filterId = \"lg\" + useId().replace(/:/g, \"\");\n\n const [maps, setMaps] = useState<ReturnType<typeof generateGlassMaps> | null>(null);\n\n // Generate displacement maps + pre-decode the PNG data URL\n useEffect(() => {\n let cancelled = false;\n const m = generateGlassMaps({ width, height, radius, edgeSize, intensity, distortion });\n const img = new Image();\n img.onload = () => {\n if (!cancelled) setMaps(m);\n };\n img.src = m.displacement;\n return () => { cancelled = true; };\n }, [width, height, radius, edgeSize, intensity, distortion]);\n\n useEffect(() => {\n const button = buttonRef.current;\n if (!button || !blurRef.current) return;\n\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n\n const fx = {\n displacement: CONFIG.initial.displacement,\n blur: CONFIG.initial.blur,\n chroma: chroma\n };\n\n const sync = () => {\n displacerR.current?.setAttribute(\"scale\", (fx.displacement + fx.chroma).toString());\n displacerG.current?.setAttribute(\"scale\", fx.displacement.toString());\n displacerB.current?.setAttribute(\"scale\", (fx.displacement - fx.chroma).toString());\n blurRef.current?.setAttribute(\"stdDeviation\", fx.blur.toString());\n };\n\n sync();\n\n const onEnter = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: CONFIG.hover.displacement,\n blur: CONFIG.hover.blur,\n chroma: chroma * 2.5,\n duration: CONFIG.duration.hover,\n ease: CONFIG.ease.hover,\n onUpdate: sync\n });\n gsap.to(button, { scale: CONFIG.hover.scale, duration: CONFIG.duration.hover, ease: CONFIG.ease.hover });\n };\n\n const onLeave = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: CONFIG.initial.displacement,\n blur: CONFIG.initial.blur,\n chroma: chroma,\n duration: CONFIG.duration.hover,\n ease: CONFIG.ease.hoverOut,\n onUpdate: sync\n });\n gsap.to(button, { scale: CONFIG.initial.scale, duration: CONFIG.duration.hover, ease: CONFIG.ease.hoverOut });\n };\n\n const onClick = () => {\n gsap.killTweensOf(button);\n const cur = gsap.getProperty(button, \"scale\") as number;\n gsap.timeline()\n .to(button, { scale: cur * CONFIG.click.scaleDown, duration: CONFIG.duration.clickDown, ease: CONFIG.ease.clickDown })\n .to(button, { scale: CONFIG.click.scaleUp, duration: CONFIG.duration.clickUp, ease: CONFIG.ease.clickUp });\n };\n\n button.addEventListener(\"pointerenter\", onEnter);\n button.addEventListener(\"pointerleave\", onLeave);\n button.addEventListener(\"click\", onClick);\n\n return () => {\n button.removeEventListener(\"pointerenter\", onEnter);\n button.removeEventListener(\"pointerleave\", onLeave);\n button.removeEventListener(\"click\", onClick);\n gsap.killTweensOf([button, fx]);\n };\n }, [buttonRef, maps, chroma]);\n\n // Server and first client render: null (no hydration mismatch)\n if (!maps) return null;\n\n // NO opacity/visibility management here - the CONSUMER controls show/hide.\n // This component always renders at full opacity so the browser's compositor\n // keeps the backdrop-filter layer warm at all times.\n return (\n <>\n <button\n ref={buttonRef}\n className={cn(\"relative overflow-hidden shadow-2xl shadow-black/20 cursor-pointer\", className)}\n style={{ width, height, borderRadius: radius, border: \"none\", background: glassColor, ...style }}\n {...props}\n >\n <div\n className=\"absolute inset-0 z-0\"\n style={{\n borderRadius: \"inherit\",\n backdropFilter: `url(#${filterId})`,\n WebkitBackdropFilter: `url(#${filterId})`,\n willChange: \"backdrop-filter\",\n transform: \"translateZ(0)\",\n }}\n />\n <div className=\"absolute inset-0 z-10 flex items-center justify-center font-bold text-white shadow-[inset_0_1px_1px_rgba(255,255,255,0.4)]\" style={{ background: \"linear-gradient(180deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.0) 100%)\", borderRadius: \"inherit\" }}>\n {children}\n </div>\n </button>\n\n <svg style={{ position: \"absolute\", width: 0, height: 0, pointerEvents: \"none\" }} aria-hidden=\"true\">\n <defs>\n <filter id={filterId} x={`-${PADDING_PCT}%`} y={`-${PADDING_PCT}%`} width={`${100 + PADDING_PCT * 2}%`} height={`${100 + PADDING_PCT * 2}%`} colorInterpolationFilters=\"sRGB\">\n <feGaussianBlur ref={blurRef} in=\"SourceGraphic\" stdDeviation={CONFIG.initial.blur} result=\"blurred_bg\" edgeMode=\"duplicate\" />\n\n <feImage href={maps.displacement} result=\"disp_map\" x={`${PADDING_PCT}%`} y={`${PADDING_PCT}%`} width={`${100}%`} height={`${100}%`} preserveAspectRatio=\"none\" />\n\n <feGaussianBlur in=\"disp_map\" stdDeviation={smoothness} result=\"disp_blurred\" edgeMode=\"duplicate\" />\n\n <feDisplacementMap ref={displacerR} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement + chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_r\" />\n <feColorMatrix in=\"displaced_r\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"red_channel\" />\n\n <feDisplacementMap ref={displacerG} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_g\" />\n <feColorMatrix in=\"displaced_g\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"green_channel\" />\n\n <feDisplacementMap ref={displacerB} in=\"blurred_bg\" in2=\"disp_blurred\" scale={CONFIG.initial.displacement - chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_b\" />\n <feColorMatrix in=\"displaced_b\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"blue_channel\" />\n\n <feBlend in=\"red_channel\" in2=\"green_channel\" mode=\"screen\" result=\"rg_channels\" />\n <feBlend in=\"rg_channels\" in2=\"blue_channel\" mode=\"screen\" result=\"rgb_channels\" />\n\n <feColorMatrix in=\"rgb_channels\" type=\"saturate\" values=\"1.2\" result=\"final\" />\n </filter>\n </defs>\n </svg>\n </>\n );\n }\n);\n","export function cn(...classes: (string | undefined | null | false)[]) {\n return classes.filter(Boolean).join(\" \");\n}\n","export interface MapOptions {\n width: number;\n height: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n distortion?: number;\n}\n\nconst VERT = `attribute vec4 position; void main(){ gl_Position = position; }`;\n\nconst FRAG = `\nprecision mediump float;\nuniform vec2 uRes;\nuniform float uRadius;\nuniform float uEdgeSize;\nuniform float uIntensity;\nuniform float uDistortion;\n\nfloat sdRoundedBox(vec2 p, vec2 b, float r){\n r = min(r, min(b.x, b.y));\n vec2 q = abs(p) - b + r;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;\n}\n\nfloat getHeight(vec2 p) {\n vec2 halfSize = uRes * 0.5 - 2.0;\n\n // Aumenta o tamanho base do box ligeiramente proporcinal ao edge\n halfSize += uEdgeSize * 0.2;\n\n float d = sdRoundedBox(p, halfSize, uRadius);\n\n float borderSoftness = uEdgeSize * uIntensity;\n d = max(d, -borderSoftness);\n return smoothstep(0.0, -borderSoftness, d);\n}\n\nvoid main(){\n vec2 p = gl_FragCoord.xy - uRes * 0.5;\n p.y = -p.y;\n\n // --- Displacement Map ---\n const vec2 e = vec2(1.0, 0.0);\n float hx = getHeight(p + e.xy) - getHeight(p - e.xy);\n float hy = getHeight(p + e.yx) - getHeight(p - e.yx);\n\n vec2 normal = vec2(-hx, -hy) * uDistortion;\n vec2 color = clamp(normal * 0.5 + 0.5, 0.0, 1.0);\n\n gl_FragColor = vec4(color.x, color.y, 0.5, 1.0);\n}\n`;\n\nfunction compile(gl: WebGLRenderingContext, type: number, src: string) {\n const s = gl.createShader(type)!;\n gl.shaderSource(s, src);\n gl.compileShader(s);\n return s;\n}\n\nlet _cachedProgram: { gl: WebGLRenderingContext; program: WebGLProgram; canvas: HTMLCanvasElement } | null = null;\n\nfunction getGL() {\n if (_cachedProgram) return _cachedProgram;\n\n const canvas = document.createElement(\"canvas\");\n const gl = canvas.getContext(\"webgl\", { preserveDrawingBuffer: true, premultipliedAlpha: false })!;\n\n const vs = compile(gl, gl.VERTEX_SHADER, VERT);\n const fs = compile(gl, gl.FRAGMENT_SHADER, FRAG);\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.useProgram(program);\n\n const buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const pos = gl.getAttribLocation(program, \"position\");\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n _cachedProgram = { gl, program, canvas };\n return _cachedProgram;\n}\n\nfunction render(width: number, height: number, radius: number, edgeSize: number, intensity: number, distortion: number): string {\n const { gl, program, canvas } = getGL();\n canvas.width = width;\n canvas.height = height;\n gl.viewport(0, 0, width, height);\n gl.clearColor(0.5, 0.5, 0.5, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.useProgram(program);\n\n gl.uniform2f(gl.getUniformLocation(program, \"uRes\"), width, height);\n gl.uniform1f(gl.getUniformLocation(program, \"uRadius\"), radius);\n gl.uniform1f(gl.getUniformLocation(program, \"uEdgeSize\"), edgeSize);\n gl.uniform1f(gl.getUniformLocation(program, \"uIntensity\"), intensity);\n gl.uniform1f(gl.getUniformLocation(program, \"uDistortion\"), distortion);\n\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n return canvas.toDataURL(\"image/png\");\n}\n\nexport function generateGlassMaps(opts: MapOptions): { displacement: string } {\n const { width, height, radius = 60, edgeSize = 40, intensity = 1.0, distortion = 15.0 } = opts;\n const r = Math.min(radius, width / 2, height / 2);\n\n return {\n displacement: render(width, height, r, edgeSize, intensity, distortion),\n };\n}\n"],"mappings":"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","names":["LiquidGlassButton","_a","_b"]}
|
|
1
|
+
{"version":3,"sources":["../src/liquid-glass-button.tsx","../src/utils.ts","../src/generate-displacement-map.ts"],"sourcesContent":["import React, { useRef, useEffect, useState, useId, forwardRef } from \"react\";\nimport gsap from \"gsap\";\nimport { cn } from \"./utils\";\nimport { generateGlassMaps } from \"./generate-displacement-map\";\n\nconst PADDING_PCT = 50;\n\nexport interface LiquidGlassButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Button width in px */\n width?: number;\n /** Button height in px */\n height?: number;\n /** Border radius in px */\n radius?: number;\n /** Edge thickness of the glass refraction (shader param) */\n edgeSize?: number;\n /** Edge intensity of the glass refraction (shader param) */\n intensity?: number;\n /** Blur applied to the displacement map (higher = softer transitions) */\n smoothness?: number;\n /** Normal scale in the shader (higher = more warped background) */\n distortion?: number;\n /** RGB channel separation - chromatic aberration amount */\n chroma?: number;\n /** Background color of the glass */\n glassColor?: string;\n /** feDisplacementMap scale - how much the background refracts */\n displacement?: number;\n /** Gaussian blur applied to the background */\n blur?: number;\n /** Saturation boost applied to the final result (1 = normal) */\n saturation?: number;\n /** Scale multiplier on hover */\n hoverScale?: number;\n /** Displacement scale on hover */\n hoverDisplacement?: number;\n /** Blur amount on hover */\n hoverBlur?: number;\n /** Chroma multiplier on hover (applied to chroma prop) */\n hoverChromaMultiplier?: number;\n /** Duration of hover animation in seconds */\n hoverDuration?: number;\n /** Disable all GSAP animations */\n disableAnimation?: boolean;\n}\n\nexport const LiquidGlassButton = forwardRef<HTMLButtonElement, LiquidGlassButtonProps>(\n function LiquidGlassButton({\n children, className, style,\n width = 300,\n height = 56,\n radius = 60,\n edgeSize,\n intensity,\n smoothness = 1,\n distortion,\n chroma = 3,\n glassColor = \"rgba(255,255,255,0.05)\",\n displacement = 35,\n blur = 2,\n saturation = 1.2,\n hoverScale = 1.05,\n hoverDisplacement = 65,\n hoverBlur = 4,\n hoverChromaMultiplier = 2.5,\n hoverDuration = 0.4,\n disableAnimation = false,\n ...props\n }, ref) {\n const internalRef = useRef<HTMLButtonElement>(null);\n const buttonRef = (ref as React.RefObject<HTMLButtonElement>) ?? internalRef;\n\n const blurRef = useRef<SVGFEGaussianBlurElement>(null);\n const displacerR = useRef<SVGFEDisplacementMapElement>(null);\n const displacerG = useRef<SVGFEDisplacementMapElement>(null);\n const displacerB = useRef<SVGFEDisplacementMapElement>(null);\n\n const filterId = \"lg\" + useId().replace(/:/g, \"\");\n\n const [maps, setMaps] = useState<ReturnType<typeof generateGlassMaps> | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const m = generateGlassMaps({ width, height, radius, edgeSize, intensity, distortion });\n const img = new Image();\n img.onload = () => {\n if (!cancelled) setMaps(m);\n };\n img.src = m.displacement;\n return () => { cancelled = true; };\n }, [width, height, radius, edgeSize, intensity, distortion]);\n\n useEffect(() => {\n const button = buttonRef.current;\n if (!button || !blurRef.current || disableAnimation) return;\n\n if (window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches) return;\n\n const fx = {\n displacement: displacement,\n blur: blur,\n chroma: chroma\n };\n\n const sync = () => {\n displacerR.current?.setAttribute(\"scale\", (fx.displacement + fx.chroma).toString());\n displacerG.current?.setAttribute(\"scale\", fx.displacement.toString());\n displacerB.current?.setAttribute(\"scale\", (fx.displacement - fx.chroma).toString());\n blurRef.current?.setAttribute(\"stdDeviation\", fx.blur.toString());\n };\n\n sync();\n\n const onEnter = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: hoverDisplacement,\n blur: hoverBlur,\n chroma: chroma * hoverChromaMultiplier,\n duration: hoverDuration,\n ease: \"power3.out\",\n onUpdate: sync\n });\n gsap.to(button, { scale: hoverScale, duration: hoverDuration, ease: \"power3.out\" });\n };\n\n const onLeave = () => {\n gsap.killTweensOf([fx, button]);\n gsap.to(fx, {\n displacement: displacement,\n blur: blur,\n chroma: chroma,\n duration: hoverDuration,\n ease: \"power2.out\",\n onUpdate: sync\n });\n gsap.to(button, { scale: 1, duration: hoverDuration, ease: \"power2.out\" });\n };\n\n const onClick = () => {\n gsap.killTweensOf(button);\n const cur = gsap.getProperty(button, \"scale\") as number;\n gsap.timeline()\n .to(button, { scale: cur * 0.95, duration: 0.1, ease: \"power2.in\" })\n .to(button, { scale: hoverScale, duration: 0.3, ease: \"back.out(2)\" });\n };\n\n button.addEventListener(\"pointerenter\", onEnter);\n button.addEventListener(\"pointerleave\", onLeave);\n button.addEventListener(\"click\", onClick);\n\n return () => {\n button.removeEventListener(\"pointerenter\", onEnter);\n button.removeEventListener(\"pointerleave\", onLeave);\n button.removeEventListener(\"click\", onClick);\n gsap.killTweensOf([button, fx]);\n };\n }, [buttonRef, maps, chroma, displacement, blur, hoverScale, hoverDisplacement, hoverBlur, hoverChromaMultiplier, hoverDuration, disableAnimation]);\n\n if (!maps) return null;\n\n return (\n <>\n <button\n ref={buttonRef}\n className={cn(\"relative overflow-hidden shadow-2xl shadow-black/20 cursor-pointer\", className)}\n style={{ width, height, borderRadius: radius, border: \"none\", background: glassColor, ...style }}\n {...props}\n >\n <div\n className=\"absolute inset-0 z-0\"\n style={{\n borderRadius: \"inherit\",\n backdropFilter: `url(#${filterId})`,\n WebkitBackdropFilter: `url(#${filterId})`,\n willChange: \"backdrop-filter\",\n transform: \"translateZ(0)\",\n }}\n />\n <div className=\"absolute inset-0 z-10 flex items-center justify-center font-bold text-white shadow-[inset_0_1px_1px_rgba(255,255,255,0.4)]\" style={{ background: \"linear-gradient(180deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.0) 100%)\", borderRadius: \"inherit\" }}>\n {children}\n </div>\n </button>\n\n <svg style={{ position: \"absolute\", width: 0, height: 0, pointerEvents: \"none\" }} aria-hidden=\"true\">\n <defs>\n <filter id={filterId} x={`-${PADDING_PCT}%`} y={`-${PADDING_PCT}%`} width={`${100 + PADDING_PCT * 2}%`} height={`${100 + PADDING_PCT * 2}%`} colorInterpolationFilters=\"sRGB\">\n <feGaussianBlur ref={blurRef} in=\"SourceGraphic\" stdDeviation={blur} result=\"blurred_bg\" edgeMode=\"duplicate\" />\n\n <feImage href={maps.displacement} result=\"disp_map\" x={`${PADDING_PCT}%`} y={`${PADDING_PCT}%`} width={`${100}%`} height={`${100}%`} preserveAspectRatio=\"none\" />\n\n <feGaussianBlur in=\"disp_map\" stdDeviation={smoothness} result=\"disp_blurred\" edgeMode=\"duplicate\" />\n\n <feDisplacementMap ref={displacerR} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement + chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_r\" />\n <feColorMatrix in=\"displaced_r\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"red_channel\" />\n\n <feDisplacementMap ref={displacerG} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_g\" />\n <feColorMatrix in=\"displaced_g\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"green_channel\" />\n\n <feDisplacementMap ref={displacerB} in=\"blurred_bg\" in2=\"disp_blurred\" scale={displacement - chroma} xChannelSelector=\"R\" yChannelSelector=\"G\" result=\"displaced_b\" />\n <feColorMatrix in=\"displaced_b\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"blue_channel\" />\n\n <feBlend in=\"red_channel\" in2=\"green_channel\" mode=\"screen\" result=\"rg_channels\" />\n <feBlend in=\"rg_channels\" in2=\"blue_channel\" mode=\"screen\" result=\"rgb_channels\" />\n\n <feColorMatrix in=\"rgb_channels\" type=\"saturate\" values={saturation.toString()} result=\"final\" />\n </filter>\n </defs>\n </svg>\n </>\n );\n }\n);\n","export function cn(...classes: (string | undefined | null | false)[]) {\n return classes.filter(Boolean).join(\" \");\n}\n","export interface MapOptions {\n width: number;\n height: number;\n radius?: number;\n edgeSize?: number;\n intensity?: number;\n distortion?: number;\n}\n\nconst VERT = `attribute vec4 position; void main(){ gl_Position = position; }`;\n\nconst FRAG = `\nprecision mediump float;\nuniform vec2 uRes;\nuniform float uRadius;\nuniform float uEdgeSize;\nuniform float uIntensity;\nuniform float uDistortion;\n\nfloat sdRoundedBox(vec2 p, vec2 b, float r){\n r = min(r, min(b.x, b.y));\n vec2 q = abs(p) - b + r;\n return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;\n}\n\nfloat getHeight(vec2 p) {\n vec2 halfSize = uRes * 0.5 - 2.0;\n\n // Aumenta o tamanho base do box ligeiramente proporcinal ao edge\n halfSize += uEdgeSize * 0.2;\n\n float d = sdRoundedBox(p, halfSize, uRadius);\n\n float borderSoftness = uEdgeSize * uIntensity;\n d = max(d, -borderSoftness);\n return smoothstep(0.0, -borderSoftness, d);\n}\n\nvoid main(){\n vec2 p = gl_FragCoord.xy - uRes * 0.5;\n p.y = -p.y;\n\n // --- Displacement Map ---\n const vec2 e = vec2(1.0, 0.0);\n float hx = getHeight(p + e.xy) - getHeight(p - e.xy);\n float hy = getHeight(p + e.yx) - getHeight(p - e.yx);\n\n vec2 normal = vec2(-hx, -hy) * uDistortion;\n vec2 color = clamp(normal * 0.5 + 0.5, 0.0, 1.0);\n\n gl_FragColor = vec4(color.x, color.y, 0.5, 1.0);\n}\n`;\n\nfunction compile(gl: WebGLRenderingContext, type: number, src: string) {\n const s = gl.createShader(type)!;\n gl.shaderSource(s, src);\n gl.compileShader(s);\n return s;\n}\n\nlet _cachedProgram: { gl: WebGLRenderingContext; program: WebGLProgram; canvas: HTMLCanvasElement } | null = null;\n\nfunction getGL() {\n if (_cachedProgram) return _cachedProgram;\n\n const canvas = document.createElement(\"canvas\");\n const gl = canvas.getContext(\"webgl\", { preserveDrawingBuffer: true, premultipliedAlpha: false })!;\n\n const vs = compile(gl, gl.VERTEX_SHADER, VERT);\n const fs = compile(gl, gl.FRAGMENT_SHADER, FRAG);\n const program = gl.createProgram()!;\n gl.attachShader(program, vs);\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.useProgram(program);\n\n const buf = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buf);\n gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);\n const pos = gl.getAttribLocation(program, \"position\");\n gl.enableVertexAttribArray(pos);\n gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);\n\n _cachedProgram = { gl, program, canvas };\n return _cachedProgram;\n}\n\nfunction render(width: number, height: number, radius: number, edgeSize: number, intensity: number, distortion: number): string {\n const { gl, program, canvas } = getGL();\n canvas.width = width;\n canvas.height = height;\n gl.viewport(0, 0, width, height);\n gl.clearColor(0.5, 0.5, 0.5, 1.0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.useProgram(program);\n\n gl.uniform2f(gl.getUniformLocation(program, \"uRes\"), width, height);\n gl.uniform1f(gl.getUniformLocation(program, \"uRadius\"), radius);\n gl.uniform1f(gl.getUniformLocation(program, \"uEdgeSize\"), edgeSize);\n gl.uniform1f(gl.getUniformLocation(program, \"uIntensity\"), intensity);\n gl.uniform1f(gl.getUniformLocation(program, \"uDistortion\"), distortion);\n\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n return canvas.toDataURL(\"image/png\");\n}\n\nexport function generateGlassMaps(opts: MapOptions): { displacement: string } {\n const { width, height, radius = 60, edgeSize = 40, intensity = 1.0, distortion = 15.0 } = opts;\n const r = Math.min(radius, width / 2, height / 2);\n\n return {\n displacement: render(width, height, r, edgeSize, intensity, distortion),\n };\n}\n"],"mappings":"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","names":["LiquidGlassButton","_a","_b"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marcosdemik/liquidglass",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Liquid Glass UI effect for React - glassmorphism refraction with SVG filters, WebGL and GSAP animations",
|
|
5
5
|
"author": "Marcos Demik <marcosdemik>",
|
|
6
6
|
"license": "MIT",
|