react-morphcard 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["screenRectOf","rectOf","screenRectOf","visibleBoxOf","screenVisibleBoxOf"],"sources":["../src/geometry.ts","../src/dom.ts","../src/timing.ts","../src/animate.ts","../src/layers.ts","../src/measure.ts","../src/morph.ts","../src/use-morph.ts"],"sourcesContent":["/**\n * Pure geometry and decision helpers. Nothing here touches the DOM, so every\n * rule that decides how an element moves can be unit tested.\n */\n\nexport interface Box {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\nexport function box(left: number, top: number, width: number, height: number): Box {\n return { left, top, width, height };\n}\n\nexport function toBox(rect: { left: number; top: number; width: number; height: number }): Box {\n return { left: rect.left, top: rect.top, width: rect.width, height: rect.height };\n}\n\n/**\n * Screen pixels per CSS pixel of an element: its rendered width over its\n * layout width. Not 1 when an ancestor is scaled (a preview frame shrunk to\n * fit, a zoomed canvas). Falls back to 1 when either size is unusable.\n */\nexport function unitOf(rendered: number, layout: number): number {\n if (!(rendered > 0) || !(layout > 0)) return 1;\n const unit = rendered / layout;\n return Math.abs(unit - 1) < 0.001 ? 1 : unit;\n}\n\n/**\n * A box measured on screen, in the CSS pixels of a scaled subtree. Clip\n * insets and transforms are written in those pixels, so every measured box\n * goes through this before it becomes a keyframe.\n */\nexport function toLocal(b: Box, unit: number): Box {\n if (unit === 1) return b;\n return { left: b.left / unit, top: b.top / unit, width: b.width / unit, height: b.height / unit };\n}\n\nexport function area(b: Box | null): number {\n return b ? Math.max(0, b.width) * Math.max(0, b.height) : 0;\n}\n\n/** The overlap of two boxes, or null when they do not overlap. */\nexport function intersect(a: Box, b: Box): Box | null {\n const left = Math.max(a.left, b.left);\n const top = Math.max(a.top, b.top);\n const right = Math.min(a.left + a.width, b.left + b.width);\n const bottom = Math.min(a.top + a.height, b.top + b.height);\n if (right <= left || bottom <= top) return null;\n return { left, top, width: right - left, height: bottom - top };\n}\n\n/** Share of `rect` that is inside `visible` (0 to 1). Empty boxes count as hidden. */\nexport function visibleRatio(rect: Box, visible: Box | null): number {\n const whole = area(rect);\n if (whole <= 0 || !visible) return 0;\n return area(intersect(rect, visible)) / whole;\n}\n\n/** Below this share of their area on screen, elements do not take part in a flight. */\nexport const MIN_VISIBLE = 0.5;\n\nexport function isOnScreen(rect: Box, visible: Box | null, min = MIN_VISIBLE): boolean {\n return visibleRatio(rect, visible) >= min;\n}\n\nexport interface Shift {\n x: number;\n y: number;\n}\n\nexport const NO_SHIFT: Shift = { x: 0, y: 0 };\n\nexport function moveBox(b: Box, shift: Shift): Box {\n return shift.x === 0 && shift.y === 0 ? b : box(b.left + shift.x, b.top + shift.y, b.width, b.height);\n}\n\n/**\n * How far to move `outer` so that it covers `inner`, moving it as little as\n * possible. When `inner` is larger on an axis, `outer` ends up inside it.\n * Used for a sheet smaller than the screen (a centred panel) that must start\n * over a card it does not cover.\n */\nexport function coverShift(inner: Box, outer: Box): Shift {\n const axis = (a0: number, a1: number, b0: number, b1: number) => {\n if (a0 >= b0 && a1 <= b1) return 0;\n if (a1 - a0 <= b1 - b0) return a0 < b0 ? a0 - b0 : a1 - b1;\n if (b0 >= a0 && b1 <= a1) return 0;\n return b0 < a0 ? a0 - b0 : a1 - b1;\n };\n return {\n x: axis(inner.left, inner.left + inner.width, outer.left, outer.left + outer.width),\n y: axis(inner.top, inner.top + inner.height, outer.top, outer.top + outer.height),\n };\n}\n\nfunction px(n: number): string {\n // Round to 0.01px so keyframes stay readable and stable in tests.\n return `${Math.round(n * 100) / 100}px`;\n}\n\n/**\n * A clip-path that shows only `rect` of an element whose border box is\n * `container`. The rect is clamped to the container, so a card that sticks\n * out of the surface never produces negative insets.\n */\nexport function insetClip(rect: Box, container: Box, radius: number): string {\n const top = Math.max(0, rect.top - container.top);\n const left = Math.max(0, rect.left - container.left);\n const right = Math.max(0, container.left + container.width - (rect.left + rect.width));\n const bottom = Math.max(0, container.top + container.height - (rect.top + rect.height));\n return `inset(${px(top)} ${px(right)} ${px(bottom)} ${px(left)} round ${px(radius)})`;\n}\n\nexport function fullClip(radius: number): string {\n return `inset(0px 0px 0px 0px round ${px(radius)})`;\n}\n\n/**\n * First length of a computed border-radius (\"16px\", \"16px 8px\"). Percentages\n * resolve against `width`; anything else counts as square.\n */\nexport function parseRadius(value: string | null | undefined, width = 0): number {\n const text = value?.trim() ?? \"\";\n const pxMatch = /^(\\d*\\.?\\d+)px/.exec(text);\n if (pxMatch) return Number(pxMatch[1]);\n const pctMatch = /^(\\d*\\.?\\d+)%/.exec(text);\n if (pctMatch) return (Number(pctMatch[1]) / 100) * width;\n return 0;\n}\n\n/** Lines of text in a box, given its computed line-height and font-size. */\nexport function lineCount(height: number, lineHeight: string, fontSize: number): number {\n const parsed = Number.parseFloat(lineHeight);\n // \"normal\" does not parse; browsers use roughly 1.2 for common fonts.\n const lh = Number.isFinite(parsed) && parsed > 0 ? (lineHeight.endsWith(\"px\") ? parsed : parsed * fontSize) : fontSize * 1.2;\n if (lh <= 0) return 1;\n return Math.max(1, Math.round(height / lh));\n}\n\nexport interface PairInput {\n /** Source box on the card. */\n src: Box;\n /** Destination box on the detail screen. */\n dst: Box;\n /** \"text\" scales by font size, \"box\" (images, icons) by width. */\n mode: \"text\" | \"box\";\n srcFont?: number;\n dstFont?: number;\n srcLines?: number;\n dstLines?: number;\n /** The source text is cut off (ellipsis or overflow). */\n srcClipped?: boolean;\n}\n\nexport interface PairPlan {\n /** Uniform scale that turns the destination into the source. */\n scale: number;\n /**\n * True when one scaled copy cannot stand in for the other: the text wraps\n * differently, is cut off on the card, or the box proportions differ. Then\n * both copies fly together and crossfade instead of one copy stretching.\n */\n crossfade: boolean;\n}\n\n/** How far the width or height ratio may drift from the scale before we crossfade. */\nexport const ASPECT_TOLERANCE = 0.04;\n\nexport function planPair(input: PairInput): PairPlan {\n const { src, dst } = input;\n if (input.mode === \"box\") {\n const scale = dst.width > 0 ? src.width / dst.width : 1;\n const crossfade = dst.height <= 0 || Math.abs(src.height / dst.height - scale) > ASPECT_TOLERANCE;\n return { scale, crossfade };\n }\n const srcFont = input.srcFont ?? 16;\n const dstFont = input.dstFont ?? 16;\n const scale = dstFont > 0 ? srcFont / dstFont : 1;\n const crossfade =\n Boolean(input.srcClipped) ||\n (input.srcLines ?? 1) !== (input.dstLines ?? 1) ||\n dst.width <= 0 ||\n dst.height <= 0 ||\n Math.abs(src.width / dst.width - scale) > ASPECT_TOLERANCE ||\n Math.abs(src.height / dst.height - scale) > ASPECT_TOLERANCE;\n return { scale, crossfade };\n}\n\n/** Transform (origin 0 0) that draws an element laid out at `at` over `over`, scaled by `scale`. */\nexport function placeOver(at: Box, over: Box, scale: number): string {\n return `translate(${px(over.left - at.left)}, ${px(over.top - at.top)}) scale(${Math.round(scale * 10000) / 10000})`;\n}\n\n/** Keyframes that move one copy of a crossfading picture. */\nexport interface FillFrame {\n [property: string]: string | number;\n offset: number;\n transform: string;\n transformOrigin: string;\n clipPath: string;\n}\n\n/** How many steps a picture flight is sampled in. Enough for sub-pixel error on a full-screen flight. */\nexport const FILL_STEPS = 16;\n\nexport interface FillInput {\n /** Where the large picture (the sheet's element) is laid out. */\n big: Box;\n /** Where the small picture (the card's element) is laid out. */\n small: Box;\n /** The visible rectangle at the start and at the end. */\n from: Box;\n to: Box;\n /**\n * Where the small picture sits inside the large one, per axis: 0 start,\n * 0.5 centre, 1 end. Read from the card picture's object-position.\n */\n align?: [number, number];\n /**\n * true (default): the small picture is a crop of the large one (an image\n * or a video with object-fit: cover), so it keeps its place inside it.\n * false: two different boxes (a gradient, an icon tile); each covers the\n * moving frame on its own.\n */\n crop?: boolean;\n /** Corner radius at the start and at the end, in px. */\n radius?: [number, number];\n steps?: number;\n}\n\n/**\n * Frames for a picture that changes shape on the way: a square thumbnail\n * into a wide banner, a cropped poster into a tall video. The small picture\n * is treated as a crop of the large one, the way `object-fit: cover` crops\n * it. A rectangle moves from the card to the sheet; the large copy covers it\n * and both copies are cut to it with a clip-path. The small copy is scaled so\n * that it shows the same part of the picture at the same size and place as\n * the large copy under it. So while the two copies swap, the reader sees one\n * picture whose frame changes shape: never two pictures of different sizes,\n * never a zoom into a crop.\n *\n * The rectangle moves linearly; the effect's easing shapes it in time. The\n * frames are sampled because a clip-path inside a changing scale is not linear.\n */\nexport function fillFrames(input: FillInput): { big: FillFrame[]; small: FillFrame[] } {\n const { big, small, from, to } = input;\n const [ax, ay] = input.align ?? [0.5, 0.5];\n const [r0, r1] = input.radius ?? [0, 0];\n const steps = input.steps ?? FILL_STEPS;\n const out = { big: [] as FillFrame[], small: [] as FillFrame[] };\n if (!(big.width > 0 && big.height > 0 && small.width > 0 && small.height > 0)) return out;\n // The large picture scaled by k covers the small one: the small picture is\n // that, cropped at `align`.\n const k = Math.max(small.width / big.width, small.height / big.height);\n const cropX = ax * (big.width * k - small.width);\n const cropY = ay * (big.height * k - small.height);\n const lerp = (a: number, b: number, t: number) => a + (b - a) * t;\n const frame = (at: Box, left: number, top: number, s: number, rect: Box, radius: number, offset: number): FillFrame => {\n const c = (n: number) => px(Math.max(0, n) / s);\n const inset = [\n c(rect.top - top),\n c(left + at.width * s - (rect.left + rect.width)),\n c(top + at.height * s - (rect.top + rect.height)),\n c(rect.left - left),\n ];\n return {\n offset,\n transform: `translate(${px(left - at.left)}, ${px(top - at.top)}) scale(${Math.round(s * 10000) / 10000})`,\n transformOrigin: \"0 0\",\n clipPath: `inset(${inset.join(\" \")} round ${px(radius / s)})`,\n };\n };\n for (let i = 0; i <= steps; i++) {\n const t = i / steps;\n const offset = Math.round(t * 10000) / 10000;\n const rect = box(\n lerp(from.left, to.left, t),\n lerp(from.top, to.top, t),\n lerp(from.width, to.width, t),\n lerp(from.height, to.height, t),\n );\n const radius = lerp(r0, r1, t);\n // The large copy covers the rectangle.\n const sb = Math.max(rect.width / big.width, rect.height / big.height);\n const bl = rect.left + ax * (rect.width - big.width * sb);\n const bt = rect.top + ay * (rect.height - big.height * sb);\n out.big.push(frame(big, bl, bt, sb, rect, radius, offset));\n if (input.crop === false) {\n // Each box covers the frame on its own.\n const s2 = Math.max(rect.width / small.width, rect.height / small.height);\n const sl = rect.left + ax * (rect.width - small.width * s2);\n const st = rect.top + ay * (rect.height - small.height * s2);\n out.small.push(frame(small, sl, st, s2, rect, radius, offset));\n } else {\n // The small copy shows the same part of the picture on top of it.\n const ss = sb / k;\n out.small.push(frame(small, bl + cropX * ss, bt + cropY * ss, ss, rect, radius, offset));\n }\n }\n return out;\n}\n\n/**\n * Transform origin for scaling the background back: the horizontal centre of\n * its visible part and 30% down it, so a long scrolled page shrinks around\n * what the reader sees, not around the middle of the whole document.\n */\nexport function backgroundOrigin(element: Box, visible: Box | null): string {\n const v = visible ?? element;\n const x = v.left + v.width / 2 - element.left;\n const y = v.top + v.height * 0.3 - element.top;\n return `${px(x)} ${px(y)}`;\n}\n","/**\n * DOM helpers: measuring what is on screen, finding marked elements, and\n * undoing every attribute or inline style the library sets.\n */\nimport { type Box, intersect, lineCount, toBox, unitOf } from \"./geometry\";\n\nexport const SHARED_ATTR = \"data-morph\";\nexport const GHOST_ATTR = \"data-morph-ghost\";\nconst STAGGER_ATTR = \"data-morph-stagger\";\nconst DOCK_ATTR = \"data-morph-dock\";\n\nexport const FOCUSABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nexport function viewportBox(): Box {\n const doc = document.documentElement;\n return { left: 0, top: 0, width: doc.clientWidth || window.innerWidth, height: window.innerHeight };\n}\n\n/**\n * The part of the viewport where `el` can be seen: the viewport cut down by\n * every ancestor that clips its content (overflow other than visible).\n * Returns null when an ancestor clips everything away.\n */\nexport function visibleBoxOf(el: Element): Box | null {\n let visible: Box | null = viewportBox();\n for (let node = el.parentElement; node && visible; node = node.parentElement) {\n if (node === document.body || node === document.documentElement) break;\n const style = getComputedStyle(node);\n if (style.display === \"contents\") continue;\n if (style.overflowX !== \"visible\" || style.overflowY !== \"visible\") {\n const rect = node.getBoundingClientRect();\n // Client sizes and borders are in layout pixels; rect and the viewport\n // are in screen pixels. Account for scale on this node or an ancestor\n // before clipping, otherwise a shrunk list includes cards it hides.\n const scaleX = unitOf(rect.width, node.offsetWidth);\n const scaleY = unitOf(rect.height, node.offsetHeight);\n visible = intersect(visible, {\n left: rect.left + node.clientLeft * scaleX,\n top: rect.top + node.clientTop * scaleY,\n width: node.clientWidth * scaleX,\n height: node.clientHeight * scaleY,\n });\n }\n // A fixed ancestor is positioned against the viewport, so clipping by\n // its own ancestors does not apply in the common case.\n if (style.position === \"fixed\") break;\n }\n return visible;\n}\n\nexport function rectOf(el: Element): Box {\n return toBox(el.getBoundingClientRect());\n}\n\n/**\n * True when a descendant is position: fixed. A transform on the ancestor\n * would become the containing block of that descendant and drag it along.\n */\nexport function hasFixedDescendant(el: Element): boolean {\n const all = el.getElementsByTagName(\"*\");\n for (let i = 0; i < all.length; i++) {\n const node = all[i];\n if (node && getComputedStyle(node).position === \"fixed\") return true;\n }\n return false;\n}\n\n/** The text is cut off: an ellipsis, a line clamp or hidden overflow. */\nexport function isClipped(el: Element, style = getComputedStyle(el)): boolean {\n if (style.overflowX === \"visible\" && style.overflowY === \"visible\") return false;\n if (el.clientWidth === 0) return false;\n return el.scrollWidth > el.clientWidth + 1 || el.scrollHeight > el.clientHeight + 1;\n}\n\nexport function textLines(el: Element, height: number, style = getComputedStyle(el)): number {\n const fontSize = Number.parseFloat(style.fontSize) || 16;\n const inner =\n height -\n (Number.parseFloat(style.paddingTop) || 0) -\n (Number.parseFloat(style.paddingBottom) || 0) -\n (Number.parseFloat(style.borderTopWidth) || 0) -\n (Number.parseFloat(style.borderBottomWidth) || 0);\n return lineCount(Math.max(0, inner), style.lineHeight, fontSize);\n}\n\n/** Index once per measurement; duplicate keys keep the first non-ghost element. */\nexport function sharedElements(root: Element): Map<string, HTMLElement> {\n const elements = new Map<string, HTMLElement>();\n for (const el of root.querySelectorAll<HTMLElement>(`[${SHARED_ATTR}]`)) {\n if (el.closest(`[${GHOST_ATTR}]`)) continue;\n const key = el.getAttribute(SHARED_ATTR);\n if (key && !elements.has(key)) elements.set(key, el);\n }\n return elements;\n}\n\nexport interface SheetContent {\n /** Blocks marked data-morph-stagger, in document order. */\n stagger: HTMLElement[];\n /** Unmarked blocks: they fade with the content so they never show through the card. */\n plain: HTMLElement[];\n /** Bars marked data-morph-dock, which slide in from below. */\n docks: HTMLElement[];\n}\n\n/**\n * Splits the sheet into the parts that move differently. Walks down only\n * into elements that contain shared, stagger or dock markers, so each\n * returned element is the largest block that can fade as a whole.\n */\nexport function collectContent(sheet: Element): SheetContent {\n const out: SheetContent = { stagger: [], plain: [], docks: [] };\n const marked = `[${SHARED_ATTR}], [${STAGGER_ATTR}], [${DOCK_ATTR}]`;\n const walk = (parent: Element) => {\n for (const child of Array.from(parent.children)) {\n if (!(child instanceof HTMLElement) && !(child instanceof SVGElement)) continue;\n if (child.hasAttribute(GHOST_ATTR) || child.hasAttribute(SHARED_ATTR)) continue;\n if (child.hasAttribute(DOCK_ATTR)) {\n out.docks.push(child as HTMLElement);\n } else if (child.hasAttribute(STAGGER_ATTR) && !child.querySelector(`[${SHARED_ATTR}]`)) {\n out.stagger.push(child as HTMLElement);\n } else if (child.querySelector(marked)) {\n walk(child);\n } else {\n out.plain.push(child as HTMLElement);\n }\n }\n };\n walk(sheet);\n return out;\n}\n\n/** Largest blocks of a card copy that contain no shared element. */\nexport function collectRest(root: Element): Element[] {\n const out: Element[] = [];\n const walk = (parent: Element) => {\n for (const child of Array.from(parent.children)) {\n if (child.hasAttribute(SHARED_ATTR)) continue;\n if (child.querySelector(`[${SHARED_ATTR}]`)) walk(child);\n else out.push(child);\n }\n };\n walk(root);\n return out;\n}\n\nexport function focusTargetIn(root: HTMLElement): HTMLElement | null {\n if (root.matches(\"[data-morph-focus]\")) return root;\n const marked = root.querySelector<HTMLElement>(\"[data-morph-focus]\");\n if (marked) return marked;\n if (root.matches(FOCUSABLE)) return root;\n const first = root.querySelector<HTMLElement>(FOCUSABLE);\n if (first) return first;\n return root.tabIndex >= 0 ? root : null;\n}\n\nexport type Scroller = HTMLElement | Window;\n\n/** Nearest ancestor that scrolls vertically, or the window. */\nexport function scrollerOf(el: Element): Scroller {\n for (let node = el.parentElement; node; node = node.parentElement) {\n if (node === document.body || node === document.documentElement) break;\n const overflow = getComputedStyle(node).overflowY;\n if ((overflow === \"auto\" || overflow === \"scroll\" || overflow === \"overlay\") && node.scrollHeight > node.clientHeight) {\n return node;\n }\n }\n return window;\n}\n\nexport interface SavedScroll {\n target: Scroller;\n top: number;\n left: number;\n}\n\nexport function saveScroll(target: Scroller): SavedScroll {\n if (target instanceof Window) return { target, top: window.scrollY, left: window.scrollX };\n return { target, top: target.scrollTop, left: target.scrollLeft };\n}\n\n/** Puts the scroll position back at once, ignoring scroll-behavior: smooth. */\nexport function restoreScroll(saved: SavedScroll): void {\n const { target, top, left } = saved;\n if (target instanceof Window) {\n if (window.scrollY !== top || window.scrollX !== left) window.scrollTo({ top, left, behavior: \"instant\" });\n } else if (target.isConnected && (target.scrollTop !== top || target.scrollLeft !== left)) {\n target.scrollTo({ top, left, behavior: \"instant\" });\n }\n}\n\n/**\n * Records every attribute it changes and puts them back in reverse order, so\n * nothing the library touched survives a cleanup.\n */\nexport class Undo {\n private steps: Array<() => void> = [];\n\n attr(el: Element, name: string, value: string | null): void {\n const previous = el.getAttribute(name);\n if (value === null) el.removeAttribute(name);\n else el.setAttribute(name, value);\n this.steps.push(() => {\n if (previous === null) el.removeAttribute(name);\n else el.setAttribute(name, previous);\n });\n }\n\n get size(): number {\n return this.steps.length;\n }\n\n flush(): void {\n for (let step = this.steps.pop(); step; step = this.steps.pop()) step();\n }\n}\n","import type { MorphOptions, MorphTiming } from \"./types\";\n\nexport const defaults: MorphTiming = {\n duration: { open: 400, close: 300 },\n easing: {\n surface: \"cubic-bezier(0.32, 0.72, 0, 1)\",\n content: \"cubic-bezier(0.23, 1, 0.32, 1)\",\n },\n stagger: 45,\n backgroundScale: 0.96,\n reducedMotion: \"system\",\n timeScale: 1,\n closeOnEscape: true,\n restoreScroll: true,\n};\n\n/**\n * Fractions of the open or close duration. With the defaults (400 / 300 ms):\n * content enters at 130 ms, the card copy of a crossfading text is gone by\n * 160 ms, and on close the big heading hands over to the card text by 90 ms.\n */\nexport const choreography = {\n open: {\n contentDelay: 0.325,\n content: 0.65,\n copyOut: 0.4,\n targetIn: 0.5,\n restOut: 0.35,\n borderOut: 0.2,\n lateIn: 0.4,\n dockDelay: 0.4,\n dock: 0.75,\n },\n close: { copyIn: 0.37, targetOut: 0.3, restDelay: 0.5, rest: 0.5, contentOut: 0.37, dock: 0.6 },\n /** Opacity only, in ms: the empty surface covers the page before any text appears. */\n fade: { surface: 120, contentDelay: 100, content: 140, closeContent: 100, closeSurfaceDelay: 100, closeSurface: 120 },\n} as const;\n\nexport function resolveTiming(options: Partial<MorphOptions>, base: MorphTiming): MorphTiming {\n return {\n duration: { ...base.duration, ...options.duration },\n easing: { ...base.easing, ...options.easing },\n stagger: options.stagger ?? base.stagger,\n backgroundScale: options.backgroundScale ?? base.backgroundScale,\n reducedMotion: options.reducedMotion ?? base.reducedMotion,\n timeScale: options.timeScale ?? base.timeScale,\n closeOnEscape: options.closeOnEscape ?? base.closeOnEscape,\n restoreScroll: options.restoreScroll ?? base.restoreScroll,\n };\n}\n\nexport function durationFor(direction: \"open\" | \"close\", timing: MorphTiming, fade: boolean): number {\n const f = choreography.fade;\n const ms = fade\n ? direction === \"open\" ? f.contentDelay + f.content : f.closeSurfaceDelay + f.closeSurface\n : timing.duration[direction];\n return ms * timing.timeScale;\n}\n","import { fullClip, fillFrames, insetClip, placeOver, toLocal } from \"./geometry\";\nimport { GHOST_ATTR, SHARED_ATTR, collectContent, collectRest, hasFixedDescendant, rectOf as screenRectOf } from \"./dom\";\nimport { choreography } from \"./timing\";\nimport type { MorphTiming } from \"./types\";\nimport type { Geometry, PairGeometry, Run, Session } from \"./transition\";\n\nconst EASE_OUT = \"ease-out\";\n\ninterface AnimationContext {\n sheet: HTMLElement;\n background: HTMLElement | null;\n scrim: HTMLElement | null;\n timing: MorphTiming;\n session: Session | null;\n}\n\n/** Build one run from measured geometry. Lifecycle and cleanup belong to morph.ts. */\nexport function buildAnimations(r: Run, g: Geometry, context: AnimationContext): void {\n const { sheet, background, scrim, timing, session } = context;\n const pending: Array<{ el: Element; frames: Keyframe[]; options: KeyframeAnimationOptions }> = [];\n function queueAnimation(el: Element, frames: Keyframe[], duration: number, delay = 0, easing = \"linear\") {\n pending.push({ el, frames, options: { duration: Math.max(0, duration), delay, easing, fill: \"both\" } });\n }\n\n /**\n * A copy of the card placed exactly over it, inside the sheet. It carries\n * what the sheet does not have (meta lines, icons, the border) and the\n * card's own version of texts that crossfade.\n */\n function makeGhost(r: Run, g: Geometry) {\n const card = g.card as HTMLElement;\n const ghost = card.cloneNode(true) as HTMLElement;\n ghost.removeAttribute(\"id\");\n for (const node of ghost.querySelectorAll(\"[id]\")) node.removeAttribute(\"id\");\n // A cloned radio with the same name would uncheck the original.\n for (const node of ghost.querySelectorAll(\"[name]\")) node.removeAttribute(\"name\");\n ghost.setAttribute(GHOST_ATTR, \"\");\n ghost.setAttribute(\"aria-hidden\", \"true\");\n ghost.inert = true;\n const style = getComputedStyle(card);\n // Inherited text styles come from the list, not from the sheet.\n for (const prop of [\n \"color\",\n \"font-family\",\n \"font-size\",\n \"font-weight\",\n \"font-style\",\n \"line-height\",\n \"letter-spacing\",\n \"text-align\",\n \"white-space\",\n \"direction\",\n \"font-feature-settings\",\n \"font-variant-numeric\",\n ]) {\n ghost.style.setProperty(prop, style.getPropertyValue(prop));\n }\n const left = g.cardBox.left - g.sheetBox.left - sheet.clientLeft + sheet.scrollLeft;\n const top = g.cardBox.top - g.sheetBox.top - sheet.clientTop + sheet.scrollTop;\n Object.assign(ghost.style, {\n position: \"absolute\",\n boxSizing: \"border-box\",\n margin: \"0\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${g.cardBox.width}px`,\n height: `${g.cardBox.height}px`,\n minWidth: \"0\",\n maxWidth: \"none\",\n minHeight: \"0\",\n maxHeight: \"none\",\n background: \"transparent\",\n boxShadow: \"none\",\n outline: \"none\",\n transform: \"none\",\n transition: \"none\",\n animation: \"none\",\n opacity: \"1\",\n visibility: \"visible\",\n pointerEvents: \"none\",\n zIndex: \"0\",\n });\n ghost.style.borderColor = g.border ?? \"transparent\";\n\n const copies = new Map<string, HTMLElement>();\n const rest: Element[] = collectRest(ghost);\n const pairs = new Map(g.pairs.map((pair) => [pair.key, pair]));\n for (const node of ghost.querySelectorAll<HTMLElement>(`[${SHARED_ATTR}]`)) {\n const key = node.getAttribute(SHARED_ATTR) ?? \"\";\n const pair = pairs.get(key);\n if (pair?.mode === \"scale\") node.style.visibility = \"hidden\";\n else if (pair?.mode === \"crossfade\") copies.set(key, node);\n // Not flying (skipped or not in `shared`): it fades in place like the rest of the card.\n else rest.push(node);\n }\n // Paint the old card below the live shared elements. A topmost ghost\n // lets its opaque cover hide a live icon/photo whose ghost is hidden\n // (scale mode), making that element vanish until the cover fades out.\n sheet.prepend(ghost);\n r.ghosts.push(ghost);\n // Correct for borders, scroll offsets or an unexpected containing block.\n const placed = toLocal(screenRectOf(ghost), g.unit);\n const dx = g.cardBox.left - placed.left;\n const dy = g.cardBox.top - placed.top;\n if (Math.abs(dx) > 0.5 || Math.abs(dy) > 0.5) {\n ghost.style.left = `${left + dx}px`;\n ghost.style.top = `${top + dy}px`;\n }\n return { root: ghost, copies, rest };\n }\n\n /**\n * A sheet that does not cover the card at rest (a centred panel) starts\n * moved over it and slides into place while it grows, on the same curve,\n * so the surface and every flight follow the same path on screen as with\n * a sheet that covers the card.\n */\n function slide(g: Geometry, duration: number, back: boolean) {\n if (g.shift.x === 0 && g.shift.y === 0) return;\n const moved = { translate: `${g.shift.x}px ${g.shift.y}px` };\n const home = { translate: \"0px 0px\" };\n queueAnimation(sheet, back ? [home, moved] : [moved, home], duration, 0, timing.easing.surface);\n }\n\n function recede(duration: number, back: boolean, isReduced: boolean) {\n if (background && session?.scaled && !isReduced) {\n const still = { transform: \"none\", transformOrigin: session.origin };\n const away = { transform: `scale(${session.scale})`, transformOrigin: session.origin };\n queueAnimation(background, back ? [away, still] : [still, away], duration, 0, timing.easing.surface);\n }\n if (scrim) queueAnimation(scrim, back ? [{ opacity: 1 }, { opacity: 0 }] : [{ opacity: 0 }, { opacity: 1 }], duration, 0, EASE_OUT);\n }\n\n function fillOf(p: PairGeometry, direction: \"open\" | \"close\") {\n const f = p.fill ?? { radius: [0, 0] as [number, number], align: [0.5, 0.5] as [number, number], crop: true };\n const open = direction === \"open\";\n return fillFrames({\n big: p.dstBox,\n small: p.srcBox,\n from: open ? p.srcBox : p.dstBox,\n to: open ? p.dstBox : p.srcBox,\n align: f.align,\n crop: f.crop,\n radius: open ? f.radius : [f.radius[1], f.radius[0]],\n });\n }\n\n function buildOpen(r: Run, g: Geometry) {\n const D = timing.duration.open * timing.timeScale;\n const k = choreography.open;\n const surface = timing.easing.surface;\n const content = timing.easing.content;\n\n queueAnimation(sheet, [{ clipPath: insetClip(g.clipBox, g.sheetBox, g.radius) }, { clipPath: fullClip(g.sheetRadius) }], D, 0, surface);\n if (g.colors) queueAnimation(sheet, [{ backgroundColor: g.colors[0] }, { backgroundColor: g.colors[1] }], D, 0, surface);\n\n const ghost = makeGhost(r, g);\n // After the ghost is placed: it is measured against the sheet at rest.\n slide(g, D, false);\n for (const p of g.pairs) {\n if (p.mode === \"skip\" || !p.dst) {\n // Nothing to fly from: appear once the flights around it have landed.\n if (p.dst) queueAnimation(p.dst, [{ opacity: 0 }, { opacity: 1 }], k.lateIn * D, (1 - k.lateIn) * D, EASE_OUT);\n continue;\n }\n const fill = p.fill ? fillOf(p, \"open\") : null;\n queueAnimation(\n p.dst,\n fill\n ? fill.big\n : [\n { transform: placeOver(p.dstBox, p.srcBox, p.scale), transformOrigin: \"0 0\" },\n { transform: \"none\", transformOrigin: \"0 0\" },\n ],\n D,\n 0,\n surface,\n );\n if (p.mode !== \"crossfade\") continue;\n const copy = ghost.copies.get(p.key);\n if (copy) {\n queueAnimation(\n copy,\n fill\n ? fill.small\n : [\n { transform: \"none\", transformOrigin: \"0 0\" },\n { transform: placeOver(p.srcBox, p.dstBox, 1 / p.scale), transformOrigin: \"0 0\" },\n ],\n D,\n 0,\n surface,\n );\n queueAnimation(copy, [{ opacity: 1 }, { opacity: 0 }], k.copyOut * D, 0, EASE_OUT);\n }\n queueAnimation(p.dst, [{ opacity: 0 }, { opacity: 1 }], k.targetIn * D, 0, EASE_OUT);\n }\n for (const el of ghost.rest) queueAnimation(el, [{ opacity: 1 }, { opacity: 0 }], k.restOut * D, 0, EASE_OUT);\n if (g.border) queueAnimation(ghost.root, [{ borderColor: g.border }, { borderColor: \"transparent\" }], k.borderOut * D, 0, EASE_OUT);\n\n const parts = collectContent(sheet);\n parts.stagger.forEach((el, i) => {\n const frames = hasFixedDescendant(el)\n ? [{ opacity: 0 }, { opacity: 1 }]\n : [\n { opacity: 0, transform: \"translateY(10px)\" },\n { opacity: 1, transform: \"none\" },\n ];\n queueAnimation(el, frames, k.content * D, (k.contentDelay * timing.duration.open + i * timing.stagger) * timing.timeScale, content);\n });\n for (const el of parts.plain) queueAnimation(el, [{ opacity: 0 }, { opacity: 1 }], k.content * D, k.contentDelay * D, content);\n for (const el of parts.docks) {\n const frames = hasFixedDescendant(el)\n ? [{ opacity: 0 }, { opacity: 1 }]\n : [{ transform: \"translateY(100%)\" }, { transform: \"none\" }];\n queueAnimation(el, frames, k.dock * D, k.dockDelay * D, content);\n }\n\n recede(D, false, false);\n }\n\n function buildClose(r: Run, g: Geometry) {\n const C = timing.duration.close * timing.timeScale;\n const k = choreography.close;\n const surface = timing.easing.surface;\n\n queueAnimation(sheet, [{ clipPath: fullClip(g.sheetRadius) }, { clipPath: insetClip(g.clipBox, g.sheetBox, g.radius) }], C, 0, surface);\n if (g.colors) queueAnimation(sheet, [{ backgroundColor: g.colors[1] }, { backgroundColor: g.colors[0] }], C, 0, surface);\n\n const ghost = makeGhost(r, g);\n slide(g, C, true);\n let anchor: PairGeometry | null = null;\n for (const p of g.pairs) {\n if (p.mode === \"skip\" || !p.dst) {\n if (p.dst) queueAnimation(p.dst, [{ opacity: 1 }, { opacity: 0 }], k.contentOut * C, 0, EASE_OUT);\n continue;\n }\n if (!anchor || p.dstBox.top + p.dstBox.height > anchor.dstBox.top + anchor.dstBox.height) anchor = p;\n const fill = p.fill ? fillOf(p, \"close\") : null;\n queueAnimation(\n p.dst,\n fill\n ? fill.big\n : [\n { transform: \"none\", transformOrigin: \"0 0\" },\n { transform: placeOver(p.dstBox, p.srcBox, p.scale), transformOrigin: \"0 0\" },\n ],\n C,\n 0,\n surface,\n );\n if (p.mode !== \"crossfade\") continue;\n // The texts wrap differently: swap them at the start, while the heading\n // still has room, so the card's own text is what lands on the card.\n const copy = ghost.copies.get(p.key);\n if (copy) {\n queueAnimation(\n copy,\n fill\n ? fill.small\n : [\n { transform: placeOver(p.srcBox, p.dstBox, 1 / p.scale), transformOrigin: \"0 0\" },\n { transform: \"none\", transformOrigin: \"0 0\" },\n ],\n C,\n 0,\n surface,\n );\n queueAnimation(copy, [{ opacity: 0 }, { opacity: 1 }], k.copyIn * C, 0, EASE_OUT);\n }\n queueAnimation(p.dst, [{ opacity: 1 }, { opacity: 0 }], k.targetOut * C, 0, EASE_OUT);\n }\n // The rest of the card comes back at the end, finishing with everything else.\n for (const el of ghost.rest) queueAnimation(el, [{ opacity: 0 }, { opacity: 1 }], k.rest * C, k.restDelay * C, EASE_OUT);\n if (g.border) queueAnimation(ghost.root, [{ borderColor: \"transparent\" }, { borderColor: g.border }], k.rest * C, k.restDelay * C, EASE_OUT);\n\n // Content follows the lowest flying element down into the card and fades.\n const parts = collectContent(sheet);\n const follow = anchor\n ? `translate(${anchor.srcBox.left - anchor.dstBox.left}px, ${anchor.srcBox.top - anchor.dstBox.top}px)`\n : null;\n for (const el of parts.stagger) {\n if (follow && !hasFixedDescendant(el)) queueAnimation(el, [{ transform: \"none\" }, { transform: follow }], C, 0, surface);\n queueAnimation(el, [{ opacity: 1 }, { opacity: 0 }], k.contentOut * C, 0, EASE_OUT);\n }\n for (const el of parts.plain) queueAnimation(el, [{ opacity: 1 }, { opacity: 0 }], k.contentOut * C, 0, EASE_OUT);\n for (const el of parts.docks) {\n const frames = hasFixedDescendant(el)\n ? [{ opacity: 1 }, { opacity: 0 }]\n : [{ transform: \"none\" }, { transform: \"translateY(100%)\" }];\n queueAnimation(el, frames, k.dock * C, 0, EASE_OUT);\n }\n\n recede(C, true, false);\n }\n\n function sheetChildren(): Element[] {\n return Array.from(sheet.children).filter((el) => !el.hasAttribute(GHOST_ATTR));\n }\n\n /** Opacity only: the empty surface first, then the content, so two screens of text never overlap. */\n function buildFadeOpen(isReduced: boolean) {\n const f = choreography.fade;\n const t = timing.timeScale;\n queueAnimation(sheet, [{ opacity: 0 }, { opacity: 1 }], f.surface * t, 0, \"ease\");\n for (const el of sheetChildren()) queueAnimation(el, [{ opacity: 0 }, { opacity: 1 }], f.content * t, f.contentDelay * t, \"ease\");\n recede((f.contentDelay + f.content) * t, false, isReduced);\n }\n\n function buildFadeClose(isReduced: boolean) {\n const f = choreography.fade;\n const t = timing.timeScale;\n for (const el of sheetChildren()) queueAnimation(el, [{ opacity: 1 }, { opacity: 0 }], f.closeContent * t, 0, \"ease\");\n queueAnimation(sheet, [{ opacity: 1 }, { opacity: 0 }], f.closeSurface * t, f.closeSurfaceDelay * t, \"ease\");\n recede((f.closeSurfaceDelay + f.closeSurface) * t, true, isReduced);\n }\n\n if (g.plan.choreography === \"morph\") {\n if (r.kind === \"open\") buildOpen(r, g);\n else buildClose(r, g);\n } else if (r.kind === \"open\") buildFadeOpen(g.plan.reduced);\n else buildFadeClose(g.plan.reduced);\n\n // animate() invalidates styles. Finish all DOM/style reads (including\n // fixed-descendant checks and ghost placement) before starting any effect,\n // otherwise each content block forces another style recalculation.\n for (const { el, frames, options } of pending) r.anims.push(el.animate(frames, options));\n}\n","// Activation order, scoped to the document. A lower sheet must not handle\n// Escape just because its listener was registered first.\nconst layers = new WeakMap<Document, HTMLElement[]>();\n\nexport function activate(sheet: HTMLElement): void {\n deactivate(sheet);\n const stack = layers.get(sheet.ownerDocument) ?? [];\n stack.push(sheet);\n layers.set(sheet.ownerDocument, stack);\n}\n\nexport function deactivate(sheet: HTMLElement): void {\n const stack = layers.get(sheet.ownerDocument);\n const index = stack?.indexOf(sheet) ?? -1;\n if (index >= 0) stack?.splice(index, 1);\n}\n\nexport function isTopLayer(sheet: HTMLElement): boolean {\n return layers.get(sheet.ownerDocument)?.at(-1) === sheet;\n}\n","import { type Box, area, backgroundOrigin, intersect, isOnScreen, moveBox, coverShift, NO_SHIFT, parseRadius, planPair, toLocal, unitOf } from \"./geometry\";\nimport { hasFixedDescendant, isClipped, rectOf as screenRectOf, sharedElements, textLines, visibleBoxOf as screenVisibleBoxOf } from \"./dom\";\nimport type { MorphOptions, SkipReason } from \"./types\";\nimport type { Geometry, PairGeometry } from \"./transition\";\n\nconst TRANSPARENT = /^(transparent|rgba\\(0, 0, 0, 0\\))$/;\n\nconst ZERO: Box = { left: 0, top: 0, width: 0, height: 0 };\n\n/** Jumps CSS transitions on the card (hover, press) to their end so the card is measured at rest. */\nfunction settleTransitions(card: HTMLElement) {\n if (typeof card.getAnimations !== \"function\") return;\n for (const a of card.getAnimations({ subtree: true })) {\n if (typeof CSSTransition !== \"undefined\" && a instanceof CSSTransition) a.finish();\n }\n}\n\n/** Smallest visible strip of a card, in px, that a flight starts from or lands on. */\nconst MIN_SEEN = 8;\n\nfunction isSeen(b: Box | null): b is Box {\n return b !== null && b.width >= MIN_SEEN && b.height >= MIN_SEEN;\n}\n\n/** Measure one transition before constructing any of its animations. */\nexport function measureTransition(\n direction: \"open\" | \"close\", card: HTMLElement | null, isReduced: boolean,\n hooks: Pick<MorphOptions, \"sheet\" | \"shared\" | \"radius\"> & { backgroundScaled: boolean },\n): Geometry {\n const { sheet, backgroundScaled } = hooks;\n const destinations = sharedElements(sheet);\n const keys = [...destinations.keys()];\n // No cache survives this measurement: React may replace the card or detail\n // between open and Back.\n let sources: Map<string, HTMLElement>;\n // Boxes are measured on screen and used in the sheet's CSS pixels. They\n // differ when an ancestor of the demo is scaled (a preview shrunk to fit).\n const unit = unitOf(sheet.getBoundingClientRect().width, sheet.offsetWidth);\n const rectOf = (el: Element): Box => toLocal(screenRectOf(el), unit);\n const visibleBoxOf = (el: Element): Box | null => {\n const v = screenVisibleBoxOf(el);\n return v ? toLocal(v, unit) : null;\n };\n\n function isShared(key: string): boolean {\n return !hooks.shared || hooks.shared.includes(key);\n }\n\n function radiusOf(el: Element, width: number): number {\n return parseRadius(getComputedStyle(el).borderTopLeftRadius, width);\n }\n\n /**\n * A card picture that is an image or a video is a crop of the large one, at\n * its object-position. A plain box (a gradient, an icon tile) is not.\n */\n function cropOf(el: Element): { align: [number, number]; crop: boolean } {\n const media = /^(img|video|picture|canvas)$/i.test(el.tagName) ? el : el.querySelector(\"img, video, canvas\");\n const pos = media ? getComputedStyle(media).objectPosition : \"\";\n const part = (v: string | undefined) => {\n if (!v) return 0.5;\n if (v === \"left\" || v === \"top\") return 0;\n if (v === \"right\" || v === \"bottom\") return 1;\n if (v.endsWith(\"%\")) return Math.min(1, Math.max(0, Number.parseFloat(v) / 100));\n return 0.5;\n };\n const [x, y] = pos.trim().split(/\\s+/);\n return { align: [part(x), part(y)], crop: Boolean(media) };\n }\n\n function pairFor(key: string, card: HTMLElement): PairGeometry {\n sources ??= sharedElements(card);\n const src = sources.get(key) ?? null;\n const dst = destinations.get(key) ?? null;\n const skip = (reason: SkipReason): PairGeometry => ({\n key,\n mode: \"skip\",\n reason,\n src,\n dst,\n srcBox: ZERO,\n dstBox: ZERO,\n scale: 1,\n });\n if (!isShared(key)) return skip(\"not-shared\");\n if (!src) return skip(\"missing-card-element\");\n if (!dst) return skip(\"missing-sheet-element\");\n const srcBox = rectOf(src);\n const dstBox = rectOf(dst);\n if (area(srcBox) === 0) return skip(\"missing-card-element\");\n if (area(dstBox) === 0) return skip(\"missing-sheet-element\");\n // Never fly to a place the reader cannot see: the copy would end up\n // floating over an unrelated part of the screen. The source may be cut off\n // by the list's edge: the surface starts at the visible part of the card,\n // so a hidden source stays hidden until the growing surface reveals it.\n if (!isOnScreen(dstBox, visibleBoxOf(dst))) return skip(\"sheet-element-offscreen\");\n const declared = dst.getAttribute(\"data-morph-mode\") ?? src.getAttribute(\"data-morph-mode\");\n const mode =\n declared === \"box\" || declared === \"text\"\n ? declared\n : /^(img|svg|video|canvas|picture)$/i.test(dst.tagName)\n ? \"box\"\n : \"text\";\n const srcStyle = getComputedStyle(src);\n const dstStyle = getComputedStyle(dst);\n const decision = planPair({\n src: srcBox,\n dst: dstBox,\n mode,\n srcFont: Number.parseFloat(srcStyle.fontSize) || 16,\n dstFont: Number.parseFloat(dstStyle.fontSize) || 16,\n srcLines: mode === \"text\" ? textLines(src, srcBox.height, srcStyle) : 1,\n dstLines: mode === \"text\" ? textLines(dst, dstBox.height, dstStyle) : 1,\n srcClipped: mode === \"text\" && isClipped(src, srcStyle),\n });\n return {\n key,\n mode: decision.crossfade ? \"crossfade\" : \"scale\",\n src,\n dst,\n srcBox,\n dstBox,\n scale: decision.scale,\n fill:\n decision.crossfade && mode === \"box\"\n ? { radius: [radiusOf(src, srcBox.width), radiusOf(dst, dstBox.width)], ...cropOf(src) }\n : undefined,\n };\n }\n\n const sheetBox = rectOf(sheet);\n let reason: SkipReason | undefined;\n let cardBox = ZERO;\n let clipBox = ZERO;\n let shift = NO_SHIFT;\n if (isReduced) reason = \"reduced-motion\";\n else if (!card || !card.isConnected) reason = \"no-card\";\n else if (area(sheetBox) === 0) reason = \"sheet-hidden\";\n else {\n // A press effect (scale on :active) would shrink the measured card.\n settleTransitions(card);\n cardBox = rectOf(card);\n // Never fly from (or back to) a card the reader cannot see at all. A\n // card the reader can click, even one cut off by the edge of the\n // screen or of its list, grows from the part that shows.\n const view = visibleBoxOf(card);\n const shown = view ? intersect(cardBox, view) : null;\n if (!isSeen(shown)) reason = \"card-offscreen\";\n else {\n // The flight is drawn inside the sheet. A sheet smaller than the\n // screen (a centred panel) may not cover the card: it then starts\n // moved over the card and slides into place while it grows. A\n // transform would drag position: fixed children, so those sheets\n // only use the part of the card under them.\n if (!hasFixedDescendant(sheet)) shift = coverShift(shown, sheetBox);\n const under = intersect(shown as Box, moveBox(sheetBox, shift));\n if (!isSeen(under)) reason = \"card-offscreen\";\n // The surface starts as the part of the card the reader sees, not the\n // part hidden under a toolbar or the list's edge.\n else clipBox = under;\n }\n }\n const pairs: PairGeometry[] =\n reason || !card\n ? keys.map((key) => ({\n key,\n mode: \"skip\" as const,\n reason: reason ?? \"no-card\",\n src: null,\n dst: destinations.get(key) ?? null,\n srcBox: ZERO,\n dstBox: ZERO,\n scale: 1,\n }))\n : keys.map((key) => pairFor(key, card));\n\n let colors: [string, string] | null = null;\n let border: string | null = null;\n let radius = 0;\n let sheetRadius = 0;\n if (!reason && card) {\n const cardStyle = getComputedStyle(card);\n const sheetStyle = getComputedStyle(sheet);\n const from = cardStyle.backgroundColor;\n const to = sheetStyle.backgroundColor;\n if (from !== to && !TRANSPARENT.test(from) && !TRANSPARENT.test(to)) colors = [from, to];\n if ((Number.parseFloat(cardStyle.borderTopWidth) || 0) > 0 && !TRANSPARENT.test(cardStyle.borderTopColor)) {\n border = cardStyle.borderTopColor;\n }\n radius = hooks.radius ?? parseRadius(cardStyle.borderTopLeftRadius, cardBox.width);\n sheetRadius = parseRadius(sheetStyle.borderTopLeftRadius, sheetBox.width);\n }\n\n // Everything is drawn inside the sheet, so boxes on the card side are\n // given relative to where the sheet is when it covers the card.\n const back = { x: -shift.x, y: -shift.y };\n if (reason) shift = NO_SHIFT;\n const local = reason ? pairs : pairs.map((p) => (p.mode === \"skip\" ? p : { ...p, srcBox: moveBox(p.srcBox, back) }));\n\n return {\n plan: {\n direction,\n choreography: reason ? \"fade\" : \"morph\",\n reason,\n reduced: isReduced,\n backgroundScaled: Boolean(backgroundScaled),\n pairs: pairs.map(({ key, mode, reason: why }) => (why ? { key, mode, reason: why } : { key, mode })),\n },\n card: reason ? null : card,\n cardBox: moveBox(cardBox, back),\n clipBox: moveBox(clipBox, back),\n sheetBox,\n shift,\n unit,\n radius,\n sheetRadius,\n colors,\n border,\n pairs: local,\n };\n}\n\nexport function backgroundOriginFor(background: HTMLElement): string {\n const unit = unitOf(background.getBoundingClientRect().width, background.offsetWidth);\n const visible = screenVisibleBoxOf(background);\n return backgroundOrigin(toLocal(screenRectOf(background), unit), visible ? toLocal(visible, unit) : null);\n}\n","/**\n * createMorph: a card that grows into a full detail sheet and shrinks back.\n *\n * The sheet is one surface whose clip-path starts as the card's shape. Shared\n * elements (data-morph=\"key\") fly from the card to their place on the sheet.\n * Everything else fades or slides. All motion uses the Web Animations API, so\n * a close that arrives mid-open reverses the running animations from where\n * they are instead of jumping.\n */\nimport { FOCUSABLE, GHOST_ATTR, Undo, focusTargetIn, hasFixedDescendant, restoreScroll, saveScroll, scrollerOf } from \"./dom\";\nimport { buildAnimations } from \"./animate\";\nimport { activate, deactivate, isTopLayer } from \"./layers\";\nimport { backgroundOriginFor, measureTransition } from \"./measure\";\nimport { choreography, defaults, durationFor, resolveTiming } from \"./timing\";\nimport type { CloseOptions, Morph, MorphOptions, MorphPlan, MorphState } from \"./types\";\nimport type { Run, Session } from \"./transition\";\n\n// Internal engine consumers (examples and fixtures) share the same contracts.\nexport type { CloseOptions, Morph, MorphOptions, MorphPlan, MorphState, MorphTiming, PairReport, SkipReason } from \"./types\";\nexport { choreography, defaults, resolveTiming } from \"./timing\";\n\nfunction time(a: Animation): number {\n return Number(a.currentTime ?? 0);\n}\n\nexport function createMorph(options: MorphOptions): Morph {\n const sheet = options.sheet;\n if (!sheet) throw new TypeError(\"morphcard: the `sheet` option is required\");\n const background = options.background ?? null;\n const scrim = options.scrim ?? null;\n if (background && (background.contains(sheet) || background === scrim)) {\n // It would scale and make inert the sheet itself.\n throw new TypeError(\"morphcard: `background` must not contain the sheet\");\n }\n if (scrim?.contains(sheet)) throw new TypeError(\"morphcard: `scrim` must not contain the sheet\");\n // Closed means hidden: the library shows the sheet only while it is used.\n sheet.hidden = true;\n if (scrim) scrim.hidden = true;\n for (const el of [sheet, scrim]) {\n if (el?.isConnected && getComputedStyle(el).display !== \"none\") {\n console.warn(\n \"morphcard: an element with the hidden attribute is still displayed. A display rule in your CSS overrides [hidden]; add `[hidden] { display: none !important }`.\",\n el,\n );\n }\n }\n\n let timing = resolveTiming(options, defaults);\n let hooks = {\n prepare: options.prepare,\n onStateChange: options.onStateChange,\n shared: options.shared,\n radius: options.radius,\n scroller: options.scroller,\n resolveCard: options.resolveCard,\n };\n\n let state: MorphState = \"closed\";\n let current: HTMLElement | null = null;\n let returnTo: HTMLElement | null = null;\n let gen = 0;\n let run: Run | null = null;\n let holds: Animation[] = [];\n let session: Session | null = null;\n let plan: MorphPlan | null = null;\n let lockTimer: ReturnType<typeof setTimeout> | undefined;\n let destroyed = false;\n const waiters = new Set<{ target: \"open\" | \"closed\"; resolve: (reached: boolean) => void }>();\n // inert on the sheet and scrim while they move: undone at the end of every run.\n const runUndo = new Undo();\n // inert on the background: undone as soon as a close starts.\n const inertUndo = new Undo();\n // Anything else kept while the sheet is shown (tabindex on the sheet).\n const sessionUndo = new Undo();\n\n const reduced = () =>\n timing.reducedMotion === \"system\"\n ? typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches\n : timing.reducedMotion;\n\n function setState(next: MorphState) {\n if (state === next) return;\n state = next;\n if (next === \"closed\") sheet.removeAttribute(\"data-morph-state\");\n else sheet.setAttribute(\"data-morph-state\", next);\n hooks.onStateChange?.(next, current);\n }\n\n function wait(target: \"open\" | \"closed\"): Promise<boolean> {\n return new Promise((resolve) => waiters.add({ target, resolve }));\n }\n\n function resolveWaiters(reached: \"open\" | \"closed\") {\n for (const waiter of waiters) waiter.resolve(waiter.target === reached);\n waiters.clear();\n }\n\n // ------------------------------------------------------------- lifecycle\n\n function applyHolds() {\n cancelHolds();\n const hold = (el: Element, frame: Keyframe) => holds.push(el.animate([frame, frame], { duration: 0, fill: \"forwards\" }));\n if (background && session?.scaled) {\n hold(background, { transform: `scale(${session.scale})`, transformOrigin: session.origin });\n }\n if (scrim) hold(scrim, { opacity: 1 });\n }\n\n function cancelHolds() {\n for (const a of holds) a.cancel();\n holds = [];\n }\n\n /**\n * inert while the surface moves: clicks pass through to the page below (so\n * a card can be clicked again mid-close) and nothing inside takes focus.\n * An attribute, not an inline style, so nothing lingers after cleanup.\n */\n function lock(ms?: number) {\n if (!sheet.inert) runUndo.attr(sheet, \"inert\", \"\");\n if (scrim && !scrim.inert) runUndo.attr(scrim, \"inert\", \"\");\n clearTimeout(lockTimer);\n if (ms !== undefined) {\n const owner = run;\n lockTimer = setTimeout(() => {\n if (run === owner) runUndo.flush();\n }, ms);\n }\n }\n\n function unlock() {\n clearTimeout(lockTimer);\n runUndo.flush();\n }\n\n /** Keeps clicks and keys off the page behind while the sheet opens and stays open. */\n function shield() {\n if (background && !background.inert && inertUndo.size === 0) inertUndo.attr(background, \"inert\", \"\");\n }\n\n function focusIn() {\n const target = sheet.querySelector<HTMLElement>(\"[data-morph-focus]\") ?? sheet.querySelector<HTMLElement>(FOCUSABLE);\n if (target && !target.closest(`[${GHOST_ATTR}]`)) {\n target.focus({ preventScroll: true });\n return;\n }\n if (!sheet.hasAttribute(\"tabindex\")) sessionUndo.attr(sheet, \"tabindex\", \"-1\");\n sheet.focus({ preventScroll: true });\n }\n\n function focusOut() {\n const active = document.activeElement;\n const lost = !active || active === document.body || sheet.contains(active);\n // preventScroll: focusing must not undo the restored scroll position.\n if (lost && returnTo?.isConnected) returnTo.focus({ preventScroll: true });\n }\n\n function watch(r: Run) {\n const owner = gen;\n Promise.allSettled(r.anims.map((a) => a.finished)).then(() => {\n // A newer transition owns the state now; leave it alone.\n if (owner !== gen || run !== r) return;\n settle(reachedBy(r));\n });\n }\n\n function reachedBy(r: Run): \"open\" | \"closed\" {\n return (r.kind === \"open\") === (r.dir === 1) ? \"open\" : \"closed\";\n }\n\n function settle(target: \"open\" | \"closed\") {\n const r = run;\n run = null;\n if (r) {\n for (const a of r.anims) a.cancel();\n for (const ghost of r.ghosts) ghost.remove();\n }\n unlock();\n if (target === \"open\") {\n applyHolds();\n shield();\n focusIn();\n setState(\"open\");\n } else {\n deactivate(sheet);\n cancelHolds();\n inertUndo.flush();\n focusOut();\n sessionUndo.flush();\n sheet.hidden = true;\n if (scrim) scrim.hidden = true;\n setState(\"closed\");\n current = null;\n returnTo = null;\n session = null;\n }\n resolveWaiters(target);\n }\n\n /** Plays the current run the other way from where it is now. */\n function flip(r: Run) {\n gen++;\n r.dir = r.dir === 1 ? -1 : 1;\n const target = reachedBy(r);\n setState(target === \"open\" ? \"opening\" : \"closing\");\n if (target === \"closed\") {\n // The list is usable again while the sheet shrinks away.\n inertUndo.flush();\n lock();\n } else {\n unlock();\n shield();\n }\n const elapsed = Math.max(0, ...r.anims.map(time));\n const now = Number(document.timeline.currentTime ?? Number.NaN);\n const destinationMs = durationFor(target === \"open\" ? \"open\" : \"close\", timing, plan?.choreography === \"fade\");\n if (elapsed <= 0 || !Number.isFinite(now) || destinationMs <= 0) {\n // Nothing has been painted yet: there is nothing to reverse.\n settle(target);\n return;\n }\n const speed = r.duration > 0 ? r.duration / destinationMs : 1;\n const rate = r.dir * speed;\n for (const a of r.anims) {\n // Every animation of a run shares one clock. Seeking them all to the\n // same point keeps short fades in step with the long flights.\n // Let the browser establish the next start time. Assigning startTime\n // directly can advance WebKit's composited transform within this task,\n // even though currentTime still reports the saved position.\n a.pause();\n a.playbackRate = rate;\n a.currentTime = elapsed;\n a.play();\n }\n watch(r);\n }\n\n function begin(card: HTMLElement | null): Promise<boolean> {\n const owner = ++gen;\n activate(sheet);\n current = card;\n session = { scroll: null, scaled: false, scale: 1, origin: \"50% 30%\" };\n setState(\"opening\");\n const result = wait(\"open\");\n let prepared: void | Promise<void>;\n try {\n prepared = hooks.prepare?.(card);\n } catch (error) {\n settle(\"closed\");\n throw error;\n }\n if (prepared && typeof (prepared as Promise<void>).then === \"function\") {\n (prepared as Promise<void>).then(\n () => {\n if (owner === gen) start();\n },\n (error: unknown) => {\n if (owner !== gen) return;\n settle(\"closed\");\n if (typeof reportError === \"function\") reportError(error);\n },\n );\n } else {\n start();\n }\n return result;\n }\n\n function start() {\n try {\n startOpen();\n } catch (error) {\n gen++;\n settle(\"closed\");\n throw error;\n }\n }\n\n function startOpen() {\n const card = current;\n const isReduced = reduced();\n const s = session as Session;\n if (card) s.scroll = saveScroll(hooks.scroller ?? scrollerOf(card));\n if (background && !isReduced && timing.backgroundScale !== false && !hasFixedDescendant(background)) {\n s.scaled = true;\n s.scale = timing.backgroundScale;\n s.origin = backgroundOriginFor(background);\n }\n sheet.hidden = false;\n if (scrim) scrim.hidden = false;\n sheet.scrollTop = 0;\n for (const el of sheet.querySelectorAll(\"*\")) if (el.scrollTop > 0) el.scrollTop = 0;\n\n const g = measureTransition(\"open\", card, isReduced, { ...hooks, sheet, backgroundScaled: s.scaled });\n plan = g.plan;\n returnTo = pickReturn(card);\n shield();\n\n const r: Run = { kind: \"open\", dir: 1, anims: [], ghosts: [], duration: durationFor(\"open\", timing, g.plan.choreography === \"fade\") };\n run = r;\n buildAnimations(r, g, { sheet, background, scrim, timing, session });\n // The second click of a double click must not land on the sheet's content.\n const openMs = g.plan.choreography === \"morph\" ? timing.duration.open : choreography.fade.surface * 2;\n lock(0.5 * openMs * timing.timeScale);\n watch(r);\n }\n\n function pickReturn(card: HTMLElement | null): HTMLElement | null {\n const active = document.activeElement as HTMLElement | null;\n if (card) return active && card.contains(active) ? active : focusTargetIn(card);\n return active && active !== document.body && !sheet.contains(active) ? active : null;\n }\n\n function beginClose(): Promise<boolean> {\n try {\n return startClose();\n } catch (error) {\n gen++;\n settle(\"closed\");\n throw error;\n }\n }\n\n function startClose(): Promise<boolean> {\n gen++;\n const isReduced = reduced();\n setState(\"closing\");\n cancelHolds();\n // Scroll first, then measure: the card must be found where the reader left it.\n if (timing.restoreScroll && session?.scroll) restoreScroll(session.scroll);\n const g = measureTransition(\"close\", current, isReduced, { ...hooks, sheet, backgroundScaled: Boolean(session?.scaled) });\n plan = g.plan;\n inertUndo.flush();\n const r: Run = { kind: \"close\", dir: 1, anims: [], ghosts: [], duration: durationFor(\"close\", timing, g.plan.choreography === \"fade\") };\n run = r;\n buildAnimations(r, g, { sheet, background, scrim, timing, session });\n lock();\n watch(r);\n return wait(\"closed\");\n }\n\n function open(card?: HTMLElement | null): Promise<boolean> {\n if (destroyed) return Promise.resolve(false);\n const target = card ?? null;\n if (state === \"open\") return Promise.resolve(target === current);\n if (state === \"opening\") return target === current ? wait(\"open\") : Promise.resolve(false);\n if (state === \"closing\") {\n if (run && target !== null && target === current) {\n const result = wait(\"open\");\n flip(run);\n return result;\n }\n // Another card: finish this close at once, then open the new one.\n gen++;\n settle(\"closed\");\n }\n return begin(target);\n }\n\n function close(opts?: CloseOptions): Promise<boolean> {\n if (destroyed || state === \"closed\") return Promise.resolve(state === \"closed\");\n if (state === \"closing\") return wait(\"closed\");\n let retarget = opts !== undefined && \"to\" in opts;\n let target = retarget ? (opts?.to ?? null) : current;\n if (!retarget && hooks.resolveCard) {\n const found = hooks.resolveCard(current);\n if (found !== current) {\n retarget = true;\n target = found;\n }\n }\n if (state === \"opening\") {\n if (!run) {\n // Still preparing: nothing is on screen yet.\n gen++;\n settle(\"closed\");\n return Promise.resolve(true);\n }\n if (target === current) {\n const result = wait(\"closed\");\n flip(run);\n return result;\n }\n gen++;\n settle(\"open\");\n }\n if (retarget) {\n current = target;\n returnTo = target ? focusTargetIn(target) : null;\n }\n return beginClose();\n }\n\n const onKey = (event: KeyboardEvent) => {\n if (event.key !== \"Escape\" || event.defaultPrevented || !timing.closeOnEscape || !isTopLayer(sheet)) return;\n // Keep a second Escape during close from dismissing a lower sheet.\n event.preventDefault();\n if (state === \"open\" || state === \"opening\") {\n void close();\n }\n };\n const onClick = (event: Event) => {\n const target = event.target as Element | null;\n const trigger = target?.closest?.(\"[data-morph-close]\");\n if (trigger && !trigger.closest(`[${GHOST_ATTR}]`)) void close();\n };\n document.addEventListener(\"keydown\", onKey);\n sheet.addEventListener(\"click\", onClick);\n scrim?.addEventListener(\"click\", onClick);\n\n return {\n open,\n close,\n get state() {\n return state;\n },\n get card() {\n return current;\n },\n get plan() {\n return plan;\n },\n setOptions(next) {\n timing = resolveTiming(next, timing);\n hooks = {\n prepare: \"prepare\" in next ? next.prepare : hooks.prepare,\n onStateChange: \"onStateChange\" in next ? next.onStateChange : hooks.onStateChange,\n shared: \"shared\" in next ? next.shared : hooks.shared,\n radius: \"radius\" in next ? next.radius : hooks.radius,\n scroller: \"scroller\" in next ? next.scroller : hooks.scroller,\n resolveCard: \"resolveCard\" in next ? next.resolveCard : hooks.resolveCard,\n };\n },\n destroy() {\n if (destroyed) return;\n gen++;\n if (state !== \"closed\") settle(\"closed\");\n destroyed = true;\n document.removeEventListener(\"keydown\", onKey);\n sheet.removeEventListener(\"click\", onClick);\n scrim?.removeEventListener(\"click\", onClick);\n },\n };\n}\n","/**\n * useMorph: the public API. The sheet stays mounted; the hook shows and hides\n * it. The engine underneath (createMorph in ./morph) has no React in it and\n * is not part of the package's exports.\n *\n * const morph = useMorph<Delivery>();\n * <main ref={morph.backgroundRef}>\n * <article ref={morph.cardRef(d.id)} onClick={() => morph.open({ key: d.id, item: d })}>…</article>\n * </main>\n * <div ref={morph.scrimRef} data-morph-close hidden />\n * <section ref={morph.sheetRef} hidden>{morph.item && <Detail d={morph.item} />}</section>\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { createMorph } from \"./morph\";\nimport { defaults, resolveTiming } from \"./timing\";\nimport type { Morph, MorphOptions, MorphState } from \"./types\";\n\nexport type UseMorphOptions = Omit<MorphOptions, \"sheet\" | \"background\" | \"scrim\" | \"prepare\" | \"resolveCard\">;\n\n/** Identifies a card registered with `cardRef(key)`. */\nexport type MorphKey = string | number;\n\n/** The object form of `open`'s first argument. */\nexport interface MorphTarget<T> {\n /** A card registered with `cardRef(key)`. */\n key?: MorphKey;\n /** A card element. Used instead of the registered one when both are given. */\n card?: HTMLElement | null;\n /** Becomes `item` inside flushSync, before anything is measured. */\n item?: T;\n}\n\nexport interface UseMorphCloseOptions {\n /**\n * The card to return to: an element, a key registered with `cardRef`, or\n * null to fade out. Default: the card it opened from, or the element now\n * registered under the same key if the list re-rendered.\n */\n to?: HTMLElement | MorphKey | null;\n}\n\n/** Read-only view of the engine, for debugging a transition. */\nexport type MorphInstance = Pick<Morph, \"state\" | \"card\" | \"plan\">;\n\nexport interface UseMorph<T = unknown> {\n sheetRef: (el: HTMLElement | null) => void;\n backgroundRef: (el: HTMLElement | null) => void;\n scrimRef: (el: HTMLElement | null) => void;\n /** A stable callback ref for each key. `open(key)` finds the card through it. */\n cardRef: (key: MorphKey) => (el: HTMLElement | null) => void;\n state: MorphState;\n /**\n * The item passed to the latest `open`. Set before measuring and cleared\n * once the sheet has finished closing, so the sheet never empties mid-flight.\n */\n item: T | null;\n /**\n * Opens the sheet from a card element, a key registered with `cardRef`, or\n * `{ key, card, item }`. null opens without a flight (deep link). `update`\n * runs inside flushSync before anything is measured.\n */\n open(target: HTMLElement | MorphKey | MorphTarget<T> | null, update?: () => void): Promise<boolean>;\n close(options?: UseMorphCloseOptions): Promise<boolean>;\n /** The engine once the sheet is mounted, for reading `plan` and `card`. */\n readonly instance: MorphInstance | null;\n}\n\ninterface Pending {\n key: MorphKey | null;\n apply: () => void;\n}\n\ninterface QueuedOpen {\n run: () => Promise<boolean>;\n resolve: (reached: boolean) => void;\n reject: (error: unknown) => void;\n}\n\nconst isKey = (value: unknown): value is MorphKey => typeof value === \"string\" || typeof value === \"number\";\nconst isElement = (value: unknown): value is HTMLElement =>\n typeof value === \"object\" && value !== null && \"nodeType\" in value;\n\nexport function useMorph<T = unknown>(options: UseMorphOptions = {}): UseMorph<T> {\n const [state, setState] = useState<MorphState>(\"closed\");\n const [item, setItem] = useState<T | null>(null);\n const [sheet, setSheet] = useState<HTMLElement | null>(null);\n const [background, setBackground] = useState<HTMLElement | null>(null);\n const [scrim, setScrim] = useState<HTMLElement | null>(null);\n const instance = useRef<Morph | null>(null);\n const pending = useRef<Pending | null>(null);\n const queued = useRef<QueuedOpen | null>(null);\n const mounted = useRef(false);\n const initialized = useRef(false);\n const latest = useRef(options);\n latest.current = options;\n // Cards registered with cardRef, one callback per key, and the key the sheet opened from.\n const cards = useRef(new Map<MorphKey, HTMLElement>());\n const refs = useRef(new Map<MorphKey, (el: HTMLElement | null) => void>());\n const openKey = useRef<MorphKey | null>(null);\n\n // The element registered under `key`, if it is still in the document.\n const cardFor = useCallback((key: MorphKey): HTMLElement | null => {\n const el = cards.current.get(key);\n return el?.isConnected ? el : null;\n }, []);\n\n // A mount effect may request a deep link before callback refs have caused\n // the engine's first render. Keep that request until the engine is ready.\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n queueMicrotask(() => {\n if (mounted.current) return; // StrictMode immediately mounted again.\n queued.current?.resolve(false);\n queued.current = null;\n });\n };\n }, []);\n\n useEffect(() => {\n if (!sheet) return;\n const morph = createMorph({\n ...latest.current,\n sheet,\n background,\n scrim,\n prepare: () => {\n const next = pending.current;\n pending.current = null;\n openKey.current = next?.key ?? null;\n if (next) flushSync(next.apply);\n },\n // A close without `to` follows the card if the list replaced it with a\n // new element under the same key while the sheet was open.\n resolveCard: (card) => (card?.isConnected || openKey.current === null ? card : cardFor(openKey.current) || card),\n onStateChange: (next, card) => {\n setState(next);\n if (next === \"closed\") {\n openKey.current = null;\n setItem(null);\n }\n latest.current.onStateChange?.(next, card);\n },\n });\n instance.current = morph;\n initialized.current = true;\n queueMicrotask(() => {\n if (!mounted.current || instance.current !== morph) return;\n const job = queued.current;\n queued.current = null;\n // flushSync must run outside React's effect/commit phase.\n if (job) {\n try {\n job.run().then(job.resolve, job.reject);\n } catch (error) {\n job.reject(error);\n }\n }\n });\n return () => {\n morph.destroy();\n if (instance.current === morph) instance.current = null;\n setState(\"closed\");\n };\n }, [sheet, background, scrim]);\n\n // Options are declarative: one removed since the last render goes back to\n // its default instead of keeping the old value. Applied after every render,\n // and again right before open and close so a run never uses stale ones.\n const applyOptions = useCallback(() => {\n const next = latest.current;\n instance.current?.setOptions({\n ...resolveTiming(next, defaults),\n shared: next.shared,\n radius: next.radius,\n scroller: next.scroller,\n });\n }, []);\n useEffect(applyOptions);\n\n const cardRef = useCallback((key: MorphKey) => {\n let ref = refs.current.get(key);\n if (!ref) {\n ref = (el: HTMLElement | null) => {\n if (el) {\n cards.current.set(key, el);\n return;\n }\n // React may attach the next element for this key before or after it\n // detaches the old one. Forget the key once the commit is done and\n // nothing connected is left under it.\n queueMicrotask(() => {\n if (cards.current.get(key)?.isConnected) return;\n cards.current.delete(key);\n refs.current.delete(key);\n });\n };\n refs.current.set(key, ref);\n }\n return ref;\n }, []);\n\n const open = useCallback((target: HTMLElement | MorphKey | MorphTarget<T> | null, update?: () => void): Promise<boolean> => {\n let card: HTMLElement | null = null;\n let key: MorphKey | null = null;\n let hasItem = false;\n let nextItem: T | null = null;\n if (isKey(target)) key = target;\n else if (isElement(target)) card = target;\n else if (target) {\n key = target.key ?? null;\n card = target.card ?? null;\n if (\"item\" in target) {\n hasItem = true;\n nextItem = target.item ?? null;\n }\n }\n if (!card && key !== null) card = cardFor(key);\n const apply = () => {\n if (hasItem) setItem(() => nextItem);\n update?.();\n };\n const morph = instance.current;\n if (!morph) {\n if (!initialized.current && mounted.current) {\n queued.current?.resolve(false);\n return new Promise<boolean>((resolve, reject) => {\n queued.current = { run: () => open(target, update), resolve, reject };\n });\n }\n apply();\n return Promise.resolve(false);\n }\n applyOptions();\n pending.current = { key, apply };\n try {\n return morph.open(card);\n } finally {\n // prepare runs synchronously; do not retain updates from refused/failed opens.\n pending.current = null;\n }\n }, [cardFor, applyOptions]);\n\n const close = useCallback((opts?: UseMorphCloseOptions) => {\n queued.current?.resolve(false);\n queued.current = null;\n const morph = instance.current;\n if (!morph) return Promise.resolve(true);\n applyOptions();\n if (!opts || !(\"to\" in opts)) return morph.close();\n const to = opts.to ?? null;\n return morph.close({ to: isKey(to) ? cardFor(to) : to });\n }, [cardFor, applyOptions]);\n\n return useMemo(\n () => ({\n sheetRef: setSheet,\n backgroundRef: setBackground,\n scrimRef: setScrim,\n cardRef,\n state,\n item,\n open,\n close,\n get instance(): MorphInstance | null {\n return instance.current;\n },\n }),\n [state, item, cardRef, open, close],\n );\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "react-morphcard",
3
+ "version": "0.1.0",
4
+ "description": "React hook for a card that grows into a full detail screen and shrinks back, with shared elements flying between the two. Works in any modern browser, installed PWAs and WebViews. Not for React Native. No dependencies besides React.",
5
+ "keywords": [
6
+ "react",
7
+ "react-hook",
8
+ "hook",
9
+ "animation",
10
+ "shared-element-transition",
11
+ "card",
12
+ "detail-view",
13
+ "transition",
14
+ "web-animations-api",
15
+ "nextjs",
16
+ "pwa",
17
+ "webview"
18
+ ],
19
+ "homepage": "https://morphcard.lucaspiera.com",
20
+ "bugs": "https://github.com/pieralukasz/react-morphcard/issues",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/pieralukasz/react-morphcard.git"
24
+ },
25
+ "license": "MIT",
26
+ "author": "Łukasz Piera (https://lucaspiera.com)",
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "main": "./dist/index.js",
37
+ "module": "./dist/index.js",
38
+ "types": "./dist/index.d.ts",
39
+ "files": [
40
+ "dist"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "scripts": {
46
+ "build": "tsdown",
47
+ "build:examples": "tsdown -c tsdown.fixtures.config.ts",
48
+ "prepare": "tsdown",
49
+ "dev": "tsdown --watch",
50
+ "typecheck": "tsc --noEmit",
51
+ "test": "tsdown && vitest run",
52
+ "test:e2e": "pnpm build:examples && playwright test",
53
+ "serve": "pnpm build:examples && node scripts/serve.mjs",
54
+ "check:package": "publint",
55
+ "prepublishOnly": "pnpm typecheck && pnpm test"
56
+ },
57
+ "peerDependencies": {
58
+ "react": ">=18",
59
+ "react-dom": ">=18"
60
+ },
61
+ "devDependencies": {
62
+ "@playwright/test": "1.63.0",
63
+ "@types/node": "^26.6.1",
64
+ "@types/react": "^19.3.0",
65
+ "@types/react-dom": "^19.3.0",
66
+ "publint": "^0.3.18",
67
+ "react": "^19.3.0",
68
+ "react-dom": "^19.3.0",
69
+ "tsdown": "^0.23.0",
70
+ "typescript": "^7.0.2",
71
+ "vitest": "^5.0.2"
72
+ },
73
+ "packageManager": "pnpm@12.4.2"
74
+ }