@pixodesk/svg-animator-vue 1.0.35 → 1.0.40
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/README.md +16 -9
- package/dist/index.cjs +79 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +76 -36
- package/dist/index.d.ts +76 -36
- package/dist/index.js +77 -51
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +4938 -3226
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -64,7 +64,8 @@ const animator = ref<VueAnimatorApi | null>(null);
|
|
|
64
64
|
</template>
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
<!-- px-check members VueAnimatorApi pkg=vue -->
|
|
68
|
+
`VueAnimatorApi` methods: `play()`, `pause()`, `cancel()`, `finish()`, `isPlaying()`, `setPlaybackRate(rate)`, `getCurrentTime()`, `setCurrentTime(ms)`, `getCurrentProgress()`, `setCurrentProgress(p)`.
|
|
68
69
|
|
|
69
70
|
### Controlled time
|
|
70
71
|
|
|
@@ -79,6 +80,7 @@ Render a single frame — by time in milliseconds, or by fraction of the whole t
|
|
|
79
80
|
|
|
80
81
|
## Props
|
|
81
82
|
|
|
83
|
+
<!-- px-check props PixodeskSvgAnimator pkg=vue -->
|
|
82
84
|
| Prop | Type | Description |
|
|
83
85
|
|---|---|---|
|
|
84
86
|
| `doc` | `PxAnimatedSvgDocument` | The animation document to render (required) |
|
|
@@ -87,12 +89,16 @@ Render a single frame — by time in milliseconds, or by fraction of the whole t
|
|
|
87
89
|
| `pause` | `boolean` | Pause current playback |
|
|
88
90
|
| `progress` | `number` | show the frame at this position in the whole timeline (duration × iterations): `0` is the first frame, `0.5` the middle, `1` the last |
|
|
89
91
|
| `time` | `number` | show the frame at that time, in milliseconds from the start |
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `duration` | `number` | Shortcut for `
|
|
93
|
-
| `delay` | `number` | Shortcut for `
|
|
94
|
-
| `iterations` | `number \| 'infinite'` | Shortcut for `
|
|
95
|
-
| `startOn` | `'load' \| 'mouseOver' \| 'click' \| 'scrollIntoView' \| 'programmatic'` | Shortcut for `
|
|
92
|
+
| `timeline` | `object \| string` | per-instance override of the document's `timeline` block, deep-merged over it — same shape as the file; `null` at any slot deletes that key. A JSON string is accepted too. See [Playback overrides](#playback-overrides) |
|
|
93
|
+
| `resetTimeline` | `boolean` | ignore the document's own timeline and start from the player's default timeline, with `timeline` on top |
|
|
94
|
+
| `duration` | `number` | Shortcut for `timeline.duration` (ms) |
|
|
95
|
+
| `delay` | `number` | Shortcut for `timeline.delay` (ms) |
|
|
96
|
+
| `iterations` | `number \| 'infinite'` | Shortcut for `timeline.iterations` |
|
|
97
|
+
| `startOn` | `'load' \| 'mouseOver' \| 'click' \| 'scrollIntoView' \| 'programmatic'` | Shortcut for `timeline.trigger.startOn` |
|
|
98
|
+
| `onWarn` | `(diagnostic) => void` | it plays, but something was ignored, degraded or misspelled; without it → `console.warn` (a prop, not an event — see below) |
|
|
99
|
+
| `onError` | `(diagnostic) => void` | this instance will not play — failed to load, parse or build, or the render threw; without it → `console.error` |
|
|
100
|
+
| `muteWarn` | `boolean` | switch the `console.warn` fallback off — for when you know the player has something to say about this document and are prepared to tolerate it. `onWarn`, if you gave it, still fires: mute is about the console, not about you |
|
|
101
|
+
| `muteError` | `boolean` | the same switch for `console.error` |
|
|
96
102
|
|
|
97
103
|
With none of `autoplay` / `play` / `pause` / `progress` / `time` set, the component renders the animation statically (initial state, no playback); use the template ref for imperative control.
|
|
98
104
|
|
|
@@ -100,11 +106,12 @@ Note: passing a different `doc` (or unmounting) throws the old animator away and
|
|
|
100
106
|
|
|
101
107
|
## Events
|
|
102
108
|
|
|
109
|
+
<!-- px-check emits PixodeskSvgAnimator pkg=vue -->
|
|
103
110
|
| Event | Description |
|
|
104
111
|
|---|---|
|
|
105
112
|
| `play` | Animation started or resumed |
|
|
106
113
|
| `pause` | Animation paused |
|
|
107
|
-
| `cancel` | Animation
|
|
108
|
-
| `finish` | Animation
|
|
114
|
+
| `cancel` | Animation canceled |
|
|
115
|
+
| `finish` | Animation reached its end — every iteration played, or `finish()` was called |
|
|
109
116
|
| `remove` | Animation cleaned up (e.g. on unmount) |
|
|
110
117
|
| `stop` | Fired alongside any event that halts playback (`pause` / `cancel` / `finish` / `remove`) |
|
package/dist/index.cjs
CHANGED
|
@@ -28,22 +28,24 @@ module.exports = __toCommonJS(index_exports);
|
|
|
28
28
|
|
|
29
29
|
// src/PixodeskSvgAnimator.ts
|
|
30
30
|
var import_svg_animator_web = require("@pixodesk/svg-animator-web");
|
|
31
|
+
var import_svg_animator_core = require("@pixodesk/svg-animator-core");
|
|
32
|
+
var import_internal = require("@pixodesk/svg-animator-core/internal");
|
|
31
33
|
var import_vue = require("vue");
|
|
32
34
|
var VUE_PROP = { ref: "ref" };
|
|
33
|
-
function createVueAdapter(elementRefs) {
|
|
35
|
+
function createVueAdapter(elementRefs, diag) {
|
|
34
36
|
const warnedSelectors = /* @__PURE__ */ new Set();
|
|
35
37
|
const adapter = {
|
|
36
38
|
isConnected: () => true,
|
|
37
39
|
setAttribute: (id, attrName, value) => {
|
|
38
|
-
attrName = (0,
|
|
40
|
+
attrName = (0, import_internal.camelCaseToKebabWordIfNeeded)(attrName);
|
|
39
41
|
const element = elementRefs.get(id);
|
|
40
42
|
if (!element && !warnedSelectors.has(id)) {
|
|
41
43
|
warnedSelectors.add(id);
|
|
42
|
-
|
|
44
|
+
diag.warn(import_svg_animator_web.PxDiagnosticKind.host, 'setAttribute: No elements found for id "' + id + '"');
|
|
43
45
|
}
|
|
44
46
|
if (element) {
|
|
45
47
|
element.setAttribute(attrName, value);
|
|
46
|
-
if (
|
|
48
|
+
if (import_internal.STYLE_ATTR_NAMES.has(attrName)) {
|
|
47
49
|
element.style[attrName] = value;
|
|
48
50
|
}
|
|
49
51
|
}
|
|
@@ -51,31 +53,31 @@ function createVueAdapter(elementRefs) {
|
|
|
51
53
|
};
|
|
52
54
|
return adapter;
|
|
53
55
|
}
|
|
54
|
-
function applyDocOverrides(doc, props, compMode) {
|
|
55
|
-
const {
|
|
56
|
-
const patch = (0,
|
|
57
|
-
const fullPatch = compMode
|
|
56
|
+
function applyDocOverrides(doc, props, compMode, diag) {
|
|
57
|
+
const { timeline, resetTimeline, duration, delay, iterations, startOn } = props;
|
|
58
|
+
const patch = (0, import_svg_animator_core.foldTimelineOverride)(timeline, { duration, delay, iterations, startOn });
|
|
59
|
+
const fullPatch = (0, import_svg_animator_core.controlModeTakesOverTrigger)(compMode) ? {
|
|
58
60
|
...patch ?? {},
|
|
59
61
|
timeline: {
|
|
60
62
|
...patch?.timeline ?? {},
|
|
61
63
|
trigger: { ...patch?.timeline?.trigger ?? {}, startOn: "programmatic" }
|
|
62
64
|
}
|
|
63
65
|
} : patch;
|
|
64
|
-
if (fullPatch !== void 0 ||
|
|
65
|
-
const applied = (0,
|
|
66
|
-
for (const w of applied.warnings)
|
|
66
|
+
if (fullPatch !== void 0 || resetTimeline) {
|
|
67
|
+
const applied = (0, import_svg_animator_core.applyAnimatorConfig)(doc, fullPatch ?? {}, { resetDefaults: !!resetTimeline });
|
|
68
|
+
for (const w of applied.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage, "timeline override: " + w);
|
|
67
69
|
doc = applied.doc;
|
|
68
70
|
}
|
|
69
71
|
return doc;
|
|
70
72
|
}
|
|
71
73
|
function calcSeekMs(doc, props) {
|
|
72
74
|
let seekMs;
|
|
73
|
-
const animator = (0,
|
|
75
|
+
const animator = (0, import_svg_animator_core.getAnimatorConfig)(doc) || {};
|
|
74
76
|
if (props.progress !== void 0) {
|
|
75
77
|
const iterationsValue = props.iterations ?? animator.iterations;
|
|
76
|
-
const iterationsCount = typeof iterationsValue === "number" && iterationsValue >= 1 ? iterationsValue : 1;
|
|
77
|
-
const singleDuration = props.duration ?? animator.duration ??
|
|
78
|
-
seekMs = props.progress
|
|
78
|
+
const iterationsCount = iterationsValue === "infinite" ? Infinity : typeof iterationsValue === "number" && iterationsValue >= 1 ? iterationsValue : 1;
|
|
79
|
+
const singleDuration = props.duration ?? animator.duration ?? import_internal.DEFAULT_DURATION_MS;
|
|
80
|
+
seekMs = (0, import_svg_animator_core.progressToTimeMs)(props.progress, singleDuration, iterationsCount);
|
|
79
81
|
}
|
|
80
82
|
if (props.time !== void 0) seekMs = props.time;
|
|
81
83
|
return seekMs;
|
|
@@ -85,10 +87,10 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
85
87
|
props: {
|
|
86
88
|
// -- Source
|
|
87
89
|
doc: { type: Object, required: true },
|
|
88
|
-
// -- Playback override:
|
|
89
|
-
// plus the four shortcuts people reach for most.
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
// -- Playback override: the document's `timeline` block as a patch (or a JSON string),
|
|
91
|
+
// plus the four shortcuts people reach for most. The same names as React / RN.
|
|
92
|
+
timeline: { type: [Object, String] },
|
|
93
|
+
resetTimeline: { type: Boolean, default: void 0 },
|
|
92
94
|
duration: { type: Number },
|
|
93
95
|
delay: { type: Number },
|
|
94
96
|
iterations: { type: [Number, String] },
|
|
@@ -99,21 +101,42 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
99
101
|
pause: { type: Boolean, default: void 0 },
|
|
100
102
|
// -- Controlled time
|
|
101
103
|
progress: { type: Number },
|
|
102
|
-
time: { type: Number }
|
|
104
|
+
time: { type: Number },
|
|
105
|
+
// -- Diagnostics (API review §5).
|
|
106
|
+
// Function PROPS, not emits, on purpose: an emit handler always exists, so wiring
|
|
107
|
+
// these to `emit` would permanently suppress the console fallback for anyone who
|
|
108
|
+
// never listens. As props, "not given" really is undefined and the console still
|
|
109
|
+
// speaks by default — the same contract as React and React Native.
|
|
110
|
+
onWarn: { type: Function },
|
|
111
|
+
onError: { type: Function },
|
|
112
|
+
// `muteWarn` / `muteError` switch the console fallback off — for a host that knows
|
|
113
|
+
// about the warnings and tolerates them; a handler you passed still fires.
|
|
114
|
+
muteWarn: { type: Boolean, default: void 0 },
|
|
115
|
+
muteError: { type: Boolean, default: void 0 }
|
|
103
116
|
},
|
|
104
117
|
emits: ["play", "stop", "pause", "cancel", "finish", "remove"],
|
|
105
118
|
setup(props, { expose, emit }) {
|
|
106
119
|
const elementRefs = /* @__PURE__ */ new Map();
|
|
107
120
|
const apiRef = (0, import_vue.shallowRef)(null);
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
121
|
+
const makeDiag = () => (0, import_internal.createDiagnostics)(
|
|
122
|
+
{ onWarn: props.onWarn, onError: props.onError, muteWarn: props.muteWarn, muteError: props.muteError },
|
|
123
|
+
"[PixodeskSvgAnimator]"
|
|
124
|
+
);
|
|
125
|
+
const resolvedMode = (0, import_vue.computed)(() => (0, import_svg_animator_core.resolveControlMode)({
|
|
126
|
+
progress: props.progress,
|
|
127
|
+
time: props.time,
|
|
128
|
+
play: props.play,
|
|
129
|
+
pause: props.pause,
|
|
130
|
+
autoplay: props.autoplay
|
|
131
|
+
}));
|
|
132
|
+
const compMode = (0, import_vue.computed)(() => resolvedMode.value.mode);
|
|
133
|
+
(0, import_vue.watch)(resolvedMode, (r) => {
|
|
134
|
+
const diag = makeDiag();
|
|
135
|
+
for (const w of r.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage, w);
|
|
136
|
+
}, { immediate: true });
|
|
114
137
|
const resolvedDoc = (0, import_vue.computed)(() => {
|
|
115
138
|
let doc = (0, import_svg_animator_web.generateNewIds)(props.doc);
|
|
116
|
-
return applyDocOverrides(doc, props, compMode.value);
|
|
139
|
+
return applyDocOverrides(doc, props, compMode.value, makeDiag());
|
|
117
140
|
});
|
|
118
141
|
function renderNode(node) {
|
|
119
142
|
if (!node) return null;
|
|
@@ -130,32 +153,29 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
130
153
|
};
|
|
131
154
|
}
|
|
132
155
|
const childVNodes = children?.map((child) => renderNode(child)).filter(Boolean);
|
|
133
|
-
|
|
156
|
+
const text = typeof node.textContent === "string" ? node.textContent : void 0;
|
|
157
|
+
return (0, import_vue.h)(type, normProps, childVNodes?.length ? childVNodes : text);
|
|
134
158
|
}
|
|
135
159
|
function createApi() {
|
|
136
160
|
destroyApi();
|
|
137
161
|
const doc = resolvedDoc.value;
|
|
138
162
|
if (!doc) return;
|
|
139
|
-
const
|
|
163
|
+
const options = {
|
|
164
|
+
doc,
|
|
165
|
+
adapter: createVueAdapter(elementRefs, makeDiag()),
|
|
140
166
|
onPlay: () => emit("play"),
|
|
141
|
-
onPause: () =>
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
emit("stop");
|
|
152
|
-
},
|
|
153
|
-
onRemove: () => {
|
|
154
|
-
emit("remove");
|
|
155
|
-
emit("stop");
|
|
156
|
-
}
|
|
167
|
+
onPause: () => emit("pause"),
|
|
168
|
+
onCancel: () => emit("cancel"),
|
|
169
|
+
onFinish: () => emit("finish"),
|
|
170
|
+
onRemove: () => emit("remove"),
|
|
171
|
+
onStop: () => emit("stop"),
|
|
172
|
+
// The player's own diagnostics reach the same handlers as the component's.
|
|
173
|
+
onWarn: props.onWarn,
|
|
174
|
+
onError: props.onError,
|
|
175
|
+
muteWarn: props.muteWarn,
|
|
176
|
+
muteError: props.muteError
|
|
157
177
|
};
|
|
158
|
-
apiRef.value = (0, import_svg_animator_web.createAnimator)(
|
|
178
|
+
apiRef.value = (0, import_svg_animator_web.createAnimator)(options);
|
|
159
179
|
syncPlayState();
|
|
160
180
|
applySeek();
|
|
161
181
|
}
|
|
@@ -164,19 +184,19 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
164
184
|
apiRef.value = null;
|
|
165
185
|
}
|
|
166
186
|
function syncPlayState() {
|
|
167
|
-
if (compMode.value !==
|
|
187
|
+
if (compMode.value !== import_svg_animator_core.PxControlMode.play) return;
|
|
168
188
|
if (props.play && !props.pause) {
|
|
169
189
|
apiRef.value?.play();
|
|
170
190
|
} else if (props.pause) {
|
|
171
191
|
apiRef.value?.pause();
|
|
172
192
|
} else if (props.play === false) {
|
|
173
|
-
apiRef.value?.
|
|
193
|
+
apiRef.value?.pause();
|
|
174
194
|
} else {
|
|
175
195
|
apiRef.value?.play();
|
|
176
196
|
}
|
|
177
197
|
}
|
|
178
198
|
function applySeek() {
|
|
179
|
-
if (compMode.value !==
|
|
199
|
+
if (compMode.value !== import_svg_animator_core.PxControlMode.fixedTime) return;
|
|
180
200
|
const doc = resolvedDoc.value;
|
|
181
201
|
if (!doc) return;
|
|
182
202
|
const seekMs = calcSeekMs(doc, props);
|
|
@@ -200,7 +220,9 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
200
220
|
finish: () => apiRef.value?.finish(),
|
|
201
221
|
setPlaybackRate: (rate) => apiRef.value?.setPlaybackRate(rate),
|
|
202
222
|
getCurrentTime: () => apiRef.value?.getCurrentTime() ?? null,
|
|
203
|
-
setCurrentTime: (time) => apiRef.value?.setCurrentTime(time)
|
|
223
|
+
setCurrentTime: (time) => apiRef.value?.setCurrentTime(time),
|
|
224
|
+
getCurrentProgress: () => apiRef.value?.getCurrentProgress() ?? null,
|
|
225
|
+
setCurrentProgress: (progress) => apiRef.value?.setCurrentProgress(progress)
|
|
204
226
|
};
|
|
205
227
|
expose(publicApi);
|
|
206
228
|
return () => {
|
|
@@ -212,13 +234,15 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
212
234
|
var PixodeskSvgAnimator_default = PixodeskSvgAnimator;
|
|
213
235
|
|
|
214
236
|
// src/PixodeskSvgCssAnimator.ts
|
|
237
|
+
var import_svg_animator_core2 = require("@pixodesk/svg-animator-core");
|
|
215
238
|
var import_vue2 = require("vue");
|
|
216
239
|
var PixodeskSvgCssAnimator = (0, import_vue2.defineComponent)({
|
|
217
240
|
name: "PixodeskSvgCssAnimator",
|
|
218
241
|
inheritAttrs: false,
|
|
219
242
|
props: {
|
|
220
243
|
startOn: { type: String, default: "load" },
|
|
221
|
-
outAction: { type: String, default: "continue" }
|
|
244
|
+
outAction: { type: String, default: "continue" },
|
|
245
|
+
scrollIntoViewThreshold: { type: Number, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold }
|
|
222
246
|
},
|
|
223
247
|
setup(props, { slots }) {
|
|
224
248
|
const attrs = (0, import_vue2.useAttrs)();
|
|
@@ -233,11 +257,13 @@ var PixodeskSvgCssAnimator = (0, import_vue2.defineComponent)({
|
|
|
233
257
|
const el = divRef.value;
|
|
234
258
|
if (!el) return;
|
|
235
259
|
const outState = props.outAction === "reset" ? "idle" : props.outAction === "pause" ? "paused" : "playing";
|
|
260
|
+
const threshold = props.scrollIntoViewThreshold;
|
|
261
|
+
const visible = (entry) => threshold > 0 ? entry.intersectionRatio >= threshold : entry.isIntersecting;
|
|
236
262
|
const observer = new IntersectionObserver(
|
|
237
263
|
([entry]) => {
|
|
238
|
-
state.value = entry
|
|
264
|
+
state.value = visible(entry) ? "playing" : outState;
|
|
239
265
|
},
|
|
240
|
-
{ threshold
|
|
266
|
+
{ threshold }
|
|
241
267
|
);
|
|
242
268
|
observer.observe(el);
|
|
243
269
|
observerCleanup = () => observer.disconnect();
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/PixodeskSvgAnimator.ts","../src/PixodeskSvgCssAnimator.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport PixodeskSvgAnimator from './PixodeskSvgAnimator';\nexport { PixodeskSvgAnimator };\nexport type { VueAnimatorApi } from './PixodeskSvgAnimator';\n\nimport PixodeskSvgCssAnimator from './PixodeskSvgCssAnimator';\nexport { PixodeskSvgCssAnimator };","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport type { PxAnimatedSvgDocument, PxAnimatorAPI, PxAnimatorConfigPatch, PxNode, PxPlatformAdapter, PxTimelineEngineExtra, PxTrigger } from '@pixodesk/svg-animator-web';\nimport { camelCaseToKebabWordIfNeeded, createAnimator, FillMode, generateNewIds, getNormalizedProps, STYLE_ATTR_NAMES, applyAnimatorConfig, foldAnimatorConfigShortcuts, getAnimatorConfig } from '@pixodesk/svg-animator-web';\nimport {\n computed, defineComponent, h, onMounted, onUnmounted, ref, shallowRef, type PropType, type VNode,\n watch,\n} from 'vue';\n\n\n// -- Public types -----------------------------------------------------------\n\n/** Vue's own prop names on the vnode — not wire keys. See the React twin. */\nconst VUE_PROP = { ref: 'ref' } as const;\n\nexport interface VueAnimatorApi {\n /** Returns true if the animation is currently running. */\n isPlaying(): boolean;\n\n /** Starts or resumes the animation. */\n play(): void;\n\n /** Pauses the animation at its current state. */\n pause(): void;\n\n /** Stops the animation and resets it to its initial state. */\n cancel(): void;\n\n /** Jumps to the end of the animation and holds the final state. */\n finish(): void;\n\n /** Changes the speed of the animation. 1 is normal, 2 is double, -1 is reverse. */\n setPlaybackRate(rate: number): void;\n\n /** Returns the current playback time in milliseconds. */\n getCurrentTime(): number | null;\n\n /** Jumps to a specific time (in milliseconds) in the animation. */\n setCurrentTime(time: number): void;\n}\n\n\n// -- Internal types ---------------------------------------------------------\n\nenum CompMode {\n static = 'static',\n autoplay = 'autoplay',\n play = 'play',\n fixedTime = 'fixedTime'\n}\n\n\n// -- Vue ↔ Animator bridge --------------------------------------------------\n\n/**\n * Creates a platform adapter that routes animator attribute updates\n * to the corresponding Vue-managed DOM element refs.\n */\nfunction createVueAdapter(elementRefs: Map<string, Element>) {\n const warnedSelectors = new Set<string>();\n\n const adapter: PxPlatformAdapter = {\n isConnected: () => true,\n setAttribute: (id, attrName, value) => {\n attrName = camelCaseToKebabWordIfNeeded(attrName);\n\n const element = elementRefs.get(id);\n\n if (!element && !warnedSelectors.has(id)) {\n warnedSelectors.add(id);\n console.warn('setAttribute: No elements found for id \"' + id + '\"');\n }\n\n if (element) {\n element.setAttribute(attrName, value);\n if (STYLE_ATTR_NAMES.has(attrName)) {\n (element as HTMLElement).style[attrName as any] = value;\n }\n }\n },\n };\n return adapter;\n}\n\n// FIXME: add model validation (e.g. isElementFileJson check)\n\n\n// -- Helper: apply doc overrides --------------------------------------------\n\ninterface DocOverrideProps {\n /** Per-instance override of the document's `animator` config — the same shape as\n * `animator` in SCHEMA.md, deep-merged; `null` at a slot deletes it. Also accepts a\n * JSON string. Replaces the former flat mode/fill/direction/frameRate/outAction props. */\n config?: PxAnimatorConfigPatch | string;\n /** Start from the player's defaults instead of the document's playback settings. */\n resetDocDefaults?: boolean;\n duration?: number;\n delay?: number;\n iterations?: number | 'infinite';\n startOn?: 'load' | 'mouseOver' | 'click' | 'scrollIntoView' | 'programmatic';\n progress?: number;\n time?: number;\n}\n\nfunction applyDocOverrides(\n doc: PxAnimatedSvgDocument,\n props: DocOverrideProps,\n compMode: CompMode,\n): PxAnimatedSvgDocument {\n\n // ONE patch, applied ONCE: the props, plus the component's own need to take the trigger\n // over in the non-autoplay control modes.\n //\n // This replaces three hand-rolled spread blocks that wrote the FLAT runtime keys. On a\n // wire-format document — which is what every writer emits — `flattenAnimatorTimeline`\n // overwrote them from `timeline` immediately afterwards, so the overrides were silently\n // discarded. See PLAYBACK-OVERRIDE-PLAN.md §1.1.\n const { config, resetDocDefaults, duration, delay, iterations, startOn } = props;\n const patch = foldAnimatorConfigShortcuts(config, { duration, delay, iterations, startOn });\n const fullPatch: any = compMode !== CompMode.autoplay\n ? {\n ...(patch ?? {}),\n timeline: {\n ...((patch as any)?.timeline ?? {}),\n trigger: { ...((patch as any)?.timeline?.trigger ?? {}), startOn: 'programmatic' },\n },\n }\n : patch;\n\n if (fullPatch !== undefined || resetDocDefaults) {\n const applied = applyAnimatorConfig(doc, fullPatch ?? {}, { resetDefaults: !!resetDocDefaults });\n for (const w of applied.warnings) console.warn('[PixodeskSvgAnimator] config override:', w);\n doc = applied.doc;\n }\n\n return doc;\n}\n\n/**\n * Controlled-time mode: absolute seek target in ms. `progress` is a fraction\n * (0–1) of the WHOLE timeline (duration × iterations); `time` is absolute.\n * Applied through the animator API (setCurrentTime) so scrubbing does NOT\n * recreate the animator.\n */\nfunction calcSeekMs(doc: PxAnimatedSvgDocument, props: DocOverrideProps): number | undefined {\n let seekMs: number | undefined;\n // The FLAT runtime view, so this works on a wire-format document too — reading\n // `doc.animator.duration` directly finds nothing there.\n const animator = getAnimatorConfig(doc) || {};\n if (props.progress !== undefined) {\n const iterationsValue = props.iterations ?? animator.iterations;\n const iterationsCount = typeof iterationsValue === 'number' && iterationsValue >= 1 ? iterationsValue : 1;\n const singleDuration = props.duration ?? animator.duration ?? 1000; // engine default duration\n seekMs = props.progress * singleDuration * iterationsCount;\n }\n if (props.time !== undefined) seekMs = props.time;\n return seekMs;\n}\n\n\n// -- Main public component --------------------------------------------------\n\n/**\n * Vue component for rendering and controlling Pixodesk SVG animations.\n *\n * Supports four mutually-exclusive control modes:\n *\n * 1. **Autoplay** – uses triggers from the animation document.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" autoplay />\n * ```\n *\n * 2. **Declarative play/pause** – controlled via boolean props.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" play :pause=\"false\" />\n * ```\n *\n * 3. **Imperative** – exposes a ref-based API for full programmatic control.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" ref=\"animator\" />\n * <button @click=\"$refs.animator.play()\">Play</button>\n * ```\n *\n * 4. **Controlled time** – renders a single frame at a given time.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" :progress=\"0.5\" />\n * <PixodeskSvgAnimator :doc=\"animation\" :time=\"500\" />\n * ```\n */\nconst PixodeskSvgAnimator = defineComponent({\n name: 'PixodeskSvgAnimator',\n\n props: {\n // -- Source\n doc: { type: Object as PropType<PxAnimatedSvgDocument>, required: true },\n\n // -- Playback override: one object spelled exactly like `animator` in the file,\n // plus the four shortcuts people reach for most.\n config: { type: [Object, String] as PropType<PxAnimatorConfigPatch | string> },\n resetDocDefaults: { type: Boolean, default: undefined },\n duration: { type: Number },\n delay: { type: Number },\n iterations: { type: [Number, String] as PropType<number | 'infinite'> },\n startOn: { type: String as PropType<'load' | 'mouseOver' | 'click' | 'scrollIntoView' | 'programmatic'> },\n\n // -- Declarative control\n autoplay: { type: Boolean, default: undefined },\n play: { type: Boolean, default: undefined },\n pause: { type: Boolean, default: undefined },\n\n // -- Controlled time\n progress: { type: Number },\n time: { type: Number },\n },\n\n emits: ['play', 'stop', 'pause', 'cancel', 'finish', 'remove'],\n\n setup(props, { expose, emit }) {\n const elementRefs = new Map<string, Element>();\n const apiRef = shallowRef<PxAnimatorAPI | null>(null);\n\n // -- Determine control mode ---------------------------------------------\n\n const compMode = computed<CompMode>(() => {\n if (props.autoplay) return CompMode.autoplay;\n if (props.progress !== undefined || props.time !== undefined) return CompMode.fixedTime;\n if (props.play !== undefined || props.pause !== undefined) return CompMode.play;\n return CompMode.static;\n });\n\n // -- Prepare the document with overrides --------------------------------\n\n const resolvedDoc = computed(() => {\n let doc = generateNewIds(props.doc);\n return applyDocOverrides(doc, props, compMode.value);\n });\n\n // -- Render the SVG node tree -------------------------------------------\n\n function renderNode(node: PxNode | undefined): VNode | null {\n if (!node) return null;\n\n const { type, animate, meta, children, ...attrs } = node;\n const normProps = getNormalizedProps(attrs);\n\n // Capture a ref to each element with an id.\n if (node.id) {\n const nodeId = node.id;\n normProps[VUE_PROP.ref] = (el: Element | null) => {\n if (el) {\n elementRefs.set(nodeId, el);\n } else {\n elementRefs.delete(nodeId);\n }\n };\n }\n\n const childVNodes = children?.map(child => renderNode(child)).filter(Boolean) as VNode[] | undefined;\n return h(type, normProps, childVNodes);\n }\n\n // -- Animator lifecycle -------------------------------------------------\n\n function createApi() {\n destroyApi();\n const doc = resolvedDoc.value;\n if (!doc) return;\n\n // Route animator lifecycle events to Vue component events.\n // `stop` fires alongside any event that halts playback.\n const callbacks = {\n onPlay: () => emit('play'),\n onPause: () => { emit('pause'); emit('stop'); },\n onCancel: () => { emit('cancel'); emit('stop'); },\n onFinish: () => { emit('finish'); emit('stop'); },\n onRemove: () => { emit('remove'); emit('stop'); },\n };\n\n apiRef.value = createAnimator({ data: doc, adapter: createVueAdapter(elementRefs), callbacks });\n\n // (Re)apply the declarative control state to the fresh animator —\n // covers both the initial mount (e.g. `:play=\"true\"` from the\n // start) and doc swaps.\n syncPlayState();\n applySeek();\n }\n\n function destroyApi() {\n apiRef.value?.destroy();\n apiRef.value = null;\n }\n\n /** Declarative play/pause → animator calls. */\n function syncPlayState() {\n if (compMode.value !== CompMode.play) return;\n if (props.play && !props.pause) {\n apiRef.value?.play();\n } else if (props.pause) {\n apiRef.value?.pause();\n } else if (props.play === false) {\n // explicit play=false → jump to the end state\n apiRef.value?.finish();\n } else {\n // pause-only usage: pause switched off → resume\n apiRef.value?.play();\n }\n }\n\n /** Controlled-time mode: seek through the animator API (no recreate). */\n function applySeek() {\n if (compMode.value !== CompMode.fixedTime) return;\n const doc = resolvedDoc.value;\n if (!doc) return;\n const seekMs = calcSeekMs(doc, props);\n if (seekMs !== undefined) {\n apiRef.value?.setCurrentTime(seekMs);\n apiRef.value?.pause();\n }\n }\n\n // Create the animator once DOM refs are available.\n onMounted(() => createApi());\n\n // Recreate the animator when the resolved doc changes.\n // `flush: 'post'` — the animator must be created AFTER the DOM is\n // patched, otherwise the new root element isn't in the document yet\n // and trigger setup fails (autoplay would never resume after a doc swap).\n watch(resolvedDoc, () => createApi(), { flush: 'post' });\n\n // Sync declarative play/pause props with the animator.\n watch([compMode, () => props.play, () => props.pause], () => syncPlayState());\n\n // Scrubbing progress/time only seeks — the animator is NOT recreated.\n watch([compMode, () => props.progress, () => props.time], () => applySeek());\n\n onUnmounted(() => {\n destroyApi();\n });\n\n // -- Expose imperative API ----------------------------------------------\n\n const publicApi: VueAnimatorApi = {\n isPlaying: () => apiRef.value?.isPlaying() || false,\n play: () => apiRef.value?.play(),\n pause: () => apiRef.value?.pause(),\n cancel: () => apiRef.value?.cancel(),\n finish: () => apiRef.value?.finish(),\n setPlaybackRate: (rate: number) => apiRef.value?.setPlaybackRate(rate),\n getCurrentTime: () => apiRef.value?.getCurrentTime() ?? null,\n setCurrentTime: (time: number) => apiRef.value?.setCurrentTime(time),\n };\n\n expose(publicApi);\n\n // -- Render -------------------------------------------------------------\n\n return () => {\n const doc = resolvedDoc.value;\n return doc ? renderNode(doc) : null;\n };\n },\n});\n\nexport default PixodeskSvgAnimator;\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport { OutAction, StartOn } from \"@pixodesk/svg-animator-web\";\nimport { computed, defineComponent, h, onMounted, onUnmounted, ref, useAttrs, type PropType } from 'vue';\n\n\ntype AnimState = 'idle' | 'paused' | 'playing';\n\n\n/**\n * Controls playback of a SVG+CSS animated file by toggling class names on a wrapper div.\n *\n * Intended for use with SVG files exported from the Pixodesk editor using the\n * **CSS Keyframes** flavor (no `<script>` tag). Import the SVG as a Vue component\n * via `vite-svg-loader` and pass it as the default slot:\n *\n * ```vue\n * <script setup>\n * import AnimationSvg from './animation.svg'; // vite-svg-loader\n * </script>\n *\n * <template>\n * <PixodeskSvgCssAnimator startOn=\"mouseOver\" outAction=\"pause\">\n * <AnimationSvg />\n * </PixodeskSvgCssAnimator>\n * </template>\n * ```\n *\n * The wrapper div carries one of three animation states via CSS class names:\n * - *(no class)* — idle, animation not started\n * - `px-anim-enabled` — started but paused\n * - `px-anim-enabled px-anim-playing` — actively playing\n *\n * @prop startOn - What triggers the animation to start:\n * - `'load'` — plays immediately on mount (default)\n * - `'mouseOver'` — plays on hover\n * - `'click'` — plays on click, toggles on second click\n * - `'scrollIntoView'` — plays when the element enters the viewport\n * @prop outAction - What happens when the trigger ends (hover/scroll out, second click):\n * - `'continue'` — keeps playing (default)\n * - `'pause'` — pauses at the current frame\n * - `'reset'` — resets to the beginning\n */\nconst PixodeskSvgCssAnimator = defineComponent({\n name: 'PixodeskSvgCssAnimator',\n\n inheritAttrs: false,\n\n props: {\n startOn: { type: String as PropType<StartOn>, default: 'load' },\n outAction: { type: String as PropType<OutAction>, default: 'continue' },\n },\n\n setup(props, { slots }) {\n const attrs = useAttrs();\n const state = ref<AnimState>(props.startOn === 'load' ? 'playing' : 'idle');\n const divRef = ref<HTMLDivElement | null>(null);\n\n const goOut = () => {\n state.value =\n props.outAction === 'reset' ? 'idle' :\n props.outAction === 'pause' ? 'paused' : 'playing';\n };\n\n let observerCleanup: (() => void) | undefined;\n\n onMounted(() => {\n if (props.startOn !== 'scrollIntoView') return;\n const el = divRef.value;\n if (!el) return;\n const outState: AnimState =\n props.outAction === 'reset' ? 'idle' :\n props.outAction === 'pause' ? 'paused' : 'playing';\n const observer = new IntersectionObserver(\n ([entry]) => { state.value = entry.isIntersecting ? 'playing' : outState; },\n { threshold: 0.1 }\n );\n observer.observe(el);\n observerCleanup = () => observer.disconnect();\n });\n\n onUnmounted(() => observerCleanup?.());\n\n const animClass = computed(() =>\n state.value === 'playing' ? 'px-anim-enabled px-anim-playing' :\n state.value === 'paused' ? 'px-anim-enabled' : ''\n );\n\n const handlers = computed(() =>\n props.startOn === 'mouseOver' ? {\n onMouseenter: () => { state.value = 'playing'; },\n onMouseleave: goOut,\n } :\n props.startOn === 'click' ? {\n onClick: () => state.value === 'playing' ? goOut() : (state.value = 'playing'),\n } : {}\n );\n\n return () => h('div', {\n ref: divRef,\n ...attrs,\n class: [attrs.class, animClass.value],\n ...handlers.value,\n }, slots.default?.());\n },\n});\n\nexport default PixodeskSvgCssAnimator;\n"],"mappings":"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","names":["import_vue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/PixodeskSvgAnimator.ts","../src/PixodeskSvgCssAnimator.ts"],"sourcesContent":["/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport PixodeskSvgAnimator from './PixodeskSvgAnimator';\nexport { PixodeskSvgAnimator };\nexport type { VueAnimatorApi } from './PixodeskSvgAnimator';\n\nimport PixodeskSvgCssAnimator from './PixodeskSvgCssAnimator';\nexport { PixodeskSvgCssAnimator };","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport type { PxAnimatedSvgDocument, PxAnimatorAPI, PxNode, PxPlatformAdapter, PxTimelineEngineExtra, PxTimelinePatch, PxTrigger } from '@pixodesk/svg-animator-web';\nimport type { PxInternalAnimatorOptions } from '@pixodesk/svg-animator-web/internal';\nimport { createAnimator, generateNewIds, getNormalizedProps, PxDiagnosticKind, type PxPlaybackOverrideProps, type PxDiagnostic, type PxDiagnostics } from '@pixodesk/svg-animator-web';\nimport { applyAnimatorConfig, foldTimelineOverride, getAnimatorConfig, PxControlMode, resolveControlMode, controlModeTakesOverTrigger, progressToTimeMs, type PxAnimatorHandle, type PxControlProps } from '@pixodesk/svg-animator-core';\nimport { camelCaseToKebabWordIfNeeded, createDiagnostics, STYLE_ATTR_NAMES, DEFAULT_DURATION_MS } from '@pixodesk/svg-animator-core/internal';\nimport {\n computed, defineComponent, h, onMounted, onUnmounted, ref, shallowRef, type PropType, type VNode,\n watch,\n} from 'vue';\n\n\n// -- Public types -----------------------------------------------------------\n\n/** Vue's own prop names on the vnode — not wire keys. See the React twin. */\nconst VUE_PROP = { ref: 'ref' } as const;\n\n/**\n * The imperative handle the template ref exposes — core's `PxAnimatorHandle` under this\n * package's name (review §9). One definition for React, Vue and React Native.\n * @public\n */\nexport type VueAnimatorApi = PxAnimatorHandle;\n\n\n// -- Internal types ---------------------------------------------------------\n\n// The control mode is core's `PxControlMode`, shared with React and React Native\n// (API review §1/§7) — one precedence rule, one set of conflict warnings.\n\n\n// -- Vue ↔ Animator bridge --------------------------------------------------\n\n/**\n * Creates a platform adapter that routes animator attribute updates\n * to the corresponding Vue-managed DOM element refs.\n */\nfunction createVueAdapter(elementRefs: Map<string, Element>, diag: PxDiagnostics) {\n const warnedSelectors = new Set<string>();\n\n const adapter: PxPlatformAdapter = {\n isConnected: () => true,\n setAttribute: (id, attrName, value) => {\n attrName = camelCaseToKebabWordIfNeeded(attrName);\n\n const element = elementRefs.get(id);\n\n if (!element && !warnedSelectors.has(id)) {\n warnedSelectors.add(id);\n diag.warn(PxDiagnosticKind.host, 'setAttribute: No elements found for id \"' + id + '\"');\n }\n\n if (element) {\n element.setAttribute(attrName, value);\n if (STYLE_ATTR_NAMES.has(attrName)) {\n (element as HTMLElement).style[attrName as any] = value;\n }\n }\n },\n };\n return adapter;\n}\n\n// FIXME: add model validation (e.g. isElementFileJson check)\n\n\n// -- Helper: apply doc overrides --------------------------------------------\n\n/**\n * What `applyDocOverrides` / `calcSeekMs` read off the props — core's shared shapes, not a local\n * copy (review §9). The runtime `props: {…}` block below stays Vue's own, because Vue needs\n * runtime prop declarations; this is only the TypeScript view of the same members.\n */\ntype DocOverrideProps = PxPlaybackOverrideProps & Pick<PxControlProps, 'progress' | 'time'>;\n\nfunction applyDocOverrides(\n doc: PxAnimatedSvgDocument,\n props: DocOverrideProps,\n compMode: PxControlMode,\n diag: PxDiagnostics,\n): PxAnimatedSvgDocument {\n\n // ONE patch, applied ONCE: the props, plus the component's own need to take the trigger\n // over in the non-autoplay control modes.\n //\n // This replaces three hand-rolled spread blocks that wrote the FLAT runtime keys. On a\n // wire-format document — which is what every writer emits — `flattenAnimatorTimeline`\n // overwrote them from `timeline` immediately afterwards, so the overrides were silently\n // discarded. See PLAYBACK-OVERRIDE-PLAN.md §1.1.\n const { timeline, resetTimeline, duration, delay, iterations, startOn } = props;\n const patch = foldTimelineOverride(timeline, { duration, delay, iterations, startOn });\n const fullPatch: any = controlModeTakesOverTrigger(compMode)\n ? {\n ...(patch ?? {}),\n timeline: {\n ...((patch as any)?.timeline ?? {}),\n trigger: { ...((patch as any)?.timeline?.trigger ?? {}), startOn: 'programmatic' },\n },\n }\n : patch;\n\n if (fullPatch !== undefined || resetTimeline) {\n const applied = applyAnimatorConfig(doc, fullPatch ?? {}, { resetDefaults: !!resetTimeline });\n for (const w of applied.warnings) diag.warn(PxDiagnosticKind.usage, 'timeline override: ' + w);\n doc = applied.doc;\n }\n\n return doc;\n}\n\n/**\n * Controlled-time mode: absolute seek target in ms. `progress` is a fraction\n * (0–1) of the WHOLE timeline (duration × iterations — ONE iteration when\n * endless); `time` is absolute. Applied through the animator API\n * (setCurrentTime) so scrubbing does NOT recreate the animator.\n */\nfunction calcSeekMs(doc: PxAnimatedSvgDocument, props: DocOverrideProps): number | undefined {\n let seekMs: number | undefined;\n // The FLAT runtime view, so this works on a wire-format document too — reading\n // `doc.animator.duration` directly finds nothing there.\n const animator = getAnimatorConfig(doc) || {};\n if (props.progress !== undefined) {\n // ONE rule for progress → time (core's `progressToTimeMs`): the same mapping\n // `getCurrentProgress` reads back, so a prop of 0.5 and a read of 0.5 agree.\n const iterationsValue = props.iterations ?? animator.iterations;\n const iterationsCount = iterationsValue === 'infinite' ? Infinity\n : (typeof iterationsValue === 'number' && iterationsValue >= 1 ? iterationsValue : 1);\n const singleDuration = props.duration ?? animator.duration ?? DEFAULT_DURATION_MS;\n seekMs = progressToTimeMs(props.progress, singleDuration, iterationsCount);\n }\n if (props.time !== undefined) seekMs = props.time;\n return seekMs;\n}\n\n\n// -- Main public component --------------------------------------------------\n\n/**\n * Vue component for rendering and controlling Pixodesk SVG animations.\n *\n * Supports four mutually-exclusive control modes:\n *\n * 1. **Autoplay** – uses triggers from the animation document.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" autoplay />\n * ```\n *\n * 2. **Declarative play/pause** – controlled via boolean props.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" play :pause=\"false\" />\n * ```\n *\n * 3. **Imperative** – exposes a ref-based API for full programmatic control.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" ref=\"animator\" />\n * <button @click=\"$refs.animator.play()\">Play</button>\n * ```\n *\n * 4. **Controlled time** – renders a single frame at a given time.\n * ```vue\n * <PixodeskSvgAnimator :doc=\"animation\" :progress=\"0.5\" />\n * <PixodeskSvgAnimator :doc=\"animation\" :time=\"500\" />\n * ```\n * @public\n */\nconst PixodeskSvgAnimator = defineComponent({\n name: 'PixodeskSvgAnimator',\n\n props: {\n // -- Source\n doc: { type: Object as PropType<PxAnimatedSvgDocument>, required: true },\n\n // -- Playback override: the document's `timeline` block as a patch (or a JSON string),\n // plus the four shortcuts people reach for most. The same names as React / RN.\n timeline: { type: [Object, String] as PropType<PxTimelinePatch | string> },\n resetTimeline: { type: Boolean, default: undefined },\n duration: { type: Number },\n delay: { type: Number },\n iterations: { type: [Number, String] as PropType<number | 'infinite'> },\n startOn: { type: String as PropType<'load' | 'mouseOver' | 'click' | 'scrollIntoView' | 'programmatic'> },\n\n // -- Declarative control\n autoplay: { type: Boolean, default: undefined },\n play: { type: Boolean, default: undefined },\n pause: { type: Boolean, default: undefined },\n\n // -- Controlled time\n progress: { type: Number },\n time: { type: Number },\n\n // -- Diagnostics (API review §5).\n // Function PROPS, not emits, on purpose: an emit handler always exists, so wiring\n // these to `emit` would permanently suppress the console fallback for anyone who\n // never listens. As props, \"not given\" really is undefined and the console still\n // speaks by default — the same contract as React and React Native.\n onWarn: { type: Function as PropType<(diagnostic: PxDiagnostic) => void> },\n onError: { type: Function as PropType<(diagnostic: PxDiagnostic) => void> },\n // `muteWarn` / `muteError` switch the console fallback off — for a host that knows\n // about the warnings and tolerates them; a handler you passed still fires.\n muteWarn: { type: Boolean, default: undefined },\n muteError: { type: Boolean, default: undefined },\n },\n\n emits: ['play', 'stop', 'pause', 'cancel', 'finish', 'remove'],\n\n setup(props, { expose, emit }) {\n const elementRefs = new Map<string, Element>();\n const apiRef = shallowRef<PxAnimatorAPI | null>(null);\n\n /**\n * The diagnostics channel, built from the CURRENT props each time (API review §5).\n * Not hoisted into a constant wrapper: `(m, d) => props.onWarn?.(m, d)` would always be\n * a function, so the channel would think a handler exists and the console fallback\n * would never fire for anyone who passed nothing.\n */\n const makeDiag = (): PxDiagnostics => createDiagnostics(\n { onWarn: props.onWarn, onError: props.onError, muteWarn: props.muteWarn, muteError: props.muteError },\n '[PixodeskSvgAnimator]',\n );\n\n // -- Determine control mode ---------------------------------------------\n\n // ONE control-mode rule, decided in core (API review §1/§7). The template ref is not an\n // input: it is exposed in every mode and never changes which one is chosen.\n const resolvedMode = computed(() => resolveControlMode({\n progress: props.progress, time: props.time,\n play: props.play, pause: props.pause, autoplay: props.autoplay,\n }));\n const compMode = computed<PxControlMode>(() => resolvedMode.value.mode);\n\n // Warn where the mode is COMPUTED, not inside `applyDocOverrides` — that runs again on\n // every doc recompute and would repeat the same sentence.\n watch(resolvedMode, r => {\n const diag = makeDiag();\n for (const w of r.warnings) diag.warn(PxDiagnosticKind.usage, w);\n }, { immediate: true });\n\n // -- Prepare the document with overrides --------------------------------\n\n const resolvedDoc = computed(() => {\n let doc = generateNewIds(props.doc);\n return applyDocOverrides(doc, props, compMode.value, makeDiag());\n });\n\n // -- Render the SVG node tree -------------------------------------------\n\n function renderNode(node: PxNode | undefined): VNode | null {\n if (!node) return null;\n\n const { type, animate, meta, children, ...attrs } = node;\n const normProps = getNormalizedProps(attrs);\n\n // Capture a ref to each element with an id.\n if (node.id) {\n const nodeId = node.id;\n normProps[VUE_PROP.ref] = (el: Element | null) => {\n if (el) {\n elementRefs.set(nodeId, el);\n } else {\n elementRefs.delete(nodeId);\n }\n };\n }\n\n const childVNodes = children?.map(child => renderNode(child)).filter(Boolean) as VNode[] | undefined;\n // Text content: a node's own `textContent` renders only when it has no child nodes — a\n // line <tspan> can carry both, and then its children are the styled spans (the React\n // Native renderer's rule). `getNormalizedProps` strips `textContent` from the attributes.\n const text = typeof node.textContent === 'string' ? node.textContent : undefined;\n return h(type, normProps, childVNodes?.length ? childVNodes : text);\n }\n\n // -- Animator lifecycle -------------------------------------------------\n\n function createApi() {\n destroyApi();\n const doc = resolvedDoc.value;\n if (!doc) return;\n\n // Route animator lifecycle events to Vue component events, INLINE under the same\n // names every surface uses (review §9). `stop` fires alongside any event that halts\n // playback — that is the PLAYER's rule, so `onStop` is passed through, not re-derived.\n // `adapter` is the components' extension of the public options (`PxInternalAnimatorOptions`,\n // review §25.14): the frame loop writes to the elements Vue rendered, not to a container.\n const options: PxInternalAnimatorOptions = {\n doc,\n adapter: createVueAdapter(elementRefs, makeDiag()),\n onPlay: () => emit('play'),\n onPause: () => emit('pause'),\n onCancel: () => emit('cancel'),\n onFinish: () => emit('finish'),\n onRemove: () => emit('remove'),\n onStop: () => emit('stop'),\n // The player's own diagnostics reach the same handlers as the component's.\n onWarn: props.onWarn,\n onError: props.onError,\n muteWarn: props.muteWarn,\n muteError: props.muteError,\n };\n apiRef.value = createAnimator(options);\n\n // (Re)apply the declarative control state to the fresh animator —\n // covers both the initial mount (e.g. `:play=\"true\"` from the\n // start) and doc swaps.\n syncPlayState();\n applySeek();\n }\n\n function destroyApi() {\n apiRef.value?.destroy();\n apiRef.value = null;\n }\n\n /** Declarative play/pause → animator calls. */\n function syncPlayState() {\n if (compMode.value !== PxControlMode.play) return;\n if (props.play && !props.pause) {\n apiRef.value?.play();\n } else if (props.pause) {\n apiRef.value?.pause();\n } else if (props.play === false) {\n // explicit play=false → hold where it is (review §8). This used to `finish()`;\n // a boolean whose `false` means \"jump to the end\" is not what anyone guesses.\n apiRef.value?.pause();\n } else {\n // pause-only usage: pause switched off → resume\n apiRef.value?.play();\n }\n }\n\n /** Controlled-time mode: seek through the animator API (no recreate). */\n function applySeek() {\n if (compMode.value !== PxControlMode.fixedTime) return;\n const doc = resolvedDoc.value;\n if (!doc) return;\n const seekMs = calcSeekMs(doc, props);\n if (seekMs !== undefined) {\n apiRef.value?.setCurrentTime(seekMs);\n apiRef.value?.pause();\n }\n }\n\n // Create the animator once DOM refs are available.\n onMounted(() => createApi());\n\n // Recreate the animator when the resolved doc changes.\n // `flush: 'post'` — the animator must be created AFTER the DOM is\n // patched, otherwise the new root element isn't in the document yet\n // and trigger setup fails (autoplay would never resume after a doc swap).\n watch(resolvedDoc, () => createApi(), { flush: 'post' });\n\n // Sync declarative play/pause props with the animator.\n watch([compMode, () => props.play, () => props.pause], () => syncPlayState());\n\n // Scrubbing progress/time only seeks — the animator is NOT recreated.\n watch([compMode, () => props.progress, () => props.time], () => applySeek());\n\n onUnmounted(() => {\n destroyApi();\n });\n\n // -- Expose imperative API ----------------------------------------------\n\n const publicApi: VueAnimatorApi = {\n isPlaying: () => apiRef.value?.isPlaying() || false,\n play: () => apiRef.value?.play(),\n pause: () => apiRef.value?.pause(),\n cancel: () => apiRef.value?.cancel(),\n finish: () => apiRef.value?.finish(),\n setPlaybackRate: (rate: number) => apiRef.value?.setPlaybackRate(rate),\n getCurrentTime: () => apiRef.value?.getCurrentTime() ?? null,\n setCurrentTime: (time: number) => apiRef.value?.setCurrentTime(time),\n getCurrentProgress: () => apiRef.value?.getCurrentProgress() ?? null,\n setCurrentProgress: (progress: number) => apiRef.value?.setCurrentProgress(progress),\n };\n\n expose(publicApi);\n\n // -- Render -------------------------------------------------------------\n\n return () => {\n const doc = resolvedDoc.value;\n return doc ? renderNode(doc) : null;\n };\n },\n});\n\nexport default PixodeskSvgAnimator;\n","/*---------------------------------------------------------------------------------------\n * Copyright (c) Pixodesk LTD.\n * Licensed under the MIT License. See the LICENSE file in the project root for details.\n *---------------------------------------------------------------------------------------*/\n\nimport { PX_TRIGGER_DEFAULTS, PxOutAction, PxStartOn } from '@pixodesk/svg-animator-core';\nimport { computed, defineComponent, h, onMounted, onUnmounted, ref, useAttrs, type PropType } from 'vue';\n\n\ntype AnimState = 'idle' | 'paused' | 'playing';\n\n\n/**\n * Controls playback of a SVG+CSS animated file by toggling class names on a wrapper div.\n *\n * Intended for use with SVG files exported from the Pixodesk editor using the\n * **CSS Keyframes** flavor (no `<script>` tag). Import the SVG as a Vue component\n * via `vite-svg-loader` and pass it as the default slot:\n *\n * ```vue\n * <script setup>\n * import AnimationSvg from './animation.svg'; // vite-svg-loader\n * </script>\n *\n * <template>\n * <PixodeskSvgCssAnimator startOn=\"mouseOver\" outAction=\"pause\">\n * <AnimationSvg />\n * </PixodeskSvgCssAnimator>\n * </template>\n * ```\n *\n * The wrapper div carries one of three animation states via CSS class names:\n * - *(no class)* — idle, animation not started\n * - `px-anim-enabled` — started but paused\n * - `px-anim-enabled px-anim-playing` — actively playing\n *\n * @prop startOn - What triggers the animation to start:\n * - `'load'` — plays immediately on mount (default)\n * - `'mouseOver'` — plays on hover\n * - `'click'` — plays on click, toggles on second click\n * - `'scrollIntoView'` — plays when the element enters the viewport\n * - `'programmatic'` — **not supported here.** This wrapper exposes no `play()`, so there is\n * nothing to wait for and the animation never starts. The prop keeps the\n * shared `PxStartOn` type (one enum per wire key), so the value type-checks\n * — it simply has no effect. Use `PixodeskSvgAnimator` (the JSON player)\n * when you need to start an animation from code.\n * @prop outAction - What happens when the trigger ends (hover/scroll out, second click):\n * - `'continue'` — keeps playing (default)\n * - `'pause'` — pauses at the current frame\n * - `'reset'` — resets to the beginning\n * - `'reverse'` — **acts as `'continue'` here.** A CSS class toggle cannot run keyframes\n * backwards. Accepted so the prop keeps the shared `PxOutAction` type.\n * @prop scrollIntoViewThreshold - For `'scrollIntoView'`: how much of the element must be\n * visible (0–1) before it starts, and below which the out action applies. Defaults to the\n * wire default (`0`, any pixel) — the same as the JSON player, not a private `0.1`.\n * @public\n */\nconst PixodeskSvgCssAnimator = defineComponent({\n name: 'PixodeskSvgCssAnimator',\n\n inheritAttrs: false,\n\n props: {\n startOn: { type: String as PropType<PxStartOn>, default: 'load' },\n outAction: { type: String as PropType<PxOutAction>, default: 'continue' },\n scrollIntoViewThreshold: { type: Number, default: PX_TRIGGER_DEFAULTS.scrollIntoViewThreshold },\n },\n\n setup(props, { slots }) {\n const attrs = useAttrs();\n const state = ref<AnimState>(props.startOn === 'load' ? 'playing' : 'idle');\n const divRef = ref<HTMLDivElement | null>(null);\n\n const goOut = () => {\n state.value =\n props.outAction === 'reset' ? 'idle' :\n props.outAction === 'pause' ? 'paused' : 'playing';\n };\n\n let observerCleanup: (() => void) | undefined;\n\n onMounted(() => {\n if (props.startOn !== 'scrollIntoView') return;\n const el = divRef.value;\n if (!el) return;\n const outState: AnimState =\n props.outAction === 'reset' ? 'idle' :\n props.outAction === 'pause' ? 'paused' : 'playing';\n // `isIntersecting` is true at ONE visible pixel, so with a threshold above 0 it could\n // never report \"out\" — read the ratio against the threshold instead (review §13).\n const threshold = props.scrollIntoViewThreshold;\n const visible = (entry: IntersectionObserverEntry): boolean =>\n threshold > 0 ? entry.intersectionRatio >= threshold : entry.isIntersecting;\n const observer = new IntersectionObserver(\n ([entry]) => { state.value = visible(entry) ? 'playing' : outState; },\n { threshold }\n );\n observer.observe(el);\n observerCleanup = () => observer.disconnect();\n });\n\n onUnmounted(() => observerCleanup?.());\n\n const animClass = computed(() =>\n state.value === 'playing' ? 'px-anim-enabled px-anim-playing' :\n state.value === 'paused' ? 'px-anim-enabled' : ''\n );\n\n const handlers = computed(() =>\n props.startOn === 'mouseOver' ? {\n onMouseenter: () => { state.value = 'playing'; },\n onMouseleave: goOut,\n } :\n props.startOn === 'click' ? {\n onClick: () => state.value === 'playing' ? goOut() : (state.value = 'playing'),\n } : {}\n );\n\n return () => h('div', {\n ref: divRef,\n ...attrs,\n class: [attrs.class, animClass.value],\n ...handlers.value,\n }, slots.default?.());\n },\n});\n\nexport default PixodeskSvgCssAnimator;\n"],"mappings":"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","names":["import_svg_animator_core","import_vue"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { PropType, VNode } from 'vue';
|
|
3
|
-
import { PxAnimatedSvgDocument,
|
|
3
|
+
import { PxAnimatedSvgDocument, PxTimelinePatch, PxDiagnostic } from '@pixodesk/svg-animator-web';
|
|
4
|
+
import { PxAnimatorHandle, PxStartOn, PxOutAction } from '@pixodesk/svg-animator-core';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
pause(): void;
|
|
12
|
-
/** Stops the animation and resets it to its initial state. */
|
|
13
|
-
cancel(): void;
|
|
14
|
-
/** Jumps to the end of the animation and holds the final state. */
|
|
15
|
-
finish(): void;
|
|
16
|
-
/** Changes the speed of the animation. 1 is normal, 2 is double, -1 is reverse. */
|
|
17
|
-
setPlaybackRate(rate: number): void;
|
|
18
|
-
/** Returns the current playback time in milliseconds. */
|
|
19
|
-
getCurrentTime(): number | null;
|
|
20
|
-
/** Jumps to a specific time (in milliseconds) in the animation. */
|
|
21
|
-
setCurrentTime(time: number): void;
|
|
22
|
-
}
|
|
6
|
+
/**
|
|
7
|
+
* The imperative handle the template ref exposes — core's `PxAnimatorHandle` under this
|
|
8
|
+
* package's name (review §9). One definition for React, Vue and React Native.
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
type VueAnimatorApi = PxAnimatorHandle;
|
|
23
12
|
/**
|
|
24
13
|
* Vue component for rendering and controlling Pixodesk SVG animations.
|
|
25
14
|
*
|
|
@@ -46,16 +35,17 @@ interface VueAnimatorApi {
|
|
|
46
35
|
* <PixodeskSvgAnimator :doc="animation" :progress="0.5" />
|
|
47
36
|
* <PixodeskSvgAnimator :doc="animation" :time="500" />
|
|
48
37
|
* ```
|
|
38
|
+
* @public
|
|
49
39
|
*/
|
|
50
40
|
declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
51
41
|
doc: {
|
|
52
42
|
type: PropType<PxAnimatedSvgDocument>;
|
|
53
43
|
required: true;
|
|
54
44
|
};
|
|
55
|
-
|
|
56
|
-
type: PropType<
|
|
45
|
+
timeline: {
|
|
46
|
+
type: PropType<PxTimelinePatch | string>;
|
|
57
47
|
};
|
|
58
|
-
|
|
48
|
+
resetTimeline: {
|
|
59
49
|
type: BooleanConstructor;
|
|
60
50
|
default: undefined;
|
|
61
51
|
};
|
|
@@ -89,17 +79,31 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
89
79
|
time: {
|
|
90
80
|
type: NumberConstructor;
|
|
91
81
|
};
|
|
82
|
+
onWarn: {
|
|
83
|
+
type: PropType<(diagnostic: PxDiagnostic) => void>;
|
|
84
|
+
};
|
|
85
|
+
onError: {
|
|
86
|
+
type: PropType<(diagnostic: PxDiagnostic) => void>;
|
|
87
|
+
};
|
|
88
|
+
muteWarn: {
|
|
89
|
+
type: BooleanConstructor;
|
|
90
|
+
default: undefined;
|
|
91
|
+
};
|
|
92
|
+
muteError: {
|
|
93
|
+
type: BooleanConstructor;
|
|
94
|
+
default: undefined;
|
|
95
|
+
};
|
|
92
96
|
}>, () => VNode<vue.RendererNode, vue.RendererElement, {
|
|
93
97
|
[key: string]: any;
|
|
94
|
-
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("
|
|
98
|
+
}> | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("finish" | "play" | "pause" | "cancel" | "stop" | "remove")[], "finish" | "play" | "pause" | "cancel" | "stop" | "remove", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
95
99
|
doc: {
|
|
96
100
|
type: PropType<PxAnimatedSvgDocument>;
|
|
97
101
|
required: true;
|
|
98
102
|
};
|
|
99
|
-
|
|
100
|
-
type: PropType<
|
|
103
|
+
timeline: {
|
|
104
|
+
type: PropType<PxTimelinePatch | string>;
|
|
101
105
|
};
|
|
102
|
-
|
|
106
|
+
resetTimeline: {
|
|
103
107
|
type: BooleanConstructor;
|
|
104
108
|
default: undefined;
|
|
105
109
|
};
|
|
@@ -133,18 +137,34 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
133
137
|
time: {
|
|
134
138
|
type: NumberConstructor;
|
|
135
139
|
};
|
|
140
|
+
onWarn: {
|
|
141
|
+
type: PropType<(diagnostic: PxDiagnostic) => void>;
|
|
142
|
+
};
|
|
143
|
+
onError: {
|
|
144
|
+
type: PropType<(diagnostic: PxDiagnostic) => void>;
|
|
145
|
+
};
|
|
146
|
+
muteWarn: {
|
|
147
|
+
type: BooleanConstructor;
|
|
148
|
+
default: undefined;
|
|
149
|
+
};
|
|
150
|
+
muteError: {
|
|
151
|
+
type: BooleanConstructor;
|
|
152
|
+
default: undefined;
|
|
153
|
+
};
|
|
136
154
|
}>> & Readonly<{
|
|
155
|
+
onFinish?: ((...args: any[]) => any) | undefined;
|
|
137
156
|
onPlay?: ((...args: any[]) => any) | undefined;
|
|
138
|
-
onStop?: ((...args: any[]) => any) | undefined;
|
|
139
157
|
onPause?: ((...args: any[]) => any) | undefined;
|
|
140
158
|
onCancel?: ((...args: any[]) => any) | undefined;
|
|
141
|
-
|
|
159
|
+
onStop?: ((...args: any[]) => any) | undefined;
|
|
142
160
|
onRemove?: ((...args: any[]) => any) | undefined;
|
|
143
161
|
}>, {
|
|
144
|
-
autoplay: boolean;
|
|
145
162
|
play: boolean;
|
|
146
|
-
resetDocDefaults: boolean;
|
|
147
163
|
pause: boolean;
|
|
164
|
+
autoplay: boolean;
|
|
165
|
+
resetTimeline: boolean;
|
|
166
|
+
muteWarn: boolean;
|
|
167
|
+
muteError: boolean;
|
|
148
168
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
149
169
|
|
|
150
170
|
/**
|
|
@@ -176,34 +196,54 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
176
196
|
* - `'mouseOver'` — plays on hover
|
|
177
197
|
* - `'click'` — plays on click, toggles on second click
|
|
178
198
|
* - `'scrollIntoView'` — plays when the element enters the viewport
|
|
199
|
+
* - `'programmatic'` — **not supported here.** This wrapper exposes no `play()`, so there is
|
|
200
|
+
* nothing to wait for and the animation never starts. The prop keeps the
|
|
201
|
+
* shared `PxStartOn` type (one enum per wire key), so the value type-checks
|
|
202
|
+
* — it simply has no effect. Use `PixodeskSvgAnimator` (the JSON player)
|
|
203
|
+
* when you need to start an animation from code.
|
|
179
204
|
* @prop outAction - What happens when the trigger ends (hover/scroll out, second click):
|
|
180
205
|
* - `'continue'` — keeps playing (default)
|
|
181
206
|
* - `'pause'` — pauses at the current frame
|
|
182
207
|
* - `'reset'` — resets to the beginning
|
|
208
|
+
* - `'reverse'` — **acts as `'continue'` here.** A CSS class toggle cannot run keyframes
|
|
209
|
+
* backwards. Accepted so the prop keeps the shared `PxOutAction` type.
|
|
210
|
+
* @prop scrollIntoViewThreshold - For `'scrollIntoView'`: how much of the element must be
|
|
211
|
+
* visible (0–1) before it starts, and below which the out action applies. Defaults to the
|
|
212
|
+
* wire default (`0`, any pixel) — the same as the JSON player, not a private `0.1`.
|
|
213
|
+
* @public
|
|
183
214
|
*/
|
|
184
215
|
declare const PixodeskSvgCssAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
185
216
|
startOn: {
|
|
186
|
-
type: PropType<
|
|
217
|
+
type: PropType<PxStartOn>;
|
|
187
218
|
default: string;
|
|
188
219
|
};
|
|
189
220
|
outAction: {
|
|
190
|
-
type: PropType<
|
|
221
|
+
type: PropType<PxOutAction>;
|
|
191
222
|
default: string;
|
|
192
223
|
};
|
|
224
|
+
scrollIntoViewThreshold: {
|
|
225
|
+
type: NumberConstructor;
|
|
226
|
+
default: 0;
|
|
227
|
+
};
|
|
193
228
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
194
229
|
[key: string]: any;
|
|
195
230
|
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
196
231
|
startOn: {
|
|
197
|
-
type: PropType<
|
|
232
|
+
type: PropType<PxStartOn>;
|
|
198
233
|
default: string;
|
|
199
234
|
};
|
|
200
235
|
outAction: {
|
|
201
|
-
type: PropType<
|
|
236
|
+
type: PropType<PxOutAction>;
|
|
202
237
|
default: string;
|
|
203
238
|
};
|
|
239
|
+
scrollIntoViewThreshold: {
|
|
240
|
+
type: NumberConstructor;
|
|
241
|
+
default: 0;
|
|
242
|
+
};
|
|
204
243
|
}>> & Readonly<{}>, {
|
|
205
|
-
startOn:
|
|
206
|
-
outAction:
|
|
244
|
+
startOn: PxStartOn;
|
|
245
|
+
outAction: PxOutAction;
|
|
246
|
+
scrollIntoViewThreshold: number;
|
|
207
247
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
208
248
|
|
|
209
249
|
export { PixodeskSvgAnimator, PixodeskSvgCssAnimator, type VueAnimatorApi };
|