@lottiefiles/dotlottie-svelte 0.9.11 → 0.10.0

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.
@@ -1,213 +1,283 @@
1
1
  <script lang="ts">
2
- import { type Config, DotLottie } from '@lottiefiles/dotlottie-web';
3
- import { onMount } from 'svelte';
4
-
5
- export function setWasmUrl(url: string): void {
6
- DotLottie.setWasmUrl(url);
7
- }
8
-
9
- export let autoplay: Config['autoplay'] = false;
10
- export let backgroundColor: Config['backgroundColor'] = undefined;
11
- export let data: Config['data'] = undefined;
12
- export let loop: Config['loop'] = false;
13
- export let mode: Config['mode'] = 'forward';
14
- export let renderConfig: Config['renderConfig'] = undefined;
15
- export let segment: Config['segment'] = undefined;
16
- export let speed: Config['speed'] = 1;
17
- export let src: Config['src'] = undefined;
18
- export let useFrameInterpolation: Config['useFrameInterpolation'] = true;
19
- export let marker: Config['marker'] = undefined;
20
- export let layout: Config['layout'] = undefined;
21
- export let animationId: Config['animationId'] = '';
22
- export let themeId: Config['themeId'] = '';
23
- export let stateMachineId: Config['stateMachineId'] = undefined;
24
- export let stateMachineConfig: Config['stateMachineConfig'] = undefined;
25
-
26
- export let playOnHover: boolean = false;
27
- export let themeData: string = '';
28
-
29
- export let dotLottieRefCallback: (dotLottie: DotLottie) => void = () => {};
30
-
31
- const hoverHandler = (event: MouseEvent) => {
32
- if (!playOnHover || !dotLottie.isLoaded) return;
33
-
34
- if (event.type === 'mouseenter') {
35
- dotLottie.play();
36
- } else if (event.type === 'mouseleave') {
37
- dotLottie.pause();
38
- }
39
- };
40
-
41
- let dotLottie: DotLottie;
42
- let canvas: HTMLCanvasElement;
43
- let prevSrc: string | undefined;
44
- let prevData: Config['data'];
45
-
46
- onMount(() => {
47
- const shouldAutoplay = autoplay && !playOnHover;
48
- dotLottie = new DotLottie({
49
- canvas,
50
- src,
51
- autoplay: shouldAutoplay,
52
- loop,
53
- speed,
54
- data,
55
- renderConfig,
56
- segment,
57
- useFrameInterpolation,
58
- backgroundColor,
59
- mode,
60
- animationId,
61
- themeId,
62
- stateMachineId,
63
- stateMachineConfig,
64
- });
65
-
66
- if (dotLottieRefCallback) {
67
- dotLottieRefCallback(dotLottie);
68
- }
69
-
70
- canvas.addEventListener('mouseenter', hoverHandler);
71
- canvas.addEventListener('mouseleave', hoverHandler);
72
-
73
- return () => {
74
- canvas.removeEventListener('mouseenter', hoverHandler);
75
- canvas.removeEventListener('mouseleave', hoverHandler);
76
- dotLottie.destroy();
77
- };
78
- });
79
-
80
- $: {
81
- if (dotLottie && typeof layout === 'object') {
82
- dotLottie.setLayout(layout);
83
- }
84
- }
85
-
86
- $: {
87
- if (dotLottie && typeof marker === 'string') {
88
- dotLottie.setMarker(marker);
89
- }
90
- }
91
-
92
- $: {
93
- if (dotLottie && dotLottie.isLoaded && typeof speed == 'number') {
94
- dotLottie.setSpeed(speed);
95
- }
96
- }
97
-
98
- $: {
99
- if (dotLottie && dotLottie.isLoaded && typeof useFrameInterpolation == 'boolean') {
100
- dotLottie.setUseFrameInterpolation(useFrameInterpolation);
101
- }
102
- }
103
-
104
- $: {
105
- if (
106
- dotLottie &&
107
- dotLottie.isLoaded &&
108
- Array.isArray(segment) &&
109
- segment.length === 2 &&
110
- typeof segment[0] === 'number' &&
111
- typeof segment[1] === 'number'
112
- ) {
113
- const [start, end] = segment;
114
- dotLottie.setSegment(start, end);
115
- }
116
- }
117
-
118
- $: {
119
- if (dotLottie && dotLottie.isLoaded && typeof loop == 'boolean') {
120
- dotLottie.setLoop(loop);
121
- }
122
- }
123
-
124
- $: {
125
- if (dotLottie) {
126
- dotLottie.setBackgroundColor(backgroundColor || '');
127
- }
128
- }
129
-
130
- $: {
131
- if (dotLottie && dotLottie.isLoaded && typeof mode == 'string') {
132
- dotLottie.setMode(mode);
133
- }
134
- }
135
-
136
- $: if (dotLottie && src !== prevSrc) {
137
- dotLottie.load({
138
- src,
139
- autoplay,
140
- loop,
141
- speed,
142
- data,
143
- renderConfig,
144
- segment,
145
- useFrameInterpolation,
146
- backgroundColor,
147
- mode,
148
- marker,
149
- layout,
150
- animationId,
151
- themeId,
152
- stateMachineId,
153
- stateMachineConfig,
154
- });
155
- prevSrc = src;
156
- }
157
-
158
- $: if (dotLottie && data !== prevData) {
159
- dotLottie.load({
160
- src,
161
- autoplay,
162
- loop,
163
- speed,
164
- data,
165
- renderConfig,
166
- segment,
167
- useFrameInterpolation,
168
- backgroundColor,
169
- mode,
170
- marker,
171
- layout,
172
- animationId,
173
- themeId,
174
- stateMachineId,
175
- stateMachineConfig,
176
- });
177
- prevData = data;
178
- }
179
-
180
- $: if (dotLottie && dotLottie.isLoaded && dotLottie.activeAnimationId !== animationId) {
181
- dotLottie.loadAnimation(animationId);
182
- }
183
-
184
- $: if (dotLottie && dotLottie.isLoaded && dotLottie.activeThemeId !== themeId) {
185
- dotLottie.setTheme(themeId);
186
- }
187
-
188
- $: if (dotLottie && dotLottie.isLoaded) {
189
- dotLottie.setThemeData(themeData);
190
- }
191
-
192
- $: {
193
- if (dotLottie && dotLottie.isLoaded) {
194
- if (typeof stateMachineId === 'string' && stateMachineId) {
195
- const smLoaded = dotLottie.stateMachineLoad(stateMachineId);
196
-
197
- if (smLoaded) {
198
- dotLottie.stateMachineStart();
199
- }
200
- } else {
201
- dotLottie.stateMachineStop();
202
- }
203
- }
204
- }
205
-
206
- $: {
207
- if (dotLottie) {
208
- dotLottie.stateMachineSetConfig(stateMachineConfig ?? null);
209
- }
210
- }
2
+ import { type Config, DotLottie } from '@lottiefiles/dotlottie-web';
3
+ import { untrack } from 'svelte';
4
+
5
+ interface DotLottieSvelteProps {
6
+ autoplay?: Config['autoplay'];
7
+ backgroundColor?: Config['backgroundColor'];
8
+ data?: Config['data'];
9
+ loop?: Config['loop'];
10
+ mode?: Config['mode'];
11
+ renderConfig?: Config['renderConfig'];
12
+ segment?: Config['segment'];
13
+ speed?: Config['speed'];
14
+ src?: Config['src'];
15
+ useFrameInterpolation?: Config['useFrameInterpolation'];
16
+ marker?: Config['marker'];
17
+ layout?: Config['layout'];
18
+ animationId?: Config['animationId'];
19
+ themeId?: Config['themeId'];
20
+ stateMachineId?: Config['stateMachineId'];
21
+ stateMachineConfig?: Config['stateMachineConfig'];
22
+ playOnHover?: boolean;
23
+ themeData?: string;
24
+ dotLottieRefCallback?: (dotLottie: DotLottie) => void;
25
+ }
26
+
27
+ let {
28
+ autoplay = false,
29
+ backgroundColor = undefined,
30
+ data = undefined,
31
+ loop = false,
32
+ mode = 'forward',
33
+ renderConfig = undefined,
34
+ segment = undefined,
35
+ speed = 1,
36
+ src = undefined,
37
+ useFrameInterpolation = true,
38
+ marker = undefined,
39
+ layout = undefined,
40
+ animationId = '',
41
+ themeId = '',
42
+ stateMachineId = undefined,
43
+ stateMachineConfig = undefined,
44
+ playOnHover = false,
45
+ themeData = '',
46
+ dotLottieRefCallback = () => {}
47
+ }: DotLottieSvelteProps = $props();
48
+
49
+ let canvas: HTMLCanvasElement;
50
+ let dotLottie: DotLottie | undefined = $state(undefined);
51
+ let prevSrc: Config['src'];
52
+ let prevData: Config['data'];
53
+
54
+ // Initialize DotLottie instance once when canvas is ready.
55
+ // Use untrack() to read initial prop values without establishing reactive dependencies —
56
+ // prop changes are handled by separate $effect blocks below.
57
+ $effect(() => {
58
+ const currentCanvas = canvas;
59
+ if (!currentCanvas) return;
60
+
61
+ const instance = new DotLottie(
62
+ untrack(() => ({
63
+ canvas: currentCanvas,
64
+ src,
65
+ autoplay: autoplay && !playOnHover,
66
+ loop,
67
+ speed,
68
+ data,
69
+ renderConfig,
70
+ segment,
71
+ useFrameInterpolation,
72
+ backgroundColor,
73
+ mode,
74
+ animationId,
75
+ themeId,
76
+ stateMachineId,
77
+ stateMachineConfig
78
+ }))
79
+ );
80
+
81
+ dotLottie = instance;
82
+ untrack(() => dotLottieRefCallback?.(instance));
83
+
84
+ return () => {
85
+ instance.destroy();
86
+ dotLottie = undefined;
87
+ };
88
+ });
89
+
90
+ // Hover handler — re-registers listeners whenever playOnHover or dotLottie changes.
91
+ // Capture the canvas element locally so cleanup detaches listeners from the same
92
+ // node we attached to, even if `canvas` rebinds later.
93
+ $effect(() => {
94
+ const currentPlayOnHover = playOnHover;
95
+ const currentDotLottie = dotLottie;
96
+ const currentCanvas = canvas;
97
+
98
+ if (!currentCanvas) return;
99
+
100
+ const handlePlayOnHover = (event: MouseEvent): void => {
101
+ if (!currentPlayOnHover || !currentDotLottie?.isLoaded) return;
102
+ if (event.type === 'mouseenter') {
103
+ currentDotLottie.play();
104
+ } else if (event.type === 'mouseleave') {
105
+ currentDotLottie.pause();
106
+ }
107
+ };
108
+
109
+ currentCanvas.addEventListener('mouseenter', handlePlayOnHover);
110
+ currentCanvas.addEventListener('mouseleave', handlePlayOnHover);
111
+
112
+ return () => {
113
+ currentCanvas.removeEventListener('mouseenter', handlePlayOnHover);
114
+ currentCanvas.removeEventListener('mouseleave', handlePlayOnHover);
115
+ };
116
+ });
117
+
118
+ $effect(() => {
119
+ if (dotLottie && typeof layout === 'object') {
120
+ dotLottie.setLayout(layout);
121
+ }
122
+ });
123
+
124
+ $effect(() => {
125
+ if (dotLottie && typeof marker === 'string') {
126
+ dotLottie.setMarker(marker);
127
+ }
128
+ });
129
+
130
+ $effect(() => {
131
+ const currentSpeed = speed;
132
+ if (dotLottie && typeof currentSpeed === 'number') {
133
+ dotLottie.setSpeed(currentSpeed);
134
+ }
135
+ });
136
+
137
+ $effect(() => {
138
+ const currentUseFrameInterpolation = useFrameInterpolation;
139
+ if (dotLottie && typeof currentUseFrameInterpolation === 'boolean') {
140
+ dotLottie.setUseFrameInterpolation(currentUseFrameInterpolation);
141
+ }
142
+ });
143
+
144
+ $effect(() => {
145
+ const currentSegment = segment;
146
+ if (
147
+ dotLottie &&
148
+ Array.isArray(currentSegment) &&
149
+ currentSegment.length === 2 &&
150
+ typeof currentSegment[0] === 'number' &&
151
+ typeof currentSegment[1] === 'number'
152
+ ) {
153
+ const [start, end] = currentSegment;
154
+ dotLottie.setSegment(start, end);
155
+ }
156
+ });
157
+
158
+ $effect(() => {
159
+ const currentLoop = loop;
160
+ if (dotLottie && typeof currentLoop === 'boolean') {
161
+ dotLottie.setLoop(currentLoop);
162
+ }
163
+ });
164
+
165
+ $effect(() => {
166
+ if (dotLottie) {
167
+ dotLottie.setBackgroundColor(backgroundColor || '');
168
+ }
169
+ });
170
+
171
+ $effect(() => {
172
+ const currentMode = mode;
173
+ if (dotLottie && typeof currentMode === 'string') {
174
+ dotLottie.setMode(currentMode);
175
+ }
176
+ });
177
+
178
+ $effect(() => {
179
+ if (dotLottie) {
180
+ dotLottie.setRenderConfig(renderConfig ?? {});
181
+ }
182
+ });
183
+
184
+ $effect(() => {
185
+ if (dotLottie && typeof src === 'string' && src !== prevSrc) {
186
+ prevSrc = src;
187
+ dotLottie.load({
188
+ src,
189
+ ...untrack(() => ({
190
+ autoplay,
191
+ loop,
192
+ speed,
193
+ data,
194
+ renderConfig,
195
+ segment,
196
+ useFrameInterpolation,
197
+ backgroundColor,
198
+ mode,
199
+ marker,
200
+ layout,
201
+ animationId,
202
+ themeId,
203
+ stateMachineId,
204
+ stateMachineConfig
205
+ }))
206
+ });
207
+ }
208
+ });
209
+
210
+ $effect(() => {
211
+ if (
212
+ dotLottie &&
213
+ (typeof data === 'string' || typeof data === 'object') &&
214
+ data !== undefined &&
215
+ data !== prevData
216
+ ) {
217
+ prevData = data;
218
+ dotLottie.load({
219
+ data,
220
+ ...untrack(() => ({
221
+ src,
222
+ autoplay,
223
+ loop,
224
+ speed,
225
+ renderConfig,
226
+ segment,
227
+ useFrameInterpolation,
228
+ backgroundColor,
229
+ mode,
230
+ marker,
231
+ layout,
232
+ animationId,
233
+ themeId,
234
+ stateMachineId,
235
+ stateMachineConfig
236
+ }))
237
+ });
238
+ }
239
+ });
240
+
241
+ $effect(() => {
242
+ const currentAnimationId = animationId;
243
+ if (dotLottie) {
244
+ dotLottie.loadAnimation(currentAnimationId);
245
+ }
246
+ });
247
+
248
+ $effect(() => {
249
+ const currentThemeId = themeId;
250
+ if (dotLottie) {
251
+ dotLottie.setTheme(currentThemeId);
252
+ }
253
+ });
254
+
255
+ $effect(() => {
256
+ const currentThemeData = themeData;
257
+ if (dotLottie) {
258
+ dotLottie.setThemeData(currentThemeData);
259
+ }
260
+ });
261
+
262
+ $effect(() => {
263
+ const currentStateMachineId = stateMachineId;
264
+ if (dotLottie && dotLottie.isLoaded) {
265
+ if (typeof currentStateMachineId === 'string' && currentStateMachineId) {
266
+ const smLoaded = dotLottie.stateMachineLoad(currentStateMachineId);
267
+ if (smLoaded) {
268
+ dotLottie.stateMachineStart();
269
+ }
270
+ } else {
271
+ dotLottie.stateMachineStop();
272
+ }
273
+ }
274
+ });
275
+
276
+ $effect(() => {
277
+ if (dotLottie) {
278
+ dotLottie.stateMachineSetConfig(stateMachineConfig ?? null);
279
+ }
280
+ });
211
281
  </script>
