{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "glass",
  "title": "Glass",
  "description": "The refraction engine: lens maps, the SVG filter and the glass surfaces.",
  "dependencies": [
    "motion@^13.4.4"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "src/glass/use-glass-switch.ts",
      "content": "\"use client\";\n\nimport {\n\ttype AnimationPlaybackControls,\n\tanimate,\n\ttype MotionValue,\n\tuseMotionValue,\n\tuseReducedMotion,\n\tuseTransform,\n} from \"motion/react\";\nimport {\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tCLOSE,\n\tDEFAULT_LIQUID,\n\tDRAG_SLOP,\n\tDWELL,\n\tOPEN,\n\trubberBand,\n\tTRAVEL,\n} from \"./motion\";\nimport { MAX_SPREAD, MAX_STRETCH, squashed, useSquish } from \"./use-squish\";\n\nconst INSET_RATIO = 0.107;\nconst OVERSHOOT = 0.12;\nconst OPEN_HEIGHT = 1.45;\nconst OPEN_ASPECT = 1.5;\n\nexport type GlassSwitchGeometry = {\n\twidth: number;\n\theight: number;\n\tinset: number;\n\tthumbWidth: number;\n\tthumbHeight: number;\n\ttravel: number;\n\tmargin: number;\n\tcontainerWidth: number;\n\tcontainerHeight: number;\n};\n\nexport type UseGlassSwitchOptions = {\n\tchecked: boolean;\n\tonCheckedChange?: (checked: boolean) => void;\n\twidth?: number;\n\theight?: number;\n\tdisabled?: boolean;\n\tdraggable?: boolean;\n\tliquid?: number;\n};\n\nexport type UseGlassSwitchResult = {\n\tgeometry: GlassSwitchGeometry;\n\trootStyle: Record<string, string>;\n\tlensProps: {\n\t\twidth: number;\n\t\theight: number;\n\t\tx: MotionValue<number>;\n\t\ty: number;\n\t\tlensWidth: MotionValue<number>;\n\t\tlensHeight: MotionValue<number>;\n\t\tlensRadius: MotionValue<number>;\n\t\tshadowOpacity: MotionValue<number>;\n\t\ttintOpacity: MotionValue<number>;\n\t\tedgeBias: MotionValue<number>;\n\t\tlag?: MotionValue<number>;\n\t};\n\tthumbProps: {\n\t\tstyle: { x: MotionValue<number> };\n\t\tonPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerCancel: () => void;\n\t};\n\trootRef: RefObject<HTMLElement | null>;\n\ttrackRef: RefObject<HTMLElement | null>;\n\tflash: () => void;\n\tconsumeDragGuard: () => boolean;\n};\n\nexport function useGlassSwitch({\n\tchecked,\n\tonCheckedChange,\n\twidth = 74,\n\theight = 28,\n\tdisabled,\n\tdraggable = true,\n\tliquid = DEFAULT_LIQUID,\n}: UseGlassSwitchOptions): UseGlassSwitchResult {\n\tconst reduceMotion = useReducedMotion() ?? false;\n\n\tconst inset = Math.round(height * INSET_RATIO);\n\tconst thumbHeight = height - inset * 2;\n\tconst thumbWidth = Math.round(thumbHeight * 2);\n\tconst travel = width - thumbWidth - inset * 2;\n\tconst overshoot = width * OVERSHOOT;\n\n\tconst restHalfWidth = thumbWidth / 2;\n\tconst restHalfHeight = thumbHeight / 2;\n\tconst openHalfHeight = (height * OPEN_HEIGHT) / 2;\n\tconst openHalfWidth = openHalfHeight * OPEN_ASPECT;\n\tconst margin =\n\t\tMath.ceil(\n\t\t\tMath.max(\n\t\t\t\topenHalfWidth * MAX_SPREAD - restHalfWidth + overshoot,\n\t\t\t\topenHalfHeight * MAX_STRETCH - height / 2,\n\t\t\t),\n\t\t) + 2;\n\n\tconst x = useMotionValue(checked ? travel : 0);\n\tconst lensHalfWidth = useMotionValue(restHalfWidth);\n\tconst lensHalfHeight = useMotionValue(restHalfHeight);\n\tconst restProgress = useMotionValue(1);\n\tconst shadowOpacity = useMotionValue(0);\n\n\tconst { squish, lag, kick } = useSquish(x, !reduceMotion, liquid);\n\n\tconst lensWidth = useTransform(\n\t\t[lensHalfWidth, squish],\n\t\t([half, amount]: number[]) => squashed(half * 2, amount, true),\n\t);\n\tconst lensHeight = useTransform(\n\t\t[lensHalfHeight, squish],\n\t\t([half, amount]: number[]) => squashed(half * 2, amount, false),\n\t);\n\tconst lensRadius = useTransform(\n\t\t[lensWidth, lensHeight],\n\t\t([across, tall]: number[]) => Math.min(across, tall) / 2,\n\t);\n\tconst lensX = useTransform(x, (at) => margin + inset + thumbWidth / 2 + at);\n\tconst edgeBias = useTransform(restProgress, (at) => at * 0.5);\n\n\tconst rootRef = useRef<HTMLElement | null>(null);\n\tconst trackRef = useRef<HTMLElement | null>(null);\n\tconst pointer = useRef<number | null>(null);\n\tconst startX = useRef(0);\n\tconst startOffset = useRef(0);\n\tconst dragged = useRef(false);\n\tconst dragGuard = useRef(false);\n\tconst isOpen = useRef(false);\n\tconst closeTimer = useRef<ReturnType<typeof setTimeout> | undefined>(\n\t\tundefined,\n\t);\n\tconst travelAnimation = useRef<AnimationPlaybackControls | undefined>(\n\t\tundefined,\n\t);\n\n\tconst setShape = useCallback(\n\t\t(open: boolean) => {\n\t\t\tisOpen.current = open;\n\t\t\tconst options = open ? OPEN : CLOSE;\n\t\t\tconst targets: Array<[typeof lensHalfWidth, number]> = [\n\t\t\t\t[lensHalfWidth, open ? openHalfWidth : restHalfWidth],\n\t\t\t\t[lensHalfHeight, open ? openHalfHeight : restHalfHeight],\n\t\t\t\t[restProgress, open ? 0 : 1],\n\t\t\t\t[shadowOpacity, open ? 1 : 0],\n\t\t\t];\n\t\t\tfor (const [value, target] of targets) {\n\t\t\t\tif (reduceMotion) value.set(target);\n\t\t\t\telse animate(value, target, options);\n\t\t\t}\n\t\t\tkick(open ? 1 : -1);\n\t\t},\n\t\t[\n\t\t\tkick,\n\t\t\tlensHalfHeight,\n\t\t\tlensHalfWidth,\n\t\t\topenHalfHeight,\n\t\t\topenHalfWidth,\n\t\t\treduceMotion,\n\t\t\trestHalfHeight,\n\t\t\trestHalfWidth,\n\t\t\trestProgress,\n\t\t\tshadowOpacity,\n\t\t],\n\t);\n\n\tconst open = useCallback(() => {\n\t\tclearTimeout(closeTimer.current);\n\t\tif (!isOpen.current) setShape(true);\n\t}, [setShape]);\n\n\tconst closeAfterDwell = useCallback(() => {\n\t\tclearTimeout(closeTimer.current);\n\t\tcloseTimer.current = setTimeout(() => setShape(false), DWELL);\n\t}, [setShape]);\n\n\tconst moveTo = useCallback(\n\t\t(target: number) => {\n\t\t\ttravelAnimation.current?.stop();\n\t\t\tif (reduceMotion) x.set(target);\n\t\t\telse travelAnimation.current = animate(x, target, TRAVEL);\n\t\t},\n\t\t[reduceMotion, x],\n\t);\n\n\tconst [rootStyle] = useState(() => ({\n\t\t\"--switch-progress\": String(checked ? 1 : 0),\n\t}));\n\n\tuseEffect(() => {\n\t\tconst apply = (value: number) => {\n\t\t\tconst progress =\n\t\t\t\ttravel > 0 ? Math.min(1, Math.max(0, value / travel)) : 0;\n\t\t\trootRef.current?.style.setProperty(\"--switch-progress\", String(progress));\n\t\t};\n\t\tapply(x.get());\n\t\treturn x.on(\"change\", apply);\n\t}, [travel, x]);\n\n\tuseEffect(() => {\n\t\tif (pointer.current !== null) return;\n\t\tmoveTo(checked ? travel : 0);\n\t}, [checked, moveTo, travel]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tclearTimeout(closeTimer.current);\n\t\t\ttravelAnimation.current?.stop();\n\t\t},\n\t\t[],\n\t);\n\n\tconst pointerScale = () => {\n\t\tconst box = trackRef.current?.getBoundingClientRect();\n\t\treturn box && box.width > 0 ? box.width / width : 1;\n\t};\n\n\tconst onPointerDown = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (disabled || pointer.current !== null || reduceMotion) return;\n\t\tpointer.current = event.pointerId;\n\t\tif (draggable) event.currentTarget.setPointerCapture(event.pointerId);\n\t\tstartX.current = event.clientX;\n\t\tstartOffset.current = x.get();\n\t\tdragged.current = false;\n\t\tdragGuard.current = false;\n\t\ttravelAnimation.current?.stop();\n\t\topen();\n\t\tif (!draggable) closeAfterDwell();\n\t};\n\n\tconst onPointerMove = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (!draggable || event.pointerId !== pointer.current) return;\n\t\tconst scale = pointerScale();\n\t\tconst moved = (event.clientX - startX.current) / scale;\n\t\tif (!dragged.current) {\n\t\t\tif (Math.abs(moved) < DRAG_SLOP) return;\n\t\t\tdragged.current = true;\n\t\t\tdragGuard.current = true;\n\t\t\tstartOffset.current = x.get();\n\t\t\tstartX.current = event.clientX;\n\t\t}\n\t\tlet next = startOffset.current + (event.clientX - startX.current) / scale;\n\t\tif (next < 0) next = -rubberBand(-next, overshoot);\n\t\telse if (next > travel)\n\t\t\tnext = travel + rubberBand(next - travel, overshoot);\n\t\tx.set(next);\n\t};\n\n\tconst onPointerUp = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (event.pointerId !== pointer.current) return;\n\t\tpointer.current = null;\n\t\tcloseAfterDwell();\n\t\tif (!dragged.current) return;\n\n\t\tdragged.current = false;\n\t\tconst next = Math.max(0, Math.min(travel, x.get())) > travel / 2;\n\t\tmoveTo(next ? travel : 0);\n\t\tif (next !== checked) onCheckedChange?.(next);\n\t};\n\n\tconst onPointerCancel = () => {\n\t\tpointer.current = null;\n\t\tdragged.current = false;\n\t\tdragGuard.current = false;\n\t\tsetShape(false);\n\t\tmoveTo(checked ? travel : 0);\n\t};\n\n\tconst flash = useCallback(() => {\n\t\topen();\n\t\tcloseAfterDwell();\n\t}, [closeAfterDwell, open]);\n\n\tconst consumeDragGuard = useCallback(() => {\n\t\tif (!dragGuard.current) return false;\n\t\tdragGuard.current = false;\n\t\treturn true;\n\t}, []);\n\n\treturn {\n\t\trootStyle,\n\t\tgeometry: {\n\t\t\twidth,\n\t\t\theight,\n\t\t\tinset,\n\t\t\tthumbWidth,\n\t\t\tthumbHeight,\n\t\t\ttravel,\n\t\t\tmargin,\n\t\t\tcontainerWidth: width + margin * 2,\n\t\t\tcontainerHeight: height + margin * 2,\n\t\t},\n\t\tlensProps: {\n\t\t\twidth: width + margin * 2,\n\t\t\theight: height + margin * 2,\n\t\t\tx: lensX,\n\t\t\ty: margin + height / 2,\n\t\t\tlensWidth,\n\t\t\tlensHeight,\n\t\t\tlensRadius,\n\t\t\tshadowOpacity,\n\t\t\ttintOpacity: restProgress,\n\t\t\tedgeBias,\n\t\t\tlag,\n\t\t},\n\t\tthumbProps: {\n\t\t\tstyle: { x },\n\t\t\tonPointerDown,\n\t\t\tonPointerMove,\n\t\t\tonPointerUp,\n\t\t\tonPointerCancel,\n\t\t},\n\t\trootRef,\n\t\ttrackRef,\n\t\tflash,\n\t\tconsumeDragGuard,\n\t};\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/use-glass-switch.ts"
    },
    {
      "path": "src/glass/index.ts",
      "content": "export { supportsBackdropRefraction } from \"./backdrop\";\nexport { Glass, type GlassProps } from \"./glass\";\nexport {\n\ttype GlassLanding,\n\tGlassPane,\n\ttype GlassPaneProps,\n\ttype GlassPaneReach,\n\ttype GlassPaneShape,\n\ttype GlassPaneVariant,\n\ttype GlassRefraction,\n\thideGlass,\n\tlandGlass,\n} from \"./glass-pane\";\nexport {\n\tGlassSegmented,\n\ttype GlassSegmentedOption,\n\ttype GlassSegmentedProps,\n} from \"./glass-segmented\";\nexport {\n\tGlassSegmentedSurface,\n\ttype GlassSegmentedSurfaceProps,\n} from \"./glass-segmented-surface\";\nexport { GlassSlider, type GlassSliderProps } from \"./glass-slider\";\nexport {\n\tGlassSliderSurface,\n\ttype GlassSliderSurfaceProps,\n} from \"./glass-slider-surface\";\nexport { GlassSwitch, type GlassSwitchProps } from \"./glass-switch\";\nexport {\n\tGlassSwitchSurface,\n\ttype GlassSwitchSurfaceProps,\n} from \"./glass-switch-surface\";\nexport {\n\tGlassToggleGroup,\n\ttype GlassToggleGroupProps,\n\ttype GlassToggleItem,\n} from \"./glass-toggle-group\";\nexport {\n\tCLOSE,\n\tDEFAULT_LIQUID,\n\tDRAG_SLOP,\n\tDWELL,\n\tOPEN,\n\tPRESS_SCALE,\n\trubberBand,\n\tTRAVEL,\n\tuseDerived,\n} from \"./motion\";\nexport {\n\tdecodeMap,\n\tgenerateLensMap,\n\tisMapDecoded,\n\ttype LensMap,\n\ttype LensProfile,\n\ttype LensShape,\n\tprofileKey,\n\tsnapShape,\n} from \"./optics\";\nexport {\n\tdarkLens,\n\tdefaultLens,\n\ttype GlassTheme,\n\tpaneLens,\n\tsliderLens,\n\tswitchLens,\n\ttoggleLens,\n\tuseLens,\n} from \"./presets\";\nexport {\n\tGlassScope,\n\ttype GlassScopeProps,\n\ttype GlassScopeRefraction,\n} from \"./scope\";\nexport {\n\tGlassThemeProvider,\n\ttype GlassThemeProviderProps,\n\tuseGlassTheme,\n} from \"./theme\";\nexport {\n\ttype OptionBounds,\n\ttype SegmentPress,\n\ttype SegmentRun,\n\ttype UseGlassSegmentedOptions,\n\ttype UseGlassSegmentedResult,\n\tuseGlassSegmented,\n\tuseSegmentLens,\n} from \"./use-glass-segmented\";\nexport {\n\ttype GlassSliderGeometry,\n\ttype UseGlassSliderOptions,\n\ttype UseGlassSliderResult,\n\tuseGlassSlider,\n} from \"./use-glass-slider\";\nexport {\n\ttype GlassSwitchGeometry,\n\ttype UseGlassSwitchOptions,\n\ttype UseGlassSwitchResult,\n\tuseGlassSwitch,\n} from \"./use-glass-switch\";\nexport { squashed, useSquish } from \"./use-squish\";\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/index.ts"
    },
    {
      "path": "src/glass/glass-segmented.tsx",
      "content": "\"use client\";\n\nimport { useId, useRef, useState } from \"react\";\nimport {\n\ttype GlassSegmentedOption,\n\tGlassSegmentedSurface,\n\ttype GlassSegmentedSurfaceProps,\n} from \"./glass-segmented-surface\";\nimport \"./glass-segmented.css\";\nimport type { LensProfile } from \"./optics\";\nimport type { GlassTheme } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport type { UseGlassSegmentedResult } from \"./use-glass-segmented\";\n\nexport type { GlassSegmentedOption };\n\nexport type GlassSegmentedProps = {\n\toptions: ReadonlyArray<string | GlassSegmentedOption>;\n\tvalue?: string;\n\tdefaultValue?: string;\n\tonValueChange?: (value: string) => void;\n\tname?: string;\n\theight?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tdisabled?: boolean;\n\tclassName?: string;\n\t\"aria-label\"?: string;\n\tsurfaceProps?: Partial<GlassSegmentedSurfaceProps>;\n};\n\nfunction normalise(\n\toption: string | GlassSegmentedOption,\n): GlassSegmentedOption {\n\treturn typeof option === \"string\" ? { value: option, label: option } : option;\n}\n\nexport function GlassSegmented({\n\toptions,\n\tvalue,\n\tdefaultValue,\n\tonValueChange,\n\tname,\n\theight = 36,\n\tlens,\n\ttheme: themeProp,\n\tdisabled,\n\tclassName,\n\t\"aria-label\": ariaLabel,\n\tsurfaceProps,\n}: GlassSegmentedProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst generatedId = useId();\n\tconst groupName = name ?? `glass-toggle-${generatedId.replaceAll(\":\", \"\")}`;\n\tconst items = options.map(normalise);\n\tconst isControlled = value !== undefined;\n\tconst [uncontrolled, setUncontrolled] = useState(\n\t\tdefaultValue ?? items[0]?.value,\n\t);\n\tconst current = isControlled ? value : uncontrolled;\n\tconst selectedIndex = Math.max(\n\t\t0,\n\t\titems.findIndex((item) => item.value === current),\n\t);\n\tconst controls = useRef<UseGlassSegmentedResult>(null);\n\n\tconst select = (next: string) => {\n\t\tif (!isControlled) setUncontrolled(next);\n\t\tonValueChange?.(next);\n\t\tcontrols.current?.flash();\n\t};\n\n\treturn (\n\t\t<div\n\t\t\tclassName={[\"glass-segmented\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tdata-theme={theme}\n\t\t\trole=\"radiogroup\"\n\t\t\taria-label={ariaLabel}\n\t\t>\n\t\t\t<GlassSegmentedSurface\n\t\t\t\t{...surfaceProps}\n\t\t\t\toptions={items}\n\t\t\t\tselected={[selectedIndex]}\n\t\t\t\theight={height}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlens={lens}\n\t\t\t\ttheme={theme}\n\t\t\t\tonDragSelect={(index) => {\n\t\t\t\t\tconst item = items[index];\n\t\t\t\t\tif (item && item.value !== current) select(item.value);\n\t\t\t\t}}\n\t\t\t\tcontrolsRef={controls}\n\t\t\t\titems={(bounds) =>\n\t\t\t\t\titems.map((item, index) => (\n\t\t\t\t\t\t<label\n\t\t\t\t\t\t\tkey={item.value}\n\t\t\t\t\t\t\tclassName=\"glass-segmented__hit\"\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tleft: bounds[index]?.left ?? 0,\n\t\t\t\t\t\t\t\twidth: bounds[index]?.width ?? 0,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<input\n\t\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\t\tname={groupName}\n\t\t\t\t\t\t\t\tvalue={item.value}\n\t\t\t\t\t\t\t\tchecked={index === selectedIndex}\n\t\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\t\tclassName=\"glass-segmented__input\"\n\t\t\t\t\t\t\t\tonChange={() => select(item.value)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t<span className=\"glass-segmented__hit-label\">{item.label}</span>\n\t\t\t\t\t\t</label>\n\t\t\t\t\t))\n\t\t\t\t}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-segmented.tsx"
    },
    {
      "path": "src/glass/use-glass-segmented.ts",
      "content": "\"use client\";\n\nimport {\n\ttype AnimationPlaybackControls,\n\tanimate,\n\ttype MotionValue,\n\tuseMotionValue,\n\tuseReducedMotion,\n\tuseTransform,\n} from \"motion/react\";\nimport {\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tCLOSE,\n\tDEFAULT_LIQUID,\n\tDRAG_SLOP,\n\tOPEN,\n\tPRESS_SCALE,\n\trubberBand,\n\tTRAVEL,\n\tuseDerived,\n} from \"./motion\";\nimport { MAX_SPREAD, MAX_STRETCH, squashed, useSquish } from \"./use-squish\";\n\nconst INSET_RATIO = 0.107;\nconst PRESS_HEIGHT = PRESS_SCALE;\nconst SETTLE = 340;\nconst OVERDRAG = 0.35;\nconst SPEED_STRETCH = -0.25;\n\nexport type OptionBounds = { left: number; width: number };\n\nexport type SegmentRun = {\n\tstart: number;\n\tend: number;\n\tleft: number;\n\twidth: number;\n};\n\nexport type SegmentPress = {\n\tstretch: MotionValue<number>;\n\tshadowOpacity: MotionValue<number>;\n\trest: MotionValue<number>;\n\theld: MotionValue<number>;\n\tdrag: MotionValue<number>;\n\tdragWidth: MotionValue<number>;\n};\n\nexport type UseGlassSegmentedOptions = {\n\tselected: readonly number[];\n\toptionCount: number;\n\theight?: number;\n\tinset?: number;\n\tpressScale?: number;\n\tdisabled?: boolean;\n\tonDragSelect?: (index: number) => void;\n};\n\nexport type UseGlassSegmentedResult = {\n\tgeometry: {\n\t\theight: number;\n\t\tinset: number;\n\t\tindicatorHeight: number;\n\t\tmargin: number;\n\t\ttrackWidth: number;\n\t\tcontainerWidth: number;\n\t\tcontainerHeight: number;\n\t};\n\truns: SegmentRun[];\n\tdividers: number[];\n\tbounds: OptionBounds[];\n\tattachRow: (element: HTMLElement | null) => void;\n\tattachOption: (index: number) => (element: HTMLElement | null) => void;\n\trootRef: RefObject<HTMLElement | null>;\n\trootProps: {\n\t\tonPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerCancel: (event: ReactPointerEvent<HTMLElement>) => void;\n\t};\n\tpress: SegmentPress;\n\tflash: () => void;\n\tsetPressed: (pressed: boolean) => void;\n};\n\nfunction runsOf(\n\tselected: readonly number[],\n\tbounds: OptionBounds[],\n): SegmentRun[] {\n\tconst sorted = [...new Set(selected)]\n\t\t.filter((index) => index >= 0 && bounds[index] !== undefined)\n\t\t.sort((a, b) => a - b);\n\n\tconst runs: SegmentRun[] = [];\n\tfor (const index of sorted) {\n\t\tconst open = runs.at(-1);\n\t\tif (open && index === open.end + 1) {\n\t\t\topen.end = index;\n\t\t\tcontinue;\n\t\t}\n\t\truns.push({ start: index, end: index, left: 0, width: 0 });\n\t}\n\n\treturn runs.map((run) => {\n\t\tconst first = bounds[run.start];\n\t\tconst last = bounds[run.end];\n\t\treturn {\n\t\t\t...run,\n\t\t\tleft: first.left,\n\t\t\twidth: last.left + last.width - first.left,\n\t\t};\n\t});\n}\n\nconst centreOf = (bound: OptionBounds) => bound.left + bound.width / 2;\n\nfunction capsuleAt(bounds: OptionBounds[], centre: number) {\n\tconst first = bounds[0];\n\tconst last = bounds.at(-1);\n\tif (!first || !last) return { centre, width: 0 };\n\tif (centre <= centreOf(first)) return { centre, width: first.width };\n\tif (centre >= centreOf(last)) return { centre, width: last.width };\n\tfor (let index = 0; index < bounds.length - 1; index += 1) {\n\t\tconst from = bounds[index];\n\t\tconst to = bounds[index + 1];\n\t\tif (centre > centreOf(to)) continue;\n\t\tconst t = (centre - centreOf(from)) / (centreOf(to) - centreOf(from));\n\t\treturn { centre, width: from.width + (to.width - from.width) * t };\n\t}\n\treturn { centre, width: last.width };\n}\n\nfunction nearestTo(bounds: OptionBounds[], centre: number) {\n\tlet best = 0;\n\tfor (let index = 1; index < bounds.length; index += 1) {\n\t\tconst distance = Math.abs(centreOf(bounds[index]) - centre);\n\t\tif (distance < Math.abs(centreOf(bounds[best]) - centre)) best = index;\n\t}\n\treturn best;\n}\n\nexport function useGlassSegmented({\n\tselected,\n\toptionCount,\n\theight = 36,\n\tinset: insetOption,\n\tpressScale = PRESS_HEIGHT,\n\tdisabled,\n\tonDragSelect,\n}: UseGlassSegmentedOptions): UseGlassSegmentedResult {\n\tconst reduceMotion = useReducedMotion() ?? false;\n\n\tconst inset = insetOption ?? Math.round(height * INSET_RATIO);\n\tconst indicatorHeight = height - inset * 2;\n\tconst margin =\n\t\tMath.ceil(\n\t\t\tMath.max(\n\t\t\t\t((indicatorHeight * pressScale) / 2) * MAX_STRETCH - height / 2,\n\t\t\t\t(indicatorHeight * (pressScale - 1)) / 2 +\n\t\t\t\t\tindicatorHeight * (MAX_SPREAD - 1),\n\t\t\t),\n\t\t) + 2;\n\n\tconst [bounds, setBounds] = useState<OptionBounds[]>([]);\n\tconst [trackWidth, setTrackWidth] = useState(0);\n\n\tconst rootRef = useRef<HTMLElement | null>(null);\n\tconst optionRefs = useRef<Array<HTMLElement | null>>([]);\n\tconst observer = useRef<ResizeObserver | undefined>(undefined);\n\n\tconst attachRow = useCallback((element: HTMLElement | null) => {\n\t\tobserver.current?.disconnect();\n\t\tobserver.current = undefined;\n\t\tif (!element) return;\n\n\t\tconst measure = () => {\n\t\t\tconst origin = element.offsetLeft;\n\t\t\tsetTrackWidth(element.offsetWidth);\n\t\t\tsetBounds(\n\t\t\t\toptionRefs.current.map((option) => ({\n\t\t\t\t\tleft: (option?.offsetLeft ?? 0) - origin,\n\t\t\t\t\twidth: option?.offsetWidth ?? 0,\n\t\t\t\t})),\n\t\t\t);\n\t\t};\n\t\tmeasure();\n\n\t\tif (typeof ResizeObserver === \"undefined\") return;\n\t\tconst watcher = new ResizeObserver(measure);\n\t\twatcher.observe(element);\n\t\tfor (const option of optionRefs.current) {\n\t\t\tif (option) watcher.observe(option);\n\t\t}\n\t\tobserver.current = watcher;\n\t}, []);\n\n\tconst attachOption = useCallback(\n\t\t(index: number) => (element: HTMLElement | null) => {\n\t\t\toptionRefs.current[index] = element;\n\t\t},\n\t\t[],\n\t);\n\n\tuseEffect(() => {\n\t\toptionRefs.current.length = optionCount;\n\t\treturn () => observer.current?.disconnect();\n\t}, [optionCount]);\n\n\tconst runs = runsOf(selected, bounds);\n\tconst dividers = runs.flatMap((run) => {\n\t\tconst lines: number[] = [];\n\t\tfor (let index = run.start; index < run.end; index++) {\n\t\t\tconst edge = bounds[index];\n\t\t\tif (edge) lines.push(edge.left + edge.width);\n\t\t}\n\t\treturn lines;\n\t});\n\n\tconst stretch = useMotionValue(1);\n\tconst shadowOpacity = useMotionValue(0);\n\tconst rest = useMotionValue(1);\n\tconst held = useMotionValue(0);\n\tconst drag = useMotionValue(Number.NaN);\n\tconst dragWidth = useMotionValue(0);\n\n\tconst isOpen = useRef(false);\n\tconst closeTimer = useRef<ReturnType<typeof setTimeout> | undefined>(\n\t\tundefined,\n\t);\n\n\tconst setPressed = useCallback(\n\t\t(pressed: boolean) => {\n\t\t\tisOpen.current = pressed;\n\t\t\tconst options = pressed ? OPEN : CLOSE;\n\t\t\tconst targets: Array<[MotionValue<number>, number]> = [\n\t\t\t\t[stretch, pressed ? pressScale : 1],\n\t\t\t\t[shadowOpacity, pressed ? 1 : 0],\n\t\t\t\t[rest, pressed ? 0 : 1],\n\t\t\t];\n\t\t\tfor (const [value, next] of targets) {\n\t\t\t\tif (reduceMotion) value.set(next);\n\t\t\t\telse animate(value, next, options);\n\t\t\t}\n\t\t\theld.set(pressed && !reduceMotion ? 1 : 0);\n\t\t},\n\t\t[held, pressScale, reduceMotion, rest, shadowOpacity, stretch],\n\t);\n\n\tconst open = useCallback(() => {\n\t\tclearTimeout(closeTimer.current);\n\t\tif (!isOpen.current) setPressed(true);\n\t}, [setPressed]);\n\n\tconst settle = useCallback(() => {\n\t\tclearTimeout(closeTimer.current);\n\t\tcloseTimer.current = setTimeout(() => setPressed(false), SETTLE);\n\t}, [setPressed]);\n\n\tconst flash = useCallback(() => {\n\t\tif (reduceMotion) return;\n\t\topen();\n\t\tsettle();\n\t}, [open, reduceMotion, settle]);\n\n\tuseEffect(() => () => clearTimeout(closeTimer.current), []);\n\n\tconst pointer = useRef<number | null>(null);\n\tconst startX = useRef(0);\n\tconst startCentre = useRef(Number.NaN);\n\tconst dragging = useRef(false);\n\tconst latest = useRef({ bounds, runs, onDragSelect });\n\tlatest.current = { bounds, runs, onDragSelect };\n\n\tconst localX = (clientX: number) => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return clientX;\n\t\tconst box = root.getBoundingClientRect();\n\t\tconst scale = root.offsetWidth > 0 ? box.width / root.offsetWidth : 1;\n\t\treturn (clientX - box.left) / scale;\n\t};\n\n\tconst onPointerDown = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (disabled || reduceMotion || pointer.current !== null) return;\n\t\tif (event.pointerType === \"mouse\" && event.button !== 0) return;\n\t\tpointer.current = event.pointerId;\n\t\tstartX.current = event.clientX;\n\t\tdragging.current = false;\n\t\tstartCentre.current = Number.NaN;\n\t\tconst { runs: chosen, onDragSelect: pick } = latest.current;\n\t\tconst only = chosen.length === 1 && chosen[0].start === chosen[0].end;\n\t\tif (pick && only) {\n\t\t\tconst at = localX(event.clientX);\n\t\t\tconst run = chosen[0];\n\t\t\tif (at >= run.left && at <= run.left + run.width) {\n\t\t\t\tstartCentre.current = run.left + run.width / 2;\n\t\t\t}\n\t\t}\n\t\topen();\n\t};\n\n\tconst onPointerMove = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (event.pointerId !== pointer.current) return;\n\t\tif (Number.isNaN(startCentre.current)) return;\n\t\tconst root = rootRef.current;\n\t\tconst scale =\n\t\t\troot && root.offsetWidth > 0\n\t\t\t\t? root.getBoundingClientRect().width / root.offsetWidth\n\t\t\t\t: 1;\n\t\tconst moved = (event.clientX - startX.current) / scale;\n\t\tif (!dragging.current) {\n\t\t\tif (Math.abs(moved) < DRAG_SLOP) return;\n\t\t\tdragging.current = true;\n\t\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\t}\n\t\tconst options = latest.current.bounds;\n\t\tconst first = options[0];\n\t\tconst last = options.at(-1);\n\t\tif (!first || !last) return;\n\t\tconst low = centreOf(first);\n\t\tconst high = centreOf(last);\n\t\tconst limit = indicatorHeight * OVERDRAG;\n\t\tlet centre = startCentre.current + moved;\n\t\tif (centre < low) centre = low - rubberBand(low - centre, limit);\n\t\telse if (centre > high) centre = high + rubberBand(centre - high, limit);\n\t\tconst capsule = capsuleAt(options, centre);\n\t\tdragWidth.set(capsule.width);\n\t\tdrag.set(capsule.centre);\n\t};\n\n\tconst endPointer = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (event.pointerId !== pointer.current) return;\n\t\tpointer.current = null;\n\t\tif (dragging.current) {\n\t\t\tdragging.current = false;\n\t\t\tconst index = nearestTo(latest.current.bounds, drag.get());\n\t\t\tlatest.current.onDragSelect?.(index);\n\t\t\tdrag.set(Number.NaN);\n\t\t}\n\t\tsettle();\n\t};\n\n\tuseEffect(() => {\n\t\tconst apply = (value: number) =>\n\t\t\trootRef.current?.style.setProperty(\"--segment-rest\", String(value));\n\t\tapply(rest.get());\n\t\treturn rest.on(\"change\", apply);\n\t}, [rest]);\n\n\tconst press = useMemo<SegmentPress>(\n\t\t() => ({ stretch, shadowOpacity, rest, held, drag, dragWidth }),\n\t\t[drag, dragWidth, held, rest, shadowOpacity, stretch],\n\t);\n\n\treturn {\n\t\tgeometry: {\n\t\t\theight,\n\t\t\tinset,\n\t\t\tindicatorHeight,\n\t\t\tmargin,\n\t\t\ttrackWidth,\n\t\t\tcontainerWidth: trackWidth + margin * 2,\n\t\t\tcontainerHeight: height + margin * 2,\n\t\t},\n\t\truns,\n\t\tdividers,\n\t\tbounds,\n\t\tattachRow,\n\t\tattachOption,\n\t\trootRef,\n\t\trootProps: {\n\t\t\tonPointerDown,\n\t\t\tonPointerMove,\n\t\t\tonPointerUp: endPointer,\n\t\t\tonPointerCancel: endPointer,\n\t\t},\n\t\tpress,\n\t\tflash,\n\t\tsetPressed,\n\t};\n}\n\nexport function useSegmentLens({\n\trun,\n\tindicatorHeight,\n\tmargin,\n\tpress,\n\tliquid = DEFAULT_LIQUID,\n}: {\n\trun: SegmentRun;\n\tindicatorHeight: number;\n\tmargin: number;\n\tpress: SegmentPress;\n\tliquid?: number;\n}) {\n\tconst reduceMotion = useReducedMotion() ?? false;\n\tconst centre = run.left + run.width / 2;\n\n\tconst x = useMotionValue(centre);\n\tconst span = useMotionValue(run.width);\n\tconst { squish, kick } = useSquish(x, !reduceMotion, liquid, SPEED_STRETCH);\n\n\tconst lensWidth = useDerived(\n\t\t[span, press.stretch, squish],\n\t\t([width, factor, amount]) =>\n\t\t\tsquashed(width + indicatorHeight * (factor - 1), amount, true),\n\t);\n\tconst lensHeight = useDerived([press.stretch, squish], ([factor, amount]) =>\n\t\tsquashed(indicatorHeight * factor, amount, false),\n\t);\n\tconst lensRadius = useDerived(\n\t\t[lensWidth, lensHeight],\n\t\t([across, tall]) => Math.min(across, tall) / 2,\n\t);\n\tconst lensX = useTransform(x, (at) => margin + at);\n\tconst edgeBias = useTransform(press.rest, (at) => at * 0.5);\n\n\tconst settled = useRef(false);\n\tconst moves = useRef<AnimationPlaybackControls[]>([]);\n\tconst target = useRef({ centre, width: run.width });\n\ttarget.current = { centre, width: run.width };\n\n\tconst glide = useCallback(\n\t\t(to: { centre: number; width: number }) => {\n\t\t\tfor (const move of moves.current) move.stop();\n\t\t\tmoves.current = [\n\t\t\t\tanimate(x, to.centre, TRAVEL),\n\t\t\t\tanimate(span, to.width, TRAVEL),\n\t\t\t];\n\t\t},\n\t\t[span, x],\n\t);\n\n\tuseEffect(() => {\n\t\tif (!Number.isNaN(press.drag.get())) return;\n\t\tif (reduceMotion || !settled.current) {\n\t\t\tfor (const move of moves.current) move.stop();\n\t\t\tx.set(centre);\n\t\t\tspan.set(run.width);\n\t\t\tsettled.current = true;\n\t\t\treturn;\n\t\t}\n\t\tglide({ centre, width: run.width });\n\t}, [centre, glide, press.drag, reduceMotion, run.width, span, x]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tfor (const move of moves.current) move.stop();\n\t\t},\n\t\t[],\n\t);\n\n\tuseEffect(() => {\n\t\tconst follow = (at: number) => {\n\t\t\tif (Number.isNaN(at)) {\n\t\t\t\tglide(target.current);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (const move of moves.current) move.stop();\n\t\t\tmoves.current = [];\n\t\t\tspan.set(press.dragWidth.get());\n\t\t\tx.set(at);\n\t\t};\n\t\treturn press.drag.on(\"change\", follow);\n\t}, [glide, press.drag, press.dragWidth, span, x]);\n\n\tuseEffect(() => {\n\t\tlet wasHeld = press.held.get() > 0.5;\n\t\treturn press.held.on(\"change\", (value) => {\n\t\t\tconst holding = value > 0.5;\n\t\t\tif (holding !== wasHeld) kick(holding ? 1 : -1);\n\t\t\twasHeld = holding;\n\t\t});\n\t}, [kick, press.held]);\n\n\treturn {\n\t\tx: lensX,\n\t\tlensWidth,\n\t\tlensHeight,\n\t\tlensRadius,\n\t\tshadowOpacity: press.shadowOpacity,\n\t\ttintOpacity: press.rest,\n\t\tedgeBias,\n\t};\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/use-glass-segmented.ts"
    },
    {
      "path": "src/glass/glass-slider.css",
      "content": ".glass-slider {\n\t--glass-slider-track: color(display-p3 0.882 0.875 0.875);\n\t--glass-slider-fill: var(\n\t\t--glass-accent-fill,\n\t\tcolor(display-p3 0.596 0.588 1)\n\t);\n\t--glass-slider-focus: var(--glass-accent, #7774ff);\n\tdisplay: inline-flex;\n\tflex-direction: column;\n\tgap: 10px;\n\twidth: fit-content;\n\tcursor: pointer;\n\t-webkit-tap-highlight-color: transparent;\n}\n\n.glass-slider__box {\n\tposition: relative;\n\tdisplay: flow-root;\n\tflex: none;\n\t--glass-slider-track: color(display-p3 0.882 0.875 0.875);\n\t--glass-slider-fill: var(\n\t\t--glass-accent-fill,\n\t\tcolor(display-p3 0.596 0.588 1)\n\t);\n\t--slider-fill: 0%;\n\t--slider-progress: 0;\n\t--glass-body: #fff;\n}\n\n/* A slider that fills its container draws its resting handle in CSS until it\n   has measured itself, so a server-rendered page shows it at the right size. */\n.glass-slider__rest {\n\tposition: absolute;\n\ttop: 0;\n\tleft: calc(var(--slider-progress) * (100% - var(--slider-thumb-width)));\n\twidth: var(--slider-thumb-width);\n\theight: 100%;\n\t/* The glass body itself is white in both themes, like iOS's knobs. */\n\tbackground: #fff;\n\tborder-radius: 999px;\n}\n\n.glass-slider__box[data-theme=\"dark\"] {\n\t--glass-slider-track: color(display-p3 0.26 0.26 0.28);\n\t--glass-body: #1b1b1f;\n}\n\n.glass-slider__input {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip-path: inset(50%);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n.glass-slider__glass {\n\tpointer-events: none;\n}\n\n.glass-slider__row {\n\tposition: relative;\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.glass-slider__hit {\n\ttouch-action: none;\n\tpointer-events: auto;\n}\n\n.glass-slider__track {\n\tposition: relative;\n\twidth: 100%;\n\toverflow: hidden;\n\tbackground: var(--glass-slider-track);\n}\n\n.glass-slider__track-fill {\n\tposition: absolute;\n\tinset: 0;\n\tbackground: var(--glass-slider-fill);\n\tborder-radius: inherit;\n\ttransform: translateX(calc(var(--slider-fill) - 100%));\n}\n\n.glass-slider__label {\n\tfont: 600 13px / 1.25 var(--font-sans, inherit);\n\tcolor: currentColor;\n\t-webkit-user-select: none;\n\tuser-select: none;\n}\n\n.glass-slider__input:focus-visible + .glass-slider__box .glass-slider__track {\n\toutline: 2px solid var(--glass-slider-focus);\n\toutline-offset: 4px;\n}\n\n.glass-slider[data-disabled] {\n\tcursor: not-allowed;\n\topacity: 0.48;\n}\n\n.glass-slider[data-theme=\"dark\"] {\n\t--glass-slider-track: color(display-p3 0.26 0.26 0.28);\n\t--glass-body: #1b1b1f;\n}\n",
      "type": "registry:file",
      "target": "@components/liquikit/glass/glass-slider.css"
    },
    {
      "path": "src/glass/light.ts",
      "content": "const overlays = new Map<string, Promise<string | undefined>>();\nconst ready = new Map<string, string>();\nconst OVERLAY_LIMIT = 64;\n\nexport function readyOverlay(light: string) {\n\treturn ready.get(light);\n}\n\n// A light map is blended hard-light over the glass, which is the same as\n// painting white (above mid-grey) or black (below) at |2L - 1|. Baking that\n// into a transparent image lets plain CSS draw the light with no filter.\nexport function lightOverlay(light: string) {\n\tconst known = overlays.get(light);\n\tif (known) return known;\n\tconst made = new Promise<string | undefined>((resolve) => {\n\t\tif (typeof Image === \"undefined\") {\n\t\t\tresolve(undefined);\n\t\t\treturn;\n\t\t}\n\t\tconst image = new Image();\n\t\timage.src = light;\n\t\t// WebKit can fire load before a canvas is able to read the pixels.\n\t\timage.decode().then(\n\t\t\t() => {\n\t\t\t\tconst canvas = document.createElement(\"canvas\");\n\t\t\t\tcanvas.width = image.naturalWidth;\n\t\t\t\tcanvas.height = image.naturalHeight;\n\t\t\t\tconst context = canvas.getContext(\"2d\", { willReadFrequently: true });\n\t\t\t\tif (!context || canvas.width === 0 || canvas.height === 0) {\n\t\t\t\t\tresolve(undefined);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tcontext.drawImage(image, 0, 0);\n\t\t\t\tconst pixels = context.getImageData(0, 0, canvas.width, canvas.height);\n\t\t\t\tconst data = pixels.data;\n\t\t\t\tfor (let offset = 0; offset < data.length; offset += 4) {\n\t\t\t\t\tconst level = data[offset] / 255;\n\t\t\t\t\tconst value = level >= 0.5 ? 255 : 0;\n\t\t\t\t\tdata[offset] = value;\n\t\t\t\t\tdata[offset + 1] = value;\n\t\t\t\t\tdata[offset + 2] = value;\n\t\t\t\t\tdata[offset + 3] = Math.round(Math.abs(2 * level - 1) * 255);\n\t\t\t\t}\n\t\t\t\tcontext.putImageData(pixels, 0, 0);\n\t\t\t\tconst url = canvas.toDataURL(\"image/png\");\n\t\t\t\tready.set(light, url);\n\t\t\t\tresolve(url);\n\t\t\t},\n\t\t\t() => resolve(undefined),\n\t\t);\n\t});\n\toverlays.set(light, made);\n\tif (overlays.size > OVERLAY_LIMIT) {\n\t\tconst oldest = overlays.keys().next().value;\n\t\tif (oldest !== undefined) {\n\t\t\toverlays.delete(oldest);\n\t\t\tready.delete(oldest);\n\t\t}\n\t}\n\treturn made;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/light.ts"
    },
    {
      "path": "src/glass/glass-switch.css",
      "content": ".glass-switch {\n\t--glass-switch-off: color(display-p3 0.882 0.875 0.875);\n\t--glass-switch-on: var(--glass-accent-fill, color(display-p3 0.596 0.588 1));\n\t--glass-switch-focus: var(--glass-accent, #7774ff);\n\t--switch-progress: 0;\n\t--glass-body: #fff;\n\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 12px;\n\twidth: fit-content;\n\tcursor: pointer;\n\t-webkit-tap-highlight-color: transparent;\n}\n\n.glass-switch__box {\n\tposition: relative;\n\tdisplay: flow-root;\n\tflex: none;\n\t--glass-switch-off: color(display-p3 0.882 0.875 0.875);\n\t--glass-switch-on: var(--glass-accent-fill, color(display-p3 0.596 0.588 1));\n\t--switch-progress: 0;\n\t--glass-body: #fff;\n}\n\n.glass-switch__box[data-theme=\"dark\"] {\n\t--glass-switch-off: color(display-p3 0.26 0.26 0.28);\n\t--glass-body: #1b1b1f;\n}\n\n.glass-switch__input {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip-path: inset(50%);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n.glass-switch__glass {\n\tpointer-events: none;\n}\n\n.glass-switch__track {\n\tposition: relative;\n\tbackground: color-mix(\n\t\tin srgb,\n\t\tvar(--glass-switch-off),\n\t\tvar(--glass-switch-on) calc(var(--switch-progress) * 100%)\n\t);\n}\n\n.glass-switch__thumb-area {\n\tposition: absolute;\n\tdisplay: block;\n\ttouch-action: none;\n\tpointer-events: auto;\n\tcursor: inherit;\n}\n\n.glass-switch__label {\n\tfont: 600 15px / 1.25 var(--font-sans, inherit);\n\tcolor: currentColor;\n\t-webkit-user-select: none;\n\tuser-select: none;\n}\n\n.glass-switch__input:focus-visible + .glass-switch__box .glass-switch__track {\n\toutline: 2px solid var(--glass-switch-focus);\n\toutline-offset: 3px;\n}\n\n.glass-switch[data-disabled] {\n\tcursor: not-allowed;\n\topacity: 0.48;\n}\n\n.glass-switch[data-theme=\"dark\"] {\n\t--glass-switch-off: color(display-p3 0.26 0.26 0.28);\n\t--glass-body: #1b1b1f;\n}\n",
      "type": "registry:file",
      "target": "@components/liquikit/glass/glass-switch.css"
    },
    {
      "path": "src/glass/backdrop.ts",
      "content": "let backdropSupport: boolean | undefined;\n\nexport function supportsBackdropRefraction() {\n\tif (backdropSupport !== undefined) return backdropSupport;\n\tif (typeof navigator === \"undefined\" || typeof CSS === \"undefined\") {\n\t\treturn false;\n\t}\n\tconst brands = (\n\t\tnavigator as Navigator & {\n\t\t\tuserAgentData?: { brands?: Array<{ brand: string }> };\n\t\t}\n\t).userAgentData?.brands;\n\tbackdropSupport =\n\t\tBoolean(brands?.some(({ brand }) => brand === \"Chromium\")) &&\n\t\tCSS.supports(\"backdrop-filter\", \"url(#glass)\");\n\treturn backdropSupport;\n}\n\nconst ROOT_KEYFRAMES = [\n\t\"opacity\",\n\t\"filter\",\n\t\"backdropFilter\",\n\t\"clipPath\",\n\t\"mask\",\n\t\"maskImage\",\n];\n\n// A backdrop filter reads only up to the nearest backdrop root: an ancestor\n// with opacity, a filter, a backdrop filter, a mask, a clip-path or a blend\n// mode. Under one it sees that ancestor's own see-through paint over nothing,\n// and Chromium draws the box dark. An animation that ever touched opacity or a\n// filter keeps the root while it fills, even once it has settled on 1.\nexport function underBackdropRoot(element: Element) {\n\tconst top = element.ownerDocument.documentElement;\n\tfor (\n\t\tlet node = element.parentElement;\n\t\tnode && node !== top;\n\t\tnode = node.parentElement\n\t) {\n\t\tconst style = getComputedStyle(node);\n\t\tif (\n\t\t\tNumber(style.opacity) < 1 ||\n\t\t\tstyle.filter !== \"none\" ||\n\t\t\tstyle.backdropFilter !== \"none\" ||\n\t\t\tstyle.clipPath !== \"none\" ||\n\t\t\tstyle.maskImage !== \"none\" ||\n\t\t\tstyle.mixBlendMode !== \"normal\" ||\n\t\t\t/opacity|filter|mask|clip-path|mix-blend-mode/.test(style.willChange)\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t\tfor (const animation of node.getAnimations?.() ?? []) {\n\t\t\tconst effect = animation.effect;\n\t\t\tif (\n\t\t\t\teffect instanceof KeyframeEffect &&\n\t\t\t\teffect\n\t\t\t\t\t.getKeyframes()\n\t\t\t\t\t.some((frame) => ROOT_KEYFRAMES.some((key) => key in frame))\n\t\t\t) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/backdrop.ts"
    },
    {
      "path": "src/glass/glass-segmented-surface.tsx",
      "content": "\"use client\";\n\nimport {\n\ttype CSSProperties,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype Ref,\n\tuseImperativeHandle,\n} from \"react\";\nimport { Glass } from \"./glass\";\nimport \"./glass-segmented.css\";\nimport type { LensProfile } from \"./optics\";\nimport { type GlassTheme, toggleLens, useLens } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport {\n\ttype OptionBounds,\n\ttype SegmentPress,\n\ttype SegmentRun,\n\ttype UseGlassSegmentedResult,\n\tuseGlassSegmented,\n\tuseSegmentLens,\n} from \"./use-glass-segmented\";\n\nexport type GlassSegmentedOption = {\n\tvalue: string;\n\tlabel: ReactNode;\n};\n\nexport type GlassSegmentedSurfaceProps = Omit<\n\tHTMLAttributes<HTMLSpanElement>,\n\t\"children\"\n> & {\n\toptions: ReadonlyArray<GlassSegmentedOption>;\n\tselected: readonly number[];\n\theight?: number;\n\tinset?: number;\n\tpressScale?: number;\n\tdisabled?: boolean;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tliquid?: number;\n\tonDragSelect?: (index: number) => void;\n\tref?: Ref<HTMLSpanElement>;\n\tcontrolsRef?: Ref<UseGlassSegmentedResult>;\n\titems?: (bounds: OptionBounds[]) => ReactNode;\n};\n\nexport function GlassSegmentedSurface({\n\toptions,\n\tselected,\n\theight = 36,\n\tinset,\n\tpressScale,\n\tdisabled,\n\tlens: lensOverrides,\n\ttheme: themeProp,\n\tliquid,\n\tonDragSelect,\n\tclassName,\n\tstyle,\n\tref,\n\tcontrolsRef,\n\titems,\n\t...rest\n}: GlassSegmentedSurfaceProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst lens = useLens(theme, lensOverrides, toggleLens);\n\tconst controls = useGlassSegmented({\n\t\tselected,\n\t\toptionCount: options.length,\n\t\theight,\n\t\tinset,\n\t\tpressScale,\n\t\tdisabled,\n\t\tonDragSelect,\n\t});\n\tconst {\n\t\tgeometry,\n\t\truns,\n\t\tdividers,\n\t\tbounds,\n\t\tattachRow,\n\t\tattachOption,\n\t\trootRef,\n\t\trootProps,\n\t\tpress,\n\t} = controls;\n\tuseImperativeHandle(controlsRef, () => controls, [controls]);\n\n\tconst { margin, trackWidth, containerWidth, containerHeight } = geometry;\n\tconst chosen = new Set(selected);\n\n\tconst row = (highlighted: boolean, copy = false) => (\n\t\t<div\n\t\t\tclassName=\"glass-segmented__row\"\n\t\t\tstyle={{ height, padding: `0 ${geometry.inset}px` }}\n\t\t\tdata-highlighted={highlighted ? \"\" : undefined}\n\t\t\taria-hidden=\"true\"\n\t\t\tref={highlighted || copy ? undefined : attachRow}\n\t\t>\n\t\t\t{options.map((option, index) => (\n\t\t\t\t<span\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tdata-option=\"\"\n\t\t\t\t\tdata-selected={chosen.has(index) ? \"\" : undefined}\n\t\t\t\t\tref={highlighted || copy ? undefined : attachOption(index)}\n\t\t\t\t\tclassName=\"glass-segmented__option\"\n\t\t\t\t>\n\t\t\t\t\t{option.label}\n\t\t\t\t</span>\n\t\t\t))}\n\n\t\t\t{highlighted\n\t\t\t\t? dividers.map((at) => (\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tkey={at}\n\t\t\t\t\t\t\tclassName=\"glass-segmented__divider\"\n\t\t\t\t\t\t\tstyle={{ left: at }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))\n\t\t\t\t: null}\n\t\t</div>\n\t);\n\n\treturn (\n\t\t<span\n\t\t\t{...rest}\n\t\t\tonPointerDown={(event) => {\n\t\t\t\trest.onPointerDown?.(event);\n\t\t\t\trootProps.onPointerDown(event);\n\t\t\t}}\n\t\t\tonPointerMove={(event) => {\n\t\t\t\trest.onPointerMove?.(event);\n\t\t\t\trootProps.onPointerMove(event);\n\t\t\t}}\n\t\t\tonPointerUp={(event) => {\n\t\t\t\trest.onPointerUp?.(event);\n\t\t\t\trootProps.onPointerUp(event);\n\t\t\t}}\n\t\t\tonPointerCancel={(event) => {\n\t\t\t\trest.onPointerCancel?.(event);\n\t\t\t\trootProps.onPointerCancel(event);\n\t\t\t}}\n\t\t\tref={(element) => {\n\t\t\t\trootRef.current = element;\n\t\t\t\tif (typeof ref === \"function\") ref(element);\n\t\t\t\telse if (ref) ref.current = element;\n\t\t\t}}\n\t\t\tclassName={[\"glass-segmented__box\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-theme={theme}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tdata-measured={trackWidth > 0 ? \"\" : undefined}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t...style,\n\t\t\t\t\t\"--toggle-height\": `${height}px`,\n\t\t\t\t\t\"--segment-pill\": `${geometry.indicatorHeight}px`,\n\t\t\t\t\t\"--segment-shadow\": lens.restEdgeShadow,\n\t\t\t\t\t\"--segment-rest\": \"1\",\n\t\t\t\t} as CSSProperties\n\t\t\t}\n\t\t>\n\t\t\t{row(false)}\n\n\t\t\t{trackWidth > 0\n\t\t\t\t? runs.map((run, position) => (\n\t\t\t\t\t\t<SegmentCapsule\n\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: that is the point\n\t\t\t\t\t\t\tkey={position}\n\t\t\t\t\t\t\trun={run}\n\t\t\t\t\t\t\tindicatorHeight={geometry.indicatorHeight}\n\t\t\t\t\t\t\tmargin={margin}\n\t\t\t\t\t\t\ttrackHeight={height}\n\t\t\t\t\t\t\tcontainerWidth={containerWidth}\n\t\t\t\t\t\t\tcontainerHeight={containerHeight}\n\t\t\t\t\t\t\tpress={press}\n\t\t\t\t\t\t\tliquid={liquid}\n\t\t\t\t\t\t\tlens={lens}\n\t\t\t\t\t\t\tplain={row(false, true)}\n\t\t\t\t\t\t\tface={row(true)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))\n\t\t\t\t: null}\n\n\t\t\t{items?.(bounds)}\n\t\t</span>\n\t);\n}\n\nfunction SegmentCapsule({\n\trun,\n\tindicatorHeight,\n\tmargin,\n\ttrackHeight,\n\tcontainerWidth,\n\tcontainerHeight,\n\tpress,\n\tliquid,\n\tlens,\n\tplain,\n\tface,\n}: {\n\trun: SegmentRun;\n\tindicatorHeight: number;\n\tmargin: number;\n\ttrackHeight: number;\n\tcontainerWidth: number;\n\tcontainerHeight: number;\n\tpress: SegmentPress;\n\tliquid?: number;\n\tlens: LensProfile;\n\tplain: ReactNode;\n\tface: ReactNode;\n}) {\n\tconst lensProps = useSegmentLens({\n\t\trun,\n\t\tindicatorHeight,\n\t\tmargin,\n\t\tpress,\n\t\tliquid,\n\t});\n\n\treturn (\n\t\t<Glass\n\t\t\tclassName=\"glass-segmented__glass\"\n\t\t\twidth={containerWidth}\n\t\t\theight={containerHeight}\n\t\t\ty={margin + trackHeight / 2}\n\t\t\t{...lensProps}\n\t\t\tstyle={{ margin: -margin }}\n\t\t\tlens={lens}\n\t\t\ttintColor=\"var(--glass-body)\"\n\t\t\trelax\n\t\t\trefractionTarget={<div style={{ padding: margin }}>{plain}</div>}\n\t\t\tface={<div style={{ padding: margin }}>{face}</div>}\n\t\t/>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-segmented-surface.tsx"
    },
    {
      "path": "src/glass/engine.ts",
      "content": "let smoothDisplacement: boolean | undefined;\n\nexport function displacementIsSmooth() {\n\tif (smoothDisplacement === undefined) {\n\t\tsmoothDisplacement =\n\t\t\ttypeof navigator !== \"undefined\" &&\n\t\t\t/\\bGecko\\/\\d/.test(navigator.userAgent);\n\t}\n\treturn smoothDisplacement;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/engine.ts"
    },
    {
      "path": "src/glass/glass-toggle-group.tsx",
      "content": "\"use client\";\n\nimport { type ReactNode, useCallback, useRef, useState } from \"react\";\nimport {\n\tGlassSegmentedSurface,\n\ttype GlassSegmentedSurfaceProps,\n} from \"./glass-segmented-surface\";\nimport \"./glass-segmented.css\";\nimport type { LensProfile } from \"./optics\";\nimport type { GlassTheme } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport type { UseGlassSegmentedResult } from \"./use-glass-segmented\";\n\nexport type GlassToggleItem = {\n\tvalue: string;\n\tlabel: ReactNode;\n\tdisabled?: boolean;\n};\n\ntype Common = {\n\toptions: ReadonlyArray<string | GlassToggleItem>;\n\theight?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tdisabled?: boolean;\n\tclassName?: string;\n\t\"aria-label\"?: string;\n\tsurfaceProps?: Partial<GlassSegmentedSurfaceProps>;\n};\n\nexport type GlassToggleGroupProps = Common &\n\t(\n\t\t| {\n\t\t\t\ttype?: \"single\";\n\t\t\t\tvalue?: string | null;\n\t\t\t\tdefaultValue?: string | null;\n\t\t\t\tonValueChange?: (value: string | null) => void;\n\t\t  }\n\t\t| {\n\t\t\t\ttype: \"multiple\";\n\t\t\t\tvalue?: string[];\n\t\t\t\tdefaultValue?: string[];\n\t\t\t\tonValueChange?: (value: string[]) => void;\n\t\t  }\n\t);\n\nfunction normalise(option: string | GlassToggleItem): GlassToggleItem {\n\treturn typeof option === \"string\" ? { value: option, label: option } : option;\n}\n\nexport function GlassToggleGroup(props: GlassToggleGroupProps) {\n\tconst {\n\t\toptions,\n\t\theight = 36,\n\t\tlens,\n\t\ttheme: themeProp,\n\t\tdisabled,\n\t\tclassName,\n\t\t\"aria-label\": ariaLabel,\n\t\tsurfaceProps,\n\t} = props;\n\tconst theme = useGlassTheme(themeProp);\n\tconst items = options.map(normalise);\n\tconst multiple = props.type === \"multiple\";\n\tconst controls = useRef<UseGlassSegmentedResult>(null);\n\n\tconst [uncontrolledSingle, setUncontrolledSingle] = useState<string | null>(\n\t\t!multiple ? (props.defaultValue ?? null) : null,\n\t);\n\tconst [uncontrolledMany, setUncontrolledMany] = useState<string[]>(\n\t\tmultiple ? ((props.defaultValue as string[]) ?? []) : [],\n\t);\n\n\tconst pressedValues = multiple\n\t\t? ((props.value as string[] | undefined) ?? uncontrolledMany)\n\t\t: [\n\t\t\t\t(props.value as string | null | undefined) ?? uncontrolledSingle ?? \"\",\n\t\t\t].filter(Boolean);\n\n\tconst setPressed = useCallback(\n\t\t(value: string, next: boolean) => {\n\t\t\tif (props.type === \"multiple\") {\n\t\t\t\tconst current = props.value ?? uncontrolledMany;\n\t\t\t\tconst updated = next\n\t\t\t\t\t? items\n\t\t\t\t\t\t\t.map((item) => item.value)\n\t\t\t\t\t\t\t.filter((entry) =>\n\t\t\t\t\t\t\t\tentry === value ? true : current.includes(entry),\n\t\t\t\t\t\t\t)\n\t\t\t\t\t: current.filter((entry) => entry !== value);\n\t\t\t\tif (props.value === undefined) setUncontrolledMany(updated);\n\t\t\t\tprops.onValueChange?.(updated);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst updated = next ? value : null;\n\t\t\tif (props.value === undefined) setUncontrolledSingle(updated);\n\t\t\tprops.onValueChange?.(updated);\n\t\t},\n\t\t[items, props, uncontrolledMany],\n\t);\n\n\tconst pressedFlags = items.map((item) => pressedValues.includes(item.value));\n\tconst selected = pressedFlags.reduce<number[]>((all, on, index) => {\n\t\tif (on) all.push(index);\n\t\treturn all;\n\t}, []);\n\n\treturn (\n\t\t// biome-ignore lint/a11y/useSemanticElements: a group of toggle buttons, not a fieldset\n\t\t<div\n\t\t\tclassName={[\"glass-segmented\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-theme={theme}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\trole=\"group\"\n\t\t\taria-label={ariaLabel}\n\t\t>\n\t\t\t<GlassSegmentedSurface\n\t\t\t\t{...surfaceProps}\n\t\t\t\toptions={items}\n\t\t\t\tselected={selected}\n\t\t\t\theight={height}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlens={lens}\n\t\t\t\ttheme={theme}\n\t\t\t\tonDragSelect={\n\t\t\t\t\tmultiple\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: (index) => {\n\t\t\t\t\t\t\t\tconst item = items[index];\n\t\t\t\t\t\t\t\tif (item && !item.disabled && !pressedFlags[index]) {\n\t\t\t\t\t\t\t\t\tsetPressed(item.value, true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontrolsRef={controls}\n\t\t\t\titems={(bounds) =>\n\t\t\t\t\titems.map((item, index) => (\n\t\t\t\t\t\t<button\n\t\t\t\t\t\t\tkey={item.value}\n\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\taria-pressed={pressedFlags[index]}\n\t\t\t\t\t\t\tdisabled={disabled || item.disabled}\n\t\t\t\t\t\t\tclassName=\"glass-segmented__hit\"\n\t\t\t\t\t\t\tdata-state={pressedFlags[index] ? \"on\" : \"off\"}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\tleft: bounds[index]?.left ?? 0,\n\t\t\t\t\t\t\t\twidth: bounds[index]?.width ?? 0,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetPressed(item.value, !pressedFlags[index]);\n\t\t\t\t\t\t\t\tcontrols.current?.flash();\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<span className=\"glass-segmented__hit-label\">{item.label}</span>\n\t\t\t\t\t\t</button>\n\t\t\t\t\t))\n\t\t\t\t}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-toggle-group.tsx"
    },
    {
      "path": "src/glass/use-glass-slider.ts",
      "content": "\"use client\";\n\nimport {\n\ttype AnimationPlaybackControls,\n\tanimate,\n\ttype MotionValue,\n\tuseMotionValue,\n\tuseReducedMotion,\n\tuseTransform,\n} from \"motion/react\";\nimport {\n\ttype PointerEvent as ReactPointerEvent,\n\ttype RefObject,\n\tuseCallback,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tCLOSE,\n\tDEFAULT_LIQUID,\n\tOPEN,\n\tPRESS_SCALE,\n\trubberBand,\n\tTRAVEL,\n} from \"./motion\";\nimport { MAX_SPREAD, squashed, useSquish } from \"./use-squish\";\n\nconst OVERSHOOT = 0.06;\n\nexport function clamp(value: number, low: number, high: number) {\n\treturn value < low ? low : value > high ? high : value;\n}\n\nfunction quantise(value: number, min: number, max: number, step: number) {\n\tif (step <= 0) return clamp(value, min, max);\n\treturn clamp(min + Math.round((value - min) / step) * step, min, max);\n}\n\nfunction tidy(value: number, step: number) {\n\tconst decimals = (String(step).split(\".\")[1] ?? \"\").length;\n\treturn decimals > 0 ? Number(value.toFixed(decimals)) : value;\n}\n\nexport type GlassSliderGeometry = {\n\twidth: number;\n\ttrackHeight: number;\n\tthumbWidth: number;\n\tthumbHeight: number;\n\ttravel: number;\n\tmargin: number;\n\tcontainerWidth: number;\n\tcontainerHeight: number;\n};\n\nexport type UseGlassSliderOptions = {\n\tvalue: number;\n\tonValueChange?: (value: number) => void;\n\tmin?: number;\n\tmax?: number;\n\tstep?: number;\n\twidth?: number;\n\ttrackHeight?: number;\n\tthumbHeight?: number;\n\tthumbWidth?: number;\n\tdisabled?: boolean;\n\tinteractive?: boolean;\n\tliquid?: number;\n};\n\nexport type UseGlassSliderResult = {\n\tgeometry: GlassSliderGeometry;\n\trootStyle: Record<string, string>;\n\tlensProps: {\n\t\twidth: number;\n\t\theight: number;\n\t\tx: MotionValue<number>;\n\t\ty: number;\n\t\tlensWidth: MotionValue<number>;\n\t\tlensHeight: MotionValue<number>;\n\t\tlensRadius: MotionValue<number>;\n\t\tshadowOpacity: MotionValue<number>;\n\t\ttintOpacity: MotionValue<number>;\n\t\tedgeBias: MotionValue<number>;\n\t\tlag?: MotionValue<number>;\n\t};\n\ttrackProps: {\n\t\tonPointerDown: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerMove: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerUp: (event: ReactPointerEvent<HTMLElement>) => void;\n\t\tonPointerCancel: (event: ReactPointerEvent<HTMLElement>) => void;\n\t};\n\trootRef: RefObject<HTMLElement | null>;\n\thitRef: RefObject<HTMLElement | null>;\n\tsetPressed: (pressed: boolean) => void;\n};\n\nexport function useGlassSlider({\n\tvalue,\n\tonValueChange,\n\tmin = 0,\n\tmax = 100,\n\tstep = 1,\n\twidth = 240,\n\ttrackHeight = 6,\n\tthumbHeight = 22,\n\tthumbWidth: thumbWidthProp,\n\tdisabled,\n\tinteractive = true,\n\tliquid = DEFAULT_LIQUID,\n}: UseGlassSliderOptions): UseGlassSliderResult {\n\tconst reduceMotion = useReducedMotion() ?? false;\n\n\tconst thumbWidth = thumbWidthProp ?? Math.round(2 * thumbHeight);\n\tconst travel = width - thumbWidth;\n\tconst overshoot = width * OVERSHOOT;\n\n\tconst restHalfWidth = thumbWidth / 2;\n\tconst restHalfHeight = thumbHeight / 2;\n\tconst margin =\n\t\tMath.ceil(\n\t\t\tMath.max(\n\t\t\t\trestHalfWidth * (PRESS_SCALE * MAX_SPREAD - 1),\n\t\t\t\trestHalfHeight * (PRESS_SCALE - 1),\n\t\t\t) + overshoot,\n\t\t) + 2;\n\n\tconst span = max - min || 1;\n\tconst offsetFor = useCallback(\n\t\t(next: number) => ((clamp(next, min, max) - min) / span) * travel,\n\t\t[max, min, span, travel],\n\t);\n\n\tconst x = useMotionValue(offsetFor(value));\n\tconst lensHalfWidth = useMotionValue(restHalfWidth);\n\tconst lensHalfHeight = useMotionValue(restHalfHeight);\n\tconst restProgress = useMotionValue(1);\n\tconst shadowOpacity = useMotionValue(0);\n\n\tconst { squish, lag, setHeld, kick, jumped } = useSquish(\n\t\tx,\n\t\t!reduceMotion,\n\t\tliquid,\n\t);\n\n\tconst lensWidth = useTransform(\n\t\t[lensHalfWidth, squish],\n\t\t([half, amount]: number[]) => squashed(half * 2, amount, true),\n\t);\n\tconst lensHeight = useTransform(\n\t\t[lensHalfHeight, squish],\n\t\t([half, amount]: number[]) => squashed(half * 2, amount, false),\n\t);\n\tconst lensRadius = useTransform(\n\t\t[lensWidth, lensHeight],\n\t\t([across, tall]: number[]) => Math.min(across, tall) / 2,\n\t);\n\tconst lensX = useTransform(x, (at) => margin + thumbWidth / 2 + at);\n\tconst edgeBias = useTransform(restProgress, (at) => at * 0.5);\n\n\tconst rootRef = useRef<HTMLElement | null>(null);\n\tconst hitRef = useRef<HTMLElement | null>(null);\n\tconst pointer = useRef<number | null>(null);\n\tconst dragging = useRef(false);\n\tconst moveAnimation = useRef<AnimationPlaybackControls | undefined>(\n\t\tundefined,\n\t);\n\n\tconst setShape = useCallback(\n\t\t(open: boolean) => {\n\t\t\tconst factor = open ? PRESS_SCALE : 1;\n\t\t\tconst options = open ? OPEN : CLOSE;\n\t\t\tconst targets: Array<[typeof lensHalfWidth, number]> = [\n\t\t\t\t[lensHalfWidth, restHalfWidth * factor],\n\t\t\t\t[lensHalfHeight, restHalfHeight * factor],\n\t\t\t\t[restProgress, open ? 0 : 1],\n\t\t\t\t[shadowOpacity, open ? 1 : 0],\n\t\t\t];\n\t\t\tfor (const [motionValue, target] of targets) {\n\t\t\t\tif (reduceMotion) motionValue.set(target);\n\t\t\t\telse animate(motionValue, target, options);\n\t\t\t}\n\t\t\tsetHeld(open && !reduceMotion);\n\t\t\tif (open) kick(1);\n\t\t},\n\t\t[\n\t\t\tkick,\n\t\t\tlensHalfHeight,\n\t\t\tlensHalfWidth,\n\t\t\treduceMotion,\n\t\t\trestHalfHeight,\n\t\t\trestHalfWidth,\n\t\t\trestProgress,\n\t\t\tsetHeld,\n\t\t\tshadowOpacity,\n\t\t],\n\t);\n\n\t// The fill is a share of the track, so it is right at any width, including\n\t// before a slider that fills its container has measured it.\n\tconst [rootStyle] = useState(() => {\n\t\tconst progress = travel > 0 ? clamp(x.get() / travel, 0, 1) : 0;\n\t\treturn {\n\t\t\t\"--slider-fill\": `${progress * 100}%`,\n\t\t\t\"--slider-progress\": String(progress),\n\t\t};\n\t});\n\n\tuseEffect(() => {\n\t\tconst apply = (at: number) => {\n\t\t\tconst root = rootRef.current;\n\t\t\tif (!root) return;\n\t\t\tconst progress = travel > 0 ? clamp(at / travel, 0, 1) : 0;\n\t\t\troot.style.setProperty(\"--slider-fill\", `${progress * 100}%`);\n\t\t\troot.style.setProperty(\"--slider-progress\", String(progress));\n\t\t};\n\t\tapply(x.get());\n\t\treturn x.on(\"change\", apply);\n\t}, [travel, x]);\n\n\t// A new width moves the handle to where its value now sits, at once: a spring\n\t// would slide it across the track every time the container resized.\n\tconst lastTravel = useRef(travel);\n\tuseLayoutEffect(() => {\n\t\tif (lastTravel.current === travel) return;\n\t\tlastTravel.current = travel;\n\t\tif (dragging.current) return;\n\t\tmoveAnimation.current?.stop();\n\t\t// jump, not set: set would record the move as velocity, and the spring\n\t\t// that follows a value change would carry it past the new spot and back.\n\t\tx.jump(offsetFor(value));\n\t\tjumped();\n\t}, [jumped, offsetFor, travel, value, x]);\n\n\tuseEffect(() => {\n\t\tif (dragging.current) return;\n\t\tconst target = offsetFor(value);\n\t\tmoveAnimation.current?.stop();\n\t\tif (reduceMotion) x.set(target);\n\t\telse moveAnimation.current = animate(x, target, TRAVEL);\n\t}, [offsetFor, reduceMotion, value, x]);\n\n\tuseEffect(\n\t\t() => () => {\n\t\t\tmoveAnimation.current?.stop();\n\t\t},\n\t\t[],\n\t);\n\n\tconst offsetAt = useCallback(\n\t\t(clientX: number) => {\n\t\t\tconst hit = hitRef.current;\n\t\t\tif (!hit) return x.get();\n\t\t\tconst box = hit.getBoundingClientRect();\n\t\t\tconst scale = box.width > 0 ? box.width / width : 1;\n\t\t\treturn (clientX - box.left) / scale - thumbWidth / 2;\n\t\t},\n\t\t[thumbWidth, width, x],\n\t);\n\n\tconst valueAt = useCallback(\n\t\t(offset: number) => {\n\t\t\tconst at = clamp(offset, 0, travel);\n\t\t\tconst raw = min + (travel > 0 ? at / travel : 0) * span;\n\t\t\treturn tidy(quantise(raw, min, max, step), step);\n\t\t},\n\t\t[max, min, span, step, travel],\n\t);\n\n\tconst onPointerDown = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (disabled || pointer.current !== null) return;\n\t\tpointer.current = event.pointerId;\n\t\tsetShape(true);\n\t\tif (!interactive) return;\n\t\tevent.currentTarget.setPointerCapture(event.pointerId);\n\t\tdragging.current = true;\n\t\tmoveAnimation.current?.stop();\n\t\tconst offset = offsetAt(event.clientX);\n\t\tx.set(clamp(offset, 0, travel));\n\t\tconst next = valueAt(offset);\n\t\tif (next !== value) onValueChange?.(next);\n\t};\n\n\tconst onPointerMove = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (event.pointerId !== pointer.current || !interactive) return;\n\t\tconst offset = offsetAt(event.clientX);\n\t\tlet position = offset;\n\t\tif (position < 0) position = -rubberBand(-position, overshoot);\n\t\telse if (position > travel) {\n\t\t\tposition = travel + rubberBand(position - travel, overshoot);\n\t\t}\n\t\tx.set(position);\n\t\tconst next = valueAt(offset);\n\t\tif (next !== value) onValueChange?.(next);\n\t};\n\n\tconst endPointer = (event: ReactPointerEvent<HTMLElement>) => {\n\t\tif (event.pointerId !== pointer.current) return;\n\t\tpointer.current = null;\n\t\tdragging.current = false;\n\t\tsetShape(false);\n\t\tif (!interactive) return;\n\t\tconst settled = offsetFor(valueAt(clamp(x.get(), 0, travel)));\n\t\tmoveAnimation.current?.stop();\n\t\tif (reduceMotion) x.set(settled);\n\t\telse moveAnimation.current = animate(x, settled, TRAVEL);\n\t};\n\n\treturn {\n\t\trootStyle,\n\t\tgeometry: {\n\t\t\twidth,\n\t\t\ttrackHeight,\n\t\t\tthumbWidth,\n\t\t\tthumbHeight,\n\t\t\ttravel,\n\t\t\tmargin,\n\t\t\tcontainerWidth: width + margin * 2,\n\t\t\tcontainerHeight: thumbHeight + margin * 2,\n\t\t},\n\t\tlensProps: {\n\t\t\twidth: width + margin * 2,\n\t\t\theight: thumbHeight + margin * 2,\n\t\t\tx: lensX,\n\t\t\ty: margin + thumbHeight / 2,\n\t\t\tlensWidth,\n\t\t\tlensHeight,\n\t\t\tlensRadius,\n\t\t\tshadowOpacity,\n\t\t\ttintOpacity: restProgress,\n\t\t\tedgeBias,\n\t\t\tlag,\n\t\t},\n\t\ttrackProps: {\n\t\t\tonPointerDown,\n\t\t\tonPointerMove,\n\t\t\tonPointerUp: endPointer,\n\t\t\tonPointerCancel: endPointer,\n\t\t},\n\t\trootRef,\n\t\thitRef,\n\t\tsetPressed: setShape,\n\t};\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/use-glass-slider.ts"
    },
    {
      "path": "src/glass/glass-pane.tsx",
      "content": "\"use client\";\n\nimport {\n\tanimate,\n\ttype MotionValue,\n\tuseMotionValue,\n\tuseReducedMotion,\n} from \"motion/react\";\nimport {\n\ttype CSSProperties,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype Ref,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { supportsBackdropRefraction } from \"./backdrop\";\nimport { Glass } from \"./glass\";\nimport \"./glass-pane.css\";\nimport { DEFAULT_LIQUID, useDerived } from \"./motion\";\nimport type { LensProfile, LensShape } from \"./optics\";\nimport { type GlassTheme, paneLens, useLens } from \"./presets\";\nimport {\n\tLensPoolProvider,\n\tuseGlassBackdrop,\n\tuseGlassScope,\n\tuseLensPool,\n} from \"./scope\";\nimport { afterScroll, useInView } from \"./settle\";\nimport { useGlassTheme } from \"./theme\";\nimport { squashed, useSquish } from \"./use-squish\";\n\nexport type GlassPaneVariant = \"regular\" | \"clear\";\n\nexport type GlassRefraction = \"interactive\" | \"always\";\n\nconst MATERIAL: Record<\n\tGlassPaneVariant,\n\t{ tint: number; blur: number; saturate: number }\n> = {\n\tregular: { tint: 0.5, blur: 14, saturate: 1.8 },\n\tclear: { tint: 0.12, blur: 0, saturate: 1 },\n};\n\nconst PRESS_GROW = 0.1;\nconst EDGE_BIAS = 0.5;\nconst LIVE_FROM = 0.3;\nconst LIVE_SETTLE_MS = 900;\nconst WARM_PRESS = [0.35, 1] as const;\nconst VIEW_MARGIN = \"120px\";\nconst NESTED_MARGIN = 48;\nconst NESTED_FEATHER = 8;\nconst PRESS_LIGHT = 0.18;\nconst BARE_TINT = 0.35;\nconst LAND_EVENT = \"glass-pane:land\";\nconst HIDE_EVENT = \"glass-pane:hide\";\nconst LAND = { type: \"spring\", stiffness: 300, damping: 15 } as const;\nconst LAND_SPEED = 2.4;\n\nexport type GlassLanding = { x: number; y: number };\n\nfunction paneOf(element: Element) {\n\treturn element.classList.contains(\"glass-pane\")\n\t\t? element\n\t\t: element.querySelector(\".glass-pane\");\n}\n\nexport function hideGlass(\n\telement: Element | null | undefined,\n\thidden: boolean,\n) {\n\tif (!element) return;\n\tpaneOf(element)?.dispatchEvent(\n\t\tnew CustomEvent(HIDE_EVENT, { detail: hidden }),\n\t);\n}\n\nexport function landGlass(\n\telement: Element | null | undefined,\n\tdirection: GlassLanding = { x: 0, y: 1 },\n) {\n\tif (!element) return;\n\tpaneOf(element)?.dispatchEvent(\n\t\tnew CustomEvent(LAND_EVENT, { detail: direction }),\n\t);\n}\n\nconst ROOM = 24;\n\nexport type GlassPaneShape = {\n\tx: MotionValue<number>;\n\ty: MotionValue<number>;\n\twidth: MotionValue<number>;\n\theight: MotionValue<number>;\n\tradius: MotionValue<number>;\n};\n\nexport type GlassPaneReach = {\n\ttop: number;\n\tright: number;\n\tbottom: number;\n\tleft: number;\n};\n\nexport type GlassPaneProps = HTMLAttributes<HTMLDivElement> & {\n\tradius?: number | \"capsule\";\n\tvariant?: GlassPaneVariant;\n\ttint?: string;\n\ttintOpacity?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\trefraction?: GlassRefraction;\n\tpress?: MotionValue<number>;\n\tliquid?: number;\n\tfrost?: MotionValue<number>;\n\tshape?: GlassPaneShape;\n\treach?: GlassPaneReach;\n\tref?: Ref<HTMLDivElement>;\n\tchildren?: ReactNode;\n};\n\nconst NO_REACH: GlassPaneReach = { top: 0, right: 0, bottom: 0, left: 0 };\n\nexport function GlassPane({\n\tradius = \"capsule\",\n\tvariant = \"regular\",\n\ttint,\n\ttintOpacity,\n\tlens: lensOverrides,\n\ttheme: themeProp,\n\trefraction = \"interactive\",\n\tpress,\n\tliquid = DEFAULT_LIQUID,\n\tfrost,\n\tshape,\n\treach = NO_REACH,\n\tclassName,\n\tstyle,\n\tref,\n\tchildren,\n\t...rest\n}: GlassPaneProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst lens = useLens(theme, lensOverrides, paneLens);\n\tconst reduceMotion = useReducedMotion() ?? false;\n\tconst material = MATERIAL[variant];\n\tconst bodyOpacity = tintOpacity ?? material.tint;\n\n\tconst rootRef = useRef<HTMLDivElement | null>(null);\n\tconst contentRef = useRef<HTMLDivElement | null>(null);\n\tconst [size, setSize] = useState({ width: 0, height: 0 });\n\tconst [hidden, setHidden] = useState(false);\n\tconst paneWidth = useMotionValue(0);\n\tconst paneHeight = useMotionValue(0);\n\n\tuseLayoutEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\t\tconst measure = () => {\n\t\t\tpaneWidth.set(root.offsetWidth);\n\t\t\tpaneHeight.set(root.offsetHeight);\n\t\t\tsetSize((current) =>\n\t\t\t\tcurrent.width === root.offsetWidth &&\n\t\t\t\tcurrent.height === root.offsetHeight\n\t\t\t\t\t? current\n\t\t\t\t\t: { width: root.offsetWidth, height: root.offsetHeight },\n\t\t\t);\n\t\t};\n\t\tmeasure();\n\t\tif (typeof ResizeObserver === \"undefined\") return;\n\t\tlet frame = 0;\n\t\tconst observer = new ResizeObserver(() => {\n\t\t\tpaneWidth.set(root.offsetWidth);\n\t\t\tpaneHeight.set(root.offsetHeight);\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tframe = requestAnimationFrame(measure);\n\t\t});\n\t\tobserver.observe(root);\n\t\treturn () => {\n\t\t\tobserver.disconnect();\n\t\t\tcancelAnimationFrame(frame);\n\t\t};\n\t}, [paneHeight, paneWidth]);\n\n\tconst { width, height } = size;\n\tconst drawn = width > 0 && height > 0;\n\tconst cornerFor = (tall: number) =>\n\t\tradius === \"capsule\" ? tall / 2 : Math.min(radius, tall / 2);\n\n\tconst idle = useMotionValue(0);\n\tconst pressed = press ?? idle;\n\tconst still = useMotionValue(0);\n\tconst { squish, kick } = useSquish(still, !reduceMotion, liquid);\n\tuseEffect(() => {\n\t\tlet down = pressed.get() > 0.5;\n\t\treturn pressed.on(\"change\", (value) => {\n\t\t\tconst now = value > 0.5;\n\t\t\tif (now !== down) kick(now ? 1 : -1);\n\t\t\tdown = now;\n\t\t});\n\t}, [kick, pressed]);\n\n\tconst restable = refraction === \"always\";\n\tconst [deferred, setDeferred] = useState(false);\n\tuseLayoutEffect(() => setDeferred(!supportsBackdropRefraction()), []);\n\n\t// Safari and Firefox draw filters on the CPU and redraw them as they scroll\n\t// back into view, so resting glass there only starts bending on screen, once\n\t// the page has stopped scrolling.\n\tconst inView = useInView(rootRef, VIEW_MARGIN, restable && deferred);\n\tconst [resting, setResting] = useState(false);\n\tuseEffect(() => {\n\t\tif (!restable || (deferred && !inView)) {\n\t\t\tsetResting(false);\n\t\t\treturn;\n\t\t}\n\t\tif (!deferred) {\n\t\t\tsetResting(true);\n\t\t\treturn;\n\t\t}\n\t\treturn afterScroll(() => setResting(true));\n\t}, [deferred, inView, restable]);\n\n\tconst [live, setLive] = useState(false);\n\tuseEffect(() => {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\t// Shapes are derived during render, so their changes can arrive mid-render.\n\t\tconst wake = () => {\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = undefined;\n\t\t\tqueueMicrotask(() => setLive(true));\n\t\t};\n\t\tconst settle = () => {\n\t\t\tif (timer !== undefined) return;\n\t\t\ttimer = setTimeout(() => {\n\t\t\t\ttimer = undefined;\n\t\t\t\tsetLive(false);\n\t\t\t}, LIVE_SETTLE_MS);\n\t\t};\n\t\tconst follow = (value: number) => (value > LIVE_FROM ? wake() : settle());\n\t\tfollow(pressed.get());\n\t\tconst stops = [pressed.on(\"change\", follow)];\n\t\tif (shape) {\n\t\t\tconst moved = () => {\n\t\t\t\twake();\n\t\t\t\tsettle();\n\t\t\t};\n\t\t\tfor (const value of [shape.x, shape.y, shape.width, shape.height]) {\n\t\t\t\tstops.push(value.on(\"change\", moved));\n\t\t\t}\n\t\t}\n\t\treturn () => {\n\t\t\tclearTimeout(timer);\n\t\t\tfor (const stop of stops) stop();\n\t\t};\n\t}, [pressed, shape]);\n\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root) return;\n\t\tconst hide = (event: Event) =>\n\t\t\tsetHidden(Boolean((event as CustomEvent<boolean>).detail));\n\t\troot.addEventListener(HIDE_EVENT, hide);\n\t\treturn () => root.removeEventListener(HIDE_EVENT, hide);\n\t}, []);\n\n\tconst nudgeX = useMotionValue(0);\n\tconst nudgeY = useMotionValue(0);\n\tuseEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tif (!root || reduceMotion) return;\n\t\tconst land = (event: Event) => {\n\t\t\tconst way = (event as CustomEvent<GlassLanding>).detail ?? { x: 0, y: 1 };\n\t\t\tconst speed = LAND_SPEED * paneHeight.get();\n\t\t\tanimate(nudgeX, 0, { ...LAND, velocity: way.x * speed });\n\t\t\tanimate(nudgeY, 0, { ...LAND, velocity: way.y * speed });\n\t\t};\n\t\troot.addEventListener(LAND_EVENT, land);\n\t\treturn () => root.removeEventListener(LAND_EVENT, land);\n\t}, [nudgeX, nudgeY, paneHeight, reduceMotion]);\n\tuseEffect(() => {\n\t\tconst move = () => {\n\t\t\tconst content = contentRef.current;\n\t\t\tif (!content) return;\n\t\t\tconst x = nudgeX.get();\n\t\t\tconst y = nudgeY.get();\n\t\t\tcontent.style.transform =\n\t\t\t\tx === 0 && y === 0 ? \"\" : `translate(${x}px, ${y}px)`;\n\t\t};\n\t\tconst stops = [nudgeX.on(\"change\", move), nudgeY.on(\"change\", move)];\n\t\treturn () => {\n\t\t\tfor (const stop of stops) stop();\n\t\t};\n\t}, [nudgeX, nudgeY]);\n\n\tconst boxX = useDerived([paneWidth], ([w]) => w / 2);\n\tconst boxY = useDerived([paneHeight], ([h]) => h / 2);\n\tconst centreX = shape?.x ?? boxX;\n\tconst centreY = shape?.y ?? boxY;\n\tconst baseWidth = shape?.width ?? paneWidth;\n\tconst baseHeight = shape?.height ?? paneHeight;\n\tconst baseRadius = useDerived(\n\t\tshape ? [shape.radius] : [paneHeight],\n\t\t([value]) => (shape ? value : cornerFor(value)),\n\t);\n\n\tconst grow = useDerived([pressed, paneHeight], ([amount, tall]) =>\n\t\tshape ? 0 : tall * PRESS_GROW * amount,\n\t);\n\tconst lensWidth = useDerived(\n\t\t[baseWidth, grow, squish],\n\t\t([value, extra, amount]) => squashed(value + extra * 2, amount, true),\n\t);\n\tconst lensHeight = useDerived(\n\t\t[baseHeight, grow, squish],\n\t\t([value, extra, amount]) => squashed(value + extra * 2, amount, false),\n\t);\n\tconst lensRadius = useDerived(\n\t\t[baseRadius, grow, lensWidth, lensHeight],\n\t\t([value, extra, across, tall]) =>\n\t\t\tradius === \"capsule\" && !shape\n\t\t\t\t? Math.min(across, tall) / 2\n\t\t\t\t: Math.min(value + extra, across / 2, tall / 2),\n\t);\n\tconst originX = ROOM + reach.left;\n\tconst originY = ROOM + reach.top;\n\tconst lensX = useDerived([centreX, nudgeX], ([at, by]) => originX + at + by);\n\tconst warm = useMemo<LensShape[] | undefined>(() => {\n\t\tif (shape || !drawn) return undefined;\n\t\treturn WARM_PRESS.map((amount) => {\n\t\t\tconst extra = height * PRESS_GROW * amount;\n\t\t\tconst across = width + extra * 2;\n\t\t\tconst tall = height + extra * 2;\n\t\t\tconst corner =\n\t\t\t\tradius === \"capsule\"\n\t\t\t\t\t? Math.min(across, tall) / 2\n\t\t\t\t\t: Math.min(\n\t\t\t\t\t\t\tMath.min(radius, height / 2) + extra,\n\t\t\t\t\t\t\tacross / 2,\n\t\t\t\t\t\t\ttall / 2,\n\t\t\t\t\t\t);\n\t\t\tconst innerWidth = across - EDGE_BIAS * 2;\n\t\t\tconst innerHeight = tall - EDGE_BIAS * 2;\n\t\t\treturn {\n\t\t\t\thalfWidth: innerWidth / 2,\n\t\t\t\thalfHeight: innerHeight / 2,\n\t\t\t\tborderRadius: Math.max(\n\t\t\t\t\t0,\n\t\t\t\t\tMath.min(corner - EDGE_BIAS, innerWidth / 2, innerHeight / 2),\n\t\t\t\t),\n\t\t\t};\n\t\t});\n\t}, [drawn, height, radius, shape, width]);\n\tconst lensY = useDerived([centreY, nudgeY], ([at, by]) => originY + at + by);\n\tconst solid = useMotionValue(1);\n\tconst frosted = frost ?? solid;\n\tconst blur = useDerived([frosted], ([amount]) => material.blur * amount);\n\tconst body = useDerived([pressed, frosted], ([amount, frostAmount]) =>\n\t\tMath.min(\n\t\t\t1,\n\t\t\tbodyOpacity * (BARE_TINT + (1 - BARE_TINT) * frostAmount) +\n\t\t\t\tPRESS_LIGHT * amount,\n\t\t),\n\t);\n\n\t// Glass on this pane bends a copy of the backdrop dressed as this pane:\n\t// blurred and tinted the same, drawn above the pane and below its content.\n\tconst outer = useGlassScope();\n\tconst backdropNode = useGlassBackdrop();\n\tconst lensesRef = useRef<HTMLDivElement | null>(null);\n\tconst [hosting, setHosting] = useState(false);\n\tuseLayoutEffect(() => {\n\t\tconst root = rootRef.current;\n\t\tsetHosting(\n\t\t\tBoolean(\n\t\t\t\touter &&\n\t\t\t\t\tbackdropNode &&\n\t\t\t\t\troot?.closest(\"[data-glass-nested]\") &&\n\t\t\t\t\tcontentRef.current?.querySelector(\"[data-glass]\"),\n\t\t\t),\n\t\t);\n\t}, [outer, backdropNode]);\n\tconst nested = useLensPool({\n\t\tnested: true,\n\t\tenabled: hosting,\n\t\telement: () => lensesRef.current,\n\t\tbackdrop: () => outer?.backdrop() ?? null,\n\t\tmargin: NESTED_MARGIN,\n\t\tfeather: NESTED_FEATHER,\n\t\tdress: ({ box, frost: layer }) => {\n\t\t\tconst amount = material.blur * frosted.get();\n\t\t\tlayer.style.filter =\n\t\t\t\tamount > 0 ? `blur(${amount}px) saturate(${material.saturate})` : \"\";\n\t\t\tconst tintLayer = rootRef.current?.querySelector(\n\t\t\t\t\":scope > .glass-pane__glass > .glass__tint\",\n\t\t\t);\n\t\t\tif (!tintLayer) return;\n\t\t\tconst style = getComputedStyle(tintLayer);\n\t\t\tbox.style.setProperty(\"--lens-tint\", style.backgroundColor);\n\t\t\tbox.style.setProperty(\"--lens-tint-opacity\", style.opacity);\n\t\t},\n\t});\n\n\tuseEffect(() => {\n\t\tif (!shape) return;\n\t\tconst content = contentRef.current;\n\t\tif (!content) return;\n\t\tconst clip = () => {\n\t\t\tconst w = lensWidth.get();\n\t\t\tconst h = lensHeight.get();\n\t\t\tconst left = centreX.get() - w / 2;\n\t\t\tconst top = centreY.get() - h / 2;\n\t\t\tcontent.style.clipPath = `inset(${top}px ${width - left - w}px ${height - top - h}px ${left}px round ${lensRadius.get()}px)`;\n\t\t};\n\t\tclip();\n\t\tconst stops = [centreX, centreY, lensWidth, lensHeight, lensRadius].map(\n\t\t\t(value) => value.on(\"change\", clip),\n\t\t);\n\t\treturn () => {\n\t\t\tfor (const stop of stops) stop();\n\t\t};\n\t}, [\n\t\tcentreX,\n\t\tcentreY,\n\t\theight,\n\t\tlensHeight,\n\t\tlensRadius,\n\t\tlensWidth,\n\t\tshape,\n\t\twidth,\n\t]);\n\n\treturn (\n\t\t<div\n\t\t\t{...rest}\n\t\t\tref={(element) => {\n\t\t\t\trootRef.current = element;\n\t\t\t\tif (typeof ref === \"function\") ref(element);\n\t\t\t\telse if (ref) ref.current = element;\n\t\t\t}}\n\t\t\tclassName={[\"glass-pane\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-theme={theme}\n\t\t\tdata-variant={variant}\n\t\t\tdata-drawn={drawn ? \"\" : undefined}\n\t\t\tdata-shaped={shape ? \"\" : undefined}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t\"--glass-pane-fill\": tint ?? \"var(--glass-pane-tint)\",\n\t\t\t\t\t\"--glass-pane-fill-opacity\": String(bodyOpacity),\n\t\t\t\t\t\"--glass-pane-frost\": material.blur\n\t\t\t\t\t\t? `blur(${material.blur}px) saturate(${material.saturate})`\n\t\t\t\t\t\t: \"none\",\n\t\t\t\t\t\"--glass-pane-shadow\": lens.edgeShadow,\n\t\t\t\t\t...style,\n\t\t\t\t\tborderRadius: drawn\n\t\t\t\t\t\t? cornerFor(height)\n\t\t\t\t\t\t: radius === \"capsule\"\n\t\t\t\t\t\t\t? 9999\n\t\t\t\t\t\t\t: radius,\n\t\t\t\t} as CSSProperties\n\t\t\t}\n\t\t>\n\t\t\t{drawn ? (\n\t\t\t\t<Glass\n\t\t\t\t\tclassName=\"glass-pane__glass\"\n\t\t\t\t\twidth={width + ROOM * 2 + reach.left + reach.right}\n\t\t\t\t\theight={height + ROOM * 2 + reach.top + reach.bottom}\n\t\t\t\t\tstyle={{ left: -originX, top: -originY }}\n\t\t\t\t\tx={lensX}\n\t\t\t\t\ty={lensY}\n\t\t\t\t\tlensWidth={lensWidth}\n\t\t\t\t\tlensHeight={lensHeight}\n\t\t\t\t\tlensRadius={lensRadius}\n\t\t\t\t\tlens={lens}\n\t\t\t\t\trefract={resting || live}\n\t\t\t\t\tlight\n\t\t\t\t\twarm={warm}\n\t\t\t\t\ttintColor={tint ?? \"var(--glass-pane-tint)\"}\n\t\t\t\t\ttintOpacity={body}\n\t\t\t\t\ttintBlur={blur}\n\t\t\t\t\ttintSaturate={material.saturate}\n\t\t\t\t\tshadowOpacity={1}\n\t\t\t\t\tedgeBias={EDGE_BIAS}\n\t\t\t\t\thidden={hidden}\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{hosting ? (\n\t\t\t\t<div ref={lensesRef} className=\"glass-pane__lenses\">\n\t\t\t\t\t{nested.render(backdropNode)}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<LensPoolProvider value={hosting ? nested.pool : outer}>\n\t\t\t\t<div ref={contentRef} className=\"glass-pane__content\">\n\t\t\t\t\t{children}\n\t\t\t\t</div>\n\t\t\t</LensPoolProvider>\n\t\t</div>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-pane.tsx"
    },
    {
      "path": "src/glass/glass-slider.tsx",
      "content": "\"use client\";\n\nimport { type InputHTMLAttributes, useCallback, useId, useState } from \"react\";\nimport {\n\tGlassSliderSurface,\n\ttype GlassSliderSurfaceProps,\n} from \"./glass-slider-surface\";\nimport \"./glass-slider.css\";\nimport type { LensProfile } from \"./optics\";\nimport type { GlassTheme } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport { clamp } from \"./use-glass-slider\";\n\ntype NativeProps = Omit<\n\tInputHTMLAttributes<HTMLInputElement>,\n\t\"type\" | \"onChange\" | \"value\" | \"defaultValue\" | \"width\" | \"height\" | \"size\"\n>;\n\nexport type GlassSliderProps = NativeProps & {\n\tvalue?: number;\n\tdefaultValue?: number;\n\tonValueChange?: (value: number) => void;\n\tmin?: number;\n\tmax?: number;\n\tstep?: number;\n\tlabel?: string;\n\twidth?: number;\n\ttrackHeight?: number;\n\tthumbHeight?: number;\n\tthumbWidth?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tsurfaceProps?: Partial<GlassSliderSurfaceProps>;\n};\n\nexport function GlassSlider({\n\tvalue,\n\tdefaultValue = 50,\n\tonValueChange,\n\tmin = 0,\n\tmax = 100,\n\tstep = 1,\n\tlabel,\n\twidth = 240,\n\ttrackHeight = 6,\n\tthumbHeight = 22,\n\tthumbWidth,\n\tlens,\n\ttheme: themeProp,\n\tdisabled,\n\tclassName,\n\tid,\n\tsurfaceProps,\n\t...inputProps\n}: GlassSliderProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst generatedId = useId();\n\tconst inputId = id ?? generatedId;\n\tconst isControlled = value !== undefined;\n\tconst [uncontrolled, setUncontrolled] = useState(defaultValue);\n\tconst current = clamp(isControlled ? value : uncontrolled, min, max);\n\n\tconst commit = useCallback(\n\t\t(next: number) => {\n\t\t\tif (!isControlled) setUncontrolled(next);\n\t\t\tonValueChange?.(next);\n\t\t},\n\t\t[isControlled, onValueChange],\n\t);\n\n\treturn (\n\t\t<label\n\t\t\thtmlFor={inputId}\n\t\t\tclassName={[\"glass-slider\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tdata-theme={theme}\n\t\t>\n\t\t\t{label ? <span className=\"glass-slider__label\">{label}</span> : null}\n\t\t\t<input\n\t\t\t\t{...inputProps}\n\t\t\t\tid={inputId}\n\t\t\t\ttype=\"range\"\n\t\t\t\tclassName=\"glass-slider__input\"\n\t\t\t\tmin={min}\n\t\t\t\tmax={max}\n\t\t\t\tstep={step}\n\t\t\t\tvalue={current}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonChange={(event) => commit(Number(event.currentTarget.value))}\n\t\t\t/>\n\t\t\t<GlassSliderSurface\n\t\t\t\t{...surfaceProps}\n\t\t\t\tvalue={current}\n\t\t\t\tonValueChange={commit}\n\t\t\t\tmin={min}\n\t\t\t\tmax={max}\n\t\t\t\tstep={step}\n\t\t\t\twidth={width}\n\t\t\t\ttrackHeight={trackHeight}\n\t\t\t\tthumbHeight={thumbHeight}\n\t\t\t\tthumbWidth={thumbWidth}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlens={lens}\n\t\t\t\ttheme={theme}\n\t\t\t/>\n\t\t</label>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-slider.tsx"
    },
    {
      "path": "src/glass/scope.tsx",
      "content": "\"use client\";\n\nimport {\n\tcreateContext,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype Ref,\n\tuseContext,\n\tuseId,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\n\nexport type GlassLens = {\n\tindex: number;\n\tbox: HTMLDivElement;\n\tfrost: HTMLDivElement;\n\tcopy: HTMLDivElement;\n\tmargin: number;\n\tfeather: number;\n};\n\nexport type LensPool = {\n\tnested: boolean;\n\telement: () => HTMLElement | null;\n\tbackdrop: () => HTMLElement | null;\n\tlease: () => GlassLens | null;\n\trelease: (lens: GlassLens) => void;\n\tonChange: (listener: () => void) => () => void;\n\t// Content scopes: the filtered layer, and the filter each glass in use hands it.\n\tinPlace?: boolean;\n\tapplyFilter?: (key: string, filter: SVGFilterElement | null) => void;\n};\n\nconst PoolContext = createContext<LensPool | null>(null);\nconst BackdropContext = createContext<ReactNode>(null);\n\nexport const LensPoolProvider = PoolContext.Provider;\n\nexport function useGlassScope() {\n\treturn useContext(PoolContext);\n}\n\nexport function useGlassBackdrop() {\n\treturn useContext(BackdropContext);\n}\n\nexport function offsetWithin(element: Element, scope: HTMLElement) {\n\tconst inner = element.getBoundingClientRect();\n\tconst outer = scope.getBoundingClientRect();\n\tconst scale =\n\t\tscope.offsetWidth > 0 && outer.width > 0\n\t\t\t? outer.width / scope.offsetWidth\n\t\t\t: 1;\n\treturn {\n\t\tx: (inner.left - outer.left) / scale - scope.clientLeft,\n\t\ty: (inner.top - outer.top) / scale - scope.clientTop,\n\t\twidth: outer.width / scale - scope.clientLeft * 2,\n\t\theight: outer.height / scale - scope.clientTop * 2,\n\t};\n}\n\nconst BACKGROUND = [\n\t\"backgroundColor\",\n\t\"backgroundImage\",\n\t\"backgroundSize\",\n\t\"backgroundPosition\",\n\t\"backgroundRepeat\",\n\t\"backgroundOrigin\",\n\t\"backgroundClip\",\n] as const;\n\n// The copy covers the backdrop rather than adding to it, so it starts from the\n// scope's own background: a translucent backdrop would otherwise draw twice.\nfunction underlay(copy: HTMLElement, scope: HTMLElement | null) {\n\tif (!scope) return;\n\tconst style = getComputedStyle(scope);\n\tfor (const name of BACKGROUND) copy.style[name] = style[name];\n}\n\nfunction idle(box: HTMLElement) {\n\tbox.style.width = \"\";\n\tbox.style.height = \"\";\n\tbox.style.filter = \"\";\n}\n\nexport function useLensPool({\n\tnested,\n\tenabled,\n\telement,\n\tbackdrop,\n\tmargin = 0,\n\tfeather = 0,\n\tdress,\n}: {\n\tnested: boolean;\n\tenabled: boolean;\n\telement: () => HTMLElement | null;\n\tbackdrop: () => HTMLElement | null;\n\tmargin?: number;\n\tfeather?: number;\n\tdress?: (lens: GlassLens) => void;\n}) {\n\tconst boxes = useRef<Array<HTMLDivElement | null>>([]);\n\tconst frosts = useRef<Array<HTMLDivElement | null>>([]);\n\tconst copies = useRef<Array<HTMLDivElement | null>>([]);\n\tconst taken = useRef(new Set<number>());\n\tconst listeners = useRef(new Set<() => void>());\n\tconst latest = useRef({ element, backdrop, margin, feather, dress });\n\tlatest.current = { element, backdrop, margin, feather, dress };\n\tconst [count, setCount] = useState(0);\n\n\tuseLayoutEffect(() => {\n\t\tif (enabled) setCount((current) => Math.max(current, 1));\n\t}, [enabled]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: waiting lenses retry whenever the pool grows\n\tuseLayoutEffect(() => {\n\t\tfor (const listener of listeners.current) listener();\n\t}, [count]);\n\n\tconst pool = useMemo<LensPool>(\n\t\t() => ({\n\t\t\tnested,\n\t\t\telement: () => latest.current.element(),\n\t\t\tbackdrop: () => latest.current.backdrop(),\n\t\t\tlease: () => {\n\t\t\t\tfor (let index = 0; index < boxes.current.length; index++) {\n\t\t\t\t\tconst box = boxes.current[index];\n\t\t\t\t\tconst frost = frosts.current[index];\n\t\t\t\t\tconst copy = copies.current[index];\n\t\t\t\t\tif (box && frost && copy && !taken.current.has(index)) {\n\t\t\t\t\t\ttaken.current.add(index);\n\t\t\t\t\t\tconst lens = {\n\t\t\t\t\t\t\tindex,\n\t\t\t\t\t\t\tbox,\n\t\t\t\t\t\t\tfrost,\n\t\t\t\t\t\t\tcopy,\n\t\t\t\t\t\t\tmargin: latest.current.margin,\n\t\t\t\t\t\t\tfeather: latest.current.feather,\n\t\t\t\t\t\t};\n\t\t\t\t\t\tunderlay(copy, latest.current.backdrop());\n\t\t\t\t\t\tlatest.current.dress?.(lens);\n\t\t\t\t\t\treturn lens;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tsetCount((current) => Math.max(current, taken.current.size + 1));\n\t\t\t\treturn null;\n\t\t\t},\n\t\t\trelease: (lens) => {\n\t\t\t\ttaken.current.delete(lens.index);\n\t\t\t\tidle(lens.box);\n\t\t\t},\n\t\t\tonChange: (listener) => {\n\t\t\t\tlisteners.current.add(listener);\n\t\t\t\treturn () => listeners.current.delete(listener);\n\t\t\t},\n\t\t}),\n\t\t[nested],\n\t);\n\n\tconst render = (content: ReactNode) =>\n\t\tArray.from({ length: count }, (_, index) => (\n\t\t\t<div\n\t\t\t\t// biome-ignore lint/suspicious/noArrayIndexKey: the pool only grows, so an index names one box for good\n\t\t\t\tkey={index}\n\t\t\t\taria-hidden=\"true\"\n\t\t\t\tclassName=\"glass-scope__lens\"\n\t\t\t\tref={(node) => {\n\t\t\t\t\tboxes.current[index] = node;\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\tclassName=\"glass-scope__frost\"\n\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\tfrosts.current[index] = node;\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"glass-scope__copy\"\n\t\t\t\t\t\tref={(node) => {\n\t\t\t\t\t\t\tcopies.current[index] = node;\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{content}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t));\n\n\treturn { pool, render };\n}\n\nexport type GlassScopeRefraction = \"content\" | \"backdrop\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\nconst SHARED_INPUTS = new Set([\n\t\"SourceGraphic\",\n\t\"SourceAlpha\",\n\t\"BackgroundImage\",\n\t\"BackgroundAlpha\",\n\t\"FillPaint\",\n\t\"StrokePaint\",\n]);\n\nconst REFERENCE_ATTRIBUTES = new Set([\"result\", \"in\", \"in2\"]);\n\ntype MergedLens = {\n\tsource: SVGFilterElement;\n\tclones: Element[];\n\toutput: string;\n\toutline: string;\n};\n\n// Alpha of a computed colour: rgba() or a `/ alpha` suffix.\nfunction alphaOf(color: string) {\n\tconst slash = color.lastIndexOf(\"/\");\n\tif (slash >= 0) return Number.parseFloat(color.slice(slash + 1)) || 0;\n\tconst parts = color.replace(/^[a-z]+\\(|\\)$/g, \"\").split(\",\");\n\treturn parts.length >= 4 ? Number.parseFloat(parts[3]) || 0 : 1;\n}\n\nfunction reference(key: string, name: string, value: string) {\n\treturn REFERENCE_ATTRIBUTES.has(name) && !SHARED_INPUTS.has(value)\n\t\t? `${key}-${value}`\n\t\t: value;\n}\n\n// Keeps a clone in step with its source, its results prefixed by lens.\nfunction follow(key: string, source: Element, clone: Element) {\n\tfor (const { name, value } of Array.from(source.attributes)) {\n\t\tconst next = reference(key, name, value);\n\t\tif (clone.getAttribute(name) !== next) clone.setAttribute(name, next);\n\t}\n\tfor (const { name } of Array.from(clone.attributes)) {\n\t\tif (!source.hasAttribute(name)) clone.removeAttribute(name);\n\t}\n\tconst sourceChildren = Array.from(source.children);\n\tconst cloneChildren = Array.from(clone.children);\n\tsourceChildren.forEach((child, index) => {\n\t\tconst twin = cloneChildren[index];\n\t\tif (twin) follow(key, child, twin);\n\t});\n}\n\n// A lens's primitives without the ending it uses on its own.\nfunction lensPrimitives(filter: SVGFilterElement) {\n\tconst children = Array.from(filter.children);\n\tconst output = filter.dataset.result;\n\tif (output) {\n\t\treturn {\n\t\t\tprimitives: children.filter(\n\t\t\t\t(child) => !child.hasAttribute(\"data-standalone\"),\n\t\t\t),\n\t\t\toutput,\n\t\t\toutline: filter.dataset.outline ?? \"\",\n\t\t};\n\t}\n\tconst last = children[children.length - 1];\n\tif (last && !last.hasAttribute(\"result\")) {\n\t\treturn {\n\t\t\tprimitives: children.slice(0, -1),\n\t\t\toutput: last.getAttribute(\"in\") ?? \"\",\n\t\t\toutline: \"\",\n\t\t};\n\t}\n\treturn {\n\t\tprimitives: children,\n\t\toutput: last?.getAttribute(\"result\") ?? \"\",\n\t\toutline: \"\",\n\t};\n}\n\nexport type GlassScopeProps = HTMLAttributes<HTMLDivElement> & {\n\tbackdrop?: ReactNode;\n\t// `content` bends the scope's own content, with one filter over the whole\n\t// scope. `backdrop` bends a lens-sized copy of `backdrop` and nothing else.\n\trefraction?: GlassScopeRefraction;\n\t// With `content`, how far past the scope's edge a lens still bends, in px.\n\tbleed?: number;\n\tref?: Ref<HTMLDivElement>;\n\tchildren?: ReactNode;\n};\n\nconst DEFAULT_BLEED = 40;\n\nexport function GlassScope({\n\tbackdrop,\n\trefraction = \"content\",\n\tbleed = DEFAULT_BLEED,\n\tclassName,\n\tref,\n\tchildren,\n\t...props\n}: GlassScopeProps) {\n\tconst rootRef = useRef<HTMLDivElement | null>(null);\n\tconst contentRef = useRef<HTMLDivElement | null>(null);\n\tconst sharedId = `glass-scope-${useId().replaceAll(\":\", \"\")}`;\n\tconst inPlace = refraction === \"content\";\n\tconst copied = backdrop !== undefined && backdrop !== null;\n\tconst { pool, render } = useLensPool({\n\t\tnested: false,\n\t\tenabled: copied && !inPlace,\n\t\telement: () => rootRef.current,\n\t\tbackdrop: () => rootRef.current,\n\t});\n\n\t// One filter for every lens: two url() filters on one element leave one\n\t// unrendered in Chromium and WebKit, and WebKit drops a filter around a filtered layer.\n\tconst sharedRef = useRef<SVGFilterElement | null>(null);\n\tconst merged = useRef(new Map<string, MergedLens>());\n\tconst version = useRef(0);\n\tconst inPlacePool = useMemo<LensPool>(\n\t\t() => ({\n\t\t\tnested: false,\n\t\t\tinPlace: true,\n\t\t\telement: () => contentRef.current,\n\t\t\tbackdrop: () => contentRef.current,\n\t\t\tlease: () => null,\n\t\t\trelease: () => {},\n\t\t\tonChange: () => () => {},\n\t\t\tapplyFilter: (key, filter) => {\n\t\t\t\tconst shared = sharedRef.current;\n\t\t\t\tconst content = contentRef.current;\n\t\t\t\tif (!shared || !content) return;\n\t\t\t\tconst lenses = merged.current;\n\t\t\t\tif (filter === null) {\n\t\t\t\t\tconst lens = lenses.get(key);\n\t\t\t\t\tif (!lens) return;\n\t\t\t\t\tlenses.delete(key);\n\t\t\t\t\tfor (const clone of lens.clones) clone.remove();\n\t\t\t\t} else {\n\t\t\t\t\tconst { primitives, output, outline } = lensPrimitives(filter);\n\t\t\t\t\tlet lens = lenses.get(key);\n\t\t\t\t\tif (!lens || lens.source !== filter) {\n\t\t\t\t\t\tif (lens) for (const clone of lens.clones) clone.remove();\n\t\t\t\t\t\tlens = {\n\t\t\t\t\t\t\tsource: filter,\n\t\t\t\t\t\t\tclones: primitives.map(\n\t\t\t\t\t\t\t\t(primitive) => primitive.cloneNode(true) as Element,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\toutput: \"\",\n\t\t\t\t\t\t\toutline: \"\",\n\t\t\t\t\t\t};\n\t\t\t\t\t\tlenses.set(key, lens);\n\t\t\t\t\t}\n\t\t\t\t\tlens.output = reference(key, \"in\", output);\n\t\t\t\t\tlens.outline = outline ? reference(key, \"in\", outline) : \"\";\n\t\t\t\t\tprimitives.forEach((primitive, index) => {\n\t\t\t\t\t\tconst clone = lens.clones[index];\n\t\t\t\t\t\tif (clone) follow(key, primitive, clone);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (lenses.size === 0) {\n\t\t\t\t\tcontent.style.filter = \"\";\n\t\t\t\t\tshared.replaceChildren();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// A see-through layer gets the outlines cut out first, or translucent\n\t\t\t\t// pixels under a lens draw twice. One merged cut: every pass costs in Safari.\n\t\t\t\tconst make = (name: string) =>\n\t\t\t\t\tshared.ownerDocument.createElementNS(SVG_NS, name);\n\t\t\t\tconst node = (input: string) => {\n\t\t\t\t\tconst element = make(\"feMergeNode\");\n\t\t\t\t\telement.setAttribute(\"in\", input);\n\t\t\t\t\treturn element;\n\t\t\t\t};\n\t\t\t\tconst merge = make(\"feMerge\");\n\t\t\t\tconst nodes: Element[] = [];\n\t\t\t\tconst outlines: string[] = [];\n\t\t\t\tfor (const lens of lenses.values()) {\n\t\t\t\t\tnodes.push(...lens.clones);\n\t\t\t\t\tif (lens.outline) outlines.push(lens.outline);\n\t\t\t\t\tmerge.append(node(lens.output));\n\t\t\t\t}\n\t\t\t\tconst seeThrough =\n\t\t\t\t\talphaOf(getComputedStyle(content).backgroundColor) < 1;\n\t\t\t\tlet rest = \"SourceGraphic\";\n\t\t\t\tif (seeThrough && outlines.length) {\n\t\t\t\t\tconst all = make(\"feMerge\");\n\t\t\t\t\tfor (const outline of outlines) all.append(node(outline));\n\t\t\t\t\tall.setAttribute(\"result\", \"outlines\");\n\t\t\t\t\tconst hole = make(\"feComposite\");\n\t\t\t\t\thole.setAttribute(\"in\", \"SourceGraphic\");\n\t\t\t\t\thole.setAttribute(\"in2\", \"outlines\");\n\t\t\t\t\thole.setAttribute(\"operator\", \"out\");\n\t\t\t\t\thole.setAttribute(\"result\", \"rest\");\n\t\t\t\t\tnodes.push(all, hole);\n\t\t\t\t\trest = \"rest\";\n\t\t\t\t}\n\t\t\t\tmerge.prepend(node(rest));\n\t\t\t\tshared.replaceChildren(...nodes, merge);\n\t\t\t\t// Safari caches filter output by id, so every update takes a fresh one.\n\t\t\t\tversion.current += 1;\n\t\t\t\tshared.id = `${sharedId}-v${version.current}`;\n\t\t\t\tcontent.style.filter = `url(#${shared.id})`;\n\t\t\t},\n\t\t}),\n\t\t[sharedId],\n\t);\n\n\treturn (\n\t\t<PoolContext.Provider value={inPlace ? inPlacePool : copied ? pool : null}>\n\t\t\t<BackdropContext.Provider value={copied && !inPlace ? backdrop : null}>\n\t\t\t\t<div\n\t\t\t\t\t{...props}\n\t\t\t\t\tref={(element) => {\n\t\t\t\t\t\trootRef.current = element;\n\t\t\t\t\t\tif (typeof ref === \"function\") ref(element);\n\t\t\t\t\t\telse if (ref) ref.current = element;\n\t\t\t\t\t}}\n\t\t\t\t\tclassName={[\n\t\t\t\t\t\t\"glass-scope\",\n\t\t\t\t\t\tinPlace ? \"glass-scope--in-place\" : undefined,\n\t\t\t\t\t\tclassName,\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\" \")}\n\t\t\t\t>\n\t\t\t\t\t{inPlace ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<svg className=\"glass-scope__defs\" aria-hidden=\"true\">\n\t\t\t\t\t\t\t\t<filter\n\t\t\t\t\t\t\t\t\tref={sharedRef}\n\t\t\t\t\t\t\t\t\tid={sharedId}\n\t\t\t\t\t\t\t\t\tfilterUnits=\"objectBoundingBox\"\n\t\t\t\t\t\t\t\t\tprimitiveUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t\tcolorInterpolationFilters=\"sRGB\"\n\t\t\t\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\t\t\t\twidth=\"1\"\n\t\t\t\t\t\t\t\t\theight=\"1\"\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tref={contentRef}\n\t\t\t\t\t\t\t\tclassName=\"glass-scope__content\"\n\t\t\t\t\t\t\t\tstyle={{ margin: -bleed, padding: bleed }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<div className=\"glass-scope__inner\">\n\t\t\t\t\t\t\t\t\t{copied ? (\n\t\t\t\t\t\t\t\t\t\t<div aria-hidden=\"true\" className=\"glass-scope__backdrop\">\n\t\t\t\t\t\t\t\t\t\t\t{backdrop}\n\t\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{copied ? (\n\t\t\t\t\t\t\t\t<div aria-hidden=\"true\" className=\"glass-scope__backdrop\">\n\t\t\t\t\t\t\t\t\t{backdrop}\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t{copied ? render(backdrop) : null}\n\t\t\t\t\t\t\t{children}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</BackdropContext.Provider>\n\t\t</PoolContext.Provider>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/scope.tsx"
    },
    {
      "path": "src/glass/glass.css",
      "content": ".glass {\n\tposition: relative;\n\tdisplay: block;\n\toverflow: visible;\n}\n\n:where(.glass-scope) {\n\ttransform: translate(0);\n}\n\n.glass-scope__backdrop,\n.glass-scope__lens {\n\tposition: absolute;\n\tz-index: -1;\n\tpointer-events: none;\n}\n\n.glass-scope__backdrop {\n\tinset: 0;\n}\n\n/* The filtered layer of a content scope, padded by the bleed. WebKit measures\n   a filter from the nearest transformed element. */\n.glass-scope__content {\n\tposition: relative;\n\tbox-sizing: content-box;\n\theight: 100%;\n\ttransform: translate(0);\n\t/* Inherited so a recolour follows at once; painted inside the bleed only. */\n\tbackground: inherit;\n\tbackground-clip: content-box;\n\tbackground-origin: content-box;\n\tpointer-events: none;\n}\n\n/* Or the layer's negative margin collapses through the scope. */\n.glass-scope--in-place {\n\tcontain: layout;\n}\n\n/* The scope's own box, isolated so the backdrop's z-index -1 stays above\n   the layer's background. */\n.glass-scope__inner {\n\tposition: relative;\n\theight: 100%;\n\tisolation: isolate;\n\tpointer-events: auto;\n}\n\n.glass-scope__defs {\n\tposition: absolute;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n}\n\n/* Safari paints a partial repaint of a filtered layer black, so the lens\n   keeps a layer of its own. WebKit measures a filter from the nearest\n   transformed element, so it carries an identity transform too. */\n.glass-scope__lens {\n\ttop: 0;\n\tleft: 0;\n\twidth: 0;\n\theight: 0;\n\toverflow: hidden;\n\ttransform: translate(0);\n\twill-change: transform;\n}\n\n.glass-scope__frost,\n.glass-scope__copy {\n\tposition: absolute;\n}\n\n.glass-scope__frost {\n\tinset: 0;\n}\n\n.glass__target {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpointer-events: none;\n\ttransform-origin: left top;\n\twill-change: filter, clip-path;\n}\n\n.glass__target-inner {\n\ttransform-origin: left top;\n}\n\n.glass__backdrop {\n\tposition: absolute;\n\tinset: 0;\n\tpointer-events: none;\n}\n\n.glass__defs {\n\tposition: absolute;\n\tinset: 0;\n\twidth: 100%;\n\theight: 100%;\n\toverflow: visible;\n\tpointer-events: none;\n}\n\n.glass__rim {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tbox-sizing: border-box;\n\tpointer-events: none;\n\twill-change: transform, opacity;\n}\n\n.glass__tint {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\twill-change: transform, opacity;\n}\n\n.glass__frost {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpointer-events: none;\n\twill-change: transform, backdrop-filter;\n}\n\n.glass__face {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpointer-events: none;\n}\n\n.glass__light {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpointer-events: none;\n\tbackground-repeat: no-repeat;\n\tbackground-size: 100% 100%;\n\twill-change: transform;\n}\n\n/* Overlays in a filtered layer must not be composited. */\n.glass[data-flat] .glass__rim,\n.glass[data-flat] .glass__tint,\n.glass[data-flat] .glass__frost,\n.glass[data-flat] .glass__light {\n\twill-change: auto;\n}\n\n.glass-theme {\n\tdisplay: contents;\n}\n",
      "type": "registry:file",
      "target": "@components/liquikit/glass/glass.css"
    },
    {
      "path": "src/glass/motion.ts",
      "content": "\"use client\";\n\nimport { type MotionValue, motionValue } from \"motion/react\";\nimport { useLayoutEffect, useState } from \"react\";\n\nexport const TRAVEL = {\n\ttype: \"spring\",\n\tstiffness: 320,\n\tdamping: 30,\n\tmass: 1,\n} as const;\n\nexport const OPEN = {\n\ttype: \"spring\",\n\tstiffness: 520,\n\tdamping: 34,\n\tmass: 0.7,\n} as const;\n\nexport const CLOSE = {\n\ttype: \"spring\",\n\tstiffness: 260,\n\tdamping: 30,\n\tmass: 1,\n} as const;\n\nexport const DWELL = 260;\n\nexport const DEFAULT_LIQUID = 0.6;\n\nexport const DRAG_SLOP = 3;\n\nexport const PRESS_SCALE = 1.4;\n\nexport function rubberBand(distance: number, limit: number) {\n\tif (distance <= 0 || limit <= 0) return 0;\n\treturn (1 - 1 / (distance / limit + 1)) * limit;\n}\n\nexport function useDerived<T>(\n\tinputs: readonly MotionValue<number>[],\n\tcompute: (values: number[]) => T,\n): MotionValue<T> {\n\tconst [value] = useState(() =>\n\t\tmotionValue(compute(inputs.map((input) => input.get()))),\n\t);\n\tvalue.set(compute(inputs.map((input) => input.get())));\n\tuseLayoutEffect(() => {\n\t\tconst update = () => value.set(compute(inputs.map((input) => input.get())));\n\t\tupdate();\n\t\tconst stops = inputs.map((input) => input.on(\"change\", update));\n\t\treturn () => {\n\t\t\tfor (const stop of stops) stop();\n\t\t};\n\t});\n\treturn value;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/motion.ts"
    },
    {
      "path": "src/glass/presets.ts",
      "content": "\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { LensProfile } from \"./optics\";\n\nexport type GlassTheme = \"light\" | \"dark\";\n\nexport const defaultLens: LensProfile = {\n\tmapSize: 1024,\n\tior: 1.52,\n\tdispersion: 0.04,\n\tthickness: 8.5,\n\tbase: 0,\n\tbevel: 4,\n\tbevelProfile: 2,\n\tmaxSlope: 6,\n\tmagnification: 1.1,\n\tdomeLength: 1,\n\tsoftness: 1,\n\tenvironment: 1.4,\n\trimLight: 0.55,\n\trimShadow: 0.12,\n\troughness: 0.28,\n\tspecularStrength: 0.8,\n\tbackLight: 0.45,\n\tlightAngle: 115,\n\tlightElevation: 30,\n\tshadingStrength: 0.9,\n\topenTint: 0,\n\tedgeShadow: \"0 2px 6px rgba(0, 0, 0, 0.16)\",\n\tedgeInsetShadow: \"none\",\n\trestEdgeShadow:\n\t\t\"0 1.5px 4px rgba(0, 0, 0, 0.14), 0 0 1px rgba(0, 0, 0, 0.06)\",\n};\n\nexport const switchLens: LensProfile = {\n\t...defaultLens,\n\tthickness: 14,\n\tbevel: 8,\n\tbevelProfile: 3,\n\tdispersion: 0.2,\n\tmagnification: 0.78,\n};\n\nexport const sliderLens: LensProfile = {\n\t...defaultLens,\n\tthickness: 6,\n\tbase: 32,\n\tbevel: 10,\n\tbevelProfile: 4,\n\tmaxSlope: 4,\n\tmagnification: 1,\n\tdispersion: 0,\n\topenTint: 0.1,\n\tedgeShadow: \"0 3px 14px rgba(0, 0, 0, 0.1)\",\n\trestEdgeShadow: \"0 1.333px 5.333px rgba(0, 0, 0, 0.18)\",\n};\n\nexport const toggleLens: LensProfile = {\n\t...defaultLens,\n\tthickness: 6.4,\n\tbase: 14,\n\tbevel: 10.7,\n\tbevelProfile: 4,\n\tmaxSlope: 4,\n\tmagnification: 1,\n\tdispersion: 0,\n\topenTint: 0.1,\n\tedgeShadow: \"0 3px 14px rgba(0, 0, 0, 0.1)\",\n\trestEdgeShadow:\n\t\t\"0 3px 8px rgba(0, 0, 0, 0.12), 0 1px 1px rgba(0, 0, 0, 0.04)\",\n};\n\nexport const paneLens: LensProfile = {\n\t...defaultLens,\n\tthickness: 5,\n\tbase: 8,\n\tbevel: 7,\n\tbevelProfile: 4,\n\tmaxSlope: 4,\n\tmagnification: 1,\n\tdispersion: 0,\n\trimLight: 0.8,\n\tedgeShadow: \"0 8px 24px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08)\",\n\tedgeInsetShadow: \"none\",\n\trestEdgeShadow: \"none\",\n};\n\nexport const darkLens: Partial<LensProfile> = {\n\tenvironment: 1.2,\n\tspecularStrength: 1.1,\n\tshadingStrength: 1.1,\n\tedgeShadow: \"0 2px 6px rgba(0, 0, 0, 0.36)\",\n\tedgeInsetShadow: \"none\",\n};\n\nexport function useLens(\n\ttheme: GlassTheme = \"light\",\n\toverrides?: Partial<LensProfile>,\n\tbase: LensProfile = defaultLens,\n): LensProfile {\n\treturn useMemo<LensProfile>(\n\t\t() => ({\n\t\t\t...base,\n\t\t\t...(theme === \"dark\" ? darkLens : undefined),\n\t\t\t...overrides,\n\t\t}),\n\t\t[base, theme, overrides],\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/presets.ts"
    },
    {
      "path": "src/glass/theme.tsx",
      "content": "\"use client\";\n\nimport { createContext, type ReactNode, useContext } from \"react\";\nimport type { GlassTheme } from \"./presets\";\nimport \"./glass.css\";\n\nconst GlassThemeContext = createContext<GlassTheme>(\"light\");\n\nexport function useGlassTheme(theme?: GlassTheme): GlassTheme {\n\tconst inherited = useContext(GlassThemeContext);\n\treturn theme ?? inherited;\n}\n\nexport type GlassThemeProviderProps = {\n\ttheme: GlassTheme;\n\tchildren?: ReactNode;\n};\n\nexport function GlassThemeProvider({\n\ttheme,\n\tchildren,\n}: GlassThemeProviderProps) {\n\treturn (\n\t\t<GlassThemeContext.Provider value={theme}>\n\t\t\t<div className=\"glass-theme\" data-glass-theme={theme}>\n\t\t\t\t{children}\n\t\t\t</div>\n\t\t</GlassThemeContext.Provider>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/theme.tsx"
    },
    {
      "path": "src/glass/use-squish.ts",
      "content": "\"use client\";\n\nimport { type MotionValue, useMotionValue } from \"motion/react\";\nimport { useCallback, useEffect, useRef } from \"react\";\n\nconst MAX_SQUASH = 0.3;\nconst MAX_WOBBLE = 0.08;\nexport const MAX_STRETCH = 1 / (1 - MAX_SQUASH - MAX_WOBBLE);\nexport const MAX_SPREAD = 1 + MAX_WOBBLE;\nconst KNEE_SPEED = 900;\nconst HELD_SQUASH = 0.16;\nconst STIFFNESS = 240;\nconst DAMPING = 17;\n\nconst WOBBLE_FREQUENCY = 3.5;\nconst WOBBLE_DAMPING = 0.4;\nconst WOBBLE_KICK = 2.2;\nconst WOBBLE_FROM_STOP = 0.5;\n\nconst LAG_PIXELS = 3;\nconst LAG_KNEE_SPEED = 900;\nconst LAG_FREQUENCY = 4;\nconst LAG_DAMPING = 0.5;\nconst SUBSTEPS = 4;\n\nexport function useSquish(\n\tposition: MotionValue<number>,\n\tenabled = true,\n\tliquid = 0,\n\tspeedSquash = 1,\n) {\n\tconst squish = useMotionValue(0);\n\tconst lag = useMotionValue(0);\n\tconst held = useRef(0);\n\tconst start = useRef<() => void>(() => {});\n\tconst rebase = useRef<() => void>(() => {});\n\tconst pending = useRef(0);\n\tconst amount = enabled ? Math.max(0, liquid) : 0;\n\n\tuseEffect(() => {\n\t\tif (!enabled) return;\n\t\tlet frame = 0;\n\t\tlet offset = 0;\n\t\tlet velocity = 0;\n\t\tlet wobble = 0;\n\t\tlet wobbleVelocity = 0;\n\t\tlet trail = 0;\n\t\tlet trailVelocity = 0;\n\t\tlet last = 0;\n\t\tlet previous = position.get();\n\t\tlet running = false;\n\t\tconst wobbleRate = 2 * Math.PI * WOBBLE_FREQUENCY;\n\t\tconst lagRate = 2 * Math.PI * LAG_FREQUENCY;\n\n\t\tconst step = (now: number) => {\n\t\t\tconst elapsed = (now - last) / 1000;\n\t\t\tconst delta = Math.min(elapsed, 0.033);\n\t\t\tlast = now;\n\n\t\t\tconst current = position.get();\n\t\t\tconst speed =\n\t\t\t\t(current - previous) / Math.min(Math.max(elapsed, 0.008), 0.03);\n\t\t\tprevious = current;\n\t\t\tconst magnitude = Math.abs(speed);\n\n\t\t\tconst fromSpeed =\n\t\t\t\tMAX_SQUASH * speedSquash * (1 - Math.exp(-magnitude / KNEE_SPEED));\n\t\t\tconst target =\n\t\t\t\theld.current > 0 ? Math.max(fromSpeed, held.current) : fromSpeed;\n\n\t\t\tconst acceleration = -STIFFNESS * (offset - target) - DAMPING * velocity;\n\t\t\tvelocity += acceleration * delta;\n\t\t\toffset += velocity * delta;\n\n\t\t\tif (Math.abs(offset - target) < 2e-3 && Math.abs(velocity) < 2e-2) {\n\t\t\t\toffset = target;\n\t\t\t\tvelocity = 0;\n\t\t\t}\n\n\t\t\tif (amount > 0) {\n\t\t\t\twobbleVelocity += pending.current;\n\t\t\t\tpending.current = 0;\n\t\t\t\tconst trailTarget =\n\t\t\t\t\t-LAG_PIXELS * amount * Math.tanh(speed / LAG_KNEE_SPEED);\n\t\t\t\tconst collapsing = offset > 0 ? velocity < 0 : velocity > 0;\n\t\t\t\tconst thrown = collapsing ? WOBBLE_FROM_STOP * amount * velocity : 0;\n\t\t\t\tconst slice = delta / SUBSTEPS;\n\t\t\t\tfor (let index = 0; index < SUBSTEPS; index += 1) {\n\t\t\t\t\twobbleVelocity +=\n\t\t\t\t\t\t(-wobbleRate * wobbleRate * wobble -\n\t\t\t\t\t\t\t2 * WOBBLE_DAMPING * wobbleRate * wobbleVelocity +\n\t\t\t\t\t\t\tthrown * wobbleRate) *\n\t\t\t\t\t\tslice;\n\t\t\t\t\twobble += wobbleVelocity * slice;\n\t\t\t\t\ttrailVelocity +=\n\t\t\t\t\t\t(-lagRate * lagRate * (trail - trailTarget) -\n\t\t\t\t\t\t\t2 * LAG_DAMPING * lagRate * trailVelocity) *\n\t\t\t\t\t\tslice;\n\t\t\t\t\ttrail += trailVelocity * slice;\n\t\t\t\t}\n\t\t\t\twobble = Math.max(-MAX_WOBBLE, Math.min(MAX_WOBBLE, wobble));\n\t\t\t\tif (Math.abs(wobble) < 5e-4 && Math.abs(wobbleVelocity) < 5e-3) {\n\t\t\t\t\twobble = 0;\n\t\t\t\t\twobbleVelocity = 0;\n\t\t\t\t}\n\t\t\t\tif (\n\t\t\t\t\tMath.abs(trail - trailTarget) < 0.02 &&\n\t\t\t\t\tMath.abs(trailVelocity) < 0.2\n\t\t\t\t) {\n\t\t\t\t\ttrail = trailTarget;\n\t\t\t\t\ttrailVelocity = 0;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst shaped =\n\t\t\t\tspeedSquash < 0 ? Math.min(0, offset) : Math.max(0, offset);\n\t\t\tsquish.set(shaped + wobble);\n\t\t\tlag.set(Math.round(trail * 100) / 100);\n\n\t\t\tconst settled =\n\t\t\t\tMath.abs(offset) < 5e-4 &&\n\t\t\t\tMath.abs(velocity) < 5e-3 &&\n\t\t\t\tmagnitude < 5e-3 &&\n\t\t\t\theld.current === 0 &&\n\t\t\t\twobble === 0 &&\n\t\t\t\tpending.current === 0 &&\n\t\t\t\tMath.abs(trail) < 0.01 &&\n\t\t\t\ttrailVelocity === 0;\n\t\t\tif (settled) {\n\t\t\t\trunning = false;\n\t\t\t\tsquish.set(0);\n\t\t\t\tlag.set(0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tframe = requestAnimationFrame(step);\n\t\t};\n\n\t\tstart.current = () => {\n\t\t\tif (running) return;\n\t\t\trunning = true;\n\t\t\tlast = performance.now();\n\t\t\tprevious = position.get();\n\t\t\tframe = requestAnimationFrame(step);\n\t\t};\n\n\t\trebase.current = () => {\n\t\t\tprevious = position.get();\n\t\t};\n\n\t\tconst unsubscribe = position.on(\"change\", () => start.current());\n\t\treturn () => {\n\t\t\tunsubscribe();\n\t\t\tcancelAnimationFrame(frame);\n\t\t\tstart.current = () => {};\n\t\t\trebase.current = () => {};\n\t\t};\n\t}, [amount, enabled, lag, position, speedSquash, squish]);\n\n\t// A move that was a jump, such as a track resizing under its handle, is not\n\t// speed: the next frame measures from where the jump landed.\n\tconst jumped = useCallback(() => rebase.current(), []);\n\n\tconst setHeld = useCallback((value: boolean) => {\n\t\theld.current = value ? HELD_SQUASH : 0;\n\t\tif (value) start.current();\n\t}, []);\n\n\tconst kick = useCallback(\n\t\t(direction: 1 | -1) => {\n\t\t\tif (amount <= 0) return;\n\t\t\tpending.current += direction * WOBBLE_KICK * amount;\n\t\t\tstart.current();\n\t\t},\n\t\t[amount],\n\t);\n\n\treturn { squish, lag: amount > 0 ? lag : undefined, setHeld, kick, jumped };\n}\n\nexport function squashed(base: number, amount: number, across: boolean) {\n\tconst factor = 1 - Math.min(0.6, Math.max(-MAX_WOBBLE, amount));\n\treturn across ? base * factor : base / factor;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/use-squish.ts"
    },
    {
      "path": "src/glass/optics.ts",
      "content": "export type LensShape = {\n\thalfWidth: number;\n\thalfHeight: number;\n\tborderRadius: number;\n};\n\nexport type LensMap = {\n\tid: number;\n\turl: string;\n\tlight: string;\n\tslices?: LensSlices;\n\tdisplacement: number;\n\tchroma: [number, number, number];\n\treach: number;\n\trimReach: number;\n\tshadingStrength: number;\n};\n\nexport type LensSlices = {\n\twidth: number;\n\theight: number;\n\tcut?: LensCut;\n\tmap: string[];\n\tlight: string[];\n};\n\nexport type LensCut = {\n\taxis: \"x\" | \"y\";\n\tstart: number;\n\tend: number;\n};\n\nexport type LensProfile = {\n\tmapSize: number;\n\tior: number;\n\tdispersion: number;\n\tthickness: number;\n\tbase: number;\n\tbevel: number;\n\tbevelProfile: number;\n\tmaxSlope: number;\n\tmagnification: number;\n\tdomeLength: number;\n\tsoftness: number;\n\tenvironment: number;\n\trimLight: number;\n\trimShadow: number;\n\troughness: number;\n\tspecularStrength: number;\n\tbackLight: number;\n\tlightAngle: number;\n\tlightElevation: number;\n\tshadingStrength: number;\n\topenTint: number;\n\tedgeShadow: string;\n\tedgeInsetShadow: string;\n\trestEdgeShadow: string;\n};\n\nconst PROFILE_SAMPLES = 512;\n\nconst DOME_HANDOVER = 0.5;\n\nconst SHAPE_STEP = 0.5;\n\nconst MIN_DENSITY = 2;\nconst MAX_DENSITY = 8;\n\nexport function snapShape(shape: LensShape): LensShape {\n\tconst snap = (value: number) => Math.round(value / SHAPE_STEP) * SHAPE_STEP;\n\treturn {\n\t\thalfWidth: snap(shape.halfWidth),\n\t\thalfHeight: snap(shape.halfHeight),\n\t\tborderRadius: snap(shape.borderRadius),\n\t};\n}\n\nconst decodedMaps = new Set<string>();\nconst decodingMaps = new Map<string, Promise<void>>();\n\nexport function isMapDecoded(url: string) {\n\treturn decodedMaps.has(url);\n}\n\nexport function decodeMap(url: string): Promise<void> {\n\tif (decodedMaps.has(url)) return Promise.resolve();\n\tconst pending = decodingMaps.get(url);\n\tif (pending) return pending;\n\n\tconst task = new Promise<void>((resolve) => {\n\t\tif (typeof Image === \"undefined\") {\n\t\t\tresolve();\n\t\t\treturn;\n\t\t}\n\t\tconst image = new Image();\n\t\tconst settle = () => {\n\t\t\tdecodedMaps.add(url);\n\t\t\tdecodingMaps.delete(url);\n\t\t\tresolve();\n\t\t};\n\t\timage.src = url;\n\t\tif (typeof image.decode === \"function\") {\n\t\t\timage.decode().then(settle, settle);\n\t\t} else {\n\t\t\timage.onload = settle;\n\t\t\timage.onerror = settle;\n\t\t}\n\t});\n\tdecodingMaps.set(url, task);\n\treturn task;\n}\n\nfunction clamp(value: number, low: number, high: number) {\n\treturn value < low ? low : value > high ? high : value;\n}\n\nfunction toByte(value: number) {\n\tconst rounded = Math.round(value);\n\treturn rounded < 0 ? 0 : rounded > 255 ? 255 : rounded;\n}\n\nfunction surface(\n\tinward: number,\n\tthickness: number,\n\tbevel: number,\n\tshape: number,\n\tmaxSlope: number,\n\tbase: number,\n) {\n\tif (inward >= 1) return { height: base + thickness, slope: 0 };\n\tconst outward = 1 - inward;\n\tconst raised = 1 - outward ** shape;\n\tconst height = base + thickness * raised ** (1 / shape);\n\tconst rise =\n\t\traised > 1e-6\n\t\t\t? thickness * outward ** (shape - 1) * raised ** (1 / shape - 1)\n\t\t\t: thickness * 1e6;\n\treturn { height, slope: Math.min(rise / bevel, maxSlope) };\n}\n\ntype Profile = {\n\tmagnitude: Float32Array;\n\ttangent: Float32Array;\n\tupward: Float32Array;\n\tfresnel: Float32Array;\n\tpeak: number;\n};\n\nfunction buildProfile(profile: LensProfile, bevel: number): Profile {\n\tconst magnitude = new Float32Array(PROFILE_SAMPLES);\n\tconst tangent = new Float32Array(PROFILE_SAMPLES);\n\tconst upward = new Float32Array(PROFILE_SAMPLES);\n\tconst fresnel = new Float32Array(PROFILE_SAMPLES);\n\tconst eta = 1 / profile.ior;\n\tconst f0 = ((profile.ior - 1) / (profile.ior + 1)) ** 2;\n\tlet peak = 0;\n\n\tfor (let index = 0; index < PROFILE_SAMPLES; index += 1) {\n\t\tconst inward = index / (PROFILE_SAMPLES - 1);\n\t\tconst { height, slope } = surface(\n\t\t\tinward,\n\t\t\tprofile.thickness,\n\t\t\tbevel,\n\t\t\tprofile.bevelProfile,\n\t\t\tprofile.maxSlope,\n\t\t\tprofile.base,\n\t\t);\n\t\tconst length = Math.hypot(slope, 1);\n\t\tconst normalZ = 1 / length;\n\t\tconst normalXY = slope / length;\n\n\t\tlet reach = 0;\n\t\tconst k = 1 - eta * eta * (1 - normalZ * normalZ);\n\t\tif (k >= 0) {\n\t\t\tconst bend = eta * normalZ - Math.sqrt(k);\n\t\t\tconst downward = -eta + bend * normalZ;\n\t\t\tif (downward < 0) reach = (bend * normalXY * height) / -downward;\n\t\t}\n\n\t\tmagnitude[index] = reach;\n\t\ttangent[index] = normalXY;\n\t\tupward[index] = normalZ;\n\t\tfresnel[index] = (1 - f0) * (1 - normalZ) ** 5;\n\t\tconst size = Math.abs(reach);\n\t\tif (size > peak) peak = size;\n\t}\n\n\treturn { magnitude, tangent, upward, fresnel, peak };\n}\n\nlet sharedCanvas: HTMLCanvasElement | undefined;\n\nconst mapCache = new Map<string, LensMap>();\nconst MAP_CACHE_LIMIT = 24;\nlet lastMapId = 0;\n\nlet encodeCanvas: HTMLCanvasElement | undefined;\n\nfunction encodeImage(image: ImageData) {\n\tencodeCanvas ??= document.createElement(\"canvas\");\n\tencodeCanvas.width = image.width;\n\tencodeCanvas.height = image.height;\n\tencodeCanvas\n\t\t.getContext(\"2d\", { willReadFrequently: true })\n\t\t?.putImageData(image, 0, 0);\n\treturn encodeCanvas.toDataURL(\"image/png\");\n}\n\nfunction cornerReach(reach: number, step: number) {\n\treturn Math.ceil(reach / step - 0.5) + 1;\n}\n\nfunction cropImage(\n\timage: ImageData,\n\tx0: number,\n\tx1: number,\n\ty0: number,\n\ty1: number,\n) {\n\tconst piece = new ImageData(x1 - x0, y1 - y0);\n\tfor (let y = y0; y < y1; y += 1) {\n\t\tconst from = (y * image.width + x0) * 4;\n\t\tpiece.data.set(\n\t\t\timage.data.subarray(from, from + (x1 - x0) * 4),\n\t\t\t(y - y0) * piece.width * 4,\n\t\t);\n\t}\n\treturn encodeImage(piece);\n}\n\nfunction planCut(\n\twidth: number,\n\theight: number,\n\treach: { x: number; y: number },\n) {\n\tconst axis = width >= height ? \"x\" : \"y\";\n\tconst length = axis === \"x\" ? width : height;\n\tconst ends = axis === \"x\" ? reach.x : reach.y;\n\treturn ends * 2 < length\n\t\t? ({ axis, start: ends, end: ends } satisfies LensCut)\n\t\t: undefined;\n}\n\nfunction beyondStretch(\n\tcut: LensCut | undefined,\n\trow: number,\n\tcolumn: number,\n\twidth: number,\n\theight: number,\n) {\n\tif (!cut) return false;\n\treturn cut.axis === \"x\"\n\t\t? column > cut.start && column < width - cut.end\n\t\t: row > cut.start && row < height - cut.end;\n}\n\nfunction slicePieces(image: ImageData, cut: LensCut) {\n\tconst { width, height } = image;\n\tconst length = cut.axis === \"x\" ? width : height;\n\treturn [\n\t\t[0, cut.start],\n\t\t[cut.start, cut.start + 1],\n\t\t[length - cut.end, length],\n\t].map(([from, to]) =>\n\t\tcut.axis === \"x\"\n\t\t\t? cropImage(image, from, to, 0, height)\n\t\t\t: cropImage(image, 0, width, from, to),\n\t);\n}\n\nfunction unslice(image: ImageData, cut: LensCut) {\n\tconst { width, height, data } = image;\n\tconst whole = new ImageData(new Uint8ClampedArray(data), width, height);\n\tfor (let row = 0; row < height; row += 1) {\n\t\tfor (let column = 0; column < width; column += 1) {\n\t\t\tif (!beyondStretch(cut, row, column, width, height)) continue;\n\t\t\tconst from =\n\t\t\t\t(cut.axis === \"x\"\n\t\t\t\t\t? row * width + cut.start\n\t\t\t\t\t: cut.start * width + column) * 4;\n\t\t\twhole.data.copyWithin((row * width + column) * 4, from, from + 4);\n\t\t}\n\t}\n\treturn whole;\n}\n\nexport function profileKey(profile: LensProfile) {\n\treturn [\n\t\tprofile.ior,\n\t\tprofile.dispersion,\n\t\tprofile.thickness,\n\t\tprofile.base,\n\t\tprofile.bevel,\n\t\tprofile.bevelProfile,\n\t\tprofile.maxSlope,\n\t\tprofile.magnification,\n\t\tprofile.domeLength,\n\t\tprofile.environment,\n\t\tprofile.rimLight,\n\t\tprofile.rimShadow,\n\t\tprofile.roughness,\n\t\tprofile.specularStrength,\n\t\tprofile.backLight,\n\t\tprofile.lightAngle,\n\t\tprofile.lightElevation,\n\t].join(\":\");\n}\n\nfunction cacheKey(\n\tshape: LensShape,\n\tprofile: LensProfile,\n\twidth: number,\n\theight: number,\n) {\n\treturn [\n\t\tshape.halfWidth,\n\t\tshape.halfHeight,\n\t\tshape.borderRadius,\n\t\twidth,\n\t\theight,\n\t\tprofileKey(profile),\n\t].join(\":\");\n}\n\nfunction resolutionFor(shape: LensShape, ceiling: number, scale: number) {\n\tconst width = shape.halfWidth * 2;\n\tconst height = shape.halfHeight * 2;\n\tlet density = clamp(scale, MIN_DENSITY, MAX_DENSITY);\n\tdensity = Math.min(density, ceiling / Math.max(width, height));\n\treturn {\n\t\twidth: Math.max(4, Math.round(width * density)),\n\t\theight: Math.max(4, Math.round(height * density)),\n\t};\n}\n\nfunction halfVector(azimuth: number, elevation: number) {\n\tconst lightX = Math.cos(azimuth) * Math.cos(elevation);\n\tconst lightY = -Math.sin(azimuth) * Math.cos(elevation);\n\tconst lightZ = Math.sin(elevation);\n\tconst length = Math.hypot(lightX, lightY, lightZ + 1) || 1;\n\treturn {\n\t\tx: lightX / length,\n\t\ty: lightY / length,\n\t\tz: (lightZ + 1) / length,\n\t};\n}\n\nexport function generateLensMap(\n\tshape: LensShape,\n\tprofile: LensProfile,\n\tscale = 1,\n): LensMap | undefined {\n\tif (typeof document === \"undefined\") return undefined;\n\tif (shape.halfWidth <= 0 || shape.halfHeight <= 0) return undefined;\n\n\tconst snapped = snapShape(shape);\n\tconst size = resolutionFor(snapped, profile.mapSize, scale);\n\tconst key = cacheKey(snapped, profile, size.width, size.height);\n\tconst cached = mapCache.get(key);\n\tif (cached) return cached;\n\tif (\n\t\t!sharedCanvas ||\n\t\tsharedCanvas.width !== size.width ||\n\t\tsharedCanvas.height !== size.height\n\t) {\n\t\tsharedCanvas = document.createElement(\"canvas\");\n\t\tsharedCanvas.width = size.width;\n\t\tsharedCanvas.height = size.height;\n\t}\n\tconst context = sharedCanvas.getContext(\"2d\", { willReadFrequently: true });\n\tif (!context) return undefined;\n\n\tconst { halfWidth, halfHeight } = snapped;\n\tconst inradius = Math.min(halfWidth, halfHeight);\n\tconst radius = clamp(snapped.borderRadius, 0, inradius);\n\tconst bevel = clamp(profile.bevel, 0.5, inradius);\n\n\tconst { magnitude, tangent, upward, fresnel } = buildProfile(profile, bevel);\n\n\tconst pull = 1 - 1 / Math.max(profile.magnification, 0.01);\n\tconst dished = Math.abs(pull) > 1e-4;\n\tconst handover = bevel * DOME_HANDOVER;\n\tconst lastSample = PROFILE_SAMPLES - 1;\n\tconst perUnit = lastSample / bevel;\n\n\tconst length = clamp(profile.domeLength, 0, 1);\n\tconst coreX = Math.max(0, halfWidth - halfHeight) * length;\n\tconst coreY = Math.max(0, halfHeight - halfWidth) * length;\n\n\tconst azimuth = (profile.lightAngle * Math.PI) / 180;\n\tconst elevation = (profile.lightElevation * Math.PI) / 180;\n\tconst keyHalf = halfVector(azimuth, elevation);\n\tconst echoHalf = halfVector(azimuth + Math.PI, elevation);\n\n\tconst shininess = 2 / Math.max(1e-4, profile.roughness ** 4) - 2;\n\tconst lobeFloor = (1 / 512) ** (1 / shininess);\n\n\tconst { width, height } = size;\n\tconst stepX = (2 * halfWidth) / width;\n\tconst stepY = (2 * halfHeight) / height;\n\tconst halfStep = (stepX + stepY) / 4;\n\tconst innerX = halfWidth - radius;\n\tconst innerY = halfHeight - radius;\n\tconst cut = dished\n\t\t? undefined\n\t\t: planCut(width, height, {\n\t\t\t\tx: cornerReach(Math.max(radius, bevel), stepX),\n\t\t\t\ty: cornerReach(Math.max(radius, bevel), stepY),\n\t\t\t});\n\tconst keep = (side: \"x\" | \"y\", size: number): Array<[number, number]> =>\n\t\tcut?.axis === side\n\t\t\t? [\n\t\t\t\t\t[0, cut.start + 1],\n\t\t\t\t\t[size - cut.end, size],\n\t\t\t\t]\n\t\t\t: [[0, size]];\n\tconst keptRows = keep(\"y\", height);\n\tconst keptColumns = keep(\"x\", width);\n\tconst eachKept = (visit: (index: number) => void) => {\n\t\tfor (const [firstRow, lastRow] of keptRows) {\n\t\t\tfor (let row = firstRow; row < lastRow; row += 1) {\n\t\t\t\tfor (const [firstColumn, lastColumn] of keptColumns) {\n\t\t\t\t\tfor (let column = firstColumn; column < lastColumn; column += 1) {\n\t\t\t\t\t\tvisit(row * width + column);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n\tconst count = width * height;\n\tconst rimX = new Float32Array(count);\n\tconst rimY = new Float32Array(count);\n\tconst dishX = new Float32Array(count);\n\tconst dishY = new Float32Array(count);\n\tconst shades = new Float32Array(count);\n\tconst covered = new Uint8ClampedArray(count);\n\tlet reach = 0;\n\tlet rimReach = 0;\n\n\tfor (const [firstRow, lastRow] of keptRows)\n\t\tfor (let row = firstRow; row < lastRow; row += 1) {\n\t\t\tconst y = (row + 0.5) * stepY - halfHeight;\n\t\t\tconst absY = Math.abs(y);\n\t\t\tconst signY = y < 0 ? -1 : 1;\n\t\t\tconst cornerY = absY - innerY;\n\t\t\tconst axialY = y - clamp(y, -coreY, coreY);\n\n\t\t\tfor (const [firstColumn, lastColumn] of keptColumns)\n\t\t\t\tfor (let column = firstColumn; column < lastColumn; column += 1) {\n\t\t\t\t\tconst index = row * width + column;\n\t\t\t\t\tconst x = (column + 0.5) * stepX - halfWidth;\n\t\t\t\t\tconst absX = Math.abs(x);\n\t\t\t\t\tconst cornerX = absX - innerX;\n\n\t\t\t\t\tlet distance: number;\n\t\t\t\t\tif (cornerX > 0 && cornerY > 0) {\n\t\t\t\t\t\tdistance = Math.hypot(cornerX, cornerY) - radius;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdistance = Math.max(cornerX, cornerY) - radius;\n\t\t\t\t\t}\n\t\t\t\t\tif (distance >= halfStep) continue;\n\t\t\t\t\tconst coverage = clamp(0.5 - distance / (halfStep * 2), 0, 1);\n\t\t\t\t\tcovered[index] = Math.round(coverage * 255);\n\t\t\t\t\tconst depth = Math.max(0, -distance);\n\n\t\t\t\t\tif (dished) {\n\t\t\t\t\t\tconst t = handover > 0 ? clamp(depth / handover, 0, 1) : 1;\n\t\t\t\t\t\tconst fade = t * t * (3 - 2 * t) * coverage;\n\t\t\t\t\t\tconst domeX = -pull * (x - clamp(x, -coreX, coreX)) * fade;\n\t\t\t\t\t\tconst domeY = -pull * axialY * fade;\n\t\t\t\t\t\tdishX[index] = domeX;\n\t\t\t\t\t\tdishY[index] = domeY;\n\t\t\t\t\t\tconst outside = Math.max(\n\t\t\t\t\t\t\tMath.abs(x + domeX) - halfWidth,\n\t\t\t\t\t\t\tMath.abs(y + domeY) - halfHeight,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (outside > reach) reach = outside;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (depth >= bevel) continue;\n\n\t\t\t\t\tlet gradientX: number;\n\t\t\t\t\tlet gradientY: number;\n\t\t\t\t\tif (cornerX > 0 && cornerY > 0) {\n\t\t\t\t\t\tconst length = Math.hypot(cornerX, cornerY) || 1e-6;\n\t\t\t\t\t\tgradientX = (cornerX / length) * (x < 0 ? -1 : 1);\n\t\t\t\t\t\tgradientY = (cornerY / length) * signY;\n\t\t\t\t\t} else if (cornerX > cornerY) {\n\t\t\t\t\t\tgradientX = x < 0 ? -1 : 1;\n\t\t\t\t\t\tgradientY = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgradientX = 0;\n\t\t\t\t\t\tgradientY = signY;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst at = depth * perUnit;\n\t\t\t\t\tconst low = at | 0;\n\t\t\t\t\tconst high = low >= lastSample ? lastSample : low + 1;\n\t\t\t\t\tconst blend = at - low;\n\n\t\t\t\t\tconst bend =\n\t\t\t\t\t\tmagnitude[low] + (magnitude[high] - magnitude[low]) * blend;\n\t\t\t\t\tconst lateral = tangent[low] + (tangent[high] - tangent[low]) * blend;\n\t\t\t\t\tconst vertical = upward[low] + (upward[high] - upward[low]) * blend;\n\t\t\t\t\tconst reflectance =\n\t\t\t\t\t\tfresnel[low] + (fresnel[high] - fresnel[low]) * blend;\n\n\t\t\t\t\tconst normalX = lateral * gradientX;\n\t\t\t\t\tconst normalY = lateral * gradientY;\n\n\t\t\t\t\tconst facing = -normalY * profile.environment;\n\t\t\t\t\tlet shade =\n\t\t\t\t\t\treflectance *\n\t\t\t\t\t\t(profile.rimLight +\n\t\t\t\t\t\t\t(facing > 0 ? facing : facing * profile.rimShadow));\n\n\t\t\t\t\tconst lobe =\n\t\t\t\t\t\tnormalX * keyHalf.x + normalY * keyHalf.y + vertical * keyHalf.z;\n\t\t\t\t\tif (lobe > lobeFloor) {\n\t\t\t\t\t\tshade += lobe ** shininess * profile.specularStrength;\n\t\t\t\t\t}\n\t\t\t\t\tconst echo =\n\t\t\t\t\t\tnormalX * echoHalf.x + normalY * echoHalf.y + vertical * echoHalf.z;\n\t\t\t\t\tif (echo > lobeFloor && profile.backLight > 0) {\n\t\t\t\t\t\tshade +=\n\t\t\t\t\t\t\techo ** shininess * profile.specularStrength * profile.backLight;\n\t\t\t\t\t}\n\n\t\t\t\t\trimX[index] = bend * gradientX * coverage;\n\t\t\t\t\trimY[index] = bend * gradientY * coverage;\n\t\t\t\t\tshades[index] = clamp(shade, -1, 1) * coverage;\n\t\t\t\t\tconst beyond = Math.max(\n\t\t\t\t\t\tMath.abs(x + rimX[index] + dishX[index]) - halfWidth,\n\t\t\t\t\t\tMath.abs(y + rimY[index] + dishY[index]) - halfHeight,\n\t\t\t\t\t);\n\t\t\t\t\tif (beyond > rimReach) rimReach = beyond;\n\t\t\t\t}\n\t\t}\n\n\tlet combinedPeak = 0;\n\teachKept((index) => {\n\t\trimX[index] += dishX[index];\n\t\trimY[index] += dishY[index];\n\t\tconst amount = Math.max(Math.abs(rimX[index]), Math.abs(rimY[index]));\n\t\tif (amount > combinedPeak) combinedPeak = amount;\n\t});\n\tconst bendScale = combinedPeak > 1e-6 ? 127.5 / combinedPeak : 0;\n\tconst image = context.createImageData(width, height);\n\tconst pixels = image.data;\n\tconst lightImage = context.createImageData(width, height);\n\tconst lightPixels = lightImage.data;\n\tconst shading = profile.shadingStrength;\n\teachKept((index) => {\n\t\tconst offset = index * 4;\n\t\tconst red = toByte(127.5 + rimX[index] * bendScale);\n\t\tconst green = toByte(127.5 + rimY[index] * bendScale);\n\t\tconst blue = toByte(127.5 + 127.5 * shades[index]);\n\t\tconst coverage = covered[index] / 255;\n\t\tconst ground = 128 * (1 - coverage);\n\t\tpixels[offset] = Math.round(red * coverage + ground);\n\t\tpixels[offset + 1] = Math.round(green * coverage + ground);\n\t\tpixels[offset + 2] = covered[index];\n\t\tpixels[offset + 3] = 255;\n\t\tconst lit = (blue * coverage + ground) / 255;\n\t\tconst grey = toByte(255 * (0.5 + shading * (lit - 0.5)));\n\t\tlightPixels[offset] = grey;\n\t\tlightPixels[offset + 1] = grey;\n\t\tlightPixels[offset + 2] = grey;\n\t\tlightPixels[offset + 3] = 255;\n\t});\n\tconst slices: LensSlices | undefined = dished\n\t\t? undefined\n\t\t: cut\n\t\t\t? {\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tcut,\n\t\t\t\t\tmap: slicePieces(image, cut),\n\t\t\t\t\tlight: slicePieces(lightImage, cut),\n\t\t\t\t}\n\t\t\t: {\n\t\t\t\t\twidth,\n\t\t\t\t\theight,\n\t\t\t\t\tmap: [encodeImage(image)],\n\t\t\t\t\tlight: [encodeImage(lightImage)],\n\t\t\t\t};\n\tlet url: string | undefined;\n\tlet light: string | undefined;\n\tif (!slices) {\n\t\tcontext.putImageData(image, 0, 0);\n\t\turl = sharedCanvas.toDataURL(\"image/png\");\n\t\tlight = encodeImage(lightImage);\n\t}\n\n\tconst half = profile.dispersion * 0.5;\n\tlastMapId += 1;\n\tconst result: LensMap = {\n\t\tid: lastMapId,\n\t\tget url() {\n\t\t\tif (url === undefined)\n\t\t\t\turl = encodeImage(cut ? unslice(image, cut) : image);\n\t\t\treturn url;\n\t\t},\n\t\tget light() {\n\t\t\tif (light === undefined) {\n\t\t\t\tlight = encodeImage(cut ? unslice(lightImage, cut) : lightImage);\n\t\t\t}\n\t\t\treturn light;\n\t\t},\n\t\tslices,\n\t\tdisplacement: 2 * combinedPeak,\n\t\tchroma: [1 - half, 1, 1 + half],\n\t\treach,\n\t\trimReach: Math.max(rimReach, reach),\n\t\tshadingStrength: profile.shadingStrength,\n\t};\n\n\tif (mapCache.size >= MAP_CACHE_LIMIT) {\n\t\tconst oldest = mapCache.keys().next().value;\n\t\tif (oldest !== undefined) mapCache.delete(oldest);\n\t}\n\tmapCache.set(key, result);\n\treturn result;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/optics.ts"
    },
    {
      "path": "src/glass/glass.tsx",
      "content": "\"use client\";\n\nimport {\n\tcancelFrame,\n\tframe as frameLoop,\n\ttype MotionValue,\n\tuseMotionValue,\n} from \"motion/react\";\nimport {\n\ttype CSSProperties,\n\ttype ReactNode,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport { supportsBackdropRefraction, underBackdropRoot } from \"./backdrop\";\nimport { displacementIsSmooth } from \"./engine\";\nimport \"./glass.css\";\nimport { lightOverlay, readyOverlay } from \"./light\";\nimport {\n\tdecodeMap,\n\tgenerateLensMap,\n\tisMapDecoded,\n\ttype LensMap,\n\ttype LensProfile,\n\ttype LensShape,\n\tprofileKey,\n\tsnapShape,\n} from \"./optics\";\nimport { type GlassLens, offsetWithin, useGlassScope } from \"./scope\";\n\nexport type Animatable = MotionValue<number> | number;\n\nfunction read(value: Animatable) {\n\treturn typeof value === \"number\" ? value : value.get();\n}\n\nfunction lensBox(\n\tx: Animatable,\n\ty: Animatable,\n\tlensWidth: Animatable,\n\tlensHeight: Animatable,\n\tlensRadius: Animatable,\n\tbias: Animatable,\n) {\n\tconst inset = read(bias);\n\tconst innerWidth = Math.max(1, read(lensWidth) - inset * 2);\n\tconst innerHeight = Math.max(1, read(lensHeight) - inset * 2);\n\tconst radius = Math.max(\n\t\t0,\n\t\tMath.min(read(lensRadius) - inset, Math.min(innerWidth, innerHeight) / 2),\n\t);\n\treturn {\n\t\tleft: read(x) - innerWidth / 2,\n\t\ttop: read(y) - innerHeight / 2,\n\t\tinnerWidth,\n\t\tinnerHeight,\n\t\tradius,\n\t};\n}\n\nfunction subscribe(value: Animatable, listener: () => void) {\n\treturn typeof value === \"number\" ? undefined : value.on(\"change\", listener);\n}\n\ntype Mode = \"backdrop\" | \"copy\" | \"lens\" | \"inplace\" | \"none\";\n\ntype Place = {\n\tx: number;\n\ty: number;\n\toriginX: number;\n\toriginY: number;\n\twidth: number;\n\theight: number;\n};\n\ntype Held = { shape: LensShape; key: string; scale: number; result: LensMap };\n\nconst STRETCH_LIMIT = 0.12;\nconst SETTLE_MS = 90;\nconst PINCH_SETTLE_MS = 160;\nconst MAX_PINCH = 4;\nconst BODY_OPAQUE = 0.995;\nconst RELAX_FROM = 0.35;\nconst WARM_TIMEOUT_MS = 2000;\n\nfunction withinStretch(shape: LensShape, drawn: LensShape) {\n\tconst near = (value: number, reference: number) =>\n\t\treference > 0\n\t\t\t? Math.abs(value / reference - 1) <= STRETCH_LIMIT\n\t\t\t: value === reference;\n\treturn (\n\t\tnear(shape.halfWidth, drawn.halfWidth) &&\n\t\tnear(shape.halfHeight, drawn.halfHeight) &&\n\t\tnear(shape.borderRadius, drawn.borderRadius)\n\t);\n}\n\nfunction mapImages(map: LensMap, sliced: boolean) {\n\tif (!sliced) return [map.url, map.light];\n\treturn map.slices ? [...map.slices.map, ...map.slices.light] : [];\n}\n\nfunction mapReady(map: LensMap, sliced: boolean) {\n\treturn mapImages(map, sliced).every(isMapDecoded);\n}\n\nfunction decodeLensMap(map: LensMap, sliced: boolean) {\n\treturn Promise.all(mapImages(map, sliced).map(decodeMap));\n}\n\nfunction sameShape(a: LensShape, b: LensShape) {\n\treturn (\n\t\ta.halfWidth === b.halfWidth &&\n\t\ta.halfHeight === b.halfHeight &&\n\t\ta.borderRadius === b.borderRadius\n\t);\n}\n\nfunction drawn(value: string | undefined) {\n\treturn value && value !== \"none\" ? value : undefined;\n}\n\nfunction whenIdle(task: () => void) {\n\tif (typeof requestIdleCallback === \"function\") {\n\t\tconst handle = requestIdleCallback(task, { timeout: WARM_TIMEOUT_MS });\n\t\treturn () => cancelIdleCallback(handle);\n\t}\n\tconst handle = setTimeout(task, WARM_TIMEOUT_MS / 4);\n\treturn () => clearTimeout(handle);\n}\n\nconst IDENTITY_KERNEL = \"0 0 0 0 1 0 0 0 0\";\n\n// The lens outline is the map's blue channel (coverage) moved to alpha. On a\n// wide-gamut screen Chromium converts the map into the display's colour space\n// first, so blue reads about 0.15 outside the lens and 0.96 inside it, and the\n// unbent page leaks through a faint box around the lens. Coverage 0.25 → 0 and\n// 0.9 → 1, clamped, gives back a clean 0 and 1 in any colour space.\nconst OUTLINE_MATRIX = \"0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1.5385 0 -0.3846\";\n\nfunction smoothingKernel(amount: number) {\n\tconst s = clamp01(amount);\n\tif (s === 0) return IDENTITY_KERNEL;\n\tconst corner = s / 16;\n\tconst side = (2 * s) / 16;\n\tconst centre = 1 - s + (4 * s) / 16;\n\treturn [corner, side, corner, side, centre, side, corner, side, corner]\n\t\t.map((value) => value.toFixed(5))\n\t\t.join(\" \");\n}\n\nfunction smoothstep(from: number, to: number, value: number) {\n\tconst k = clamp01((value - from) / (to - from));\n\treturn k * k * (3 - 2 * k);\n}\n\nfunction clamp01(value: number) {\n\treturn value < 0 ? 0 : value > 1 ? 1 : value;\n}\n\nexport type GlassProps = {\n\twidth: number;\n\theight: number;\n\tx: Animatable;\n\ty: Animatable;\n\tlensWidth: Animatable;\n\tlensHeight: Animatable;\n\tlensRadius: Animatable;\n\tlens: LensProfile;\n\trefractionTarget?: ReactNode;\n\trefract?: boolean;\n\tlight?: boolean;\n\twarm?: LensShape[];\n\tshadowOpacity?: Animatable;\n\ttintColor?: string;\n\ttintOpacity?: Animatable;\n\tface?: ReactNode;\n\ttintBlur?: Animatable;\n\ttintSaturate?: number;\n\tedgeBias?: Animatable;\n\tlag?: Animatable;\n\tresolution?: number;\n\thidden?: boolean;\n\trelax?: boolean;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tchildren?: ReactNode;\n};\n\nexport function Glass({\n\twidth,\n\theight,\n\tx,\n\ty,\n\tlensWidth,\n\tlensHeight,\n\tlensRadius,\n\tlens,\n\trefractionTarget,\n\trefract = true,\n\tlight = false,\n\twarm,\n\tshadowOpacity,\n\ttintColor = \"white\",\n\ttintOpacity,\n\tface,\n\ttintBlur,\n\ttintSaturate = 1,\n\tedgeBias,\n\tlag,\n\tresolution = 2,\n\thidden = false,\n\trelax = false,\n\tclassName,\n\tstyle,\n\tchildren,\n}: GlassProps) {\n\tconst softness = lens.softness;\n\tconst openTint = clamp01(lens.openTint);\n\tconst rawId = useId();\n\tconst baseId = `glass-${rawId.replaceAll(\":\", \"\")}`;\n\tconst scope = useGlassScope();\n\n\tconst rootRef = useRef<HTMLDivElement>(null);\n\tconst layerRef = useRef<HTMLDivElement>(null);\n\tconst filterRef = useRef<SVGFilterElement>(null);\n\tconst rimImageRef = useRef<Element>(null);\n\tconst lightImageRef = useRef<Element>(null);\n\tconst mapSliceRefs = useRef<Element[]>([]);\n\tconst lightSliceRefs = useRef<Element[]>([]);\n\tconst lagPassRef = useRef<Element>(null);\n\tconst frostPassRef = useRef<Element>(null);\n\tconst saturatePassRef = useRef<Element>(null);\n\tconst softenRefs = useRef<Element[]>([]);\n\tconst tintRef = useRef<HTMLDivElement>(null);\n\tconst frostRef = useRef<HTMLDivElement>(null);\n\tconst faceRef = useRef<HTMLDivElement>(null);\n\tconst lightRef = useRef<HTMLDivElement>(null);\n\tconst shadowRef = useRef<HTMLDivElement>(null);\n\tconst restShadowRef = useRef<HTMLDivElement>(null);\n\tconst lensRegionRefs = useRef<Element[]>([]);\n\tconst reachRegionRefs = useRef<Element[]>([]);\n\tconst rimRegionRefs = useRef<Element[]>([]);\n\tconst rimPassRefs = useRef<Element[]>([]);\n\tconst version = useRef(0);\n\tconst dished = Math.abs(1 - 1 / Math.max(lens.magnification, 0.01)) > 1e-4;\n\tconst sliced = !dished;\n\tconst lastMap = useRef<number | undefined>(undefined);\n\tconst lastSignature = useRef(\"\");\n\tconst heldMap = useRef<Held | undefined>(undefined);\n\tconst warmed = useRef<Held[]>([]);\n\tconst readyMap = useRef<LensMap | undefined>(undefined);\n\tconst leased = useRef<GlassLens | null>(null);\n\tconst offset = useRef<Place | null>(null);\n\tconst shownLight = useRef<string | undefined>(undefined);\n\tconst settleTimer = useRef<ReturnType<typeof setTimeout> | undefined>(\n\t\tundefined,\n\t);\n\tconst screenScale = useRef(1);\n\tconst forceNext = useRef(false);\n\tconst frame = useRef(0);\n\tconst pending = useRef<(() => void) | null>(null);\n\tconst alive = useRef(true);\n\tconst hiddenRef = useRef(hidden);\n\thiddenRef.current = hidden;\n\tconst refractRef = useRef(refract);\n\trefractRef.current = refract;\n\tconst scheduleRef = useRef<() => void>(() => {});\n\n\tconst targeted = refractionTarget !== undefined;\n\tconst [mode, setMode] = useState<Mode>(targeted ? \"copy\" : \"none\");\n\tconst frostInFilter = mode === \"backdrop\" && tintBlur !== undefined;\n\tuseLayoutEffect(() => {\n\t\tconst chromium = supportsBackdropRefraction();\n\t\tconst root = rootRef.current;\n\t\t// Chromium drops an SVG backdrop filter with other glass behind it, and\n\t\t// glass bent under other glass is lost under its frost anyway.\n\t\tconst outside = targeted\n\t\t\t? root\n\t\t\t: root?.closest(\".glass-pane\")?.parentElement;\n\t\tconst nested = Boolean(outside?.closest(\".glass-pane\"));\n\t\tconst scoped = Boolean(scope && root?.closest(\".glass-scope\"));\n\t\t// Only a pane's rim bends, so its content stays as it is behind its padding.\n\t\tconst inPlace = scoped && Boolean(scope?.inPlace);\n\t\t// WebKit paints a frosted card's content above the frost, out of a scope\n\t\t// filter's reach, so glass on glass bends in place only in Chromium and Firefox.\n\t\tconst liveNested = chromium || displacementIsSmooth();\n\t\tsetMode(\n\t\t\tinPlace && (!nested || liveNested)\n\t\t\t\t? \"inplace\"\n\t\t\t\t: nested\n\t\t\t\t\t? scope?.nested\n\t\t\t\t\t\t? \"lens\"\n\t\t\t\t\t\t: targeted\n\t\t\t\t\t\t\t? \"copy\"\n\t\t\t\t\t\t\t: \"none\"\n\t\t\t\t\t: targeted && chromium\n\t\t\t\t\t\t? \"backdrop\"\n\t\t\t\t\t\t: scoped\n\t\t\t\t\t\t\t? \"lens\"\n\t\t\t\t\t\t\t: chromium\n\t\t\t\t\t\t\t\t? \"backdrop\"\n\t\t\t\t\t\t\t\t: targeted\n\t\t\t\t\t\t\t\t\t? \"copy\"\n\t\t\t\t\t\t\t\t\t: \"none\",\n\t\t);\n\t}, [scope, targeted]);\n\n\tconst zero = useMotionValue(0);\n\tconst one = useMotionValue(1);\n\tconst shadow = shadowOpacity ?? zero;\n\tconst tint = tintOpacity ?? one;\n\tconst blur = tintBlur ?? zero;\n\tconst bias = edgeBias ?? zero;\n\tconst trail = lag ?? zero;\n\n\tconst mapFor = useCallback(\n\t\t(shape: LensShape) => {\n\t\t\tconst key = profileKey(lens);\n\t\t\tconst scale = screenScale.current;\n\t\t\tconst snapped = snapShape(shape);\n\t\t\tconst candidates = [heldMap.current, ...warmed.current].filter(\n\t\t\t\t(entry): entry is Held =>\n\t\t\t\t\tentry !== undefined && entry.key === key && entry.scale === scale,\n\t\t\t);\n\t\t\tconst exact = candidates.find((entry) => sameShape(snapped, entry.shape));\n\t\t\tif (exact) {\n\t\t\t\theldMap.current = exact;\n\t\t\t\treturn exact.result;\n\t\t\t}\n\t\t\tconst near = candidates.find((entry) =>\n\t\t\t\twithinStretch(snapped, entry.shape),\n\t\t\t);\n\t\t\tif (near) {\n\t\t\t\theldMap.current = near;\n\t\t\t\tclearTimeout(settleTimer.current);\n\t\t\t\tsettleTimer.current = setTimeout(() => {\n\t\t\t\t\tif (!alive.current) return;\n\t\t\t\t\theldMap.current = undefined;\n\t\t\t\t\tscheduleRef.current();\n\t\t\t\t}, SETTLE_MS);\n\t\t\t\treturn near.result;\n\t\t\t}\n\t\t\tconst result = generateLensMap(shape, lens, scale);\n\t\t\theldMap.current = result\n\t\t\t\t? { shape: snapped, key, scale, result }\n\t\t\t\t: undefined;\n\t\t\treturn result;\n\t\t},\n\t\t[lens],\n\t);\n\n\tconst measurePlace = useCallback(() => {\n\t\tconst root = rootRef.current;\n\t\tconst element = scope?.element();\n\t\tconst backdrop = scope?.backdrop();\n\t\tif (!root || !element || !backdrop) {\n\t\t\toffset.current = null;\n\t\t\treturn;\n\t\t}\n\t\tconst at = offsetWithin(root, element);\n\t\tconst origin = element === backdrop ? at : offsetWithin(element, backdrop);\n\t\tconst size = offsetWithin(backdrop, backdrop);\n\t\toffset.current = {\n\t\t\tx: at.x,\n\t\t\ty: at.y,\n\t\t\toriginX: element === backdrop ? 0 : origin.x,\n\t\t\toriginY: element === backdrop ? 0 : origin.y,\n\t\t\twidth: size.width,\n\t\t\theight: size.height,\n\t\t};\n\t}, [scope]);\n\n\tconst release = useCallback(() => {\n\t\tconst held = leased.current;\n\t\tif (!held) return;\n\t\tleased.current = null;\n\t\tscope?.release(held);\n\t\tlastSignature.current = \"\";\n\t}, [scope]);\n\n\tconst sync = useCallback(() => {\n\t\tframe.current = 0;\n\t\tconst filter = filterRef.current;\n\t\tconst layer = layerRef.current;\n\t\tif (!filter) return;\n\n\t\tconst { left, top, innerWidth, innerHeight, radius } = lensBox(\n\t\t\tx,\n\t\t\ty,\n\t\t\tlensWidth,\n\t\t\tlensHeight,\n\t\t\tlensRadius,\n\t\t\tbias,\n\t\t);\n\n\t\t// Overlays inside the filtered layer must not be composited: WebKit leaves\n\t\t// them out of a software filter and promotes what overlaps them.\n\t\tconst flat = mode === \"inplace\";\n\t\tconst placeOnLens = (element: HTMLDivElement | null) => {\n\t\t\tif (!element) return;\n\t\t\telement.style.transform = flat\n\t\t\t\t? `translate(${left}px, ${top}px)`\n\t\t\t\t: `translate3d(${left}px, ${top}px, 0)`;\n\t\t\telement.style.width = `${innerWidth}px`;\n\t\t\telement.style.height = `${innerHeight}px`;\n\t\t\telement.style.borderRadius = `${radius}px`;\n\t\t};\n\n\t\tconst shadowAmount = clamp01(read(shadow));\n\t\tconst rim = shadowRef.current;\n\t\tplaceOnLens(rim);\n\t\tif (rim) rim.style.opacity = String(shadowAmount);\n\n\t\tconst restRim = restShadowRef.current;\n\t\tplaceOnLens(restRim);\n\t\tif (restRim) restRim.style.opacity = String(1 - shadowAmount);\n\n\t\tconst bodyOpacity = clamp01(read(tint));\n\t\tconst body = tintRef.current;\n\t\tplaceOnLens(body);\n\t\tif (body) {\n\t\t\tbody.style.opacity = String(openTint + (1 - openTint) * bodyOpacity);\n\t\t}\n\n\t\tconst refracting =\n\t\t\trefractRef.current &&\n\t\t\t!hiddenRef.current &&\n\t\t\tmode !== \"none\" &&\n\t\t\tbodyOpacity < BODY_OPAQUE;\n\n\t\tconst frost = frostRef.current;\n\t\tif (frost && frostInFilter && refracting) {\n\t\t\tfrost.style.display = \"none\";\n\t\t} else if (frost) {\n\t\t\tconst amount = read(blur);\n\t\t\tplaceOnLens(frost);\n\t\t\tconst backdropBlur =\n\t\t\t\tamount > 0\n\t\t\t\t\t? `blur(${amount}px)${tintSaturate !== 1 ? ` saturate(${tintSaturate})` : \"\"}`\n\t\t\t\t\t: \"none\";\n\t\t\tfrost.style.display = amount > 0 ? \"\" : \"none\";\n\t\t\tfrost.style.backdropFilter = backdropBlur;\n\t\t\tfrost.style.setProperty(\"-webkit-backdrop-filter\", backdropBlur);\n\t\t}\n\n\t\tconst faceLayer = faceRef.current;\n\t\tif (faceLayer) {\n\t\t\tfaceLayer.style.opacity = String(bodyOpacity);\n\t\t\tfaceLayer.style.clipPath = `inset(${top}px ${width - left - innerWidth}px ${height - top - innerHeight}px ${left}px round ${radius}px)`;\n\t\t}\n\n\t\t// A copy on a see-through layer gives the filter's light nothing to land\n\t\t// on, so it takes the baked light instead, as the lens opens.\n\t\tconst lensLit = targeted && mode === \"copy\" && refracting;\n\t\tconst lit = (light || lensLit) && !hiddenRef.current;\n\t\tconst shape = {\n\t\t\thalfWidth: innerWidth / 2,\n\t\t\thalfHeight: innerHeight / 2,\n\t\t\tborderRadius: radius,\n\t\t};\n\t\tconst drawnMap = lit || refracting ? mapFor(shape) : undefined;\n\n\t\tconst lightLayer = lightRef.current;\n\t\tif (lightLayer) {\n\t\t\tlightLayer.style.display = lit ? \"\" : \"none\";\n\t\t\tif (lit) {\n\t\t\t\tplaceOnLens(lightLayer);\n\t\t\t\tlightLayer.style.opacity = light ? \"\" : String(1 - bodyOpacity);\n\t\t\t\tconst overlay = drawnMap ? readyOverlay(drawnMap.light) : undefined;\n\t\t\t\tif (drawnMap && !overlay) {\n\t\t\t\t\tlightOverlay(drawnMap.light).then(() => {\n\t\t\t\t\t\tif (alive.current) scheduleRef.current();\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst next = overlay ?? shownLight.current;\n\t\t\t\tif (next !== shownLight.current) {\n\t\t\t\t\tshownLight.current = next;\n\t\t\t\t\tlightLayer.style.backgroundImage = next ? `url(\"${next}\")` : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (layer) {\n\t\t\tconst hide = !refracting;\n\t\t\tif (hide !== (layer.style.visibility === \"hidden\")) {\n\t\t\t\tlayer.style.visibility = hide ? \"hidden\" : \"\";\n\t\t\t\tif (!hide) forceNext.current = true;\n\t\t\t}\n\t\t}\n\n\t\tif (!refracting) {\n\t\t\tif (mode === \"backdrop\" && layer && layer.style.backdropFilter) {\n\t\t\t\tlayer.style.backdropFilter = \"\";\n\t\t\t\tlastSignature.current = \"\";\n\t\t\t}\n\t\t\tif (mode === \"inplace\") {\n\t\t\t\tscope?.applyFilter?.(baseId, null);\n\t\t\t\tlastSignature.current = \"\";\n\t\t\t}\n\t\t\trelease();\n\t\t\treturn;\n\t\t}\n\n\t\t// Checked as the glass opens, since a card or a fade can turn into a\n\t\t// backdrop root after the glass mounts.\n\t\tif (\n\t\t\tmode === \"backdrop\" &&\n\t\t\tlayer &&\n\t\t\t!layer.style.backdropFilter &&\n\t\t\tunderBackdropRoot(layer)\n\t\t) {\n\t\t\tconst scoped = Boolean(scope && rootRef.current?.closest(\".glass-scope\"));\n\t\t\tsetMode(targeted ? (scoped ? \"lens\" : \"copy\") : \"none\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst factor = mode === \"copy\" ? resolution : 1;\n\t\tconst scaled = (value: number) => value * factor;\n\t\tconst grid = screenScale.current / factor;\n\t\tconst snap = (value: number) => Math.round(value * grid) / grid;\n\n\t\tif (mode === \"copy\" && layer) {\n\t\t\tconst regionWidth = scaled(width);\n\t\t\tconst regionHeight = scaled(height);\n\t\t\tlayer.style.clipPath = `inset(${scaled(top)}px ${regionWidth - scaled(left + innerWidth)}px ${regionHeight - scaled(top + innerHeight)}px ${scaled(left)}px round ${scaled(radius)}px)`;\n\t\t}\n\n\t\tlet result = drawnMap;\n\t\tif (drawnMap && !mapReady(drawnMap, sliced)) {\n\t\t\tdecodeLensMap(drawnMap, sliced).then(() => {\n\t\t\t\tif (!alive.current) return;\n\t\t\t\tforceNext.current = true;\n\t\t\t\tscheduleRef.current();\n\t\t\t});\n\t\t\tif (readyMap.current) result = readyMap.current;\n\t\t} else if (drawnMap) {\n\t\t\treadyMap.current = drawnMap;\n\t\t}\n\t\tconst pieces = sliced ? result?.slices : undefined;\n\t\tif (sliced && !pieces) result = undefined;\n\t\t// WebKit blanks a layer under a filter whose images have not arrived.\n\t\tif (mode === \"inplace\" && !result) return;\n\n\t\tconst settled = relax\n\t\t\t? 1 - smoothstep(RELAX_FROM, BODY_OPAQUE, bodyOpacity)\n\t\t\t: 1;\n\t\tconst unit = result ? scaled(result.displacement) * settled : 0;\n\t\tconst scales = result\n\t\t\t? ([\n\t\t\t\t\tunit * result.chroma[0],\n\t\t\t\t\tunit * result.chroma[1],\n\t\t\t\t\tunit * result.chroma[2],\n\t\t\t\t] as const)\n\t\t\t: ([0, 0, 0] as const);\n\t\tconst soften =\n\t\t\tdished && !displacementIsSmooth()\n\t\t\t\t? smoothingKernel(softness)\n\t\t\t\t: IDENTITY_KERNEL;\n\t\tconst shift = snap(scaled(read(trail)));\n\t\tconst frostAmount = frostInFilter\n\t\t\t? Math.round(scaled(read(blur)) * 100) / 100\n\t\t\t: 0;\n\n\t\tconst outward = (distance: number | undefined) =>\n\t\t\tdistance\n\t\t\t\t? Math.ceil((scaled(distance * 1.15) + factor) * grid) / grid\n\t\t\t\t: 0;\n\t\tconst rimReach = outward(result?.rimReach);\n\t\tconst reach = Math.max(outward(result?.reach), rimReach);\n\n\t\tlet originX = 0;\n\t\tlet originY = 0;\n\t\tif (mode === \"inplace\") {\n\t\t\tif (!offset.current) measurePlace();\n\t\t\tconst at = offset.current;\n\t\t\tif (!at) return;\n\t\t\toriginX = at.x;\n\t\t\toriginY = at.y;\n\t\t}\n\t\tif (mode === \"lens\") {\n\t\t\tif (!leased.current) {\n\t\t\t\tleased.current = scope?.lease() ?? null;\n\t\t\t\tif (!leased.current) return;\n\t\t\t\tforceNext.current = true;\n\t\t\t}\n\t\t\tif (!offset.current) measurePlace();\n\t\t\tconst at = offset.current;\n\t\t\tif (!at) return;\n\t\t\tconst pull =\n\t\t\t\tMath.max(\n\t\t\t\t\treach,\n\t\t\t\t\tMath.abs(shift),\n\t\t\t\t\t...scales.map((s) => Math.abs(s) / 2),\n\t\t\t\t) +\n\t\t\t\t2 +\n\t\t\t\tleased.current.feather;\n\t\t\tconst bounds = {\n\t\t\t\tleft: Math.floor(at.x + left - pull),\n\t\t\t\ttop: Math.floor(at.y + top - pull),\n\t\t\t\tright: Math.ceil(at.x + left + innerWidth + pull),\n\t\t\t\tbottom: Math.ceil(at.y + top + innerHeight + pull),\n\t\t\t};\n\t\t\toriginX = at.x - bounds.left;\n\t\t\toriginY = at.y - bounds.top;\n\t\t\tconst { box, frost, copy, margin } = leased.current;\n\t\t\tconst boxWidth = bounds.right - bounds.left;\n\t\t\tconst boxHeight = bounds.bottom - bounds.top;\n\t\t\tbox.style.left = `${bounds.left}px`;\n\t\t\tbox.style.top = `${bounds.top}px`;\n\t\t\tbox.style.width = `${boxWidth}px`;\n\t\t\tbox.style.height = `${boxHeight}px`;\n\t\t\tfrost.style.left = `${-margin}px`;\n\t\t\tfrost.style.top = `${-margin}px`;\n\t\t\tfrost.style.width = `${boxWidth + margin * 2}px`;\n\t\t\tfrost.style.height = `${boxHeight + margin * 2}px`;\n\t\t\tcopy.style.left = `${margin - bounds.left - at.originX}px`;\n\t\t\tcopy.style.top = `${margin - bounds.top - at.originY}px`;\n\t\t\tcopy.style.width = `${at.width}px`;\n\t\t\tcopy.style.height = `${at.height}px`;\n\t\t}\n\n\t\tconst edge = factor / 2;\n\t\tconst regionX = snap(originX + scaled(left) + edge);\n\t\tconst regionY = snap(originY + scaled(top) + edge);\n\t\tconst regionInnerWidth =\n\t\t\tsnap(originX + scaled(left + innerWidth) - edge) - regionX;\n\t\tconst regionInnerHeight =\n\t\t\tsnap(originY + scaled(top + innerHeight) - edge) - regionY;\n\n\t\tconst signature = `${regionX}|${regionY}|${regionInnerWidth}|${regionInnerHeight}|${reach}|${rimReach}|${scales.join(\",\")}|${soften}|${shift}|${frostAmount}|${result?.id ?? \"\"}`;\n\t\tif (!forceNext.current && signature === lastSignature.current) return;\n\t\tlastSignature.current = signature;\n\t\tforceNext.current = false;\n\n\t\tfor (const element of lensRegionRefs.current) {\n\t\t\telement.setAttribute(\"x\", String(regionX));\n\t\t\telement.setAttribute(\"y\", String(regionY));\n\t\t\telement.setAttribute(\"width\", String(regionInnerWidth));\n\t\t\telement.setAttribute(\"height\", String(regionInnerHeight));\n\t\t}\n\t\tconst grow = (elements: Element[], by: number) => {\n\t\t\tfor (const element of elements) {\n\t\t\t\telement.setAttribute(\"x\", String(regionX - by));\n\t\t\t\telement.setAttribute(\"y\", String(regionY - by));\n\t\t\t\telement.setAttribute(\"width\", String(regionInnerWidth + by * 2));\n\t\t\t\telement.setAttribute(\"height\", String(regionInnerHeight + by * 2));\n\t\t\t}\n\t\t};\n\t\tgrow(reachRegionRefs.current, reach);\n\t\tgrow(rimRegionRefs.current, rimReach);\n\t\tif (pieces) {\n\t\t\tconst { cut } = pieces;\n\t\t\tconst alongX = cut?.axis !== \"y\";\n\t\t\tconst from = alongX ? regionX : regionY;\n\t\t\tconst size = alongX ? regionInnerWidth : regionInnerHeight;\n\t\t\tconst length = alongX ? pieces.width : pieces.height;\n\t\t\tconst pixel = 1 / grid;\n\t\t\tconst spans = cut\n\t\t\t\t? [\n\t\t\t\t\t\t[from, from + (cut.start * size) / length],\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tMath.max(from, from + (cut.start * size) / length - pixel),\n\t\t\t\t\t\t\tMath.min(\n\t\t\t\t\t\t\t\tfrom + size,\n\t\t\t\t\t\t\t\tfrom + ((length - cut.end) * size) / length + pixel,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t],\n\t\t\t\t\t\t[from + ((length - cut.end) * size) / length, from + size],\n\t\t\t\t\t]\n\t\t\t\t: [[from, from + size]];\n\t\t\tconst place = (element: Element, index: number) => {\n\t\t\t\tconst [lead, tail] = spans[index] ?? spans[0];\n\t\t\t\tconst span = String(tail - lead);\n\t\t\t\telement.setAttribute(\"x\", String(alongX ? lead : regionX));\n\t\t\t\telement.setAttribute(\"y\", String(alongX ? regionY : lead));\n\t\t\t\telement.setAttribute(\"width\", alongX ? span : String(regionInnerWidth));\n\t\t\t\telement.setAttribute(\n\t\t\t\t\t\"height\",\n\t\t\t\t\talongX ? String(regionInnerHeight) : span,\n\t\t\t\t);\n\t\t\t};\n\t\t\tmapSliceRefs.current.forEach(place);\n\t\t\tlightSliceRefs.current.forEach(place);\n\t\t}\n\t\tif (result && result.id !== lastMap.current) {\n\t\t\tlastMap.current = result.id;\n\t\t\tif (pieces) {\n\t\t\t\t// An feImage without an image drops the whole filter in WebKit.\n\t\t\t\tconst show = (elements: Element[], urls: string[]) => {\n\t\t\t\t\telements.forEach((element, index) => {\n\t\t\t\t\t\telement.setAttribute(\"href\", urls[index] ?? urls[0]);\n\t\t\t\t\t});\n\t\t\t\t};\n\t\t\t\tshow(mapSliceRefs.current, pieces.map);\n\t\t\t\tshow(lightSliceRefs.current, pieces.light);\n\t\t\t} else {\n\t\t\t\trimImageRef.current?.setAttribute(\"href\", result.url);\n\t\t\t\tlightImageRef.current?.setAttribute(\"href\", result.light);\n\t\t\t}\n\t\t}\n\t\tlagPassRef.current?.setAttribute(\"dx\", String(shift));\n\t\tfrostPassRef.current?.setAttribute(\"stdDeviation\", String(frostAmount));\n\t\tsaturatePassRef.current?.setAttribute(\n\t\t\t\"values\",\n\t\t\tString(frostAmount > 0 ? tintSaturate : 1),\n\t\t);\n\t\tfor (const element of softenRefs.current) {\n\t\t\telement.setAttribute(\"kernelMatrix\", soften);\n\t\t}\n\t\trimPassRefs.current.forEach((element, index) => {\n\t\t\telement.setAttribute(\"scale\", String(scales[index] ?? 0));\n\t\t});\n\n\t\t// Safari caches filter output by id, so every update takes a fresh one.\n\t\tversion.current += 1;\n\t\tconst id = `${baseId}-v${version.current}`;\n\t\tfilter.id = id;\n\t\tif (mode === \"lens\" && leased.current) {\n\t\t\tleased.current.box.style.filter = `url(#${id})`;\n\t\t} else if (mode === \"backdrop\" && layer) {\n\t\t\tlayer.style.backdropFilter = `url(#${id})`;\n\t\t} else if (mode === \"inplace\") {\n\t\t\tscope?.applyFilter?.(baseId, filter);\n\t\t} else if (layer) {\n\t\t\tlayer.style.filter = `url(#${id})`;\n\t\t}\n\n\t\tif (result && !mapReady(result, sliced)) {\n\t\t\tconst shown = result.id;\n\t\t\tdecodeLensMap(result, sliced).then(() => {\n\t\t\t\tif (!alive.current || lastMap.current !== shown) return;\n\t\t\t\tforceNext.current = true;\n\t\t\t\tscheduleRef.current();\n\t\t\t});\n\t\t}\n\t}, [\n\t\tbaseId,\n\t\tbias,\n\t\tblur,\n\t\tdished,\n\t\tfrostInFilter,\n\t\theight,\n\t\tlight,\n\t\topenTint,\n\t\tsoftness,\n\t\tmapFor,\n\t\tmeasurePlace,\n\t\tmode,\n\t\tlensHeight,\n\t\tlensRadius,\n\t\tlensWidth,\n\t\trelax,\n\t\trelease,\n\t\tresolution,\n\t\tscope,\n\t\tshadow,\n\t\tsliced,\n\t\ttargeted,\n\t\ttint,\n\t\ttintSaturate,\n\t\ttrail,\n\t\twidth,\n\t\tx,\n\t\ty,\n\t]);\n\n\tconst schedule = useCallback(() => {\n\t\tif (frame.current) return;\n\t\tframe.current = 1;\n\t\tpending.current = sync;\n\t\tframeLoop.render(sync);\n\t}, [sync]);\n\tscheduleRef.current = schedule;\n\n\tuseLayoutEffect(() => {\n\t\tconst filter = filterRef.current;\n\t\tlensRegionRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll(\"[data-lens]\"))\n\t\t\t: [];\n\t\treachRegionRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll(\"[data-reach]\"))\n\t\t\t: [];\n\t\trimRegionRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll(\"[data-rim]\"))\n\t\t\t: [];\n\t\trimPassRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll('[data-pass=\"rim\"]'))\n\t\t\t: [];\n\t\tlagPassRef.current = filter?.querySelector('[data-pass=\"lag\"]') ?? null;\n\t\tfrostPassRef.current = filter?.querySelector('[data-pass=\"frost\"]') ?? null;\n\t\tsaturatePassRef.current =\n\t\t\tfilter?.querySelector('[data-pass=\"saturate\"]') ?? null;\n\t\tsoftenRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll(\"[data-soften]\"))\n\t\t\t: [];\n\t\trimImageRef.current = filter?.querySelector('[data-map=\"rim\"]') ?? null;\n\t\tlightImageRef.current = filter?.querySelector('[data-map=\"light\"]') ?? null;\n\t\tmapSliceRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll('[data-slice=\"map\"]'))\n\t\t\t: [];\n\t\tlightSliceRefs.current = filter\n\t\t\t? Array.from(filter.querySelectorAll('[data-slice=\"light\"]'))\n\t\t\t: [];\n\t\tlastMap.current = undefined;\n\t\tlastSignature.current = \"\";\n\t\talive.current = true;\n\n\t\tconst measure = () => {\n\t\t\tconst node = rootRef.current;\n\t\t\tif (!node || width <= 0) return;\n\t\t\tif (scope) {\n\t\t\t\tmeasurePlace();\n\t\t\t\tforceNext.current = true;\n\t\t\t}\n\t\t\tconst ratio =\n\t\t\t\t(node.getBoundingClientRect().width / width) *\n\t\t\t\t(window.devicePixelRatio || 1) *\n\t\t\t\tMath.min(window.visualViewport?.scale ?? 1, MAX_PINCH);\n\t\t\tif (!Number.isFinite(ratio) || ratio <= 0) return;\n\t\t\tif (Math.abs(ratio - screenScale.current) < 0.01 && !scope) return;\n\t\t\tscreenScale.current = ratio;\n\t\t\tforceNext.current = true;\n\t\t\tsync();\n\t\t};\n\t\tmeasure();\n\t\tsync();\n\n\t\tlet moved = 0;\n\t\tconst scopeElement = scope?.backdrop();\n\t\tconst layout =\n\t\t\tscopeElement && typeof ResizeObserver !== \"undefined\"\n\t\t\t\t? new ResizeObserver(() => {\n\t\t\t\t\t\tif (moved) return;\n\t\t\t\t\t\tmoved = requestAnimationFrame(() => {\n\t\t\t\t\t\t\tmoved = 0;\n\t\t\t\t\t\t\tmeasure();\n\t\t\t\t\t\t});\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\tif (layout && scopeElement) {\n\t\t\tlet node = rootRef.current?.parentElement ?? null;\n\t\t\twhile (node && node !== scopeElement) {\n\t\t\t\tlayout.observe(node);\n\t\t\t\tnode = node.parentElement;\n\t\t\t}\n\t\t\tlayout.observe(scopeElement);\n\t\t}\n\t\tconst stopScope = scope?.onChange(() => {\n\t\t\tforceNext.current = true;\n\t\t\tscheduleRef.current();\n\t\t});\n\n\t\tlet pinched: ReturnType<typeof setTimeout> | undefined;\n\t\tconst settle = () => {\n\t\t\tclearTimeout(pinched);\n\t\t\tpinched = setTimeout(measure, PINCH_SETTLE_MS);\n\t\t};\n\t\twindow.addEventListener(\"resize\", measure);\n\t\twindow.visualViewport?.addEventListener(\"resize\", settle);\n\t\treturn () => {\n\t\t\twindow.removeEventListener(\"resize\", measure);\n\t\t\twindow.visualViewport?.removeEventListener(\"resize\", settle);\n\t\t\tclearTimeout(pinched);\n\t\t\tlayout?.disconnect();\n\t\t\tstopScope?.();\n\t\t\tcancelAnimationFrame(moved);\n\t\t\tclearTimeout(settleTimer.current);\n\t\t\trelease();\n\t\t\tscope?.applyFilter?.(baseId, null);\n\t\t\talive.current = false;\n\t\t};\n\t}, [baseId, measurePlace, release, scope, sync, width]);\n\n\tuseEffect(() => {\n\t\tconst unsubscribes = [\n\t\t\tx,\n\t\t\ty,\n\t\t\tlensWidth,\n\t\t\tlensHeight,\n\t\t\tlensRadius,\n\t\t\tshadow,\n\t\t\ttint,\n\t\t\tblur,\n\t\t\tbias,\n\t\t\ttrail,\n\t\t].map((value) => subscribe(value, schedule));\n\t\treturn () => {\n\t\t\tif (pending.current) cancelFrame(pending.current);\n\t\t\tpending.current = null;\n\t\t\tframe.current = 0;\n\t\t\tfor (const unsubscribe of unsubscribes) unsubscribe?.();\n\t\t};\n\t}, [\n\t\tbias,\n\t\tblur,\n\t\tlensHeight,\n\t\tlensRadius,\n\t\tlensWidth,\n\t\tschedule,\n\t\tshadow,\n\t\ttint,\n\t\ttrail,\n\t\tx,\n\t\ty,\n\t]);\n\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: a flip of either only needs a fresh sync\n\tuseEffect(() => {\n\t\tforceNext.current = true;\n\t\tscheduleRef.current();\n\t}, [hidden, refract]);\n\n\tconst warmKey = warm\n\t\t?.map((shape) => {\n\t\t\tconst snapped = snapShape(shape);\n\t\t\treturn `${snapped.halfWidth}x${snapped.halfHeight}r${snapped.borderRadius}`;\n\t\t})\n\t\t.join(\"|\");\n\t// biome-ignore lint/correctness/useExhaustiveDependencies: warmKey stands in for the shapes\n\tuseEffect(() => {\n\t\tif (!warm?.length || mode === \"none\") return;\n\t\treturn whenIdle(() => {\n\t\t\tconst key = profileKey(lens);\n\t\t\tconst scale = screenScale.current;\n\t\t\twarmed.current = warm.flatMap((shape) => {\n\t\t\t\tconst result = generateLensMap(shape, lens, scale);\n\t\t\t\tif (!result) return [];\n\t\t\t\tdecodeLensMap(result, sliced);\n\t\t\t\tif (light) lightOverlay(result.light);\n\t\t\t\treturn [{ shape: snapShape(shape), key, scale, result }];\n\t\t\t});\n\t\t});\n\t}, [lens, light, mode, sliced, warmKey]);\n\n\tconst region = width * resolution;\n\tconst regionHeight = height * resolution;\n\tconst insetShadow = drawn(lens.edgeInsetShadow);\n\n\tconst [first] = useState(() => {\n\t\tconst box = lensBox(x, y, lensWidth, lensHeight, lensRadius, edgeBias ?? 0);\n\t\tconst place = {\n\t\t\ttransform: `translate3d(${box.left}px, ${box.top}px, 0)`,\n\t\t\twidth: box.innerWidth,\n\t\t\theight: box.innerHeight,\n\t\t\tborderRadius: box.radius,\n\t\t};\n\t\tconst shadowAmount = clamp01(read(shadowOpacity ?? 0));\n\t\tconst bodyOpacity = clamp01(read(tintOpacity ?? 1));\n\t\tconst r = resolution;\n\t\tconst copy = {\n\t\t\tvisibility: \"hidden\" as const,\n\t\t\tclipPath: `inset(${box.top * r}px ${(width - box.left - box.innerWidth) * r}px ${(height - box.top - box.innerHeight) * r}px ${box.left * r}px round ${box.radius * r}px)`,\n\t\t};\n\t\treturn {\n\t\t\tplace,\n\t\t\tcopy,\n\t\t\tshadow: shadowAmount,\n\t\t\tbody: openTint + (1 - openTint) * bodyOpacity,\n\t\t\tface: {\n\t\t\t\topacity: bodyOpacity,\n\t\t\t\tclipPath: `inset(${box.top}px ${width - box.left - box.innerWidth}px ${height - box.top - box.innerHeight}px ${box.left}px round ${box.radius}px)`,\n\t\t\t},\n\t\t};\n\t});\n\n\treturn (\n\t\t<div\n\t\t\tref={rootRef}\n\t\t\tclassName={[\"glass\", className].filter(Boolean).join(\" \")}\n\t\t\tstyle={{ ...style, width, height }}\n\t\t\tdata-glass=\"\"\n\t\t\tdata-flat={mode === \"inplace\" ? \"\" : undefined}\n\t\t>\n\t\t\t<div className=\"glass__content\">{children}</div>\n\n\t\t\t{mode === \"backdrop\" ? (\n\t\t\t\t<div ref={layerRef} className=\"glass__backdrop\" />\n\t\t\t) : mode === \"copy\" && refractionTarget ? (\n\t\t\t\t<div\n\t\t\t\t\tref={layerRef}\n\t\t\t\t\tclassName=\"glass__target\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...first.copy,\n\t\t\t\t\t\twidth: region,\n\t\t\t\t\t\theight: regionHeight,\n\t\t\t\t\t\ttransform: `scale(${1 / resolution})`,\n\t\t\t\t\t}}\n\t\t\t\t>\n\t\t\t\t\t<div\n\t\t\t\t\t\tclassName=\"glass__target-inner\"\n\t\t\t\t\t\tstyle={{ width, height, transform: `scale(${resolution})` }}\n\t\t\t\t\t>\n\t\t\t\t\t\t{refractionTarget}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : null}\n\n\t\t\t<svg\n\t\t\t\tclassName=\"glass__defs\"\n\t\t\t\tviewBox={`0 0 ${width} ${height}`}\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<defs>\n\t\t\t\t\t<filter\n\t\t\t\t\t\tref={filterRef}\n\t\t\t\t\t\tid={baseId}\n\t\t\t\t\t\tfilterUnits=\"objectBoundingBox\"\n\t\t\t\t\t\tprimitiveUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\tcolorInterpolationFilters=\"sRGB\"\n\t\t\t\t\t\tx=\"0\"\n\t\t\t\t\t\ty=\"0\"\n\t\t\t\t\t\twidth=\"1\"\n\t\t\t\t\t\theight=\"1\"\n\t\t\t\t\t\tdata-result={mode === \"inplace\" ? \"lensResult\" : undefined}\n\t\t\t\t\t\tdata-outline={mode === \"inplace\" ? \"outline\" : undefined}\n\t\t\t\t\t>\n\t\t\t\t\t\t<LensPrimitives\n\t\t\t\t\t\t\tdished={dished}\n\t\t\t\t\t\t\tsliced={sliced}\n\t\t\t\t\t\t\tfrosted={frostInFilter}\n\t\t\t\t\t\t\tlagged={lag !== undefined}\n\t\t\t\t\t\t\tsplit={lens.dispersion > 0}\n\t\t\t\t\t\t\tshaded={!light}\n\t\t\t\t\t\t\tclear={mode === \"copy\" || mode === \"inplace\"}\n\t\t\t\t\t\t\thole={mode === \"inplace\"}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</filter>\n\t\t\t\t</defs>\n\t\t\t</svg>\n\n\t\t\t<div\n\t\t\t\tref={frostRef}\n\t\t\t\tclassName=\"glass__frost\"\n\t\t\t\tstyle={{ display: \"none\" }}\n\t\t\t/>\n\t\t\t<div\n\t\t\t\tref={tintRef}\n\t\t\t\tclassName=\"glass__tint\"\n\t\t\t\tstyle={{ ...first.place, opacity: first.body, background: tintColor }}\n\t\t\t/>\n\t\t\t{face ? (\n\t\t\t\t<div\n\t\t\t\t\tref={faceRef}\n\t\t\t\t\tclassName=\"glass__face\"\n\t\t\t\t\tstyle={{ width, height, ...first.face }}\n\t\t\t\t>\n\t\t\t\t\t{face}\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t{light || targeted ? (\n\t\t\t\t<div\n\t\t\t\t\tref={lightRef}\n\t\t\t\t\tclassName=\"glass__light\"\n\t\t\t\t\tstyle={{ ...first.place, display: \"none\" }}\n\t\t\t\t/>\n\t\t\t) : null}\n\n\t\t\t{drawn(lens.restEdgeShadow) ? (\n\t\t\t\t<div\n\t\t\t\t\tref={restShadowRef}\n\t\t\t\t\tclassName=\"glass__rim\"\n\t\t\t\t\tstyle={{\n\t\t\t\t\t\t...first.place,\n\t\t\t\t\t\tboxShadow: lens.restEdgeShadow,\n\t\t\t\t\t\topacity: 1 - first.shadow,\n\t\t\t\t\t}}\n\t\t\t\t/>\n\t\t\t) : null}\n\n\t\t\t<div\n\t\t\t\tref={shadowRef}\n\t\t\t\tclassName=\"glass__rim\"\n\t\t\t\tstyle={{\n\t\t\t\t\t...first.place,\n\t\t\t\t\tboxShadow: [\n\t\t\t\t\t\tdrawn(lens.edgeShadow),\n\t\t\t\t\t\tinsetShadow ? `inset ${insetShadow}` : undefined,\n\t\t\t\t\t]\n\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t.join(\", \"),\n\t\t\t\t\topacity: first.shadow,\n\t\t\t\t}}\n\t\t\t/>\n\t\t</div>\n\t);\n}\n\nconst SLICES = [0, 1, 2] as const;\n\nfunction SliceImages({ name }: { name: \"map\" | \"light\" }) {\n\treturn SLICES.map((index) => (\n\t\t<feImage\n\t\t\tkey={index}\n\t\t\tdata-slice={name}\n\t\t\tpreserveAspectRatio=\"none\"\n\t\t\tresult={`${name}${index}`}\n\t\t/>\n\t));\n}\n\nfunction OnGround({\n\tground,\n\tname,\n\tpieces,\n\tresult,\n}: {\n\tground: string;\n\tname: \"map\" | \"light\";\n\tpieces: number;\n\tresult: string;\n}) {\n\treturn (\n\t\t<feMerge result={result}>\n\t\t\t<feMergeNode in={ground} />\n\t\t\t{SLICES.slice(0, pieces).map((index) => (\n\t\t\t\t<feMergeNode key={index} in={`${name}${index}`} />\n\t\t\t))}\n\t\t</feMerge>\n\t);\n}\n\nfunction LensPrimitives({\n\tdished,\n\tsliced,\n\tfrosted,\n\tlagged,\n\tsplit,\n\tshaded,\n\tclear,\n\thole,\n}: {\n\tdished: boolean;\n\tsliced: boolean;\n\tfrosted: boolean;\n\tlagged: boolean;\n\tsplit: boolean;\n\tshaded: boolean;\n\tclear: boolean;\n\t// Cut out of the source and laid into the hole: laid over a see-through\n\t// layer, the lens would double every translucent pixel.\n\thole: boolean;\n}) {\n\tconst source = lagged ? \"lagged\" : \"SourceGraphic\";\n\tconst rimSource = frosted ? \"frosted\" : source;\n\tconst bent = dished ? \"bent\" : \"refracted\";\n\t// Over a see-through source a channel bent past the content reads black,\n\t// so it falls back to the content below. Region-limited, or it runs over the whole layer.\n\tconst filled = (name: string) => (clear ? `${name}Filled` : name);\n\tconst fill = (name: string) =>\n\t\tclear ? (\n\t\t\t<feComposite\n\t\t\t\tdata-rim=\"\"\n\t\t\t\tin={name}\n\t\t\t\tin2=\"SourceGraphic\"\n\t\t\t\toperator=\"over\"\n\t\t\t\tresult={`${name}Filled`}\n\t\t\t/>\n\t\t) : null;\n\treturn (\n\t\t<>\n\t\t\t{lagged ? (\n\t\t\t\t<feOffset\n\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\tdata-pass=\"lag\"\n\t\t\t\t\tin=\"SourceGraphic\"\n\t\t\t\t\tdx={0}\n\t\t\t\t\tdy={0}\n\t\t\t\t\tresult=\"lagged\"\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t<feFlood data-reach=\"\" floodColor=\"rgb(128,128,0)\" result=\"mapGround\" />\n\t\t\t{sliced ? (\n\t\t\t\t<SliceImages name=\"map\" />\n\t\t\t) : (\n\t\t\t\t<feImage\n\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\tdata-map=\"rim\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tresult=\"map0\"\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t<OnGround\n\t\t\t\tground=\"mapGround\"\n\t\t\t\tname=\"map\"\n\t\t\t\tpieces={sliced ? 3 : 1}\n\t\t\t\tresult=\"rawRim\"\n\t\t\t/>\n\t\t\t{hole ? (\n\t\t\t\t<feColorMatrix\n\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\tin=\"rawRim\"\n\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\tvalues={OUTLINE_MATRIX}\n\t\t\t\t\tresult=\"outline\"\n\t\t\t\t/>\n\t\t\t) : null}\n\t\t\t{frosted ? (\n\t\t\t\t<>\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\t\tin=\"rawRim\"\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues={OUTLINE_MATRIX}\n\t\t\t\t\t\tresult=\"outline\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feGaussianBlur\n\t\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\t\tdata-pass=\"frost\"\n\t\t\t\t\t\tin={source}\n\t\t\t\t\t\tstdDeviation={0}\n\t\t\t\t\t\tedgeMode=\"duplicate\"\n\t\t\t\t\t\tresult=\"blurred\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\t\tdata-pass=\"saturate\"\n\t\t\t\t\t\tin=\"blurred\"\n\t\t\t\t\t\ttype=\"saturate\"\n\t\t\t\t\t\tvalues=\"1\"\n\t\t\t\t\t\tresult=\"saturated\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\t\tin=\"saturated\"\n\t\t\t\t\t\tin2=\"outline\"\n\t\t\t\t\t\toperator=\"in\"\n\t\t\t\t\t\tresult=\"frostInLens\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\t\tin=\"frostInLens\"\n\t\t\t\t\t\tin2={source}\n\t\t\t\t\t\toperator=\"over\"\n\t\t\t\t\t\tresult=\"frosted\"\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t{split ? (\n\t\t\t\t<>\n\t\t\t\t\t<feDisplacementMap\n\t\t\t\t\t\tdata-rim=\"\"\n\t\t\t\t\t\tdata-pass=\"rim\"\n\t\t\t\t\t\tin={rimSource}\n\t\t\t\t\t\tin2=\"rawRim\"\n\t\t\t\t\t\tscale={0}\n\t\t\t\t\t\txChannelSelector=\"R\"\n\t\t\t\t\t\tyChannelSelector=\"G\"\n\t\t\t\t\t\tresult=\"bentR\"\n\t\t\t\t\t/>\n\t\t\t\t\t{fill(\"bentR\")}\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tin={filled(\"bentR\")}\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues=\"1 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 1\"\n\t\t\t\t\t\tresult=\"onlyR\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feDisplacementMap\n\t\t\t\t\t\tdata-rim=\"\"\n\t\t\t\t\t\tdata-pass=\"rim\"\n\t\t\t\t\t\tin={rimSource}\n\t\t\t\t\t\tin2=\"rawRim\"\n\t\t\t\t\t\tscale={0}\n\t\t\t\t\t\txChannelSelector=\"R\"\n\t\t\t\t\t\tyChannelSelector=\"G\"\n\t\t\t\t\t\tresult=\"bentG\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tin=\"bentG\"\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues=\"0 0 0 0 0  0 1 0 0 0  0 0 0 0 0  0 0 0 0 1\"\n\t\t\t\t\t\tresult=\"onlyG\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feDisplacementMap\n\t\t\t\t\t\tdata-rim=\"\"\n\t\t\t\t\t\tdata-pass=\"rim\"\n\t\t\t\t\t\tin={rimSource}\n\t\t\t\t\t\tin2=\"rawRim\"\n\t\t\t\t\t\tscale={0}\n\t\t\t\t\t\txChannelSelector=\"R\"\n\t\t\t\t\t\tyChannelSelector=\"G\"\n\t\t\t\t\t\tresult=\"bentB\"\n\t\t\t\t\t/>\n\t\t\t\t\t{fill(\"bentB\")}\n\t\t\t\t\t<feColorMatrix\n\t\t\t\t\t\tin={filled(\"bentB\")}\n\t\t\t\t\t\ttype=\"matrix\"\n\t\t\t\t\t\tvalues=\"0 0 0 0 0  0 0 0 0 0  0 0 1 0 0  0 0 0 0 1\"\n\t\t\t\t\t\tresult=\"onlyB\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tin=\"onlyR\"\n\t\t\t\t\t\tin2=\"onlyG\"\n\t\t\t\t\t\toperator=\"arithmetic\"\n\t\t\t\t\t\tk2=\"1\"\n\t\t\t\t\t\tk3=\"1\"\n\t\t\t\t\t\tresult=\"rg\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tin=\"rg\"\n\t\t\t\t\t\tin2=\"onlyB\"\n\t\t\t\t\t\toperator=\"arithmetic\"\n\t\t\t\t\t\tk2=\"1\"\n\t\t\t\t\t\tk3=\"1\"\n\t\t\t\t\t\tresult=\"rgb\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feComposite in=\"rgb\" in2=\"bentG\" operator=\"in\" result={bent} />\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<feDisplacementMap\n\t\t\t\t\tdata-rim=\"\"\n\t\t\t\t\tdata-pass=\"rim\"\n\t\t\t\t\tin={rimSource}\n\t\t\t\t\tin2=\"rawRim\"\n\t\t\t\t\tscale={0}\n\t\t\t\t\txChannelSelector=\"R\"\n\t\t\t\t\tyChannelSelector=\"G\"\n\t\t\t\t\tresult={bent}\n\t\t\t\t/>\n\t\t\t)}\n\t\t\t{dished ? (\n\t\t\t\t<feConvolveMatrix\n\t\t\t\t\tdata-rim=\"\"\n\t\t\t\t\tdata-soften=\"\"\n\t\t\t\t\tin={bent}\n\t\t\t\t\torder=\"3\"\n\t\t\t\t\tkernelMatrix={IDENTITY_KERNEL}\n\t\t\t\t\tedgeMode=\"duplicate\"\n\t\t\t\t\tresult=\"refracted\"\n\t\t\t\t/>\n\t\t\t) : null}\n\n\t\t\t{shaded ? (\n\t\t\t\t<>\n\t\t\t\t\t<feFlood\n\t\t\t\t\t\tdata-reach=\"\"\n\t\t\t\t\t\tfloodColor=\"rgb(128,128,128)\"\n\t\t\t\t\t\tresult=\"lightGround\"\n\t\t\t\t\t/>\n\t\t\t\t\t{sliced ? (\n\t\t\t\t\t\t<SliceImages name=\"light\" />\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<feImage\n\t\t\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\t\t\tdata-map=\"light\"\n\t\t\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\t\t\tresult=\"light0\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\t\t\t\t\t<OnGround\n\t\t\t\t\t\tground=\"lightGround\"\n\t\t\t\t\t\tname=\"light\"\n\t\t\t\t\t\tpieces={sliced ? 3 : 1}\n\t\t\t\t\t\tresult=\"light\"\n\t\t\t\t\t/>\n\t\t\t\t\t{/* A blend over transparent pixels returns the light itself, so the\n\t\t\t\t\t    light is kept to what the lens bent. */}\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\t\tin=\"light\"\n\t\t\t\t\t\tin2=\"refracted\"\n\t\t\t\t\t\toperator=\"in\"\n\t\t\t\t\t\tresult=\"lightOnBent\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feBlend\n\t\t\t\t\t\tdata-lens=\"\"\n\t\t\t\t\t\tmode=\"hard-light\"\n\t\t\t\t\t\tin=\"lightOnBent\"\n\t\t\t\t\t\tin2=\"refracted\"\n\t\t\t\t\t\tresult=\"lit\"\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t\t{/* Kept even over opaque content: without it Chromium's GPU cost balloons while scrolling. */}\n\t\t\t<feComposite\n\t\t\t\tdata-lens=\"\"\n\t\t\t\tin={shaded ? \"lit\" : \"refracted\"}\n\t\t\t\tin2={hole ? \"outline\" : \"SourceGraphic\"}\n\t\t\t\toperator=\"in\"\n\t\t\t\tresult=\"lensResult\"\n\t\t\t/>\n\n\t\t\t{hole ? (\n\t\t\t\t<>\n\t\t\t\t\t<feComposite\n\t\t\t\t\t\tdata-standalone=\"\"\n\t\t\t\t\t\tin=\"SourceGraphic\"\n\t\t\t\t\t\tin2=\"outline\"\n\t\t\t\t\t\toperator=\"out\"\n\t\t\t\t\t\tresult=\"rest\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feMerge data-standalone=\"\">\n\t\t\t\t\t\t<feMergeNode in=\"rest\" />\n\t\t\t\t\t\t<feMergeNode in=\"lensResult\" />\n\t\t\t\t\t</feMerge>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<feComposite in=\"lensResult\" in2=\"SourceGraphic\" operator=\"over\" />\n\t\t\t)}\n\t\t</>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass.tsx"
    },
    {
      "path": "src/glass/glass-switch.tsx",
      "content": "\"use client\";\n\nimport {\n\ttype InputHTMLAttributes,\n\tuseCallback,\n\tuseEffect,\n\tuseId,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tGlassSwitchSurface,\n\ttype GlassSwitchSurfaceProps,\n} from \"./glass-switch-surface\";\nimport type { LensProfile } from \"./optics\";\nimport type { GlassTheme } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport type { UseGlassSwitchResult } from \"./use-glass-switch\";\n\ntype NativeProps = Omit<\n\tInputHTMLAttributes<HTMLInputElement>,\n\t\"type\" | \"onChange\" | \"size\" | \"width\" | \"height\"\n>;\n\nexport type GlassSwitchProps = NativeProps & {\n\tonCheckedChange?: (checked: boolean) => void;\n\tlabel?: string;\n\twidth?: number;\n\theight?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tsurfaceProps?: Partial<GlassSwitchSurfaceProps>;\n};\n\nexport function GlassSwitch({\n\tchecked,\n\tdefaultChecked = false,\n\tonCheckedChange,\n\tlabel,\n\twidth = 74,\n\theight = 28,\n\tlens,\n\ttheme: themeProp,\n\tdisabled,\n\tclassName,\n\tid,\n\tsurfaceProps,\n\t...inputProps\n}: GlassSwitchProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst generatedId = useId();\n\tconst inputId = id ?? generatedId;\n\tconst isControlled = checked !== undefined;\n\tconst [uncontrolled, setUncontrolled] = useState(defaultChecked);\n\tconst isChecked = Boolean(isControlled ? checked : uncontrolled);\n\n\tconst controls = useRef<UseGlassSwitchResult>(null);\n\tconst committed = useRef(isChecked);\n\tuseEffect(() => {\n\t\tcommitted.current = isChecked;\n\t}, [isChecked]);\n\n\tconst commit = useCallback(\n\t\t(next: boolean) => {\n\t\t\tcommitted.current = next;\n\t\t\tif (!isControlled) setUncontrolled(next);\n\t\t\tonCheckedChange?.(next);\n\t\t},\n\t\t[isControlled, onCheckedChange],\n\t);\n\n\treturn (\n\t\t<label\n\t\t\thtmlFor={inputId}\n\t\t\tclassName={[\"glass-switch\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tdata-theme={theme}\n\t\t>\n\t\t\t<input\n\t\t\t\t{...inputProps}\n\t\t\t\tid={inputId}\n\t\t\t\ttype=\"checkbox\"\n\t\t\t\trole=\"switch\"\n\t\t\t\taria-checked={isChecked}\n\t\t\t\tclassName=\"glass-switch__input\"\n\t\t\t\tchecked={isChecked}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tonChange={(event) => {\n\t\t\t\t\tif (controls.current?.consumeDragGuard()) {\n\t\t\t\t\t\tevent.currentTarget.checked = committed.current;\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tcommit(event.currentTarget.checked);\n\t\t\t\t\tcontrols.current?.flash();\n\t\t\t\t}}\n\t\t\t/>\n\n\t\t\t<GlassSwitchSurface\n\t\t\t\t{...surfaceProps}\n\t\t\t\tchecked={isChecked}\n\t\t\t\tonCheckedChange={commit}\n\t\t\t\twidth={width}\n\t\t\t\theight={height}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tlens={lens}\n\t\t\t\ttheme={theme}\n\t\t\t\tcontrolsRef={controls}\n\t\t\t/>\n\t\t\t{label ? <span className=\"glass-switch__label\">{label}</span> : null}\n\t\t</label>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-switch.tsx"
    },
    {
      "path": "src/glass/glass-segmented.css",
      "content": ".glass-segmented {\n\tdisplay: inline-block;\n\t-webkit-tap-highlight-color: transparent;\n}\n\n.glass-segmented__box {\n\tposition: relative;\n\tdisplay: inline-block;\n\ttouch-action: pan-y;\n\t-webkit-user-select: none;\n\tuser-select: none;\n\t--toggle-track: color(display-p3 0.93 0.928 0.932);\n\t--toggle-label: rgb(0 0 0 / 0.55);\n\t--toggle-selected: rgb(0 0 0 / 0.92);\n\t--toggle-divider: rgb(0 0 0 / 0.12);\n\t--toggle-focus: var(--glass-accent, #7774ff);\n\t--glass-body: #fff;\n}\n\n.glass-segmented__box[data-theme=\"dark\"] {\n\t--toggle-track: color(display-p3 0.19 0.19 0.21);\n\t--toggle-label: rgb(255 255 255 / 0.6);\n\t--toggle-divider: rgb(255 255 255 / 0.16);\n\t--toggle-selected: rgb(255 255 255 / 0.95);\n\t--glass-body: #1b1b1f;\n}\n\n.glass-segmented__row {\n\tposition: relative;\n\tdisplay: grid;\n\tgrid-auto-flow: column;\n\tgrid-auto-columns: 1fr;\n\tbox-sizing: border-box;\n\talign-items: center;\n\twidth: fit-content;\n\tbackground: var(--toggle-track);\n\tborder-radius: calc(var(--toggle-height) / 2);\n}\n\n.glass-segmented__option {\n\tpadding: 0 18px;\n\tfont: 600 13px / 1 var(--font-sans, inherit);\n\tcolor: var(--toggle-label);\n\ttext-align: center;\n\twhite-space: nowrap;\n\t-webkit-user-select: none;\n\tuser-select: none;\n}\n\n.glass-segmented__row:not([data-highlighted])\n\t.glass-segmented__option[data-selected] {\n\topacity: calc(1 - var(--segment-rest, 0));\n}\n\n.glass-segmented__box:not([data-measured])\n\t.glass-segmented__option[data-selected] {\n\tposition: relative;\n\tz-index: 0;\n\tcolor: var(--toggle-selected);\n\topacity: 1;\n}\n\n.glass-segmented__box:not([data-measured])\n\t.glass-segmented__option[data-selected]::before {\n\tposition: absolute;\n\ttop: 50%;\n\tright: 0;\n\tleft: 0;\n\tz-index: -1;\n\theight: var(--segment-pill);\n\tcontent: \"\";\n\tbackground: var(--glass-body);\n\tborder-radius: 999px;\n\tbox-shadow: var(--segment-shadow);\n\ttransform: translateY(-50%);\n}\n\n.glass-segmented__row[data-highlighted] {\n\tbackground: transparent;\n}\n\n.glass-segmented__row[data-highlighted] .glass-segmented__option {\n\tcolor: var(--toggle-selected);\n}\n\n.glass-segmented__divider {\n\tposition: absolute;\n\ttop: 0;\n\tbottom: 0;\n\twidth: 1px;\n\tbackground: var(--toggle-divider);\n\ttransform: translateX(-0.5px);\n}\n\n.glass-segmented__glass {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tpointer-events: none;\n}\n\n.glass-segmented__hit {\n\tposition: absolute;\n\ttop: 0;\n\tz-index: 1;\n\theight: 100%;\n\tpadding: 0;\n\tbackground: none;\n\tborder: 0;\n\tcursor: pointer;\n}\n\n.glass-segmented__input,\n.glass-segmented__hit-label {\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tmargin: -1px;\n\tpadding: 0;\n\toverflow: hidden;\n\tclip-path: inset(50%);\n\twhite-space: nowrap;\n\tborder: 0;\n}\n\n.glass-segmented__input:focus-visible ~ .glass-segmented__hit-label {\n\tposition: absolute;\n\tinset: 0;\n\twidth: auto;\n\theight: auto;\n\tmargin: 0;\n\toverflow: visible;\n\tclip-path: none;\n\tcolor: transparent;\n\tborder-radius: calc(var(--toggle-height) / 2);\n\toutline: 2px solid var(--toggle-focus);\n\toutline-offset: 2px;\n}\n\n.glass-segmented__hit:focus-visible {\n\tborder-radius: calc(var(--toggle-height) / 2);\n\toutline: 2px solid var(--toggle-focus);\n\toutline-offset: 2px;\n}\n\n.glass-segmented__hit:disabled {\n\tcursor: not-allowed;\n\topacity: 0.5;\n}\n\n.glass-segmented[data-disabled],\n.glass-segmented__box[data-disabled] {\n\tcursor: not-allowed;\n\topacity: 0.48;\n}\n\n.glass-segmented[data-disabled] .glass-segmented__hit {\n\tcursor: not-allowed;\n}\n",
      "type": "registry:file",
      "target": "@components/liquikit/glass/glass-segmented.css"
    },
    {
      "path": "src/glass/glass-pane.css",
      "content": ".glass-pane {\n\tposition: relative;\n\tdisplay: inline-block;\n\tisolation: isolate;\n\tcolor: var(--glass-pane-ink);\n}\n\n/* The defaults weigh nothing, so an app's own tint wins whichever stylesheet\n   loads first. */\n:where(.glass-pane) {\n\t--glass-pane-tint: #fff;\n\t--glass-pane-ink: rgb(0 0 0 / 0.88);\n}\n\n:where(.glass-pane[data-theme=\"dark\"]) {\n\t--glass-pane-tint: #2a2a2e;\n\t--glass-pane-ink: rgb(255 255 255 / 0.92);\n}\n\n.glass-pane__glass {\n\tposition: absolute;\n\tpointer-events: none;\n}\n\n.glass-pane__content {\n\tposition: relative;\n}\n\n.glass-pane:not([data-drawn])::before,\n.glass-pane:not([data-drawn])::after {\n\tposition: absolute;\n\tinset: 0;\n\tz-index: -1;\n\tcontent: \"\";\n\tborder-radius: inherit;\n\tpointer-events: none;\n}\n\n.glass-pane:not([data-drawn])::before {\n\t-webkit-backdrop-filter: var(--glass-pane-frost);\n\tbackdrop-filter: var(--glass-pane-frost);\n\tbox-shadow: var(--glass-pane-shadow);\n}\n\n.glass-pane:not([data-drawn])::after {\n\tbackground: var(--glass-pane-fill);\n\topacity: var(--glass-pane-fill-opacity);\n}\n\n.glass-pane[data-shaped]:not([data-drawn])::before,\n.glass-pane[data-shaped]:not([data-drawn])::after {\n\tcontent: none;\n}\n\n.glass-pane__lenses {\n\tposition: absolute;\n\tinset: 0;\n\toverflow: hidden;\n\tpointer-events: none;\n\tborder-radius: inherit;\n}\n\n/* The copy only approximates the pane, so its edges fade into it. */\n.glass-pane__lenses .glass-scope__lens {\n\tz-index: auto;\n\t-webkit-mask:\n\t\tlinear-gradient(\n\t\t\tto right,\n\t\t\ttransparent,\n\t\t\t#000 8px,\n\t\t\t#000 calc(100% - 8px),\n\t\t\ttransparent\n\t\t),\n\t\tlinear-gradient(\n\t\t\tto bottom,\n\t\t\ttransparent,\n\t\t\t#000 8px,\n\t\t\t#000 calc(100% - 8px),\n\t\t\ttransparent\n\t\t);\n\t-webkit-mask-composite: source-in;\n\tmask:\n\t\tlinear-gradient(\n\t\t\tto right,\n\t\t\ttransparent,\n\t\t\t#000 8px,\n\t\t\t#000 calc(100% - 8px),\n\t\t\ttransparent\n\t\t),\n\t\tlinear-gradient(\n\t\t\tto bottom,\n\t\t\ttransparent,\n\t\t\t#000 8px,\n\t\t\t#000 calc(100% - 8px),\n\t\t\ttransparent\n\t\t);\n\tmask-composite: intersect;\n}\n\n.glass-pane__lenses .glass-scope__lens::after {\n\tposition: absolute;\n\tinset: 0;\n\tcontent: \"\";\n\tbackground: var(--lens-tint);\n\topacity: var(--lens-tint-opacity, 0);\n}\n",
      "type": "registry:file",
      "target": "@components/liquikit/glass/glass-pane.css"
    },
    {
      "path": "src/glass/glass-switch-surface.tsx",
      "content": "\"use client\";\n\nimport { motion } from \"motion/react\";\nimport {\n\ttype CSSProperties,\n\ttype HTMLAttributes,\n\ttype Ref,\n\tuseImperativeHandle,\n} from \"react\";\nimport { Glass } from \"./glass\";\nimport \"./glass-switch.css\";\nimport type { LensProfile } from \"./optics\";\nimport { type GlassTheme, switchLens, useLens } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport { type UseGlassSwitchResult, useGlassSwitch } from \"./use-glass-switch\";\n\nexport type GlassSwitchSurfaceProps = Omit<\n\tHTMLAttributes<HTMLSpanElement>,\n\t\"onChange\" | \"children\"\n> & {\n\tchecked: boolean;\n\tonCheckedChange?: (checked: boolean) => void;\n\twidth?: number;\n\theight?: number;\n\tdisabled?: boolean;\n\tdraggable?: boolean;\n\tliquid?: number;\n\tlens?: Partial<LensProfile>;\n\ttheme?: GlassTheme;\n\tref?: Ref<HTMLSpanElement>;\n\tcontrolsRef?: Ref<UseGlassSwitchResult>;\n};\n\nexport function GlassSwitchSurface({\n\tchecked,\n\tonCheckedChange,\n\twidth = 74,\n\theight = 28,\n\tdisabled,\n\tdraggable,\n\tliquid,\n\tlens: lensOverrides,\n\ttheme: themeProp,\n\tclassName,\n\tstyle,\n\tref,\n\tcontrolsRef,\n\t...rest\n}: GlassSwitchSurfaceProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst lens = useLens(theme, lensOverrides, switchLens);\n\tconst controls = useGlassSwitch({\n\t\tchecked,\n\t\tonCheckedChange,\n\t\twidth,\n\t\theight,\n\t\tdisabled,\n\t\tdraggable,\n\t\tliquid,\n\t});\n\tconst { geometry, lensProps, thumbProps, rootRef, trackRef, rootStyle } =\n\t\tcontrols;\n\n\tuseImperativeHandle(controlsRef, () => controls, [controls]);\n\n\treturn (\n\t\t<span\n\t\t\t{...rest}\n\t\t\tref={(element) => {\n\t\t\t\trootRef.current = element;\n\t\t\t\tif (typeof ref === \"function\") ref(element);\n\t\t\t\telse if (ref) ref.current = element;\n\t\t\t}}\n\t\t\tclassName={[\"glass-switch__box\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-theme={theme}\n\t\t\tdata-disabled={disabled ? \"\" : undefined}\n\t\t\tstyle={{ ...rootStyle, ...style, width, height } as CSSProperties}\n\t\t>\n\t\t\t<Glass\n\t\t\t\tclassName=\"glass-switch__glass\"\n\t\t\t\t{...lensProps}\n\t\t\t\tstyle={{ margin: -geometry.margin }}\n\t\t\t\tlens={lens}\n\t\t\t\trefractionTarget={\n\t\t\t\t\t<div style={{ padding: geometry.margin }}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName=\"glass-switch__track\"\n\t\t\t\t\t\t\tstyle={{ width, height, borderRadius: height / 2 }}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t>\n\t\t\t\t<div style={{ padding: geometry.margin }}>\n\t\t\t\t\t<div\n\t\t\t\t\t\tref={(element) => {\n\t\t\t\t\t\t\ttrackRef.current = element;\n\t\t\t\t\t\t}}\n\t\t\t\t\t\tclassName=\"glass-switch__track\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\tstyle={{ width, height, borderRadius: height / 2 }}\n\t\t\t\t\t>\n\t\t\t\t\t\t<motion.span\n\t\t\t\t\t\t\tclassName=\"glass-switch__thumb-area\"\n\t\t\t\t\t\t\t{...thumbProps}\n\t\t\t\t\t\t\tstyle={{\n\t\t\t\t\t\t\t\t...thumbProps.style,\n\t\t\t\t\t\t\t\twidth: geometry.thumbWidth,\n\t\t\t\t\t\t\t\theight: geometry.thumbHeight,\n\t\t\t\t\t\t\t\ttop: geometry.inset,\n\t\t\t\t\t\t\t\tleft: geometry.inset,\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</Glass>\n\t\t</span>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-switch-surface.tsx"
    },
    {
      "path": "src/glass/settle.ts",
      "content": "import { type RefObject, useEffect, useState } from \"react\";\n\nconst SCROLL_SETTLE_MS = 160;\n\nlet scrolling = false;\nlet listening = false;\nlet timer: ReturnType<typeof setTimeout> | undefined;\nconst waiting = new Set<() => void>();\n\nfunction onScroll() {\n\tscrolling = true;\n\tclearTimeout(timer);\n\ttimer = setTimeout(() => {\n\t\tscrolling = false;\n\t\trequestAnimationFrame(drain);\n\t}, SCROLL_SETTLE_MS);\n}\n\nfunction drain() {\n\tif (scrolling) return;\n\tconst [task] = waiting;\n\tif (!task) return;\n\twaiting.delete(task);\n\ttask();\n\trequestAnimationFrame(drain);\n}\n\nexport function afterScroll(task: () => void) {\n\tif (!listening) {\n\t\tlistening = true;\n\t\twindow.addEventListener(\"scroll\", onScroll, {\n\t\t\tcapture: true,\n\t\t\tpassive: true,\n\t\t});\n\t}\n\tif (!scrolling) {\n\t\ttask();\n\t\treturn () => {};\n\t}\n\twaiting.add(task);\n\treturn () => {\n\t\twaiting.delete(task);\n\t};\n}\n\nexport function useInView(\n\tref: RefObject<Element | null>,\n\tmargin: string,\n\tenabled: boolean,\n) {\n\tconst [inView, setInView] = useState(false);\n\tuseEffect(() => {\n\t\tconst element = ref.current;\n\t\tif (!enabled || !element || typeof IntersectionObserver === \"undefined\") {\n\t\t\treturn;\n\t\t}\n\t\tconst observer = new IntersectionObserver(\n\t\t\t([entry]) => setInView(entry.isIntersecting),\n\t\t\t{ rootMargin: margin },\n\t\t);\n\t\tobserver.observe(element);\n\t\treturn () => observer.disconnect();\n\t}, [enabled, margin, ref]);\n\treturn inView;\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/settle.ts"
    },
    {
      "path": "src/glass/glass-slider-surface.tsx",
      "content": "\"use client\";\n\nimport {\n\ttype CSSProperties,\n\ttype HTMLAttributes,\n\ttype ReactNode,\n\ttype Ref,\n\tuseImperativeHandle,\n\tuseLayoutEffect,\n\tuseState,\n} from \"react\";\nimport { Glass } from \"./glass\";\nimport \"./glass-slider.css\";\nimport type { LensProfile } from \"./optics\";\nimport { type GlassTheme, sliderLens, useLens } from \"./presets\";\nimport { useGlassTheme } from \"./theme\";\nimport {\n\ttype UseGlassSliderOptions,\n\ttype UseGlassSliderResult,\n\tuseGlassSlider,\n} from \"./use-glass-slider\";\n\nexport type GlassSliderSurfaceProps = Omit<\n\tHTMLAttributes<HTMLSpanElement>,\n\t\"onChange\" | \"children\" | \"defaultValue\"\n> &\n\tUseGlassSliderOptions & {\n\t\tlens?: Partial<LensProfile>;\n\t\ttheme?: GlassTheme;\n\t\tref?: Ref<HTMLSpanElement>;\n\t\toverlay?: ReactNode;\n\t\tcontrolsRef?: Ref<UseGlassSliderResult>;\n\t};\n\n// What a slider with no width is laid out at before it has measured itself.\nconst FALLBACK_WIDTH = 240;\n\nexport function GlassSliderSurface({\n\tlens: lensOverrides,\n\ttheme: themeProp,\n\tclassName,\n\tstyle,\n\tref,\n\toverlay,\n\tcontrolsRef,\n\t...options\n}: GlassSliderSurfaceProps) {\n\tconst theme = useGlassTheme(themeProp);\n\tconst lens = useLens(theme, lensOverrides, sliderLens);\n\t// With no width the slider fills its container, at the width it measures.\n\tconst fluid = options.width === undefined;\n\tconst [measured, setMeasured] = useState<number | null>(null);\n\tconst controls = useGlassSlider({\n\t\t...options,\n\t\twidth: options.width ?? measured ?? FALLBACK_WIDTH,\n\t});\n\tconst { geometry, lensProps, trackProps, rootRef, hitRef, rootStyle } =\n\t\tcontrols;\n\tuseImperativeHandle(controlsRef, () => controls, [controls]);\n\tconst { width, thumbWidth, thumbHeight, trackHeight, margin } = geometry;\n\n\tuseLayoutEffect(() => {\n\t\tconst box = rootRef.current;\n\t\tif (!fluid || !box) return;\n\t\t// Layout width, so a scaled ancestor, such as a popup growing in, is\n\t\t// measured at its real size.\n\t\tconst measure = () => {\n\t\t\tif (box.offsetWidth > 0) setMeasured(box.offsetWidth);\n\t\t};\n\t\tmeasure();\n\t\tconst observer = new ResizeObserver(measure);\n\t\tobserver.observe(box);\n\t\treturn () => observer.disconnect();\n\t}, [fluid, rootRef]);\n\n\tconst track = (\n\t\t<div\n\t\t\tclassName=\"glass-slider__track\"\n\t\t\tstyle={{ height: trackHeight, borderRadius: trackHeight / 2 }}\n\t\t>\n\t\t\t<div className=\"glass-slider__track-fill\" />\n\t\t</div>\n\t);\n\n\treturn (\n\t\t<span\n\t\t\tref={(element) => {\n\t\t\t\trootRef.current = element;\n\t\t\t\tif (typeof ref === \"function\") ref(element);\n\t\t\t\telse if (ref) ref.current = element;\n\t\t\t}}\n\t\t\tclassName={[\"glass-slider__box\", className].filter(Boolean).join(\" \")}\n\t\t\tdata-theme={theme}\n\t\t\tdata-disabled={options.disabled ? \"\" : undefined}\n\t\t\tstyle={\n\t\t\t\t{\n\t\t\t\t\t...rootStyle,\n\t\t\t\t\t...style,\n\t\t\t\t\twidth: fluid ? undefined : width,\n\t\t\t\t\theight: thumbHeight,\n\t\t\t\t\t\"--slider-thumb-width\": `${thumbWidth}px`,\n\t\t\t\t} as CSSProperties\n\t\t\t}\n\t\t>\n\t\t\t{fluid && measured === null ? (\n\t\t\t\t<>\n\t\t\t\t\t<div className=\"glass-slider__row\" style={{ height: thumbHeight }}>\n\t\t\t\t\t\t{track}\n\t\t\t\t\t</div>\n\t\t\t\t\t<span\n\t\t\t\t\t\tclassName=\"glass-slider__rest\"\n\t\t\t\t\t\tstyle={{ boxShadow: lens.restEdgeShadow }}\n\t\t\t\t\t/>\n\t\t\t\t</>\n\t\t\t) : (\n\t\t\t\t<Glass\n\t\t\t\t\tclassName=\"glass-slider__glass\"\n\t\t\t\t\t{...lensProps}\n\t\t\t\t\tstyle={{ margin: -margin }}\n\t\t\t\t\tlens={lens}\n\t\t\t\t\trefractionTarget={\n\t\t\t\t\t\t<div style={{ padding: margin }}>\n\t\t\t\t\t\t\t<div\n\t\t\t\t\t\t\t\tclassName=\"glass-slider__row\"\n\t\t\t\t\t\t\t\tstyle={{ width, height: thumbHeight }}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{track}\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t\t\t<div style={{ padding: margin }}>\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tref={(element) => {\n\t\t\t\t\t\t\t\thitRef.current = element;\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\tclassName=\"glass-slider__row glass-slider__hit\"\n\t\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t\t\tstyle={{ width, height: thumbHeight }}\n\t\t\t\t\t\t\t{...trackProps}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{track}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</Glass>\n\t\t\t)}\n\t\t\t{overlay}\n\t\t</span>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/glass/glass-slider-surface.tsx"
    }
  ],
  "type": "registry:lib"
}