@cardstack/choreo 0.0.0 → 0.1.0-unstable.1

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.
Files changed (165) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/LICENSE +21 -0
  3. package/README.md +55 -6
  4. package/addon-main.cjs +4 -0
  5. package/declarations/anchors.d.ts +26 -0
  6. package/declarations/anchors.d.ts.map +1 -0
  7. package/declarations/arming.d.ts +33 -0
  8. package/declarations/arming.d.ts.map +1 -0
  9. package/declarations/beacon.d.ts +9 -0
  10. package/declarations/beacon.d.ts.map +1 -0
  11. package/declarations/beacons.d.ts +23 -0
  12. package/declarations/beacons.d.ts.map +1 -0
  13. package/declarations/changeset.d.ts +46 -0
  14. package/declarations/changeset.d.ts.map +1 -0
  15. package/declarations/choreo.d.ts +261 -0
  16. package/declarations/choreo.d.ts.map +1 -0
  17. package/declarations/compile.d.ts +45 -0
  18. package/declarations/compile.d.ts.map +1 -0
  19. package/declarations/deliver.d.ts +44 -0
  20. package/declarations/deliver.d.ts.map +1 -0
  21. package/declarations/easings.d.ts +20 -0
  22. package/declarations/easings.d.ts.map +1 -0
  23. package/declarations/far.d.ts +33 -0
  24. package/declarations/far.d.ts.map +1 -0
  25. package/declarations/film/clip.d.ts +51 -0
  26. package/declarations/film/clip.d.ts.map +1 -0
  27. package/declarations/film/clips.d.ts +155 -0
  28. package/declarations/film/clips.d.ts.map +1 -0
  29. package/declarations/film/film.d.ts +1208 -0
  30. package/declarations/film/film.d.ts.map +1 -0
  31. package/declarations/film/graph/adjust.d.ts +112 -0
  32. package/declarations/film/graph/adjust.d.ts.map +1 -0
  33. package/declarations/film/graph/compile.d.ts +140 -0
  34. package/declarations/film/graph/compile.d.ts.map +1 -0
  35. package/declarations/film/graph/host.d.ts +67 -0
  36. package/declarations/film/graph/host.d.ts.map +1 -0
  37. package/declarations/film/graph/nodes.d.ts +287 -0
  38. package/declarations/film/graph/nodes.d.ts.map +1 -0
  39. package/declarations/film/index.d.ts +24 -0
  40. package/declarations/film/index.d.ts.map +1 -0
  41. package/declarations/film/joins.d.ts +143 -0
  42. package/declarations/film/joins.d.ts.map +1 -0
  43. package/declarations/film/math.d.ts +15 -0
  44. package/declarations/film/math.d.ts.map +1 -0
  45. package/declarations/film/overlays.d.ts +54 -0
  46. package/declarations/film/overlays.d.ts.map +1 -0
  47. package/declarations/film/picture.d.ts +104 -0
  48. package/declarations/film/picture.d.ts.map +1 -0
  49. package/declarations/film/plate.d.ts +37 -0
  50. package/declarations/film/plate.d.ts.map +1 -0
  51. package/declarations/film/player.d.ts +120 -0
  52. package/declarations/film/player.d.ts.map +1 -0
  53. package/declarations/film/rail.d.ts +40 -0
  54. package/declarations/film/rail.d.ts.map +1 -0
  55. package/declarations/film/schedule.d.ts +93 -0
  56. package/declarations/film/schedule.d.ts.map +1 -0
  57. package/declarations/film/seam.d.ts +38 -0
  58. package/declarations/film/seam.d.ts.map +1 -0
  59. package/declarations/film/titles.d.ts +37 -0
  60. package/declarations/film/titles.d.ts.map +1 -0
  61. package/declarations/film/types.d.ts +544 -0
  62. package/declarations/film/types.d.ts.map +1 -0
  63. package/declarations/film.d.ts +3 -0
  64. package/declarations/film.d.ts.map +1 -0
  65. package/declarations/gesture.d.ts +33 -0
  66. package/declarations/gesture.d.ts.map +1 -0
  67. package/declarations/index.d.ts +26 -0
  68. package/declarations/index.d.ts.map +1 -0
  69. package/declarations/measure.d.ts +29 -0
  70. package/declarations/measure.d.ts.map +1 -0
  71. package/declarations/path.d.ts +73 -0
  72. package/declarations/path.d.ts.map +1 -0
  73. package/declarations/registry.d.ts +46 -0
  74. package/declarations/registry.d.ts.map +1 -0
  75. package/declarations/run.d.ts +406 -0
  76. package/declarations/run.d.ts.map +1 -0
  77. package/declarations/space.d.ts +31 -0
  78. package/declarations/space.d.ts.map +1 -0
  79. package/declarations/steps.d.ts +479 -0
  80. package/declarations/steps.d.ts.map +1 -0
  81. package/declarations/test-support/index.d.ts +30 -0
  82. package/declarations/test-support/index.d.ts.map +1 -0
  83. package/declarations/types.d.ts +761 -0
  84. package/declarations/types.d.ts.map +1 -0
  85. package/dist/anchors.js +34 -0
  86. package/dist/anchors.js.map +1 -0
  87. package/dist/arming.js +120 -0
  88. package/dist/arming.js.map +1 -0
  89. package/dist/beacon.js +25 -0
  90. package/dist/beacon.js.map +1 -0
  91. package/dist/beacons.js +77 -0
  92. package/dist/beacons.js.map +1 -0
  93. package/dist/changeset.js +129 -0
  94. package/dist/changeset.js.map +1 -0
  95. package/dist/choreo.js +1026 -0
  96. package/dist/choreo.js.map +1 -0
  97. package/dist/compile.js +1403 -0
  98. package/dist/compile.js.map +1 -0
  99. package/dist/deliver.js +326 -0
  100. package/dist/deliver.js.map +1 -0
  101. package/dist/easings.js +39 -0
  102. package/dist/easings.js.map +1 -0
  103. package/dist/far.js +147 -0
  104. package/dist/far.js.map +1 -0
  105. package/dist/film/clip.js +100 -0
  106. package/dist/film/clip.js.map +1 -0
  107. package/dist/film/clips.js +147 -0
  108. package/dist/film/clips.js.map +1 -0
  109. package/dist/film/film.js +4424 -0
  110. package/dist/film/film.js.map +1 -0
  111. package/dist/film/graph/adjust.js +160 -0
  112. package/dist/film/graph/adjust.js.map +1 -0
  113. package/dist/film/graph/compile.js +225 -0
  114. package/dist/film/graph/compile.js.map +1 -0
  115. package/dist/film/graph/host.js +77 -0
  116. package/dist/film/graph/host.js.map +1 -0
  117. package/dist/film/graph/nodes.js +500 -0
  118. package/dist/film/graph/nodes.js.map +1 -0
  119. package/dist/film/index.js +18 -0
  120. package/dist/film/index.js.map +1 -0
  121. package/dist/film/joins.js +260 -0
  122. package/dist/film/joins.js.map +1 -0
  123. package/dist/film/math.js +49 -0
  124. package/dist/film/math.js.map +1 -0
  125. package/dist/film/overlays.js +66 -0
  126. package/dist/film/overlays.js.map +1 -0
  127. package/dist/film/picture.js +58 -0
  128. package/dist/film/picture.js.map +1 -0
  129. package/dist/film/plate.js +36 -0
  130. package/dist/film/plate.js.map +1 -0
  131. package/dist/film/player.js +79 -0
  132. package/dist/film/player.js.map +1 -0
  133. package/dist/film/rail.js +38 -0
  134. package/dist/film/rail.js.map +1 -0
  135. package/dist/film/schedule.js +238 -0
  136. package/dist/film/schedule.js.map +1 -0
  137. package/dist/film/seam.js +64 -0
  138. package/dist/film/seam.js.map +1 -0
  139. package/dist/film/titles.js +45 -0
  140. package/dist/film/titles.js.map +1 -0
  141. package/dist/film/types.js +2 -0
  142. package/dist/film/types.js.map +1 -0
  143. package/dist/film.js +18 -0
  144. package/dist/film.js.map +1 -0
  145. package/dist/gesture.js +111 -0
  146. package/dist/gesture.js.map +1 -0
  147. package/dist/index.js +9 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/measure.js +99 -0
  150. package/dist/measure.js.map +1 -0
  151. package/dist/path.js +272 -0
  152. package/dist/path.js.map +1 -0
  153. package/dist/registry.js +55 -0
  154. package/dist/registry.js.map +1 -0
  155. package/dist/run.js +2423 -0
  156. package/dist/run.js.map +1 -0
  157. package/dist/space.js +57 -0
  158. package/dist/space.js.map +1 -0
  159. package/dist/steps.js +831 -0
  160. package/dist/steps.js.map +1 -0
  161. package/dist/test-support/index.js +150 -0
  162. package/dist/test-support/index.js.map +1 -0
  163. package/dist/types.js +2 -0
  164. package/dist/types.js.map +1 -0
  165. package/package.json +201 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps.js","sources":["../src/steps.gts"],"sourcesContent":["/**\n * The timeline, declared in the template. Each step renders a hidden marker\n * so the region can read the tree back in document order — nesting in the\n * markup IS the sequence/parallel nesting. Nothing here animates; the region\n * compiles these into cues when a render pass produces a changeset.\n */\nimport Component from '@glimmer/component';\nimport { modifier } from 'ember-modifier';\n\nimport { type AnchorRef, at } from './anchors.ts';\nimport type { BeaconRef } from './beacons.ts';\nimport type { GestureRef } from './gesture.ts';\nimport type {\n Block,\n Camera3DWaypoint,\n DeliveryBy,\n DeliveryOrder,\n DeriveContext,\n Easing,\n PropSource,\n PropValue,\n Query,\n Rect,\n SpringSpec,\n TimelineNode,\n} from './types.ts';\n\ninterface Provider {\n node(): TimelineNode;\n}\n\nconst providers = new WeakMap<Element, Provider>();\n\n/** unnamed crossings still need a stable, unique inner anchor name */\nlet crossings = 0;\n\n/** the steps directly inside an element, in document order; a nested <Choreo> is another region's */\nexport function collect(el: Element): TimelineNode[] {\n const out: TimelineNode[] = [];\n for (const child of Array.from(el.children)) {\n if (child.hasAttribute('data-choreo')) {\n continue;\n }\n const provider = providers.get(child);\n if (provider) {\n out.push(provider.node());\n } else {\n out.push(...collect(child));\n }\n }\n return out;\n}\n\n/**\n * args that are the step's own; every other named arg is a property to animate.\n * `rotate` is NOT here although Move has a `@rotate` arg: on a Tween or\n * Spring it is a property (Keynote's Spin), and Move never reads its props.\n */\nconst RESERVED = new Set([\n 'align',\n 'at',\n 'by',\n 'delay',\n 'duration',\n 'ease',\n 'fill',\n 'from',\n 'name',\n 'of',\n 'order',\n 'path',\n 'read',\n 'repeat',\n 'repeatType',\n 'rest',\n 'shadow',\n 'size',\n 'space',\n 'spring',\n 'stagger',\n 'swap',\n 'to',\n 'times',\n]);\n\n/** the pre-seconds spellings, kept only to fail loudly with the new name */\nconst RENAMED: Record<string, string> = {\n crossfade: '@swap',\n ms: '@duration (in seconds)',\n overlap: '@stagger (in seconds)',\n};\n\nfunction propsOf(args: Record<string, unknown>): Record<string, PropSource> {\n const props: Record<string, PropSource> = {};\n for (const key of Object.keys(args)) {\n if (args[key] === undefined) {\n continue;\n }\n if (RENAMED[key]) {\n throw new Error(`choreo: @${key} was renamed — use ${RENAMED[key]}`);\n }\n if (!RESERVED.has(key)) {\n props[key] = args[key] as PropSource;\n }\n }\n return props;\n}\n\n/**\n * The template speaks seconds, as Motion does; the compiler's clock is ms.\n * A composite step writes node literals, which are BELOW that boundary —\n * so it converts its own seconds args here, and `undefined` stays\n * `undefined` so an unset arg still means \"take the default\".\n */\nexport function toMs<T extends number | undefined>(\n seconds: T,\n): T extends number ? number : number | undefined {\n // the conditional return type is the whole point — a required `ms` field\n // takes toMs(x) without a null check when x is a number — and TypeScript\n // cannot verify a conditional return from inside, so the cast is the\n // price of stating it\n return (\n seconds === undefined ? undefined : seconds * 1000\n ) as T extends number ? number : number | undefined;\n}\n\nconst msOf = toMs;\n\n/** the args every step shares — a composite step extends this */\nexport interface StepArgsBase {\n [prop: string]: unknown;\n /** `{{at 'name' 0.4}}` / `{{after 'name' 0.2}}` — start against a named step */\n at?: AnchorRef;\n /** seconds before the step starts, inside its slot */\n delay?: number;\n /** a label other steps may anchor against */\n name?: string;\n /** seconds between one matched sprite and the next, in document order */\n stagger?: number;\n}\n\n/** …and the args of a step that names sprites */\nexport interface StepArgs extends StepArgsBase {\n of: Query | Query[];\n}\n\n/**\n * The base every step is built on, and the public seam for a COMPOSITE\n * step — a new word in the timeline that expands into the built-in\n * vocabulary. `c.Crossing` is one, and is written in nothing but this.\n *\n * Subclass it, implement `node()`, and render the component anywhere\n * inside a `<Choreo>`: the region reads the tree back in document order\n * and your node takes its place in it.\n *\n * ```gts\n * export class Reveal extends StepComponent<StepArgs & { rise?: number }> {\n * node(): TimelineNode {\n * const { of, name, rise = 12 } = this.args;\n * return {\n * at: this.args.at,\n * children: [\n * { kind: 'tween', generic: true, of, ms: 240, props: { opacity: [0, 1] } },\n * { kind: 'tween', generic: true, of, ms: 240, props: { y: [rise, 0] } },\n * ],\n * kind: 'parallel',\n * name,\n * };\n * }\n * }\n * ```\n *\n * **`node()` is called on every pass**, and its result is fingerprinted to\n * decide whether an edited timeline replays the run. So it must be pure\n * and cheap: no measurement, no DOM writes, no tracked writes (a tracked\n * write re-renders, which replays the pass, which calls `node()`). And\n * because functions in the tree are compared by identity, a `node()` that\n * allocates a fresh closure per call declares an edit on every pass —\n * hoist property functions to module scope.\n *\n * Two conventions worth keeping: mark children `generic: true` so a\n * sibling step can claim a sprite away from your defaults (the yield\n * rule, §4.7), and derive any inner `name` from your own `@name` so two\n * of your step in one timeline do not collide.\n */\nexport abstract class StepComponent<A extends StepArgsBase> extends Component<{\n Args: A;\n}> {\n abstract node(): TimelineNode;\n mark = modifier((el: Element) => {\n providers.set(el, this);\n return () => providers.delete(el);\n });\n <template>\n <span hidden data-choreo-step {{this.mark}}></span>\n </template>\n}\n\nexport class Tween extends StepComponent<\n StepArgs & {\n /** split a text sprite's delivery: by word, character, or paragraph */\n by?: DeliveryBy;\n /** seconds, as Motion counts them */\n duration: number;\n ease?: Easing;\n order?: DeliveryOrder;\n /** extra plays after the first; `Infinity` is an ambient loop whose phase rides the run clock */\n repeat?: number;\n repeatType?: 'loop' | 'mirror' | 'reverse';\n /** Normalized keyframe offsets, one per value in every keyframe track. */\n times?: number[];\n }\n> {\n node(): TimelineNode {\n const { of, by, duration, ease, delay, order, repeat, repeatType, times } =\n this.args;\n return {\n at: this.args.at,\n by,\n delay: msOf(delay),\n ease,\n kind: 'tween',\n name: this.args.name,\n ms: duration * 1000,\n of,\n order,\n props: propsOf(this.args),\n repeat,\n repeatType,\n times,\n stagger: msOf(this.args.stagger),\n };\n }\n}\n\nexport class Spring extends StepComponent<\n StepArgs & {\n by?: DeliveryBy;\n order?: DeliveryOrder;\n spring?: SpringSpec;\n }\n> {\n node(): TimelineNode {\n const { of, by, spring, delay, order } = this.args;\n return {\n at: this.args.at,\n by,\n delay: msOf(delay),\n kind: 'spring',\n name: this.args.name,\n of,\n order,\n props: propsOf(this.args),\n spring,\n stagger: msOf(this.args.stagger),\n };\n }\n}\n\nexport class Move extends StepComponent<\n StepArgs & {\n /** seconds; with @ease, the tween form of the flight */\n duration?: number;\n ease?: string | readonly number[];\n /** `{{c.beacon 'compose'}}` or `{{c.gesture}}` — fly in from that box */\n from?: BeaconRef | GestureRef;\n /** an SVG path for the journey, drawn from where the sprite stands */\n path?: string;\n /** 'auto' orients along the tangent; a number adds a constant offset */\n rotate?: 'auto' | number;\n size?: boolean | 'crop' | 'scale';\n /** measure the delta in 'page' (default) or the sprite's 'parent' space */\n space?: 'page' | 'parent';\n spring?: SpringSpec;\n /** counterpart skins: 'during' (default), 'settle', or 'none' */\n swap?: 'during' | 'none' | 'settle';\n /** `{{c.beacon 'trash'}}` — fly out to that box rather than to where the sprite landed */\n to?: BeaconRef;\n }\n> {\n node(): TimelineNode {\n const {\n of,\n duration,\n ease,\n delay,\n path,\n rotate,\n space,\n spring,\n size,\n swap,\n from,\n to,\n stagger,\n } = this.args;\n propsOf(this.args); // no properties — evaluated for the renamed-arg errors\n return {\n at: this.args.at,\n delay: msOf(delay),\n ease,\n from,\n kind: 'move',\n name: this.args.name,\n ms: msOf(duration),\n of,\n path,\n rotate,\n size,\n space,\n spring,\n stagger: msOf(stagger),\n swap,\n to,\n };\n }\n}\n\nexport class Hold extends StepComponent<\n StepArgs & { duration?: number; fill?: boolean }\n> {\n node(): TimelineNode {\n const { of, duration, delay, fill, stagger } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n fill,\n kind: 'hold',\n name: this.args.name,\n ms: msOf(duration),\n of,\n props: propsOf(this.args),\n stagger: msOf(stagger),\n };\n }\n}\n\n/**\n * `<c.Wait />` — a hole in a sequence. It has no subject: `@of` is accepted\n * (a wait can be laddered across sprites with `@stagger`) but never needed.\n */\nexport class Wait extends StepComponent<\n StepArgsBase & { duration: number; of?: Query | Query[] }\n> {\n node(): TimelineNode {\n const { of, duration, delay, stagger } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n kind: 'wait',\n name: this.args.name,\n ms: duration * 1000,\n of,\n stagger: msOf(stagger),\n };\n }\n}\n\n/**\n * `<c.Perform />` — a semantic command on the timeline (§C4). It occupies\n * an instant, positioned like any step (sequence order, `@at`, `@delay`),\n * and carries `@action` (required), `@target` and `@payload` to the\n * region's dispatcher (`<Choreo @onPerform>`). The fold's law: forward\n * playback dispatches it once as the clock crosses it; a seek past it\n * includes it; a seek before it resets the host and replays the remaining\n * prefix. Commands are idempotent statements of state — `lightbox.open`,\n * never `lightbox.toggle`.\n */\nexport class Perform extends StepComponent<\n StepArgsBase & { action: string; payload?: unknown; target?: string }\n> {\n node(): TimelineNode {\n const { action, delay, payload, target } = this.args;\n return {\n action,\n at: this.args.at,\n delay: msOf(delay),\n kind: 'perform',\n name: this.args.name,\n payload,\n target,\n };\n }\n}\n\n/**\n * `<c.Scroll />` — animate the sprite's scroll container so the sprite lands\n * at `@align`; occupies the sequence like any step (§6.1).\n */\n/**\n * `<c.Attach @region @duration />` — drive another region's run over a\n * window of this one's clock. Positioned like any step (sequence order,\n * `@at`, `@delay`); `@in` and `@rate` map the window onto the child's own\n * seconds; `@end` says what happens past it; `@exact` refuses a child\n * that cannot be driven exactly (a spring, a follow).\n */\nexport class Attach extends StepComponent<\n StepArgsBase & {\n duration: number;\n end?: 'hold' | 'remove';\n exact?: boolean;\n in?: number;\n rate?: number;\n region: string;\n }\n> {\n node(): TimelineNode {\n const { delay, duration, end, exact, rate, region } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n end,\n exact,\n in: this.args.in,\n kind: 'attach',\n ms: duration * 1000,\n name: this.args.name,\n rate,\n region,\n };\n }\n}\n\nexport class Scroll extends StepComponent<\n StepArgs & { align?: 'center' | 'end' | 'start'; duration?: number }\n> {\n node(): TimelineNode {\n const { of, align, duration, delay, stagger } = this.args;\n return {\n align,\n at: this.args.at,\n delay: msOf(delay),\n kind: 'scroll',\n ms: msOf(duration),\n name: this.args.name,\n of,\n stagger: msOf(stagger),\n };\n }\n}\n\n/**\n * `<c.Raise />` — promote the sprites to the region's elevated layer for the\n * span of its block (or `@duration`): above every stacking context and clip\n * in the region, with measured continuity both ways. `@shadow` casts on the\n * layer below (§6.3).\n */\nexport class Raise extends StepComponent<\n StepArgs & { duration?: number; shadow?: boolean }\n> {\n node(): TimelineNode {\n const { of, duration, delay, shadow, stagger } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n kind: 'raise',\n ms: msOf(duration),\n name: this.args.name,\n of,\n shadow,\n stagger: msOf(stagger),\n };\n }\n}\n\n/**\n * `<c.Camera />` — the region's frame as a step (§6.3): `@zoom` / `@x` /\n * `@y` animate the scene, `@origin` aims the zoom at a sprite, `@steady`\n * names sprites that keep their size against it (damped by default).\n * `@fit` is the other, more common shape — dive on this sprite and CENTRE\n * it, zoom and pan computed from rest-layout geometry (`@margin` sets the\n * share of the frame it fills); pass `null` to fit nothing: back to rest.\n */\nexport class Camera extends StepComponent<\n StepArgsBase & {\n duration?: number;\n ease?: Easing;\n fit?: Query | null;\n margin?: number;\n of?: Query | Query[];\n origin?: Query;\n spring?: SpringSpec;\n steady?: Query | Query[];\n x?: number;\n y?: number;\n zoom?: number;\n }\n> {\n node(): TimelineNode {\n const { duration, ease, delay, fit, margin, origin, spring, steady } =\n this.args;\n const { x, y, zoom } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n ease,\n fit,\n kind: 'camera',\n margin,\n ms: msOf(duration),\n name: this.args.name,\n of: this.args.of ?? {},\n origin,\n spring,\n steady,\n x,\n y,\n zoom,\n };\n }\n}\n\n/**\n * `<c.Camera3D @yaw={{-24}} @pitch={{-6}} @dolly={{0.9}} />` — the shot,\n * for a scene Choreo is not the one drawing.\n *\n * `c.Camera` moves the region's own frame, which is a 2D transform on real\n * DOM. A 3D scene has no such frame: its camera belongs to whatever is\n * rendering it. So this step carries the POSE and nothing else — yaw and\n * pitch in degrees, dolly as a multiple of the host's own framing — and\n * the region hands it to `@onCamera3D` every frame it changes. The host\n * applies it to three.js, to a CSS 3D stage, to anything that takes three\n * numbers.\n *\n * What Choreo keeps is the part it is actually good at: the pose is a pure\n * function of the clock, so a scrub lands the shot exactly where playing\n * there would, and a preset expands into this one seekable cue rather than\n * a second scheduler.\n *\n * `@by` makes it relative — added to the pose in force when the cue\n * starts, the way `Pan` and `SlowZoom` are relative — so a drift composes\n * with whatever shot preceded it.\n */\nexport class Camera3D extends StepComponent<\n StepArgsBase & {\n by?: boolean;\n dolly?: number;\n duration?: number;\n ease?: Easing;\n /** the orbit centre, in the host's scene units — tweened with the pose */\n look?: { x: number; y: number; z: number };\n of?: Query | Query[];\n pitch?: number;\n /** smoothing window for a path, seconds — see Camera3DStep.settle */\n settle?: number;\n spring?: SpringSpec;\n /** the path's grip, 0 lively .. 1 linear — see Camera3DStep.tension */\n tension?: number;\n /** waypoints for a spline path — see Camera3DStep.through */\n through?: Camera3DWaypoint[];\n x?: number;\n y?: number;\n yaw?: number;\n }\n> {\n node(): TimelineNode {\n const {\n by,\n delay,\n dolly,\n duration,\n ease,\n look,\n pitch,\n settle,\n spring,\n tension,\n through,\n x,\n y,\n yaw,\n } = this.args;\n return {\n at: this.args.at,\n by,\n delay: msOf(delay),\n dolly,\n ease,\n kind: 'camera3d',\n look,\n ms: msOf(duration),\n name: this.args.name,\n of: this.args.of ?? {},\n pitch,\n settle,\n spring,\n tension,\n through,\n x,\n y,\n yaw,\n };\n }\n}\n\n/* ---- the direction vocabulary (notes/choreo-composition.md C5) ----\n Presets expand into the SAME seekable camera cue — sugar, never a new\n runtime primitive. Frame and Aim are absolute (computed from measured\n geometry at compile); Pan and SlowZoom are RELATIVE, resolved against\n the pose in force when the cue starts, so they compose with whatever\n shot preceded them and reconstruct under random access like any cue. */\n\n/**\n * `<c.Frame @of={{c.id 'hero'}} @padding={{0.8}} />` — fit-and-centre the\n * target: the fit camera under its editorial name. `@padding` is the\n * share of the frame the target fills on whichever axis fits first.\n */\nexport class Frame extends StepComponent<\n StepArgsBase & {\n duration?: number;\n ease?: Easing;\n of: Query | null;\n padding?: number;\n spring?: SpringSpec;\n steady?: Query | Query[];\n }\n> {\n node(): TimelineNode {\n const { duration, ease, delay, of, padding, spring, steady } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n ease,\n fit: of,\n kind: 'camera',\n margin: padding,\n ms: msOf(duration),\n name: this.args.name,\n of: {},\n spring,\n steady,\n };\n }\n}\n\n/**\n * `<c.Aim @of={{c.id 'hero'}} />` — recentre the picture on the target\n * with the zoom HELD: the reframe that does not change magnification.\n */\nexport class Aim extends StepComponent<\n StepArgsBase & {\n duration?: number;\n ease?: Easing;\n of: Query;\n spring?: SpringSpec;\n steady?: Query | Query[];\n }\n> {\n node(): TimelineNode {\n const { duration, ease, delay, of, spring, steady } = this.args;\n return {\n aim: of,\n at: this.args.at,\n delay: msOf(delay),\n ease,\n kind: 'camera',\n ms: msOf(duration),\n name: this.args.name,\n of: {},\n spring,\n steady,\n };\n }\n}\n\n/**\n * `<c.Pan @x={{40}} @y={{-20}} />` — shift the picture by exactly this\n * many pixels from wherever it stands. Relative on purpose: a pan after\n * any shot means \"from here\", not \"to there\".\n */\nexport class Pan extends StepComponent<\n StepArgsBase & {\n duration?: number;\n ease?: Easing;\n spring?: SpringSpec;\n steady?: Query | Query[];\n x?: number;\n y?: number;\n }\n> {\n node(): TimelineNode {\n const { duration, ease, delay, spring, steady, x, y } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n ease,\n kind: 'camera',\n ms: msOf(duration),\n name: this.args.name,\n of: {},\n panBy: { x, y },\n spring,\n steady,\n };\n }\n}\n\n/**\n * `<c.SlowZoom @by={{1.05}} @duration={{2}} />` — multiply the zoom in\n * force: the push-in (or, below 1, the pull-back) that gives a hold its\n * life. The aim in force is kept, so it pushes toward what the previous\n * shot was looking at.\n */\nexport class SlowZoom extends StepComponent<\n StepArgsBase & {\n by: number;\n duration?: number;\n ease?: Easing;\n spring?: SpringSpec;\n steady?: Query | Query[];\n }\n> {\n node(): TimelineNode {\n const { by, duration, ease, delay, spring, steady } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n ease,\n kind: 'camera',\n ms: msOf(duration),\n name: this.args.name,\n of: {},\n spring,\n steady,\n zoomBy: by,\n };\n }\n}\n\n/**\n * `<c.Tether />` — geometry continuously derived from sprites (§6.1):\n * `@path` receives both endpoints' region-relative boxes every frame and\n * returns the path data the wire draws.\n */\nexport class Tether extends StepComponent<\n StepArgsBase & {\n duration?: number;\n from: Query;\n of?: Query | Query[];\n path: (from: Rect, to: Rect) => string;\n to: Query;\n }\n> {\n node(): TimelineNode {\n const { duration, delay, from, path, to } = this.args;\n return {\n at: this.args.at,\n delay: msOf(delay),\n from,\n kind: 'tether',\n ms: msOf(duration),\n name: this.args.name,\n of: this.args.of,\n path,\n to,\n };\n }\n}\n\n/**\n * `<c.Crossing />` — the canned scene crossing (§4.7): what only the old\n * scene had fades as the flight lifts off, everything paired flies (skins\n * swapping per `@swap`), and what only the new scene has fades in near the\n * settle. One step in the template; a whole overlapped score on the clock —\n * Keynote's Magic Move does not wait for the dissolve to finish before the\n * movers leave, and a crossing that does reads as three acts, not one.\n *\n * It is also the reference COMPOSITE step, and deliberately written in\n * nothing but the public seam (`StepComponent`, `toMs`, `at`, and node\n * literals): if this needed a privilege an author could not have, the\n * contract on `StepComponent` would be a lie.\n */\nexport class Crossing extends StepComponent<\n StepArgsBase & {\n /** seconds to fade what only the new scene has */\n arrive?: number;\n /** the tween form of the flight */\n duration?: number;\n ease?: Easing;\n /** seconds to fade what only the old scene had */\n leave?: number;\n /** arrivals start at this fraction of the flight — near the settle */\n overlap?: number;\n /**\n * The flight's size mode. Default `'crop'` — uniform scale from\n * width, tops pinned, extra height clipped. `'scale'` stretches\n * per-axis; `true` writes layout width/height (reflows a grid row).\n */\n size?: boolean | 'crop' | 'scale';\n spring?: SpringSpec;\n /** the counterpart-skin policy, forwarded to the flight */\n swap?: 'during' | 'none' | 'settle';\n }\n> {\n /**\n * The flight is addressable from outside — `{{at 'page:flight' 0.5}}`\n * for a step that wants to ride the move itself. Derived from this\n * crossing's own `@name` rather than fixed, so two crossings in one\n * timeline do not collide over it; unnamed, it takes a per-instance\n * number, which is stable for the life of the component and so does not\n * disturb the tree fingerprint between passes.\n */\n private flightName = `${this.args.name ?? `crossing-${++crossings}`}:flight`;\n\n node(): TimelineNode {\n const {\n arrive = 0.22,\n duration,\n ease,\n leave = 0.18,\n overlap = 0.7,\n size = 'crop',\n spring,\n swap,\n } = this.args;\n const FLIGHT = this.flightName;\n return {\n at: this.args.at,\n delay: toMs(this.args.delay),\n name: this.args.name,\n children: [\n {\n generic: true,\n kind: 'tween',\n ms: toMs(leave),\n of: { onstage: true, type: 'departed' },\n props: { opacity: 0 },\n },\n {\n ease,\n generic: true,\n kind: 'move',\n ms: toMs(duration),\n name: FLIGHT,\n of: { type: 'received' },\n // iOS's rule: uniform scale matched by cover, the aspect mismatch\n // cropped by the interpolating window — never a stretch, and\n // never layout (a receiver animating real width/height reflows\n // its whole row for the flight). Overridable; the default stays\n // crop so a crossing in a grid cannot stretch the row.\n size,\n spring,\n swap,\n },\n {\n generic: true,\n kind: 'hold',\n of: { type: 'received' },\n props: { zIndex: 2 },\n },\n {\n at: at(FLIGHT, overlap),\n generic: true,\n kind: 'tween',\n ms: toMs(arrive),\n of: { onstage: true, type: 'inserted' },\n props: { opacity: [0, 1] },\n },\n ],\n kind: 'parallel',\n };\n }\n}\n\n/**\n * `<c.Follow />` — a value DERIVED from the scene rather than interpolated\n * between two keyframes (§4.10). `@to` names what to read; `@read` gets\n * the pass's measurements every frame — each source's resting boxes\n * (`from`, `to`) and its composed position this frame (`now`), plus the\n * follower's own `rest` — and returns the properties to write; `@rest`\n * says what those properties are when nothing is driving them, so a\n * measure pass can put the element back.\n *\n * ```gts\n * <c.Follow @of={{c.id 'badge'}} @to={{c.id 'card'}}\n * @read={{corner}} @rest={{hash x=0 y=0}} />\n * ```\n *\n * `@read` never sees the live page. Everything it is handed was measured\n * by the pass or composed from the run's own values, so it cannot read\n * back what it wrote last frame and it cannot force a style recalculation\n * mid-move — pure by construction, and correct under interruption because\n * a replacement pass re-measures (docs/postmortem-follow.md).\n *\n * Three things it is not: it is not accelerated (a derived value is\n * computed on the main thread, every frame — the price, and the same one\n * `c.Tether` pays); it may not write layout, only transform, opacity and\n * filter; and `@read` must still be a pure function of its context,\n * because the run is scrubbable in both directions and a value with\n * memory could not be sought back to.\n */\nexport class Follow extends StepComponent<\n StepArgs & {\n duration?: number;\n read: (ctx: DeriveContext) => Record<string, PropValue>;\n rest: Record<string, PropValue>;\n to: Query | Query[];\n }\n> {\n node(): TimelineNode {\n const { duration, of, read, rest, to } = this.args;\n return {\n at: this.args.at,\n delay: msOf(this.args.delay),\n kind: 'follow',\n ms: msOf(duration),\n name: this.args.name,\n of,\n read,\n rest,\n stagger: msOf(this.args.stagger),\n to,\n };\n }\n}\n\n/**\n * `<c.Gate />` — park the run until `c.advance()`; `@delay` opens it by\n * itself after that many seconds (§4.1). A gate is a pause, and a pause is\n * a total order: it may only stand in a sequence that no parallel contains.\n */\nexport class Gate extends Component<{\n Args: { delay?: number };\n}> {\n node(): TimelineNode {\n return { kind: 'gate', ms: msOf(this.args.delay) };\n }\n mark = modifier((el: Element) => {\n providers.set(el, this);\n return () => providers.delete(el);\n });\n <template>\n <span hidden data-choreo-step {{this.mark}}></span>\n </template>\n}\n\n/**\n * A block is a step's equal to the anchor system: it takes `@name`, `@at`\n * and `@delay` on the same terms, so a composite step — a `node()` that\n * returns a block — is something the rest of the score can point at.\n */\nabstract class BlockComponent extends Component<{\n Args: {\n /** `{{at 'name' 0.4}}` / `{{after 'name'}}` — start against a named step or block */\n at?: AnchorRef;\n /** seconds before the block's contents start, inside its slot */\n delay?: number;\n /** a label other steps may anchor against; the block's span is its contents */\n name?: string;\n };\n Blocks: { default: [] };\n}> {\n abstract readonly kind: Block['kind'];\n private el?: Element;\n node(): Block {\n return {\n at: this.args.at,\n children: this.el ? collect(this.el) : [],\n delay: msOf(this.args.delay),\n kind: this.kind,\n name: this.args.name,\n };\n }\n mark = modifier((el: Element) => {\n this.el = el;\n providers.set(el, this);\n return () => {\n providers.delete(el);\n this.el = undefined;\n };\n });\n <template>\n <span hidden data-choreo-block {{this.mark}}>{{yield}}</span>\n </template>\n}\n\nexport class Sequence extends BlockComponent {\n readonly kind = 'sequence';\n}\nexport class Parallel extends BlockComponent {\n readonly kind = 'parallel';\n}\n"],"names":["providers","WeakMap","crossings","collect","el","out","child","Array","from","children","hasAttribute","provider","get","push","node","RESERVED","Set","RENAMED","crossfade","ms","overlap","propsOf","args","props","key","Object","keys","undefined","Error","has","toMs","seconds","msOf","StepComponent","Component","mark","modifier","set","delete","setComponentTemplate","precompileTemplate","strictMode","Tween","of","by","duration","ease","delay","order","repeat","repeatType","times","at","kind","name","stagger","Spring","spring","Move","path","rotate","space","size","swap","to","Hold","fill","Wait","Perform","action","payload","target","Attach","end","exact","rate","region","in","Scroll","align","Raise","shadow","Camera","fit","margin","origin","steady","x","y","zoom","Camera3D","dolly","look","pitch","settle","tension","through","yaw","Frame","padding","Aim","aim","Pan","panBy","SlowZoom","zoomBy","Tether","Crossing","flightName","arrive","leave","FLIGHT","generic","onstage","type","opacity","zIndex","Follow","read","rest","Gate","BlockComponent","Sequence","Parallel"],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ import { settled } from '@ember/test-helpers';
2
+ import { registerMotionReset, animationsSettled, setupMotion } from 'glimmer-motion/test-support';
3
+ import { frame, visualElementStore } from 'motion-dom';
4
+ import { resetBeacons } from '../beacons.js';
5
+ import { resetBarrier } from '../far.js';
6
+ import { resetGestures } from '../gesture.js';
7
+ import { activeRuns } from '../run.js';
8
+
9
+ /**
10
+ * @cardstack/choreo/test-support — how a test drives and checks <Choreo>.
11
+ *
12
+ * import { animationsSettled } from 'glimmer-motion/test-support';
13
+ * import { live, orphanCount, setupChoreo } from '@cardstack/choreo/test-support';
14
+ *
15
+ * module('…', function (hooks) {
16
+ * setupRenderingTest(hooks);
17
+ * setupChoreo(hooks);
18
+ *
19
+ * test('…', async function (assert) {
20
+ * await render(<template>…</template>);
21
+ * await click(live('.open')!);
22
+ * await animationsSettled();
23
+ * assert.strictEqual(orphanCount(), 0);
24
+ * });
25
+ * });
26
+ *
27
+ * `setupChoreo()` is the one setup call a Choreo suite makes. It is
28
+ * `setupMotion()`, and Choreo's document-wide state — the beacon registry, the
29
+ * far-match barrier, the gesture samples — is reset alongside glimmer-motion's
30
+ * own, because loading this module adds those resets to `resetMotion()`.
31
+ *
32
+ * They are document-wide by design: a beacon in the chrome has to be visible to
33
+ * a region in an outlet, and the barrier exists to see across regions. That is
34
+ * right for an app and a leak between tests: a torn-down element still holding
35
+ * the name "trash" wins the first-registration race against the next test's
36
+ * real one.
37
+ */
38
+ registerMotionReset(resetBeacons);
39
+ registerMotionReset(resetGestures);
40
+ registerMotionReset(resetBarrier);
41
+ const nextFrame = () => new Promise(resolve => frame.postRender(() => resolve()));
42
+
43
+ /* ---- setup ---- */
44
+
45
+ /** `setupMotion(hooks)`, with Choreo's resets among the ones it runs */
46
+ function setupChoreo(hooks) {
47
+ setupMotion(hooks);
48
+ }
49
+
50
+ /* ---- driving the run from a test (§8.3) ---- */
51
+
52
+ /** open every parked gate and settle the segment it releases */
53
+ async function advanceGate() {
54
+ for (const run of activeRuns) {
55
+ if (run.parked) {
56
+ run.advance();
57
+ }
58
+ }
59
+ await animationsSettled();
60
+ }
61
+
62
+ /** set every live run's clock, in seconds — a scrubbed still */
63
+ async function seekTo(seconds) {
64
+ for (const run of activeRuns) {
65
+ run.pause();
66
+ run.time = seconds;
67
+ }
68
+ await settled();
69
+ await nextFrame();
70
+ }
71
+
72
+ /* ---- Choreo invariants, shared by the contract suite and the soak ---- */
73
+
74
+ const testRoot = () => document.querySelector('#ember-testing') ?? document.body;
75
+
76
+ /** how many leavers are parked in a <Choreo> orphan layer right now */
77
+ function orphanCount(root = testRoot()) {
78
+ return [...root.querySelectorAll('[data-choreo-orphans]')].reduce((n, layer) => n + layer.children.length, 0);
79
+ }
80
+
81
+ /**
82
+ * The first LIVE match for `selector` — the copy that is still part of the
83
+ * rendered tree, never a leaver parked in a region's orphan layer.
84
+ *
85
+ * Mid-crossing an identity exists twice: the arriving element in the live
86
+ * tree, and the departing skin the region locked into `[data-choreo-orphans]`
87
+ * so it can be flown and faded. That layer is the region's FIRST child, so a
88
+ * bare `querySelector` answers with the ghost — an element whose component
89
+ * has already been torn down, whose listeners are gone, and whose box is
90
+ * where the OLD scene stood. Clicking it does nothing; measuring it measures
91
+ * the past. Neither failure names itself.
92
+ *
93
+ * So any assertion or interaction a test performs while a crossing may be
94
+ * aloft should come through here. A raised sprite (`c.Raise`) is deliberately
95
+ * still live: it is the real element on a different layer, not a copy.
96
+ */
97
+ function live(selector, root = testRoot()) {
98
+ return liveAll(selector, root)[0] ?? null;
99
+ }
100
+
101
+ /** every live match for `selector`, in document order — see `live()` */
102
+ function liveAll(selector, root = testRoot()) {
103
+ return [...root.querySelectorAll(selector)].filter(el => !el.closest('[data-choreo-orphans]'));
104
+ }
105
+
106
+ /**
107
+ * Elements still wearing a transform that nothing is animating.
108
+ *
109
+ * The identity spellings (`translateX(0px)`, `scale(1)`) are rest: the engine
110
+ * writes them and they are harmless. Anything else, once everything has
111
+ * settled, is a value somebody borrowed and never gave back.
112
+ */
113
+ const IDENTITY = /^(translate[XYZ]?\(0px\)\s*|translate\(0px,\s*0px\)\s*|scale[XY]?\(1\)\s*|rotate\(0deg\)\s*)+$/;
114
+ function strandedTransforms(root = testRoot()) {
115
+ return [...root.querySelectorAll('*')].filter(el => {
116
+ const t = el.style.transform;
117
+ if (!t || t === 'none' || IDENTITY.test(t)) {
118
+ return false;
119
+ }
120
+ // a region root's transform is its camera, and a directed plane
121
+ // RESTS transformed — a held zoom is a pose, not a leak
122
+ if (el.hasAttribute('data-choreo')) {
123
+ return false;
124
+ }
125
+ return !isFollower(el);
126
+ }).map(el => `${el.tagName.toLowerCase()}.${el.className}: ${el.style.transform}`);
127
+ }
128
+
129
+ /**
130
+ * Is this element's transform owned by somebody else?
131
+ *
132
+ * A shared-element pair is one identity with two elements, and only one of them
133
+ * leads. The follower is projected onto the lead's box on purpose — that is
134
+ * what makes the crossfade possible — so a thumbnail sitting behind an open
135
+ * lightbox wears a large scale at rest and is entirely correct.
136
+ *
137
+ * Without this, "no element kept a transform" fails for any stage a test
138
+ * happens to leave open, which reads exactly like a leak and is not one.
139
+ */
140
+ function isFollower(el) {
141
+ const projection = visualElementStore.get(el)?.projection;
142
+ if (!projection || projection.isLead()) {
143
+ return false;
144
+ }
145
+ const lead = projection.getStack()?.lead;
146
+ return Boolean(lead?.instance?.isConnected);
147
+ }
148
+
149
+ export { advanceGate, live, liveAll, orphanCount, seekTo, setupChoreo, strandedTransforms };
150
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/test-support/index.ts"],"sourcesContent":["/**\n * @cardstack/choreo/test-support — how a test drives and checks <Choreo>.\n *\n * import { animationsSettled } from 'glimmer-motion/test-support';\n * import { live, orphanCount, setupChoreo } from '@cardstack/choreo/test-support';\n *\n * module('…', function (hooks) {\n * setupRenderingTest(hooks);\n * setupChoreo(hooks);\n *\n * test('…', async function (assert) {\n * await render(<template>…</template>);\n * await click(live('.open')!);\n * await animationsSettled();\n * assert.strictEqual(orphanCount(), 0);\n * });\n * });\n *\n * `setupChoreo()` is the one setup call a Choreo suite makes. It is\n * `setupMotion()`, and Choreo's document-wide state — the beacon registry, the\n * far-match barrier, the gesture samples — is reset alongside glimmer-motion's\n * own, because loading this module adds those resets to `resetMotion()`.\n *\n * They are document-wide by design: a beacon in the chrome has to be visible to\n * a region in an outlet, and the barrier exists to see across regions. That is\n * right for an app and a leak between tests: a torn-down element still holding\n * the name \"trash\" wins the first-registration race against the next test's\n * real one.\n */\nimport { settled } from '@ember/test-helpers';\nimport {\n animationsSettled,\n registerMotionReset,\n setupMotion,\n} from 'glimmer-motion/test-support';\nimport { frame, visualElementStore } from 'motion-dom';\n\nimport { resetBeacons } from '../beacons.ts';\nimport { resetBarrier } from '../far.ts';\nimport { resetGestures } from '../gesture.ts';\nimport { activeRuns } from '../run.ts';\n\nregisterMotionReset(resetBeacons);\nregisterMotionReset(resetGestures);\nregisterMotionReset(resetBarrier);\n\nconst nextFrame = () =>\n new Promise<void>((resolve) => frame.postRender(() => resolve()));\n\n/* ---- setup ---- */\n\n/** `setupMotion(hooks)`, with Choreo's resets among the ones it runs */\nexport function setupChoreo(hooks: Parameters<typeof setupMotion>[0]) {\n setupMotion(hooks);\n}\n\n/* ---- driving the run from a test (§8.3) ---- */\n\n/** open every parked gate and settle the segment it releases */\nexport async function advanceGate(): Promise<void> {\n for (const run of activeRuns) {\n if (run.parked) {\n run.advance();\n }\n }\n await animationsSettled();\n}\n\n/** set every live run's clock, in seconds — a scrubbed still */\nexport async function seekTo(seconds: number): Promise<void> {\n for (const run of activeRuns) {\n run.pause();\n run.time = seconds;\n }\n await settled();\n await nextFrame();\n}\n\n/* ---- Choreo invariants, shared by the contract suite and the soak ---- */\n\nconst testRoot = () =>\n (document.querySelector('#ember-testing') ?? document.body) as HTMLElement;\n\n/** how many leavers are parked in a <Choreo> orphan layer right now */\nexport function orphanCount(root: HTMLElement = testRoot()): number {\n return [...root.querySelectorAll('[data-choreo-orphans]')].reduce(\n (n, layer) => n + layer.children.length,\n 0,\n );\n}\n\n/**\n * The first LIVE match for `selector` — the copy that is still part of the\n * rendered tree, never a leaver parked in a region's orphan layer.\n *\n * Mid-crossing an identity exists twice: the arriving element in the live\n * tree, and the departing skin the region locked into `[data-choreo-orphans]`\n * so it can be flown and faded. That layer is the region's FIRST child, so a\n * bare `querySelector` answers with the ghost — an element whose component\n * has already been torn down, whose listeners are gone, and whose box is\n * where the OLD scene stood. Clicking it does nothing; measuring it measures\n * the past. Neither failure names itself.\n *\n * So any assertion or interaction a test performs while a crossing may be\n * aloft should come through here. A raised sprite (`c.Raise`) is deliberately\n * still live: it is the real element on a different layer, not a copy.\n */\nexport function live<E extends Element = HTMLElement>(\n selector: string,\n root: ParentNode = testRoot(),\n): E | null {\n return liveAll<E>(selector, root)[0] ?? null;\n}\n\n/** every live match for `selector`, in document order — see `live()` */\nexport function liveAll<E extends Element = HTMLElement>(\n selector: string,\n root: ParentNode = testRoot(),\n): E[] {\n return [...root.querySelectorAll<E>(selector)].filter(\n (el) => !el.closest('[data-choreo-orphans]'),\n );\n}\n\n/**\n * Elements still wearing a transform that nothing is animating.\n *\n * The identity spellings (`translateX(0px)`, `scale(1)`) are rest: the engine\n * writes them and they are harmless. Anything else, once everything has\n * settled, is a value somebody borrowed and never gave back.\n */\nconst IDENTITY =\n /^(translate[XYZ]?\\(0px\\)\\s*|translate\\(0px,\\s*0px\\)\\s*|scale[XY]?\\(1\\)\\s*|rotate\\(0deg\\)\\s*)+$/;\n\nexport function strandedTransforms(root: HTMLElement = testRoot()): string[] {\n return [...root.querySelectorAll<HTMLElement>('*')]\n .filter((el) => {\n const t = el.style.transform;\n if (!t || t === 'none' || IDENTITY.test(t)) {\n return false;\n }\n // a region root's transform is its camera, and a directed plane\n // RESTS transformed — a held zoom is a pose, not a leak\n if (el.hasAttribute('data-choreo')) {\n return false;\n }\n return !isFollower(el);\n })\n .map(\n (el) =>\n `${el.tagName.toLowerCase()}.${el.className}: ${el.style.transform}`,\n );\n}\n\n/**\n * Is this element's transform owned by somebody else?\n *\n * A shared-element pair is one identity with two elements, and only one of them\n * leads. The follower is projected onto the lead's box on purpose — that is\n * what makes the crossfade possible — so a thumbnail sitting behind an open\n * lightbox wears a large scale at rest and is entirely correct.\n *\n * Without this, \"no element kept a transform\" fails for any stage a test\n * happens to leave open, which reads exactly like a leak and is not one.\n */\nfunction isFollower(el: HTMLElement): boolean {\n const projection = visualElementStore.get(el)?.projection;\n if (!projection || projection.isLead()) {\n return false;\n }\n const lead = projection.getStack()?.lead;\n return Boolean(lead?.instance?.isConnected);\n}\n"],"names":["registerMotionReset","resetBeacons","resetGestures","resetBarrier","nextFrame","Promise","resolve","frame","postRender","setupChoreo","hooks","setupMotion","advanceGate","run","activeRuns","parked","advance","animationsSettled","seekTo","seconds","pause","time","settled","testRoot","document","querySelector","body","orphanCount","root","querySelectorAll","reduce","n","layer","children","length","live","selector","liveAll","filter","el","closest","IDENTITY","strandedTransforms","t","style","transform","test","hasAttribute","isFollower","map","tagName","toLowerCase","className","projection","visualElementStore","get","isLead","lead","getStack","Boolean","instance","isConnected"],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,12 +1,207 @@
1
1
  {
2
2
  "name": "@cardstack/choreo",
3
- "version": "0.0.0",
4
- "description": "Placeholder reserving this name. Real releases are published from https://github.com/cardstack/boxel.",
5
- "license": "MIT",
3
+ "version": "0.1.0-unstable.1",
4
+ "description": "Motion, Choreographed. A changeset and a timeline over a whole render pass, on glimmer-motion.",
5
+ "keywords": [
6
+ "ember-addon",
7
+ "animation",
8
+ "choreography",
9
+ "motion",
10
+ "glimmer",
11
+ "transition",
12
+ "timeline"
13
+ ],
6
14
  "repository": {
7
15
  "type": "git",
8
- "url": "git+https://github.com/cardstack/boxel.git",
16
+ "url": "https://github.com/cardstack/boxel.git",
9
17
  "directory": "packages/choreo"
10
18
  },
11
- "files": ["README.md"]
12
- }
19
+ "license": "MIT",
20
+ "author": "Cardstack",
21
+ "exports": {
22
+ ".": {
23
+ "developing:choreo": "./src/index.ts",
24
+ "types": "./declarations/index.d.ts",
25
+ "default": "./dist/index.js"
26
+ },
27
+ "./test-support": {
28
+ "developing:choreo": "./src/test-support/index.ts",
29
+ "types": "./declarations/test-support/index.d.ts",
30
+ "default": "./dist/test-support/index.js"
31
+ },
32
+ "./choreo": {
33
+ "developing:choreo": "./src/choreo.gts",
34
+ "types": "./declarations/choreo.d.ts",
35
+ "default": "./dist/choreo.js"
36
+ },
37
+ "./film/clip": {
38
+ "developing:choreo": "./src/film/clip.gts",
39
+ "types": "./declarations/film/clip.d.ts",
40
+ "default": "./dist/film/clip.js"
41
+ },
42
+ "./film/film": {
43
+ "developing:choreo": "./src/film/film.gts",
44
+ "types": "./declarations/film/film.d.ts",
45
+ "default": "./dist/film/film.js"
46
+ },
47
+ "./film/graph/adjust": {
48
+ "developing:choreo": "./src/film/graph/adjust.gts",
49
+ "types": "./declarations/film/graph/adjust.d.ts",
50
+ "default": "./dist/film/graph/adjust.js"
51
+ },
52
+ "./film/graph/host": {
53
+ "developing:choreo": "./src/film/graph/host.gts",
54
+ "types": "./declarations/film/graph/host.d.ts",
55
+ "default": "./dist/film/graph/host.js"
56
+ },
57
+ "./film/graph/nodes": {
58
+ "developing:choreo": "./src/film/graph/nodes.gts",
59
+ "types": "./declarations/film/graph/nodes.d.ts",
60
+ "default": "./dist/film/graph/nodes.js"
61
+ },
62
+ "./film/joins": {
63
+ "developing:choreo": "./src/film/joins.gts",
64
+ "types": "./declarations/film/joins.d.ts",
65
+ "default": "./dist/film/joins.js"
66
+ },
67
+ "./film/overlays": {
68
+ "developing:choreo": "./src/film/overlays.gts",
69
+ "types": "./declarations/film/overlays.d.ts",
70
+ "default": "./dist/film/overlays.js"
71
+ },
72
+ "./film/picture": {
73
+ "developing:choreo": "./src/film/picture.gts",
74
+ "types": "./declarations/film/picture.d.ts",
75
+ "default": "./dist/film/picture.js"
76
+ },
77
+ "./film/plate": {
78
+ "developing:choreo": "./src/film/plate.gts",
79
+ "types": "./declarations/film/plate.d.ts",
80
+ "default": "./dist/film/plate.js"
81
+ },
82
+ "./film/player": {
83
+ "developing:choreo": "./src/film/player.gts",
84
+ "types": "./declarations/film/player.d.ts",
85
+ "default": "./dist/film/player.js"
86
+ },
87
+ "./film/rail": {
88
+ "developing:choreo": "./src/film/rail.gts",
89
+ "types": "./declarations/film/rail.d.ts",
90
+ "default": "./dist/film/rail.js"
91
+ },
92
+ "./film/titles": {
93
+ "developing:choreo": "./src/film/titles.gts",
94
+ "types": "./declarations/film/titles.d.ts",
95
+ "default": "./dist/film/titles.js"
96
+ },
97
+ "./steps": {
98
+ "developing:choreo": "./src/steps.gts",
99
+ "types": "./declarations/steps.d.ts",
100
+ "default": "./dist/steps.js"
101
+ },
102
+ "./*": {
103
+ "developing:choreo": "./src/*.ts",
104
+ "types": "./declarations/*.d.ts",
105
+ "default": "./dist/*.js"
106
+ },
107
+ "./addon-main.js": "./addon-main.cjs"
108
+ },
109
+ "typesVersions": {
110
+ "*": {
111
+ "*": [
112
+ "declarations/*",
113
+ "declarations/*/index"
114
+ ]
115
+ }
116
+ },
117
+ "files": [
118
+ "addon-main.cjs",
119
+ "declarations",
120
+ "dist",
121
+ "CHANGELOG.md"
122
+ ],
123
+ "publishConfig": {
124
+ "access": "public"
125
+ },
126
+ "dependencies": {
127
+ "@embroider/addon-shim": "^1.8.9",
128
+ "decorator-transforms": "^2.3.0"
129
+ },
130
+ "devDependencies": {
131
+ "@babel/core": "^7.26.10",
132
+ "@babel/plugin-transform-runtime": "^7.29.0",
133
+ "@babel/plugin-transform-typescript": "^7.16.8",
134
+ "@babel/runtime": "^7.22.11",
135
+ "@cardstack/choreo-eslint-config": "0.0.0",
136
+ "@ember/library-tsconfig": "^1.1.3",
137
+ "@ember/test-helpers": "^4.0.5",
138
+ "@embroider/addon-dev": "^8.0.0",
139
+ "@embroider/config-meta-loader": "^1.0.0",
140
+ "@embroider/core": "^4.6.3",
141
+ "@embroider/macros": "^1.20.2",
142
+ "@embroider/vite": "^1.7.10",
143
+ "@glimmer/component": "^2.0.0",
144
+ "@glimmer/tracking": "^1.1.2",
145
+ "@glimmer/validator": "^0.95.0",
146
+ "@glint/ember-tsc": "1.5.0",
147
+ "@glint/template": "^1.7.7",
148
+ "@rollup/plugin-babel": "^6.0.4",
149
+ "@types/qunit": "^2.19.12",
150
+ "babel-plugin-ember-template-compilation": "^2.4.1",
151
+ "concurrently": "^8.2.2",
152
+ "ember-modifier": "^4.3.0",
153
+ "ember-qunit": "^9.0.4",
154
+ "ember-source": "~6.10.0",
155
+ "ember-strict-application-resolver": "^0.1.0",
156
+ "ember-template-lint": "^7.8.1",
157
+ "eslint": "^9.39.4",
158
+ "glimmer-motion": "0.1.0-unstable.1",
159
+ "motion-dom": "13.4.5",
160
+ "motion-utils": "13.3.0",
161
+ "prettier": "^3.6.2",
162
+ "prettier-plugin-ember-template-tag": "^2.0.0",
163
+ "qunit": "^2.24.1",
164
+ "qunit-dom": "^3.5.0",
165
+ "rollup": "^4.18.1",
166
+ "testem": "^3.10.1",
167
+ "typescript": "~5.9.3",
168
+ "vite": "^6.3.2"
169
+ },
170
+ "peerDependenciesMeta": {
171
+ "@ember/test-helpers": {
172
+ "optional": true
173
+ }
174
+ },
175
+ "ember-addon": {
176
+ "version": 2,
177
+ "type": "addon",
178
+ "main": "addon-main.cjs",
179
+ "app-js": {}
180
+ },
181
+ "peerDependencies": {
182
+ "@ember/test-helpers": ">=3.0.0",
183
+ "@glimmer/component": "^2.0.0",
184
+ "ember-modifier": "^4.3.0",
185
+ "ember-source": ">=5.4.0",
186
+ "glimmer-motion": "0.1.0-unstable.1",
187
+ "motion-dom": "^13.4.5",
188
+ "motion-utils": "^13.3.0"
189
+ },
190
+ "scripts": {
191
+ "build": "rollup --config && node scripts/fix-declarations.mjs",
192
+ "check:packed-exports": "node ../glimmer-motion/scripts/check-exports.mjs --packed",
193
+ "format": "prettier . --cache --write",
194
+ "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\" --prefixColors auto",
195
+ "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\" --prefixColors auto && pnpm run format",
196
+ "lint:format": "prettier . --cache --check",
197
+ "lint:hbs": "ember-template-lint .",
198
+ "lint:hbs:fix": "ember-template-lint . --fix",
199
+ "lint:js": "eslint . --cache",
200
+ "lint:js:fix": "eslint . --fix",
201
+ "lint:exports": "node ../glimmer-motion/scripts/check-exports.mjs --source",
202
+ "lint:types": "ember-tsc --noEmit",
203
+ "start": "rollup --config --watch",
204
+ "test": "vite build --mode=development --out-dir dist-tests && testem --file testem.cjs ci --port 0",
205
+ "start:test": "vite dev --open /tests/"
206
+ }
207
+ }