212
282
 
213
283
  <div>
@@ -1,42 +1,25 @@
1
1
  import { type Config, DotLottie } from '@lottiefiles/dotlottie-web';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const Dotlottie: $$__sveltets_2_IsomorphicComponent<{
16
- setWasmUrl?: (url: string) => void;
17
- autoplay?: Config["autoplay"];
18
- backgroundColor?: Config["backgroundColor"];
19
- data?: Config["data"];
20
- loop?: Config["loop"];
21
- mode?: Config["mode"];
22
- renderConfig?: Config["renderConfig"];
23
- segment?: Config["segment"];
24
- speed?: Config["speed"];
25
- src?: Config["src"];
26
- useFrameInterpolation?: Config["useFrameInterpolation"];
27
- marker?: Config["marker"];
28
- layout?: Config["layout"];
29
- animationId?: Config["animationId"];
30
- themeId?: Config["themeId"];
31
- stateMachineId?: Config["stateMachineId"];
32
- stateMachineConfig?: Config["stateMachineConfig"];
2
+ interface DotLottieSvelteProps {
3
+ autoplay?: Config['autoplay'];
4
+ backgroundColor?: Config['backgroundColor'];
5
+ data?: Config['data'];
6
+ loop?: Config['loop'];
7
+ mode?: Config['mode'];
8
+ renderConfig?: Config['renderConfig'];
9
+ segment?: Config['segment'];
10
+ speed?: Config['speed'];
11
+ src?: Config['src'];
12
+ useFrameInterpolation?: Config['useFrameInterpolation'];
13
+ marker?: Config['marker'];
14
+ layout?: Config['layout'];
15
+ animationId?: Config['animationId'];
16
+ themeId?: Config['themeId'];
17
+ stateMachineId?: Config['stateMachineId'];
18
+ stateMachineConfig?: Config['stateMachineConfig'];
33
19
  playOnHover?: boolean;
34
20
  themeData?: string;
35
21
  dotLottieRefCallback?: (dotLottie: DotLottie) => void;
36
- }, {
37
- [evt: string]: CustomEvent<any>;
38
- }, {}, {
39
- setWasmUrl: (url: string) => void;
40
- }, string>;
41
- type Dotlottie = InstanceType<typeof Dotlottie>;
22
+ }
23
+ declare const Dotlottie: import("svelte").Component<DotLottieSvelteProps, {}, "">;
24
+ type Dotlottie = ReturnType<typeof Dotlottie>;
42
25
  export default Dotlottie;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lottiefiles/dotlottie-svelte",
