{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popup",
  "title": "Popup",
  "description": "The morphing glass panel behind every popup.",
  "dependencies": [
    "motion@^13.4.4"
  ],
  "registryDependencies": [
    "https://liquikit.dev/r/glass.json"
  ],
  "files": [
    {
      "path": "src/popup.tsx",
      "content": "\"use client\";\n\nimport {\n\ttype AnimationPlaybackControls,\n\tanimate,\n\tmotion,\n\tuseMotionValue,\n\tuseReducedMotion,\n\tuseTransform,\n} from \"motion/react\";\nimport {\n\tcreateContext,\n\ttype ReactNode,\n\ttype Ref,\n\ttype RefObject,\n\tuseCallback,\n\tuseContext,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseMemo,\n\tuseRef,\n\tuseState,\n} from \"react\";\nimport {\n\tGlassPane,\n\ttype GlassPaneProps,\n\ttype GlassPaneReach,\n\ttype GlassRefraction,\n\ttype GlassTheme,\n\thideGlass,\n\tlandGlass,\n\tuseDerived,\n} from \"./glass\";\n\nexport const PopupState = createContext<{\n\topen: boolean;\n\ttrigger: RefObject<HTMLElement | null>;\n\tpoint?: RefObject<{ x: number; y: number } | null>;\n} | null>(null);\n\nexport type GlassHandoff = {\n\tpanel: { current: { rect: DOMRect; radius: number; at: number } | null };\n\topen: { current: number };\n};\nexport const Handoff = createContext<GlassHandoff | null>(null);\n\nexport function usePopupState() {\n\tconst state = useContext(PopupState);\n\tif (!state) throw new Error(\"A glass popup must be inside its Root.\");\n\treturn state;\n}\n\nconst LIFT = { type: \"spring\", visualDuration: 0.16, bounce: 0.2 } as const;\nconst TRAVEL = { type: \"spring\", visualDuration: 0.3, bounce: 0.22 } as const;\nconst LEAD = {\n\ttype: \"spring\",\n\tvisualDuration: 0.36,\n\tbounce: 0.3,\n\tdelay: 0.035,\n} as const;\nconst TRAIL = {\n\ttype: \"spring\",\n\tvisualDuration: 0.4,\n\tbounce: 0.34,\n\tdelay: 0.065,\n} as const;\nconst HANDOVER = {\n\ttype: \"spring\",\n\tvisualDuration: 0.38,\n\tbounce: 0.14,\n} as const;\nconst HANDOVER_MS = 250;\nconst BACK = { type: \"spring\", visualDuration: 0.26, bounce: 0.12 } as const;\nconst HOMEWARD = {\n\ttype: \"spring\",\n\tvisualDuration: 0.28,\n\tbounce: 0.15,\n\tdelay: 0.03,\n} as const;\nconst SETTLE = {\n\ttype: \"spring\",\n\tvisualDuration: 0.2,\n\tbounce: 0.2,\n\tdelay: 0.09,\n} as const;\nconst HOME = 0.05;\nconst FADE_START = 0.55;\nconst FADE_END = 0.12;\nconst HOLD_MS = 1000;\nconst DROP = 1.35;\nconst SEED = 0.3;\nconst SWELL = { type: \"spring\", visualDuration: 0.36, bounce: 0.3 } as const;\nconst SWELL_LAG = 0.016;\nconst POINT_SEED = 14;\nconst ISLAND = { width: 120, height: 34 };\nconst CONTENT_BLUR = 10;\nconst CONTENT_SCALE = 0.9;\nconst GLOW = 0.6;\nconst FLIGHT_FROST = 0.3;\n\nconst NO_REACH: GlassPaneReach = { top: 0, right: 0, bottom: 0, left: 0 };\n\ntype Box = {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n\tradius: number;\n};\nconst EMPTY: Box = { x: 0, y: 0, width: 0, height: 0, radius: 0 };\n\nconst lerp = (from: number, to: number, t: number) => from + (to - from) * t;\nconst clamp01 = (value: number) => Math.min(1, Math.max(0, value));\nconst smoothstep = (from: number, to: number, value: number) => {\n\tconst t = clamp01((value - from) / (to - from));\n\treturn t * t * (3 - 2 * t);\n};\n\nfunction absorb(trigger: HTMLElement | null, absorbed: boolean) {\n\tif (!trigger) return;\n\tif (absorbed) trigger.setAttribute(\"data-absorbed\", \"\");\n\telse trigger.removeAttribute(\"data-absorbed\");\n\thideGlass(trigger, absorbed);\n}\n\nexport type MorphOrigin = \"trigger\" | \"centre\" | \"top\" | \"point\";\n\nexport type MorphPaneProps = Omit<GlassPaneProps, \"shape\" | \"reach\"> & {\n\tpanelRadius?: number;\n\torigin?: MorphOrigin;\n\ttheme?: GlassTheme;\n\trefraction?: GlassRefraction;\n\tref?: Ref<HTMLDivElement>;\n\tchildren?: ReactNode;\n};\n\nexport function MorphPane({\n\tpanelRadius = 22,\n\torigin = \"trigger\",\n\ttheme,\n\trefraction,\n\tref,\n\tchildren,\n\t...paneProps\n}: MorphPaneProps) {\n\tconst { open, trigger, point } = usePopupState();\n\tconst handoff = useContext(Handoff);\n\tconst reduceMotion = useReducedMotion() ?? false;\n\tconst paneRef = useRef<HTMLDivElement | null>(null);\n\tconst contentRef = useRef<HTMLDivElement | null>(null);\n\tconst from = useRef<Box>(EMPTY);\n\tconst to = useRef<Box>(EMPTY);\n\tconst drop = useRef({ width: 0, height: 0 });\n\tconst seeded = useRef(false);\n\tconst handedOver = useRef(false);\n\tconst running = useRef<AnimationPlaybackControls[]>([]);\n\tconst covers = useRef(false);\n\tconst absorbed = useRef(false);\n\tconst hold = useRef<Animation | null>(null);\n\tconst home = useRef<() => void>(() => {});\n\tconst [reach, setReach] = useState<GlassPaneReach>(NO_REACH);\n\n\tconst lift = useMotionValue(0);\n\tconst travel = useMotionValue(0);\n\tconst wide = useMotionValue(0);\n\tconst tall = useMotionValue(0);\n\tconst resized = useMotionValue(0);\n\n\tconst x = useDerived([travel, resized], ([t]) =>\n\t\tlerp(from.current.x, to.current.x, t),\n\t);\n\tconst y = useDerived([travel, resized], ([t]) =>\n\t\tlerp(from.current.y, to.current.y, t),\n\t);\n\tconst width = useDerived([lift, wide, resized], ([l, g]) =>\n\t\tMath.max(\n\t\t\t0,\n\t\t\tlerp(\n\t\t\t\tlerp(from.current.width, drop.current.width, l),\n\t\t\t\tto.current.width,\n\t\t\t\tg,\n\t\t\t),\n\t\t),\n\t);\n\tconst height = useDerived([lift, tall, resized], ([l, g]) =>\n\t\tMath.max(\n\t\t\t0,\n\t\t\tlerp(\n\t\t\t\tlerp(from.current.height, drop.current.height, l),\n\t\t\t\tto.current.height,\n\t\t\t\tg,\n\t\t\t),\n\t\t),\n\t);\n\tconst landed = useDerived([wide, tall], ([a, b]) => Math.min(a, b));\n\tconst radius = useDerived([width, height, landed], ([w, h, g]) => {\n\t\tconst round = Math.min(w, h) / 2;\n\t\tif (handedOver.current) {\n\t\t\treturn Math.min(round, lerp(from.current.radius, to.current.radius, g));\n\t\t}\n\t\treturn Math.min(\n\t\t\tround,\n\t\t\tlerp(round, to.current.radius, smoothstep(0.35, 0.95, g)),\n\t\t);\n\t});\n\tconst shape = useMemo(\n\t\t() => ({ x, y, width, height, radius }),\n\t\t[height, radius, width, x, y],\n\t);\n\tconst glow = useDerived([lift, landed], ([l, g]) =>\n\t\tseeded.current || handedOver.current\n\t\t\t? 0\n\t\t\t: GLOW * l * (1 - smoothstep(0.3, 1, g)),\n\t);\n\n\tconst frost = useDerived([landed], ([g]) =>\n\t\thandedOver.current ? 1 : lerp(FLIGHT_FROST, 1, smoothstep(0.2, 0.9, g)),\n\t);\n\n\tconst focus = useTransform(landed, (g) =>\n\t\thandedOver.current ? clamp01(g / 0.6) : clamp01((g - 0.4) / 0.5),\n\t);\n\tconst contentOpacity = useTransform(landed, (g) =>\n\t\thandedOver.current ? clamp01(g / 0.3) : clamp01((g - 0.4) / 0.25),\n\t);\n\tconst contentFilter = useTransform(focus, (f) =>\n\t\tf > 0.97 ? \"none\" : `blur(${((1 - f) * CONTENT_BLUR).toFixed(2)}px)`,\n\t);\n\tconst contentScale = useTransform(focus, (f) => lerp(CONTENT_SCALE, 1, f));\n\n\tuseLayoutEffect(() => {\n\t\tif (!handoff || !open) return;\n\t\thandoff.open.current += 1;\n\t\treturn () => {\n\t\t\thandoff.open.current -= 1;\n\t\t};\n\t}, [handoff, open]);\n\n\tconst measureTrigger = useCallback(\n\t\t(pane: HTMLElement) => {\n\t\t\tconst source = trigger.current?.getBoundingClientRect();\n\t\t\tif (!source) return false;\n\t\t\tconst box = pane.getBoundingClientRect();\n\t\t\tconst scale = pane.offsetWidth > 0 ? box.width / pane.offsetWidth : 1;\n\t\t\tconst left = (source.left - box.left) / scale;\n\t\t\tconst top = (source.top - box.top) / scale;\n\t\t\tconst w = source.width / scale;\n\t\t\tconst h = source.height / scale;\n\t\t\tconst panel = to.current;\n\t\t\tfrom.current = {\n\t\t\t\tx: left + w / 2,\n\t\t\t\ty: top + h / 2,\n\t\t\t\twidth: w,\n\t\t\t\theight: h,\n\t\t\t\tradius: h / 2,\n\t\t\t};\n\t\t\tconst size = Math.min(h * DROP, panel.width, panel.height);\n\t\t\tdrop.current = { width: size, height: size };\n\t\t\tcovers.current = true;\n\t\t\tconst spare = 8;\n\t\t\tconst reachX = Math.max(w, size) / 2;\n\t\t\tconst reachY = Math.max(h, size) / 2;\n\t\t\tsetReach({\n\t\t\t\tleft: Math.max(0, reachX - from.current.x) + spare,\n\t\t\t\ttop: Math.max(0, reachY - from.current.y) + spare,\n\t\t\t\tright: Math.max(0, from.current.x + reachX - panel.width) + spare,\n\t\t\t\tbottom: Math.max(0, from.current.y + reachY - panel.height) + spare,\n\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t\t[trigger],\n\t);\n\n\tuseLayoutEffect(() => {\n\t\tif (!open) return;\n\t\thold.current?.cancel();\n\t\thold.current = null;\n\t\thome.current();\n\t\tif (paneRef.current) {\n\t\t\tpaneRef.current.style.minWidth = \"\";\n\t\t\tpaneRef.current.style.minHeight = \"\";\n\t\t\tpaneRef.current.style.opacity = \"\";\n\t\t}\n\t\tlet frame = requestAnimationFrame(() => {\n\t\t\tframe = 0;\n\t\t\tconst pane = paneRef.current;\n\t\t\tif (!pane) return;\n\t\t\tconst box = pane.getBoundingClientRect();\n\t\t\tconst scale = pane.offsetWidth > 0 ? box.width / pane.offsetWidth : 1;\n\t\t\tconst panel = {\n\t\t\t\tx: pane.offsetWidth / 2,\n\t\t\t\ty: pane.offsetHeight / 2,\n\t\t\t\twidth: pane.offsetWidth,\n\t\t\t\theight: pane.offsetHeight,\n\t\t\t\tradius: panelRadius,\n\t\t\t};\n\t\t\tto.current = panel;\n\t\t\tconst source =\n\t\t\t\torigin === \"trigger\" ? trigger.current?.getBoundingClientRect() : null;\n\t\t\tconst at = origin === \"point\" ? point?.current : null;\n\t\t\tconst pointer = at\n\t\t\t\t? {\n\t\t\t\t\t\tx: Math.min(Math.max((at.x - box.left) / scale, 0), panel.width),\n\t\t\t\t\t\ty: Math.min(Math.max((at.y - box.top) / scale, 0), panel.height),\n\t\t\t\t\t}\n\t\t\t\t: null;\n\t\t\tif (reduceMotion) {\n\t\t\t\tfrom.current = panel;\n\t\t\t\tdrop.current = { width: panel.width, height: panel.height };\n\t\t\t\tcovers.current = false;\n\t\t\t\tseeded.current = false;\n\t\t\t\tfor (const value of [lift, travel, wide, tall]) value.set(1);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst prior = handoff?.panel.current;\n\t\t\tif (handoff && prior && performance.now() - prior.at < HANDOVER_MS) {\n\t\t\t\thandoff.panel.current = null;\n\t\t\t\tconst w = prior.rect.width / scale;\n\t\t\t\tconst h = prior.rect.height / scale;\n\t\t\t\tfrom.current = {\n\t\t\t\t\tx: (prior.rect.left - box.left) / scale + w / 2,\n\t\t\t\t\ty: (prior.rect.top - box.top) / scale + h / 2,\n\t\t\t\t\twidth: w,\n\t\t\t\t\theight: h,\n\t\t\t\t\tradius: prior.radius,\n\t\t\t\t};\n\t\t\t\tdrop.current = { width: w, height: h };\n\t\t\t\thandedOver.current = true;\n\t\t\t\tseeded.current = false;\n\t\t\t\tcovers.current = false;\n\t\t\t\tconst spare = 8;\n\t\t\t\tsetReach({\n\t\t\t\t\tleft: Math.max(0, w / 2 - from.current.x) + spare,\n\t\t\t\t\ttop: Math.max(0, h / 2 - from.current.y) + spare,\n\t\t\t\t\tright: Math.max(0, from.current.x + w / 2 - panel.width) + spare,\n\t\t\t\t\tbottom: Math.max(0, from.current.y + h / 2 - panel.height) + spare,\n\t\t\t\t});\n\t\t\t\tconst content = contentRef.current;\n\t\t\t\tif (content) {\n\t\t\t\t\tcontent.style.transformOrigin = `${from.current.x}px ${from.current.y}px`;\n\t\t\t\t}\n\t\t\t\tlift.set(1);\n\t\t\t\tfor (const value of [travel, wide, tall]) {\n\t\t\t\t\tanimate(value, 1, HANDOVER);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thandedOver.current = false;\n\t\t\tif (!source) {\n\t\t\t\tconst seed =\n\t\t\t\t\torigin === \"top\"\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tx: panel.x,\n\t\t\t\t\t\t\t\ty: ISLAND.height / 2,\n\t\t\t\t\t\t\t\twidth: Math.min(ISLAND.width, panel.width * 0.6),\n\t\t\t\t\t\t\t\theight: Math.min(ISLAND.height, panel.height),\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: pointer\n\t\t\t\t\t\t\t? { ...pointer, width: POINT_SEED, height: POINT_SEED }\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tx: panel.x,\n\t\t\t\t\t\t\t\t\ty: panel.y,\n\t\t\t\t\t\t\t\t\twidth: panel.width * SEED,\n\t\t\t\t\t\t\t\t\theight: panel.height * SEED,\n\t\t\t\t\t\t\t\t};\n\t\t\t\tfrom.current = { ...seed, radius: seed.height / 2 };\n\t\t\t\tdrop.current = { width: seed.width, height: seed.height };\n\t\t\t\tseeded.current = true;\n\t\t\t\tcovers.current = false;\n\t\t\t\tsetReach(NO_REACH);\n\t\t\t\tconst content = contentRef.current;\n\t\t\t\tif (content) {\n\t\t\t\t\tcontent.style.transformOrigin = `${seed.x}px ${seed.y}px`;\n\t\t\t\t}\n\t\t\t\tlift.set(1);\n\t\t\t\tanimate(travel, 1, pointer ? SWELL : TRAVEL);\n\t\t\t\tconst wideFirst = origin === \"top\" || panel.width >= panel.height;\n\t\t\t\tanimate(wideFirst ? wide : tall, 1, SWELL);\n\t\t\t\tanimate(wideFirst ? tall : wide, 1, {\n\t\t\t\t\t...SWELL,\n\t\t\t\t\tdelay: SWELL_LAG,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tseeded.current = false;\n\t\t\tmeasureTrigger(pane);\n\t\t\tconst content = contentRef.current;\n\t\t\tif (content) {\n\t\t\t\tcontent.style.transformOrigin = `${from.current.x}px ${from.current.y}px`;\n\t\t\t}\n\t\t\tconst alongY =\n\t\t\t\tMath.abs(panel.y - from.current.y) >=\n\t\t\t\tMath.abs(panel.x - from.current.x);\n\t\t\tanimate(lift, 1, LIFT);\n\t\t\tanimate(travel, 1, TRAVEL);\n\t\t\tanimate(tall, 1, alongY ? LEAD : TRAIL);\n\t\t\tanimate(wide, 1, alongY ? TRAIL : LEAD);\n\t\t});\n\t\treturn () => {\n\t\t\tif (frame) cancelAnimationFrame(frame);\n\t\t};\n\t}, [\n\t\thandoff,\n\t\tlift,\n\t\topen,\n\t\torigin,\n\t\tpanelRadius,\n\t\tpoint,\n\t\treduceMotion,\n\t\ttall,\n\t\ttravel,\n\t\ttrigger,\n\t\twide,\n\t\tmeasureTrigger,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst pane = paneRef.current;\n\t\tif (!open || !pane || typeof ResizeObserver === \"undefined\") return;\n\t\tconst observer = new ResizeObserver(() => {\n\t\t\tconst width = pane.offsetWidth;\n\t\t\tconst height = pane.offsetHeight;\n\t\t\tconst panel = to.current;\n\t\t\tif (panel === EMPTY) return;\n\t\t\tif (width === panel.width && height === panel.height) return;\n\t\t\tto.current = {\n\t\t\t\t...panel,\n\t\t\t\tx: width / 2,\n\t\t\t\ty: height / 2,\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t};\n\t\t\tresized.set(resized.get() + 1);\n\t\t});\n\t\tobserver.observe(pane);\n\t\treturn () => observer.disconnect();\n\t}, [open, resized]);\n\n\tuseLayoutEffect(() => {\n\t\tif (open) return;\n\t\tconst pane = paneRef.current;\n\t\tif (!pane || reduceMotion || lift.get() === 0) return;\n\t\tconst holding = pane.animate(\n\t\t\t[{ visibility: \"visible\" }, { visibility: \"visible\" }],\n\t\t\t{ duration: HOLD_MS },\n\t\t);\n\t\thold.current = holding;\n\n\t\tif (handoff) {\n\t\t\tconst pane = paneRef.current;\n\t\t\tconst box = pane?.getBoundingClientRect();\n\t\t\tconst scale =\n\t\t\t\tpane && pane.offsetWidth > 0 && box ? box.width / pane.offsetWidth : 1;\n\t\t\tconst w = width.get();\n\t\t\tconst h = height.get();\n\t\t\tconst rect =\n\t\t\t\tbox &&\n\t\t\t\tnew DOMRect(\n\t\t\t\t\tbox.left + (x.get() - w / 2) * scale,\n\t\t\t\t\tbox.top + (y.get() - h / 2) * scale,\n\t\t\t\t\tw * scale,\n\t\t\t\t\th * scale,\n\t\t\t\t);\n\t\t\tconst handOver = () => {\n\t\t\t\tif (!rect || handoff.open.current === 0) return false;\n\t\t\t\thandoff.panel.current = {\n\t\t\t\t\trect,\n\t\t\t\t\tradius: radius.get(),\n\t\t\t\t\tat: performance.now(),\n\t\t\t\t};\n\t\t\t\thome.current();\n\t\t\t\tfor (const move of running.current) move.stop();\n\t\t\t\tif (hold.current === holding) holding.finish();\n\t\t\t\treturn true;\n\t\t\t};\n\t\t\tif (!handOver()) {\n\t\t\t\trequestAnimationFrame(() => {\n\t\t\t\t\tif (hold.current === holding) handOver();\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (handedOver.current && !seeded.current) {\n\t\t\thandedOver.current = false;\n\t\t\tmeasureTrigger(pane);\n\t\t} else if (!seeded.current && origin === \"trigger\") {\n\t\t\tif (to.current !== EMPTY) {\n\t\t\t\tto.current = {\n\t\t\t\t\t...to.current,\n\t\t\t\t\tx: pane.offsetWidth / 2,\n\t\t\t\t\ty: pane.offsetHeight / 2,\n\t\t\t\t\twidth: pane.offsetWidth,\n\t\t\t\t\theight: pane.offsetHeight,\n\t\t\t\t};\n\t\t\t}\n\t\t\tpane.style.minWidth = `${pane.offsetWidth}px`;\n\t\t\tpane.style.minHeight = `${pane.offsetHeight}px`;\n\t\t\tmeasureTrigger(pane);\n\t\t}\n\t\tif (seeded.current) {\n\t\t\tdrop.current = { width: 0, height: 0 };\n\t\t\tconst stop = landed.on(\"change\", (value) => {\n\t\t\t\tif (value > HOME) return;\n\t\t\t\tstop();\n\t\t\t\tif (hold.current === holding) holding.finish();\n\t\t\t});\n\t\t\thome.current = stop;\n\t\t\trunning.current = [\n\t\t\t\tanimate(wide, 0, BACK),\n\t\t\t\tanimate(tall, 0, BACK),\n\t\t\t\tanimate(travel, 0, HOMEWARD),\n\t\t\t];\n\t\t\treturn;\n\t\t}\n\t\tconst fade = absorbed.current\n\t\t\t? () => {}\n\t\t\t: travel.on(\"change\", (value) => {\n\t\t\t\t\tpane.style.opacity = String(\n\t\t\t\t\t\tclamp01((value - FADE_END) / (FADE_START - FADE_END)),\n\t\t\t\t\t);\n\t\t\t\t});\n\t\tconst follow =\n\t\t\torigin === \"trigger\"\n\t\t\t\t? travel.on(\"change\", () => {\n\t\t\t\t\t\tconst source = trigger.current?.getBoundingClientRect();\n\t\t\t\t\t\tif (!source) return;\n\t\t\t\t\t\tconst box = pane.getBoundingClientRect();\n\t\t\t\t\t\tconst scale =\n\t\t\t\t\t\t\tpane.offsetWidth > 0 ? box.width / pane.offsetWidth : 1;\n\t\t\t\t\t\tfrom.current = {\n\t\t\t\t\t\t\t...from.current,\n\t\t\t\t\t\t\tx: (source.left - box.left) / scale + from.current.width / 2,\n\t\t\t\t\t\t\ty: (source.top - box.top) / scale + from.current.height / 2,\n\t\t\t\t\t\t};\n\t\t\t\t\t})\n\t\t\t\t: () => {};\n\t\tconst stop = lift.on(\"change\", (value) => {\n\t\t\tif (value > HOME) return;\n\t\t\tstop();\n\t\t\tfollow();\n\t\t\tfade();\n\t\t\tconst dx = from.current.x - to.current.x;\n\t\t\tconst dy = from.current.y - to.current.y;\n\t\t\tconst length = Math.hypot(dx, dy);\n\t\t\tlandGlass(\n\t\t\t\ttrigger.current,\n\t\t\t\tlength > 0 ? { x: dx / length, y: dy / length } : undefined,\n\t\t\t);\n\t\t\tif (hold.current === holding) holding.finish();\n\t\t});\n\t\thome.current = () => {\n\t\t\tstop();\n\t\t\tfollow();\n\t\t\tfade();\n\t\t};\n\t\trunning.current = [\n\t\t\tanimate(wide, 0, BACK),\n\t\t\tanimate(tall, 0, BACK),\n\t\t\tanimate(travel, 0, HOMEWARD),\n\t\t\tanimate(lift, 0, SETTLE),\n\t\t];\n\t}, [\n\t\thandoff,\n\t\theight,\n\t\tlanded,\n\t\tlift,\n\t\topen,\n\t\torigin,\n\t\tradius,\n\t\treduceMotion,\n\t\ttall,\n\t\ttravel,\n\t\ttrigger,\n\t\twide,\n\t\twidth,\n\t\tx,\n\t\ty,\n\t\tmeasureTrigger,\n\t]);\n\n\tuseEffect(() => {\n\t\tconst button = trigger.current;\n\t\tconst coveredBy = (pane: HTMLElement | null) => {\n\t\t\tconst source = button?.getBoundingClientRect();\n\t\t\tconst box = pane?.getBoundingClientRect();\n\t\t\tif (!source || !box) return false;\n\t\t\treturn (\n\t\t\t\tsource.left >= box.left - 1 &&\n\t\t\t\tsource.top >= box.top - 1 &&\n\t\t\t\tsource.right <= box.right + 1 &&\n\t\t\t\tsource.bottom <= box.bottom + 1\n\t\t\t);\n\t\t};\n\t\tconst stop = lift.on(\"change\", (value) => {\n\t\t\tconst next =\n\t\t\t\tcovers.current &&\n\t\t\t\tvalue > HOME &&\n\t\t\t\t(absorbed.current || coveredBy(paneRef.current));\n\t\t\tif (next === absorbed.current) return;\n\t\t\tabsorbed.current = next;\n\t\t\tabsorb(button, next);\n\t\t});\n\t\treturn () => {\n\t\t\tstop();\n\t\t\tabsorbed.current = false;\n\t\t\tabsorb(button, false);\n\t\t};\n\t}, [lift, trigger]);\n\n\treturn (\n\t\t<GlassPane\n\t\t\t{...paneProps}\n\t\t\tref={(element) => {\n\t\t\t\tpaneRef.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\tradius={panelRadius}\n\t\t\ttheme={theme}\n\t\t\trefraction={refraction}\n\t\t\tshape={shape}\n\t\t\treach={reach}\n\t\t\tpress={glow}\n\t\t\tfrost={frost}\n\t\t>\n\t\t\t<motion.div\n\t\t\t\tref={contentRef}\n\t\t\t\tclassName=\"glass-ui-popup__content\"\n\t\t\t\tstyle={{\n\t\t\t\t\topacity: contentOpacity,\n\t\t\t\t\tfilter: contentFilter,\n\t\t\t\t\tscale: contentScale,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t{children}\n\t\t\t</motion.div>\n\t\t</GlassPane>\n\t);\n}\n",
      "type": "registry:lib",
      "target": "@components/liquikit/popup.tsx"
    }
  ],
  "type": "registry:lib"
}