@aarsteinmedia/dotlottie-player 4.0.3 → 4.0.5

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/esm/index.js CHANGED
@@ -77,12 +77,20 @@ const addExt = (ext, str)=>{
77
77
  default:
78
78
  return 'xMidYMid meet';
79
79
  }
80
- }, base64ToU8 = (str)=>strToU8(isServer() ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), createDotLottie = async ({ animations, fileName, manifest, shouldDownload = true })=>{
80
+ }, /**
81
+ * Convert Base64 encoded string to Uint8Array
82
+ * @param { string } str Base64 encoded string
83
+ * @returns { Uint8Array } UTF-8/Latin-1 binary
84
+ */ base64ToU8 = (str)=>strToU8(isServer() ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), /**
85
+ * Convert a JSON Lottie to dotLottie or combine several animations and download new dotLottie file in your browser.
86
+ */ createDotLottie = async ({ animations, fileName, manifest, shouldDownload = true })=>{
81
87
  try {
88
+ // Input validation
82
89
  if (!animations?.length || !manifest) {
83
90
  throw new Error(`Missing or malformed required parameter(s):\n ${animations?.length ? '- manifest\n' : ''} ${manifest ? '- animations\n' : ''}`);
84
91
  }
85
- const manifestCompressionLevel = 0, animationCompressionLevel = 9, name = addExt('lottie', fileName) || `${useId()}.lottie`, dotlottie = {
92
+ const manifestCompressionLevel = 0, animationCompressionLevel = 9, // Prepare the dotLottie file
93
+ name = addExt('lottie', fileName) || `${useId()}.lottie`, dotlottie = {
86
94
  'manifest.json': [
87
95
  strToU8(JSON.stringify(manifest), true),
88
96
  {
@@ -90,14 +98,19 @@ const addExt = (ext, str)=>{
90
98
  }
91
99
  ]
92
100
  };
101
+ // Add animations and assets to the dotLottie file
93
102
  for (const [i, animation] of animations.entries()){
94
103
  for (const asset of animation.assets ?? []){
95
104
  if (!asset.p || !isImage(asset) && !isAudio(asset)) {
96
105
  continue;
97
106
  }
98
- const { p: file, u: path } = asset, assetId = useId('asset'), isEncoded = file.startsWith('data:'), ext = isEncoded ? getExtFromB64(file) : getExt(file), dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
107
+ const { p: file, u: path } = asset, // Original asset.id caused issues with multianimations
108
+ 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
109
+ dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
99
110
  asset.p = `${assetId}.${ext}`;
111
+ // Asset is embedded, so path empty string
100
112
  asset.u = '';
113
+ // Asset is encoded
101
114
  asset.e = 1;
102
115
  dotlottie[`${isAudio(asset) ? 'audio' : 'images'}/${assetId}.${ext}`] = [
103
116
  base64ToU8(dataURL),
@@ -134,7 +147,11 @@ const addExt = (ext, str)=>{
134
147
  } catch (err) {
135
148
  console.error(`❌ ${handleErrors(err).message}`);
136
149
  }
137
- }, download = (data, options)=>{
150
+ }, /**
151
+ * Download file, either SVG or dotLottie.
152
+ * @param { string } data The data to be downloaded
153
+ * @param { string } name Don't include file extension in the filename
154
+ */ download = (data, options)=>{
138
155
  const blob = new Blob([
139
156
  data
140
157
  ], {
@@ -191,7 +208,11 @@ const addExt = (ext, str)=>{
191
208
  error.status = result.status;
192
209
  throw error;
193
210
  }
194
- const ext = getExt(input);
211
+ /**
212
+ * Check if file is JSON, first by parsing file name for extension,
213
+ * then – if filename has no extension – by cloning the response
214
+ * and parsing it for content.
215
+ */ const ext = getExt(input);
195
216
  if (ext === 'json' || !ext) {
196
217
  if (ext) {
197
218
  const lottie = await result.json();
@@ -213,9 +234,8 @@ const addExt = (ext, str)=>{
213
234
  isDotLottie: false,
214
235
  manifest: undefined
215
236
  };
216
- } catch (e) {
217
- console.warn(e);
218
- }
237
+ } catch (_e) {
238
+ /* empty */ }
219
239
  }
220
240
  const { data, manifest } = await getLottieJSON(result);
221
241
  return {
@@ -244,7 +264,10 @@ const addExt = (ext, str)=>{
244
264
  });
245
265
  });
246
266
  return arrayBuffer;
247
- }, getExt = (str)=>{
267
+ }, /**
268
+ * Get extension from filename, URL or path
269
+ * @param { string } str Filename, URL or path
270
+ */ getExt = (str)=>{
248
271
  if (typeof str !== 'string' || !str || !hasExt(str)) {
249
272
  return;
250
273
  }
@@ -252,9 +275,16 @@ const addExt = (ext, str)=>{
252
275
  }, getExtFromB64 = (str)=>{
253
276
  const mime = str.split(':')[1].split(';')[0], ext = mime.split('/')[1].split('+')[0];
254
277
  return ext;
255
- }, getFilename = (src, keepExt)=>{
278
+ }, /**
279
+ * Parse URL to get filename
280
+ * @param { string } src The url string
281
+ * @param { boolean } keepExt Whether to include file extension
282
+ * @returns { string } Filename, in lowercase
283
+ */ getFilename = (src, keepExt)=>{
284
+ // Because the regex strips all special characters, we need to extract the file extension, so we can add it later if we need it
256
285
  getExt(src);
257
- return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replace(/\W+/g, '-')}${''}`;
286
+ return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replace(/\W+/g, '-')}${''}` // .toLowerCase()
287
+ ;
258
288
  }, getLottieJSON = async (resp)=>{
259
289
  const unzipped = await unzip(resp), manifest = getManifest(unzipped), data = [], toResolve = [];
260
290
  for (const { id } of manifest.animations){
@@ -346,7 +376,7 @@ const addExt = (ext, str)=>{
346
376
  await Promise.all(toResolve);
347
377
  }, unzip = async (resp)=>{
348
378
  const u8 = new Uint8Array(await resp.arrayBuffer()), unzipped = await new Promise((resolve, reject)=>{
349
- unzip$1(u8, (err, file)=>{
379
+ unzip$1(u8, /* { filter }, */ (err, file)=>{
350
380
  if (err) {
351
381
  reject(err);
352
382
  }
@@ -359,15 +389,19 @@ const addExt = (ext, str)=>{
359
389
  return `${prefix ?? `:${s4()}`}_${s4()}`;
360
390
  };
361
391
 
362
- function renderPlayer() {
363
- this.template.innerHTML = `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document?.documentElement?.lang : 'en'}" role="img" aria-label="${this.description ?? 'Lottie animation'}" data-loaded="${this._playerState.loaded}"><figure class="animation" style="background:${this.background}">${this.playerState === PlayerState.Error ? `<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>`;
392
+ /**
393
+ * Render Player
394
+ */ function renderPlayer() {
395
+ this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document?.documentElement?.lang : 'en'}" role="img" 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>`;
364
396
  this.shadow.adoptedStyleSheets = [
365
397
  DotLottiePlayer.styles
366
398
  ];
367
399
  this.shadow.appendChild(this.template.content.cloneNode(true));
368
400
  }
369
401
 
370
- function renderControls() {
402
+ /**
403
+ * Render Controls
404
+ */ function renderControls() {
371
405
  const slot = this.shadow.querySelector('slot[name=controls]');
372
406
  if (!slot) {
373
407
  return;
@@ -376,7 +410,7 @@ function renderControls() {
376
410
  slot.innerHTML = '';
377
411
  return;
378
412
  }
379
- slot.innerHTML = `<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 ? '' : `<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>`;
413
+ 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>`;
380
414
  const togglePlay = this.shadow.querySelector('.togglePlay');
381
415
  if (togglePlay instanceof HTMLButtonElement) {
382
416
  togglePlay.onclick = this.togglePlay;
@@ -413,7 +447,7 @@ function renderControls() {
413
447
  }
414
448
  const snapshot = this.shadow.querySelector('.snapshot');
415
449
  if (snapshot instanceof HTMLButtonElement) {
416
- snapshot.onclick = this.snapshot;
450
+ snapshot.onclick = ()=>this.snapshot(true);
417
451
  }
418
452
  const toggleSettings = this.shadow.querySelector('.toggleSettings');
419
453
  if (toggleSettings instanceof HTMLButtonElement) {
@@ -423,8 +457,14 @@ function renderControls() {
423
457
  }
424
458
  }
425
459
 
426
- const UPDATE_ON_CONNECTED = Symbol('UPDATE_ON_CONNECTED');
460
+ /**
461
+ * Credit to:
462
+ * @author Leonardo Favre <https://github.com/leofavre/observed-properties>
463
+ * @description Enhanced HTML element with reactive state handlers
464
+ */ /* eslint-disable @typescript-eslint/ban-ts-comment */ const UPDATE_ON_CONNECTED = Symbol('UPDATE_ON_CONNECTED');
427
465
  if (isServer()) {
466
+ // Mock HTMLElement for server-side rendering
467
+ // @ts-ignore
428
468
  global.HTMLElement = class EmptyHTMLElement {
429
469
  };
430
470
  }
@@ -445,6 +485,7 @@ let EnhancedElement = class EnhancedElement extends HTMLElement {
445
485
  }
446
486
  constructor(){
447
487
  super();
488
+ // @ts-ignore
448
489
  const { observedProperties = [] } = this.constructor;
449
490
  if (UPDATE_ON_CONNECTED in this) {
450
491
  this[UPDATE_ON_CONNECTED] = [];
@@ -452,6 +493,7 @@ let EnhancedElement = class EnhancedElement extends HTMLElement {
452
493
  if ('propertyChangedCallback' in this && typeof this.propertyChangedCallback === 'function') {
453
494
  for (const propName of observedProperties){
454
495
  const initialValue = this[propName], CACHED_VALUE = Symbol(propName);
496
+ // @ts-ignore
455
497
  this[CACHED_VALUE] = initialValue;
456
498
  Object.defineProperty(this, propName, {
457
499
  get () {
@@ -473,34 +515,46 @@ let EnhancedElement = class EnhancedElement extends HTMLElement {
473
515
  }
474
516
  };
475
517
 
476
- var $schema="https://json.schemastore.org/package";var name="@aarsteinmedia/dotlottie-player";var version="4.0.3";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"git+https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var contributors=[{name:"Anthony Colpron",email:"anthonycolpron@gmail.com",url:"https://github.com/anthony-colpron"}];var license="GPL-2.0-or-later";var scripts={test:"wtr",prebuild:"rimraf ./dist",build:"rollup -c","prebuild:types":"rimraf ./types","build:types":"tsc -p ./tsconfig.prod.json && tsc-alias","build:cem":"npx cem analyze --config cem.config.mjs",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development","lint:js":"eslint","lint:js:fix":"eslint --fix","lint:css":"npx stylelint **/*.scss","lint:css:fix":"npx stylelint **/*.scss --fix","lint:pkg":"npmPkgJsonLint .","lint:pkg:fix":"npmPkgJsonLint . --fix"};var dependencies={fflate:"^0.8.2","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.10.3","@eslint/compat":"^1.2.2","@eslint/eslintrc":"^3.1.0","@eslint/js":"^9.13.0","@esm-bundle/chai":"4.3.4-fix.0","@open-wc/testing":"^4.0.0","@rollup/plugin-commonjs":"^28.0.1","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.3.0","@rollup/plugin-typescript":"^11.1.6","@swc/core":"^1.7.40","@types/mocha":"^10.0.9","@types/node":"^22.8.4","@typescript-eslint/eslint-plugin":"^8.12.2","@typescript-eslint/parser":"^8.12.2","@web/dev-server-esbuild":"^1.0.2","@web/dev-server-import-maps":"^0.2.1","@web/dev-server-rollup":"^0.6.4","@web/test-runner":"^0.19.0","@web/test-runner-playwright":"^0.11.0",autoprefixer:"^10.4.20",esbuild:"^0.24.0","esbuild-sass-plugin":"^3.3.1",eslint:"^9.13.0","eslint-config-prettier":"^9.1.0","eslint-import-resolver-typescript":"^3.6.3","eslint-plugin-import":"^2.31.0","eslint-plugin-jsdoc":"^48.11.0","eslint-plugin-perfectionist":"^3.9.1","eslint-plugin-prettier":"^5.2.1",globals:"^15.11.0","npm-package-json-lint":"^8.0.0","npm-package-json-lint-config-default":"^7.0.1","postcss-flexbugs-fixes":"^5.0.2",prettier:"^3.3.3",rimraf:"^6.0.1",rollup:"^4.24.3","rollup-plugin-dts":"^6.1.1","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.1","rollup-plugin-swc3":"^0.12.1","rollup-plugin-typescript-paths":"^1.5.0",sass:"^1.80.5",stylelint:"^16.10.0","stylelint-config-standard-scss":"^13.1.0","tsc-alias":"^1.8.10",tslib:"^2.8.0",typescript:"^5.6.3"};var browserslist={production:[">0.3%","not dead","not op_mini all"],development:["last 1 chrome version","last 1 firefox version","last 1 safari version"]};var customElements$1="custom-elements.json";var files=["custom-elements.json","dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {$schema:$schema,name:name,version:version,description:description,exports:exports,main:main,unpkg:unpkg,module:module,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,contributors:contributors,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,browserslist:browserslist,customElements:customElements$1,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
518
+ var $schema="https://json.schemastore.org/package";var name="@aarsteinmedia/dotlottie-player";var version="4.0.5";var description="Web Component for playing Lottie animations in your web app. Previously @johanaarstein/dotlottie-player";var exports={".":{"import":"./dist/esm/index.js",node:"./dist/esm/index.js",require:"./dist/cjs/index.js",types:"./dist/index.d.ts"}};var main="./dist/esm/index.js";var unpkg="./dist/index.js";var module="./dist/esm/index.js";var types="./dist/index.d.ts";var type="module";var homepage="https://www.aarstein.media/en/dotlottie-player";var repository={url:"git+https://github.com/aarsteinmedia/dotlottie-player.git",type:"git"};var bugs="https://github.com/aarsteinmedia/dotlottie-player/issues";var author={name:"Johan Martin Aarstein",email:"johan@aarstein.media",url:"https://www.aarstein.media",organization:"Aarstein Media"};var contributors=[{name:"Anthony Colpron",email:"anthonycolpron@gmail.com",url:"https://github.com/anthony-colpron"}];var license="GPL-2.0-or-later";var scripts={test:"wtr",prebuild:"rimraf ./dist",build:"rollup -c","prebuild:types":"rimraf ./types","build:types":"tsc -p ./tsconfig.prod.json && tsc-alias","build:cem":"npx cem analyze --config cem.config.mjs",prod:"pnpm build:types && pnpm build && pnpm build:cem",dev:"rollup -c -w --environment NODE_ENV:development","lint:js":"eslint","lint:js:fix":"eslint --fix","lint:css":"npx stylelint **/*.scss","lint:css:fix":"npx stylelint **/*.scss --fix","lint:pkg":"npmPkgJsonLint .","lint:pkg:fix":"npmPkgJsonLint . --fix"};var dependencies={fflate:"^0.8.2","lottie-web":"^5.12.2"};var peerDependencies={"@types/react":">= 16.0.0"};var devDependencies={"@custom-elements-manifest/analyzer":"^0.10.3","@eslint/compat":"^1.2.2","@eslint/eslintrc":"^3.1.0","@eslint/js":"^9.14.0","@esm-bundle/chai":"4.3.4-fix.0","@open-wc/testing":"^4.0.0","@rollup/plugin-commonjs":"^28.0.1","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.3.0","@rollup/plugin-typescript":"^11.1.6","@swc/core":"^1.7.42","@types/mocha":"^10.0.9","@types/node":"^22.8.7","@typescript-eslint/eslint-plugin":"^8.12.2","@typescript-eslint/parser":"^8.12.2","@web/dev-server-esbuild":"^1.0.2","@web/dev-server-import-maps":"^0.2.1","@web/dev-server-rollup":"^0.6.4","@web/test-runner":"^0.19.0","@web/test-runner-playwright":"^0.11.0",autoprefixer:"^10.4.20",esbuild:"^0.24.0","esbuild-sass-plugin":"^3.3.1",eslint:"^9.14.0","eslint-config-prettier":"^9.1.0","eslint-import-resolver-typescript":"^3.6.3","eslint-plugin-import":"^2.31.0","eslint-plugin-jsdoc":"^48.11.0","eslint-plugin-perfectionist":"^3.9.1","eslint-plugin-prettier":"^5.2.1",globals:"^15.11.0","npm-package-json-lint":"^8.0.0","npm-package-json-lint-config-default":"^7.0.1","postcss-flexbugs-fixes":"^5.0.2",prettier:"^3.3.3",rimraf:"^6.0.1",rollup:"^4.24.3","rollup-plugin-dts":"^6.1.1","rollup-plugin-html-literals":"^1.1.8","rollup-plugin-livereload":"^2.0.5","rollup-plugin-postcss":"^4.0.2","rollup-plugin-serve":"^1.1.1","rollup-plugin-summary":"^2.0.1","rollup-plugin-swc3":"^0.12.1","rollup-plugin-typescript-paths":"^1.5.0",sass:"^1.80.6",stylelint:"^16.10.0","stylelint-config-standard-scss":"^13.1.0","tsc-alias":"^1.8.10",tslib:"^2.8.1",typescript:"^5.6.3"};var browserslist={production:[">0.3%","not dead","not op_mini all"],development:["last 1 chrome version","last 1 firefox version","last 1 safari version"]};var customElements$1="custom-elements.json";var files=["CHANGELOG.md","custom-elements.json","dist","README.md"];var keywords=["lottie","dotlottie","animation","web component","svg","vector","player"];var publishConfig={access:"public"};var engines={node:">= 8.17.0"};var funding={type:"paypal",url:"https://www.paypal.com/donate/?hosted_button_id=E7C7DMN8KSQ6A"};var pkg = {$schema:$schema,name:name,version:version,description:description,exports:exports,main:main,unpkg:unpkg,module:module,types:types,type:type,homepage:homepage,repository:repository,bugs:bugs,author:author,contributors:contributors,license:license,scripts:scripts,dependencies:dependencies,peerDependencies:peerDependencies,devDependencies:devDependencies,browserslist:browserslist,customElements:customElements$1,files:files,keywords:keywords,publishConfig:publishConfig,engines:engines,funding:funding};
477
519
 
478
520
  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 display: block;\n width: 100%;\n height: 100%;\n}\n:host .main {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n}\n:host .animation {\n width: 100%;\n height: 100%;\n display: flex;\n margin: 0;\n padding: 0;\n}\n:host [data-controls=true] .animation {\n height: calc(100% - 35px);\n}\n:host .animation-container {\n position: relative;\n}\n:host .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 0.2s ease-in-out;\n}\n:host .popover::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:host .error {\n display: flex;\n margin: auto;\n justify-content: center;\n height: 100%;\n align-items: center;\n}\n:host .error svg {\n width: 100%;\n height: auto;\n}\n:host .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:host .toolbar.has-error {\n pointer-events: none;\n opacity: 0.5;\n}\n:host .toolbar 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: 0.9;\n}\n:host .toolbar button:not([hidden]) {\n display: flex;\n}\n:host .toolbar button:hover {\n opacity: 1;\n}\n:host .toolbar button[data-active=true] {\n opacity: 1;\n fill: var(--lottie-player-toolbar-icon-active-color);\n}\n:host .toolbar button:disabled {\n opacity: 0.5;\n}\n:host .toolbar button:focus {\n outline: 0;\n}\n:host .toolbar button svg {\n pointer-events: none;\n}\n:host .toolbar button svg > * {\n fill: inherit;\n}\n:host .toolbar button.disabled svg {\n display: none;\n}\n:host .progress-container {\n position: relative;\n width: 100%;\n}\n:host .progress-container.simple {\n margin-right: 12px;\n}\n:host .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 /* background-color: var(--lottie-player-seeker-track-color); */\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:host .seeker::-webkit-slider-runnable-track, :host .seeker::-webkit-slider-thumb {\n appearance: none;\n outline: none;\n}\n:host .seeker::-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 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n}\n:host .seeker:hover::-webkit-slider-thumb, :host .seeker:focus::-webkit-slider-thumb {\n transform: scale(1);\n}\n:host .seeker::-moz-range-progress {\n background-color: var(--lottie-player-seeker-thumb-color);\n height: 5px;\n border-radius: 3px;\n}\n:host .seeker::-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 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n}\n:host .seeker:hover::-moz-range-thumb, :host .seeker:focus::-moz-range-thumb {\n transform: scale(1);\n}\n:host .seeker::-ms-track {\n width: 100%;\n height: 5px;\n cursor: pointer;\n background: transparent;\n border-color: transparent;\n color: transparent;\n}\n:host .seeker::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n border-radius: 3px;\n}\n:host .seeker::-ms-fill-lower {\n background-color: var(--lottie-player-seeker-thumb-color);\n border-radius: 3px;\n}\n:host .seeker::-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 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n}\n:host .seeker:hover::-ms-thumb {\n transform: scale(1);\n}\n:host .seeker:focus::-ms-thumb {\n transform: scale(1);\n}\n:host .seeker:focus::-ms-fill-lower, :host .seeker:focus::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n}\n:host 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:host ::-moz-progress-bar {\n background-color: var(--lottie-player-seeker-thumb-color);\n}\n:host ::-webkit-progress-inner-element {\n border-radius: 3px;\n overflow: hidden;\n}\n:host ::-webkit-slider-runnable-track {\n background-color: transparent;\n}\n:host ::-webkit-progress-value {\n background-color: var(--lottie-player-seeker-thumb-color);\n}\n\n@keyframes fade-in {\n 0% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\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}";
479
521
 
480
522
  let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
481
- async connectedCallback() {
523
+ /**
524
+ * Initialize everything on component first render
525
+ */ async connectedCallback() {
482
526
  super.connectedCallback();
483
527
  this._render();
484
528
  this._container = this.shadow.querySelector('.animation');
485
529
  this._renderControls();
530
+ // Add listener for Visibility API's change event.
486
531
  if (typeof document.hidden !== 'undefined') {
487
532
  document.addEventListener('visibilitychange', this._onVisibilityChange);
488
533
  }
534
+ // Add intersection observer for detecting component being out-of-view.
489
535
  this._addIntersectionObserver();
536
+ // Setup lottie player
490
537
  await this.load(this.src);
491
538
  this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
492
539
  }
493
- disconnectedCallback() {
540
+ /**
541
+ * Cleanup on component destroy
542
+ */ disconnectedCallback() {
543
+ // Remove intersection observer for detecting component being out-of-view
494
544
  if (this._intersectionObserver) {
495
545
  this._intersectionObserver.disconnect();
496
546
  this._intersectionObserver = undefined;
497
547
  }
548
+ // Destroy the animation instance
498
549
  if (this._lottieInstance) {
499
550
  this._lottieInstance.destroy();
500
551
  }
552
+ // Remove the attached Visibility API's change event listener
501
553
  document.removeEventListener('visibilitychange', this._onVisibilityChange);
502
554
  }
503
- static get observedAttributes() {
555
+ /**
556
+ * Attributes to observe
557
+ */ static get observedAttributes() {
504
558
  return [
505
559
  'animateOnScroll',
506
560
  'autoplay',
@@ -514,7 +568,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
514
568
  'subframe'
515
569
  ];
516
570
  }
517
- async attributeChangedCallback(name, _oldValue, value) {
571
+ /**
572
+ * Runs when the value of an attribute is changed on the component
573
+ */ async attributeChangedCallback(name, _oldValue, value) {
518
574
  if (!this._lottieInstance) {
519
575
  return;
520
576
  }
@@ -593,6 +649,7 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
593
649
  '_animations'
594
650
  ];
595
651
  }
652
+ // name: string, oldValue: string, newValue: string
596
653
  propertyChangedCallback(name, _oldValue, value) {
597
654
  if (!this.shadow) {
598
655
  return;
@@ -605,9 +662,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
605
662
  togglePlay.dataset.active = (value === PlayerState.Playing || value === PlayerState.Paused).toString();
606
663
  stop.dataset.active = (value === PlayerState.Stopped).toString();
607
664
  if (value === PlayerState.Playing) {
608
- togglePlay.innerHTML = `<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>`;
665
+ 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>`;
609
666
  } else {
610
- togglePlay.innerHTML = `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z"/></svg>`;
667
+ 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>`;
611
668
  }
612
669
  }
613
670
  if (name === '_seeker' && typeof value === 'number') {
@@ -637,7 +694,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
637
694
  convert.hidden = this._isDotLottie;
638
695
  }
639
696
  }
640
- set animateOnScroll(value) {
697
+ /**
698
+ * Whether to trigger next frame with scroll
699
+ */ set animateOnScroll(value) {
641
700
  this.setAttribute('animateOnScroll', (!!value).toString());
642
701
  }
643
702
  get animateOnScroll() {
@@ -647,7 +706,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
647
706
  }
648
707
  return false;
649
708
  }
650
- set autoplay(value) {
709
+ /**
710
+ * Autoplay
711
+ */ set autoplay(value) {
651
712
  this.setAttribute('autoplay', (!!value).toString());
652
713
  }
653
714
  get autoplay() {
@@ -657,13 +718,17 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
657
718
  }
658
719
  return false;
659
720
  }
660
- set background(value) {
721
+ /**
722
+ * Background color
723
+ */ set background(value) {
661
724
  this.setAttribute('background', value);
662
725
  }
663
726
  get background() {
664
727
  return this.getAttribute('background') || 'transparent';
665
728
  }
666
- set controls(value) {
729
+ /**
730
+ * Show controls
731
+ */ set controls(value) {
667
732
  this.setAttribute('controls', (!!value).toString());
668
733
  }
669
734
  get controls() {
@@ -673,7 +738,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
673
738
  }
674
739
  return false;
675
740
  }
676
- set count(value) {
741
+ /**
742
+ * Number of times to loop
743
+ */ set count(value) {
677
744
  this.setAttribute('count', value.toString());
678
745
  }
679
746
  get count() {
@@ -683,13 +750,17 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
683
750
  }
684
751
  return 0;
685
752
  }
686
- set description(value) {
753
+ /**
754
+ * Description for screen readers
755
+ */ set description(value) {
687
756
  this.setAttribute('description', value);
688
757
  }
689
758
  get description() {
690
759
  return this.getAttribute('description') || '';
691
760
  }
692
- set direction(value) {
761
+ /**
762
+ * Direction of animation
763
+ */ set direction(value) {
693
764
  this.setAttribute('direction', value.toString());
694
765
  }
695
766
  get direction() {
@@ -699,7 +770,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
699
770
  }
700
771
  return 1;
701
772
  }
702
- set hover(value) {
773
+ /**
774
+ * Whether to play on mouseover
775
+ */ set hover(value) {
703
776
  this.setAttribute('hover', value.toString());
704
777
  }
705
778
  get hover() {
@@ -709,7 +782,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
709
782
  }
710
783
  return false;
711
784
  }
712
- set intermission(value) {
785
+ /**
786
+ * Pause between loop intrations, in miliseconds
787
+ */ set intermission(value) {
713
788
  this.setAttribute('intermission', value.toString());
714
789
  }
715
790
  get intermission() {
@@ -719,7 +794,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
719
794
  }
720
795
  return 0;
721
796
  }
722
- set loop(value) {
797
+ /**
798
+ * Loop animation
799
+ */ set loop(value) {
723
800
  this.setAttribute('loop', (!!value).toString());
724
801
  }
725
802
  get loop() {
@@ -729,7 +806,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
729
806
  }
730
807
  return false;
731
808
  }
732
- set mode(value) {
809
+ /**
810
+ * Play mode
811
+ */ set mode(value) {
733
812
  this.setAttribute('mode', value.toString());
734
813
  }
735
814
  get mode() {
@@ -739,7 +818,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
739
818
  }
740
819
  return PlayMode.Normal;
741
820
  }
742
- set objectfit(value) {
821
+ /**
822
+ * Resizing to container
823
+ */ set objectfit(value) {
743
824
  this.setAttribute('objectfit', value);
744
825
  }
745
826
  get objectfit() {
@@ -749,7 +830,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
749
830
  }
750
831
  return ObjectFit.Contain;
751
832
  }
752
- set preserveAspectRatio(value) {
833
+ /**
834
+ * Resizing to container (Deprecated)
835
+ */ set preserveAspectRatio(value) {
753
836
  this.setAttribute('preserveAspectRatio', value || PreserveAspectRatio.Contain);
754
837
  }
755
838
  get preserveAspectRatio() {
@@ -759,7 +842,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
759
842
  }
760
843
  return null;
761
844
  }
762
- set renderer(value) {
845
+ /**
846
+ * Renderer to use: svg, canvas or html
847
+ */ set renderer(value) {
763
848
  this.setAttribute('renderer', value);
764
849
  }
765
850
  get renderer() {
@@ -769,7 +854,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
769
854
  }
770
855
  return 'svg';
771
856
  }
772
- set simple(value) {
857
+ /**
858
+ * Hide advanced controls
859
+ */ set simple(value) {
773
860
  this.setAttribute('simple', value.toString());
774
861
  }
775
862
  get simple() {
@@ -779,7 +866,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
779
866
  }
780
867
  return false;
781
868
  }
782
- set speed(value) {
869
+ /**
870
+ * Speed
871
+ */ set speed(value) {
783
872
  this.setAttribute('speed', value?.toString());
784
873
  }
785
874
  get speed() {
@@ -789,13 +878,17 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
789
878
  }
790
879
  return 1;
791
880
  }
792
- set src(value) {
881
+ /**
882
+ * Source, either path or JSON string
883
+ */ set src(value) {
793
884
  this.setAttribute('src', value || '');
794
885
  }
795
886
  get src() {
796
887
  return this.getAttribute('src');
797
888
  }
798
- set subframe(value) {
889
+ /**
890
+ * Subframe
891
+ */ set subframe(value) {
799
892
  this.setAttribute('subframe', (!!value).toString());
800
893
  }
801
894
  get subframe() {
@@ -805,29 +898,45 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
805
898
  }
806
899
  return false;
807
900
  }
808
- getMultiAnimationSettings() {
901
+ /**
902
+ * Get Multi-animation settings
903
+ * @returns { AnimationSettings[] }
904
+ */ getMultiAnimationSettings() {
809
905
  return this._multiAnimationSettings;
810
906
  }
811
- setMultiAnimationSettings(settings) {
907
+ /**
908
+ * Set Multi-animation settings
909
+ * @param { AnimationSettings[] } settings
910
+ */ setMultiAnimationSettings(settings) {
812
911
  if (!this._lottieInstance) {
813
912
  return;
814
913
  }
815
914
  this._multiAnimationSettings = settings;
816
915
  }
817
- setSegment(segment) {
916
+ /**
917
+ * Set playback segment
918
+ * @param { AnimationSegment } settings
919
+ */ setSegment(segment) {
818
920
  if (!this._lottieInstance) {
819
921
  return;
820
922
  }
821
923
  this._segment = segment;
822
924
  }
823
- getSegment() {
925
+ /**
926
+ * Get playback segment
927
+ * @returns { AnimationSegment }
928
+ */ getSegment() {
824
929
  return this._segment;
825
930
  }
826
- _getOptions() {
931
+ /**
932
+ * Get options from props
933
+ * @returns { AnimationConfig }
934
+ */ _getOptions() {
827
935
  if (!this._container) {
828
936
  throw new Error('Container not rendered');
829
937
  }
830
938
  const preserveAspectRatio = this.preserveAspectRatio ?? (this.objectfit && aspectRatio(this.objectfit)), currentAnimationSettings = this._multiAnimationSettings?.length ? this._multiAnimationSettings?.[this._currentAnimation] : undefined, currentAnimationManifest = this._manifest.animations?.[this._currentAnimation];
939
+ // Loop
831
940
  let loop = !!this.loop;
832
941
  if (currentAnimationManifest.loop !== undefined && this.loop === undefined) {
833
942
  loop = !!currentAnimationManifest.loop;
@@ -835,6 +944,7 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
835
944
  if (currentAnimationSettings?.loop !== undefined) {
836
945
  loop = !!currentAnimationSettings.loop;
837
946
  }
947
+ // Autoplay
838
948
  let autoplay = !!this.autoplay;
839
949
  if (currentAnimationManifest.autoplay !== undefined && this.autoplay === undefined) {
840
950
  autoplay = !!currentAnimationManifest.autoplay;
@@ -845,6 +955,7 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
845
955
  if (this.animateOnScroll) {
846
956
  autoplay = false;
847
957
  }
958
+ // Segment
848
959
  let initialSegment = this._segment;
849
960
  if (this._segment?.every((val)=>val > 0)) {
850
961
  initialSegment = [
@@ -890,7 +1001,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
890
1001
  }
891
1002
  return options;
892
1003
  }
893
- _addIntersectionObserver() {
1004
+ /**
1005
+ * Add IntersectionObserver
1006
+ */ _addIntersectionObserver() {
894
1007
  if (!this._container || this._intersectionObserver || !('IntersectionObserver' in window)) {
895
1008
  return;
896
1009
  }
@@ -914,10 +1027,13 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
914
1027
  });
915
1028
  this._intersectionObserver.observe(this._container);
916
1029
  }
917
- async load(src) {
1030
+ /**
1031
+ * Initialize Lottie Web player
1032
+ */ async load(src) {
918
1033
  if (!this.shadowRoot || !src) {
919
1034
  return;
920
1035
  }
1036
+ // Load the resource
921
1037
  try {
922
1038
  const { animations, isDotLottie, manifest } = await getAnimationData(src);
923
1039
  if (!animations || animations.some((animation)=>!this._isLottie(animation))) {
@@ -943,6 +1059,7 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
943
1059
  }
944
1060
  ]
945
1061
  };
1062
+ // Clear previous animation, if any
946
1063
  if (this._lottieInstance) {
947
1064
  this._lottieInstance.destroy();
948
1065
  }
@@ -950,6 +1067,7 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
950
1067
  if (!this.animateOnScroll && (this.autoplay || this._multiAnimationSettings?.[this._currentAnimation]?.autoplay)) {
951
1068
  this.playerState = PlayerState.Playing;
952
1069
  }
1070
+ // Initialize lottie player and load animation
953
1071
  this._lottieInstance = Lottie.default.loadAnimation({
954
1072
  ...this._getOptions(),
955
1073
  animationData: animations[this._currentAnimation]
@@ -962,9 +1080,11 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
962
1080
  }
963
1081
  this._addEventListeners();
964
1082
  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;
1083
+ // Set initial playback speed and direction
965
1084
  this._lottieInstance.setSpeed(speed);
966
1085
  this._lottieInstance.setDirection(direction);
967
1086
  this._lottieInstance.setSubframe(!!this.subframe);
1087
+ // Start playing if autoplay is enabled
968
1088
  if (this.autoplay || this.animateOnScroll) {
969
1089
  if (this.direction === -1) {
970
1090
  this.seek('99%');
@@ -978,10 +1098,14 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
978
1098
  this._addIntersectionObserver();
979
1099
  }
980
1100
  }
981
- getManifest() {
1101
+ /**
1102
+ * Get Lottie Manifest
1103
+ */ getManifest() {
982
1104
  return this._manifest;
983
1105
  }
984
- _toggleEventListeners(action) {
1106
+ /**
1107
+ * Toggle event listeners
1108
+ */ _toggleEventListeners(action) {
985
1109
  const method = action === 'add' ? 'addEventListener' : 'removeEventListener';
986
1110
  if (this._lottieInstance) {
987
1111
  this._lottieInstance[method]('enterFrame', this._enterFrame);
@@ -1010,17 +1134,22 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1010
1134
  });
1011
1135
  }
1012
1136
  }
1013
- _addEventListeners() {
1137
+ /**
1138
+ * Add event listeners
1139
+ */ _addEventListeners() {
1014
1140
  this._toggleEventListeners('add');
1015
1141
  }
1016
- _removeEventListeners() {
1142
+ /**
1143
+ * Remove event listeners
1144
+ */ _removeEventListeners() {
1017
1145
  this._toggleEventListeners('remove');
1018
1146
  }
1019
1147
  _loopComplete() {
1020
1148
  if (!this._lottieInstance) {
1021
1149
  return;
1022
1150
  }
1023
- const { playDirection, totalFrames } = this._lottieInstance, inPoint = this._segment ? this._segment[0] : 0, outPoint = this._segment ? this._segment[0] : totalFrames;
1151
+ const { playDirection, // firstFrame,
1152
+ totalFrames } = this._lottieInstance, inPoint = this._segment ? this._segment[0] : 0, outPoint = this._segment ? this._segment[0] : totalFrames;
1024
1153
  if (this.count) {
1025
1154
  if (this._isBounce) {
1026
1155
  this._playerState.count += 0.5;
@@ -1106,17 +1235,23 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1106
1235
  this.play();
1107
1236
  }
1108
1237
  }
1109
- _mouseEnter() {
1238
+ /**
1239
+ * Handle MouseEnter
1240
+ */ _mouseEnter() {
1110
1241
  if (this.hover && this.playerState !== PlayerState.Playing) {
1111
1242
  this.play();
1112
1243
  }
1113
1244
  }
1114
- _mouseLeave() {
1245
+ /**
1246
+ * Handle MouseLeave
1247
+ */ _mouseLeave() {
1115
1248
  if (this.hover && this.playerState === PlayerState.Playing) {
1116
1249
  this.stop();
1117
1250
  }
1118
1251
  }
1119
- _onVisibilityChange() {
1252
+ /**
1253
+ * Handle visibility change events
1254
+ */ _onVisibilityChange() {
1120
1255
  if (document.hidden && this.playerState === PlayerState.Playing) {
1121
1256
  this._freeze();
1122
1257
  return;
@@ -1125,7 +1260,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1125
1260
  this.play();
1126
1261
  }
1127
1262
  }
1128
- _handleScroll() {
1263
+ /**
1264
+ * Handle scroll
1265
+ */ _handleScroll() {
1129
1266
  if (!this.animateOnScroll || !this._lottieInstance) {
1130
1267
  return;
1131
1268
  }
@@ -1151,7 +1288,10 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1151
1288
  });
1152
1289
  }
1153
1290
  }
1154
- _handleSeekChange({ target }) {
1291
+ /**
1292
+ * Handles click and drag actions on the progress track
1293
+ * @param { Event & { HTMLInputElement } } event
1294
+ */ _handleSeekChange({ target }) {
1155
1295
  if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) {
1156
1296
  return;
1157
1297
  }
@@ -1169,7 +1309,16 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1169
1309
  ];
1170
1310
  return mandatory.every((field)=>Object.prototype.hasOwnProperty.call(json, field));
1171
1311
  }
1172
- async addAnimation(configs, fileName, shouldDownload = true) {
1312
+ /**
1313
+ * Creates a new dotLottie file, by combinig several animations
1314
+ * @param { [ AnimationConfig ] } configs
1315
+ * @param { string } fileName
1316
+ * @param { boolean } shouldDownload Whether to trigger a download in the browser.
1317
+ * If set to false the function returns an ArrayBuffer. Defaults to true.
1318
+ *
1319
+ */ async addAnimation(configs, fileName, shouldDownload = true) {
1320
+ // Initialize meta object for animation, with fallbacks for
1321
+ // when the method is called indepenently
1173
1322
  const { animations = [], manifest = {
1174
1323
  animations: this.src ? [
1175
1324
  {
@@ -1211,10 +1360,14 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1211
1360
  };
1212
1361
  }
1213
1362
  }
1214
- getLottie() {
1363
+ /**
1364
+ * Returns the lottie-web instance used in the component
1365
+ */ getLottie() {
1215
1366
  return this._lottieInstance;
1216
1367
  }
1217
- async play() {
1368
+ /**
1369
+ * Play
1370
+ */ async play() {
1218
1371
  if (!this._lottieInstance) {
1219
1372
  return;
1220
1373
  }
@@ -1228,7 +1381,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1228
1381
  this.playerState = PlayerState.Playing;
1229
1382
  }
1230
1383
  }
1231
- pause() {
1384
+ /**
1385
+ * Pause
1386
+ */ pause() {
1232
1387
  if (!this._lottieInstance) {
1233
1388
  return;
1234
1389
  }
@@ -1242,7 +1397,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1242
1397
  this.playerState = PlayerState.Paused;
1243
1398
  }
1244
1399
  }
1245
- stop() {
1400
+ /**
1401
+ * Stop
1402
+ */ stop() {
1246
1403
  if (!this._lottieInstance) {
1247
1404
  return;
1248
1405
  }
@@ -1257,7 +1414,9 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1257
1414
  this.playerState = PlayerState.Stopped;
1258
1415
  }
1259
1416
  }
1260
- destroy() {
1417
+ /**
1418
+ * Destroy animation and element
1419
+ */ destroy() {
1261
1420
  if (!this._lottieInstance) {
1262
1421
  return;
1263
1422
  }
@@ -1268,16 +1427,23 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1268
1427
  this.remove();
1269
1428
  document.removeEventListener('visibilitychange', this._onVisibilityChange);
1270
1429
  }
1271
- seek(value) {
1430
+ /**
1431
+ * Seek to a given frame
1432
+ * @param { number | string } value Frame to seek to
1433
+ */ seek(value) {
1272
1434
  if (!this._lottieInstance) {
1273
1435
  return;
1274
1436
  }
1437
+ // Extract frame number from either number or percentage value
1275
1438
  const matches = value.toString().match(/^([0-9]+)(%?)$/);
1276
1439
  if (!matches) {
1277
1440
  return;
1278
1441
  }
1442
+ // Calculate and set the frame number
1279
1443
  const frame = Math.round(matches[2] === '%' ? this._lottieInstance.totalFrames * Number(matches[1]) / 100 : Number(matches[1]));
1444
+ // Set seeker to new frame number
1280
1445
  this._seeker = frame;
1446
+ // Send lottie player to the new frame
1281
1447
  if (this.playerState === PlayerState.Playing || this.playerState === PlayerState.Frozen && this._playerState.prev === PlayerState.Playing) {
1282
1448
  this._lottieInstance.goToAndPlay(frame, true);
1283
1449
  this.playerState = PlayerState.Playing;
@@ -1286,34 +1452,52 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1286
1452
  this._lottieInstance.goToAndStop(frame, true);
1287
1453
  this._lottieInstance.pause();
1288
1454
  }
1289
- snapshot() {
1290
- if (!this.shadowRoot || !this.src) {
1291
- return;
1292
- }
1293
- const svgElement = this.shadowRoot.querySelector('.animation svg'), data = svgElement instanceof Node ? new XMLSerializer().serializeToString(svgElement) : null;
1294
- if (!data) {
1295
- console.error('Could not serialize data');
1296
- return;
1455
+ /**
1456
+ * Snapshot and download the current frame as SVG
1457
+ */ snapshot(shouldDownload = true) {
1458
+ try {
1459
+ if (!this.shadowRoot || !this.src) {
1460
+ throw new Error('Unknown error');
1461
+ }
1462
+ // Get SVG element and serialize markup
1463
+ const svgElement = this.shadowRoot.querySelector('.animation svg'), data = svgElement instanceof Node ? new XMLSerializer().serializeToString(svgElement) : null;
1464
+ if (!data) {
1465
+ throw new Error('Could not serialize data');
1466
+ }
1467
+ if (shouldDownload) {
1468
+ download(data, {
1469
+ mimeType: 'image/svg+xml',
1470
+ name: `${getFilename(this.src)}-${frameOutput(this._seeker)}.svg`
1471
+ });
1472
+ }
1473
+ return data;
1474
+ } catch (err) {
1475
+ console.error(err);
1476
+ return null;
1297
1477
  }
1298
- download(data, {
1299
- mimeType: 'image/svg+xml',
1300
- name: `${getFilename(this.src)}-${frameOutput(this._seeker)}.svg`
1301
- });
1302
- return data;
1303
1478
  }
1304
- setSubframe(value) {
1479
+ /**
1480
+ * Toggles subframe, for more smooth animations
1481
+ * @param { boolean } value Whether animation uses subframe
1482
+ */ setSubframe(value) {
1305
1483
  if (!this._lottieInstance) {
1306
1484
  return;
1307
1485
  }
1308
1486
  this._lottieInstance.setSubframe(value);
1309
1487
  }
1310
- setCount(value) {
1488
+ /**
1489
+ * Dynamically set count for loops
1490
+ */ setCount(value) {
1311
1491
  if (!this._lottieInstance) {
1312
1492
  return;
1313
1493
  }
1314
1494
  this.count = value;
1315
1495
  }
1316
- _freeze() {
1496
+ /**
1497
+ * Freeze animation.
1498
+ * This internal state pauses animation and is used to differentiate between
1499
+ * user requested pauses and component instigated pauses.
1500
+ */ _freeze() {
1317
1501
  if (!this._lottieInstance) {
1318
1502
  return;
1319
1503
  }
@@ -1327,32 +1511,45 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1327
1511
  this.playerState = PlayerState.Frozen;
1328
1512
  }
1329
1513
  }
1330
- async reload() {
1514
+ /**
1515
+ * Reload animation
1516
+ */ async reload() {
1331
1517
  if (!this._lottieInstance || !this.src) {
1332
1518
  return;
1333
1519
  }
1334
1520
  this._lottieInstance.destroy();
1335
1521
  await this.load(this.src);
1336
1522
  }
1337
- setSpeed(value = 1) {
1523
+ /**
1524
+ * Set animation playback speed
1525
+ * @param { number } value Playback speed
1526
+ */ setSpeed(value = 1) {
1338
1527
  if (!this._lottieInstance) {
1339
1528
  return;
1340
1529
  }
1341
1530
  this._lottieInstance.setSpeed(value);
1342
1531
  }
1343
- setDirection(value) {
1532
+ /**
1533
+ * Animation play direction
1534
+ * @param { AnimationDirection } value Animation direction
1535
+ */ setDirection(value) {
1344
1536
  if (!this._lottieInstance) {
1345
1537
  return;
1346
1538
  }
1347
1539
  this._lottieInstance.setDirection(value);
1348
1540
  }
1349
- setLoop(value) {
1541
+ /**
1542
+ * Set loop
1543
+ * @param { boolean } value
1544
+ */ setLoop(value) {
1350
1545
  if (!this._lottieInstance) {
1351
1546
  return;
1352
1547
  }
1353
1548
  this._lottieInstance.setLoop(value);
1354
1549
  }
1355
- togglePlay() {
1550
+ /**
1551
+ * Toggle playing state
1552
+ */ togglePlay() {
1356
1553
  if (!this._lottieInstance) {
1357
1554
  return;
1358
1555
  }
@@ -1373,12 +1570,16 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1373
1570
  }
1374
1571
  return this._lottieInstance.goToAndPlay(0, true);
1375
1572
  }
1376
- toggleLoop() {
1573
+ /**
1574
+ * Toggle loop
1575
+ */ toggleLoop() {
1377
1576
  const val = !this.loop;
1378
1577
  this.loop = val;
1379
1578
  this.setLoop(val);
1380
1579
  }
1381
- toggleBoomerang() {
1580
+ /**
1581
+ * Toggle Boomerang
1582
+ */ toggleBoomerang() {
1382
1583
  const curr = this._multiAnimationSettings?.[this._currentAnimation];
1383
1584
  if (curr?.mode !== undefined) {
1384
1585
  if (curr.mode === PlayMode.Normal) {
@@ -1398,31 +1599,40 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1398
1599
  this.mode = PlayMode.Normal;
1399
1600
  this._isBounce = false;
1400
1601
  }
1401
- _toggleSettings(flag) {
1602
+ /**
1603
+ * Toggle show Settings
1604
+ */ _toggleSettings(flag) {
1402
1605
  if (flag === undefined) {
1403
1606
  this._isSettingsOpen = !this._isSettingsOpen;
1404
1607
  return;
1405
1608
  }
1406
1609
  this._isSettingsOpen = flag;
1407
1610
  }
1408
- _handleBlur() {
1611
+ /**
1612
+ * Handle blur
1613
+ */ _handleBlur() {
1409
1614
  setTimeout(()=>this._toggleSettings(false), 200);
1410
1615
  }
1411
1616
  _switchInstance(isPrevious = false) {
1617
+ // Bail early if there is not animation to play
1412
1618
  if (!this._animations[this._currentAnimation]) {
1413
1619
  return;
1414
1620
  }
1415
1621
  try {
1622
+ // Clear previous animation
1416
1623
  if (this._lottieInstance) {
1417
1624
  this._lottieInstance.destroy();
1418
1625
  }
1626
+ // Re-initialize lottie player
1419
1627
  this._lottieInstance = Lottie.default.loadAnimation({
1420
1628
  ...this._getOptions(),
1421
1629
  animationData: this._animations[this._currentAnimation]
1422
1630
  });
1631
+ // Check play mode for current animation
1423
1632
  if (this._multiAnimationSettings?.[this._currentAnimation]?.mode) {
1424
1633
  this._isBounce = this._multiAnimationSettings[this._currentAnimation].mode === PlayMode.Bounce;
1425
1634
  }
1635
+ // Remove event listeners to new Lottie instance, and add new
1426
1636
  this._removeEventListeners();
1427
1637
  this._addEventListeners();
1428
1638
  this.dispatchEvent(new CustomEvent(isPrevious ? PlayerEvents.Previous : PlayerEvents.Next));
@@ -1444,11 +1654,15 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1444
1654
  this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1445
1655
  }
1446
1656
  }
1447
- next() {
1657
+ /**
1658
+ * Skip to next animation
1659
+ */ next() {
1448
1660
  this._currentAnimation++;
1449
1661
  this._switchInstance();
1450
1662
  }
1451
- prev() {
1663
+ /**
1664
+ * Skip to previous animation
1665
+ */ prev() {
1452
1666
  this._currentAnimation--;
1453
1667
  this._switchInstance(true);
1454
1668
  }
@@ -1470,21 +1684,40 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1470
1684
  shouldDownload
1471
1685
  });
1472
1686
  }
1473
- static get styles() {
1687
+ /**
1688
+ * Return the styles for the component
1689
+ */ static get styles() {
1474
1690
  const styleSheet = new CSSStyleSheet();
1475
1691
  styleSheet.replace(css_248z);
1476
1692
  return styleSheet;
1477
1693
  }
1478
1694
  constructor(){
1479
- super(), this._renderControls = renderControls, this._render = renderPlayer, this._multiAnimationSettings = [], this.playerState = PlayerState.Loading, this._isSettingsOpen = false, this._seeker = 0, 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 = {
1695
+ super(), this._renderControls = renderControls, this._render = renderPlayer, /**
1696
+ * Multi-animation settings
1697
+ */ this._multiAnimationSettings = [], /**
1698
+ * @state
1699
+ * Player state
1700
+ */ this.playerState = PlayerState.Loading, /**
1701
+ * @state
1702
+ * Whether settings toolbar is open
1703
+ */ this._isSettingsOpen = false, /**
1704
+ * @state
1705
+ * Seeker
1706
+ */ this._seeker = 0, /**
1707
+ * @state
1708
+ * Which animation to show, if several
1709
+ */ 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 = {
1480
1710
  count: 0,
1481
1711
  loaded: false,
1482
1712
  prev: PlayerState.Loading,
1483
1713
  scrollTimeout: null,
1484
1714
  scrollY: 0,
1485
1715
  visible: false
1486
- }, this._handleSettingsClick = ({ target })=>{
1716
+ }, /**
1717
+ * Handle settings click event
1718
+ */ this._handleSettingsClick = ({ target })=>{
1487
1719
  this._toggleSettings();
1720
+ // Because Safari does not add focus on click, we need to add it manually, so the onblur event will fire
1488
1721
  if (target instanceof HTMLElement) {
1489
1722
  target.focus();
1490
1723
  }
@@ -1521,7 +1754,10 @@ let DotLottiePlayer = class DotLottiePlayer extends EnhancedElement {
1521
1754
  }
1522
1755
  };
1523
1756
 
1524
- globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
1757
+ /**
1758
+ * Expose DotLottiePlayer class as global variable
1759
+ * @returns { DotLottiePlayer }
1760
+ */ globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
1525
1761
  const tagName = 'dotlottie-player';
1526
1762
  if (!isServer()) {
1527
1763
  customElements.define('dotlottie-player', DotLottiePlayer);