@aarsteinmedia/dotlottie-player 6.5.3 → 6.5.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.
@@ -1,5 +1,5 @@
1
1
  import { getAnimationData } from '@aarsteinmedia/lottie-web/dotlottie';
2
- import { isServer, PlayMode, PreserveAspectRatio, RendererType, createElementID, PlayerEvent, download, getFilename, clamp } from '@aarsteinmedia/lottie-web/utils';
2
+ import { isServer, PreserveAspectRatio, PlayMode, RendererType, createElementID, clamp, PlayerEvent, download, getFilename } from '@aarsteinmedia/lottie-web/utils';
3
3
 
4
4
  let modulePromise$1;
5
5
  function loadControlsModule() {
@@ -71,46 +71,7 @@ if (isServer) {
71
71
  }
72
72
  }
73
73
 
74
- var css_248z = "*{box-sizing:border-box}:host{--lottie-player-toolbar-height:35px;--lottie-player-toolbar-background-color:#fff;--lottie-player-toolbar-icon-color:#000;--lottie-player-toolbar-icon-hover-color:#000;--lottie-player-toolbar-icon-active-color:#4285f4;--lottie-player-seeker-track-color:#0003;--lottie-player-seeker-thumb-color:#4285f4;--lottie-player-seeker-display:block;height:100%;width:100%;&:not([hidden]){display:block}.main{display:flex;flex-direction:column;height:100%;margin:0;padding:0;width:100%}.animation{contain:content;display:flex;height:100%;margin:0;padding:0;width:100%;& svg g{will-change:transform}}[data-controls=true] .animation{height:calc(100% - 35px)}.animation-container{position:relative}.popover{animation:fade-in .2s ease-in-out;background-color:var(--lottie-player-toolbar-background-color);border:2px solid var(--lottie-player-toolbar-icon-color);border-radius:5px;bottom:40px;padding:10px 15px;position:absolute;right:5px;&:before{border:7px solid #0000;border-top:7px solid var(--lottie-player-toolbar-icon-color);content:\"\";height:0;margin-right:-7px;pointer-events:none;position:absolute;right:10px;top:100%;width:0}}.error{align-items:center;display:flex;height:100%;justify-content:center;margin:auto;& svg{height:auto;width:100%}}.toolbar{background:var(--lottie-player-toolbar-background-color);border-radius:5px;display:flex;gap:5px;height:35px;margin:0;padding:5px;place-items:center center;&.has-error{opacity:.5;pointer-events:none}& button{fill:var(--lottie-player-toolbar-icon-color);align-items:center;background:none;border:0;color:var(--lottie-player-toolbar-icon-color);cursor:pointer;gap:5px;height:100%;margin:0;opacity:.9;outline:0;padding:0;&:not([hidden]){display:flex}&:hover{opacity:1}&[data-active=true]{fill:var(--lottie-player-toolbar-icon-active-color);opacity:1}&:disabled{opacity:.5}&:focus{outline:0}& svg{pointer-events:none;&>*{fill:inherit}}&.disabled svg{display:none}}}.progress-container{position:relative;width:100%;&.simple{margin-right:12px}}& progress{appearance:none;background-color:var(--lottie-player-seeker-track-color);border:0;border-radius:3px;height:5px;left:0;margin:7.5px 0;outline:none;pointer-events:none;position:absolute;top:0;width:100%;&::-webkit-progress-inner-element{border-radius:3px;overflow:hidden}&::-webkit-slider-runnable-track{background-color:initial}&::-webkit-progress-value{background-color:var(--lottie-player-seeker-thumb-color)}}.seeker{appearance:none;background-color:initial;border:0;border-radius:3px;color:var(--lottie-player-seeker-thumb-color);cursor:pointer;display:var(--lottie-player-seeker-display);height:20px;margin:0;outline:none;padding:7.5px 0;position:relative;width:100%;z-index:1;&::-webkit-slider-runnable-track,&::-webkit-slider-thumb{appearance:none;outline:none}&::-webkit-slider-thumb{background-color:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-webkit-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:focus::-webkit-slider-thumb,&:hover::-webkit-slider-thumb{transform:scale(1)}&::-moz-range-progress{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px;height:5px}&::-moz-range-thumb{background-color:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-moz-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:focus::-moz-range-thumb,&:hover::-moz-range-thumb{transform:scale(1)}&::-ms-track{background:#0000;border-color:#0000;color:#0000;cursor:pointer;height:5px;width:100%}&::-ms-fill-upper{background:var(--lottie-player-seeker-track-color);border-radius:3px}&::-ms-fill-lower{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px}&::-ms-thumb{background:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-ms-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:hover::-ms-thumb{transform:scale(1)}&:focus{&::-ms-thumb{transform:scale(1)}&::-ms-fill-lower,&::-ms-fill-upper{background:var(--lottie-player-seeker-track-color)}}}& ::-moz-progress-bar{background-color:var(--lottie-player-seeker-thumb-color)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@media (prefers-color-scheme:dark){:host{--lottie-player-toolbar-background-color:#000;--lottie-player-toolbar-icon-color:#fff;--lottie-player-toolbar-icon-hover-color:#fff;--lottie-player-seeker-track-color:#fff9}}";
75
-
76
- let dotlottieTools = null, loadPromise = null;
77
- function loadDotLottieTools() {
78
- if (dotlottieTools) {
79
- return Promise.resolve(dotlottieTools);
80
- }
81
- loadPromise = loadPromise ?? (async ()=>{
82
- const { addAnimation, convert } = await import('@aarsteinmedia/lottie-web/dotlottie');
83
- dotlottieTools = {
84
- addAnimation,
85
- convert
86
- };
87
- return {
88
- addAnimation,
89
- convert
90
- };
91
- })();
92
- return loadPromise;
93
- }
94
-
95
- const boomerangIcon = /* HTML */ `<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>`;
96
-
97
- const convertIcon = /* HTML */ `<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>`;
98
-
99
- const downloadIcon = /* HTML */ `<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>`;
100
-
101
- const loopIcon = /* HTML */ `<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>`;
102
-
103
- const nextIcon = /* HTML */ `<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>`;
104
-
105
- const pauseIcon = /* 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>`;
106
-
107
- const playIcon = /* 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>`;
108
-
109
- const prevIcon = /* HTML */ `<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>`;
110
-
111
- const settingsIcon = /* HTML */ `<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>`;
112
-
113
- const stopIcon = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M6 6h12v12H6V6z"/></svg>`;
74
+ var css_248z = "*{box-sizing:border-box}:host{--lottie-player-toolbar-height:35px;--lottie-player-toolbar-background-color:#fff;--lottie-player-toolbar-icon-color:#000;--lottie-player-toolbar-icon-hover-color:#000;--lottie-player-toolbar-icon-active-color:#4285f4;--lottie-player-seeker-track-color:#0003;--lottie-player-seeker-thumb-color:#4285f4;--lottie-player-seeker-display:block;height:100%;width:100%;&:not([hidden]){display:block}& .main{display:flex;flex-direction:column;height:100%;margin:0;padding:0;width:100%}& .animation{contain:content;display:flex;height:100%;margin:0;padding:0;width:100%;& svg g{will-change:transform}}& [data-controls=true] .animation{height:calc(100% - 35px)}& .animation-container{position:relative}& .popover{animation:fade-in .2s ease-in-out;background-color:var(--lottie-player-toolbar-background-color);border:2px solid var(--lottie-player-toolbar-icon-color);border-radius:5px;bottom:40px;padding:10px 15px;position:absolute;right:5px;&:before{border:7px solid #0000;border-top:7px solid var(--lottie-player-toolbar-icon-color);content:\"\";height:0;margin-right:-7px;pointer-events:none;position:absolute;right:10px;top:100%;width:0}}& .error{align-items:center;display:flex;height:100%;justify-content:center;margin:auto;& svg{height:auto;width:100%}}& .toolbar{background:var(--lottie-player-toolbar-background-color);border-radius:5px;display:flex;gap:5px;height:35px;margin:0;padding:5px;place-items:center center;&.has-error{opacity:.5;pointer-events:none}& button{fill:var(--lottie-player-toolbar-icon-color);align-items:center;background:none;border:0;color:var(--lottie-player-toolbar-icon-color);cursor:pointer;gap:5px;height:100%;margin:0;opacity:.9;outline:0;padding:0;&:not([hidden]){display:flex}&:hover{opacity:1}&[data-active=true]{fill:var(--lottie-player-toolbar-icon-active-color);opacity:1}&:disabled{opacity:.5}&:focus{outline:0}& svg{pointer-events:none;&>*{fill:inherit}}&.disabled svg{display:none}}}& .progress-container{position:relative;width:100%;&.simple{margin-right:12px}}& progress{appearance:none;background-color:var(--lottie-player-seeker-track-color);border:0;border-radius:3px;height:5px;left:0;margin:7.5px 0;outline:none;pointer-events:none;position:absolute;top:0;width:100%;&::-webkit-progress-inner-element{border-radius:3px;overflow:hidden}&::-webkit-slider-runnable-track{background-color:initial}&::-webkit-progress-value{background-color:var(--lottie-player-seeker-thumb-color)}}& .seeker{appearance:none;background-color:initial;border:0;border-radius:3px;color:var(--lottie-player-seeker-thumb-color);cursor:pointer;display:var(--lottie-player-seeker-display);height:20px;margin:0;outline:none;padding:7.5px 0;position:relative;width:100%;z-index:1;&::-webkit-slider-runnable-track,&::-webkit-slider-thumb{appearance:none;outline:none}&::-webkit-slider-thumb{background-color:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-webkit-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:focus::-webkit-slider-thumb,&:hover::-webkit-slider-thumb{transform:scale(1)}&::-moz-range-progress{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px;height:5px}&::-moz-range-thumb{background-color:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-moz-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:focus::-moz-range-thumb,&:hover::-moz-range-thumb{transform:scale(1)}&::-ms-track{background:#0000;border-color:#0000;color:#0000;cursor:pointer;height:5px;width:100%}&::-ms-fill-upper{background:var(--lottie-player-seeker-track-color);border-radius:3px}&::-ms-fill-lower{background-color:var(--lottie-player-seeker-thumb-color);border-radius:3px}&::-ms-thumb{background:var(--lottie-player-seeker-thumb-color);border:0;border-radius:50%;cursor:pointer;height:15px;transform:scale(0);-ms-transition:transform .2s ease-in-out;transition:transform .2s ease-in-out;width:15px}&:hover::-ms-thumb{transform:scale(1)}&:focus{&::-ms-thumb{transform:scale(1)}&::-ms-fill-lower,&::-ms-fill-upper{background:var(--lottie-player-seeker-track-color)}}}& ::-moz-progress-bar{background-color:var(--lottie-player-seeker-thumb-color)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}@media (prefers-color-scheme:dark){:host{--lottie-player-toolbar-background-color:#000;--lottie-player-toolbar-icon-color:#fff;--lottie-player-toolbar-icon-hover-color:#fff;--lottie-player-seeker-track-color:#fff9}}";
114
75
 
