@aarsteinmedia/dotlottie-player 4.0.13 → 5.0.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.
package/dist/cjs/index.js DELETED
@@ -1,1804 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var fflate = require('fflate');
6
- var Lottie = require('lottie-web/build/player/lottie.js');
7
-
8
- function _interopNamespaceDefault(e) {
9
- var n = Object.create(null);
10
- if (e) {
11
- Object.keys(e).forEach(function (k) {
12
- if (k !== 'default') {
13
- var d = Object.getOwnPropertyDescriptor(e, k);
14
- Object.defineProperty(n, k, d.get ? d : {
15
- enumerable: true,
16
- get: function () { return e[k]; }
17
- });
18
- }
19
- });
20
- }
21
- n.default = e;
22
- return Object.freeze(n);
23
- }
24
-
25
- var Lottie__namespace = /*#__PURE__*/_interopNamespaceDefault(Lottie);
26
-
27
- var ObjectFit = /*#__PURE__*/ function(ObjectFit) {
28
- ObjectFit["Contain"] = "contain";
29
- ObjectFit["Cover"] = "cover";
30
- ObjectFit["Fill"] = "fill";
31
- ObjectFit["ScaleDown"] = "scale-down";
32
- ObjectFit["None"] = "none";
33
- return ObjectFit;
34
- }({});
35
- var PlayerState = /*#__PURE__*/ function(PlayerState) {
36
- PlayerState["Completed"] = "completed";
37
- PlayerState["Destroyed"] = "destroyed";
38
- PlayerState["Error"] = "error";
39
- PlayerState["Frozen"] = "frozen";
40
- PlayerState["Loading"] = "loading";
41
- PlayerState["Paused"] = "paused";
42
- PlayerState["Playing"] = "playing";
43
- PlayerState["Stopped"] = "stopped";
44
- return PlayerState;
45
- }({});
46
- var PlayMode = /*#__PURE__*/ function(PlayMode) {
47
- PlayMode["Bounce"] = "bounce";
48
- PlayMode["Normal"] = "normal";
49
- return PlayMode;
50
- }({});
51
- var PlayerEvents = /*#__PURE__*/ function(PlayerEvents) {
52
- PlayerEvents["Complete"] = "complete";
53
- PlayerEvents["Destroyed"] = "destroyed";
54
- PlayerEvents["Error"] = "error";
55
- PlayerEvents["Frame"] = "frame";
56
- PlayerEvents["Freeze"] = "freeze";
57
- PlayerEvents["Load"] = "load";
58
- PlayerEvents["Loop"] = "loop";
59
- PlayerEvents["Next"] = "next";
60
- PlayerEvents["Pause"] = "pause";
61
- PlayerEvents["Play"] = "play";
62
- PlayerEvents["Previous"] = "previous";
63
- PlayerEvents["Ready"] = "ready";
64
- PlayerEvents["Rendered"] = "rendered";
65
- PlayerEvents["Stop"] = "stop";
66
- return PlayerEvents;
67
- }({});
68
- var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
69
- PreserveAspectRatio["Contain"] = "xMidYMid meet";
70
- PreserveAspectRatio["Cover"] = "xMidYMid slice";
71
- PreserveAspectRatio["None"] = "xMinYMin slice";
72
- PreserveAspectRatio["Initial"] = "none";
73
- return PreserveAspectRatio;
74
- }({});
75
-
76
- class CustomError extends Error {
77
- }
78
- const addExt = (ext, str)=>{
79
- if (!str) {
80
- return;
81
- }
82
- if (getExt(str)) {
83
- if (getExt(str) === ext) {
84
- return str;
85
- }
86
- return `${getFilename(str)}.${ext}`;
87
- }
88
- return `${str}.${ext}`;
89
- }, aspectRatio = (objectFit)=>{
90
- switch(objectFit){
91
- case ObjectFit.Contain:
92
- case ObjectFit.ScaleDown:
93
- return 'xMidYMid meet';
94
- case ObjectFit.Cover:
95
- return 'xMidYMid slice';
96
- case ObjectFit.Fill:
97
- return 'none';
98
- case ObjectFit.None:
99
- return 'xMinYMin slice';
100
- default:
101
- return 'xMidYMid meet';
102
- }
103
- }, /**
104
- * Convert Base64 encoded string to Uint8Array
105
- * @param { string } str Base64 encoded string
106
- * @returns { Uint8Array } UTF-8/Latin-1 binary
107
- */ base64ToU8 = (str)=>fflate.strToU8(isServer() ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), /**
108
- * Convert a JSON Lottie to dotLottie or combine several animations and download new dotLottie file in your browser.
109
- */ createDotLottie = async ({ animations, fileName, manifest, shouldDownload = true })=>{
110
- try {
111
- // Input validation
112
- if (!animations?.length || !manifest) {
113
- throw new Error(`Missing or malformed required parameter(s):\n ${animations?.length ? '- manifest\n' : ''} ${manifest ? '- animations\n' : ''}`);
114
- }
115
- const manifestCompressionLevel = 0, animationCompressionLevel = 9, // Prepare the dotLottie file
116
- name = addExt('lottie', fileName) || `${useId()}.lottie`, dotlottie = {
117
- 'manifest.json': [
118
- fflate.strToU8(JSON.stringify(manifest), true),
119
- {
120
- level: manifestCompressionLevel
121
- }
122
- ]
123
- };
124
- // Add animations and assets to the dotLottie file
125
- for (const [i, animation] of animations.entries()){
126
- for (const asset of animation.assets ?? []){
127
- if (!asset.p || !isImage(asset) && !isAudio(asset)) {
128
- continue;
129
- }
130
- const { p: file, u: path } = asset, // Original asset.id caused issues with multianimations
131
- assetId = useId('asset'), isEncoded = file.startsWith('data:'), ext = isEncoded ? getExtFromB64(file) : getExt(file), // Check if the asset is already base64-encoded. If not, get path, fetch it, and encode it
132
- dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
133
- asset.p = `${assetId}.${ext}`;
134
- // Asset is embedded, so path empty string
135
- asset.u = '';
136
- // Asset is encoded
137
- asset.e = 1;
138
- dotlottie[`${isAudio(asset) ? 'audio' : 'images'}/${assetId}.${ext}`] = [
139
- base64ToU8(dataURL),
140
- {
141
- level: animationCompressionLevel
142
- }
143
- ];
144
- }
145
- dotlottie[`animations/${manifest.animations[i].id}.json`] = [
146
- fflate.strToU8(JSON.stringify(animation), true),
147
- {
148
- level: animationCompressionLevel
149
- }
150
- ];
151
- }
152
- const buffer = await getArrayBuffer(dotlottie);
153
- return shouldDownload ? download(buffer, {
154
- mimeType: 'application/zip',
155
- name
156
- }) : buffer;
157
- } catch (err) {
158
- console.error(`❌ ${handleErrors(err).message}`);
159
- }
160
- }, createJSON = ({ animation, fileName, shouldDownload })=>{
161
- try {
162
- if (!animation) {
163
- throw new Error("Missing or malformed required parameter(s):\n - animation\n'");
164
- }
165
- const name = addExt('json', fileName) || `${useId()}.json`, jsonString = JSON.stringify(animation);
166
- return shouldDownload ? download(jsonString, {
167
- mimeType: 'application/json',
168
- name
169
- }) : jsonString;
170
- } catch (err) {
171
- console.error(`❌ ${handleErrors(err).message}`);
172
- }
173
- }, /**
174
- * Download file, either SVG or dotLottie.
175
- * @param { string } data The data to be downloaded
176
- * @param { string } name Don't include file extension in the filename
177
- */ download = (data, options)=>{
178
- const blob = new Blob([
179
- data
180
- ], {
181
- type: options?.mimeType
182
- }), fileName = options?.name || useId(), dataURL = URL.createObjectURL(blob), link = document.createElement('a');
183
- link.href = dataURL;
184
- link.download = fileName;
185
- link.hidden = true;
186
- document.body.appendChild(link);
187
- link.click();
188
- setTimeout(()=>{
189
- link.remove();
190
- URL.revokeObjectURL(dataURL);
191
- }, 1000);
192
- }, fileToBase64 = async (url)=>{
193
- const response = await fetch(url), blob = await response.blob();
194
- return new Promise((resolve, reject)=>{
195
- try {
196
- const reader = new FileReader();
197
- reader.onload = ()=>{
198
- if (typeof reader.result === 'string') {
199
- resolve(reader.result);
200
- return;
201
- }
202
- reject();
203
- };
204
- reader.readAsDataURL(blob);
205
- } catch (e) {
206
- reject(e);
207
- }
208
- });
209
- }, frameOutput = (frame)=>((frame ?? 0) + 1).toString().padStart(3, '0'), getAnimationData = async (input)=>{
210
- try {
211
- if (!input || typeof input !== 'string' && typeof input !== 'object') {
212
- throw new Error('Broken file or invalid file format');
213
- }
214
- if (typeof input !== 'string') {
215
- const animations = Array.isArray(input) ? input : [
216
- input
217
- ];
218
- return {
219
- animations,
220
- isDotLottie: false,
221
- manifest: undefined
222
- };
223
- }
224
- const result = await fetch(input, {
225
- headers: {
226
- 'Content-Type': 'application/json; charset=UTF-8'
227
- }
228
- });
229
- if (!result.ok) {
230
- const error = new CustomError(result.statusText);
231
- error.status = result.status;
232
- throw error;
233
- }
234
- /**
235
- * Check if file is JSON, first by parsing file name for extension,
236
- * then – if filename has no extension – by cloning the response
237
- * and parsing it for content.
238
- */ const ext = getExt(input);
239
- if (ext === 'json' || !ext) {
240
- if (ext) {
241
- const lottie = await result.json();
242
- return {
243
- animations: [
244
- lottie
245
- ],
246
- isDotLottie: false,
247
- manifest: undefined
248
- };
249
- }
250
- const text = await result.clone().text();
251
- try {
252
- const lottie = JSON.parse(text);
253
- return {
254
- animations: [
255
- lottie
256
- ],
257
- isDotLottie: false,
258
- manifest: undefined
259
- };
260
- } catch (_e) {
261
- /* empty */ }
262
- }
263
- const { data, manifest } = await getLottieJSON(result);
264
- return {
265
- animations: data,
266
- isDotLottie: true,
267
- manifest
268
- };
269
- } catch (err) {
270
- console.error(`❌ ${handleErrors(err).message}`);
271
- return {
272
- animations: undefined,
273
- isDotLottie: false,
274
- manifest: undefined
275
- };
276
- }
277
- }, getArrayBuffer = async (zippable)=>{
278
- const arrayBuffer = await new Promise((resolve, reject)=>{
279
- fflate.zip(zippable, {
280
- level: 9
281
- }, (err, data)=>{
282
- if (err) {
283
- reject(err);
284
- return;
285
- }
286
- if (!(data.buffer instanceof ArrayBuffer)) {
287
- reject('Data is not transferable');
288
- return;
289
- }
290
- resolve(data.buffer);
291
- });
292
- });
293
- return arrayBuffer;
294
- }, /**
295
- * Get extension from filename, URL or path
296
- * @param { string } str Filename, URL or path
297
- */ getExt = (str)=>{
298
- if (typeof str !== 'string' || !str || !hasExt(str)) {
299
- return;
300
- }
301
- return str.split('.').pop()?.toLowerCase();
302
- }, getExtFromB64 = (str)=>{
303
- const mime = str.split(':')[1].split(';')[0], ext = mime.split('/')[1].split('+')[0];
304
- return ext;
305
- }, /**
306
- * Parse URL to get filename
307
- * @param { string } src The url string
308
- * @param { boolean } keepExt Whether to include file extension
309
- * @returns { string } Filename, in lowercase
310
- */ getFilename = (src, keepExt)=>{
311
- // Because the regex strips all special characters, we need to extract the file extension, so we can add it later if we need it
312
- getExt(src);
313
- return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replace(/\W+/g, '-')}${''}` // .toLowerCase()
314
- ;
315
- }, getLottieJSON = async (resp)=>{
316
- const unzipped = await unzip(resp), manifest = getManifest(unzipped), data = [], toResolve = [];
317
- for (const { id } of manifest.animations){
318
- const str = fflate.strFromU8(unzipped[`animations/${id}.json`]), lottie = JSON.parse(prepareString(str));
319
- toResolve.push(resolveAssets(unzipped, lottie.assets));
320
- data.push(lottie);
321
- }
322
- await Promise.all(toResolve);
323
- return {
324
- data,
325
- manifest
326
- };
327
- }, getManifest = (unzipped)=>{
328
- const file = fflate.strFromU8(unzipped['manifest.json'], false), manifest = JSON.parse(file);
329
- if (!('animations' in manifest)) {
330
- throw new Error('Manifest not found');
331
- }
332
- if (!manifest.animations.length) {
333
- throw new Error('No animations listed in manifest');
334
- }
335
- return manifest;
336
- }, getMimeFromExt = (ext)=>{
337
- switch(ext){
338
- case 'svg':
339
- case 'svg+xml':
340
- return 'image/svg+xml';
341
- case 'jpg':
342
- case 'jpeg':
343
- return 'image/jpeg';
344
- case 'png':
345
- case 'gif':
346
- case 'webp':
347
- case 'avif':
348
- return `image/${ext}`;
349
- case 'mp3':
350
- case 'mpeg':
351
- case 'wav':
352
- return `audio/${ext}`;
353
- default:
354
- return '';
355
- }
356
- }, handleErrors = (err)=>{
357
- const res = {
358
- message: 'Unknown error',
359
- status: isServer() ? 500 : 400
360
- };
361
- if (err && typeof err === 'object') {
362
- if ('message' in err && typeof err.message === 'string') {
363
- res.message = err.message;
364
- }
365
- if ('status' in err) {
366
- res.status = Number(err.status);
367
- }
368
- }
369
- return res;
370
- }, hasExt = (path)=>{
371
- const lastDotIndex = path?.split('/').pop()?.lastIndexOf('.');
372
- return (lastDotIndex ?? 0) > 1 && path && path.length - 1 > (lastDotIndex ?? 0);
373
- }, isAudio = (asset)=>!('h' in asset) && !('w' in asset) && 'p' in asset && 'e' in asset && 'u' in asset && 'id' in asset, isBase64 = (str)=>{
374
- if (!str) {
375
- return false;
376
- }
377
- const regex = /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/;
378
- return regex.test(parseBase64(str));
379
- }, isImage = (asset)=>'w' in asset && 'h' in asset && !('xt' in asset) && 'p' in asset, isServer = ()=>!(typeof window !== 'undefined' && window.document), parseBase64 = (str)=>str.substring(str.indexOf(',') + 1), prepareString = (str)=>str.replace(new RegExp(/"""/, 'g'), '""').replace(/(["'])(.*?)\1/g, (_match, quote, content)=>{
380
- const replacedContent = content.replace(/[^\w\s\d.#]/g, '');
381
- return `${quote}${replacedContent}${quote}`;
382
- }), resolveAssets = async (unzipped, assets)=>{
383
- if (!Array.isArray(assets)) {
384
- return;
385
- }
386
- const toResolve = [];
387
- for (const asset of assets){
388
- if (!isAudio(asset) && !isImage(asset)) {
389
- continue;
390
- }
391
- const type = isImage(asset) ? 'images' : 'audio', u8 = unzipped?.[`${type}/${asset.p}`];
392
- if (!u8) {
393
- continue;
394
- }
395
- toResolve.push(new Promise((resolveAsset)=>{
396
- const assetB64 = isServer() ? Buffer.from(u8).toString('base64') : btoa(u8.reduce((dat, byte)=>`${dat}${String.fromCharCode(byte)}`, ''));
397
- asset.p = asset.p?.startsWith('data:') || isBase64(asset.p) ? asset.p : `data:${getMimeFromExt(getExt(asset.p))};base64,${assetB64}`;
398
- asset.e = 1;
399
- asset.u = '';
400
- resolveAsset();
401
- }));
402
- }
403
- await Promise.all(toResolve);
404
- }, unzip = async (resp)=>{
405
- const u8 = new Uint8Array(await resp.arrayBuffer()), unzipped = await new Promise((resolve, reject)=>{
406
- fflate.unzip(u8, /* { filter }, */ (err, file)=>{
407
- if (err) {
408
- reject(err);
409
- }
410
- resolve(file);
411
- });
412
- });
413
- return unzipped;
414
- }, useId = (prefix)=>{
415
- const s4 = ()=>((1 + Math.random()) * 0x10000 | 0).toString(16).substring(1);
416
- return `${prefix ?? `:${s4()}`}_${s4()}`;
417
- };
418
-
419
- /**
420
- * Render Player
421
- */ function renderPlayer() {
422
- this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document?.documentElement?.lang : 'en'}" aria-label="${this.description ?? 'Lottie animation'}" data-loaded="${this._playerState.loaded}"><figure class="animation" style="background:${this.background}">${this.playerState === PlayerState.Error ? /* HTML */ `<div class="error"><svg preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1920" height="1080" viewBox="0 0 1920 1080"><path fill="#fff" d="M0 0h1920v1080H0z"/><path fill="#3a6d8b" d="M1190.2 531 1007 212.4c-22-38.2-77.2-38-98.8.5L729.5 531.3c-21.3 37.9 6.1 84.6 49.5 84.6l361.9.3c43.7 0 71.1-47.3 49.3-85.2zM937.3 288.7c.2-7.5 3.3-23.9 23.2-23.9 16.3 0 23 16.1 23 23.5 0 55.3-10.7 197.2-12.2 214.5-.1 1-.9 1.7-1.9 1.7h-18.3c-1 0-1.8-.7-1.9-1.7-1.4-17.5-13.4-162.9-11.9-214.1zm24.2 283.8c-13.1 0-23.7-10.6-23.7-23.7s10.6-23.7 23.7-23.7 23.7 10.6 23.7 23.7-10.6 23.7-23.7 23.7zM722.1 644h112.6v34.4h-70.4V698h58.8v31.7h-58.8v22.6h72.4v36.2H722.1V644zm162 57.1h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6zm78.9 0h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5H963v15.6zm39.5 36.2c0-31.3 22.2-54.8 56.6-54.8 34.4 0 56.2 23.5 56.2 54.8s-21.8 54.6-56.2 54.6c-34.4-.1-56.6-23.3-56.6-54.6zm74 0c0-17.4-6.1-29.1-17.8-29.1-11.7 0-17.4 11.7-17.4 29.1 0 17.4 5.7 29.1 17.4 29.1s17.8-11.8 17.8-29.1zm83.1-36.2h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6z"/><path fill="none" d="M718.9 807.7h645v285.4h-645z"/><text fill="#3a6d8b" style="text-align:center;position:absolute;left:100%;font-size:47px;font-family:system-ui,-apple-system,BlinkMacSystemFont,'.SFNSText-Regular',sans-serif" x="50%" y="848.017" text-anchor="middle">${this._errorMessage}</text></svg></div>` : ''}</figure><slot name="controls"></slot></div>`;
423
- this.shadow.adoptedStyleSheets = [
424
- DotLottiePlayer.styles
425
- ];
426
- this.shadow.appendChild(this.template.content.cloneNode(true));
427
- }
428
-
429
- /**
430
- * Render Controls
431
- */ function renderControls() {
432
- const slot = this.shadow.querySelector('slot[name=controls]');
433
- if (!slot) {
434
- return;
435
- }
436
- if (!this.controls) {
437
- slot.innerHTML = '';
438
- return;
439
- }
440
- slot.innerHTML = /* HTML */ `<div class="lottie-controls toolbar ${this.playerState === PlayerState.Error ? 'has-error' : ''}" aria-label="Lottie Animation controls"><button class="togglePlay" data-active="false" aria-label="Toggle Play/Pause"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z"/></svg></button> <button class="stop" data-active="true" aria-label="Stop"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M6 6h12v12H6V6z"/></svg></button> <button class="prev" aria-label="Previous animation" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.9 18.2 8.1 12l9.8-6.2v12.4zm-10.3 0H6.1V5.8h1.5v12.4z"/></svg></button> <button class="next" aria-label="Next animation" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="m6.1 5.8 9.8 6.2-9.8 6.2V5.8zM16.4 5.8h1.5v12.4h-1.5z"/></svg></button><form class="progress-container${this.simple ? ' simple' : ''}"><input class="seeker" type="range" min="0" max="100" step="1" value="${this._seeker.toString()}" aria-valuemin="0" aria-valuemax="100" role="slider" aria-valuenow="${this._seeker.toString()}" tabindex="0" aria-label="Slider for search"><progress max="100" value="${this._seeker}"></progress></form>${this.simple ? '' : /* HTML */ `<button class="toggleLoop" data-active="${this.loop}" tabindex="0" aria-label="Toggle loop"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.016 17.016v-4.031h1.969v6h-12v3l-3.984-3.984 3.984-3.984v3h10.031zM6.984 6.984v4.031H5.015v-6h12v-3l3.984 3.984-3.984 3.984v-3H6.984z"/></svg></button> <button class="toggleBoomerang" data-active="${this.mode === PlayMode.Bounce}" aria-label="Toggle boomerang" tabindex="0"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="m11.8 13.2-.3.3c-.5.5-1.1 1.1-1.7 1.5-.5.4-1 .6-1.5.8-.5.2-1.1.3-1.6.3s-1-.1-1.5-.3c-.6-.2-1-.5-1.4-1-.5-.6-.8-1.2-.9-1.9-.2-.9-.1-1.8.3-2.6.3-.7.8-1.2 1.3-1.6.3-.2.6-.4 1-.5.2-.2.5-.2.8-.3.3 0 .7-.1 1 0 .3 0 .6.1.9.2.9.3 1.7.9 2.4 1.5.4.4.8.7 1.1 1.1l.1.1.4-.4c.6-.6 1.2-1.2 1.9-1.6.5-.3 1-.6 1.5-.7.4-.1.7-.2 1-.2h.9c1 .1 1.9.5 2.6 1.4.4.5.7 1.1.8 1.8.2.9.1 1.7-.2 2.5-.4.9-1 1.5-1.8 2-.4.2-.7.4-1.1.4-.4.1-.8.1-1.2.1-.5 0-.9-.1-1.3-.3-.8-.3-1.5-.9-2.1-1.5-.4-.4-.8-.7-1.1-1.1h-.3zm-1.1-1.1c-.1-.1-.1-.1 0 0-.3-.3-.6-.6-.8-.9-.5-.5-1-.9-1.6-1.2-.4-.3-.8-.4-1.3-.4-.4 0-.8 0-1.1.2-.5.2-.9.6-1.1 1-.2.3-.3.7-.3 1.1 0 .3 0 .6.1.9.1.5.4.9.8 1.2.5.4 1.1.5 1.7.5.5 0 1-.2 1.5-.5.6-.4 1.1-.8 1.6-1.3.1-.3.3-.5.5-.6zM13 12c.5.5 1 1 1.5 1.4.5.5 1.1.9 1.9 1 .4.1.8 0 1.2-.1.3-.1.6-.3.9-.5.4-.4.7-.9.8-1.4.1-.5 0-.9-.1-1.4-.3-.8-.8-1.2-1.7-1.4-.4-.1-.8-.1-1.2 0-.5.1-1 .4-1.4.7-.5.4-1 .8-1.4 1.2-.2.2-.4.3-.5.5z"/></svg></button> <button class="toggleSettings" aria-label="Settings" aria-haspopup="true" aria-expanded="${!!this._isSettingsOpen}" aria-controls="${this._identifier}-settings"><svg width="24" height="24" aria-hidden="true" focusable="false"><circle cx="12" cy="5.4" r="2.5"/><circle cx="12" cy="12" r="2.5"/><circle cx="12" cy="18.6" r="2.5"/></svg></button><div id="${this._identifier}-settings" class="popover" hidden><button class="convert" aria-label="Convert JSON animation to dotLottie format" hidden><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M17.016 17.016v-4.031h1.969v6h-12v3l-3.984-3.984 3.984-3.984v3h10.031zM6.984 6.984v4.031H5.015v-6h12v-3l3.984 3.984-3.984 3.984v-3H6.984z"/></svg> Convert to dotLottie</button> <button class="snapshot" aria-label="Download still image"><svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M16.8 10.8 12 15.6l-4.8-4.8h3V3.6h3.6v7.2h3zM12 15.6H3v4.8h18v-4.8h-9zm7.8 2.4h-2.4v-1.2h2.4V18z"/></svg> Download still image</button></div>`}</div>`;
441
- const togglePlay = this.shadow.querySelector('.togglePlay');
442
- if (togglePlay instanceof HTMLButtonElement) {
443
- togglePlay.onclick = this.togglePlay;
444
- }
445
- const stop = this.shadow.querySelector('.stop');
446
- if (stop instanceof HTMLButtonElement) {
447
- stop.onclick = this.stop;
448
- }
449
- const prev = this.shadow.querySelector('.prev');
450
- if (prev instanceof HTMLButtonElement) {
451
- prev.onclick = this.prev;
452
- }
453
- const next = this.shadow.querySelector('.next');
454
- if (next instanceof HTMLButtonElement) {
455
- next.onclick = this.next;
456
- }
457
- const seeker = this.shadow.querySelector('.seeker');
458
- if (seeker instanceof HTMLInputElement) {
459
- seeker.onchange = this._handleSeekChange;
460
- seeker.onmousedown = this._freeze;
461
- }
462
- if (!this.simple) {
463
- const toggleLoop = this.shadow.querySelector('.toggleLoop');
464
- if (toggleLoop instanceof HTMLButtonElement) {
465
- toggleLoop.onclick = this.toggleLoop;
466
- }
467
- const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
468
- if (toggleBoomerang instanceof HTMLButtonElement) {
469
- toggleBoomerang.onclick = this.toggleBoomerang;
470
- }
471
- const convert = this.shadow.querySelector('.convert');
472
- if (convert instanceof HTMLButtonElement) {
473
- convert.onclick = this.convert;
474
- }
475
- const snapshot = this.shadow.querySelector('.snapshot');
476
- if (snapshot instanceof HTMLButtonElement) {
477
- snapshot.onclick = ()=>this.snapshot(true);
478
- }
479
- const toggleSettings = this.shadow.querySelector('.toggleSettings');
480
- if (toggleSettings instanceof HTMLButtonElement) {
481
- toggleSettings.onclick = this._handleSettingsClick;
482
- toggleSettings.onblur = this._handleBlur;
483
- }
484
- }
485
- }
486
-
487
- /**
488
- * Credit to:
489
- * @author Leonardo Favre <https://github.com/leofavre/observed-properties>
490
- * @description Enhanced HTML element with reactive state handlers
491
- */ /* eslint-disable @typescript-eslint/ban-ts-comment */ const UPDATE_ON_CONNECTED = Symbol('UPDATE_ON_CONNECTED');
492
- if (isServer()) {
493
- // Mock HTMLElement for server-side rendering
494
- // @ts-ignore
495
- global.HTMLElement = class EmptyHTMLElement {
496
- };
497
- }
498
- /**
499
- * HTMLElement enhanced to track property changes
500
- */ class EnhancedElement extends HTMLElement {
501
- constructor(){
502
- super();
503
- // @ts-ignore
504
- const { observedProperties = [] } = this.constructor;
505
- if (UPDATE_ON_CONNECTED in this) {
506
- this[UPDATE_ON_CONNECTED] = [];
507
- }
508
- if ('propertyChangedCallback' in this && typeof this.propertyChangedCallback === 'function') {
509
- for (const propName of observedProperties){
510
- const initialValue = this[propName], CACHED_VALUE = Symbol(propName);
511
- // @ts-ignore
512
- this[CACHED_VALUE] = initialValue;
513
- Object.defineProperty(this, propName, {
514
- get () {
515
- return this[CACHED_VALUE];
516
- },
517
- set (value) {
518
- const oldValue = this[CACHED_VALUE];
519
- this[CACHED_VALUE] = value;
520
- this.propertyChangedCallback(propName, oldValue, value);
521
- }
522
- });
523
- if (typeof initialValue !== 'undefined') {
524
- if (UPDATE_ON_CONNECTED in this && Array.isArray(this[UPDATE_ON_CONNECTED])) {
525
- this[UPDATE_ON_CONNECTED].push(propName);
526
- }
527
- }
528
- }
529
- }
530
- }
531
- connectedCallback() {
532
- let arr = [];
533
- if (UPDATE_ON_CONNECTED in this && Array.isArray(this[UPDATE_ON_CONNECTED])) {
534
- arr = this[UPDATE_ON_CONNECTED];
535
- }
536
- for (const propName of arr){
537
- if (!('propertyChangedCallback' in this) || typeof this.propertyChangedCallback !== 'function') {
538
- continue;
539
- }
540
- if (propName in this) {
541
- this.propertyChangedCallback(propName, undefined, this[propName]);
542
- }
543
- }
544
- }
545
- }
546
-
547
- var name="@aarsteinmedia/dotlottie-player";var pkg = {name:name};
548
-
549
- var css_248z = "* {\n box-sizing: border-box;\n}\n\n:host {\n --lottie-player-toolbar-height: 35px;\n --lottie-player-toolbar-background-color: #FFF;\n --lottie-player-toolbar-icon-color: #000;\n --lottie-player-toolbar-icon-hover-color: #000;\n --lottie-player-toolbar-icon-active-color: #4285f4;\n --lottie-player-seeker-track-color: rgb(0 0 0 / 20%);\n --lottie-player-seeker-thumb-color: #4285f4;\n --lottie-player-seeker-display: block;\n\n width: 100%;\n height: 100%;\n\n &:not([hidden]) {\n display: block;\n }\n\n .main {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n\n .animation {\n width: 100%;\n height: 100%;\n display: flex;\n margin: 0;\n padding: 0;\n }\n\n [data-controls=\"true\"] .animation {\n height: calc(100% - 35px);\n }\n\n .animation-container {\n position: relative;\n }\n\n .popover {\n position: absolute;\n right: 5px;\n bottom: 40px;\n background-color: var(--lottie-player-toolbar-background-color);\n border-radius: 5px;\n padding: 10px 15px;\n border: solid 2px var(--lottie-player-toolbar-icon-color);\n animation: fade-in .2s ease-in-out;\n\n &::before {\n content: \"\";\n right: 10px;\n border: 7px solid transparent;\n margin-right: -7px;\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none;\n top: 100%;\n border-top-color: var(--lottie-player-toolbar-icon-color);\n }\n }\n\n .error {\n display: flex;\n margin: auto;\n justify-content: center;\n height: 100%;\n align-items: center;\n\n & svg {\n width: 100%;\n height: auto;\n }\n }\n\n .toolbar {\n display: flex;\n place-items: center center;\n background: var(--lottie-player-toolbar-background-color);\n margin: 0;\n height: 35px;\n padding: 5px;\n border-radius: 5px;\n gap: 5px;\n\n &.has-error {\n pointer-events: none;\n opacity: .5;\n }\n\n & button {\n cursor: pointer;\n fill: var(--lottie-player-toolbar-icon-color);\n color: var(--lottie-player-toolbar-icon-color);\n background: none;\n border: 0;\n padding: 0;\n outline: 0;\n height: 100%;\n margin: 0;\n align-items: center;\n gap: 5px;\n opacity: .9;\n\n &:not([hidden]) {\n display: flex;\n }\n\n &:hover {\n opacity: 1;\n }\n\n &[data-active=\"true\"] {\n opacity: 1;\n fill: var(--lottie-player-toolbar-icon-active-color);\n }\n\n &:disabled {\n opacity: .5;\n }\n\n &:focus {\n outline: 0;\n }\n\n & svg {\n pointer-events: none;\n\n >* {\n fill: inherit;\n }\n }\n\n &.disabled svg {\n display: none;\n }\n }\n }\n\n .progress-container {\n position: relative;\n width: 100%;\n\n &.simple {\n margin-right: 12px;\n }\n }\n\n .seeker {\n appearance: none;\n outline: none;\n width: 100%;\n height: 20px;\n border-radius: 3px;\n border: 0;\n cursor: pointer;\n background-color: transparent;\n\n display: var(--lottie-player-seeker-display);\n color: var(--lottie-player-seeker-thumb-color);\n margin: 0;\n padding: 7.5px 0;\n position: relative;\n z-index: 1;\n\n &::-webkit-slider-runnable-track,\n &::-webkit-slider-thumb {\n appearance: none;\n outline: none;\n }\n\n &::-webkit-slider-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n border: 0;\n background-color: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -webkit-transition: transform .2s ease-in-out;\n transition: transform .2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-webkit-slider-thumb,\n &:focus::-webkit-slider-thumb {\n transform: scale(1);\n }\n\n &::-moz-range-progress {\n background-color: var(--lottie-player-seeker-thumb-color);\n height: 5px;\n border-radius: 3px;\n }\n\n &::-moz-range-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background-color: var(--lottie-player-seeker-thumb-color);\n border: 0;\n cursor: pointer;\n -moz-transition: transform .2s ease-in-out;\n transition: transform .2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-moz-range-thumb,\n &:focus::-moz-range-thumb {\n transform: scale(1);\n }\n\n &::-ms-track {\n width: 100%;\n height: 5px;\n cursor: pointer;\n background: transparent;\n border-color: transparent;\n color: transparent;\n }\n\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n border-radius: 3px;\n }\n\n &::-ms-fill-lower {\n background-color: var(--lottie-player-seeker-thumb-color);\n border-radius: 3px;\n }\n\n &::-ms-thumb {\n border: 0;\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -ms-transition: transform .2s ease-in-out;\n transition: transform .2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-ms-thumb {\n transform: scale(1);\n }\n\n &:focus {\n &::-ms-thumb {\n transform: scale(1);\n }\n\n &::-ms-fill-lower,\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n }\n }\n }\n\n & progress {\n appearance: none;\n outline: none;\n position: absolute;\n width: 100%;\n height: 5px;\n border-radius: 3px;\n border: 0;\n top: 0;\n left: 0;\n margin: 7.5px 0;\n background-color: var(--lottie-player-seeker-track-color);\n pointer-events: none;\n\n &::-webkit-progress-inner-element {\n border-radius: 3px;\n overflow: hidden;\n }\n\n &::-webkit-slider-runnable-track {\n background-color: transparent;\n }\n\n &::-webkit-progress-value {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n }\n\n ::-moz-progress-bar {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n\n}\n\n@keyframes fade-in {\n 0% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --lottie-player-toolbar-background-color: #000;\n --lottie-player-toolbar-icon-color: #FFF;\n --lottie-player-toolbar-icon-hover-color: #FFF;\n --lottie-player-seeker-track-color: rgb(255 255 255 / 60%);\n }\n}\n";
550
-
551
- /**
552
- * dotLottie Player Web Component
553
- * @export
554
- * @class DotLottiePlayer
555
- * @extends { EnhancedElement }
556
- * @description Web Component for playing Lottie animations in your web app.
557
- */ class DotLottiePlayer extends EnhancedElement {
558
- constructor(){
559
- super(), this._renderControls = renderControls, this._render = renderPlayer, /**
560
- * Multi-animation settings
561
- */ this._multiAnimationSettings = [], /**
562
- * Animation Container
563
- */ this._container = null, /**
564
- * @state
565
- * Player state
566
- */ this.playerState = PlayerState.Loading, /**
567
- * @state
568
- * Whether settings toolbar is open
569
- */ this._isSettingsOpen = false, /**
570
- * @state
571
- * Seeker
572
- */ this._seeker = 0, /**
573
- * @state
574
- * Which animation to show, if several
575
- */ this._currentAnimation = 0, this._lottieInstance = null, this._identifier = this.id || useId('dotlottie'), this._errorMessage = 'Something went wrong', this._isBounce = false, this._isDotLottie = false, this._playerState = {
576
- count: 0,
577
- loaded: false,
578
- prev: PlayerState.Loading,
579
- scrollTimeout: null,
580
- scrollY: 0,
581
- visible: false
582
- }, /**
583
- * Handle settings click event
584
- */ this._handleSettingsClick = ({ target })=>{
585
- this._toggleSettings();
586
- // Because Safari does not add focus on click, we need to add it manually, so the onblur event will fire
587
- if (target instanceof HTMLElement) {
588
- target.focus();
589
- }
590
- };
591
- this._complete = this._complete.bind(this);
592
- this._dataFailed = this._dataFailed.bind(this);
593
- this._dataReady = this._dataReady.bind(this);
594
- this._DOMLoaded = this._DOMLoaded.bind(this);
595
- this._enterFrame = this._enterFrame.bind(this);
596
- this._freeze = this._freeze.bind(this);
597
- this._handleBlur = this._handleBlur.bind(this);
598
- this._handleScroll = this._handleScroll.bind(this);
599
- this._handleSeekChange = this._handleSeekChange.bind(this);
600
- this._handleWindowBlur = this._handleWindowBlur.bind(this);
601
- this._loopComplete = this._loopComplete.bind(this);
602
- this._mouseEnter = this._mouseEnter.bind(this);
603
- this._mouseLeave = this._mouseLeave.bind(this);
604
- this._onVisibilityChange = this._onVisibilityChange.bind(this);
605
- this._switchInstance = this._switchInstance.bind(this);
606
- this.togglePlay = this.togglePlay.bind(this);
607
- this.stop = this.stop.bind(this);
608
- this.prev = this.prev.bind(this);
609
- this.next = this.next.bind(this);
610
- this._renderControls = this._renderControls.bind(this);
611
- this.snapshot = this.snapshot.bind(this);
612
- this.toggleLoop = this.toggleLoop.bind(this);
613
- this.toggleBoomerang = this.toggleBoomerang.bind(this);
614
- this.convert = this.convert.bind(this);
615
- this.destroy = this.destroy.bind(this);
616
- this.template = document.createElement('template');
617
- this.shadow = this.attachShadow({
618
- mode: 'open'
619
- });
620
- }
621
- /**
622
- * Initialize everything on component first render
623
- */ async connectedCallback() {
624
- super.connectedCallback();
625
- this._render();
626
- this._container = this.shadow.querySelector('.animation');
627
- this._renderControls();
628
- // Add listener for Visibility API's change event.
629
- if (typeof document.hidden !== 'undefined') {
630
- document.addEventListener('visibilitychange', this._onVisibilityChange);
631
- }
632
- // Add intersection observer for detecting component being out-of-view.
633
- this._addIntersectionObserver();
634
- // Setup lottie player
635
- await this.load(this.src);
636
- this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
637
- }
638
- /**
639
- * Cleanup on component destroy
640
- */ disconnectedCallback() {
641
- // Remove intersection observer for detecting component being out-of-view
642
- if (this._intersectionObserver) {
643
- this._intersectionObserver.disconnect();
644
- this._intersectionObserver = undefined;
645
- }
646
- // Destroy the animation instance
647
- if (this._lottieInstance) {
648
- this._lottieInstance.destroy();
649
- }
650
- // Remove the attached Visibility API's change event listener
651
- document.removeEventListener('visibilitychange', this._onVisibilityChange);
652
- }
653
- /**
654
- * Attributes to observe
655
- */ static get observedAttributes() {
656
- return [
657
- 'animateOnScroll',
658
- 'autoplay',
659
- 'controls',
660
- 'direction',
661
- 'hover',
662
- 'loop',
663
- 'mode',
664
- 'speed',
665
- 'src',
666
- 'subframe'
667
- ];
668
- }
669
- /**
670
- * Runs when the value of an attribute is changed on the component
671
- */ async attributeChangedCallback(name, _oldValue, value) {
672
- if (!this._lottieInstance) {
673
- return;
674
- }
675
- if (name === 'animateOnScroll') {
676
- if (value === '' || Boolean(value)) {
677
- this._lottieInstance.autoplay = false;
678
- addEventListener('scroll', this._handleScroll, {
679
- capture: true,
680
- passive: true
681
- });
682
- return;
683
- }
684
- removeEventListener('scroll', this._handleScroll, true);
685
- }
686
- if (name === 'autoplay') {
687
- if (this.animateOnScroll) {
688
- return;
689
- }
690
- if (value === '' || Boolean(value)) {
691
- this.play();
692
- return;
693
- }
694
- this.stop();
695
- }
696
- if (name === 'controls') {
697
- this._renderControls();
698
- }
699
- if (name === 'direction') {
700
- if (Number(value) === -1) {
701
- return this.setDirection(-1);
702
- }
703
- this.setDirection(1);
704
- }
705
- if (name === 'hover' && this._container) {
706
- if (value === '' || Boolean(value)) {
707
- this._container.addEventListener('mouseenter', this._mouseEnter);
708
- this._container.addEventListener('mouseleave', this._mouseLeave);
709
- return;
710
- }
711
- this._container.removeEventListener('mouseenter', this._mouseEnter);
712
- this._container.removeEventListener('mouseleave', this._mouseLeave);
713
- }
714
- if (name === 'loop') {
715
- const toggleLoop = this.shadow.querySelector('.toggleLoop');
716
- if (toggleLoop instanceof HTMLButtonElement) {
717
- toggleLoop.dataset.active = value;
718
- }
719
- this.setLoop(value === '' || Boolean(value));
720
- }
721
- if (name === 'mode') {
722
- const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
723
- if (toggleBoomerang instanceof HTMLButtonElement) {
724
- toggleBoomerang.dataset.active = (value === PlayMode.Bounce).toString();
725
- }
726
- this._isBounce = value === PlayMode.Bounce;
727
- }
728
- if (name === 'speed') {
729
- const val = Number(value);
730
- if (val && !isNaN(val)) {
731
- this.setSpeed(val);
732
- }
733
- }
734
- if (name === 'src') {
735
- await this.load(value);
736
- }
737
- if (name === 'subframe') {
738
- this.setSubframe(value === '' || Boolean(value));
739
- }
740
- }
741
- static get observedProperties() {
742
- return [
743
- 'playerState',
744
- '_isSettingsOpen',
745
- '_seeker',
746
- '_currentAnimation',
747
- '_animations'
748
- ];
749
- }
750
- // name: string, oldValue: string, newValue: string
751
- propertyChangedCallback(name, _oldValue, value) {
752
- if (!this.shadow) {
753
- return;
754
- }
755
- const togglePlay = this.shadow.querySelector('.togglePlay'), stop = this.shadow.querySelector('.stop'), prev = this.shadow.querySelector('.prev'), next = this.shadow.querySelector('.next'), seeker = this.shadow.querySelector('.seeker'), progress = this.shadow.querySelector('progress'), popover = this.shadow.querySelector('.popover'), convert = this.shadow.querySelector('.convert');
756
- if (!(togglePlay instanceof HTMLButtonElement) || !(stop instanceof HTMLButtonElement) || !(next instanceof HTMLButtonElement) || !(prev instanceof HTMLButtonElement) || !(seeker instanceof HTMLInputElement) || !(progress instanceof HTMLProgressElement)) {
757
- return;
758
- }
759
- if (name === 'playerState') {
760
- togglePlay.dataset.active = (value === PlayerState.Playing || value === PlayerState.Paused).toString();
761
- stop.dataset.active = (value === PlayerState.Stopped).toString();
762
- if (value === PlayerState.Playing) {
763
- togglePlay.innerHTML = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M14.016 5.016H18v13.969h-3.984V5.016zM6 18.984V5.015h3.984v13.969H6z"/></svg>`;
764
- } else {
765
- togglePlay.innerHTML = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z"/></svg>`;
766
- }
767
- }
768
- if (name === '_seeker' && typeof value === 'number') {
769
- seeker.value = value.toString();
770
- seeker.ariaValueNow = value.toString();
771
- progress.value = value;
772
- }
773
- if (name === '_animations' && Array.isArray(value)) {
774
- if (this._currentAnimation + 1 < value.length) {
775
- next.hidden = false;
776
- }
777
- }
778
- if (name === '_currentAnimation' && typeof value === 'number') {
779
- if (value + 1 >= this._animations.length) {
780
- next.hidden = true;
781
- } else {
782
- next.hidden = false;
783
- }
784
- if (value) {
785
- prev.hidden = false;
786
- } else {
787
- prev.hidden = true;
788
- }
789
- }
790
- if (name === '_isSettingsOpen' && typeof value === 'boolean' && popover instanceof HTMLDivElement && convert instanceof HTMLButtonElement) {
791
- popover.hidden = !value;
792
- convert.hidden = this._isDotLottie;
793
- }
794
- }
795
- /**
796
- * Whether to trigger next frame with scroll
797
- */ set animateOnScroll(value) {
798
- this.setAttribute('animateOnScroll', (!!value).toString());
799
- }
800
- get animateOnScroll() {
801
- const val = this.getAttribute('animateOnScroll');
802
- if (val === 'true' || val === '' || val === '1') {
803
- return true;
804
- }
805
- return false;
806
- }
807
- /**
808
- * Autoplay
809
- */ set autoplay(value) {
810
- this.setAttribute('autoplay', (!!value).toString());
811
- }
812
- get autoplay() {
813
- const val = this.getAttribute('autoplay');
814
- if (val === 'true' || val === '' || val === '1') {
815
- return true;
816
- }
817
- return false;
818
- }
819
- /**
820
- * Background color
821
- */ set background(value) {
822
- this.setAttribute('background', value);
823
- }
824
- get background() {
825
- return this.getAttribute('background') || 'transparent';
826
- }
827
- /**
828
- * Show controls
829
- */ set controls(value) {
830
- this.setAttribute('controls', (!!value).toString());
831
- }
832
- get controls() {
833
- const val = this.getAttribute('controls');
834
- if (val === 'true' || val === '' || val === '1') {
835
- return true;
836
- }
837
- return false;
838
- }
839
- /**
840
- * Number of times to loop
841
- */ set count(value) {
842
- this.setAttribute('count', value.toString());
843
- }
844
- get count() {
845
- const val = this.getAttribute('count');
846
- if (val) {
847
- return Number(val);
848
- }
849
- return 0;
850
- }
851
- /**
852
- * Description for screen readers
853
- */ set description(value) {
854
- if (value) {
855
- this.setAttribute('description', value);
856
- }
857
- }
858
- get description() {
859
- return this.getAttribute('description');
860
- }
861
- /**
862
- * Direction of animation
863
- */ set direction(value) {
864
- this.setAttribute('direction', value.toString());
865
- }
866
- get direction() {
867
- const val = Number(this.getAttribute('direction'));
868
- if (val === -1) {
869
- return val;
870
- }
871
- return 1;
872
- }
873
- /**
874
- * Whether to play on mouseover
875
- */ set hover(value) {
876
- this.setAttribute('hover', value.toString());
877
- }
878
- get hover() {
879
- const val = this.getAttribute('hover');
880
- if (val === 'true' || val === '' || val === '1') {
881
- return true;
882
- }
883
- return false;
884
- }
885
- /**
886
- * Pause between loop intrations, in miliseconds
887
- */ set intermission(value) {
888
- this.setAttribute('intermission', value.toString());
889
- }
890
- get intermission() {
891
- const val = Number(this.getAttribute('intermission'));
892
- if (!isNaN(val)) {
893
- return val;
894
- }
895
- return 0;
896
- }
897
- /**
898
- * Loop animation
899
- */ set loop(value) {
900
- this.setAttribute('loop', (!!value).toString());
901
- }
902
- get loop() {
903
- const val = this.getAttribute('loop');
904
- if (val === 'true' || val === '' || val === '1') {
905
- return true;
906
- }
907
- return false;
908
- }
909
- /**
910
- * Play mode
911
- */ set mode(value) {
912
- this.setAttribute('mode', value.toString());
913
- }
914
- get mode() {
915
- const val = this.getAttribute('mode');
916
- if (val === PlayMode.Bounce) {
917
- return val;
918
- }
919
- return PlayMode.Normal;
920
- }
921
- /**
922
- * Resizing to container
923
- */ set objectfit(value) {
924
- this.setAttribute('objectfit', value);
925
- }
926
- get objectfit() {
927
- const val = this.getAttribute('objectfit');
928
- if (val && Object.values(ObjectFit).includes(val)) {
929
- return val;
930
- }
931
- return ObjectFit.Contain;
932
- }
933
- /**
934
- * Resizing to container (Deprecated)
935
- */ set preserveAspectRatio(value) {
936
- this.setAttribute('preserveAspectRatio', value || PreserveAspectRatio.Contain);
937
- }
938
- get preserveAspectRatio() {
939
- const val = this.getAttribute('preserveAspectRatio');
940
- if (val && Object.values(PreserveAspectRatio).includes(val)) {
941
- return val;
942
- }
943
- return null;
944
- }
945
- /**
946
- * Renderer to use: svg, canvas or html
947
- */ set renderer(value) {
948
- this.setAttribute('renderer', value);
949
- }
950
- get renderer() {
951
- const val = this.getAttribute('renderer');
952
- if (val === 'canvas' || val === 'html') {
953
- return val;
954
- }
955
- return 'svg';
956
- }
957
- /**
958
- * Hide advanced controls
959
- */ set simple(value) {
960
- this.setAttribute('simple', value.toString());
961
- }
962
- get simple() {
963
- const val = this.getAttribute('simple');
964
- if (val === 'true' || val === '' || val === '1') {
965
- return true;
966
- }
967
- return false;
968
- }
969
- /**
970
- * Speed
971
- */ set speed(value) {
972
- this.setAttribute('speed', value?.toString());
973
- }
974
- get speed() {
975
- const val = this.getAttribute('speed');
976
- if (val !== null && !isNaN(Number(val))) {
977
- return Number(val);
978
- }
979
- return 1;
980
- }
981
- /**
982
- * Source, either path or JSON string
983
- */ set src(value) {
984
- this.setAttribute('src', value || '');
985
- }
986
- get src() {
987
- return this.getAttribute('src');
988
- }
989
- /**
990
- * Subframe
991
- */ set subframe(value) {
992
- this.setAttribute('subframe', (!!value).toString());
993
- }
994
- get subframe() {
995
- const val = this.getAttribute('subframe');
996
- if (val === 'true' || val === '' || val === '1') {
997
- return true;
998
- }
999
- return false;
1000
- }
1001
- /**
1002
- * Get Multi-animation settings
1003
- * @returns { AnimationSettings[] }
1004
- */ getMultiAnimationSettings() {
1005
- return this._multiAnimationSettings;
1006
- }
1007
- /**
1008
- * Set Multi-animation settings
1009
- * @param { AnimationSettings[] } settings
1010
- */ setMultiAnimationSettings(settings) {
1011
- this._multiAnimationSettings = settings;
1012
- }
1013
- /**
1014
- * Set playback segment
1015
- * @param { AnimationSegment } settings
1016
- */ setSegment(segment) {
1017
- this._segment = segment;
1018
- }
1019
- /**
1020
- * Get playback segment
1021
- * @returns { AnimationSegment }
1022
- */ getSegment() {
1023
- return this._segment;
1024
- }
1025
- /**
1026
- * Get options from props
1027
- * @returns { AnimationConfig }
1028
- */ _getOptions() {
1029
- if (!this._container) {
1030
- throw new Error('Container not rendered');
1031
- }
1032
- const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this._multiAnimationSettings?.length ? this._multiAnimationSettings?.[this._currentAnimation] : undefined, currentAnimationManifest = this._manifest.animations?.[this._currentAnimation];
1033
- // Loop
1034
- let loop = !!this.loop;
1035
- if (currentAnimationManifest.loop !== undefined && this.loop === undefined) {
1036
- loop = !!currentAnimationManifest.loop;
1037
- }
1038
- if (currentAnimationSettings?.loop !== undefined) {
1039
- loop = !!currentAnimationSettings.loop;
1040
- }
1041
- // Autoplay
1042
- let autoplay = !!this.autoplay;
1043
- if (currentAnimationManifest.autoplay !== undefined && this.autoplay === undefined) {
1044
- autoplay = !!currentAnimationManifest.autoplay;
1045
- }
1046
- if (currentAnimationSettings?.autoplay !== undefined) {
1047
- autoplay = !!currentAnimationSettings.autoplay;
1048
- }
1049
- if (this.animateOnScroll) {
1050
- autoplay = false;
1051
- }
1052
- // Segment
1053
- let initialSegment = this._segment;
1054
- if (this._segment?.every((val)=>val > 0)) {
1055
- initialSegment = [
1056
- this._segment[0] - 1,
1057
- this._segment[1] - 1
1058
- ];
1059
- }
1060
- if (this._segment?.some((val)=>val < 0)) {
1061
- initialSegment = undefined;
1062
- }
1063
- const options = {
1064
- autoplay,
1065
- container: this._container,
1066
- initialSegment,
1067
- loop,
1068
- renderer: this.renderer,
1069
- rendererSettings: {
1070
- imagePreserveAspectRatio: preserveAspectRatio
1071
- }
1072
- };
1073
- switch(this.renderer){
1074
- case 'svg':
1075
- options.rendererSettings = {
1076
- ...options.rendererSettings,
1077
- hideOnTransparent: true,
1078
- preserveAspectRatio,
1079
- progressiveLoad: true
1080
- };
1081
- break;
1082
- case 'canvas':
1083
- options.rendererSettings = {
1084
- ...options.rendererSettings,
1085
- clearCanvas: true,
1086
- preserveAspectRatio,
1087
- progressiveLoad: true
1088
- };
1089
- break;
1090
- case 'html':
1091
- options.rendererSettings = {
1092
- ...options.rendererSettings,
1093
- hideOnTransparent: true
1094
- };
1095
- }
1096
- return options;
1097
- }
1098
- /**
1099
- * Add IntersectionObserver
1100
- */ _addIntersectionObserver() {
1101
- if (!this._container || this._intersectionObserver || !('IntersectionObserver' in window)) {
1102
- return;
1103
- }
1104
- this._intersectionObserver = new IntersectionObserver((entries)=>{
1105
- for (const entry of entries){
1106
- if (!entry.isIntersecting || document.hidden) {
1107
- if (this.playerState === PlayerState.Playing) {
1108
- this._freeze();
1109
- }
1110
- this._playerState.visible = false;
1111
- continue;
1112
- }
1113
- if (!this.animateOnScroll && this.playerState === PlayerState.Frozen) {
1114
- this.play();
1115
- }
1116
- if (!this._playerState.scrollY) {
1117
- this._playerState.scrollY = scrollY;
1118
- }
1119
- this._playerState.visible = true;
1120
- }
1121
- });
1122
- this._intersectionObserver.observe(this._container);
1123
- }
1124
- /**
1125
- * Initialize Lottie Web player
1126
- */ async load(src) {
1127
- if (!this.shadowRoot || !src) {
1128
- return;
1129
- }
1130
- // Load the resource
1131
- try {
1132
- const { animations, isDotLottie, manifest } = await getAnimationData(src);
1133
- if (!animations || animations.some((animation)=>!this._isLottie(animation))) {
1134
- throw new Error('Broken or corrupted file');
1135
- }
1136
- this._isBounce = this.mode === PlayMode.Bounce;
1137
- if (this._multiAnimationSettings?.length) {
1138
- if (this._multiAnimationSettings[this._currentAnimation]?.mode) {
1139
- this._isBounce = this._multiAnimationSettings[this._currentAnimation].mode === PlayMode.Bounce;
1140
- }
1141
- }
1142
- this._isDotLottie = !!isDotLottie;
1143
- this._animations = animations;
1144
- this._manifest = manifest ?? {
1145
- animations: [
1146
- {
1147
- autoplay: !this.animateOnScroll && this.autoplay,
1148
- direction: this.direction,
1149
- id: useId(),
1150
- loop: this.loop,
1151
- mode: this.mode,
1152
- speed: this.speed
1153
- }
1154
- ]
1155
- };
1156
- // Clear previous animation, if any
1157
- if (this._lottieInstance) {
1158
- this._lottieInstance.destroy();
1159
- }
1160
- this.playerState = PlayerState.Stopped;
1161
- if (!this.animateOnScroll && (this.autoplay || this._multiAnimationSettings?.[this._currentAnimation]?.autoplay)) {
1162
- this.playerState = PlayerState.Playing;
1163
- }
1164
- // Initialize lottie player and load animation
1165
- this._lottieInstance = Lottie__namespace.default.loadAnimation({
1166
- ...this._getOptions(),
1167
- animationData: animations[this._currentAnimation]
1168
- });
1169
- } catch (err) {
1170
- this._errorMessage = handleErrors(err).message;
1171
- this.playerState = PlayerState.Error;
1172
- this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1173
- return;
1174
- }
1175
- this._addEventListeners();
1176
- const speed = this._multiAnimationSettings?.[this._currentAnimation]?.speed ?? this.speed ?? this._manifest.animations[this._currentAnimation].speed, direction = this._multiAnimationSettings?.[this._currentAnimation]?.direction ?? this.direction ?? this._manifest.animations[this._currentAnimation].direction ?? 1;
1177
- // Set initial playback speed and direction
1178
- this._lottieInstance.setSpeed(speed);
1179
- this._lottieInstance.setDirection(direction);
1180
- this._lottieInstance.setSubframe(!!this.subframe);
1181
- // Start playing if autoplay is enabled
1182
- if (this.autoplay || this.animateOnScroll) {
1183
- if (this.direction === -1) {
1184
- this.seek('99%');
1185
- }
1186
- if (!('IntersectionObserver' in window)) {
1187
- if (!this.animateOnScroll) {
1188
- this.play();
1189
- }
1190
- this._playerState.visible = true;
1191
- }
1192
- this._addIntersectionObserver();
1193
- }
1194
- }
1195
- /**
1196
- * Get Lottie Manifest
1197
- */ getManifest() {
1198
- return this._manifest;
1199
- }
1200
- /**
1201
- * Toggle event listeners
1202
- */ _toggleEventListeners(action) {
1203
- const method = action === 'add' ? 'addEventListener' : 'removeEventListener';
1204
- if (this._lottieInstance) {
1205
- this._lottieInstance[method]('enterFrame', this._enterFrame);
1206
- this._lottieInstance[method]('complete', this._complete);
1207
- this._lottieInstance[method]('loopComplete', this._loopComplete);
1208
- this._lottieInstance[method]('DOMLoaded', this._DOMLoaded);
1209
- this._lottieInstance[method]('data_ready', this._dataReady);
1210
- this._lottieInstance[method]('data_failed', this._dataFailed);
1211
- }
1212
- if (this._container && this.hover) {
1213
- this._container[method]('mouseenter', this._mouseEnter);
1214
- this._container[method]('mouseleave', this._mouseLeave);
1215
- }
1216
- window[method]('focus', this._handleWindowBlur, {
1217
- capture: false,
1218
- passive: true
1219
- });
1220
- window[method]('blur', this._handleWindowBlur, {
1221
- capture: false,
1222
- passive: true
1223
- });
1224
- if (this.animateOnScroll) {
1225
- window[method]('scroll', this._handleScroll, {
1226
- capture: true,
1227
- passive: true
1228
- });
1229
- }
1230
- }
1231
- /**
1232
- * Add event listeners
1233
- */ _addEventListeners() {
1234
- this._toggleEventListeners('add');
1235
- }
1236
- /**
1237
- * Remove event listeners
1238
- */ _removeEventListeners() {
1239
- this._toggleEventListeners('remove');
1240
- }
1241
- _loopComplete() {
1242
- if (!this._lottieInstance) {
1243
- return;
1244
- }
1245
- const { playDirection, // firstFrame,
1246
- totalFrames } = this._lottieInstance, inPoint = this._segment ? this._segment[0] : 0, outPoint = this._segment ? this._segment[0] : totalFrames;
1247
- if (this.count) {
1248
- if (this._isBounce) {
1249
- this._playerState.count += 0.5;
1250
- } else {
1251
- this._playerState.count += 1;
1252
- }
1253
- if (this._playerState.count >= this.count) {
1254
- this.setLoop(false);
1255
- this.playerState = PlayerState.Completed;
1256
- this.dispatchEvent(new CustomEvent(PlayerEvents.Complete));
1257
- return;
1258
- }
1259
- }
1260
- this.dispatchEvent(new CustomEvent(PlayerEvents.Loop));
1261
- if (this._isBounce) {
1262
- this._lottieInstance.goToAndStop(playDirection === -1 ? inPoint : outPoint * 0.99, true);
1263
- this._lottieInstance.setDirection(playDirection * -1);
1264
- return setTimeout(()=>{
1265
- if (!this.animateOnScroll) {
1266
- this._lottieInstance?.play();
1267
- }
1268
- }, this.intermission);
1269
- }
1270
- this._lottieInstance.goToAndStop(playDirection === -1 ? outPoint * 0.99 : inPoint, true);
1271
- return setTimeout(()=>{
1272
- if (!this.animateOnScroll) {
1273
- this._lottieInstance?.play();
1274
- }
1275
- }, this.intermission);
1276
- }
1277
- _enterFrame() {
1278
- if (!this._lottieInstance) {
1279
- return;
1280
- }
1281
- const { currentFrame, totalFrames } = this._lottieInstance;
1282
- this._seeker = Math.round(currentFrame / totalFrames * 100);
1283
- this.dispatchEvent(new CustomEvent(PlayerEvents.Frame, {
1284
- detail: {
1285
- frame: currentFrame,
1286
- seeker: this._seeker
1287
- }
1288
- }));
1289
- }
1290
- _complete() {
1291
- if (!this._lottieInstance) {
1292
- return;
1293
- }
1294
- if (this._animations.length > 1) {
1295
- if (this._multiAnimationSettings?.[this._currentAnimation + 1]?.autoplay) {
1296
- return this.next();
1297
- }
1298
- if (this.loop && this._currentAnimation === this._animations.length - 1) {
1299
- this._currentAnimation = 0;
1300
- return this._switchInstance();
1301
- }
1302
- }
1303
- const { currentFrame, totalFrames } = this._lottieInstance;
1304
- this._seeker = Math.round(currentFrame / totalFrames * 100);
1305
- this.playerState = PlayerState.Completed;
1306
- this.dispatchEvent(new CustomEvent(PlayerEvents.Complete, {
1307
- detail: {
1308
- frame: currentFrame,
1309
- seeker: this._seeker
1310
- }
1311
- }));
1312
- }
1313
- _DOMLoaded() {
1314
- this._playerState.loaded = true;
1315
- this.dispatchEvent(new CustomEvent(PlayerEvents.Ready));
1316
- }
1317
- _dataReady() {
1318
- this.dispatchEvent(new CustomEvent(PlayerEvents.Load));
1319
- }
1320
- _dataFailed() {
1321
- this.playerState = PlayerState.Error;
1322
- this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1323
- }
1324
- _handleWindowBlur({ type }) {
1325
- if (this.playerState === PlayerState.Playing && type === 'blur') {
1326
- this._freeze();
1327
- }
1328
- if (this.playerState === PlayerState.Frozen && type === 'focus') {
1329
- this.play();
1330
- }
1331
- }
1332
- /**
1333
- * Handle MouseEnter
1334
- */ _mouseEnter() {
1335
- if (this.hover && this.playerState !== PlayerState.Playing) {
1336
- this.play();
1337
- }
1338
- }
1339
- /**
1340
- * Handle MouseLeave
1341
- */ _mouseLeave() {
1342
- if (this.hover && this.playerState === PlayerState.Playing) {
1343
- this.stop();
1344
- }
1345
- }
1346
- /**
1347
- * Handle visibility change events
1348
- */ _onVisibilityChange() {
1349
- if (document.hidden && this.playerState === PlayerState.Playing) {
1350
- this._freeze();
1351
- return;
1352
- }
1353
- if (this.playerState === PlayerState.Frozen) {
1354
- this.play();
1355
- }
1356
- }
1357
- /**
1358
- * Handle scroll
1359
- */ _handleScroll() {
1360
- if (!this.animateOnScroll || !this._lottieInstance) {
1361
- return;
1362
- }
1363
- if (isServer()) {
1364
- console.warn('DotLottie: Scroll animations might not work properly in a Server Side Rendering context. Try to wrap this in a client component.');
1365
- return;
1366
- }
1367
- if (this._playerState.visible) {
1368
- if (this._playerState.scrollTimeout) {
1369
- clearTimeout(this._playerState.scrollTimeout);
1370
- }
1371
- this._playerState.scrollTimeout = setTimeout(()=>{
1372
- this.playerState = PlayerState.Paused;
1373
- }, 400);
1374
- const adjustedScroll = scrollY > this._playerState.scrollY ? scrollY - this._playerState.scrollY : this._playerState.scrollY - scrollY, clampedScroll = Math.min(Math.max(adjustedScroll / 3, 1), this._lottieInstance.totalFrames * 3), roundedScroll = clampedScroll / 3;
1375
- requestAnimationFrame(()=>{
1376
- if (roundedScroll < (this._lottieInstance?.totalFrames ?? 0)) {
1377
- this.playerState = PlayerState.Playing;
1378
- this._lottieInstance?.goToAndStop(roundedScroll, true);
1379
- } else {
1380
- this.playerState = PlayerState.Paused;
1381
- }
1382
- });
1383
- }
1384
- }
1385
- /**
1386
- * Handles click and drag actions on the progress track
1387
- * @param { Event & { HTMLInputElement } } event
1388
- */ _handleSeekChange({ target }) {
1389
- if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) {
1390
- return;
1391
- }
1392
- this.seek(Math.round(Number(target.value) / 100 * this._lottieInstance.totalFrames));
1393
- }
1394
- _isLottie(json) {
1395
- const mandatory = [
1396
- 'v',
1397
- 'ip',
1398
- 'op',
1399
- 'layers',
1400
- 'fr',
1401
- 'w',
1402
- 'h'
1403
- ];
1404
- return mandatory.every((field)=>Object.prototype.hasOwnProperty.call(json, field));
1405
- }
1406
- /**
1407
- * Creates a new dotLottie file, by combinig several animations
1408
- * @param { [ AnimationConfig ] } configs
1409
- * @param { string } fileName
1410
- * @param { boolean } shouldDownload Whether to trigger a download in the browser.
1411
- * If set to false the function returns an ArrayBuffer. Defaults to true.
1412
- *
1413
- */ async addAnimation(configs, fileName, shouldDownload = true) {
1414
- // Initialize meta object for animation, with fallbacks for
1415
- // when the method is called indepenently
1416
- const { animations = [], manifest = {
1417
- animations: this.src ? [
1418
- {
1419
- id: this._identifier
1420
- }
1421
- ] : []
1422
- } } = this.src ? await getAnimationData(this.src) : {};
1423
- try {
1424
- manifest.generator = pkg.name;
1425
- for (const config of configs){
1426
- const { url } = config, { animations: animationsToAdd } = await getAnimationData(url);
1427
- if (!animationsToAdd) {
1428
- throw new Error('No animation loaded');
1429
- }
1430
- if (manifest.animations.some(({ id })=>id === config.id)) {
1431
- throw new Error('Duplicate id for animation');
1432
- }
1433
- manifest.animations = [
1434
- ...manifest.animations,
1435
- {
1436
- id: config.id
1437
- }
1438
- ];
1439
- animations?.push(...animationsToAdd);
1440
- }
1441
- return {
1442
- result: await createDotLottie({
1443
- animations,
1444
- fileName,
1445
- manifest,
1446
- shouldDownload
1447
- }),
1448
- success: true
1449
- };
1450
- } catch (err) {
1451
- return {
1452
- error: handleErrors(err).message,
1453
- success: false
1454
- };
1455
- }
1456
- }
1457
- /**
1458
- * Returns the lottie-web instance used in the component
1459
- */ getLottie() {
1460
- return this._lottieInstance;
1461
- }
1462
- /**
1463
- * Play
1464
- */ async play() {
1465
- if (!this._lottieInstance) {
1466
- return;
1467
- }
1468
- if (this.playerState) {
1469
- this._playerState.prev = this.playerState;
1470
- }
1471
- try {
1472
- this._lottieInstance.play();
1473
- this.dispatchEvent(new CustomEvent(PlayerEvents.Play));
1474
- } finally{
1475
- this.playerState = PlayerState.Playing;
1476
- }
1477
- }
1478
- /**
1479
- * Pause
1480
- */ pause() {
1481
- if (!this._lottieInstance) {
1482
- return;
1483
- }
1484
- if (this.playerState) {
1485
- this._playerState.prev = this.playerState;
1486
- }
1487
- try {
1488
- this._lottieInstance.pause();
1489
- this.dispatchEvent(new CustomEvent(PlayerEvents.Pause));
1490
- } finally{
1491
- this.playerState = PlayerState.Paused;
1492
- }
1493
- }
1494
- /**
1495
- * Stop
1496
- */ stop() {
1497
- if (!this._lottieInstance) {
1498
- return;
1499
- }
1500
- if (this.playerState) {
1501
- this._playerState.prev = this.playerState;
1502
- }
1503
- this._playerState.count = 0;
1504
- try {
1505
- this._lottieInstance.stop();
1506
- this.dispatchEvent(new CustomEvent(PlayerEvents.Stop));
1507
- } finally{
1508
- this.playerState = PlayerState.Stopped;
1509
- }
1510
- }
1511
- /**
1512
- * Destroy animation and element
1513
- */ destroy() {
1514
- if (!this._lottieInstance) {
1515
- return;
1516
- }
1517
- this.playerState = PlayerState.Destroyed;
1518
- this._lottieInstance.destroy();
1519
- this._lottieInstance = null;
1520
- this.dispatchEvent(new CustomEvent(PlayerEvents.Destroyed));
1521
- this.remove();
1522
- document.removeEventListener('visibilitychange', this._onVisibilityChange);
1523
- }
1524
- /**
1525
- * Seek to a given frame
1526
- * @param { number | string } value Frame to seek to
1527
- */ seek(value) {
1528
- if (!this._lottieInstance) {
1529
- return;
1530
- }
1531
- // Extract frame number from either number or percentage value
1532
- const matches = value.toString().match(/^([0-9]+)(%?)$/);
1533
- if (!matches) {
1534
- return;
1535
- }
1536
- // Calculate and set the frame number
1537
- const frame = Math.round(matches[2] === '%' ? this._lottieInstance.totalFrames * Number(matches[1]) / 100 : Number(matches[1]));
1538
- // Set seeker to new frame number
1539
- this._seeker = frame;
1540
- // Send lottie player to the new frame
1541
- if (this.playerState === PlayerState.Playing || this.playerState === PlayerState.Frozen && this._playerState.prev === PlayerState.Playing) {
1542
- this._lottieInstance.goToAndPlay(frame, true);
1543
- this.playerState = PlayerState.Playing;
1544
- return;
1545
- }
1546
- this._lottieInstance.goToAndStop(frame, true);
1547
- this._lottieInstance.pause();
1548
- }
1549
- /**
1550
- * Snapshot and download the current frame as SVG
1551
- */ snapshot(shouldDownload = true, name = 'AM Lottie') {
1552
- try {
1553
- if (!this.shadowRoot) {
1554
- throw new Error('Unknown error');
1555
- }
1556
- // Get SVG element and serialize markup
1557
- const svgElement = this.shadowRoot.querySelector('.animation svg');
1558
- if (!svgElement) {
1559
- throw new Error('Could not retrieve animation from DOM');
1560
- }
1561
- const data = svgElement instanceof Node ? new XMLSerializer().serializeToString(svgElement) : null;
1562
- if (!data) {
1563
- throw new Error('Could not serialize SVG element');
1564
- }
1565
- if (shouldDownload) {
1566
- download(data, {
1567
- mimeType: 'image/svg+xml',
1568
- name: `${getFilename(this.src || name)}-${frameOutput(this._seeker)}.svg`
1569
- });
1570
- }
1571
- return data;
1572
- } catch (err) {
1573
- console.error(err);
1574
- return null;
1575
- }
1576
- }
1577
- /**
1578
- * Toggles subframe, for more smooth animations
1579
- * @param { boolean } value Whether animation uses subframe
1580
- */ setSubframe(value) {
1581
- if (!this._lottieInstance) {
1582
- return;
1583
- }
1584
- this._lottieInstance.setSubframe(value);
1585
- }
1586
- /**
1587
- * Dynamically set count for loops
1588
- */ setCount(value) {
1589
- this.count = value;
1590
- }
1591
- /**
1592
- * Freeze animation.
1593
- * This internal state pauses animation and is used to differentiate between
1594
- * user requested pauses and component instigated pauses.
1595
- */ _freeze() {
1596
- if (!this._lottieInstance) {
1597
- return;
1598
- }
1599
- if (this.playerState) {
1600
- this._playerState.prev = this.playerState;
1601
- }
1602
- try {
1603
- this._lottieInstance.pause();
1604
- this.dispatchEvent(new CustomEvent(PlayerEvents.Freeze));
1605
- } finally{
1606
- this.playerState = PlayerState.Frozen;
1607
- }
1608
- }
1609
- /**
1610
- * Reload animation
1611
- */ async reload() {
1612
- if (!this._lottieInstance || !this.src) {
1613
- return;
1614
- }
1615
- this._lottieInstance.destroy();
1616
- await this.load(this.src);
1617
- }
1618
- /**
1619
- * Set animation playback speed
1620
- * @param { number } value Playback speed
1621
- */ setSpeed(value = 1) {
1622
- if (!this._lottieInstance) {
1623
- return;
1624
- }
1625
- this._lottieInstance.setSpeed(value);
1626
- }
1627
- /**
1628
- * Animation play direction
1629
- * @param { AnimationDirection } value Animation direction
1630
- */ setDirection(value) {
1631
- if (!this._lottieInstance) {
1632
- return;
1633
- }
1634
- this._lottieInstance.setDirection(value);
1635
- }
1636
- /**
1637
- * Set loop
1638
- * @param { boolean } value
1639
- */ setLoop(value) {
1640
- if (!this._lottieInstance) {
1641
- return;
1642
- }
1643
- this._lottieInstance.setLoop(value);
1644
- }
1645
- /**
1646
- * Toggle playing state
1647
- */ togglePlay() {
1648
- if (!this._lottieInstance) {
1649
- return;
1650
- }
1651
- const { currentFrame, playDirection, totalFrames } = this._lottieInstance;
1652
- if (this.playerState === PlayerState.Playing) {
1653
- return this.pause();
1654
- }
1655
- if (this.playerState !== PlayerState.Completed) {
1656
- return this.play();
1657
- }
1658
- this.playerState = PlayerState.Playing;
1659
- if (this._isBounce) {
1660
- this.setDirection(playDirection * -1);
1661
- return this._lottieInstance.goToAndPlay(currentFrame, true);
1662
- }
1663
- if (playDirection === -1) {
1664
- return this._lottieInstance.goToAndPlay(totalFrames, true);
1665
- }
1666
- return this._lottieInstance.goToAndPlay(0, true);
1667
- }
1668
- /**
1669
- * Toggle loop
1670
- */ toggleLoop() {
1671
- const val = !this.loop;
1672
- this.loop = val;
1673
- this.setLoop(val);
1674
- }
1675
- /**
1676
- * Toggle Boomerang
1677
- */ toggleBoomerang() {
1678
- const curr = this._multiAnimationSettings?.[this._currentAnimation];
1679
- if (curr?.mode !== undefined) {
1680
- if (curr.mode === PlayMode.Normal) {
1681
- curr.mode = PlayMode.Bounce;
1682
- this._isBounce = true;
1683
- return;
1684
- }
1685
- curr.mode = PlayMode.Normal;
1686
- this._isBounce = false;
1687
- return;
1688
- }
1689
- if (this.mode === PlayMode.Normal) {
1690
- this.mode = PlayMode.Bounce;
1691
- this._isBounce = true;
1692
- return;
1693
- }
1694
- this.mode = PlayMode.Normal;
1695
- this._isBounce = false;
1696
- }
1697
- /**
1698
- * Toggle show Settings
1699
- */ _toggleSettings(flag) {
1700
- if (flag === undefined) {
1701
- this._isSettingsOpen = !this._isSettingsOpen;
1702
- return;
1703
- }
1704
- this._isSettingsOpen = flag;
1705
- }
1706
- /**
1707
- * Handle blur
1708
- */ _handleBlur() {
1709
- setTimeout(()=>this._toggleSettings(false), 200);
1710
- }
1711
- _switchInstance(isPrevious = false) {
1712
- // Bail early if there is not animation to play
1713
- if (!this._animations[this._currentAnimation]) {
1714
- return;
1715
- }
1716
- try {
1717
- // Clear previous animation
1718
- if (this._lottieInstance) {
1719
- this._lottieInstance.destroy();
1720
- }
1721
- // Re-initialize lottie player
1722
- this._lottieInstance = Lottie__namespace.default.loadAnimation({
1723
- ...this._getOptions(),
1724
- animationData: this._animations[this._currentAnimation]
1725
- });
1726
- // Check play mode for current animation
1727
- if (this._multiAnimationSettings?.[this._currentAnimation]?.mode) {
1728
- this._isBounce = this._multiAnimationSettings[this._currentAnimation].mode === PlayMode.Bounce;
1729
- }
1730
- // Remove event listeners to new Lottie instance, and add new
1731
- this._removeEventListeners();
1732
- this._addEventListeners();
1733
- this.dispatchEvent(new CustomEvent(isPrevious ? PlayerEvents.Previous : PlayerEvents.Next));
1734
- if (this._multiAnimationSettings?.[this._currentAnimation]?.autoplay ?? this.autoplay) {
1735
- if (this.animateOnScroll) {
1736
- this._lottieInstance?.goToAndStop(0, true);
1737
- this.playerState = PlayerState.Paused;
1738
- return;
1739
- }
1740
- this._lottieInstance?.goToAndPlay(0, true);
1741
- this.playerState = PlayerState.Playing;
1742
- return;
1743
- }
1744
- this._lottieInstance?.goToAndStop(0, true);
1745
- this.playerState = PlayerState.Stopped;
1746
- } catch (err) {
1747
- this._errorMessage = handleErrors(err).message;
1748
- this.playerState = PlayerState.Error;
1749
- this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1750
- }
1751
- }
1752
- /**
1753
- * Skip to next animation
1754
- */ next() {
1755
- this._currentAnimation++;
1756
- this._switchInstance();
1757
- }
1758
- /**
1759
- * Skip to previous animation
1760
- */ prev() {
1761
- this._currentAnimation--;
1762
- this._switchInstance(true);
1763
- }
1764
- async convert({ animations, fileName, manifest, shouldDownload = true, src, typeCheck }) {
1765
- if (typeCheck || this._isDotLottie) {
1766
- return createJSON({
1767
- animation: (await getAnimationData(src || this.src))?.animations?.[0],
1768
- fileName: `${getFilename(fileName || this.src || 'converted')}.json`,
1769
- shouldDownload
1770
- });
1771
- }
1772
- return createDotLottie({
1773
- animations: animations || (await getAnimationData(this.src))?.animations,
1774
- fileName: `${getFilename(fileName || this.src || 'converted')}.lottie`,
1775
- manifest: {
1776
- ...manifest || this._manifest,
1777
- generator: pkg.name
1778
- },
1779
- shouldDownload
1780
- });
1781
- }
1782
- /**
1783
- * Return the styles for the component
1784
- */ static get styles() {
1785
- const styleSheet = new CSSStyleSheet();
1786
- styleSheet.replace(css_248z);
1787
- return styleSheet;
1788
- }
1789
- }
1790
-
1791
- /**
1792
- * Expose DotLottiePlayer class as global variable
1793
- * @returns { DotLottiePlayer }
1794
- */ globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
1795
- const tagName = 'dotlottie-player';
1796
- if (!isServer()) {
1797
- customElements.define('dotlottie-player', DotLottiePlayer);
1798
- }
1799
-
1800
- exports.PlayMode = PlayMode;
1801
- exports.PlayerEvents = PlayerEvents;
1802
- exports.PlayerState = PlayerState;
1803
- exports.default = DotLottiePlayer;
1804
- exports.tagName = tagName;