domotion-svg 0.1.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 (119) hide show
  1. package/FEATURES.md +102 -0
  2. package/LICENSE +21 -0
  3. package/README.md +66 -0
  4. package/dist/animator.d.ts +158 -0
  5. package/dist/animator.js +424 -0
  6. package/dist/animator.test.d.ts +5 -0
  7. package/dist/animator.test.js +169 -0
  8. package/dist/border-radius.test.d.ts +1 -0
  9. package/dist/border-radius.test.js +148 -0
  10. package/dist/capture.d.ts +193 -0
  11. package/dist/capture.js +786 -0
  12. package/dist/chrome.d.ts +45 -0
  13. package/dist/chrome.js +107 -0
  14. package/dist/cli.d.ts +16 -0
  15. package/dist/cli.js +512 -0
  16. package/dist/client/dom.d.ts +10 -0
  17. package/dist/client/dom.js +17 -0
  18. package/dist/conic-raster.d.ts +58 -0
  19. package/dist/conic-raster.js +292 -0
  20. package/dist/conic-raster.test.d.ts +1 -0
  21. package/dist/conic-raster.test.js +187 -0
  22. package/dist/coretext-extractor.test.d.ts +1 -0
  23. package/dist/coretext-extractor.test.js +94 -0
  24. package/dist/coretext-helper.d.ts +60 -0
  25. package/dist/coretext-helper.js +205 -0
  26. package/dist/cross-origin-font-face.test.d.ts +1 -0
  27. package/dist/cross-origin-font-face.test.js +107 -0
  28. package/dist/cursor-overlay.d.ts +123 -0
  29. package/dist/cursor-overlay.js +207 -0
  30. package/dist/cursor-overlay.test.d.ts +1 -0
  31. package/dist/cursor-overlay.test.js +88 -0
  32. package/dist/dark-mode-capture.test.d.ts +1 -0
  33. package/dist/dark-mode-capture.test.js +158 -0
  34. package/dist/dark-mode-form-controls.test.d.ts +1 -0
  35. package/dist/dark-mode-form-controls.test.js +218 -0
  36. package/dist/dom-to-svg.d.ts +1016 -0
  37. package/dist/dom-to-svg.js +7717 -0
  38. package/dist/embed-remote-images.test.d.ts +1 -0
  39. package/dist/embed-remote-images.test.js +424 -0
  40. package/dist/form-controls.d.ts +70 -0
  41. package/dist/form-controls.js +1151 -0
  42. package/dist/frame-merge.d.ts +95 -0
  43. package/dist/frame-merge.js +374 -0
  44. package/dist/frame-merge.test.d.ts +6 -0
  45. package/dist/frame-merge.test.js +144 -0
  46. package/dist/gradients.d.ts +184 -0
  47. package/dist/gradients.js +937 -0
  48. package/dist/gradients.test.d.ts +1 -0
  49. package/dist/gradients.test.js +150 -0
  50. package/dist/index.d.ts +12 -0
  51. package/dist/index.js +7 -0
  52. package/dist/jsx-runtime.d.ts +27 -0
  53. package/dist/jsx-runtime.js +96 -0
  54. package/dist/jsx-runtime.test.d.ts +1 -0
  55. package/dist/jsx-runtime.test.js +41 -0
  56. package/dist/kerfjs-imports.test.d.ts +1 -0
  57. package/dist/kerfjs-imports.test.js +36 -0
  58. package/dist/mask.test.d.ts +1 -0
  59. package/dist/mask.test.js +206 -0
  60. package/dist/optimize.d.ts +12 -0
  61. package/dist/optimize.js +32 -0
  62. package/dist/preserve-aspect-ratio.test.d.ts +1 -0
  63. package/dist/preserve-aspect-ratio.test.js +38 -0
  64. package/dist/resize-embedded-images.d.ts +33 -0
  65. package/dist/resize-embedded-images.js +164 -0
  66. package/dist/resize-embedded-images.test.d.ts +9 -0
  67. package/dist/resize-embedded-images.test.js +255 -0
  68. package/dist/stacking-context.test.d.ts +1 -0
  69. package/dist/stacking-context.test.js +927 -0
  70. package/dist/text-renderer.d.ts +42 -0
  71. package/dist/text-renderer.js +608 -0
  72. package/dist/text-renderer.test.d.ts +1 -0
  73. package/dist/text-renderer.test.js +150 -0
  74. package/dist/text-to-path.d.ts +265 -0
  75. package/dist/text-to-path.js +1800 -0
  76. package/dist/text-to-path.test.d.ts +1 -0
  77. package/dist/text-to-path.test.js +570 -0
  78. package/dist/utils/escapeHtml.d.ts +2 -0
  79. package/dist/utils/escapeHtml.js +15 -0
  80. package/dist/webfont-unicode-range.test.d.ts +1 -0
  81. package/dist/webfont-unicode-range.test.js +174 -0
  82. package/package.json +55 -0
  83. package/src/animator.test.ts +179 -0
  84. package/src/animator.ts +660 -0
  85. package/src/border-radius.test.ts +160 -0
  86. package/src/capture.ts +810 -0
  87. package/src/cli.ts +582 -0
  88. package/src/conic-raster.test.ts +213 -0
  89. package/src/conic-raster.ts +309 -0
  90. package/src/coretext-extractor.test.ts +130 -0
  91. package/src/coretext-helper.ts +256 -0
  92. package/src/cross-origin-font-face.test.ts +119 -0
  93. package/src/cursor-overlay.test.ts +95 -0
  94. package/src/cursor-overlay.ts +297 -0
  95. package/src/dark-mode-capture.test.ts +177 -0
  96. package/src/dark-mode-form-controls.test.ts +228 -0
  97. package/src/dom-to-svg.ts +8376 -0
  98. package/src/embed-remote-images.test.ts +461 -0
  99. package/src/form-controls.ts +1174 -0
  100. package/src/frame-merge.test.ts +157 -0
  101. package/src/frame-merge.ts +447 -0
  102. package/src/globals.d.ts +2 -0
  103. package/src/gradients.test.ts +175 -0
  104. package/src/gradients.ts +955 -0
  105. package/src/index.ts +12 -0
  106. package/src/kerf-jsx-augmentation.d.ts +36 -0
  107. package/src/kerfjs-imports.test.tsx +45 -0
  108. package/src/mask.test.ts +274 -0
  109. package/src/optimize.ts +34 -0
  110. package/src/preserve-aspect-ratio.test.ts +49 -0
  111. package/src/resize-embedded-images.test.ts +292 -0
  112. package/src/resize-embedded-images.ts +180 -0
  113. package/src/stacking-context.test.ts +967 -0
  114. package/src/text-renderer.test.ts +162 -0
  115. package/src/text-renderer.ts +623 -0
  116. package/src/text-to-path.test.ts +639 -0
  117. package/src/text-to-path.ts +1810 -0
  118. package/src/utils/escapeHtml.ts +16 -0
  119. package/src/webfont-unicode-range.test.ts +207 -0
