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.
- package/FEATURES.md +102 -0
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/dist/animator.d.ts +158 -0
- package/dist/animator.js +424 -0
- package/dist/animator.test.d.ts +5 -0
- package/dist/animator.test.js +169 -0
- package/dist/border-radius.test.d.ts +1 -0
- package/dist/border-radius.test.js +148 -0
- package/dist/capture.d.ts +193 -0
- package/dist/capture.js +786 -0
- package/dist/chrome.d.ts +45 -0
- package/dist/chrome.js +107 -0
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +512 -0
- package/dist/client/dom.d.ts +10 -0
- package/dist/client/dom.js +17 -0
- package/dist/conic-raster.d.ts +58 -0
- package/dist/conic-raster.js +292 -0
- package/dist/conic-raster.test.d.ts +1 -0
- package/dist/conic-raster.test.js +187 -0
- package/dist/coretext-extractor.test.d.ts +1 -0
- package/dist/coretext-extractor.test.js +94 -0
- package/dist/coretext-helper.d.ts +60 -0
- package/dist/coretext-helper.js +205 -0
- package/dist/cross-origin-font-face.test.d.ts +1 -0
- package/dist/cross-origin-font-face.test.js +107 -0
- package/dist/cursor-overlay.d.ts +123 -0
- package/dist/cursor-overlay.js +207 -0
- package/dist/cursor-overlay.test.d.ts +1 -0
- package/dist/cursor-overlay.test.js +88 -0
- package/dist/dark-mode-capture.test.d.ts +1 -0
- package/dist/dark-mode-capture.test.js +158 -0
- package/dist/dark-mode-form-controls.test.d.ts +1 -0
- package/dist/dark-mode-form-controls.test.js +218 -0
- package/dist/dom-to-svg.d.ts +1016 -0
- package/dist/dom-to-svg.js +7717 -0
- package/dist/embed-remote-images.test.d.ts +1 -0
- package/dist/embed-remote-images.test.js +424 -0
- package/dist/form-controls.d.ts +70 -0
- package/dist/form-controls.js +1151 -0
- package/dist/frame-merge.d.ts +95 -0
- package/dist/frame-merge.js +374 -0
- package/dist/frame-merge.test.d.ts +6 -0
- package/dist/frame-merge.test.js +144 -0
- package/dist/gradients.d.ts +184 -0
- package/dist/gradients.js +937 -0
- package/dist/gradients.test.d.ts +1 -0
- package/dist/gradients.test.js +150 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +7 -0
- package/dist/jsx-runtime.d.ts +27 -0
- package/dist/jsx-runtime.js +96 -0
- package/dist/jsx-runtime.test.d.ts +1 -0
- package/dist/jsx-runtime.test.js +41 -0
- package/dist/kerfjs-imports.test.d.ts +1 -0
- package/dist/kerfjs-imports.test.js +36 -0
- package/dist/mask.test.d.ts +1 -0
- package/dist/mask.test.js +206 -0
- package/dist/optimize.d.ts +12 -0
- package/dist/optimize.js +32 -0
- package/dist/preserve-aspect-ratio.test.d.ts +1 -0
- package/dist/preserve-aspect-ratio.test.js +38 -0
- package/dist/resize-embedded-images.d.ts +33 -0
- package/dist/resize-embedded-images.js +164 -0
- package/dist/resize-embedded-images.test.d.ts +9 -0
- package/dist/resize-embedded-images.test.js +255 -0
- package/dist/stacking-context.test.d.ts +1 -0
- package/dist/stacking-context.test.js +927 -0
- package/dist/text-renderer.d.ts +42 -0
- package/dist/text-renderer.js +608 -0
- package/dist/text-renderer.test.d.ts +1 -0
- package/dist/text-renderer.test.js +150 -0
- package/dist/text-to-path.d.ts +265 -0
- package/dist/text-to-path.js +1800 -0
- package/dist/text-to-path.test.d.ts +1 -0
- package/dist/text-to-path.test.js +570 -0
- package/dist/utils/escapeHtml.d.ts +2 -0
- package/dist/utils/escapeHtml.js +15 -0
- package/dist/webfont-unicode-range.test.d.ts +1 -0
- package/dist/webfont-unicode-range.test.js +174 -0
- package/package.json +55 -0
- package/src/animator.test.ts +179 -0
- package/src/animator.ts +660 -0
- package/src/border-radius.test.ts +160 -0
- package/src/capture.ts +810 -0
- package/src/cli.ts +582 -0
- package/src/conic-raster.test.ts +213 -0
- package/src/conic-raster.ts +309 -0
- package/src/coretext-extractor.test.ts +130 -0
- package/src/coretext-helper.ts +256 -0
- package/src/cross-origin-font-face.test.ts +119 -0
- package/src/cursor-overlay.test.ts +95 -0
- package/src/cursor-overlay.ts +297 -0
- package/src/dark-mode-capture.test.ts +177 -0
- package/src/dark-mode-form-controls.test.ts +228 -0
- package/src/dom-to-svg.ts +8376 -0
- package/src/embed-remote-images.test.ts +461 -0
- package/src/form-controls.ts +1174 -0
- package/src/frame-merge.test.ts +157 -0
- package/src/frame-merge.ts +447 -0
- package/src/globals.d.ts +2 -0
- package/src/gradients.test.ts +175 -0
- package/src/gradients.ts +955 -0
- package/src/index.ts +12 -0
- package/src/kerf-jsx-augmentation.d.ts +36 -0
- package/src/kerfjs-imports.test.tsx +45 -0
- package/src/mask.test.ts +274 -0
- package/src/optimize.ts +34 -0
- package/src/preserve-aspect-ratio.test.ts +49 -0
- package/src/resize-embedded-images.test.ts +292 -0
- package/src/resize-embedded-images.ts +180 -0
- package/src/stacking-context.test.ts +967 -0
- package/src/text-renderer.test.ts +162 -0
- package/src/text-renderer.ts +623 -0
- package/src/text-to-path.test.ts +639 -0
- package/src/text-to-path.ts +1810 -0
- package/src/utils/escapeHtml.ts +16 -0
- 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;
|