@persian-caesar/liquid-glass 1.0.0 → 1.0.2
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 +2 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
A lightweight, performant, and fully customizable React component that creates a stunning liquid glass / fluid glassmorphism effect using SVG filters and canvas-generated displacement maps.
|
|
6
6
|
|
|
7
|
-
*
|
|
7
|
+

|
|
9
8
|
|
|
10
9
|
---
|
|
11
10
|
|
|
@@ -151,4 +150,4 @@ npm run build # production build
|
|
|
151
150
|
|
|
152
151
|
## Author
|
|
153
152
|
|
|
154
|
-
Made with ❤️ by **[Persian-Caesar](https://github.com/persian-caesar/)**
|
|
153
|
+
Made with ❤️ by **[Persian-Caesar](https://github.com/persian-caesar/)**
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useCallback as b,useEffect as
|
|
1
|
+
import{useCallback as b,useEffect as _,useId as rt,useRef as d,useState as k}from"react";import{Fragment as it,jsx as l,jsxs as A}from"react/jsx-runtime";var at=({borderRadius:S=void 0,blur:O=.25,contrast:z=1.2,brightness:W=1.05,saturation:B=1.1,shadowIntensity:w=.25,displacementScale:y=1,elasticity:R=.6,className:J="",style:K={},children:Q,as:X="div",filterId:Y})=>{let v=d(null),Z=d(null),G=d(null),$=d(null),q=d(null),j=rt(),f=Y||`liquid-glass-${j.replace(/:/g,"-")}`,[u,tt]=k(300),[h,et]=k(200),m=1,x=b((t,n,s)=>(s=Math.max(0,Math.min(1,(s-t)/(n-t))),s*s*(3-2*s)),[]),E=b((t,n)=>Math.sqrt(t*t+n*n),[]),I=b((t,n,s,i,e)=>{let r=Math.abs(t)-s+e,o=Math.abs(n)-i+e;return Math.min(Math.max(r,o),0)+E(Math.max(r,0),Math.max(o,0))-e},[E]),C=b(()=>{let t=G.current,n=$.current,s=q.current;if(!t||!n||!s)return;let i=t.getContext("2d");if(!i)return;let e=Math.max(1,Math.floor(u*m)),r=Math.max(1,Math.floor(h*m));if(e<=0||r<=0)return;(t.width!==e||t.height!==r)&&(t.width=e,t.height=r);let o=new Uint8ClampedArray(e*r*4),c=0,M=[];for(let a=0;a<o.length;a+=4){let p=a/4%e,g=Math.floor(a/4/e),F={x:p/e,y:g/r},P=F.x-.5,V=F.y-.5,nt=I(P,V,.3,.2,R),st=x(.8,0,nt-.15),H=x(0,1,st),N={x:P*H+.5,y:V*H+.5},T=N.x*e-p,U=N.y*r-g;c=Math.max(c,Math.abs(T),Math.abs(U)),M.push(T,U)}c*=.5*y;let L=0;for(let a=0;a<o.length;a+=4){let p=M[L++]/c+.5,g=M[L++]/c+.5;o[a]=p*255,o[a+1]=g*255,o[a+2]=0,o[a+3]=255}i.putImageData(new ImageData(o,e,r),0,0),n.setAttributeNS("http://www.w3.org/1999/xlink","href",t.toDataURL()),s.setAttribute("scale",(c/m).toString())},[u,h,y,R,I,x]);_(()=>{let t=v.current;if(!t)return;let n=new ResizeObserver(s=>{for(let i of s){let{width:e,height:r}=i.contentRect;tt(Math.max(e,100)),et(Math.max(r,100))}});return n.observe(t),()=>n.disconnect()},[]),_(()=>{C()},[C]);let D={backdropFilter:`url(#${f}_filter) blur(${O}px) contrast(${z}) brightness(${W}) saturate(${B})`,boxShadow:w>0?`0 4px 8px rgba(0, 0, 0, ${w}), 0 -10px 25px inset rgba(0, 0, 0, 0.15)`:void 0};return S&&(D.borderRadius=`${S}px`),A(it,{children:[l("svg",{ref:Z,xmlns:"http://www.w3.org/2000/svg",width:"0",height:"0",style:{position:"fixed",top:0,left:0,pointerEvents:"none"},children:l("defs",{children:A("filter",{id:`${f}_filter`,filterUnits:"userSpaceOnUse",colorInterpolationFilters:"sRGB",x:"0",y:"0",width:u.toString(),height:h.toString(),children:[l("feImage",{ref:$,id:`${f}_map`,width:u.toString(),height:h.toString()}),l("feDisplacementMap",{ref:q,in:"SourceGraphic",in2:`${f}_map`,xChannelSelector:"R",yChannelSelector:"G"})]})})}),l("canvas",{ref:G,width:u*m,height:h*m,style:{display:"none"}}),l(X,{ref:v,className:`liquid-glass ${J}`,style:{...D,...K},children:Q})]})},ot=at;export{ot as LiquidGlass};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/LiquidGlass.tsx"],"sourcesContent":["import type React from \"react\";\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\n\nexport interface LiquidGlassProps {\n // Core effect options\n borderRadius?: number;\n blur?: number;\n contrast?: number;\n brightness?: number;\n saturation?: number;\n shadowIntensity?: number;\n displacementScale?: number;\n elasticity?: number;\n\n // Customization\n className?: string;\n style?: React.CSSProperties; \n children?: React.ReactNode;\n\n // Advanced\n as?: React.ElementType; \n filterId?: string; \n}\n\nconst LiquidGlass: React.FC<LiquidGlassProps> = ({\n borderRadius = 20,\n blur = 0.25,\n contrast = 1.2,\n brightness = 1.05,\n saturation = 1.1,\n shadowIntensity = 0.25,\n displacementScale = 1,\n elasticity = 0.6,\n\n className = \"\",\n style = {},\n children,\n as: Component = \"div\",\n filterId,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const feImageRef = useRef<SVGFEImageElement>(null);\n const feDisplacementMapRef = useRef<SVGFEDisplacementMapElement>(null);\n\n const reactId = useId();\n const id = filterId || `liquid-glass-${reactId.replace(/:/g, \"-\")}`;\n\n const [width, setWidth] = useState(300);\n const [height, setHeight] = useState(200);\n const canvasDPI = 1;\n\n // Utility functions (همان قبلیها)\n const smoothStep = useCallback((a: number, b: number, t: number) => {\n t = Math.max(0, Math.min(1, (t - a) / (b - a)));\n return t * t * (3 - 2 * t);\n }, []);\n\n const length = useCallback((x: number, y: number) => Math.sqrt(x * x + y * y), []);\n\n const roundedRectSDF = useCallback(\n (x: number, y: number, w: number, h: number, radius: number) => {\n const qx = Math.abs(x) - w + radius;\n const qy = Math.abs(y) - h + radius;\n return (\n Math.min(Math.max(qx, qy), 0) +\n length(Math.max(qx, 0), Math.max(qy, 0)) -\n radius\n );\n },\n [length]\n );\n\n const updateShader = useCallback(() => {\n // ... (کد updateShader قبلی بدون تغییر نگه داشته میشه)\n const canvas = canvasRef.current;\n const feImage = feImageRef.current;\n const feDisplacementMap = feDisplacementMapRef.current;\n if (!canvas || !feImage || !feDisplacementMap) return;\n\n const context = canvas.getContext(\"2d\");\n if (!context) return;\n\n const w = Math.max(1, Math.floor(width * canvasDPI));\n const h = Math.max(1, Math.floor(height * canvasDPI));\n\n if (w <= 0 || h <= 0) return;\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n\n const data = new Uint8ClampedArray(w * h * 4);\n let maxScale = 0;\n const rawValues: number[] = [];\n\n for (let i = 0; i < data.length; i += 4) {\n const x = (i / 4) % w;\n const y = Math.floor(i / 4 / w);\n const uv = { x: x / w, y: y / h };\n\n const ix = uv.x - 0.5;\n const iy = uv.y - 0.5;\n const distanceToEdge = roundedRectSDF(ix, iy, 0.3, 0.2, elasticity);\n const displacement = smoothStep(0.8, 0, distanceToEdge - 0.15);\n const scaled = smoothStep(0, 1, displacement);\n\n const pos = {\n x: ix * scaled + 0.5,\n y: iy * scaled + 0.5,\n };\n\n const dx = pos.x * w - x;\n const dy = pos.y * h - y;\n\n maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy));\n rawValues.push(dx, dy);\n }\n\n maxScale *= 0.5 * displacementScale;\n\n let index = 0;\n for (let i = 0; i < data.length; i += 4) {\n const r = rawValues[index++] / maxScale + 0.5;\n const g = rawValues[index++] / maxScale + 0.5;\n data[i] = r * 255;\n data[i + 1] = g * 255;\n data[i + 2] = 0;\n data[i + 3] = 255;\n }\n\n context.putImageData(new ImageData(data, w, h), 0, 0);\n feImage.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", canvas.toDataURL());\n feDisplacementMap.setAttribute(\"scale\", (maxScale / canvasDPI).toString());\n }, [width, height, displacementScale, elasticity, roundedRectSDF, smoothStep]);\n\n // Resize Observer\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width: newWidth, height: newHeight } = entry.contentRect;\n setWidth(Math.max(newWidth, 100));\n setHeight(Math.max(newHeight, 100));\n }\n });\n\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }, []);\n\n // Update shader when needed\n useEffect(() => {\n updateShader();\n }, [updateShader]);\n\n const filterStyle: React.CSSProperties = {\n borderRadius: `${borderRadius}px`,\n backdropFilter: `url(#${id}_filter) blur(${blur}px) contrast(${contrast}) brightness(${brightness}) saturate(${saturation})`,\n boxShadow: shadowIntensity > 0\n ? `0 4px 8px rgba(0, 0, 0, ${shadowIntensity}), 0 -10px 25px inset rgba(0, 0, 0, 0.15)`\n : undefined,\n };\n\n return (\n <>\n {/* SVG Filter - Hidden */}\n <svg\n ref={svgRef}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"0\"\n height=\"0\"\n style={{ position: \"fixed\", top: 0, left: 0, pointerEvents: \"none\" }}\n >\n <defs>\n <filter\n id={`${id}_filter`}\n filterUnits=\"userSpaceOnUse\"\n colorInterpolationFilters=\"sRGB\"\n x=\"0\"\n y=\"0\"\n width={width.toString()}\n height={height.toString()}\n >\n <feImage ref={feImageRef} id={`${id}_map`} width={width.toString()} height={height.toString()} />\n <feDisplacementMap\n ref={feDisplacementMapRef}\n in=\"SourceGraphic\"\n in2={`${id}_map`}\n xChannelSelector=\"R\"\n yChannelSelector=\"G\"\n />\n </filter>\n </defs>\n </svg>\n\n {/* Hidden Canvas */}\n <canvas\n ref={canvasRef}\n width={width * canvasDPI}\n height={height * canvasDPI}\n style={{ display: \"none\" }}\n />\n\n {/* Main Glass Container - Fully Customizable */}\n <Component\n ref={containerRef}\n className={`liquid-glass ${className}`}\n style={{\n ...filterStyle,\n ...style, \n }}\n >\n {children}\n </Component>\n </>\n );\n};\n\nexport default LiquidGlass;"],"mappings":"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","names":["useCallback","useEffect","useId","useRef","useState","Fragment","jsx","jsxs","LiquidGlass","borderRadius","blur","contrast","brightness","saturation","shadowIntensity","displacementScale","elasticity","className","style","children","Component","filterId","containerRef","svgRef","canvasRef","feImageRef","feDisplacementMapRef","reactId","id","width","setWidth","height","setHeight","canvasDPI","smoothStep","a","b","t","length","x","y","roundedRectSDF","w","h","radius","qx","qy","updateShader","canvas","feImage","feDisplacementMap","context","data","maxScale","rawValues","i","uv","ix","iy","distanceToEdge","displacement","scaled","pos","dx","dy","index","r","container","resizeObserver","entries","entry","newWidth","newHeight","filterStyle","LiquidGlass_default"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/LiquidGlass.tsx"],"sourcesContent":["import type React from \"react\";\nimport { useCallback, useEffect, useId, useRef, useState } from \"react\";\n\nexport interface LiquidGlassProps {\n // Core effect options\n borderRadius?: number;\n blur?: number;\n contrast?: number;\n brightness?: number;\n saturation?: number;\n shadowIntensity?: number;\n displacementScale?: number;\n elasticity?: number;\n\n // Customization\n className?: string;\n style?: React.CSSProperties;\n children?: React.ReactNode;\n\n // Advanced\n as?: React.ElementType;\n filterId?: string;\n}\n\nconst LiquidGlass: React.FC<LiquidGlassProps> = ({\n borderRadius = undefined,\n blur = 0.25,\n contrast = 1.2,\n brightness = 1.05,\n saturation = 1.1,\n shadowIntensity = 0.25,\n displacementScale = 1,\n elasticity = 0.6,\n\n className = \"\",\n style = {},\n children,\n as: Component = \"div\",\n filterId,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const feImageRef = useRef<SVGFEImageElement>(null);\n const feDisplacementMapRef = useRef<SVGFEDisplacementMapElement>(null);\n\n const reactId = useId();\n const id = filterId || `liquid-glass-${reactId.replace(/:/g, \"-\")}`;\n\n const [width, setWidth] = useState(300);\n const [height, setHeight] = useState(200);\n const canvasDPI = 1;\n\n // Utility functions (همان قبلیها)\n const smoothStep = useCallback((a: number, b: number, t: number) => {\n t = Math.max(0, Math.min(1, (t - a) / (b - a)));\n return t * t * (3 - 2 * t);\n }, []);\n\n const length = useCallback((x: number, y: number) => Math.sqrt(x * x + y * y), []);\n\n const roundedRectSDF = useCallback(\n (x: number, y: number, w: number, h: number, radius: number) => {\n const qx = Math.abs(x) - w + radius;\n const qy = Math.abs(y) - h + radius;\n return (\n Math.min(Math.max(qx, qy), 0) +\n length(Math.max(qx, 0), Math.max(qy, 0)) -\n radius\n );\n },\n [length]\n );\n\n const updateShader = useCallback(() => {\n // ... (کد updateShader قبلی بدون تغییر نگه داشته میشه)\n const canvas = canvasRef.current;\n const feImage = feImageRef.current;\n const feDisplacementMap = feDisplacementMapRef.current;\n if (!canvas || !feImage || !feDisplacementMap) return;\n\n const context = canvas.getContext(\"2d\");\n if (!context) return;\n\n const w = Math.max(1, Math.floor(width * canvasDPI));\n const h = Math.max(1, Math.floor(height * canvasDPI));\n\n if (w <= 0 || h <= 0) return;\n if (canvas.width !== w || canvas.height !== h) {\n canvas.width = w;\n canvas.height = h;\n }\n\n const data = new Uint8ClampedArray(w * h * 4);\n let maxScale = 0;\n const rawValues: number[] = [];\n\n for (let i = 0; i < data.length; i += 4) {\n const x = (i / 4) % w;\n const y = Math.floor(i / 4 / w);\n const uv = { x: x / w, y: y / h };\n\n const ix = uv.x - 0.5;\n const iy = uv.y - 0.5;\n const distanceToEdge = roundedRectSDF(ix, iy, 0.3, 0.2, elasticity);\n const displacement = smoothStep(0.8, 0, distanceToEdge - 0.15);\n const scaled = smoothStep(0, 1, displacement);\n\n const pos = {\n x: ix * scaled + 0.5,\n y: iy * scaled + 0.5,\n };\n\n const dx = pos.x * w - x;\n const dy = pos.y * h - y;\n\n maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy));\n rawValues.push(dx, dy);\n }\n\n maxScale *= 0.5 * displacementScale;\n\n let index = 0;\n for (let i = 0; i < data.length; i += 4) {\n const r = rawValues[index++] / maxScale + 0.5;\n const g = rawValues[index++] / maxScale + 0.5;\n data[i] = r * 255;\n data[i + 1] = g * 255;\n data[i + 2] = 0;\n data[i + 3] = 255;\n }\n\n context.putImageData(new ImageData(data, w, h), 0, 0);\n feImage.setAttributeNS(\"http://www.w3.org/1999/xlink\", \"href\", canvas.toDataURL());\n feDisplacementMap.setAttribute(\"scale\", (maxScale / canvasDPI).toString());\n }, [width, height, displacementScale, elasticity, roundedRectSDF, smoothStep]);\n\n // Resize Observer\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n for (const entry of entries) {\n const { width: newWidth, height: newHeight } = entry.contentRect;\n setWidth(Math.max(newWidth, 100));\n setHeight(Math.max(newHeight, 100));\n }\n });\n\n resizeObserver.observe(container);\n return () => resizeObserver.disconnect();\n }, []);\n\n // Update shader when needed\n useEffect(() => {\n updateShader();\n }, [updateShader]);\n\n const filterStyle: React.CSSProperties = {\n backdropFilter: `url(#${id}_filter) blur(${blur}px) contrast(${contrast}) brightness(${brightness}) saturate(${saturation})`,\n boxShadow: shadowIntensity > 0\n ? `0 4px 8px rgba(0, 0, 0, ${shadowIntensity}), 0 -10px 25px inset rgba(0, 0, 0, 0.15)`\n : undefined,\n };\n\n if (borderRadius) {\n filterStyle.borderRadius = `${borderRadius}px`;\n }\n\n return (\n <>\n {/* SVG Filter - Hidden */}\n <svg\n ref={svgRef}\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"0\"\n height=\"0\"\n style={{ position: \"fixed\", top: 0, left: 0, pointerEvents: \"none\" }}\n >\n <defs>\n <filter\n id={`${id}_filter`}\n filterUnits=\"userSpaceOnUse\"\n colorInterpolationFilters=\"sRGB\"\n x=\"0\"\n y=\"0\"\n width={width.toString()}\n height={height.toString()}\n >\n <feImage ref={feImageRef} id={`${id}_map`} width={width.toString()} height={height.toString()} />\n <feDisplacementMap\n ref={feDisplacementMapRef}\n in=\"SourceGraphic\"\n in2={`${id}_map`}\n xChannelSelector=\"R\"\n yChannelSelector=\"G\"\n />\n </filter>\n </defs>\n </svg>\n\n {/* Hidden Canvas */}\n <canvas\n ref={canvasRef}\n width={width * canvasDPI}\n height={height * canvasDPI}\n style={{ display: \"none\" }}\n />\n\n {/* Main Glass Container - Fully Customizable */}\n <Component\n ref={containerRef}\n className={`liquid-glass ${className}`}\n style={{\n ...filterStyle,\n ...style,\n }}\n >\n {children}\n </Component>\n </>\n );\n};\n\nexport default LiquidGlass;"],"mappings":"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","names":["useCallback","useEffect","useId","useRef","useState","Fragment","jsx","jsxs","LiquidGlass","borderRadius","blur","contrast","brightness","saturation","shadowIntensity","displacementScale","elasticity","className","style","children","Component","filterId","containerRef","svgRef","canvasRef","feImageRef","feDisplacementMapRef","reactId","id","width","setWidth","height","setHeight","canvasDPI","smoothStep","a","b","t","length","x","y","roundedRectSDF","w","h","radius","qx","qy","updateShader","canvas","feImage","feDisplacementMap","context","data","maxScale","rawValues","i","uv","ix","iy","distanceToEdge","displacement","scaled","pos","dx","dy","index","r","container","resizeObserver","entries","entry","newWidth","newHeight","filterStyle","LiquidGlass_default"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@persian-caesar/liquid-glass",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "Liquid Glass effect component for React - Beautiful glassmorphism with displacement distortion.",
|
|
5
5
|
"author": "Sobhan-SRZA (mr.sinre) & Persian Caesar",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"build": "tsup",
|
|
32
32
|
"dev": "tsup --watch",
|
|
33
33
|
"clean": "rm -rf dist",
|
|
34
|
+
"test": "vite ./example",
|
|
34
35
|
"prepublishOnly": "npm run clean && npm run build"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
@@ -38,10 +39,14 @@
|
|
|
38
39
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
41
|
-
"
|
|
42
|
-
"tsup": "^8.4.0",
|
|
42
|
+
"@tailwindcss/vite": "^4.3.1",
|
|
43
43
|
"@types/react": "^19.0.0",
|
|
44
|
-
"@types/react-dom": "^19.0.0"
|
|
44
|
+
"@types/react-dom": "^19.0.0",
|
|
45
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
46
|
+
"tailwindcss": "^4.3.1",
|
|
47
|
+
"tsup": "^8.4.0",
|
|
48
|
+
"typescript": "^5.8.0",
|
|
49
|
+
"vite": "^8.1.0"
|
|
45
50
|
},
|
|
46
51
|
"keywords": [
|
|
47
52
|
"react",
|
|
@@ -61,4 +66,4 @@
|
|
|
61
66
|
"sobhan-srza",
|
|
62
67
|
"framer-motion-alternative"
|
|
63
68
|
]
|
|
64
|
-
}
|
|
69
|
+
}
|