@pixodesk/svg-animator-vue 1.0.41 → 1.0.44
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 +1 -1
- package/dist/index.cjs +70 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +73 -47
- package/dist/index.d.ts +73 -47
- package/dist/index.js +73 -47
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +584 -311
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -94,7 +94,7 @@ Render a single frame — by time in milliseconds, or by fraction of the whole t
|
|
|
94
94
|
| `duration` | `number` | Shortcut for `timeline.duration` (ms) |
|
|
95
95
|
| `delay` | `number` | Shortcut for `timeline.delay` (ms) |
|
|
96
96
|
| `iterations` | `number \| 'infinite'` | Shortcut for `timeline.iterations` |
|
|
97
|
-
| `
|
|
97
|
+
| `start` | `'load' \| 'mouseOver' \| 'click' \| 'none'` | Shortcut for `timeline.trigger.start` |
|
|
98
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
99
|
| `onError` | `(diagnostic) => void` | this instance will not play — failed to load, parse or build, or the render threw; without it → `console.error` |
|
|
100
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 |
|
package/dist/index.cjs
CHANGED
|
@@ -31,7 +31,13 @@ var import_svg_animator_web = require("@pixodesk/svg-animator-web");
|
|
|
31
31
|
var import_svg_animator_core = require("@pixodesk/svg-animator-core");
|
|
32
32
|
var import_internal = require("@pixodesk/svg-animator-core/internal");
|
|
33
33
|
var import_vue = require("vue");
|
|
34
|
-
var VUE_PROP = { ref: "ref" };
|
|
34
|
+
var VUE_PROP = { ref: "ref", style: "style" };
|
|
35
|
+
function toInlineStyle(style) {
|
|
36
|
+
if (!style) return void 0;
|
|
37
|
+
const inline = {};
|
|
38
|
+
for (const [prop, value] of Object.entries(style)) inline[prop] = String(value);
|
|
39
|
+
return inline;
|
|
40
|
+
}
|
|
35
41
|
function createVueAdapter(elementRefs, diag) {
|
|
36
42
|
const warnedSelectors = /* @__PURE__ */ new Set();
|
|
37
43
|
const adapter = {
|
|
@@ -41,7 +47,7 @@ function createVueAdapter(elementRefs, diag) {
|
|
|
41
47
|
const element = elementRefs.get(id);
|
|
42
48
|
if (!element && !warnedSelectors.has(id)) {
|
|
43
49
|
warnedSelectors.add(id);
|
|
44
|
-
diag.warn(import_svg_animator_web.PxDiagnosticKind.host,
|
|
50
|
+
diag.warn(import_svg_animator_web.PxDiagnosticKind.host, import_svg_animator_core.PxDiagnosticCode.setAttributeNoElement, id);
|
|
45
51
|
}
|
|
46
52
|
if (element) {
|
|
47
53
|
element.setAttribute(attrName, value);
|
|
@@ -54,18 +60,18 @@ function createVueAdapter(elementRefs, diag) {
|
|
|
54
60
|
return adapter;
|
|
55
61
|
}
|
|
56
62
|
function applyDocOverrides(doc, props, compMode, diag) {
|
|
57
|
-
const { timeline, resetTimeline, duration, delay, iterations,
|
|
58
|
-
const patch = (0, import_svg_animator_core.foldTimelineOverride)(timeline, { duration, delay, iterations,
|
|
63
|
+
const { timeline, resetTimeline, duration, delay, iterations, start } = props;
|
|
64
|
+
const patch = (0, import_svg_animator_core.foldTimelineOverride)(timeline, { duration, delay, iterations, start });
|
|
59
65
|
const fullPatch = (0, import_svg_animator_core.controlModeTakesOverTrigger)(compMode) ? {
|
|
60
66
|
...patch ?? {},
|
|
61
67
|
timeline: {
|
|
62
68
|
...patch?.timeline ?? {},
|
|
63
|
-
trigger: { ...patch?.timeline?.trigger ?? {},
|
|
69
|
+
trigger: { ...patch?.timeline?.trigger ?? {}, start: "none" }
|
|
64
70
|
}
|
|
65
71
|
} : patch;
|
|
66
72
|
if (fullPatch !== void 0 || resetTimeline) {
|
|
67
73
|
const applied = (0, import_svg_animator_core.applyAnimatorConfig)(doc, fullPatch ?? {}, { resetTimeline: !!resetTimeline });
|
|
68
|
-
for (const w of applied.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage,
|
|
74
|
+
for (const w of applied.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage, import_svg_animator_core.PxDiagnosticCode.timelineOverrideIgnored, w);
|
|
69
75
|
doc = applied.doc;
|
|
70
76
|
}
|
|
71
77
|
return doc;
|
|
@@ -94,7 +100,7 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
94
100
|
duration: { type: Number },
|
|
95
101
|
delay: { type: Number },
|
|
96
102
|
iterations: { type: [Number, String] },
|
|
97
|
-
|
|
103
|
+
start: { type: String },
|
|
98
104
|
// -- Declarative control
|
|
99
105
|
autoplay: { type: Boolean, default: void 0 },
|
|
100
106
|
play: { type: Boolean, default: void 0 },
|
|
@@ -132,7 +138,7 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
132
138
|
const compMode = (0, import_vue.computed)(() => resolvedMode.value.mode);
|
|
133
139
|
(0, import_vue.watch)(resolvedMode, (r) => {
|
|
134
140
|
const diag = makeDiag();
|
|
135
|
-
for (const w of r.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage, w);
|
|
141
|
+
for (const w of r.warnings) diag.warn(import_svg_animator_web.PxDiagnosticKind.usage, import_svg_animator_core.PxDiagnosticCode.controlPropsConflict, w);
|
|
136
142
|
}, { immediate: true });
|
|
137
143
|
const resolvedDoc = (0, import_vue.computed)(() => {
|
|
138
144
|
let doc = (0, import_svg_animator_web.generateNewIds)(props.doc);
|
|
@@ -140,8 +146,10 @@ var PixodeskSvgAnimator = (0, import_vue.defineComponent)({
|
|
|
140
146
|
});
|
|
141
147
|
function renderNode(node) {
|
|
142
148
|
if (!node) return null;
|
|
143
|
-
const { type, animate, meta, children, ...attrs } = node;
|
|
149
|
+
const { type, animate, meta, children, style, ...attrs } = node;
|
|
144
150
|
const normProps = (0, import_svg_animator_web.toDomProps)(attrs);
|
|
151
|
+
const inlineStyle = toInlineStyle(style);
|
|
152
|
+
if (inlineStyle) normProps[VUE_PROP.style] = inlineStyle;
|
|
145
153
|
if (node.id) {
|
|
146
154
|
const nodeId = node.id;
|
|
147
155
|
normProps[VUE_PROP.ref] = (el) => {
|
|
@@ -235,57 +243,75 @@ var PixodeskSvgAnimator_default = PixodeskSvgAnimator;
|
|
|
235
243
|
|
|
236
244
|
// src/PixodeskSvgCssAnimator.ts
|
|
237
245
|
var import_svg_animator_core2 = require("@pixodesk/svg-animator-core");
|
|
246
|
+
var import_internal2 = require("@pixodesk/svg-animator-web/internal");
|
|
238
247
|
var import_vue2 = require("vue");
|
|
239
248
|
var PixodeskSvgCssAnimator = (0, import_vue2.defineComponent)({
|
|
240
249
|
name: "PixodeskSvgCssAnimator",
|
|
250
|
+
// The wrapper spreads `attrs` itself and merges `class` by hand, so Vue must not ALSO
|
|
251
|
+
// apply them — otherwise a host class lands on the div twice.
|
|
241
252
|
inheritAttrs: false,
|
|
242
253
|
props: {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
254
|
+
start: { type: String, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.start },
|
|
255
|
+
offScreen: { type: String, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.offScreen },
|
|
256
|
+
mouseOut: { type: String, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.mouseOut },
|
|
257
|
+
visibilityThreshold: { type: Number, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.visibilityThreshold },
|
|
258
|
+
visibilityDebounce: { type: Number, default: import_svg_animator_core2.PX_TRIGGER_DEFAULTS.visibilityDebounce }
|
|
246
259
|
},
|
|
247
|
-
setup(props, { slots }) {
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
260
|
+
setup(props, { slots, attrs }) {
|
|
261
|
+
const state = (0, import_vue2.ref)("idle");
|
|
262
|
+
const el = (0, import_vue2.ref)(null);
|
|
263
|
+
let gate = null;
|
|
251
264
|
const goOut = () => {
|
|
252
|
-
state.value = props.
|
|
265
|
+
state.value = props.mouseOut === import_svg_animator_core2.PxMouseOutAction.reset ? "idle" : props.mouseOut === import_svg_animator_core2.PxMouseOutAction.pause ? "paused" : "playing";
|
|
253
266
|
};
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
if (!
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
267
|
+
const attach = () => {
|
|
268
|
+
gate?.dispose();
|
|
269
|
+
gate = null;
|
|
270
|
+
const node = el.value;
|
|
271
|
+
if (!node) return;
|
|
272
|
+
gate = (0, import_internal2.createVisibilityGate)(node, {
|
|
273
|
+
start: props.start,
|
|
274
|
+
offScreen: props.offScreen,
|
|
275
|
+
mouseOut: props.mouseOut,
|
|
276
|
+
visibilityThreshold: props.visibilityThreshold,
|
|
277
|
+
visibilityDebounce: props.visibilityDebounce
|
|
278
|
+
}, {
|
|
279
|
+
isPlaying: () => state.value === "playing",
|
|
280
|
+
play: () => {
|
|
281
|
+
state.value = "playing";
|
|
265
282
|
},
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
283
|
+
pause: () => {
|
|
284
|
+
state.value = "paused";
|
|
285
|
+
},
|
|
286
|
+
cancel: () => {
|
|
287
|
+
state.value = "idle";
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
if (props.start === import_svg_animator_core2.PxTriggerStart.load) gate.requestStart(false);
|
|
291
|
+
};
|
|
292
|
+
(0, import_vue2.onMounted)(attach);
|
|
293
|
+
(0, import_vue2.watch)(() => [props.start, props.offScreen, props.mouseOut, props.visibilityThreshold, props.visibilityDebounce], attach);
|
|
294
|
+
(0, import_vue2.onBeforeUnmount)(() => {
|
|
295
|
+
gate?.dispose();
|
|
296
|
+
gate = null;
|
|
270
297
|
});
|
|
271
|
-
|
|
272
|
-
|
|
298
|
+
const requestStart = () => {
|
|
299
|
+
if (gate) gate.requestStart(true);
|
|
300
|
+
else state.value = "playing";
|
|
301
|
+
};
|
|
302
|
+
const cssClass = (0, import_vue2.computed)(
|
|
273
303
|
() => state.value === "playing" ? "px-anim-enabled px-anim-playing" : state.value === "paused" ? "px-anim-enabled" : ""
|
|
274
304
|
);
|
|
275
305
|
const handlers = (0, import_vue2.computed)(
|
|
276
|
-
() => props.
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
onMouseleave: goOut
|
|
281
|
-
} : props.startOn === "click" ? {
|
|
282
|
-
onClick: () => state.value === "playing" ? goOut() : state.value = "playing"
|
|
283
|
-
} : {}
|
|
306
|
+
() => props.start === import_svg_animator_core2.PxTriggerStart.mouseOver ? { onMouseenter: requestStart, onMouseleave: goOut } : props.start === import_svg_animator_core2.PxTriggerStart.click ? { onClick: () => {
|
|
307
|
+
if (state.value === "playing") state.value = "paused";
|
|
308
|
+
else requestStart();
|
|
309
|
+
} } : {}
|
|
284
310
|
);
|
|
285
311
|
return () => (0, import_vue2.h)("div", {
|
|
286
|
-
ref:
|
|
312
|
+
ref: el,
|
|
287
313
|
...attrs,
|
|
288
|
-
class: [attrs.class,
|
|
314
|
+
class: [attrs.class, cssClass.value],
|
|
289
315
|
...handlers.value
|
|
290
316
|
}, slots.default?.());
|
|
291
317
|
}
|
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, PxNode, PxPlatformAdapter, PxTimelineEngineSetting, PxTimelinePatch, PxTrigger } from '@pixodesk/svg-animator-web';\nimport type { PxInternalAnimatorOptions } from '@pixodesk/svg-animator-web/internal';\nimport { createAnimator, generateNewIds, toDomProps, PxDiagnosticKind, type PxPlaybackOverride, 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, PX_STYLE_ATTR_NAMES, PX_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 (PX_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 = PxPlaybackOverride & 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 dev-docs/plans/playback-override.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 ?? {}, { resetTimeline: !!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 ?? PX_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 = toDomProps(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). `toDomProps` 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"]}
|
|
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, PxTimelineEngineSetting, PxTimelinePatch, PxTrigger } from '@pixodesk/svg-animator-web';\nimport type { PxInternalAnimatorOptions } from '@pixodesk/svg-animator-web/internal';\nimport { createAnimator, generateNewIds, toDomProps, PxDiagnosticKind, type PxPlaybackOverride, type PxDiagnostic, type PxDiagnostics } from '@pixodesk/svg-animator-web';\nimport { applyAnimatorConfig, foldTimelineOverride, getAnimatorConfig, PxDiagnosticCode, PxControlMode, resolveControlMode, controlModeTakesOverTrigger, progressToTimeMs, type PxAnimatorHandle, type PxControlProps } from '@pixodesk/svg-animator-core';\nimport { camelCaseToKebabWordIfNeeded, createDiagnostics, PX_STYLE_ATTR_NAMES, PX_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', style: 'style' } as const;\n\n/** `node.style` (camelCase declarations) as an element style object — values stringified, exactly\n * as the web player writes them (`element.style[prop] = String(value)`). */\nfunction toInlineStyle(style: PxNode['style']): Record<string, string> | undefined {\n if (!style) return undefined;\n const inline: Record<string, string> = {};\n for (const [prop, value] of Object.entries(style)) inline[prop] = String(value);\n return inline;\n}\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, PxDiagnosticCode.setAttributeNoElement, id);\n }\n\n if (element) {\n element.setAttribute(attrName, value);\n if (PX_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 = PxPlaybackOverride & 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 dev-docs/plans/playback-override.md §1.1.\n const { timeline, resetTimeline, duration, delay, iterations, start } = props;\n const patch = foldTimelineOverride(timeline, { duration, delay, iterations, start });\n const fullPatch: any = controlModeTakesOverTrigger(compMode)\n ? {\n ...(patch ?? {}),\n timeline: {\n ...((patch as any)?.timeline ?? {}),\n trigger: { ...((patch as any)?.timeline?.trigger ?? {}), start: 'none' },\n },\n }\n : patch;\n\n if (fullPatch !== undefined || resetTimeline) {\n const applied = applyAnimatorConfig(doc, fullPatch ?? {}, { resetTimeline: !!resetTimeline });\n for (const w of applied.warnings) diag.warn(PxDiagnosticKind.usage, PxDiagnosticCode.timelineOverrideIgnored, 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 ?? PX_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 start: { type: String as PropType<'load' | 'mouseOver' | 'click' | 'none'> },\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, PxDiagnosticCode.controlPropsConflict, 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, style, ...attrs } = node;\n const normProps = toDomProps(attrs);\n\n // `node.style` is not an attribute (`toDomProps` drops it) — it is the element's style.\n const inlineStyle = toInlineStyle(style);\n if (inlineStyle) normProps[VUE_PROP.style] = inlineStyle;\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). `toDomProps` 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, PxMouseOutAction, PxOffScreenAction, PxTriggerStart } from '@pixodesk/svg-animator-core';\nimport { createVisibilityGate, type PxVisibilityGate } from '@pixodesk/svg-animator-web/internal';\nimport { computed, defineComponent, h, onBeforeUnmount, onMounted, ref, watch, type PropType } from 'vue';\n\n\ntype AnimState = 'idle' | 'paused' | 'playing';\n\n/**\n * Controls playback of SVG+CSS animated files 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** (no `<script>` tag). Import the SVG as a Vue component\n * (`vite-svg-loader`) and pass it in the default slot:\n *\n * ```vue\n * <script setup>\n * import AnimationSvg from './animation.svg?component';\n * </script>\n *\n * <template>\n * <PixodeskSvgCssAnimator start=\"mouseOver\" mouseOut=\"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 * TWO AXES, the same two the JSON player has: `start` says what STARTS it, `offScreen` says\n * whether it may RUN. The gate itself is the player's (`createVisibilityGate`), so the threshold,\n * the dwell, the hysteresis and the hidden-tab rule cannot drift between the two.\n *\n * @prop start - What starts the animation:\n * - `'load'` — plays as soon as it is visible enough (default)\n * - `'mouseOver'` — plays on hover\n * - `'click'` — plays on click, toggles on second click\n * - `'none'` — **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 `PxTriggerStart` type (one enum per wire key), so the value\n * type-checks — it simply has no effect. Use `PixodeskSvgAnimator` (the JSON\n * player) when you need to start an animation from code.\n * @prop offScreen - What happens while none of it is on screen:\n * - `'pause'` — pauses at the current frame (default); resumes when it comes back\n * - `'continue'` — keeps playing, and starts without waiting to be seen\n * - `'reset'` — back to the beginning, so it replays on the next entry\n * @prop mouseOut - What happens when the pointer leaves, for `start: 'mouseOver'`:\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 `PxMouseOutAction` type.\n * @prop visibilityThreshold - How much of the element must be on screen (0–1) before it may run.\n * Defaults to the wire default (`0.5`), the same as the JSON player.\n * @prop visibilityDebounce - How long that must hold, in ms, before it starts. Defaults to the\n * wire default (`150`).\n * @public\n */\nconst PixodeskSvgCssAnimator = defineComponent({\n name: 'PixodeskSvgCssAnimator',\n // The wrapper spreads `attrs` itself and merges `class` by hand, so Vue must not ALSO\n // apply them — otherwise a host class lands on the div twice.\n inheritAttrs: false,\n props: {\n start: { type: String as PropType<PxTriggerStart>, default: PX_TRIGGER_DEFAULTS.start },\n offScreen: { type: String as PropType<PxOffScreenAction>, default: PX_TRIGGER_DEFAULTS.offScreen },\n mouseOut: { type: String as PropType<PxMouseOutAction>, default: PX_TRIGGER_DEFAULTS.mouseOut },\n visibilityThreshold: { type: Number, default: PX_TRIGGER_DEFAULTS.visibilityThreshold },\n visibilityDebounce: { type: Number, default: PX_TRIGGER_DEFAULTS.visibilityDebounce },\n },\n setup(props, { slots, attrs }) {\n const state = ref<AnimState>('idle');\n const el = ref<HTMLDivElement | null>(null);\n let gate: PxVisibilityGate | null = null;\n\n const goOut = (): void => {\n state.value =\n props.mouseOut === PxMouseOutAction.reset ? 'idle' :\n props.mouseOut === PxMouseOutAction.pause ? 'paused' : 'playing';\n };\n\n const attach = (): void => {\n gate?.dispose();\n gate = null;\n const node = el.value;\n if (!node) return;\n gate = createVisibilityGate(node, {\n start: props.start,\n offScreen: props.offScreen,\n mouseOut: props.mouseOut,\n visibilityThreshold: props.visibilityThreshold,\n visibilityDebounce: props.visibilityDebounce,\n }, {\n isPlaying: () => state.value === 'playing',\n play: () => { state.value = 'playing'; },\n pause: () => { state.value = 'paused'; },\n cancel: () => { state.value = 'idle'; },\n });\n // Only `load` is held by the gate; a hover or a click is aimed at something seen.\n if (props.start === PxTriggerStart.load) gate.requestStart(false);\n };\n\n onMounted(attach);\n watch(() => [props.start, props.offScreen, props.mouseOut, props.visibilityThreshold, props.visibilityDebounce], attach);\n onBeforeUnmount(() => { gate?.dispose(); gate = null; });\n\n const requestStart = (): void => {\n if (gate) gate.requestStart(true);\n else state.value = 'playing';\n };\n\n const cssClass = 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.start === PxTriggerStart.mouseOver\n ? { onMouseenter: requestStart, onMouseleave: goOut }\n : props.start === PxTriggerStart.click\n ? { onClick: () => { if (state.value === 'playing') state.value = 'paused'; else requestStart(); } }\n : {}\n );\n\n return () => h('div', {\n ref: el,\n ...attrs,\n class: [attrs.class, cssClass.value],\n ...handlers.value,\n }, slots.default?.());\n },\n});\nexport default PixodeskSvgCssAnimator;\n"],"mappings":"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","names":["import_svg_animator_core","import_internal","import_vue"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as vue from 'vue';
|
|
2
2
|
import { PropType, VNode } from 'vue';
|
|
3
3
|
import { PxAnimatedSvgDocument, PxTimelinePatch, PxDiagnostic } from '@pixodesk/svg-animator-web';
|
|
4
|
-
import { PxAnimatorHandle,
|
|
4
|
+
import { PxAnimatorHandle, PxTriggerStart, PxOffScreenAction, PxMouseOutAction } from '@pixodesk/svg-animator-core';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The imperative handle the template ref exposes — core's `PxAnimatorHandle` under this
|
|
@@ -58,8 +58,8 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
58
58
|
iterations: {
|
|
59
59
|
type: PropType<number | "infinite">;
|
|
60
60
|
};
|
|
61
|
-
|
|
62
|
-
type: PropType<"load" | "mouseOver" | "click" | "
|
|
61
|
+
start: {
|
|
62
|
+
type: PropType<"load" | "mouseOver" | "click" | "none">;
|
|
63
63
|
};
|
|
64
64
|
autoplay: {
|
|
65
65
|
type: BooleanConstructor;
|
|
@@ -116,8 +116,8 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
116
116
|
iterations: {
|
|
117
117
|
type: PropType<number | "infinite">;
|
|
118
118
|
};
|
|
119
|
-
|
|
120
|
-
type: PropType<"load" | "mouseOver" | "click" | "
|
|
119
|
+
start: {
|
|
120
|
+
type: PropType<"load" | "mouseOver" | "click" | "none">;
|
|
121
121
|
};
|
|
122
122
|
autoplay: {
|
|
123
123
|
type: BooleanConstructor;
|
|
@@ -168,82 +168,108 @@ declare const PixodeskSvgAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
168
168
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* Controls playback of
|
|
171
|
+
* Controls playback of SVG+CSS animated files by toggling class names on a wrapper div.
|
|
172
172
|
*
|
|
173
173
|
* Intended for use with SVG files exported from the Pixodesk editor using the
|
|
174
|
-
* **CSS Keyframes**
|
|
175
|
-
*
|
|
174
|
+
* **CSS Keyframes** (no `<script>` tag). Import the SVG as a Vue component
|
|
175
|
+
* (`vite-svg-loader`) and pass it in the default slot:
|
|
176
176
|
*
|
|
177
177
|
* ```vue
|
|
178
178
|
* <script setup>
|
|
179
|
-
* import AnimationSvg from './animation.svg';
|
|
179
|
+
* import AnimationSvg from './animation.svg?component';
|
|
180
180
|
* </script>
|
|
181
181
|
*
|
|
182
182
|
* <template>
|
|
183
|
-
* <PixodeskSvgCssAnimator
|
|
183
|
+
* <PixodeskSvgCssAnimator start="mouseOver" mouseOut="pause">
|
|
184
184
|
* <AnimationSvg />
|
|
185
185
|
* </PixodeskSvgCssAnimator>
|
|
186
186
|
* </template>
|
|
187
187
|
* ```
|
|
188
188
|
*
|
|
189
189
|
* The wrapper div carries one of three animation states via CSS class names:
|
|
190
|
-
* - *(no class)*
|
|
191
|
-
* - `px-anim-enabled`
|
|
192
|
-
* - `px-anim-enabled px-anim-playing`
|
|
190
|
+
* - *(no class)* — idle, animation not started
|
|
191
|
+
* - `px-anim-enabled` — started but paused
|
|
192
|
+
* - `px-anim-enabled px-anim-playing` — actively playing
|
|
193
193
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* - `'
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
194
|
+
* TWO AXES, the same two the JSON player has: `start` says what STARTS it, `offScreen` says
|
|
195
|
+
* whether it may RUN. The gate itself is the player's (`createVisibilityGate`), so the threshold,
|
|
196
|
+
* the dwell, the hysteresis and the hidden-tab rule cannot drift between the two.
|
|
197
|
+
*
|
|
198
|
+
* @prop start - What starts the animation:
|
|
199
|
+
* - `'load'` — plays as soon as it is visible enough (default)
|
|
200
|
+
* - `'mouseOver'` — plays on hover
|
|
201
|
+
* - `'click'` — plays on click, toggles on second click
|
|
202
|
+
* - `'none'` — **not supported here.** This wrapper exposes no `play()`, so there is
|
|
203
|
+
* nothing to wait for and the animation never starts. The prop keeps the
|
|
204
|
+
* shared `PxTriggerStart` type (one enum per wire key), so the value
|
|
205
|
+
* type-checks — it simply has no effect. Use `PixodeskSvgAnimator` (the JSON
|
|
206
|
+
* player) when you need to start an animation from code.
|
|
207
|
+
* @prop offScreen - What happens while none of it is on screen:
|
|
208
|
+
* - `'pause'` — pauses at the current frame (default); resumes when it comes back
|
|
209
|
+
* - `'continue'` — keeps playing, and starts without waiting to be seen
|
|
210
|
+
* - `'reset'` — back to the beginning, so it replays on the next entry
|
|
211
|
+
* @prop mouseOut - What happens when the pointer leaves, for `start: 'mouseOver'`:
|
|
205
212
|
* - `'continue'` — keeps playing (default)
|
|
206
213
|
* - `'pause'` — pauses at the current frame
|
|
207
214
|
* - `'reset'` — resets to the beginning
|
|
208
215
|
* - `'reverse'` — **acts as `'continue'` here.** A CSS class toggle cannot run keyframes
|
|
209
|
-
* backwards. Accepted so the prop keeps the shared `
|
|
210
|
-
* @prop
|
|
211
|
-
*
|
|
212
|
-
*
|
|
216
|
+
* backwards. Accepted so the prop keeps the shared `PxMouseOutAction` type.
|
|
217
|
+
* @prop visibilityThreshold - How much of the element must be on screen (0–1) before it may run.
|
|
218
|
+
* Defaults to the wire default (`0.5`), the same as the JSON player.
|
|
219
|
+
* @prop visibilityDebounce - How long that must hold, in ms, before it starts. Defaults to the
|
|
220
|
+
* wire default (`150`).
|
|
213
221
|
* @public
|
|
214
222
|
*/
|
|
215
223
|
declare const PixodeskSvgCssAnimator: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
216
|
-
|
|
217
|
-
type: PropType<
|
|
218
|
-
default:
|
|
224
|
+
start: {
|
|
225
|
+
type: PropType<PxTriggerStart>;
|
|
226
|
+
default: "load";
|
|
227
|
+
};
|
|
228
|
+
offScreen: {
|
|
229
|
+
type: PropType<PxOffScreenAction>;
|
|
230
|
+
default: "pause";
|
|
219
231
|
};
|
|
220
|
-
|
|
221
|
-
type: PropType<
|
|
222
|
-
default:
|
|
232
|
+
mouseOut: {
|
|
233
|
+
type: PropType<PxMouseOutAction>;
|
|
234
|
+
default: "continue";
|
|
235
|
+
};
|
|
236
|
+
visibilityThreshold: {
|
|
237
|
+
type: NumberConstructor;
|
|
238
|
+
default: 0.5;
|
|
223
239
|
};
|
|
224
|
-
|
|
240
|
+
visibilityDebounce: {
|
|
225
241
|
type: NumberConstructor;
|
|
226
|
-
default:
|
|
242
|
+
default: 150;
|
|
227
243
|
};
|
|
228
244
|
}>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
|
|
229
245
|
[key: string]: any;
|
|
230
246
|
}>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
|
|
231
|
-
|
|
232
|
-
type: PropType<
|
|
233
|
-
default:
|
|
247
|
+
start: {
|
|
248
|
+
type: PropType<PxTriggerStart>;
|
|
249
|
+
default: "load";
|
|
234
250
|
};
|
|
235
|
-
|
|
236
|
-
type: PropType<
|
|
237
|
-
default:
|
|
251
|
+
offScreen: {
|
|
252
|
+
type: PropType<PxOffScreenAction>;
|
|
253
|
+
default: "pause";
|
|
254
|
+
};
|
|
255
|
+
mouseOut: {
|
|
256
|
+
type: PropType<PxMouseOutAction>;
|
|
257
|
+
default: "continue";
|
|
258
|
+
};
|
|
259
|
+
visibilityThreshold: {
|
|
260
|
+
type: NumberConstructor;
|
|
261
|
+
default: 0.5;
|
|
238
262
|
};
|
|
239
|
-
|
|
263
|
+
visibilityDebounce: {
|
|
240
264
|
type: NumberConstructor;
|
|
241
|
-
default:
|
|
265
|
+
default: 150;
|
|
242
266
|
};
|
|
243
267
|
}>> & Readonly<{}>, {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
268
|
+
start: PxTriggerStart;
|
|
269
|
+
offScreen: PxOffScreenAction;
|
|
270
|
+
mouseOut: PxMouseOutAction;
|
|
271
|
+
visibilityThreshold: number;
|
|
272
|
+
visibilityDebounce: number;
|
|
247
273
|
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
|
|
248
274
|
|
|
249
275
|
export { PixodeskSvgAnimator, PixodeskSvgCssAnimator, type VueAnimatorApi };
|