UNPKG

simple-liquid-glass

Version:

A React component for creating liquid glass morphism effects with customizable distortion and blur

1 lines 51.9 kB
{"version":3,"file":"index.cjs","sources":["../src/index.tsx"],"sourcesContent":["import React, { useMemo, useEffect, useRef, useState, useId } from 'react';\n\ntype DisplacementChannel = 'R' | 'G' | 'B' | 'A';\n\nexport interface LiquidGlassProps extends React.HTMLAttributes<HTMLDivElement> {\n children?: React.ReactNode;\n mode?: string;\n scale?: number;\n radius?: number;\n border?: number;\n lightness?: number;\n displace?: number;\n alpha?: number;\n blur?: number;\n dispersion?: number;\n saturation?: number; // percent, 100 = normal\n aberrationIntensity?: number; // multiplier for chromatic separation\n frost?: number;\n borderColor?: string;\n glassColor?: string; // must be semi-transparent\n autoTextColor?: boolean; // auto-detect background and set text color\n textOnDark?: string; // text color when background is dark\n textOnLight?: string; // text color when background is light\n forceTextColor?: boolean; // enforce text color on descendants\n autoTextColorMode?: 'global' | 'perPixel'; // strategy for auto text color\n perPixelTargetSelector?: string; // CSS selector for elements to adapt in perPixel mode\n className?: string;\n style?: React.CSSProperties;\n // iOS fallback controls\n iosMinBlur?: number; // minimum blur on iOS even when blur=0\n iosBlurMode?: 'auto' | 'off'; // allow opting out of the forced iOS blur\n}\n\nfunction isSemiTransparentColor(input: string | undefined | null): boolean {\n if (!input) return false;\n const color = input.trim();\n // rgba(r,g,b,a)\n const rgba = /^rgba\\(\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*\\d+\\s*,\\s*(\\d*\\.?\\d+)\\s*\\)$/i.exec(color);\n if (rgba) {\n const a = parseFloat(rgba[1]);\n return a > 0 && a < 1;\n }\n // hsla(h,s,l,a)\n const hsla = /^hsla\\(.*?,\\s*(\\d*\\.?\\d+)\\s*\\)$/i.exec(color);\n if (hsla) {\n const a = parseFloat(hsla[1]);\n return a > 0 && a < 1;\n }\n // hsl(h s l / a) or hsl(h,s%,l%,a) with slash\n const hslSlash = /^hsl\\(.*?\\/\\s*(\\d*\\.?\\d+)\\s*\\)$/i.exec(color);\n if (hslSlash) {\n const a = parseFloat(hslSlash[1]);\n return a > 0 && a < 1;\n }\n // Hex with alpha: #RGBA or #RRGGBBAA\n const hex4 = /^#([0-9a-f]{4})$/i.exec(color);\n if (hex4) {\n const aHex = hex4[1].slice(3, 4);\n const a = parseInt(aHex + aHex, 16) / 255; // expand to 8-bit\n return a > 0 && a < 1;\n }\n const hex8 = /^#([0-9a-f]{8})$/i.exec(color);\n if (hex8) {\n const aHex = hex8[1].slice(6, 8);\n const a = parseInt(aHex, 16) / 255;\n return a > 0 && a < 1;\n }\n // No detectable alpha\n return false;\n}\n\nconst DEFAULT_WIDTH = 400;\nconst DEFAULT_HEIGHT = 200;\n\nconst preset = {\n scale: 160,\n radius: 50,\n border: 0.05,\n lightness: 53,\n displace: 5,\n alpha: 0.9,\n blur: 0,\n dispersion: 50,\n saturation: 140,\n aberrationIntensity: 2,\n frost: 0.1,\n borderColor: \"rgba(120, 120, 120, 0.7)\"\n};\n\nexport function LiquidGlass({ \n children,\n mode = \"preset\",\n scale = 160,\n radius = 50,\n border = 0.05,\n lightness = 53,\n displace = 5,\n alpha = 0.9,\n blur = 0,\n dispersion = 50,\n saturation = 140,\n aberrationIntensity = 2,\n frost = 0.1,\n borderColor = \"rgba(120, 120, 120, 0.7)\",\n glassColor,\n autoTextColor = false,\n autoTextColorMode = 'global',\n perPixelTargetSelector = '[data-lg-autotext]',\n textOnDark = '#ffffff',\n textOnLight = '#111111',\n forceTextColor = false,\n className = \"\",\n style = {},\n iosMinBlur = 2,\n iosBlurMode = 'auto',\n ...props\n}: LiquidGlassProps) {\n // Configuration based on mode\n let config: {\n mode: string;\n scale: number;\n radius: number;\n border: number;\n lightness: number;\n displace: number;\n alpha: number;\n blur: number;\n dispersion: number;\n saturation: number;\n aberrationIntensity: number;\n frost: number;\n borderColor: string;\n blend: 'difference';\n x: DisplacementChannel;\n y: DisplacementChannel;\n };\n if (mode === \"preset\") {\n config = {\n // baseline to preset, but allow incoming props to override as per library behavior\n ...preset,\n scale,\n radius,\n border,\n lightness,\n displace,\n alpha,\n blur,\n dispersion,\n saturation,\n aberrationIntensity,\n frost,\n borderColor,\n mode: \"preset\",\n blend: \"difference\",\n x: \"R\",\n y: \"B\",\n };\n } else {\n config = {\n mode,\n scale,\n radius,\n border,\n lightness,\n displace,\n alpha,\n blur,\n dispersion,\n saturation,\n aberrationIntensity,\n frost,\n borderColor,\n blend: \"difference\",\n x: \"R\",\n y: \"B\"\n };\n }\n\n const containerRef = useRef<HTMLDivElement | null>(null);\n const glassRef = useRef<HTMLDivElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n const mirrorsRef = useRef<HTMLElement[]>([]);\n const [dimensions, setDimensions] = useState({\n width: DEFAULT_WIDTH,\n height: DEFAULT_HEIGHT\n });\n const [effectiveTextColor, setEffectiveTextColor] = useState<string>(textOnLight);\n const textClassNameRef = useRef<string | null>(null);\n if (!textClassNameRef.current) {\n textClassNameRef.current = `lg-text-${Math.random().toString(36).slice(2, 9)}`;\n }\n const perPixelClassNameRef = useRef<string | null>(null);\n if (!perPixelClassNameRef.current) {\n perPixelClassNameRef.current = `lg-perpixel-${Math.random().toString(36).slice(2, 9)}`;\n }\n\n function parseCssColorToRgba(color: string): { r: number; g: number; b: number; a: number } | null {\n const c = color.trim();\n let m: RegExpExecArray | null;\n if ((m = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)(?:\\s*,\\s*(\\d*\\.?\\d+))?\\s*\\)$/i.exec(c))) {\n const r = parseInt(m[1], 10);\n const g = parseInt(m[2], 10);\n const b = parseInt(m[3], 10);\n const a = m[4] !== undefined ? parseFloat(m[4]) : 1;\n return { r, g, b, a };\n }\n if ((m = /^#([0-9a-f]{3})$/i.exec(c))) {\n const hex = m[1];\n const r = parseInt(hex[0] + hex[0], 16);\n const g = parseInt(hex[1] + hex[1], 16);\n const b = parseInt(hex[2] + hex[2], 16);\n return { r, g, b, a: 1 };\n }\n if ((m = /^#([0-9a-f]{4})$/i.exec(c))) {\n const hex = m[1];\n const r = parseInt(hex[0] + hex[0], 16);\n const g = parseInt(hex[1] + hex[1], 16);\n const b = parseInt(hex[2] + hex[2], 16);\n const a = parseInt(hex[3] + hex[3], 16) / 255;\n return { r, g, b, a };\n }\n if ((m = /^#([0-9a-f]{6})$/i.exec(c))) {\n const hex = m[1];\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n return { r, g, b, a: 1 };\n }\n if ((m = /^#([0-9a-f]{8})$/i.exec(c))) {\n const hex = m[1];\n const r = parseInt(hex.slice(0, 2), 16);\n const g = parseInt(hex.slice(2, 4), 16);\n const b = parseInt(hex.slice(4, 6), 16);\n const a = parseInt(hex.slice(6, 8), 16) / 255;\n return { r, g, b, a };\n }\n // hsla/hsl are not needed for detection since computed style returns rgb/rgba\n return null;\n }\n\n function findNearestOpaqueBackground(element: HTMLElement | null): { r: number; g: number; b: number; a: number } | null {\n let el: HTMLElement | null = element;\n while (el) {\n const style = getComputedStyle(el);\n const bg = style.backgroundColor;\n const parsed = bg ? parseCssColorToRgba(bg) : null;\n if (parsed && parsed.a > 0) {\n return parsed;\n }\n el = el.parentElement;\n }\n const bodyBg = getComputedStyle(document.body).backgroundColor;\n return bodyBg ? parseCssColorToRgba(bodyBg) : null;\n }\n\n function isRgbColorDark(rgb: { r: number; g: number; b: number }): boolean {\n const srgb = [rgb.r, rgb.g, rgb.b].map(v => v / 255);\n const linear = srgb.map(c => (c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)));\n const luminance = 0.2126 * linear[0] + 0.7152 * linear[1] + 0.0722 * linear[2];\n return luminance < 0.5; // threshold\n }\n\n // Update dimensions when the container size changes\n useEffect(() => {\n if (!containerRef.current) return;\n\n const updateDimensions = () => {\n if (!containerRef.current) return;\n\n const { width, height } = containerRef.current.getBoundingClientRect();\n if (width === 0 || height === 0) return;\n \n setDimensions({ width, height });\n };\n\n // Initial measurement\n updateDimensions();\n\n // Create ResizeObserver to watch for size changes\n const resizeObserver = new ResizeObserver(updateDimensions);\n resizeObserver.observe(containerRef.current);\n\n return () => resizeObserver.disconnect();\n }, []);\n\n // Auto-detect background and set text color for children; updates on resize/scroll/mutations\n useEffect(() => {\n if (!autoTextColor) return;\n if (autoTextColorMode === 'perPixel') return; // CSS-only in perPixel mode\n\n const update = () => {\n const target = containerRef.current?.parentElement ?? null;\n if (!target) return;\n const bg = findNearestOpaqueBackground(target);\n if (!bg) {\n setEffectiveTextColor(textOnLight);\n return;\n }\n const dark = isRgbColorDark({ r: bg.r, g: bg.g, b: bg.b });\n setEffectiveTextColor(dark ? textOnDark : textOnLight);\n };\n\n update();\n\n const onWindowChange = () => update();\n window.addEventListener('resize', onWindowChange);\n window.addEventListener('scroll', onWindowChange, true);\n\n const observers: MutationObserver[] = [];\n const observedNodes: HTMLElement[] = [];\n let el: HTMLElement | null = containerRef.current?.parentElement ?? null;\n while (el) {\n observedNodes.push(el);\n el = el.parentElement;\n }\n observedNodes.push(document.body);\n\n for (const node of observedNodes) {\n if (!node) continue;\n const obs = new MutationObserver(update);\n obs.observe(node, { attributes: true, attributeFilter: ['class', 'style'] });\n observers.push(obs);\n }\n\n return () => {\n window.removeEventListener('resize', onWindowChange);\n window.removeEventListener('scroll', onWindowChange, true);\n observers.forEach(o => o.disconnect());\n };\n }, [autoTextColor, autoTextColorMode, textOnDark, textOnLight]);\n\n // Automatically tag text-bearing descendants for perPixel mode\n useEffect(() => {\n if (!autoTextColor || autoTextColorMode !== 'perPixel') return;\n const root = contentRef.current;\n if (!root) return;\n\n const shouldTag = (el: HTMLElement): boolean => {\n if (el.hasAttribute('data-lg-no-autotext')) return false;\n if (el.hasAttribute('data-lg-autotext') || el.hasAttribute('data-lg-autotext-auto')) return false;\n const style = getComputedStyle(el);\n if (style.visibility === 'hidden' || style.display === 'none') return false;\n // Must contain a non-empty text node\n const hasText = Array.from(el.childNodes).some(n => n.nodeType === Node.TEXT_NODE && !!n.textContent && n.textContent.trim().length > 0);\n return hasText;\n };\n\n const tagAll = () => {\n const all = root.querySelectorAll('*');\n for (const node of Array.from(all)) {\n const el = node as HTMLElement;\n if (shouldTag(el)) el.setAttribute('data-lg-autotext-auto', '');\n }\n };\n\n tagAll();\n\n const mo = new MutationObserver((records) => {\n for (const rec of records) {\n if (rec.type === 'childList') {\n rec.addedNodes.forEach(n => {\n if (n.nodeType === 1) {\n const el = n as HTMLElement;\n if (shouldTag(el)) el.setAttribute('data-lg-autotext-auto', '');\n el.querySelectorAll('*').forEach(child => {\n const c = child as HTMLElement;\n if (shouldTag(c)) c.setAttribute('data-lg-autotext-auto', '');\n });\n }\n });\n } else if (rec.type === 'attributes') {\n const el = rec.target as HTMLElement;\n if (shouldTag(el)) el.setAttribute('data-lg-autotext-auto', '');\n }\n }\n });\n mo.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ['style', 'class'] });\n\n return () => {\n mo.disconnect();\n root.querySelectorAll('[data-lg-autotext-auto]').forEach(n => (n as HTMLElement).removeAttribute('data-lg-autotext-auto'));\n };\n }, [autoTextColor, autoTextColorMode, perPixelTargetSelector]);\n\n // Per-pixel mode: punch holes in the glass behind targeted text so blending sees the real background\n useEffect(() => {\n if (!autoTextColor || autoTextColorMode !== 'perPixel') return;\n if (!containerRef.current || !glassRef.current) return;\n\n let rafId = 0;\n const ensureMirrors = () => {\n const searchRoot = contentRef.current ?? containerRef.current!;\n const effectiveTargetSelector = `${perPixelTargetSelector}, [data-lg-autotext], [data-lg-autotext-auto]`;\n const targets = Array.from(searchRoot.querySelectorAll(effectiveTargetSelector)) as HTMLElement[];\n // remove mirrors for removed targets\n mirrorsRef.current = mirrorsRef.current.filter(m => {\n const targetId = m.getAttribute('data-lg-mirror-for');\n const stillExists = targets.some(t => t.dataset.lgMirrorId === targetId);\n if (!stillExists) {\n m.remove();\n return false;\n }\n return true;\n });\n // add mirrors for new targets\n for (const t of targets) {\n if (!t.dataset.lgMirrorId) {\n t.dataset.lgMirrorId = Math.random().toString(36).slice(2, 9);\n }\n const already = mirrorsRef.current.find(m => m.getAttribute('data-lg-mirror-for') === t.dataset.lgMirrorId);\n if (already) continue;\n const mirror = document.createElement('span');\n mirror.setAttribute('data-lg-mirror', '');\n mirror.setAttribute('data-lg-mirror-for', t.dataset.lgMirrorId);\n mirror.style.position = 'fixed';\n mirror.style.pointerEvents = 'none';\n mirror.style.mixBlendMode = 'difference';\n mirror.style.color = '#fff';\n mirror.style.whiteSpace = 'pre-wrap';\n mirror.style.zIndex = '2147483647';\n document.body.appendChild(mirror);\n mirrorsRef.current.push(mirror);\n }\n };\n const updateMask = () => {\n if (!containerRef.current || !glassRef.current) return;\n ensureMirrors();\n const containerRect = containerRef.current.getBoundingClientRect();\n const searchRoot = contentRef.current ?? containerRef.current;\n const effectiveTargetSelector = `${perPixelTargetSelector}, [data-lg-autotext], [data-lg-autotext-auto]`;\n const targets = Array.from(searchRoot!.querySelectorAll(effectiveTargetSelector)) as HTMLElement[];\n\n const baseImage = 'linear-gradient(#fff 0 0)';\n const images: string[] = [baseImage];\n const positions: string[] = ['0 0'];\n const sizes: string[] = ['100% 100%'];\n const repeats: string[] = ['no-repeat'];\n\n for (const t of targets) {\n const r = t.getBoundingClientRect();\n const left = Math.max(0, r.left - containerRect.left);\n const top = Math.max(0, r.top - containerRect.top);\n const width = Math.max(0, Math.min(containerRect.right, r.right) - Math.max(containerRect.left, r.left));\n const height = Math.max(0, Math.min(containerRect.bottom, r.bottom) - Math.max(containerRect.top, r.top));\n if (width <= 0 || height <= 0) continue;\n images.push('linear-gradient(#000 0 0)');\n positions.push(`${left}px ${top}px`);\n sizes.push(`${width}px ${height}px`);\n repeats.push('no-repeat');\n }\n\n const imgList = images.join(',');\n const posList = positions.join(',');\n const sizeList = sizes.join(',');\n const repList = repeats.join(',');\n const composites = new Array(Math.max(0, images.length - 1)).fill('exclude').join(',');\n const webkitComposites = new Array(Math.max(0, images.length - 1)).fill('xor').join(',');\n\n const el = glassRef.current;\n el.style.setProperty('mask-image', imgList);\n el.style.setProperty('mask-position', posList);\n el.style.setProperty('mask-size', sizeList);\n el.style.setProperty('mask-repeat', repList);\n if (composites) el.style.setProperty('mask-composite', composites);\n if (webkitComposites) el.style.setProperty('-webkit-mask-composite', webkitComposites);\n\n // Sync mirrors to targets\n for (const t of targets) {\n const id = t.dataset.lgMirrorId!;\n const mirror = mirrorsRef.current.find(m => m.getAttribute('data-lg-mirror-for') === id);\n if (!mirror) continue;\n const r = t.getBoundingClientRect();\n const cs = getComputedStyle(t);\n mirror.textContent = t.textContent || '';\n mirror.style.left = `${r.left}px`;\n mirror.style.top = `${r.top}px`;\n mirror.style.width = `${r.width}px`;\n mirror.style.height = `${r.height}px`;\n mirror.style.font = cs.font;\n mirror.style.lineHeight = cs.lineHeight;\n mirror.style.letterSpacing = cs.letterSpacing as string;\n mirror.style.textTransform = cs.textTransform as string;\n mirror.style.textShadow = 'none';\n mirror.style.textAlign = cs.textAlign as string;\n mirror.style.display = 'flex';\n mirror.style.alignItems = cs.display.includes('flex') ? (cs.alignItems as string) : 'center';\n mirror.style.justifyContent = cs.display.includes('flex') ? (cs.justifyContent as string) : 'center';\n }\n // Hide original text color to avoid double render glow\n for (const t of targets) {\n (t as HTMLElement).style.setProperty('color', 'transparent', 'important');\n }\n };\n\n const schedule = () => {\n if (rafId) return;\n rafId = requestAnimationFrame(() => {\n rafId = 0;\n updateMask();\n });\n };\n\n updateMask();\n\n const ro = new ResizeObserver(() => schedule());\n ro.observe(containerRef.current);\n const targetsObserve = () => {\n const searchRoot = contentRef.current ?? containerRef.current!;\n const effectiveTargetSelector = `${perPixelTargetSelector}, [data-lg-autotext], [data-lg-autotext-auto]`;\n const targets = Array.from(searchRoot.querySelectorAll(effectiveTargetSelector)) as HTMLElement[];\n for (const t of targets) ro.observe(t);\n };\n targetsObserve();\n\n const mo = new MutationObserver((records) => {\n // Ignore self-updates caused by setting styles on the glass layer\n const relevant = records.some(r => {\n const isSelf = glassRef.current && r.target === glassRef.current && r.attributeName === 'style';\n return !isSelf;\n });\n if (relevant) {\n schedule();\n targetsObserve();\n }\n });\n mo.observe(containerRef.current, { subtree: true, childList: true, attributes: true, attributeFilter: ['style', 'class'] });\n\n const onScroll = () => schedule();\n const onMove = () => schedule();\n window.addEventListener('scroll', onScroll, true);\n window.addEventListener('pointermove', onMove, true);\n window.addEventListener('resize', onMove);\n\n return () => {\n ro.disconnect();\n mo.disconnect();\n window.removeEventListener('scroll', onScroll, true);\n window.removeEventListener('pointermove', onMove, true);\n window.removeEventListener('resize', onMove);\n if (rafId) cancelAnimationFrame(rafId);\n if (glassRef.current) {\n glassRef.current.style.removeProperty('mask-image');\n glassRef.current.style.removeProperty('mask-position');\n glassRef.current.style.removeProperty('mask-size');\n glassRef.current.style.removeProperty('mask-repeat');\n glassRef.current.style.removeProperty('mask-composite');\n glassRef.current.style.removeProperty('-webkit-mask-composite');\n }\n // Remove mirrors and restore text colors\n const container = containerRef.current;\n if (container) {\n const targets = Array.from(container.querySelectorAll(perPixelTargetSelector)) as HTMLElement[];\n for (const t of targets) t.style.removeProperty('color');\n }\n for (const m of mirrorsRef.current) m.remove();\n mirrorsRef.current = [];\n };\n }, [autoTextColor, autoTextColorMode, perPixelTargetSelector]);\n\n // Effective radius in px clamped to box (prevents mismatch when radius > half size)\n const effectiveRadiusPx = Math.min(config.radius, dimensions.width / 2, dimensions.height / 2);\n\n // Generate displacement map SVG as data URI\n const displacementDataUri = useMemo(() => {\n const { width, height } = dimensions;\n const newwidth = width / 2;\n const newheight = height / 2;\n const borderWidth = Math.min(newwidth, newheight) * (config.border * 0.5);\n \n // Ensure radius doesn't exceed container constraints for consistent CSS/SVG behavior\n const effectiveRadius = Math.min(config.radius, width / 2, height / 2) / 2; // scaled to half-res viewBox\n \n const svgContent = `\n <svg viewBox=\"0 0 ${newwidth} ${newheight}\" xmlns=\"http://www.w3.org/2000/svg\">\n <defs>\n <linearGradient id=\"red\" x1=\"100%\" y1=\"0%\" x2=\"0%\" y2=\"0%\">\n <stop offset=\"0%\" stop-color=\"#0000\"/>\n <stop offset=\"100%\" stop-color=\"red\"/>\n </linearGradient>\n <linearGradient id=\"blue\" x1=\"0%\" y1=\"0%\" x2=\"0%\" y2=\"100%\">\n <stop offset=\"0%\" stop-color=\"#0000\"/>\n <stop offset=\"100%\" stop-color=\"blue\"/>\n </linearGradient>\n </defs>\n <rect x=\"0\" y=\"0\" width=\"${newwidth}\" height=\"${newheight}\" fill=\"black\"/>\n <rect x=\"0\" y=\"0\" width=\"${newwidth}\" height=\"${newheight}\" rx=\"${effectiveRadius}\" fill=\"url(#red)\" />\n <rect x=\"0\" y=\"0\" width=\"${newwidth}\" height=\"${newheight}\" rx=\"${effectiveRadius}\" fill=\"url(#blue)\" style=\"mix-blend-mode: ${config.blend}\" />\n <rect x=\"${borderWidth}\" y=\"${borderWidth}\" width=\"${newwidth - borderWidth * 2}\" height=\"${newheight - borderWidth * 2}\" rx=\"${effectiveRadius}\" fill=\"hsl(0 0% ${config.lightness}% / ${config.alpha})\" style=\"filter:blur(${config.displace}px)\" />\n </svg>\n `;\n \n const encoded = encodeURIComponent(svgContent);\n return `data:image/svg+xml,${encoded}`;\n }, [dimensions, config]);\n\n // Generate a unique ID for the SVG filter\n const uniqueFilterId = useId();\n const filterId = `liquid-glass-filter-${uniqueFilterId}`;\n\n const resolvedGlassBackground =\n glassColor && isSemiTransparentColor(glassColor)\n ? glassColor\n : `hsl(0 0% 100% / ${config.frost})`;\n\n if (glassColor && !isSemiTransparentColor(glassColor)) {\n // eslint-disable-next-line no-console\n console.warn(\n '[LiquidGlass] `glassColor` must be semi-transparent (alpha between 0 and 1). Falling back to frost-based color.'\n );\n }\n\n // detect iOS (WebKit on iPhone/iPad or Mac with touch)\n const isIOS = (() => {\n if (typeof navigator === 'undefined' || typeof window === 'undefined') return false;\n const ua = navigator.userAgent || '';\n const vendor = navigator.vendor || '';\n const isAndroid = /Android/i.test(ua);\n const isAppleUA = /(iPad|iPhone|iPod)/i.test(ua);\n const isIPadOS13Plus = /Macintosh/i.test(ua) && (navigator as any).maxTouchPoints > 1;\n const vendorIsApple = /Apple/i.test(vendor);\n const hasWK = typeof (window as any).webkit !== 'undefined';\n const hasMobileToken = /Mobile/i.test(ua);\n // Strict: real iOS or iPadOS WebKit on Apple device, exclude Android and most desktop emulation\n return !isAndroid && (isAppleUA || isIPadOS13Plus) && vendorIsApple && hasWK && hasMobileToken;\n })();\n\n // Build backdrop-filter string with iOS fallback\n const cssBlur = isIOS && iosBlurMode === 'auto' ? Math.max(blur, iosMinBlur) : blur;\n const backdropFilterValue = isIOS && iosBlurMode === 'auto'\n ? `blur(${cssBlur}px) saturate(${config.saturation}%)`\n : `saturate(${config.saturation}%) url(#${filterId})`;\n\n const glassMorphismStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n borderRadius: effectiveRadiusPx,\n position: \"absolute\",\n zIndex: 1,\n background: autoTextColor && autoTextColorMode === 'perPixel' ? 'transparent' : resolvedGlassBackground,\n backdropFilter: backdropFilterValue,\n WebkitBackdropFilter: backdropFilterValue,\n overflow: 'hidden'\n };\n\n // Gradient border styles\n const gradientBorderStyle: React.CSSProperties = {\n position: \"absolute\",\n inset: 0,\n borderRadius: effectiveRadiusPx,\n zIndex: 2,\n pointerEvents: \"none\",\n background: `linear-gradient(315deg, ${config.borderColor} 0%, rgba(120, 120, 120, 0) 30%, rgba(120, 120, 120, 0) 70%, ${config.borderColor} 100%) border-box`,\n mask: \"linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)\",\n maskComposite: \"exclude\",\n WebkitMask: \"linear-gradient(#fff 0 0) padding-box, linear-gradient(#fff 0 0)\",\n WebkitMaskComposite: \"xor\",\n border: `1px solid transparent`\n };\n\n const containerStyle: React.CSSProperties = {\n width: \"100%\",\n height: \"100%\",\n position: \"relative\",\n ...style\n };\n\n return (\n <div \n ref={containerRef}\n className={className}\n style={containerStyle}\n {...props}\n >\n <div style={glassMorphismStyle} ref={glassRef}>\n <svg \n className=\"liquid-glass-filter\"\n style={{\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n position: \"absolute\",\n inset: 0\n }}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <defs>\n <filter \n id={filterId}\n colorInterpolationFilters=\"sRGB\"\n >\n <feImage \n href={displacementDataUri}\n x=\"0\"\n y=\"0\"\n width=\"100%\"\n height=\"100%\"\n result=\"map\"\n />\n \n <feDisplacementMap \n in=\"SourceGraphic\"\n in2=\"map\"\n scale={config.scale + config.dispersion * config.aberrationIntensity}\n xChannelSelector={config.x}\n yChannelSelector={config.y}\n result=\"dispRed\"\n />\n <feColorMatrix \n in=\"dispRed\"\n type=\"matrix\"\n values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\"\n result=\"red\"\n />\n \n <feDisplacementMap \n in=\"SourceGraphic\"\n in2=\"map\"\n scale={config.scale}\n xChannelSelector={config.x}\n yChannelSelector={config.y}\n result=\"dispGreen\"\n />\n <feColorMatrix \n in=\"dispGreen\"\n type=\"matrix\"\n values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\"\n result=\"green\"\n />\n \n <feDisplacementMap \n in=\"SourceGraphic\"\n in2=\"map\"\n scale={config.scale - config.dispersion * config.aberrationIntensity}\n xChannelSelector={config.x}\n yChannelSelector={config.y}\n result=\"dispBlue\"\n />\n <feColorMatrix \n in=\"dispBlue\"\n type=\"matrix\"\n values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\"\n result=\"blue\"\n />\n \n <feBlend \n in=\"red\"\n in2=\"green\"\n mode=\"screen\"\n result=\"rg\"\n />\n <feBlend \n in=\"rg\"\n in2=\"blue\"\n mode=\"screen\"\n result=\"output\"\n />\n <feGaussianBlur \n in=\"output\"\n stdDeviation={config.blur}\n />\n </filter>\n </defs>\n </svg>\n </div>\n \n <div \n className=\"liquid-glass-border\"\n style={gradientBorderStyle}\n />\n \n {/* Children content */}\n {children && (\n <div \n style={{\n position: \"relative\",\n zIndex: 3,\n width: \"100%\",\n height: \"100%\",\n color: autoTextColor && autoTextColorMode !== 'perPixel' ? effectiveTextColor : undefined,\n transition: 'color 300ms ease'\n }}\n ref={contentRef}\n className={[\n forceTextColor && autoTextColor && autoTextColorMode !== 'perPixel' ? (textClassNameRef.current ?? '') : '',\n autoTextColor && autoTextColorMode === 'perPixel' ? (perPixelClassNameRef.current ?? '') : ''\n ].filter(Boolean).join(' ') || undefined}\n >\n {forceTextColor && autoTextColor && autoTextColorMode !== 'perPixel' && (\n <style>\n {`\n .${textClassNameRef.current}, .${textClassNameRef.current} * { transition: color 300ms ease; }\n .${textClassNameRef.current} { color: ${effectiveTextColor} !important; }\n .${textClassNameRef.current} * { color: ${effectiveTextColor} !important; }\n `}\n </style>\n )}\n {autoTextColor && autoTextColorMode === 'perPixel' && (\n <style>\n {`\n .${perPixelClassNameRef.current} ${perPixelTargetSelector},\n .${perPixelClassNameRef.current} [data-lg-autotext],\n .${perPixelClassNameRef.current} [data-lg-autotext-auto] {\n position: relative;\n z-index: 4;\n color: #fff !important;\n mix-blend-mode: difference !important;\n filter: grayscale(1) contrast(1000) !important;\n transition: filter 200ms ease, color 200ms ease;\n }\n `}\n </style>\n )}\n {children}\n </div>\n )}\n </div>\n );\n}\n\nLiquidGlass.displayName = \"LiquidGlass\";\n\nexport default LiquidGlass;\n\n// Removed non-working experimental components per user request"],"names":["isSemiTransparentColor","input","color","trim","rgba","exec","a","parseFloat","hsla","hslSlash","hex4","aHex","slice","parseInt","hex8","preset","scale","radius","border","lightness","displace","alpha","blur","dispersion","saturation","aberrationIntensity","frost","borderColor","LiquidGlass","_ref","_textClassNameRef$cur","_perPixelClassNameRef","config","children","_ref$mode","mode","_ref$scale","_ref$radius","_ref$border","_ref$lightness","_ref$displace","_ref$alpha","_ref$blur","_ref$dispersion","_ref$saturation","_ref$aberrationIntens","_ref$frost","_ref$borderColor","glassColor","_ref$autoTextColor","autoTextColor","_ref$autoTextColorMod","autoTextColorMode","_ref$perPixelTargetSe","perPixelTargetSelector","_ref$textOnDark","textOnDark","_ref$textOnLight","textOnLight","_ref$forceTextColor","forceTextColor","_ref$className","className","_ref$style","style","_ref$iosMinBlur","iosMinBlur","_ref$iosBlurMode","iosBlurMode","props","_objectWithoutProperties","_excluded","_objectSpread","blend","x","y","containerRef","useRef","glassRef","contentRef","mirrorsRef","_useState2","_slicedToArray","useState","width","height","dimensions","setDimensions","_useState4","effectiveTextColor","setEffectiveTextColor","textClassNameRef","current","concat","Math","random","toString","perPixelClassNameRef","parseCssColorToRgba","m","c","r","g","b","undefined","hex","useEffect","updateDimensions","_containerRef$current","getBoundingClientRect","resizeObserver","ResizeObserver","observe","disconnect","_containerRef$current4","_containerRef$current5","update","_containerRef$current2","_containerRef$current3","target","parentElement","bg","element","el","getComputedStyle","backgroundColor","parsed","bodyBg","document","body","findNearestOpaqueBackground","rgb","linear","dark","map","v","pow","onWindowChange","window","addEventListener","observers","observedNodes","push","_i","_observedNodes","length","node","obs","MutationObserver","attributes","attributeFilter","removeEventListener","forEach","o","root","shouldTag","hasAttribute","visibility","display","Array","from","childNodes","some","n","nodeType","Node","TEXT_NODE","textContent","all","querySelectorAll","_i2","_Array$from","setAttribute","tagAll","mo","records","_step","_iterator","_createForOfIteratorHelper","s","done","rec","value","type","addedNodes","child","err","e","f","subtree","childList","removeAttribute","rafId","updateMask","_contentRef$current2","_contentRef$current","searchRoot","effectiveTargetSelector","targets","filter","targetId","getAttribute","t","dataset","lgMirrorId","remove","_loop","_targets","_i3","find","mirror","createElement","position","pointerEvents","mixBlendMode","whiteSpace","zIndex","appendChild","ensureMirrors","containerRect","images","positions","sizes","repeats","_i4","_targets2","left","max","top","min","right","bottom","imgList","join","posList","sizeList","repList","composites","fill","webkitComposites","setProperty","_loop2","_targets3","_i5","id","cs","font","lineHeight","letterSpacing","textTransform","textShadow","textAlign","alignItems","includes","justifyContent","_i6","_targets4","schedule","requestAnimationFrame","ro","targetsObserve","_contentRef$current3","_i7","_targets5","attributeName","onScroll","onMove","cancelAnimationFrame","removeProperty","container","_i8","_targets6","_step2","_iterator2","effectiveRadiusPx","displacementDataUri","useMemo","newwidth","newheight","borderWidth","effectiveRadius","svgContent","encoded","encodeURIComponent","uniqueFilterId","useId","filterId","resolvedGlassBackground","console","warn","isIOS","navigator","ua","userAgent","vendor","isAndroid","test","isAppleUA","isIPadOS13Plus","maxTouchPoints","vendorIsApple","hasWK","webkit","hasMobileToken","cssBlur","backdropFilterValue","glassMorphismStyle","borderRadius","background","backdropFilter","WebkitBackdropFilter","overflow","gradientBorderStyle","inset","mask","maskComposite","WebkitMask","WebkitMaskComposite","containerStyle","React","_extends","ref","xmlns","colorInterpolationFilters","href","result","in","in2","xChannelSelector","yChannelSelector","values","stdDeviation","transition","Boolean","displayName"],"mappings":"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