package/FEATURES.md ADDED
@@ -0,0 +1,102 @@
1
+ # Domotion: Supported Features
2
+
3
+ Each feature has a visual regression test that compares HTML-to-PNG with SVG-to-PNG.
4
+
5
+ ## Rendering Features
6
+
7
+ ### Text
8
+ - [x] **text-basic**: Plain text rendering (font-size, font-family, color)
9
+ - [x] **text-bold**: Bold/weight text
10
+ - [x] **text-center**: Centered text (text-align: center)
11
+ - [x] **text-right**: Right-aligned text
12
+ - [x] **text-mono**: Monospace font rendering
13
+ - [x] **text-multiline**: Multiple lines of text in a container
14
+ - [x] **text-small**: Small/label text (11-12px)
15
+ - [x] **text-inline-mixed**: Mixed inline content (prose with inline code spans)
16
+ - [x] **text-pre-multiline**: Preformatted multiline text (`<pre>` with `white-space: pre`)
17
+
18
+ ### Backgrounds & Colors
19
+ - [x] **bg-solid**: Solid background colors
20
+ - [x] **bg-transparent**: Semi-transparent backgrounds (rgba)
21
+ - [x] **bg-nested**: Nested backgrounds (child on top of parent)
22
+ - [x] **bg-conic-gradient** (DM-547, doc 28): `conic-gradient` / `repeating-conic-gradient` background layers via pattern-raster pre-pass — covers `bg-conic-smooth`, `bg-conic-checkerboard`, `bg-conic-from-at`, `bg-conic-multilayer` fixtures
23
+ - [ ] **bg-dark-mode** (DM-455, doc 29): Dark-mode capture support — caller-chosen `colorScheme`, dark form-control palette, scheme-aware transparent-root fallback
24
+
25
+ ### Borders
26
+ - [x] **border-solid**: Solid borders with color
27
+ - [x] **border-radius**: Rounded corners
28
+ - [x] **border-radius-pill**: Fully rounded (pill shape)
29
+
30
+ ### Layout
31
+ - [x] **layout-flex-row**: Horizontal flex layout with gap
32
+ - [x] **layout-flex-col**: Vertical flex layout
33
+ - [x] **layout-flex-center**: Centered content (justify-content/align-items)
34
+ - [ ] **layout-grid**: CSS Grid layout
35
+ - [ ] **layout-absolute**: Absolute positioning
36
+ - [x] **layout-padding**: Padding affecting content position
37
+
38
+ ### Components
39
+ - [x] **comp-button**: Button with background, border, padding, text
40
+ - [x] **comp-badge**: Small badge with colored background and text
41
+ - [x] **comp-card**: Card with background, border, radius, content
42
+ - [x] **comp-card-badge**: Card with inline badge (flex row with mixed components)
43
+ - [x] **comp-input**: Form input with border and placeholder-style text
44
+ - [x] **comp-input-value**: Native `<input>` element with value attribute
45
+ - [x] **comp-code-block**: Code block with monospace, background, border
46
+ - [ ] **comp-nav**: Navigation bar with logo and links
47
+
48
+ ### SVG
49
+ - [ ] **svg-inline**: Inline SVG elements (icons) positioned correctly
50
+
51
+ ### Text effects
52
+ - [x] **text-bg-clip-gradient** (DM-462): `background-clip: text` + `-webkit-text-fill-color: transparent` — gradient fills the glyph shapes via SVG `<mask>` over the bg-color rect
53
+
54
+ ### Replaced elements (rasterized as static snapshot — DM-457)
55
+ - [x] **replaced-canvas-shape**: `<canvas>` with drawn shapes — bitmap survives via `page.screenshot`
56
+ - [x] **replaced-video-poster**: `<video poster=…>` paused — poster image captured
57
+ - [x] **replaced-canvas-overlay**: `<canvas>` under a positioned `<div z-index:10>` overlay — overlay does NOT bleed into the canvas snapshot
58
+ - [x] **replaced-canvas-fixed-overlay**: `<canvas>` under a sibling-positioned `<div>` painting on top — sibling does NOT bleed into the canvas snapshot
59
+ - [x] **replaced-iframe-same-origin**: same-origin `<iframe>` (srcdoc) — iframe content paints into the snapshot
60
+ - [x] **snapshot-isolation-pseudo-overlay** (DM-458, `tests/snapshot-isolation.tsx`): canvas covered by a sibling's `::after` pseudo overlay. Inspection-style — decodes the captured snapshot's PNG data URI and asserts no overlay-color pixels leaked through. Catches regressions in the hide-everything-else stylesheet that a comparison-style fixture wouldn't.
61
+
62
+ ### Showcase Integration Tests
63
+ - [x] **showcase-typography**: Full-page layout with headings, badges, code blocks, inline code, status text
64
+ - [x] **showcase-cards**: Card list with badges, buttons, metadata
65
+ - [x] **showcase-forms**: Publish form with labels, inputs, pre block, button
66
+
67
+ ## Testing Approach
68
+
69
+ Tests are defined in `tests/features.ts` (26 feature tests) and `tests/showcase.ts` (3 integration tests). Both use the shared runner in `tests/runner.ts`.
70
+
71
+ For each test case:
72
+ 1. Define an HTML snippet (feature tests) or full-page HTML (showcase tests) exercising the feature
73
+ 2. Render the HTML in Playwright (Chromium) and capture as PNG ("expected")
74
+ 3. Capture the DOM via `captureElementTree` on the Playwright page
75
+ 4. Convert the element tree to SVG via `elementTreeToSvg` using the selected text rendering mode
76
+ 5. Render the SVG in Playwright and capture as PNG ("actual")
77
+ 6. Compare pixel-by-pixel with per-channel tolerance (threshold 16, pass if < 8% total diff)
78
+ 7. Save expected, actual, and diff PNGs to `tests/output/` for visual inspection
79
+
80
+ ### Text Rendering Modes
81
+
82
+ The runner accepts a `--mode` flag (or `TEXT_MODE` env var) to select the text rendering strategy:
83
+
84
+ - **`css`** (default): SVG `<text>` with CSS font properties. Smallest output (~20KB). Best fidelity in Chromium (~0.6% diff). Cross-browser differences from font engine differences.
85
+ - **`path`**: Fontkit converts text to `<path>` outlines using macOS system fonts (SFNS.ttf variable font). Glyph deduplication via `<defs>`/`<use>`. Identical across browsers but larger (~290KB).
86
+ - **`font`**: Embedded woff2 `@font-face` with subsetted system fonts. Uses subset-font for character subsetting, wawoff2 for compression. Largest output (~550KB).
87
+
88
+ ### Running Tests
89
+
90
+ ```bash
91
+ # Run all feature tests (default css mode)
92
+ npx tsx tests/features.ts
93
+
94
+ # Run a single feature test
95
+ npx tsx tests/features.ts --only text-basic
96
+
97
+ # Run with a specific text mode
98
+ npx tsx tests/features.ts --mode path
99
+
100
+ # Run showcase integration tests
101
+ npx tsx tests/showcase.ts
102
+ ```
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Brian Westphal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Domotion
2
+
3
+ DOM-to-animated-SVG renderer. Captures HTML/CSS rendered in headless Chromium and converts the captured tree into a self-contained SVG with optional CSS animations — pixel-faithful to what Chromium painted, scales crisply at any size, and embeds without external assets.
4
+
5
+ ## Why
6
+
7
+ Animated demos for product marketing and documentation usually mean either:
8
+
9
+ - A bundle of MP4s — heavy, hard to scale, no inline embedding.
10
+ - A live iframe — slow, requires the source app to be online, breaks accessibility.
11
+ - Hand-authored SVG animations — accurate but enormously time-consuming for anything beyond a couple of frames.
12
+
13
+ Domotion captures real HTML/CSS as it renders in Chromium, then emits a single inline-embeddable SVG that replays the same pixels with CSS keyframe transitions. Author the demo as plain HTML/CSS in your real app, capture frames, and ship the result as a `<img src="demo.svg">` that loads lazily and scales without artifacts.
14
+
15
+ ## Status
16
+
17
+ Early — extracted in 2026-04 from the slicekit project where it had been incubating as `tools/svg-demo-gen`. APIs may still shift while the project's external surface stabilizes.
18
+
19
+ ## Install
20
+
21
+ ```bash
22
+ npm install domotion-svg
23
+ ```
24
+
25
+ That's it — Domotion auto-installs Playwright's Chromium binary on first use
26
+ (via `npx playwright install chromium`). On CI you may want to pre-install it
27
+ yourself to keep the first job's runtime down.
28
+
29
+ ## Usage
30
+
31
+ ```ts
32
+ import { captureElementTree, elementTreeToSvg, launchChromium, wrapSvg } from "domotion-svg";
33
+
34
+ const browser = await launchChromium();
35
+ const page = await browser.newPage();
36
+ await page.setContent(`<div style="padding:20px;color:white;background:#0d1117">Hello</div>`);
37
+
38
+ const tree = await captureElementTree(page, "body", { x: 0, y: 0, width: 800, height: 200 });
39
+ const svg = wrapSvg(elementTreeToSvg(tree, 800, 200), 800, 200);
40
+
41
+ console.log(svg);
42
+ await browser.close();
43
+ ```
44
+
45
+ For animated demos, capture multiple frames and pass them to `generateAnimatedSvg` (see `examples/`).
46
+
47
+ ## Scripts
48
+
49
+ ```bash
50
+ npm run build # tsc → dist/
51
+ npm test # unit tests
52
+ npm run demos:test # feature visual-regression suite
53
+ npm run demos:test:all # features + showcase + html-test-suite
54
+ npm run demos:review # local server to compare expected/actual/diff PNGs
55
+ npm run demos:examples # run the bundled example demo scripts
56
+ ```
57
+
58
+ ## Documentation
59
+
60
+ - `FEATURES.md` — per-feature support checklist with links to test fixtures.
61
+ - `docs/` — requirements docs covering rendering fidelity, supported CSS features, and known caveats.
62
+ - `CLAUDE.md` — guidance for AI assistants working in this repo.
63
+
64
+ ## License
65
+
66
+ [MIT](LICENSE) © Brian Westphal
@@ -0,0 +1,158 @@
1
+ /**
2
+ * SVG Animation Composer
3
+ *
4
+ * Takes captured SVG frame content and composes them into a single
5
+ * animated SVG with CSS keyframe transitions.
6
+ */
7
+ import { type CursorOverlay, type SelectorResolver } from "./cursor-overlay.js";
8
+ export interface AnimationFrame {
9
+ /** SVG content for this frame (from dom-to-svg) */
10
+ svgContent: string;
11
+ /** Duration this frame is shown (ms) */
12
+ duration: number;
13
+ /** Transition to next frame */
14
+ transition?: {
15
+ /**
16
+ * `crossfade` (default) overlaps fade-out and fade-in. `push-left` slides
17
+ * the outgoing frame off and the incoming frame in from the right.
18
+ * `scroll` keeps both visible during the transition. `cut` is instant —
19
+ * no fade, no slide. For `cut`, `duration` is ignored.
20
+ */
21
+ type: "crossfade" | "push-left" | "scroll" | "cut";
22
+ duration: number;
23
+ };
24
+ /** Overlays: typing, tap ripple */
25
+ overlays?: Overlay[];
26
+ /**
27
+ * Intra-frame property animations. Run during this frame's hold time.
28
+ * The CLI / `DemoRecorder` resolves selectors against the DOM at capture
29
+ * and sets `data-domotion-anim` on matching elements; this list is the
30
+ * post-resolution form referencing those ids. See `IntraFrameAnimation`.
31
+ */
32
+ animations?: IntraFrameAnimation[];
33
+ }
34
+ export interface TypingOverlay {
35
+ kind: "typing";
36
+ text: string;
37
+ x: number;
38
+ y: number;
39
+ fontSize?: number;
40
+ color?: string;
41
+ /** Delay from frame start before typing begins (ms) */
42
+ delay?: number;
43
+ /** Speed per character (ms) */
44
+ speed?: number;
45
+ /** Background color to mask placeholder text */
46
+ bgColor?: string;
47
+ bgWidth?: number;
48
+ bgHeight?: number;
49
+ }
50
+ export interface TapOverlay {
51
+ kind: "tap";
52
+ x: number;
53
+ y: number;
54
+ /** Delay from frame start (ms) */
55
+ delay?: number;
56
+ }
57
+ /**
58
+ * Frame-local SVG overlay: composites a separately-captured SVG (inlined as
59
+ * markup, not referenced as `<image href>`) on top of the captured frame.
60
+ * Used for picture-in-picture effects like sliding a phone-framed preview
61
+ * into the corner of a terminal demo.
62
+ *
63
+ * The overlay is positioned at (x, y), clipped to (width, height), and
64
+ * gets its own `class="ov-<animId>"` wrapper so intra-frame animations
65
+ * (or `enter`/`exit` sugar) can target it without colliding with elements
66
+ * inside the embedded SVG.
67
+ */
68
+ export interface SvgOverlay {
69
+ kind: "svg";
70
+ /**
71
+ * The SVG content to inline. The CLI resolves `src` paths from the
72
+ * config file's directory and namespaces the embedded SVG's ids before
73
+ * setting this field.
74
+ */
75
+ innerSvg: string;
76
+ /** Top-left corner in the captured frame's coordinate space. */
77
+ x: number;
78
+ y: number;
79
+ /** Render size — the embedded SVG's viewBox is preserved and scales to fit. */
80
+ width: number;
81
+ height: number;
82
+ /**
83
+ * Stable id used to key the overlay's wrapper class (`ov-<animId>`) so
84
+ * `enter`/`exit` / `animations` can target it. The CLI assigns this.
85
+ */
86
+ animId: string;
87
+ /** Slide-in entrance (DM-211). Sugar over `animations`. */
88
+ enter?: {
89
+ from: "top" | "bottom" | "left" | "right";
90
+ duration: number;
91
+ easing?: string;
92
+ delay?: number;
93
+ };
94
+ /** Slide-out exit (DM-211). */
95
+ exit?: {
96
+ from: "top" | "bottom" | "left" | "right";
97
+ duration: number;
98
+ easing?: string;
99
+ delay?: number;
100
+ };
101
+ }
102
+ export type Overlay = TypingOverlay | TapOverlay | SvgOverlay;
103
+ /**
104
+ * Animate a CSS property on captured elements that match a selector, while
105
+ * the frame is held on screen. The selector is resolved against the source
106
+ * DOM at capture time (see DM-209) and the matching elements get
107
+ * `class="anim-<id>"` on their rendered SVG groups.
108
+ *
109
+ * Resolution requires the consumer (CLI / `DemoRecorder`) to set
110
+ * `data-domotion-anim="<id>"` on matching DOM elements before capture; the
111
+ * `id` referenced here must be the same id set on the DOM.
112
+ */
113
+ export interface IntraFrameAnimation {
114
+ /** Anim id — must match the `data-domotion-anim` value set on the DOM pre-capture. */
115
+ animId: string;
116
+ /**
117
+ * CSS property to animate. `clipPath` takes raw CSS `clip-path` values
118
+ * (e.g. `"inset(0 100% 0 0)"` -> `"inset(0 0 0 0)"`) and is the right
119
+ * choice for left-to-right reveals like typing-into-captured-text. When
120
+ * the captured element is wrapped in a `<g class="anim-<id>">`, the
121
+ * keyframes apply `clip-path` to that wrapper.
122
+ */
123
+ property: "width" | "height" | "opacity" | "transform" | "translateX" | "translateY" | "clipPath";
124
+ /** Start value (CSS string, e.g. `"0%"`, `"240px"`, `"0.3"`). */
125
+ from: string;
126
+ /** End value (same syntax as `from`). */
127
+ to: string;
128
+ /** Duration in ms. Must be ≤ the parent frame's `duration`. */
129
+ duration: number;
130
+ /** CSS easing string. Default `linear`. */
131
+ easing?: string;
132
+ /** Ms after the frame becomes visible before animation starts. Default 0. */
133
+ delay?: number;
134
+ }
135
+ export interface AnimationConfig {
136
+ width: number;
137
+ height: number;
138
+ frames: AnimationFrame[];
139
+ /**
140
+ * Markup (e.g. `<path id="g0" d="..."/>...`) hoisted into the top-level
141
+ * `<defs>`. Frames can reference these IDs via `<use href="#...">`. Use for
142
+ * glyph paths and other assets that repeat across frames — avoids duplicating
143
+ * them in every frame's local defs.
144
+ */
145
+ sharedDefs?: string;
146
+ /**
147
+ * Optional cursor / click overlay (DM-277). Renders a macOS-style cursor
148
+ * moving along the script timeline with QuickTime-style click pulses.
149
+ * Off by default; opt-in per animation. See `docs/13-cursor-overlay.md`.
150
+ */
151
+ cursorOverlay?: CursorOverlay;
152
+ /**
153
+ * Resolver for selector-based cursor move events. Required if any event
154
+ * uses `selector`; otherwise pass undefined / null.
155
+ */
156
+ resolveSelector?: SelectorResolver;
157
+ }
158
+ export declare function generateAnimatedSvg(config: AnimationConfig): string;