@office-kit/pptx-editor 0.0.0-stage → 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":"animation-player-D2mt2MI8.js","names":[],"sources":["../src/core/animation-player.ts"],"sourcesContent":["/**\n * Object animation playback against a rendered slide.\n *\n * One implementation, three callers: the development preview's presentation\n * mode, its presenter view, and the editor's animation panel. They share it so\n * they cannot disagree about what a timing tree means — the preview bundles it\n * over HTTP (`/animation-player.js`), the panel imports it directly.\n *\n * The rule it is built around: **play only what the deck states.** A step whose\n * moment, target or preset this library cannot read is never guessed at — not\n * by inventing a moment for it, not by giving it a click of its own, and not\n * by deciding for itself whether the shape should be on the slide before its\n * turn. (How a known preset moves is approximated; see `Motion`.) Such a step\n * is reported as unsupported and everything it touches is left exactly as the\n * renderer drew it, which is the only state that cannot lose content.\n *\n * What that means in detail:\n *\n * - Only the main sequence. An `interactiveSeq` runs off its own trigger —\n * a click on some shape — and is not part of the slide's click order, so\n * it neither plays nor hides anything here.\n * - A `click` step opens a stop, wherever it appears: a click stop is stated\n * by the tree, so a group of known effects after an unsupported one still\n * plays. `withPrevious` runs from the start of the group in hand and\n * `afterPrevious` from its end. The first step of a slide has no\n * predecessor, so a leading `withPrevious` / `afterPrevious` starts as the\n * slide appears rather than waiting for a click.\n * - A step whose start, length, delay, target or preset we cannot read makes\n * the rest of *its own group* unplaceable: an `afterPrevious` chained onto\n * an effect of unknown length has no stated moment, and the `withPrevious`\n * effects sharing that start have none either. That span is unsupported.\n * The next click stop starts from a stated moment again.\n * - A shape id that is drawn more than once is not a handle. The schema puts\n * no uniqueness constraint on `<p:cNvPr id>`, and nothing says a timing\n * tree that names it means every one of them, so the step is unsupported\n * rather than animating all of them together.\n */\n\nimport type { SlideAnimationStep } from '@office-kit/pptx';\n\nconst INSTANT_EFFECTS = ['appear', 'disappear'];\n// The transition filters the reference desktop app also runs on single objects, each with an\n// `…In` entrance and an `…Out` exit.\nconst FILTER_FAMILIES = [\n 'blinds',\n 'checkerboard',\n 'peek',\n 'randomBars',\n 'shape',\n 'split',\n 'strips',\n 'wedge',\n 'wheel',\n 'wipe',\n];\n\n/** The `presetClass` of an effect the library names says which of the three it is. */\nconst PRESET_CLASS_KINDS: Readonly<Record<string, AnimationItem['kind']>> = {\n entr: 'entrance',\n exit: 'exit',\n emph: 'emphasis',\n};\n\n/**\n * What an effect does to its target beyond putting it on the slide or taking it\n * off, reproduced with the browser's own properties: `style.opacity` as\n * `opacity`, `ppt_x` / `ppt_y` as a translation, `ppt_w` / `ppt_h` as a scale\n * about the shape's centre, and `r` as a rotation about it.\n *\n * Fly (and Credits, which is a fly from below the slide) travels the distance\n * the slide gives it. A transition filter (`<p:animEffect>`) has no browser\n * equivalent, so it is drawn with an animated `clip-path` making the same\n * reveal — bars, a wedge, an outline growing out of the centre.\n *\n * Every other preset is a `pose`, and an approximation. The presets made of\n * several behaviours with timings of their own — a bounce's falls, a\n * boomerang's arc, a teeter's swings — are a `TRACK`: keyframes placed at the\n * moments the reference desktop app's own behaviours start and end (as saved in\n * test/fixtures/native/animations/), so each part keeps its share of the\n * effect at any duration, with distances the deck states against the slide\n * measured against the drawn slide. An exit plays its entrance's track\n * backwards, as the reference desktop app's own exits of these presets do, Drop and Flip\n * aside. The rest go from the pose to the shape's own place (or back, for an\n * exit) evenly over the effect's whole length. Dissolve plays as a fade.\n * Emphasis colour changes are a CSS `filter` over the drawn shape (darker,\n * lighter, greyer, or its hues turned), since the drawing has already resolved\n * the colours the deck names; like every emphasis here, they play and then\n * hand the shape back as drawn. Spin, Grow/Shrink and Transparency play the\n * angle, size and amount their Effect Options state.\n */\ntype Motion = 'none' | 'fly' | 'filter' | 'peek' | 'pose';\n\nconst motionOf = (effect: string): Motion => {\n if (INSTANT_EFFECTS.includes(effect)) return 'none';\n const family = effect.replace(/(In|Out)$/, '');\n if (family === 'fly' || family === 'credits') return 'fly';\n if (family === 'peek') return 'peek';\n return FILTER_FAMILIES.includes(family) ? 'filter' : 'pose';\n};\n\n/** Where an entrance starts and an exit ends, by preset family. */\nconst AWAY: Readonly<Record<string, Keyframe>> = {\n fade: { opacity: 0 },\n dissolve: { opacity: 0 },\n expand: { opacity: 0, scale: '0.7 1' },\n contract: { opacity: 0, scale: '0.7 1' },\n swivel: { opacity: 0, scale: '0 1' },\n zoom: { opacity: 0, scale: '0' },\n basicZoom: { scale: '0' },\n float: { opacity: 0, translate: '0% 50%' },\n growTurn: { opacity: 0, scale: '0', rotate: '90deg' },\n shrinkTurn: { opacity: 0, scale: '0', rotate: '90deg' },\n spinner: { opacity: 0, scale: '0', rotate: '-90deg' },\n stretch: { scale: '0 1' },\n stretchy: { scale: '0 1' },\n collapse: { scale: '0 1' },\n pinwheel: { opacity: 0, scale: '0', rotate: '720deg' },\n spiral: { scale: '0', translate: '-100% 100%' },\n basicSwivel: { scale: '0 1' },\n};\n\n/** Each property of a pose at the shape's own place. */\nconst AT_REST: Readonly<Record<string, string | number>> = {\n opacity: 1,\n scale: '1',\n rotate: '0deg',\n translate: '0% 0%',\n};\n\nconst restOf = (away: Keyframe): Keyframe =>\n Object.fromEntries(Object.keys(away).map((name) => [name, AT_REST[name]!]));\n\nconst turned = (from: string, to: string): Keyframe[] => [{ filter: from }, { filter: to }];\nconst flash = (from: string, to: string): Keyframe[] => [\n { filter: from },\n { filter: to },\n { filter: from },\n];\nconst HUE_TURN = turned('hue-rotate(0deg)', 'hue-rotate(180deg)');\nconst CONTRAST_FLASH = flash('contrast(1)', 'contrast(1.8)');\n\n/** The frames of each emphasis effect, which starts and ends with the shape as drawn. */\nconst EMPHASIS: Readonly<Record<string, Keyframe[]>> = {\n // Up to 105 % and back while it fades to half between a fifth and four fifths.\n pulse: [\n { offset: 0, scale: '1', opacity: 1 },\n { offset: 0.2, opacity: 0.5 },\n { offset: 0.5, scale: '1.05' },\n { offset: 0.8, opacity: 0.5 },\n { offset: 1, scale: '1', opacity: 1 },\n ],\n // Two degrees out and back over the first tenth, then four-degree swings\n // a fifth apiece (the reference desktop app's five `<p:animRot>`, the first waiting a tenth).\n teeter: [\n { offset: 0, rotate: '0deg' },\n { offset: 0.1, rotate: '2deg' },\n { offset: 0.2, rotate: '2deg' },\n { offset: 0.4, rotate: '-2deg' },\n { offset: 0.6, rotate: '2deg' },\n { offset: 0.8, rotate: '-2deg' },\n { offset: 1, rotate: '0deg' },\n ],\n // Lifted and set down again over the whole length while it rocks 25° each\n // way a quarter apiece.\n wave: [\n { offset: 0, translate: '0% 0%', rotate: '0deg', easing: 'ease-in-out' },\n { offset: 0.25, rotate: '25deg' },\n { offset: 0.5, translate: '0% -20%', rotate: '0deg', easing: 'ease-in-out' },\n { offset: 0.75, rotate: '-25deg' },\n { offset: 1, translate: '0% 0%', rotate: '0deg' },\n ],\n shimmer: [\n { scale: '1', translate: '0% 0%', rotate: '0deg' },\n { scale: '0.8 1', translate: '10% -10%', rotate: '-8deg' },\n { scale: '1', translate: '0% 0%', rotate: '0deg' },\n ],\n // Hidden for the first half, then shown (`calcmode=\"discrete\"`).\n blink: [\n { offset: 0, opacity: 0, easing: 'step-end' },\n { offset: 0.5, opacity: 1 },\n { offset: 1, opacity: 1 },\n ],\n fillColor: HUE_TURN,\n lineColor: HUE_TURN,\n fontColor: HUE_TURN,\n objectColor: HUE_TURN,\n brushColor: HUE_TURN,\n complementaryColor: HUE_TURN,\n complementaryColor2: HUE_TURN,\n contrastingColor: HUE_TURN,\n darken: turned('brightness(1)', 'brightness(0.6)'),\n lighten: turned('brightness(1)', 'brightness(1.4)'),\n desaturate: turned('saturate(1)', 'saturate(0)'),\n colorPulse: flash('brightness(1)', 'brightness(1.4)'),\n growWithColor: [\n { scale: '1', filter: 'hue-rotate(0deg)' },\n { scale: '1.1', filter: 'hue-rotate(180deg)' },\n ],\n // Bold from half-way to six tenths of the way through (`calcmode=\"discrete\"`).\n boldFlash: [\n { offset: 0, filter: 'contrast(1)', easing: 'step-end' },\n { offset: 0.5, filter: 'contrast(1.8)', easing: 'step-end' },\n { offset: 0.6, filter: 'contrast(1)' },\n { offset: 1, filter: 'contrast(1)' },\n ],\n boldReveal: CONTRAST_FLASH,\n underline: CONTRAST_FLASH,\n};\n\n/**\n * The frames of an emphasis effect whose Effect Options decide how far it\n * goes: Spin's angle and direction, Grow/Shrink's size and axes,\n * Transparency's amount. `null` for every other effect.\n */\nconst optionedEmphasis = (step: SlideAnimationStep): Keyframe[] | null => {\n switch (step.effect) {\n case 'spin': {\n const sign = step.spinDirection === 'counterclockwise' ? -1 : 1;\n return [{ rotate: '0deg' }, { rotate: `${sign * (step.spinDegrees ?? 360)}deg` }];\n }\n case 'growShrink': {\n const size = (step.scalePercent ?? 150) / 100;\n const scale =\n step.scaleDirection === 'horizontal'\n ? `${size} 1`\n : step.scaleDirection === 'vertical'\n ? `1 ${size}`\n : `${size}`;\n return [{ scale: '1' }, { scale }];\n }\n case 'transparency':\n return [{ opacity: 1 }, { opacity: 1 - (step.transparencyPercent ?? 50) / 100 }];\n default:\n return null;\n }\n};\n\n/**\n * Where a track puts the shape: a translation by fractions of the slide's\n * width and height — which is how the reference desktop app states these presets' distances\n * (`#ppt_x+0.4`) — plus fractions of the shape's own box, in the units the\n * element's own CSS transform is written in. `null` before the slide is laid\n * out, when nothing can be measured.\n */\ninterface Geometry {\n shift(slideX: number, slideY: number, ownX?: number, ownY?: number): string | null;\n /** Clear of the slide past the top or bottom edge, as a fly leaves it. */\n past(edge: 'top' | 'bottom'): { readonly dx: number; readonly dy: number } | null;\n}\n\n/** The time-to-progress curve of a `tmFilter`, read at `t`. */\nconst filtered = (points: readonly (readonly [number, number])[], t: number): number => {\n for (let at = 1; at < points.length; at += 1) {\n const [t1, p1] = points[at]!;\n const [t0, p0] = points[at - 1]!;\n if (t <= t1) return p0 + ((p1 - p0) * (t - t0)) / (t1 - t0);\n }\n return 1;\n};\n\n// Bounce's sideways drift (`tmFilter` on its `ppt_x`) and the moments it\n// lands, in milliseconds of its 1822: a third of the slide's height to fall,\n// then bounces of a ninth, a twenty-seventh and an eighty-first.\nconst BOUNCE_DRIFT: readonly (readonly [number, number])[] = [\n [0, 0],\n [0.14, 0.36],\n [0.43, 0.73],\n [0.71, 0.91],\n [1, 1],\n];\nconst BOUNCE_LENGTH = 1822;\nconst BOUNCE_LANDINGS = [664, 1324, 1656, 1822];\nconst BOUNCE_HEIGHTS = [1 / 9, 1 / 27, 1 / 81];\n\n// Center Revolve's arc, sampled from the `<p:tav>` the reference desktop app writes for it.\nconst REVOLVE_ARC: readonly (readonly [number, number, number])[] = [\n [0, 0, 0.31],\n [0.25, 0.1096, 0.2646],\n [0.5, 0.155, 0.155],\n [0.75, 0.1096, 0.0454],\n [1, 0, 0],\n];\n\n// Curve Up's motion path (`<p:animMotion path>`): the end of each of its four\n// cubic segments, from below left of the slide to the shape's own place.\nconst CURVE_POINTS: readonly (readonly [number, number])[] = [\n [-0.46736, 0.92887],\n [0.0908, 0.66613],\n [0.23177, 0.40825],\n [0.18264, 0.09152],\n [0, 0],\n];\n\nconst frame = (offset: number, translate: string | null, rest: Keyframe = {}): Keyframe | null =>\n translate === null ? null : { offset, translate, ...rest };\n\nconst all = (frames: (Keyframe | null)[]): Keyframe[] | null =>\n frames.every((f) => f !== null) ? (frames as Keyframe[]) : null;\n\n/**\n * The entrance presets made of several behaviours, as keyframes from where the\n * shape starts to its own place. Each offset is where one of the reference desktop app's\n * behaviours starts or ends, as a fraction of the preset's default length.\n */\nconst TRACKS: Readonly<Record<string, (g: Geometry) => Keyframe[] | null>> = {\n bounce: (g) => {\n const at = (ms: number, height: number, easing: string): Keyframe | null =>\n frame(\n ms / BOUNCE_LENGTH,\n g.shift(-0.25 * (1 - filtered(BOUNCE_DRIFT, ms / BOUNCE_LENGTH)), -height),\n {\n easing,\n },\n );\n const frames: (Keyframe | null)[] = [at(0, 1 / 3, 'ease-in')];\n BOUNCE_LANDINGS.forEach((landing, i) => {\n frames.push(at(landing, 0, 'ease-out'));\n const next = BOUNCE_LANDINGS[i + 1];\n if (next !== undefined) frames.push(at((landing + next) / 2, BOUNCE_HEIGHTS[i]!, 'ease-in'));\n });\n return all(frames);\n },\n boomerang: (g) =>\n all([\n frame(0, g.shift(0.4, -0.2), {\n rotate: '-90deg',\n scale: '1 1',\n opacity: 0,\n easing: 'ease-out',\n }),\n frame(0.5, g.shift(0, 0.1), {\n rotate: '0deg',\n scale: '0.05 1',\n opacity: 0.5,\n easing: 'ease-in',\n }),\n frame(1, g.shift(0, 0), { rotate: '0deg', scale: '1 1', opacity: 1 }),\n ]),\n // Faded in over the first tenth, held below its place until four tenths,\n // then swung round to it.\n centerRevolve: (g) =>\n all([\n frame(0, g.shift(0, 0.31), { opacity: 0 }),\n frame(0.1, g.shift(0, 0.31), { opacity: 1 }),\n ...REVOLVE_ARC.map(([t, x, y]) => frame(0.4 + 0.6 * t, g.shift(x, y), { opacity: 1 })),\n ]),\n // Up from a slide's height below to just past its place in nine tenths,\n // then settling back.\n riseUp: (g) =>\n all([\n frame(0, g.shift(0, 1), { opacity: 0, easing: 'ease-out' }),\n frame(0.9, g.shift(0, -0.03), { opacity: 0.9, easing: 'ease-in' }),\n frame(1, g.shift(0, 0), { opacity: 1 }),\n ]),\n floating: (g) =>\n all([\n frame(0, g.shift(0.4, -0.4), { rotate: '-90deg', opacity: 0, easing: 'ease-out' }),\n frame(0.8, g.shift(-0.05, 0.1), { rotate: '0deg', opacity: 1, easing: 'ease-in' }),\n frame(1, g.shift(0, 0), { rotate: '0deg', opacity: 1 }),\n ]),\n // Out of a tenth of its size to just past full size half-way, with a tenth\n // of the slide's swing to the right, opaque from half-way.\n whip: (g) =>\n all([\n frame(0, g.shift(0, 0), { scale: '0.1', opacity: 0 }),\n frame(0.5, g.shift(0.1, 0), { scale: '1.02', opacity: 1 }),\n frame(1, g.shift(0, 0), { scale: '1', opacity: 1 }),\n ]),\n curveUp: (g) =>\n all(\n CURVE_POINTS.map(([x, y], i) =>\n frame(i / (CURVE_POINTS.length - 1), g.shift(x, y), {\n scale: `${2.5 - (1.5 * i) / (CURVE_POINTS.length - 1)}`,\n opacity: i / (CURVE_POINTS.length - 1),\n }),\n ),\n ),\n // Tilted 45° back as it falls from a slide's height above for 45.5 % of the\n // length, bounced half its height, then swung through 45° and down.\n drop: (g) =>\n all([\n frame(0, g.shift(0, -1), { rotate: '-45deg', easing: 'ease-in' }),\n frame(0.455, g.shift(0, 0, 0, -10), { rotate: '-45deg', easing: 'ease-out' }),\n frame(0.611, g.shift(0, 0, 0, -50), { rotate: '0deg', easing: 'ease-in' }),\n frame(0.767, g.shift(0, 0, 0, -10), { rotate: '42deg' }),\n frame(0.864, g.shift(0, 0, 0, -10), { rotate: '15deg' }),\n frame(0.91, g.shift(0, 0, 0, -5), { rotate: '0deg' }),\n frame(1, g.shift(0, 0), { rotate: '0deg' }),\n ]),\n // Falls from just above the slide while it turns once and flips over,\n // drifting half its width aside half-way.\n flip: (g) => flipTrack(g, 'top'),\n};\n\nconst flipTrack = (g: Geometry, edge: 'top' | 'bottom'): Keyframe[] | null => {\n const past = g.past(edge);\n if (past === null) return null;\n const at = (share: number, own: number): string =>\n `calc(${past.dx * share}px + ${own}%) calc(${past.dy * share}px + 0%)`;\n const entering = edge === 'top';\n const from = entering ? 1 : 0;\n const to = entering ? 0 : 1;\n return [\n { offset: 0, translate: at(from, 0), scale: '1 1', rotate: '0deg' },\n { offset: 0.5, translate: at(0.5, 50), scale: '-1 1', rotate: '180deg' },\n { offset: 1, translate: at(to, 0), scale: '1 1', rotate: '360deg' },\n ];\n};\n\n/** The exits whose track is not their entrance's, played backwards. */\nconst EXIT_TRACKS: Readonly<Record<string, (g: Geometry) => Keyframe[] | null>> = {\n // Turned 45° as it falls a slide's height.\n drop: (g) =>\n all([\n frame(0, g.shift(0, 0), { rotate: '0deg', easing: 'ease-in' }),\n frame(1, g.shift(0, 1), { rotate: '45deg' }),\n ]),\n flip: (g) => flipTrack(g, 'bottom'),\n};\n\n/** The entrance track whose reverse is an exit's: Sink Down is Rise Up backwards. */\nconst TRACK_OF_EXIT: Readonly<Record<string, string>> = {\n sinkDown: 'riseUp',\n curveDown: 'curveUp',\n};\n\nconst SWAPPED_EASING: Readonly<Record<string, string>> = {\n 'ease-in': 'ease-out',\n 'ease-out': 'ease-in',\n};\n\n/**\n * A track played backwards: the last frame first, each offset mirrored, and\n * the easing of each stretch moved to the frame that now starts it, turned\n * round — a stretch that slowed into a frame speeds out of it.\n */\nconst reversed = (frames: readonly Keyframe[]): Keyframe[] => {\n const count = frames.length;\n return frames.map((_, i) => {\n const pose: Keyframe = { ...frames[count - 1 - i]! };\n delete pose.easing;\n if (typeof pose.offset === 'number') pose.offset = 1 - pose.offset;\n const easing = frames[count - 2 - i]?.easing;\n if (typeof easing === 'string') pose.easing = SWAPPED_EASING[easing] ?? easing;\n return pose;\n });\n};\n\n/** The track of a preset, in the direction the step plays it; `undefined` when it has none. */\nconst trackOf = (item: AnimationItem): ((g: Geometry) => Keyframe[] | null) | undefined => {\n const family = item.step.effect?.replace(/(In|Out)$/, '');\n if (family === undefined) return undefined;\n if (item.kind === 'entrance') return TRACKS[family];\n const own = EXIT_TRACKS[family];\n if (own !== undefined) return own;\n const entrance = TRACKS[TRACK_OF_EXIT[family] ?? family];\n return entrance === undefined\n ? undefined\n : (g) => {\n const frames = entrance(g);\n return frames === null ? null : reversed(frames);\n };\n};\n\n/** Why a step is not played. */\nexport type UnsupportedReason =\n /** It belongs to a sequence with its own trigger, not the slide's clicks. */\n | 'notInMainSeq'\n /** Its effect, target or delay is one this library only reads. */\n | 'notModelled'\n /** Its moment depends on an effect whose length or place is not stated. */\n | 'unknownTiming'\n /** More than one shape on the slide carries the id it names. */\n | 'ambiguousTarget';\n\nexport interface UnsupportedAnimation {\n readonly step: SlideAnimationStep;\n readonly reason: UnsupportedReason;\n}\n\n/** What one step does to its target, and when, within its stop. */\nexport interface AnimationItem {\n readonly step: SlideAnimationStep;\n /**\n * `'emphasis'` animates a shape that is already on the slide and leaves it\n * there, so unlike the other two it never decides whether the shape is shown.\n */\n readonly kind: 'entrance' | 'exit' | 'emphasis';\n /** Milliseconds from the start of the stop. */\n readonly begin: number;\n /** Null when the tree states no length. */\n readonly duration: number | null;\n}\n\n/** One click's worth of animation. */\nexport interface AnimationStop {\n readonly items: AnimationItem[];\n /** True when the slide starts it itself, with no click — its first step\n * runs with or after a predecessor it does not have. */\n readonly auto: boolean;\n}\n\nexport interface AnimationPlan {\n readonly stops: AnimationStop[];\n readonly unsupported: UnsupportedAnimation[];\n}\n\nexport interface AnimationProgress {\n readonly cursor: number;\n readonly stops: number;\n /** How long the stop in hand has been running; null once it has settled. */\n readonly elapsed: number | null;\n /** Bumped by every call that sets where the slide stands. */\n readonly generation: number;\n}\n\nexport interface AnimationPlayerOptions {\n /**\n * Where the slide was drawn (a shadow root is fine), or a function returning\n * it. A function is asked again on every query, because a transition draws\n * the slide into a layer of its own and the layer beside it holds a\n * different slide whose shapes may carry the very same ids.\n */\n readonly root: ParentNode | (() => ParentNode);\n readonly steps: readonly SlideAnimationStep[] | null | undefined;\n /**\n * Asked afresh on every advance, so a viewer who turns reduced motion on\n * mid-show gets the rest of the deck without motion — in the same order.\n */\n readonly reducedMotion?: () => boolean;\n /**\n * Called whenever the cursor moves and whenever the slide changes by itself\n * — a delayed effect arriving, an effect finishing — so a view mirroring the\n * slide never lags behind what the audience can see.\n */\n readonly onChange?: (player: AnimationPlayer) => void;\n}\n\nexport interface AnimationPlayer {\n readonly cursor: number;\n readonly stopCount: number;\n /** True while a click still has an effect to play on this slide. */\n readonly pending: boolean;\n /** True while an effect already started is still on its way. */\n readonly running: boolean;\n readonly progress: AnimationProgress;\n /**\n * The steps this player does not run, so a caller can say so rather than let\n * a slide look as though it has no animation.\n */\n readonly unsupported: UnsupportedAnimation[];\n reset(): void;\n /** Plays the next stop. False when the slide has none left. */\n advance(): boolean;\n /** Takes one stop back, showing everything before it. False at the start. */\n back(): boolean;\n /** Moves straight to a point in the click order, without motion. */\n jumpTo(next: number): void;\n /**\n * Shows the moment another view of the same slide is showing: the stops\n * before `next` played out, and the one it is on started `elapsed` ago — so\n * an effect waiting on a delay over there has not arrived here either, and\n * one half-way through a fade is half-way through it here.\n */\n resume(next: number, elapsed: number | null): void;\n /** Everything the slide ends with — what a still preview shows. */\n finish(): void;\n dispose(): void;\n}\n\n/** An element whose inline style we can set. */\ntype StyledElement = Element & ElementCSSInlineStyle;\n\nconst styled = (el: Element): StyledElement | null =>\n el instanceof HTMLElement || el instanceof SVGElement ? el : null;\n\n/** Whether a step reveals its target, hides it, or neither; null when we cannot tell. */\nconst kindOf = (step: SlideAnimationStep): AnimationItem['kind'] | null => {\n if (step.effect === null || step.presetClass === null) return null;\n return PRESET_CLASS_KINDS[step.presetClass] ?? null;\n};\n\n/**\n * How long an effect runs, or null when the deck does not say. Null is not\n * zero: it is the reason nothing can be chained onto the end of this effect.\n */\nconst durationOf = (step: SlideAnimationStep): number | null => {\n if (step.durationMs !== null && Number.isFinite(step.durationMs) && step.durationMs >= 0)\n return step.durationMs;\n // 'appear' and 'disappear' are instantaneous by definition of the preset, so\n // a tree that states no duration for one is not leaving anything unsaid.\n if (step.effect !== null && INSTANT_EFFECTS.includes(step.effect)) return 0;\n return null;\n};\n\n/**\n * Groups the steps into the stops the viewer clicks through, with each step's\n * start measured from the beginning of its stop, and lists the steps that are\n * left out with the reason why.\n */\nexport const buildAnimationStops = (\n steps: readonly SlideAnimationStep[] | null | undefined,\n): AnimationPlan => {\n const stops: AnimationStop[] = [];\n const unsupported: UnsupportedAnimation[] = [];\n const skip = (step: SlideAnimationStep, reason: UnsupportedReason): void => {\n unsupported.push({ step, reason });\n };\n let stop: AnimationStop | null = null;\n let groupStart: number | null = 0;\n let groupEnd: number | null = 0;\n let seen = false;\n for (const step of steps ?? []) {\n if (step.sequence !== 'mainSeq') {\n skip(step, 'notInMainSeq');\n continue;\n }\n const leading = !seen;\n seen = true;\n if (step.start === 'unknown') {\n // Nothing states whether this opens a click stop or joins the one in\n // hand, so it is neither played nor allowed to place what follows it.\n groupStart = null;\n groupEnd = null;\n skip(step, 'notModelled');\n continue;\n }\n if (step.start === 'click' || leading) {\n stop = { items: [], auto: leading && step.start !== 'click' };\n stops.push(stop);\n groupStart = 0;\n groupEnd = 0;\n } else if (step.start === 'afterPrevious') {\n groupStart = groupEnd;\n groupEnd = groupStart;\n }\n // 'withPrevious' joins the group in hand: same start, same end so far.\n const kind = step.playable ? kindOf(step) : null;\n const duration = kind === null ? null : durationOf(step);\n const delay = step.delayMs;\n if (kind === null || delay === null || groupStart === null) {\n // Its place in the click order is still known — it keeps its stop — but\n // its moment, or what it does, is not. Nothing may be chained onto it.\n skip(step, kind === null || delay === null ? 'notModelled' : 'unknownTiming');\n groupEnd = null;\n continue;\n }\n // Annotated because `groupEnd` below feeds `groupStart` on the next pass,\n // which would make the inference circular.\n const begin: number = groupStart + delay;\n stop?.items.push({ step, kind, begin, duration });\n groupEnd = duration === null || groupEnd === null ? null : Math.max(groupEnd, begin + duration);\n }\n return { stops, unsupported };\n};\n\nconst shapeSelector = (id: string): string => `[data-pptx-shape-id=\"${id}\"]`;\n\n/**\n * The elements one step animates: a whole object, or paragraphs of its text.\n * Empty when the step's target is one we do not act on.\n */\nconst targetsOf = (\n root: ParentNode,\n step: SlideAnimationStep,\n blocked: ReadonlySet<string>,\n): StyledElement[] => {\n const target = step.target;\n // 'unsupported' names a shape only as a hint about what an effect touches,\n // not as the thing to animate, so it is never resolved to an element.\n if (target.kind !== 'shape' && target.kind !== 'paragraphs') return [];\n if (!Number.isInteger(target.shapeId)) return [];\n const id = String(target.shapeId);\n if (blocked.has(id)) return [];\n const shapes = root.querySelectorAll(shapeSelector(id));\n const shape = shapes.length === 1 ? styled(shapes[0]!) : null;\n if (shape === null) return [];\n if (target.kind !== 'paragraphs') return [shape];\n const out: StyledElement[] = [];\n // One pass over the markers that were actually drawn: a paragraph range may\n // name far more paragraphs than the shape has, and a group nested inside this\n // shape brings paragraphs of its own that belong to a different target. The\n // nearest shape of *any* id is the one a paragraph belongs to.\n for (const marker of shape.querySelectorAll('[data-pptx-paragraph]')) {\n if (marker.closest('[data-pptx-shape-id]') !== shape) continue;\n const n = Number(marker.getAttribute('data-pptx-paragraph'));\n if (n < target.firstParagraph || n > target.lastParagraph) continue;\n const element = styled(marker);\n if (element !== null) out.push(element);\n }\n return out;\n};\n\nconst nowMs = (): number => (typeof performance === 'object' ? performance.now() : Date.now());\n\n/**\n * The slide's own box on screen. A fly is stated against the slide's edges\n * (`1+#ppt_h/2` puts the shape's centre one half-height below the bottom of it),\n * so that is what the distance has to be measured from — never the viewport,\n * which is not where the slide ends.\n */\nconst slideBoxOf = (el: Element, root: ParentNode): DOMRect | null => {\n const svg = el.closest('svg');\n if (svg !== null) return svg.getBoundingClientRect();\n return root instanceof Element ? root.getBoundingClientRect() : null;\n};\n\n/**\n * The matrix taking the element's own coordinates to the screen, which is also\n * the space a CSS transform written on it is read in.\n *\n * The shape and paragraph markers carry no transform of their own — the\n * renderer wraps the drawn shape rather than transforming the wrapper — so the\n * matrix does not have to be un-done first, and a shape the deck rotates or a\n * group it scales is accounted for by the ancestors it comes through. Text laid\n * out as HTML sits in a `<foreignObject>`, whose own matrix is the one its\n * pixels are scaled by.\n */\nconst screenMatrixOf = (el: StyledElement): DOMMatrix | null => {\n if (el instanceof SVGGraphicsElement) return el.getScreenCTM();\n const host = el.closest('foreignObject');\n return host instanceof SVGGraphicsElement ? host.getScreenCTM() : null;\n};\n\n/**\n * How far the element has to move to sit just outside the named edge, in the\n * units its own CSS transform is written in. `null` when the slide has not been\n * laid out yet, or its matrix cannot be inverted.\n */\nconst flyOffset = (\n el: StyledElement,\n direction: NonNullable<SlideAnimationStep['direction']>,\n root: ParentNode,\n): { readonly dx: number; readonly dy: number } | null => {\n const slide = slideBoxOf(el, root);\n if (slide === null || slide.width <= 0 || slide.height <= 0) return null;\n const box = el.getBoundingClientRect();\n // A corner moves on both axes; the side it names on each is what the edge\n // of a straight fly is.\n const lower = direction.toLowerCase();\n // Clear of the edge by the element's own extent: the far side of the box has\n // to reach the edge before the near side goes past it.\n const dx = lower.includes('right')\n ? slide.right - box.left\n : lower.includes('left')\n ? slide.left - box.right\n : 0;\n const dy = lower.includes('bottom')\n ? slide.bottom - box.top\n : lower.includes('top')\n ? slide.top - box.bottom\n : 0;\n return toOwnUnits(el, dx, dy);\n};\n\n/** A distance on screen in the units the element's own CSS transform is written in. */\nconst toOwnUnits = (\n el: StyledElement,\n dx: number,\n dy: number,\n): { readonly dx: number; readonly dy: number } | null => {\n const matrix = screenMatrixOf(el);\n // Plain HTML with no SVG above it: its pixels are the screen's.\n if (matrix === null) return { dx, dy };\n const determinant = matrix.a * matrix.d - matrix.b * matrix.c;\n if (determinant === 0) return null;\n return {\n dx: (matrix.d * dx - matrix.c * dy) / determinant,\n dy: (matrix.a * dy - matrix.b * dx) / determinant,\n };\n};\n\nconst geometryOf = (el: StyledElement, root: ParentNode): Geometry => ({\n shift(slideX, slideY, ownX = 0, ownY = 0) {\n const slide = slideBoxOf(el, root);\n if (slide === null || slide.width <= 0 || slide.height <= 0) return null;\n const own = toOwnUnits(el, slideX * slide.width, slideY * slide.height);\n if (own === null) return null;\n return `calc(${own.dx}px + ${ownX}%) calc(${own.dy}px + ${ownY}%)`;\n },\n past(edge) {\n return flyOffset(el, edge, root);\n },\n});\n\n/** What one effect runs on one element, and whether it needs the element's own box. */\ninterface Movement {\n readonly frames: Keyframe[];\n /**\n * Scaling and turning happen about the shape's centre, which is the shape's\n * own bounding box rather than the slide's — the default reference box for an\n * SVG element is the viewport, so it has to be said.\n */\n readonly aboutOwnCentre: boolean;\n}\n\n/**\n * Each motion animates a property of its own — `translate`, `scale`, `rotate`\n * — rather than all of them sharing `transform`.\n *\n * Two reasons, both of them things the deck states and a single `transform`\n * would lose. The first is that PresentationML animates a shape's position, its\n * size and its rotation as separate attributes (`ppt_x`/`ppt_y`, `ppt_w`/\n * `ppt_h`, `r`), so a slide may well run a fly and a spin over one shape at the\n * same moment; written to one property, the animation that begins second\n * replaces the first outright and the shape would only turn. The second is that\n * the drawn slide uses `transform` itself, for the rotation and the group\n * scaling the deck gives a shape — and the individual properties apply on top\n * of it rather than in place of it, so nothing the renderer did is overwritten.\n */\n\n/**\n * Whether a step's motion has to be measured against the drawn slide, so that a\n * movement of `null` means \"not read yet\" rather than \"nothing to run\".\n */\nconst needsGeometry = (item: AnimationItem): boolean =>\n item.step.effect !== null &&\n (motionOf(item.step.effect) === 'fly' || trackOf(item) !== undefined);\n\n/**\n * The keyframes one step runs on one element, or `null` when there is nothing\n * to run: an instant effect, or a fly whose distance cannot be measured. Either\n * way the element is put where the step leaves it without motion, which for\n * every effect modelled here is the element's own untransformed place.\n */\nconst movementFor = (item: AnimationItem, el: StyledElement, root: ParentNode): Movement | null => {\n const effect = item.step.effect;\n const entering = item.kind === 'entrance';\n if (effect === null) return null;\n switch (motionOf(effect)) {\n case 'none':\n return null;\n case 'pose': {\n if (item.kind === 'emphasis') {\n const frames = optionedEmphasis(item.step) ?? EMPHASIS[effect];\n return frames === undefined ? null : { frames, aboutOwnCentre: true };\n }\n const track = trackOf(item);\n if (track !== undefined) {\n const frames = track(geometryOf(el, root));\n return frames === null ? null : { frames, aboutOwnCentre: true };\n }\n const away = AWAY[effect.replace(/(In|Out)$/, '')];\n if (away === undefined) return null;\n const rest = restOf(away);\n return { frames: entering ? [away, rest] : [rest, away], aboutOwnCentre: true };\n }\n case 'fly': {\n // Credits rolls up from below the slide and away off its top.\n const direction =\n effect === 'creditsIn' ? 'bottom' : effect === 'creditsOut' ? 'top' : item.step.direction;\n if (direction === null) return null;\n const offset = flyOffset(el, direction, root);\n if (offset === null) return null;\n const away = { translate: `${offset.dx}px ${offset.dy}px` };\n const place = { translate: '0px 0px' };\n return { frames: entering ? [away, place] : [place, away], aboutOwnCentre: false };\n }\n case 'filter':\n case 'peek': {\n const reveal = filterReveal(item.step);\n if (reveal === null) return null;\n const covered: Keyframe = { clipPath: reveal.covered };\n const uncovered: Keyframe = { clipPath: reveal.uncovered };\n const shift = item.step.direction === null ? undefined : EDGE_VECTORS[item.step.direction];\n if (effect === 'peekIn' || effect === 'peekOut') {\n if (shift === undefined) return null;\n // 1.125 of the shape's own size, as the reference desktop app's `#ppt_h*1.125` says;\n // a percentage translation is of the fill box `centreOn` sets.\n covered.translate = `${shift[0] * 112.5}% ${shift[1] * 112.5}%`;\n uncovered.translate = '0% 0%';\n }\n return {\n frames: entering ? [covered, uncovered] : [uncovered, covered],\n aboutOwnCentre: true,\n };\n }\n }\n};\n\n/** Which way each edge lies from the centre, as unit steps in x and y. */\nconst EDGE_VECTORS: Readonly<Record<string, readonly [number, number]>> = {\n top: [0, -1],\n bottom: [0, 1],\n left: [-1, 0],\n right: [1, 0],\n};\n\nconst OPPOSITE_EDGE: Readonly<Record<string, string>> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\n/** `inset()` with nothing showing but the named edge's zero-width strip. */\nconst COVERED_FROM_EDGE: Readonly<Record<string, string>> = {\n top: 'inset(0% 0% 100% 0%)',\n bottom: 'inset(100% 0% 0% 0%)',\n left: 'inset(0% 100% 0% 0%)',\n right: 'inset(0% 0% 0% 100%)',\n};\n\nconst CORNERS: Readonly<Record<string, readonly [number, number]>> = {\n topLeft: [0, 0],\n topRight: [100, 0],\n bottomLeft: [0, 100],\n bottomRight: [100, 100],\n};\n\n/**\n * A `clip-path` at the two ends of a filter: nothing of the shape showing, and\n * all of it. Both ends are written with the same number of points so the\n * browser can interpolate between them. Percentages are of the shape's own\n * fill box, which is what the filter is stated against.\n */\ninterface Reveal {\n readonly covered: string;\n readonly uncovered: string;\n}\n\ntype Point = readonly [number, number];\n\nconst polygon = (points: readonly Point[], evenOdd = false): string =>\n `polygon(${evenOdd ? 'evenodd, ' : ''}${points.map(([x, y]) => `${x}% ${y}%`).join(', ')}) fill-box`;\n\nconst FULL_BOX: readonly Point[] = [\n [0, 0],\n [100, 0],\n [100, 100],\n [0, 100],\n];\n\n/**\n * `count` bars across the box, each `fraction` of its slot wide. The bars are\n * one polygon, joined along the box's edge by lines of no width.\n */\nconst bars = (count: number, horizontal: boolean, fraction: number): string => {\n const points: Point[] = [];\n for (let i = 0; i < count; i++) {\n const from = (100 * i) / count;\n const to = from + (100 * fraction) / count;\n if (horizontal) points.push([0, from], [100, from], [100, to], [0, to]);\n else points.push([from, 0], [from, 100], [to, 100], [to, 0]);\n }\n return polygon(points);\n};\n\n// A circle through the box's corners has a radius of half its diagonal.\nconst CIRCLE_RADIUS = 50 * Math.SQRT2;\nconst CIRCLE_POINTS = 32;\nconst FAN_POINTS = 12;\n\n/** An outline about the box's centre, `scale` 1 being large enough to cover the box. */\nconst outline = (shape: string, scale: number): Point[] => {\n const at = (x: number, y: number): Point => [50 + x * scale, 50 + y * scale];\n switch (shape) {\n case 'box':\n return [at(-50, -50), at(50, -50), at(50, 50), at(-50, 50)];\n case 'diamond':\n return [at(0, -100), at(100, 0), at(0, 100), at(-100, 0)];\n case 'plus':\n return [\n at(-50, -100),\n at(50, -100),\n at(50, -50),\n at(100, -50),\n at(100, 50),\n at(50, 50),\n at(50, 100),\n at(-50, 100),\n at(-50, 50),\n at(-100, 50),\n at(-100, -50),\n at(-50, -50),\n ];\n default:\n return Array.from({ length: CIRCLE_POINTS }, (_, i) => {\n const angle = (2 * Math.PI * i) / CIRCLE_POINTS;\n return at(CIRCLE_RADIUS * Math.cos(angle), CIRCLE_RADIUS * Math.sin(angle));\n });\n }\n};\n\n/**\n * A fan from the centre, swept `sweep` of a turn from `start` — both in turns,\n * clockwise from 12 o'clock — and long enough to reach every corner.\n */\nconst fan = (start: number, sweep: number): Point[] => [\n [50, 50],\n ...Array.from({ length: FAN_POINTS + 1 }, (_, i): Point => {\n const angle = 2 * Math.PI * (start + (sweep * i) / FAN_POINTS);\n return [50 + 100 * Math.sin(angle), 50 - 100 * Math.cos(angle)];\n }),\n];\n\nconst filterReveal = (step: SlideAnimationStep): Reveal | null => {\n const effect = step.effect;\n if (effect === null) return null;\n const family = effect.replace(/(In|Out)$/, '');\n const horizontal = step.orientation !== 'vertical';\n switch (family) {\n case 'wipe':\n case 'peek': {\n // The filter keeps the side it names: a wipe from the bottom shows the\n // bottom of the shape first. A peek comes in from the edge it names, so\n // the side it shows first is the far one.\n const edge =\n step.direction === null\n ? undefined\n : family === 'peek'\n ? OPPOSITE_EDGE[step.direction]\n : step.direction;\n const covered = edge === undefined ? undefined : COVERED_FROM_EDGE[edge];\n if (covered === undefined) return null;\n return { covered: `${covered} fill-box`, uncovered: 'inset(0% 0% 0% 0%) fill-box' };\n }\n case 'blinds':\n return { covered: bars(6, horizontal, 0), uncovered: bars(6, horizontal, 1) };\n case 'randomBars':\n return { covered: bars(16, horizontal, 0), uncovered: bars(16, horizontal, 1) };\n case 'checkerboard':\n // Across opens columns left to right, down opens rows top to bottom.\n return { covered: bars(8, !horizontal, 0), uncovered: bars(8, !horizontal, 1) };\n case 'split': {\n // A vertical split opens from (or closes onto) a vertical centre line.\n // `out` opens from it; `in` closes in from both edges at once — two\n // strips, one polygon joined along an edge.\n const vertical = step.orientation === 'vertical';\n if (step.inOut === 'out') {\n const line = (open: number): string => {\n const side = `${50 - open / 2}%`;\n return vertical\n ? `inset(0% ${side} 0% ${side}) fill-box`\n : `inset(${side} 0% ${side} 0%) fill-box`;\n };\n return { covered: line(0), uncovered: line(100) };\n }\n const edges = (p: number): string =>\n polygon(\n vertical\n ? [\n [0, 0],\n [p, 0],\n [p, 100],\n [100 - p, 100],\n [100 - p, 0],\n [100, 0],\n [100, 100],\n [0, 100],\n ]\n : [\n [0, 0],\n [100, 0],\n [100, p],\n [0, p],\n [0, 100 - p],\n [100, 100 - p],\n [100, 100],\n [0, 100],\n ],\n );\n return { covered: edges(0), uncovered: edges(50) };\n }\n case 'shape': {\n const shape = step.shape ?? 'circle';\n // `out` grows the outline from the centre; `in` closes it onto the\n // centre from outside — the box with a shrinking hole in it.\n if (step.inOut === 'out') {\n return { covered: polygon(outline(shape, 0)), uncovered: polygon(outline(shape, 1)) };\n }\n return {\n covered: polygon([...FULL_BOX, ...outline(shape, 1)], true),\n uncovered: polygon([...FULL_BOX, ...outline(shape, 0)], true),\n };\n }\n case 'strips': {\n // A triangle out of the corner the direction names, large enough at the\n // end to cover the box.\n const corner = step.direction === null ? undefined : CORNERS[step.direction];\n if (corner === undefined) return null;\n const [cx, cy] = corner;\n const sx = cx === 0 ? 1 : -1;\n const sy = cy === 0 ? 1 : -1;\n const triangle = (size: number): string =>\n polygon([\n [cx, cy],\n [cx + sx * size, cy],\n [cx, cy + sy * size],\n ]);\n return { covered: triangle(0), uncovered: triangle(200) };\n }\n case 'wedge':\n // Two fans from 12 o'clock, opening both ways until they meet at 6.\n return {\n covered: polygon([...fan(0, 0), ...fan(0, 0)]),\n uncovered: polygon([...fan(0, 0.5), ...fan(0, -0.5)]),\n };\n case 'wheel': {\n const spokes = step.spokes ?? 1;\n const sectors = (sweep: number): string =>\n polygon(Array.from({ length: spokes }, (_, i) => fan(i / spokes, sweep / spokes)).flat());\n return { covered: sectors(0), uncovered: sectors(1) };\n }\n default:\n return null;\n }\n};\n\n/** Plays a slide's animations against a rendered SVG. */\nexport const createAnimationPlayer = (options: AnimationPlayerOptions): AnimationPlayer => {\n const root = (): ParentNode =>\n typeof options.root === 'function' ? options.root() : options.root;\n const parsed = buildAnimationStops(options.steps);\n const stops = parsed.stops;\n const unsupported = [...parsed.unsupported];\n const reduced = (): boolean => options.reducedMotion?.() === true;\n const onChange = options.onChange ?? ((): void => {});\n const animations: Animation[] = [];\n const timers: ReturnType<typeof setTimeout>[] = [];\n const touched = new Set<StyledElement>();\n // Which elements an effect is currently driving, and which effects of the\n // stop in hand have run. Two effects of one stop can animate the same object\n // — a fade-in the deck fades straight back out, say — and the order they\n // happen to finish in is not the order the deck lists them in. Settling from\n // the list rather than from whichever animation ended last is what makes\n // playing forward land where a jump to the same point lands.\n const inFlight = new Map<StyledElement, number>();\n // Animations that have ended on an element another effect is still animating.\n // SMIL leaves such an animation in the sandwich, frozen at its last value and\n // still above everything that began before it, so an effect that ends early\n // does not hand the object back to a longer one it outranks — unless the tree\n // says its value is taken away when it ends, and then it does. The step's\n // `valueAfterEnd` is what decides, never an assumption; a step that leaves it\n // unstated never reaches here beside another effect on the same element.\n // They are dropped — and the element's own style put back in charge — once\n // nothing is animating it.\n const frozen = new Map<StyledElement, Animation[]>();\n const outstanding = new Map<AnimationItem, number>();\n const finished = new Set<AnimationItem>();\n let cursor = 0;\n let disposed = false;\n let startedAt: number | null = null;\n // Bumped by every call that sets where the slide stands, so a second view can\n // tell an explicit seek from a passing report — including a seek that lands\n // on the cursor it is already on and turns a running stop into a settled one.\n let generation = 0;\n\n // Every shape an unsupported step names — `targetShapeIds` covers a composite\n // effect that drives several — is left the way the renderer drew it. We know\n // something animates it and cannot reproduce that, and of the two states we\n // could choose, only 'shown' is unable to hide content the deck does show.\n const blocked = new Set<string>();\n for (const entry of unsupported)\n for (const shapeId of entry.step.targetShapeIds) blocked.add(String(shapeId));\n const drawn = new Map<string, number>();\n for (const stop of stops)\n for (const item of stop.items) {\n const id = String(item.step.target.shapeId);\n if (!drawn.has(id)) drawn.set(id, root().querySelectorAll(shapeSelector(id)).length);\n }\n for (const stop of stops)\n for (const item of stop.items)\n if ((drawn.get(String(item.step.target.shapeId)) ?? 0) > 1)\n unsupported.push({ step: item.step, reason: 'ambiguousTarget' });\n for (const [id, count] of drawn) if (count > 1) blocked.add(id);\n\n /**\n * Where two effects animate one element at the same time, what the slide\n * shows when the first of them ends turns on whether its value stays above\n * the other or gives way to it. `valueAfterEnd` says which; where the tree\n * does not say, there is nothing to play, so the step is reported and what it\n * names is left as the renderer drew it. On its own such a step is no\n * question at all — nothing is underneath it, and its own visibility decides\n * where the shape is left — so it plays as usual.\n *\n * Read per element, which is where \"the same thing\" is actually settled: a\n * build's paragraphs are separate elements. Each element's effects are sorted\n * once and swept twice, for what begins before an earlier one has ended and\n * what is still running when a later one begins — the pairs themselves are\n * never enumerated.\n *\n * Run again whenever the slide is drawn again, because which elements a step\n * reaches is a fact about the drawing: a transition hands over a layer, and a\n * re-render replaces the nodes underneath us.\n */\n const silence = (current: ParentNode): void => {\n const meets = new Set<AnimationItem>();\n for (const stop of stops) {\n const spans = new Map<StyledElement, { item: AnimationItem; begin: number; end: number }[]>();\n for (const item of stop.items) {\n const end = item.duration === null ? Number.POSITIVE_INFINITY : item.begin + item.duration;\n for (const el of targetsOf(current, item.step, blocked)) {\n const span = { item, begin: item.begin, end };\n const list = spans.get(el);\n if (list === undefined) spans.set(el, [span]);\n else list.push(span);\n }\n }\n for (const list of spans.values()) {\n if (list.length < 2) continue;\n list.sort((a, b) => a.begin - b.begin);\n let furthest = Number.NEGATIVE_INFINITY;\n for (const span of list) {\n if (span.begin < furthest) meets.add(span.item);\n furthest = Math.max(furthest, span.end);\n }\n let earliest = Number.POSITIVE_INFINITY;\n for (let at = list.length - 1; at >= 0; at -= 1) {\n const span = list[at];\n if (span === undefined) continue;\n if (span.end > earliest) meets.add(span.item);\n earliest = Math.min(earliest, span.begin);\n }\n }\n }\n // Removed in one pass, writing the ones that stay over the ones that go,\n // rather than a splice per removal.\n for (const stop of stops) {\n let kept = 0;\n for (const item of stop.items) {\n if (item.step.valueAfterEnd === 'unstated' && meets.has(item)) {\n unsupported.push({ step: item.step, reason: 'notModelled' });\n for (const shapeId of item.step.targetShapeIds) blocked.add(String(shapeId));\n continue;\n }\n stop.items[kept] = item;\n kept += 1;\n }\n stop.items.length = kept;\n }\n };\n\n const clearPending = (): void => {\n for (const timer of timers) clearTimeout(timer);\n timers.length = 0;\n for (const animation of animations) animation.cancel();\n animations.length = 0;\n for (const list of frozen.values()) for (const animation of list) animation.cancel();\n frozen.clear();\n inFlight.clear();\n outstanding.clear();\n finished.clear();\n };\n const drop = <T>(list: T[], entry: T): void => {\n const at = list.indexOf(entry);\n if (at >= 0) list.splice(at, 1);\n };\n const notifyChanged = (): void => {\n if (disposed) return;\n // Once the last effect of a stop has run, the slide is settled: saying so\n // is what stops a second view from resuming into a stop that has ended.\n if (timers.length === 0 && animations.length === 0) startedAt = null;\n onChange(player);\n };\n // The reference box a scale or a turn is measured against. Set while such an\n // effect runs and taken off once nothing is animating the element, so the\n // player leaves no style of its own on a settled slide. It is safe to set\n // because the markers it is set on carry no transform themselves — the\n // renderer wraps the drawn shape rather than transforming the wrapper — so\n // there is nothing already on the element for a changed origin to move.\n const centreOn = (el: StyledElement): void => {\n touched.add(el);\n el.style.transformBox = 'fill-box';\n el.style.transformOrigin = '50% 50%';\n };\n const uncentre = (el: StyledElement): void => {\n el.style.transformBox = '';\n el.style.transformOrigin = '';\n };\n const show = (el: StyledElement): void => {\n touched.add(el);\n el.style.visibility = '';\n el.style.opacity = '';\n uncentre(el);\n };\n const hide = (el: StyledElement): void => {\n touched.add(el);\n el.style.visibility = 'hidden';\n el.style.opacity = '';\n uncentre(el);\n };\n\n // Which effects touch each element and which elements each effect touches,\n // resolved once per drawing rather than per effect that finishes. A slide\n // drawn again — a transition handing its layer over, a re-render — gives a\n // different node or leaves the cached ones detached, and is indexed afresh.\n interface Entry {\n readonly item: AnimationItem;\n readonly stopIndex: number;\n /** Its rank among the effects on its element; the higher one decides. */\n order: number;\n }\n /**\n * The effects that touch one element, lowest priority first, and how far\n * through them the element stands.\n *\n * Priority is the order the effects *begin* in, not the order they are written\n * in. PresentationML timing is SMIL's timing and animation model (ECMA-376\n * Part 1 §19.5), and SMIL composites the animations of one attribute so that\n * \"the animation first begun has lowest priority and the most recently begun\n * animation has highest priority\" (SMIL 3.0 §12.4.3, the animation sandwich).\n * The document decides only between animations that begin together, and then\n * a time dependent \"is considered to activate after the syncbase element\" —\n * which in a timing tree always follows what it waits on — so sorting on the\n * begin time alone, stably, leaves document order to break exactly the ties\n * the spec leaves to it.\n *\n * A step written first but delayed past a later one therefore outranks it,\n * and reading the standing from this list rather than from whichever\n * animation happened to end last is what makes playing forward, jumping,\n * stepping back and resuming agree.\n */\n interface ElementPlan {\n readonly list: Entry[];\n /**\n * The effects that decide whether the element is on the slide at all, which\n * is every one of them but the emphasis effects: those animate a shape that\n * is already there and hand it back unchanged, so one that has run says\n * nothing about whether the shape is shown.\n */\n readonly gates: Entry[];\n /** The highest-priority gate that has run: the one that decides. */\n top: Entry | null;\n /** Whether the first gate to begin — the lowest priority — has run. */\n firstPlayed: boolean;\n }\n /** One effect's hold on one element, so finishing it costs no search. */\n interface Placement {\n readonly el: StyledElement;\n readonly plan: ElementPlan;\n readonly entry: Entry;\n /**\n * What this effect runs on this element, measured against the slide as it\n * was drawn. Read once per drawing so that playing forward, seeking and\n * resuming all work from the same geometry; `null` when the effect has\n * nothing to run here and the element simply takes its settled place.\n */\n readonly movement: Movement | null;\n }\n let indexedRoot: ParentNode | null = null;\n // Whether the last index found the geometry the effects in it need. An effect\n // that has to know where the slide's edges are cannot be measured before the\n // browser has laid the slide out, and a zero read then is not an answer.\n let laidOut = true;\n let plans = new Map<StyledElement, ElementPlan>();\n let placements = new Map<AnimationItem, Placement[]>();\n /** Every stop below this has run; within the stop in hand, `finished` says. */\n let settledBelow = 0;\n const hasPlayed = (entry: Entry): boolean =>\n entry.stopIndex < settledBelow || finished.has(entry.item);\n\n /** Reads every element's standing from its effects, for a redraw or a seek. */\n const recompute = (): void => {\n for (const plan of plans.values()) {\n plan.top = null;\n for (const entry of plan.gates) if (hasPlayed(entry)) plan.top = entry;\n const first = plan.gates[0];\n plan.firstPlayed = first !== undefined && hasPlayed(first);\n }\n };\n\n const index = (): void => {\n const current = root();\n const sample = plans.keys().next();\n // An index that found nothing is not an index: the slide may simply not\n // have been drawn yet, and a deck that really animates nothing costs one\n // empty pass to say so again. Nor is one taken before the browser laid the\n // slide out, where every distance an effect has to travel reads as zero.\n if (current === indexedRoot && sample.done !== true && sample.value.isConnected && laidOut)\n return;\n indexedRoot = current;\n laidOut = true;\n silence(current);\n plans = new Map();\n placements = new Map();\n stops.forEach((stop, stopIndex) => {\n for (const item of stop.items) {\n const spots: Placement[] = [];\n for (const el of targetsOf(current, item.step, blocked)) {\n const plan = plans.get(el) ?? { list: [], gates: [], top: null, firstPlayed: false };\n plans.set(el, plan);\n const entry: Entry = { item, stopIndex, order: 0 };\n plan.list.push(entry);\n if (item.kind !== 'emphasis') plan.gates.push(entry);\n const movement = movementFor(item, el, current);\n if (movement === null && needsGeometry(item)) laidOut = false;\n spots.push({ el, plan, entry, movement });\n }\n placements.set(item, spots);\n }\n });\n for (const plan of plans.values()) {\n // Stable, so effects that begin together keep the document's order.\n const byBegin = (a: Entry, b: Entry): number =>\n a.stopIndex - b.stopIndex || a.item.begin - b.item.begin;\n plan.list.sort(byBegin);\n plan.gates.sort(byBegin);\n plan.list.forEach((entry, at) => {\n entry.order = at;\n });\n }\n recompute();\n };\n\n /** Where an element stands: the highest-priority effect that has run wins. */\n const visibilityOf = (plan: ElementPlan): boolean => {\n const first = plan.gates[0];\n if (first === undefined) return true;\n // An entrance that has not run yet keeps its target off the slide, even\n // when a later step would have shown it.\n if (first.item.kind === 'entrance' && !plan.firstPlayed) return false;\n return plan.top === null || plan.top.item.kind !== 'exit';\n };\n\n /** An element an effect is animating is left to that effect until it ends. */\n const render = (el: StyledElement, plan: ElementPlan): void => {\n if (inFlight.has(el)) return;\n if (visibilityOf(plan)) show(el);\n else hide(el);\n };\n\n /**\n * Puts every animated element where it stands once `played` stops have run,\n * with no motion. Idempotent, so back, jump and a cancelled advance all land\n * on the same picture as playing forward to that point.\n */\n const settle = (played: number): void => {\n finished.clear();\n settledBelow = played;\n index();\n recompute();\n for (const [el, plan] of plans) render(el, plan);\n };\n\n /**\n * One effect has had its say on one element. Only that element can have\n * changed, and only against the effect deciding it so far — so a stop of many\n * effects costs one comparison each, not a re-reading of the slide each.\n */\n const markPlayed = (spot: Placement): void => {\n const { plan, entry } = spot;\n if (entry.item.kind !== 'emphasis') {\n if (entry === plan.gates[0]) plan.firstPlayed = true;\n if (plan.top === null || entry.order > plan.top.order) plan.top = entry;\n }\n render(spot.el, plan);\n };\n\n /** One effect has had its say everywhere it reaches. */\n const complete = (item: AnimationItem): void => {\n finished.add(item);\n index();\n for (const spot of placements.get(item) ?? []) markPlayed(spot);\n };\n\n // `into` is how far through the effect already is — 0 for one starting now,\n // more for one a second view is joining part-way through.\n const play = (item: AnimationItem, into: number): void => {\n index();\n const spots = placements.get(item) ?? [];\n if (spots.length === 0) {\n complete(item);\n return;\n }\n // The elements this effect actually animates. One it reaches but has\n // nothing to run on — an instant preset, or a fly whose distance the slide\n // did not give us — simply takes the place the effect leaves it in, which\n // for every effect modelled here is the element's own untransformed one.\n const moving = spots.filter((spot) => spot.movement !== null);\n const duration = item.duration;\n const from = Math.max(0, into);\n // Over before it could be seen: instantaneous, or joined after its end.\n const over = duration === null || duration === 0 || from >= duration;\n // Such an effect normally just sets the element's own style. It cannot\n // while another effect is animating that element, because an animation's\n // value is applied above the element's style — so it goes into the sandwich\n // instead, frozen at the value it ends on. Unless the tree says that value\n // is taken away when it ends: then there is nothing to hold, and the effect\n // underneath is the one that shows.\n const holds = item.step.valueAfterEnd !== 'removed';\n if (\n reduced() ||\n moving.length === 0 ||\n (over && (!holds || !moving.some((spot) => inFlight.has(spot.el))))\n ) {\n complete(item);\n return;\n }\n // Nothing is going to animate these, so they are settled the moment the\n // effect has its turn.\n for (const spot of spots) if (spot.movement === null) markPlayed(spot);\n const length = over ? 0 : duration;\n outstanding.set(item, moving.length);\n for (const spot of moving) {\n const el = spot.el;\n const movement = spot.movement!;\n touched.add(el);\n // Only an effect that decides whether the shape is on the slide may put\n // it there. An emphasis effect animates whatever is already drawn, so a\n // shape an entrance is still holding back — or one an exit has taken away\n // — stays off the slide while it turns, rather than showing for as long\n // as the turn lasts. `render` cannot undo it either: it leaves an element\n // an effect is animating to that effect until it ends.\n if (item.kind !== 'emphasis') el.style.visibility = '';\n if (movement.aboutOwnCentre) centreOn(el);\n inFlight.set(el, (inFlight.get(el) ?? 0) + 1);\n const animation = el.animate(movement.frames, { duration: length, fill: 'both' });\n animation.currentTime = over ? length : from;\n animations.push(animation);\n void animation.finished.then(\n () => {\n if (disposed) return;\n drop(animations, animation);\n const left = (inFlight.get(el) ?? 1) - 1;\n if (left <= 0 || !holds) {\n // Nothing is animating the element any more, so the sandwich comes\n // off and its own style says where it stands — or this effect's\n // value is one the tree takes away, and it leaves the sandwich now.\n if (left <= 0) {\n inFlight.delete(el);\n for (const other of frozen.get(el) ?? []) other.cancel();\n frozen.delete(el);\n } else inFlight.set(el, left);\n animation.cancel();\n } else {\n inFlight.set(el, left);\n const held = frozen.get(el);\n if (held === undefined) frozen.set(el, [animation]);\n else held.push(animation);\n }\n markPlayed(spot);\n const remaining = (outstanding.get(item) ?? 1) - 1;\n outstanding.set(item, remaining);\n if (remaining <= 0) complete(item);\n notifyChanged();\n },\n () => {},\n );\n }\n };\n\n const runStop = (stopIndex: number, elapsed: number): void => {\n const stop = stops[stopIndex];\n if (stop === undefined) return;\n const since = Math.max(0, elapsed);\n startedAt = nowMs() - since;\n // In the order they begin, stably, so the animations are built in the order\n // SMIL ranks them: the last one built is the one on top of the sandwich.\n // Joining a stop part-way through starts several at once, and the tree's\n // order is not theirs.\n const ordered = [...stop.items].sort((a, b) => a.begin - b.begin);\n for (const item of ordered) {\n const wait = item.begin - since;\n if (reduced() || wait <= 0) {\n play(item, since - item.begin);\n continue;\n }\n const timer = setTimeout(() => {\n drop(timers, timer);\n play(item, 0);\n notifyChanged();\n }, wait);\n timers.push(timer);\n }\n };\n\n const clamp = (next: number): number =>\n Math.max(0, Math.min(Number.isFinite(next) ? Math.round(next) : 0, stops.length));\n\n const player: AnimationPlayer = {\n get cursor() {\n return cursor;\n },\n get stopCount() {\n return stops.length;\n },\n get pending() {\n return cursor < stops.length;\n },\n get running() {\n return timers.length > 0 || animations.length > 0;\n },\n get progress() {\n return {\n cursor,\n stops: stops.length,\n elapsed: startedAt === null ? null : Math.round(nowMs() - startedAt),\n generation,\n };\n },\n get unsupported() {\n return [...unsupported];\n },\n reset() {\n generation += 1;\n clearPending();\n startedAt = null;\n cursor = 0;\n settle(0);\n onChange(player);\n // A slide whose first effect runs with or after 'the previous one' has no\n // previous one: it starts as the slide appears, without a click.\n if (stops[0]?.auto === true) player.advance();\n },\n advance() {\n if (disposed || cursor >= stops.length) return false;\n generation += 1;\n clearPending();\n settle(cursor);\n const stopIndex = cursor;\n cursor += 1;\n runStop(stopIndex, 0);\n onChange(player);\n return true;\n },\n back() {\n if (disposed || cursor <= 0) return false;\n generation += 1;\n clearPending();\n startedAt = null;\n cursor -= 1;\n settle(cursor);\n onChange(player);\n return true;\n },\n jumpTo(next) {\n if (disposed) return;\n generation += 1;\n clearPending();\n startedAt = null;\n cursor = clamp(next);\n settle(cursor);\n onChange(player);\n },\n resume(next, elapsed) {\n if (disposed) return;\n generation += 1;\n clearPending();\n startedAt = null;\n cursor = clamp(next);\n if (cursor > 0 && elapsed !== null && Number.isFinite(elapsed)) {\n settle(cursor - 1);\n runStop(cursor - 1, elapsed);\n } else settle(cursor);\n onChange(player);\n },\n finish() {\n player.jumpTo(stops.length);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n clearPending();\n for (const el of touched) {\n el.style.visibility = '';\n el.style.opacity = '';\n uncentre(el);\n }\n touched.clear();\n },\n };\n // So that a caller asking what will not play gets an answer before the first\n // click, rather than only once the slide has been read for a seek.\n index();\n return player;\n};\n"],"mappings":"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"}