3
- "version": "0.9.11",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "description": "Svelte component wrapper around the dotlottie-web library to render Lottie and dotLottie animations",
6
6
  "repository": {
@@ -32,23 +32,29 @@
32
32
  ],
33
33
  "license": "MIT",
34
34
  "peerDependencies": {
35
- "svelte": "^4.0.0 || ^5.0.0"
35
+ "svelte": "^5.0.0"
36
36
  },
37
37
  "dependencies": {
38
- "@lottiefiles/dotlottie-web": "0.70.0"
38
+ "@lottiefiles/dotlottie-web": "0.72.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@sveltejs/adapter-auto": "^3.0.0",
42
- "@sveltejs/kit": "^2.0.0",
43
- "@sveltejs/package": "^2.0.0",
44
- "@sveltejs/vite-plugin-svelte": "^4.0.0",
45
- "publint": "^0.1.9",
46
- "svelte": "^5.0.0",
47
- "svelte-check": "^3.6.0",
41
+ "@sveltejs/adapter-auto": "^7.0.1",
42
+ "@sveltejs/kit": "^2.58.0",
43
+ "@sveltejs/package": "^2.5.7",
44
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
45
+ "@testing-library/user-event": "^14.5.2",
46
+ "@types/node": "^25.6.0",
47
+ "@vitest/browser": "^4.0.18",
48
+ "@vitest/browser-playwright": "^4.0.18",
49
+ "@vitest/coverage-istanbul": "^4.0.18",
50
+ "publint": "^0.3.17",
51
+ "svelte": "^5.55.5",
52
+ "svelte-check": "^4.4.6",
48
53
  "tslib": "^2.4.1",
49
- "typescript": "5.9.3",
50
- "vite": "^5.0.13",
51
- "vitest": "^4.0.18"
54
+ "typescript": "6.0.3",
55
+ "vite": "^7.3.1",
56
+ "vitest": "^4.0.18",
57
+ "vitest-browser-svelte": "^2.0.2"
52
58
  },
53
59
  "sideEffects": false,
54
60
  "publishConfig": {
@@ -65,6 +71,9 @@
65
71
  "lint": "biome check .",
66
72
  "format": "biome check --write .",
67
73
  "stats:ts": "tsc -p tsconfig.build.json --extendedDiagnostics",
74
+ "test": "vitest run --browser.headless",
75
+ "test:coverage": "vitest run --browser.headless --coverage",
76
+ "test:watch": "vitest",
68
77
  "type-check": "tsc --noEmit"
69
78
  }
70
79
  }