115
76
  var ObjectFit = /*#__PURE__*/ function(ObjectFit) {
116
77
  ObjectFit["Contain"] = "contain";
@@ -139,135 +100,6 @@ var PlayerState = /*#__PURE__*/ function(PlayerState) {
139
100
  return PlayerState;
140
101
  }({});
141
102
 
142
- function advancedButtons() {
143
- if (!this.shadow) {
144
- return;
145
- }
146
- const toggleLoop = this.shadow.querySelector('.toggleLoop');
147
- if (toggleLoop instanceof HTMLButtonElement) {
148
- toggleLoop.onclick = this.toggleLoop;
149
- }
150
- const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
151
- if (toggleBoomerang instanceof HTMLButtonElement) {
152
- toggleBoomerang.onclick = this.toggleBoomerang;
153
- }
154
- const convertButton = this.shadow.querySelector('.convert');
155
- if (convertButton instanceof HTMLButtonElement) {
156
- convertButton.onclick = async ()=>{
157
- convertButton.disabled = true;
158
- try {
159
- const { convert } = await loadDotLottieTools();
160
- await convert({
161
- isDotLottie: this.isDotLottie,
162
- manifest: this.getManifest(),
163
- src: this.src || this.source
164
- });
165
- } finally{
166
- convertButton.disabled = false;
167
- }
168
- };
169
- }
170
- const snapshot = this.shadow.querySelector('.snapshot');
171
- if (snapshot instanceof HTMLButtonElement) {
172
- snapshot.onclick = ()=>this.snapshot(true);
173
- }
174
- const toggleSettings = this.shadow.querySelector('.toggleSettings');
175
- if (toggleSettings instanceof HTMLButtonElement) {
176
- toggleSettings.onclick = this._handleSettingsClick;
177
- toggleSettings.onblur = this._handleBlur;
178
- }
179
- }
180
- function handleButtons() {
181
- if (!this.shadow) {
182
- return;
183
- }
184
- const togglePlay = this.shadow.querySelector('.togglePlay');
185
- if (togglePlay instanceof HTMLButtonElement) {
186
- togglePlay.onclick = this.togglePlay;
187
- }
188
- const stopButton = this.shadow.querySelector('.stop');
189
- if (stopButton instanceof HTMLButtonElement) {
190
- stopButton.onclick = this.stop;
191
- }
192
- const prevButton = this.shadow.querySelector('.prev');
193
- if (prevButton instanceof HTMLButtonElement) {
194
- if (this.animations.length > 0 && this.currentAnimation) {
195
- prevButton.hidden = false;
196
- }
197
- prevButton.onclick = this.prev;
198
- }
199
- const nextButton = this.shadow.querySelector('.next');
200
- if (nextButton instanceof HTMLButtonElement) {
201
- if (this.animations.length > 0 && this.currentAnimation < this.animations.length - 1) {
202
- nextButton.hidden = false;
203
- }
204
- nextButton.onclick = this.next;
205
- }
206
- const seeker = this.shadow.querySelector('.seeker');
207
- if (seeker instanceof HTMLInputElement) {
208
- seeker.onchange = this._handleSeekChange;
209
- seeker.onmousedown = this._freeze;
210
- }
211
- if (this.simple) {
212
- return;
213
- }
214
- advancedButtons.call(this);
215
- }
216
- /**
217
- * Render Controls.
218
- */ function renderControls() {
219
- if (!this.shadow) {
220
- throw new Error('No Shadow Element');
221
- }
222
- const slot = this.shadow.querySelector('slot[name=controls]');
223
- if (!slot) {
224
- return;
225
- }
226
- if (!this.controls) {
227
- slot.innerHTML = '';
228
- return;
229
- }
230
- const convertLabel = this.isDotLottie ? 'dotLottie animation to JSON format' : 'JSON animation to dotLottie format', convertButtonText = this.isDotLottie ? 'Convert to JSON' : 'Convert to dotLottie';
231
- slot.innerHTML = /* HTML */ `<div class="lottie-controls toolbar ${this.playerState === PlayerState.Error ? 'has-error' : ''}" aria-label="Lottie Animation controls"><button class="togglePlay" data-active="${this.autoplay}" aria-label="Toggle Play/Pause">${playIcon}</button> <button class="stop" data-active="${!this.autoplay}" aria-label="Stop">${stopIcon}</button> <button class="prev" aria-label="Previous animation" hidden="false">${prevIcon}</button> <button class="next" aria-label="Next animation" hidden>${nextIcon}</button><form class="progress-container${this.simple ? ' simple' : ''}"><input type="range" class="seeker" min="0" max="100" step="1" value="${this._seeker.toString()}" aria-valuemin="0" aria-valuemax="100" 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">${loopIcon}</button> <button class="toggleBoomerang" data-active="${this.mode === PlayMode.Bounce}" aria-label="Toggle boomerang" tabindex="0">${boomerangIcon}</button> <button class="toggleSettings" aria-label="Settings" aria-haspopup="true" aria-expanded="${this._isSettingsOpen}" aria-controls="${this._identifier}-settings">${settingsIcon}</button><div id="${this._identifier}-settings" class="popover" hidden><button class="convert" aria-label="Convert ${convertLabel}" hidden>${convertIcon} ${convertButtonText}</button> <button class="snapshot" aria-label="Download still image">${downloadIcon} Download still image</button></div>`}</div>`;
232
- handleButtons.call(this);
233
- }
234
- function updatePlayPauseButton(togglePlay, state) {
235
- const isActive = state === PlayerState.Playing || state === PlayerState.Paused;
236
- togglePlay.dataset.active = isActive.toString();
237
- togglePlay.innerHTML = state === PlayerState.Playing ? pauseIcon : playIcon;
238
- }
239
-
240
- var controls = /*#__PURE__*/Object.freeze({
241
- __proto__: null,
242
- renderControls: renderControls,
243
- updatePlayPauseButton: updatePlayPauseButton
244
- });
245
-
246
- /**
247
- * Render Player.
248
- */ async function renderPlayer() {
249
- if (!this.shadow || !this.template) {
250
- throw new Error('No Shadow Element or Template');
251
- }
252
- let langAttribute = '';
253
- /**
254
- * If player has aria-description, it's safe to assume
255
- * language should be the same as `document.documentElement.lang`.
256
- * Accessible labels on controls are only in English, so with no
257
- * aria tag, and controls enabled, lang should reflect this.
258
- * With neither controls or description, the lang attribute is
259
- * not needed.
260
- */ if (this.description || this.controls) {
261
- const lang = this.description ? document.documentElement.lang : 'en';
262
- langAttribute = `lang="${lang}"`;
263
- }
264
- this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" ${langAttribute}><figure class="animation" style="background:${this.background}" ${this.description ? `aria-label="${this.description}"` : ''}></figure><slot name="controls"></slot></div>`;
265
- this.shadow.adoptedStyleSheets = [
266
- await DotLottiePlayerBase.styles()
267
- ];
268
- this.shadow.appendChild(this.template.content.cloneNode(true));
269
- }
270
-
271
103
  /**
272
104
  * Get extension from filename, URL or path.
273
105
  */ const aspectRatio = (objectFit)=>{
@@ -334,42 +166,12 @@ var controls = /*#__PURE__*/Object.freeze({
334
166
 
335
167
  const tagName = 'dotlottie-player', hasReducedMotion = !isServer && matchMedia('(prefers-reduced-motion: reduce)').matches, hasIOSupport = !isServer && 'IntersectionObserver' in window, hasVTSupport = !isServer && 'ViewTimeline' in window;
336
168
 
337
- const notImplemented = 'Method is not implemented', getStyles = async ()=>{
169
+ const getStyles = async ()=>{
338
170
  const styleSheet = new CSSStyleSheet();
339
171
  await styleSheet.replace(css_248z);
340
172
  return styleSheet;
341
- };
342
- /**
343
- * DotLottie Player Web Component.
344
- */ class DotLottiePlayerBase extends PropertyCallbackElement {
345
- /**
346
- * Attributes to observe.
347
- */ static get observedAttributes() {
348
- return [
349
- 'animateOnScroll',
350
- 'autoplay',
351
- 'controls',
352
- 'direction',
353
- 'hover',
354
- 'loop',
355
- 'mode',
356
- 'playOnClick',
357
- 'playOnVisible',
358
- 'selector',
359
- 'speed',
360
- 'src',
361
- 'subframe'
362
- ];
363
- }
364
- static get observedProperties() {
365
- return [
366
- 'playerState',
367
- '_isSettingsOpen',
368
- '_seeker',
369
- '_currentAnimation',
370
- '_animations'
371
- ];
372
- }
173
+ }, notImplemented$1 = 'Method is not implemented';
174
+ class BaseElement extends PropertyCallbackElement {
373
175
  /**
374
176
  * Return the styles for the component.
375
177
  */ static get styles() {
@@ -492,9 +294,6 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
492
294
  }
493
295
  return 0;
494
296
  }
495
- get isDotLottie() {
496
- return this._isDotLottie;
497
- }
498
297
  /**
499
298
  * Loop animation.
500
299
  */ set loop(value) {
@@ -588,99 +387,461 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
588
387
  }
589
388
  return null;
590
389
  }
591
- /**
592
- * Whether to display error screen on load error.
593
- */ set quiet(value) {
594
- this.setAttribute('quiet', Boolean(value).toString());
390
+ /**
391
+ * Whether to display error screen on load error.
392
+ */ set quiet(value) {
393
+ this.setAttribute('quiet', Boolean(value).toString());
394
+ }
395
+ get quiet() {
396
+ const val = this.getAttribute('quiet');
397
+ return parseHTMLBooleans(val);
398
+ }
399
+ /**
400
+ * Renderer to use: svg, canvas or html.
401
+ */ set renderer(value) {
402
+ this.setAttribute('renderer', value);
403
+ }
404
+ get renderer() {
405
+ const val = this.getAttribute('renderer');
406
+ if (val === RendererType.Canvas || val === RendererType.HTML) {
407
+ return val;
408
+ }
409
+ return RendererType.SVG;
410
+ }
411
+ /**
412
+ * Play on clicked element by id attribute, other than animation.
413
+ */ set selector(value) {
414
+ if (value) {
415
+ this.setAttribute('selector', value);
416
+ return;
417
+ }
418
+ this.removeAttribute('selector');
419
+ }
420
+ get selector() {
421
+ return this.getAttribute('selector');
422
+ }
423
+ /**
424
+ * Hide advanced controls.
425
+ */ set simple(value) {
426
+ this.setAttribute('simple', Boolean(value).toString());
427
+ }
428
+ get simple() {
429
+ const val = this.getAttribute('simple');
430
+ return parseHTMLBooleans(val);
431
+ }
432
+ /**
433
+ * Speed.
434
+ */ set speed(value) {
435
+ this.setAttribute('speed', value.toString());
436
+ }
437
+ get speed() {
438
+ const val = this.getAttribute('speed');
439
+ if (val !== null && !isNaN(Number(val))) {
440
+ return Number(val);
441
+ }
442
+ return 1;
443
+ }
444
+ /**
445
+ * Source, either path or JSON string.
446
+ */ set src(value) {
447
+ this.setAttribute('src', value || '');
448
+ }
449
+ get src() {
450
+ return this.getAttribute('src');
451
+ }
452
+ /**
453
+ * Subframe.
454
+ */ set subframe(value) {
455
+ this.setAttribute('subframe', Boolean(value).toString());
456
+ }
457
+ get subframe() {
458
+ const val = this.getAttribute('subframe');
459
+ return parseHTMLBooleans(val);
460
+ }
461
+ clearDevLog() {
462
+ this._toLog = null;
463
+ }
464
+ devLog(toLog, type = 'error') {
465
+ {
466
+ return;
467
+ }
468
+ }
469
+ play() {
470
+ throw new Error(notImplemented$1);
471
+ }
472
+ _freeze() {
473
+ throw new Error(notImplemented$1);
474
+ }
475
+ constructor(...args){
476
+ super(...args), /**
477
+ * Player state.
478
+ */ this.playerState = PlayerState.Loading, /**
479
+ * This is included in watched properties,
480
+ * so that next-button will show up
481
+ * on load, if controls are visible.
482
+ */ this._animations = [], /**
483
+ * Animation Container.
484
+ */ this._container = null, /**
485
+ * Which animation to show, if several.
486
+ */ this._currentAnimation = 0, this._errorMessage = 'Something went wrong', this._identifier = this.id || createElementID(), this._lottieInstance = null, this._playerState = {
487
+ count: 0,
488
+ frame: 0,
489
+ loaded: false,
490
+ playTimeout: null,
491
+ prev: PlayerState.Loading
492
+ }, this._toLog = null;
493
+ }
494
+ }
495
+
496
+ class ScrollElement extends BaseElement {
497
+ applyScrollProgress() {
498
+ if (!this.animateOnScroll || !this._lottieInstance) {
499
+ return;
500
+ }
501
+ const progress = this._getScrollProgress();
502
+ if (progress === null) {
503
+ return;
504
+ }
505
+ const { totalFrames } = this._lottieInstance, frame = progress * (totalFrames - 1), epsilon = this.subframe ? 0.1 : 0.5;
506
+ if (Math.abs(frame - this._playerState.frame) < epsilon) {
507
+ return;
508
+ }
509
+ this._playerState.frame = frame;
510
+ this._lottieInstance.goToAndStop(frame, true);
511
+ }
512
+ cancelIntersectionObserver() {
513
+ // Remove intersection observer for detecting component being out-of-view
514
+ this._intersectionObserver?.disconnect();
515
+ this._intersectionObserver = undefined;
516
+ }
517
+ cancelScrollProbe() {
518
+ this._scrollProbe?.cancel();
519
+ this._scrollProbe = undefined;
520
+ }
521
+ scrollLoop() {
522
+ this._playerState.scrollLoopId = requestAnimationFrame(this.scrollLoop);
523
+ this.applyScrollProgress();
524
+ }
525
+ startScrollLoop() {
526
+ if (isServer) {
527
+ this.devLog('DotLottie: Scroll animations will not work in a Server Side Rendering context. Try to wrap this in a client component.');
528
+ return;
529
+ }
530
+ this._playerState.scrollLoopId ??= requestAnimationFrame(this.scrollLoop);
531
+ }
532
+ stopScrollLoop() {
533
+ if (this._playerState.scrollLoopId === undefined) {
534
+ return;
535
+ }
536
+ cancelAnimationFrame(this._playerState.scrollLoopId);
537
+ this._playerState.scrollLoopId = undefined;
538
+ this.applyScrollProgress();
539
+ }
540
+ /**
541
+ * Add IntersectionObserver.
542
+ */ _addIntersectionObserver() {
543
+ if (!this._container || this._intersectionObserver || !hasIOSupport) {
544
+ return;
545
+ }
546
+ this._intersectionObserver = new IntersectionObserver(([{ isIntersecting }])=>{
547
+ this.isIntersecting = isIntersecting;
548
+ // Prevent animate on scroll for users with who prefers reduces motion.
549
+ if (this.animateOnScroll && !hasReducedMotion) {
550
+ if (isIntersecting) {
551
+ this.startScrollLoop();
552
+ return;
553
+ }
554
+ this.stopScrollLoop();
555
+ return;
556
+ }
557
+ if (!isIntersecting || document.hidden) {
558
+ if (this.playerState === PlayerState.Playing) {
559
+ this._freeze();
560
+ }
561
+ return;
562
+ }
563
+ if (!this.playOnVisible && this.playerState === PlayerState.Frozen && !(this.autoplay && hasReducedMotion)) {
564
+ this.play();
565
+ }
566
+ if (!this.playOnVisible || hasReducedMotion) {
567
+ return;
568
+ }
569
+ if (this.playerState === PlayerState.Completed && !this.once) {
570
+ this.playerState = PlayerState.Playing;
571
+ this._lottieInstance?.goToAndPlay(this.direction === 1 ? 0 : this._lottieInstance.totalFrames);
572
+ return;
573
+ }
574
+ this._playerState.playTimeout = setTimeout(()=>{
575
+ this.play();
576
+ }, this.delay);
577
+ if (this.playerState !== PlayerState.Playing) {
578
+ return;
579
+ }
580
+ clearTimeout(this._playerState.playTimeout);
581
+ });
582
+ this._observeIntersectionTarget();
583
+ }
584
+ _canDriveTimeline({ source }) {
585
+ if (!source || source === document.scrollingElement) {
586
+ return true;
587
+ }
588
+ return getComputedStyle(source).overflowY !== 'hidden' && source.scrollHeight > source.clientHeight;
589
+ }
590
+ _getGeometricScrollProgress() {
591
+ if (!this._container) {
592
+ return null;
593
+ }
594
+ const { height, top } = this._container.getBoundingClientRect(), viewport = visualViewport?.height ?? innerHeight;
595
+ return clamp((viewport - top) / (viewport + height), 0, 1);
596
+ }
597
+ _getScrollProgress() {
598
+ if (!this._container) {
599
+ return null;
600
+ }
601
+ if (!hasVTSupport) {
602
+ return this._getGeometricScrollProgress();
603
+ }
604
+ const timeline = new ViewTimeline({
605
+ axis: 'block',
606
+ subject: this._container
607
+ }), canDriveTimeline = this._canDriveTimeline(timeline);
608
+ if (!canDriveTimeline) {
609
+ this.devLog('[dotlottie-player] animateOnScroll: the player\'s nearest scrolling ancestor cannot ' + 'scroll, so its ViewTimeline would never advance. This is almost always an ancestor ' + 'with `overflow: hidden` — use `overflow: clip` instead. Falling back to viewport ' + 'measurement.');
610
+ return this._getGeometricScrollProgress();
611
+ }
612
+ this._scrollProbe ??= this._container.animate({
613
+ '--dotlottie-scroll': [
614
+ 0,
615
+ 1
616
+ ]
617
+ }, {
618
+ fill: 'both',
619
+ rangeEnd: 'cover 100%',
620
+ rangeStart: 'cover 0%',
621
+ timeline
622
+ });
623
+ return this._scrollProbe.effect?.getComputedTiming().progress ?? null;
624
+ }
625
+ _observeIntersectionTarget() {
626
+ if (!this._intersectionObserver || !this._container) {
627
+ return;
628
+ }
629
+ this._intersectionObserver.disconnect();
630
+ // Observing the host is more reliable than inner shadow nodes when ancestors
631
+ // use overflow-* (IO / layout interaction quirks).
632
+ this._intersectionObserver.observe(this._container);
633
+ }
634
+ constructor(...args){
635
+ super(...args), this.isIntersecting = false;
636
+ }
637
+ }
638
+
639
+ let dotlottieTools = null, loadPromise = null;
640
+ function loadDotLottieTools() {
641
+ if (dotlottieTools) {
642
+ return Promise.resolve(dotlottieTools);
643
+ }
644
+ loadPromise = loadPromise ?? (async ()=>{
645
+ const { addAnimation, convert } = await import('@aarsteinmedia/lottie-web/dotlottie');
646
+ dotlottieTools = {
647
+ addAnimation,
648
+ convert
649
+ };
650
+ return {
651
+ addAnimation,
652
+ convert
653
+ };
654
+ })();
655
+ return loadPromise;
656
+ }
657
+
658
+ const boomerangIcon = /* HTML */ `<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>`;
659
+
660
+ const convertIcon = /* HTML */ `<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>`;
661
+
662
+ const downloadIcon = /* HTML */ `<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>`;
663
+
664
+ const loopIcon = /* HTML */ `<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>`;
665
+
666
+ const nextIcon = /* HTML */ `<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>`;
667
+
668
+ const pauseIcon = /* 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>`;
669
+
670
+ const playIcon = /* 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>`;
671
+
672
+ const prevIcon = /* HTML */ `<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>`;
673
+
674
+ const settingsIcon = /* HTML */ `<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>`;
675
+
676
+ const stopIcon = /* HTML */ `<svg width="24" height="24" aria-hidden="true" focusable="false"><path d="M6 6h12v12H6V6z"/></svg>`;
677
+
678
+ function advancedButtons() {
679
+ if (!this.shadow) {
680
+ return;
681
+ }
682
+ const toggleLoop = this.shadow.querySelector('.toggleLoop');
683
+ if (toggleLoop instanceof HTMLButtonElement) {
684
+ toggleLoop.onclick = this.toggleLoop;
685
+ }
686
+ const toggleBoomerang = this.shadow.querySelector('.toggleBoomerang');
687
+ if (toggleBoomerang instanceof HTMLButtonElement) {
688
+ toggleBoomerang.onclick = this.toggleBoomerang;
689
+ }
690
+ const convertButton = this.shadow.querySelector('.convert');
691
+ if (convertButton instanceof HTMLButtonElement) {
692
+ convertButton.onclick = async ()=>{
693
+ convertButton.disabled = true;
694
+ try {
695
+ const { convert } = await loadDotLottieTools();
696
+ await convert({
697
+ isDotLottie: this.isDotLottie,
698
+ manifest: this.getManifest(),
699
+ src: this.src || this.source
700
+ });
701
+ } finally{
702
+ convertButton.disabled = false;
703
+ }
704
+ };
705
+ }
706
+ const snapshot = this.shadow.querySelector('.snapshot');
707
+ if (snapshot instanceof HTMLButtonElement) {
708
+ snapshot.onclick = ()=>this.snapshot(true);
709
+ }
710
+ const toggleSettings = this.shadow.querySelector('.toggleSettings');
711
+ if (toggleSettings instanceof HTMLButtonElement) {
712
+ toggleSettings.onclick = this._handleSettingsClick;
713
+ toggleSettings.onblur = this._handleBlur;
714
+ }
715
+ }
716
+ function handleButtons() {
717
+ if (!this.shadow) {
718
+ return;
595
719
  }
596
- get quiet() {
597
- const val = this.getAttribute('quiet');
598
- return parseHTMLBooleans(val);
720
+ const togglePlay = this.shadow.querySelector('.togglePlay');
721
+ if (togglePlay instanceof HTMLButtonElement) {
722
+ togglePlay.onclick = this.togglePlay;
599
723
  }
600
- /**
601
- * Renderer to use: svg, canvas or html.
602
- */ set renderer(value) {
603
- this.setAttribute('renderer', value);
724
+ const stopButton = this.shadow.querySelector('.stop');
725
+ if (stopButton instanceof HTMLButtonElement) {
726
+ stopButton.onclick = this.stop;
604
727
  }
605
- get renderer() {
606
- const val = this.getAttribute('renderer');
607
- if (val === RendererType.Canvas || val === RendererType.HTML) {
608
- return val;
728
+ const prevButton = this.shadow.querySelector('.prev');
729
+ if (prevButton instanceof HTMLButtonElement) {
730
+ if (this.animations.length > 0 && this.currentAnimation) {
731
+ prevButton.hidden = false;
609
732
  }
610
- return RendererType.SVG;
733
+ prevButton.onclick = this.prev;
611
734
  }
612
- /**
613
- * Play on clicked element by id attribute, other than animation.
614
- */ set selector(value) {
615
- if (value) {
616
- this.setAttribute('selector', value);
617
- return;
735
+ const nextButton = this.shadow.querySelector('.next');
736
+ if (nextButton instanceof HTMLButtonElement) {
737
+ if (this.animations.length > 0 && this.currentAnimation < this.animations.length - 1) {
738
+ nextButton.hidden = false;
618
739
  }
619
- this.removeAttribute('selector');
740
+ nextButton.onclick = this.next;
620
741
  }
621
- get selector() {
622
- return this.getAttribute('selector');
742
+ const seeker = this.shadow.querySelector('.seeker');
743
+ if (seeker instanceof HTMLInputElement) {
744
+ seeker.onchange = this._handleSeekChange;
745
+ seeker.onmousedown = this._freeze;
623
746
  }
624
- /**
625
- * Hide advanced controls.
626
- */ set simple(value) {
627
- this.setAttribute('simple', Boolean(value).toString());
747
+ if (this.simple) {
748
+ return;
628
749
  }
629
- get simple() {
630
- const val = this.getAttribute('simple');
631
- return parseHTMLBooleans(val);
750
+ advancedButtons.call(this);
751
+ }
752
+ /**
753
+ * Render Controls.
754
+ */ function renderControls() {
755
+ if (!this.shadow) {
756
+ throw new Error('No Shadow Element');
632
757
  }
633
- /**
634
- * Speed.
635
- */ set speed(value) {
636
- this.setAttribute('speed', value.toString());
758
+ const slot = this.shadow.querySelector('slot[name=controls]');
759
+ if (!slot) {
760
+ return;
637
761
  }
638
- get speed() {
639
- const val = this.getAttribute('speed');
640
- if (val !== null && !isNaN(Number(val))) {
641
- return Number(val);
642
- }
643
- return 1;
762
+ if (!this.controls) {
763
+ slot.innerHTML = '';
764
+ return;
644
765
  }
645
- /**
646
- * Source, either path or JSON string.
647
- */ set src(value) {
648
- this.setAttribute('src', value || '');
766
+ const convertLabel = this.isDotLottie ? 'dotLottie animation to JSON format' : 'JSON animation to dotLottie format', convertButtonText = this.isDotLottie ? 'Convert to JSON' : 'Convert to dotLottie';
767
+ slot.innerHTML = /* HTML */ `<div class="lottie-controls toolbar ${this.playerState === PlayerState.Error ? 'has-error' : ''}" aria-label="Lottie Animation controls"><button class="togglePlay" data-active="${this.autoplay}" aria-label="Toggle Play/Pause">${playIcon}</button> <button class="stop" data-active="${!this.autoplay}" aria-label="Stop">${stopIcon}</button> <button class="prev" aria-label="Previous animation" hidden="false">${prevIcon}</button> <button class="next" aria-label="Next animation" hidden>${nextIcon}</button><form class="progress-container${this.simple ? ' simple' : ''}"><input type="range" class="seeker" min="0" max="100" step="1" value="${this._seeker.toString()}" aria-valuemin="0" aria-valuemax="100" 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">${loopIcon}</button> <button class="toggleBoomerang" data-active="${this.mode === PlayMode.Bounce}" aria-label="Toggle boomerang" tabindex="0">${boomerangIcon}</button> <button class="toggleSettings" aria-label="Settings" aria-haspopup="true" aria-expanded="${this._isSettingsOpen}" aria-controls="${this._identifier}-settings">${settingsIcon}</button><div id="${this._identifier}-settings" class="popover" hidden><button class="convert" aria-label="Convert ${convertLabel}" hidden>${convertIcon} ${convertButtonText}</button> <button class="snapshot" aria-label="Download still image">${downloadIcon} Download still image</button></div>`}</div>`;
768
+ handleButtons.call(this);
769
+ }
770
+ function updatePlayPauseButton(togglePlay, state) {
771
+ const isActive = state === PlayerState.Playing || state === PlayerState.Paused;
772
+ togglePlay.dataset.active = isActive.toString();
773
+ togglePlay.innerHTML = state === PlayerState.Playing ? pauseIcon : playIcon;
774
+ }
775
+
776
+ var controls = /*#__PURE__*/Object.freeze({
777
+ __proto__: null,
778
+ renderControls: renderControls,
779
+ updatePlayPauseButton: updatePlayPauseButton
780
+ });
781
+
782
+ /**
783
+ * Render Player.
784
+ */ function renderPlayer() {
785
+ if (!this.shadow || !this.template) {
786
+ throw new Error('No Shadow Element or Template');
649
787
  }
650
- get src() {
651
- return this.getAttribute('src');
788
+ let langAttribute = '';
789
+ /**
790
+ * If player has aria-description, it's safe to assume
791
+ * language should be the same as `document.documentElement.lang`.
792
+ * Accessible labels on controls are only in English, so with no
793
+ * aria tag, and controls enabled, lang should reflect this.
794
+ * With neither controls or description, the lang attribute is
795
+ * not needed.
796
+ */ if (this.description || this.controls) {
797
+ const lang = this.description ? document.documentElement.lang : 'en';
798
+ langAttribute = `lang="${lang}"`;
652
799
  }
800
+ this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" ${langAttribute}><figure class="animation" style="background:${this.background}" ${this.description ? `aria-label="${this.description}"` : ''}></figure><slot name="controls"></slot></div>`;
801
+ this.shadow.appendChild(this.template.content.cloneNode(true));
802
+ }
803
+
804
+ const notImplemented = 'Method is not implemented';
805
+ /**
806
+ * DotLottie Player Web Component.
807
+ */ class DotLottiePlayerBase extends ScrollElement {
653
808
  /**
654
- * Subframe.
655
- */ set subframe(value) {
656
- this.setAttribute('subframe', Boolean(value).toString());
809
+ * Attributes to observe.
810
+ */ static get observedAttributes() {
811
+ return [
812
+ 'animateOnScroll',
813
+ 'autoplay',
814
+ 'controls',
815
+ 'direction',
816
+ 'hover',
817
+ 'loop',
818
+ 'mode',
819
+ 'playOnClick',
820
+ 'playOnVisible',
821
+ 'selector',
822
+ 'speed',
823
+ 'src',
824
+ 'subframe'
825
+ ];
657
826
  }
658
- get subframe() {
659
- const val = this.getAttribute('subframe');
660
- return parseHTMLBooleans(val);
827
+ static get observedProperties() {
828
+ return [
829
+ 'playerState',
830
+ '_isSettingsOpen',
831
+ '_seeker',
832
+ '_currentAnimation',
833
+ '_animations'
834
+ ];
835
+ }
836
+ get isDotLottie() {
837
+ return this._isDotLottie;
661
838
  }
662
839
  constructor(){
663
840
  super(), this.isLight = false, /**
664
- * Player state.
665
- */ this.playerState = PlayerState.Loading, /**
666
- * Animation Container.
667
- */ this._container = null, this._errorMessage = 'Something went wrong', this._identifier = this.id || createElementID(), /**
668
841
  * Whether settings toolbar is open.
669
- */ this._isSettingsOpen = false, this._playerState = {
670
- count: 0,
671
- frame: 0,
672
- loaded: false,
673
- playTimeout: null,
674
- prev: PlayerState.Loading
675
- }, this._render = renderPlayer, /**
842
+ */ this._isSettingsOpen = false, /**
676
843
  * Seeker.
677
- */ this._seeker = 0, /**
678
- * This is included in watched properties,
679
- * so that next-button will show up
680
- * on load, if controls are visible.
681
- */ this._animations = [], this._controlsLoadId = 0, /**
682
- * Which animation to show, if several.
683
- */ this._currentAnimation = 0, this._errorLoadId = 0, this._isBounce = false, this._isDotLottie = false, this._isIntersecting = false, this._lottieInstance = null, /**
844
+ */ this._seeker = 0, this._controlsLoadId = 0, this._errorLoadId = 0, this._isBounce = false, this._isDotLottie = false, /**
684
845
  * Multi-animation settings.
685
846
  */ this._multiAnimationSettings = [], this._renderControls = async ()=>{
686
847
  const slot = this.shadow?.querySelector('slot[name=controls]');
@@ -711,7 +872,8 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
711
872
  this._mouseEnter = this._mouseEnter.bind(this);
712
873
  this._mouseLeave = this._mouseLeave.bind(this);
713
874
  this._onVisibilityChange = this._onVisibilityChange.bind(this);
714
- this._scrollLoop = this._scrollLoop.bind(this);
875
+ this.scrollLoop = this.scrollLoop.bind(this);
876
+ // this.startScrollLoop = this.startScrollLoop.bind(this)
715
877
  this._switchInstance = this._switchInstance.bind(this);
716
878
  this._handleSettingsClick = this._handleSettingsClick.bind(this);
717
879
  this.togglePlay = this.togglePlay.bind(this);
@@ -737,17 +899,18 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
737
899
  if (!this._lottieInstance || !this.shadow || !this._container) {
738
900
  return;
739
901
  }
902
+ this.clearDevLog();
740
903
  switch(name){
741
904
  case 'animateOnScroll':
742
905
  {
743
906
  if (value === '' || Boolean(value)) {
744
907
  this._lottieInstance.autoplay = false;
745
- if (this._isIntersecting) {
746
- this._startScrollLoop();
908
+ if (this.isIntersecting) {
909
+ this.startScrollLoop();
747
910
  }
748
911
  return;
749
912
  }
750
- this._stopScrollLoop();
913
+ this.stopScrollLoop();
751
914
  break;
752
915
  }
753
916
  case 'autoplay':
@@ -885,11 +1048,11 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
885
1048
  if (!this._lottieInstance?.destroy) {
886
1049
  return;
887
1050
  }
888
- this._cancelScrollProbe();
1051
+ this.cancelScrollProbe();
889
1052
  this.playerState = PlayerState.Destroyed;
890
1053
  this._lottieInstance.destroy();
891
1054
  this._lottieInstance = null;
892
- this._stopScrollLoop();
1055
+ this.stopScrollLoop();
893
1056
  this.dispatchEvent(new CustomEvent(PlayerEvent.Destroyed));
894
1057
  this.remove();
895
1058
  document.removeEventListener('visibilitychange', this._onVisibilityChange);
@@ -897,10 +1060,8 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
897
1060
  /**
898
1061
  * Cleanup on component destroy.
899
1062
  */ disconnectedCallback() {
900
- // Remove intersection observer for detecting component being out-of-view
901
- this._intersectionObserver?.disconnect();
902
- this._intersectionObserver = undefined;
903
- this._cancelScrollProbe();
1063
+ this.cancelIntersectionObserver();
1064
+ this.cancelScrollProbe();
904
1065
  if (this._playerState.scrollLoopId) {
905
1066
  cancelAnimationFrame(this._playerState.scrollLoopId);
906
1067
  }
@@ -911,6 +1072,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
911
1072
  document.removeEventListener('visibilitychange', this._onVisibilityChange);
912
1073
  // Destroy the animation instance
913
1074
  this.destroy();
1075
+ this.clearDevLog();
914
1076
  }
915
1077
  /**
916
1078
  * Returns the lottie-web instance used in the component.
@@ -990,7 +1152,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
990
1152
  this._lottieInstance.setSubframe(Boolean(this.subframe));
991
1153
  // Set progress on load if AnimateOnScroll
992
1154
  if (this.animateOnScroll) {
993
- this._applyScrollProgress();
1155
+ this.applyScrollProgress();
994
1156
  }
995
1157
  // Start playing if autoplay is enabled
996
1158
  if ((this.autoplay || this.animateOnScroll || this.playOnVisible) && this.direction === -1) {
@@ -1023,7 +1185,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1023
1185
  this.dispatchEvent(new CustomEvent(PlayerEvent.Pause));
1024
1186
  } catch (error) {
1025
1187
  hasError = true;
1026
- console.error(error);
1188
+ this.devLog(error);
1027
1189
  } finally{
1028
1190
  this.playerState = hasError ? PlayerState.Error : PlayerState.Paused;
1029
1191
  }
@@ -1041,7 +1203,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1041
1203
  this.dispatchEvent(new CustomEvent(PlayerEvent.Play));
1042
1204
  } catch (error) {
1043
1205
  hasError = true;
1044
- console.error(error);
1206
+ this.devLog(error);
1045
1207
  } finally{
1046
1208
  this.playerState = hasError ? PlayerState.Error : PlayerState.Playing;
1047
1209
  }
@@ -1197,7 +1359,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1197
1359
  }
1198
1360
  return data;
1199
1361
  } catch (error) {
1200
- console.error(error);
1362
+ this.devLog(error);
1201
1363
  return null;
1202
1364
  }
1203
1365
  }
@@ -1323,6 +1485,15 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1323
1485
  target.focus();
1324
1486
  }
1325
1487
  }
1488
+ async _render() {
1489
+ if (!this.shadow) {
1490
+ return;
1491
+ }
1492
+ renderPlayer.call(this);
1493
+ this.shadow.adoptedStyleSheets = [
1494
+ await DotLottiePlayerBase.styles()
1495
+ ];
1496
+ }
1326
1497
  async _showError() {
1327
1498
  if (this.playerState !== PlayerState.Error) {
1328
1499
  return;
@@ -1350,68 +1521,6 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1350
1521
  */ _addEventListeners() {
1351
1522
  this._toggleEventListeners('add');
1352
1523
  }
1353
- /**
1354
- * Add IntersectionObserver.
1355
- */ _addIntersectionObserver() {
1356
- if (!this._container || this._intersectionObserver || !hasIOSupport) {
1357
- return;
1358
- }
1359
- this._intersectionObserver = new IntersectionObserver(([{ isIntersecting }])=>{
1360
- this._isIntersecting = isIntersecting;
1361
- // Prevent animate on scroll for users with who prefers reduces motion.
1362
- if (this.animateOnScroll && !hasReducedMotion) {
1363
- if (isIntersecting) {
1364
- this._startScrollLoop();
1365
- } else {
1366
- this._stopScrollLoop();
1367
- }
1368
- return;
1369
- }
1370
- if (!isIntersecting || document.hidden) {
1371
- if (this.playerState === PlayerState.Playing) {
1372
- this._freeze();
1373
- }
1374
- return;
1375
- }
1376
- if (!this.playOnVisible && this.playerState === PlayerState.Frozen && !(this.autoplay && hasReducedMotion)) {
1377
- this.play();
1378
- }
1379
- if (!this.playOnVisible || hasReducedMotion) {
1380
- return;
1381
- }
1382
- if (this.playerState === PlayerState.Completed && !this.once) {
1383
- this.playerState = PlayerState.Playing;
1384
- this._lottieInstance?.goToAndPlay(this.direction === 1 ? 0 : this._lottieInstance.totalFrames);
1385
- return;
1386
- }
1387
- this._playerState.playTimeout = setTimeout(()=>{
1388
- this.play();
1389
- }, this.delay);
1390
- if (this.playerState === PlayerState.Playing) {
1391
- clearTimeout(this._playerState.playTimeout);
1392
- }
1393
- });
1394
- this._intersectionObserver.observe(this._container);
1395
- }
1396
- _applyScrollProgress() {
1397
- if (!this.animateOnScroll || !this._lottieInstance) {
1398
- return;
1399
- }
1400
- const progress = this._getScrollProgress();
1401
- if (progress === null) {
1402
- return;
1403
- }
1404
- const { totalFrames } = this._lottieInstance, frame = progress * (totalFrames - 1), epsilon = this.subframe ? 0.1 : 0.5;
1405
- if (Math.abs(frame - this._playerState.frame) < epsilon) {
1406
- return;
1407
- }
1408
- this._playerState.frame = frame;
1409
- this._lottieInstance.goToAndStop(frame, true);
1410
- }
1411
- _cancelScrollProbe() {
1412
- this._scrollProbe?.cancel();
1413
- this._scrollProbe = undefined;
1414
- }
1415
1524
  _clearPrevious() {
1416
1525
  this._lottieInstance?.destroy();
1417
1526
  const figure = this.shadow?.querySelector('.animation');
@@ -1514,30 +1623,6 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1514
1623
  rendererType: this.renderer
1515
1624
  });
1516
1625
  }
1517
- _getScrollProgress() {
1518
- if (!this._container) {
1519
- return null;
1520
- }
1521
- if (hasVTSupport) {
1522
- this._scrollProbe ??= this._container.animate({
1523
- '--dotlottie-scroll': [
1524
- 0,
1525
- 1
1526
- ]
1527
- }, {
1528
- fill: 'both',
1529
- rangeEnd: 'cover 100%',
1530
- rangeStart: 'cover 0%',
1531
- timeline: new ViewTimeline({
1532
- axis: 'block',
1533
- subject: this._container
1534
- })
1535
- });
1536
- return this._scrollProbe.effect?.getComputedTiming().progress ?? null;
1537
- }
1538
- const { height, top } = this._container.getBoundingClientRect(), viewport = visualViewport?.height ?? innerHeight;
1539
- return clamp((viewport - top) / (viewport + height), 0, 1);
1540
- }
1541
1626
  async _handleError(error) {
1542
1627
  this.playerState = PlayerState.Error;
1543
1628
  if (!this.quiet) {
@@ -1545,7 +1630,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1545
1630
  await this._showError();
1546
1631
  }
1547
1632
  this.dispatchEvent(new CustomEvent(PlayerEvent.Error));
1548
- console.error(error);
1633
+ this.devLog(error);
1549
1634
  }
1550
1635
  _handleLdScript() {
1551
1636
  const ldScript = this.parentElement?.querySelector('script[type="application/ld+json"]');
@@ -1691,25 +1776,6 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1691
1776
  */ _removeEventListeners() {
1692
1777
  this._toggleEventListeners('remove');
1693
1778
  }
1694
- _scrollLoop() {
1695
- this._playerState.scrollLoopId = requestAnimationFrame(this._scrollLoop);
1696
- this._applyScrollProgress();
1697
- }
1698
- _startScrollLoop() {
1699
- if (isServer) {
1700
- console.warn('DotLottie: Scroll animations will not work in a Server Side Rendering context. Try to wrap this in a client component.');
1701
- return;
1702
- }
1703
- this._playerState.scrollLoopId ??= requestAnimationFrame(this._scrollLoop);
1704
- }
1705
- _stopScrollLoop() {
1706
- if (this._playerState.scrollLoopId === undefined) {
1707
- return;
1708
- }
1709
- cancelAnimationFrame(this._playerState.scrollLoopId);
1710
- this._playerState.scrollLoopId = undefined;
1711
- this._applyScrollProgress();
1712
- }
1713
1779
  _switchInstance(isPrevious = false) {
1714
1780
  // Bail early if there is not animation to play
1715
1781
  if (!this._animations[this._currentAnimation]) {
@@ -1718,7 +1784,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1718
1784
  try {
1719
1785
  // Clear previous animation
1720
1786
  this._lottieInstance?.destroy();
1721
- this._cancelScrollProbe();
1787
+ this.cancelScrollProbe();
1722
1788
  // Re-initialize lottie player
1723
1789
  this._lottieInstance = this.loadAnimation({
1724
1790
  ...this._getOptions(),
@@ -1735,7 +1801,7 @@ const notImplemented = 'Method is not implemented', getStyles = async ()=>{
1735
1801
  if (this._multiAnimationSettings[this._currentAnimation]?.autoplay ?? this.autoplay) {
1736
1802
  if (this.animateOnScroll) {
1737
1803
  // Get instant scroll position
1738
- this._applyScrollProgress();
1804
+ this.applyScrollProgress();
1739
1805
  this.playerState = PlayerState.Paused;
1740
1806
  return;
1741
1807
  }