@aarsteinmedia/dotlottie-player 5.2.4 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { isServer, createElementID, PreserveAspectRatio as PreserveAspectRatio$1, RendererType, PlayerEvents } from '@aarsteinmedia/lottie-web/utils';
2
- export { PlayerEvents } from '@aarsteinmedia/lottie-web/utils';
1
+ import { isServer, PlayMode, PreserveAspectRatio, namespaceSVG, RendererType, createElementID, PlayerEvents, download, getFilename } from '@aarsteinmedia/lottie-web/utils';
2
+ export { PlayMode, PlayerEvents } from '@aarsteinmedia/lottie-web/utils';
3
3
  import Lottie from '@aarsteinmedia/lottie-web';
4
- import { strToU8, zip, strFromU8, unzip as unzip$1 } from 'fflate';
4
+ import { convert, addAnimation, getAnimationData } from '@aarsteinmedia/lottie-web/dotlottie';
5
5
 
6
6
  /**
7
7
  * Credit to: Leonardo Favre https://github.com/leofavre/observed-properties.
@@ -41,8 +41,7 @@ if (isServer) {
41
41
  }
42
42
  }
43
43
  }
44
- // eslint-disable-next-line @typescript-eslint/require-await
45
- async connectedCallback() {
44
+ connectedCallback() {
46
45
  let arr = [];
47
46
  if (updateOnConnected in this && Array.isArray(this[updateOnConnected])) {
48
47
  arr = this[updateOnConnected];
@@ -64,6 +63,80 @@ if (isServer) {
64
63
 
65
64
  var css_248z = "* {\n box-sizing: border-box;\n}\n\n:host {\n --lottie-player-toolbar-height: 35px;\n --lottie-player-toolbar-background-color: #fff;\n --lottie-player-toolbar-icon-color: #000;\n --lottie-player-toolbar-icon-hover-color: #000;\n --lottie-player-toolbar-icon-active-color: #4285f4;\n --lottie-player-seeker-track-color: rgb(0 0 0 / 20%);\n --lottie-player-seeker-thumb-color: #4285f4;\n --lottie-player-seeker-display: block;\n\n width: 100%;\n height: 100%;\n\n &:not([hidden]) {\n display: block;\n }\n\n .main {\n display: flex;\n flex-direction: column;\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n }\n\n .animation {\n width: 100%;\n height: 100%;\n display: flex;\n margin: 0;\n padding: 0;\n }\n\n [data-controls='true'] .animation {\n height: calc(100% - 35px);\n }\n\n .animation-container {\n position: relative;\n }\n\n .popover {\n position: absolute;\n right: 5px;\n bottom: 40px;\n background-color: var(--lottie-player-toolbar-background-color);\n border-radius: 5px;\n padding: 10px 15px;\n border: solid 2px var(--lottie-player-toolbar-icon-color);\n animation: fade-in 0.2s ease-in-out;\n\n &::before {\n content: '';\n right: 10px;\n border: 7px solid transparent;\n margin-right: -7px;\n height: 0;\n width: 0;\n position: absolute;\n pointer-events: none;\n top: 100%;\n border-top-color: var(--lottie-player-toolbar-icon-color);\n }\n }\n\n .error {\n display: flex;\n margin: auto;\n justify-content: center;\n height: 100%;\n align-items: center;\n\n & svg {\n width: 100%;\n height: auto;\n }\n }\n\n .toolbar {\n display: flex;\n place-items: center center;\n background: var(--lottie-player-toolbar-background-color);\n margin: 0;\n height: 35px;\n padding: 5px;\n border-radius: 5px;\n gap: 5px;\n\n &.has-error {\n pointer-events: none;\n opacity: 0.5;\n }\n\n & button {\n cursor: pointer;\n fill: var(--lottie-player-toolbar-icon-color);\n color: var(--lottie-player-toolbar-icon-color);\n background: none;\n border: 0;\n padding: 0;\n outline: 0;\n height: 100%;\n margin: 0;\n align-items: center;\n gap: 5px;\n opacity: 0.9;\n\n &:not([hidden]) {\n display: flex;\n }\n\n &:hover {\n opacity: 1;\n }\n\n &[data-active='true'] {\n opacity: 1;\n fill: var(--lottie-player-toolbar-icon-active-color);\n }\n\n &:disabled {\n opacity: 0.5;\n }\n\n &:focus {\n outline: 0;\n }\n\n & svg {\n pointer-events: none;\n\n & > * {\n fill: inherit;\n }\n }\n\n &.disabled svg {\n display: none;\n }\n }\n }\n\n .progress-container {\n position: relative;\n width: 100%;\n\n &.simple {\n margin-right: 12px;\n }\n }\n\n .seeker {\n appearance: none;\n outline: none;\n width: 100%;\n height: 20px;\n border-radius: 3px;\n border: 0;\n cursor: pointer;\n background-color: transparent;\n\n display: var(--lottie-player-seeker-display);\n color: var(--lottie-player-seeker-thumb-color);\n margin: 0;\n padding: 7.5px 0;\n position: relative;\n z-index: 1;\n\n &::-webkit-slider-runnable-track,\n &::-webkit-slider-thumb {\n appearance: none;\n outline: none;\n }\n\n &::-webkit-slider-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n border: 0;\n background-color: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -webkit-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-webkit-slider-thumb,\n &:focus::-webkit-slider-thumb {\n transform: scale(1);\n }\n\n &::-moz-range-progress {\n background-color: var(--lottie-player-seeker-thumb-color);\n height: 5px;\n border-radius: 3px;\n }\n\n &::-moz-range-thumb {\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background-color: var(--lottie-player-seeker-thumb-color);\n border: 0;\n cursor: pointer;\n -moz-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-moz-range-thumb,\n &:focus::-moz-range-thumb {\n transform: scale(1);\n }\n\n &::-ms-track {\n width: 100%;\n height: 5px;\n cursor: pointer;\n background: transparent;\n border-color: transparent;\n color: transparent;\n }\n\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n border-radius: 3px;\n }\n\n &::-ms-fill-lower {\n background-color: var(--lottie-player-seeker-thumb-color);\n border-radius: 3px;\n }\n\n &::-ms-thumb {\n border: 0;\n height: 15px;\n width: 15px;\n border-radius: 50%;\n background: var(--lottie-player-seeker-thumb-color);\n cursor: pointer;\n -ms-transition: transform 0.2s ease-in-out;\n transition: transform 0.2s ease-in-out;\n transform: scale(0);\n }\n\n &:hover::-ms-thumb {\n transform: scale(1);\n }\n\n &:focus {\n &::-ms-thumb {\n transform: scale(1);\n }\n\n &::-ms-fill-lower,\n &::-ms-fill-upper {\n background: var(--lottie-player-seeker-track-color);\n }\n }\n }\n\n & progress {\n appearance: none;\n outline: none;\n position: absolute;\n width: 100%;\n height: 5px;\n border-radius: 3px;\n border: 0;\n top: 0;\n left: 0;\n margin: 7.5px 0;\n background-color: var(--lottie-player-seeker-track-color);\n pointer-events: none;\n\n &::-webkit-progress-inner-element {\n border-radius: 3px;\n overflow: hidden;\n }\n\n &::-webkit-slider-runnable-track {\n background-color: transparent;\n }\n\n &::-webkit-progress-value {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n }\n\n & *::-moz-progress-bar {\n background-color: var(--lottie-player-seeker-thumb-color);\n }\n}\n\n@keyframes fade-in {\n 0% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n@media (prefers-color-scheme: dark) {\n :host {\n --lottie-player-toolbar-background-color: #000;\n --lottie-player-toolbar-icon-color: #fff;\n --lottie-player-toolbar-icon-hover-color: #fff;\n --lottie-player-seeker-track-color: rgb(255 255 255 / 60%);\n }\n}\n";
66
65
 
66
+ const boomerangIcon = /* HTML */ `
67
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
68
+ <path
69
+ 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"
70
+ />
71
+ </svg>
72
+ `;
73
+
74
+ const convertIcon = /* HTML */ `
75
+ <svg
76
+ width="24"
77
+ height="24"
78
+ aria-hidden="true"
79
+ focusable="false"
80
+ >
81
+ <path
82
+ 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"
83
+ />
84
+ </svg>
85
+ `;
86
+
87
+ const downloadIcon = /* HTML */ `
88
+ <svg
89
+ width="24"
90
+ height="24"
91
+ aria-hidden="true"
92
+ focusable="false"
93
+ >
94
+ <path
95
+ 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"
96
+ />
97
+ </svg>
98
+ `;
99
+
100
+ const loopIcon = /* HTML */ `
101
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
102
+ <path
103
+ 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"
104
+ />
105
+ </svg>
106
+ `;
107
+
108
+ const nextIcon = /* HTML */ `
109
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
110
+ <path d="m6.1 5.8 9.8 6.2-9.8 6.2V5.8zM16.4 5.8h1.5v12.4h-1.5z" />
111
+ </svg>
112
+ `;
113
+
114
+ const playIcon = /* HTML */ `
115
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
116
+ <path d="M8.016 5.016L18.985 12 8.016 18.984V5.015z" />
117
+ </svg>
118
+ `;
119
+
120
+ const prevIcon = /* HTML */ `
121
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
122
+ <path d="M17.9 18.2 8.1 12l9.8-6.2v12.4zm-10.3 0H6.1V5.8h1.5v12.4z" />
123
+ </svg>
124
+ `;
125
+
126
+ const settingsIcon = /* HTML */ `
127
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
128
+ <circle cx="12" cy="5.4" r="2.5" />
129
+ <circle cx="12" cy="12" r="2.5" />
130
+ <circle cx="12" cy="18.6" r="2.5" />
131
+ </svg>
132
+ `;
133
+
134
+ const stopIcon = /* HTML */ `
135
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
136
+ <path d="M6 6h12v12H6V6z" />
137
+ </svg>
138
+ `;
139
+
67
140
  var ObjectFit = /*#__PURE__*/ function(ObjectFit) {
68
141
  ObjectFit["Contain"] = "contain";
69
142
  ObjectFit["Cover"] = "cover";
@@ -83,18 +156,6 @@ var PlayerState = /*#__PURE__*/ function(PlayerState) {
83
156
  PlayerState["Stopped"] = "stopped";
84
157
  return PlayerState;
85
158
  }({});
86
- var PlayMode = /*#__PURE__*/ function(PlayMode) {
87
- PlayMode["Bounce"] = "bounce";
88
- PlayMode["Normal"] = "normal";
89
- return PlayMode;
90
- }({});
91
- var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
92
- PreserveAspectRatio["Contain"] = "xMidYMid meet";
93
- PreserveAspectRatio["Cover"] = "xMidYMid slice";
94
- PreserveAspectRatio["Initial"] = "none";
95
- PreserveAspectRatio["None"] = "xMinYMin slice";
96
- return PreserveAspectRatio;
97
- }({});
98
159
 
99
160
  /**
100
161
  * Render Controls.
@@ -110,7 +171,7 @@ var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
110
171
  slot.innerHTML = '';
111
172
  return;
112
173
  }
113
- 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="${Boolean(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>`;
174
+ 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>${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="${Boolean(this._isSettingsOpen)}" aria-controls="${this._identifier}-settings">${settingsIcon}</button><div id="${this._identifier}-settings" class="popover" hidden><button class="convert" aria-label="Convert JSON animation to dotLottie format" hidden>${convertIcon} ${this.isDotLottie ? 'Convert to JSON' : 'Convert to dotLottie'}</button> <button class="snapshot" aria-label="Download still image">${downloadIcon} Download still image</button></div>`}</div>`;
114
175
  const togglePlay = this.shadow.querySelector('.togglePlay');
115
176
  if (togglePlay instanceof HTMLButtonElement) {
116
177
  togglePlay.onclick = this.togglePlay;
@@ -141,14 +202,16 @@ var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
141
202
  if (toggleBoomerang instanceof HTMLButtonElement) {
142
203
  toggleBoomerang.onclick = this.toggleBoomerang;
143
204
  }
144
- const convert = this.shadow.querySelector('.convert');
145
- if (convert instanceof HTMLButtonElement) {
146
- convert.onclick = this.convert;
205
+ const convertButton = this.shadow.querySelector('.convert');
206
+ if (convertButton instanceof HTMLButtonElement) {
207
+ convertButton.onclick = ()=>{
208
+ void convert({
209
+ isDotLottie: this.isDotLottie,
210
+ manifest: this.getManifest(),
211
+ src: this.src || this.source
212
+ });
213
+ };
147
214
  }
148
- // const convertJSON = this.shadow.querySelector('.convert-json')
149
- // if (convertJSON instanceof HTMLButtonElement) {
150
- // convertJSON.onclick = this.convertJSON as unknown as () => void
151
- // }
152
215
  const snapshot = this.shadow.querySelector('.snapshot');
153
216
  if (snapshot instanceof HTMLButtonElement) {
154
217
  snapshot.onclick = ()=>this.snapshot(true);
@@ -161,23 +224,27 @@ var PreserveAspectRatio = /*#__PURE__*/ function(PreserveAspectRatio) {
161
224
  }
162
225
  }
163
226
 
227
+ const pauseIcon = /* HTML */ `
228
+ <svg width="24" height="24" aria-hidden="true" focusable="false">
229
+ <path
230
+ d="M14.016 5.016H18v13.969h-3.984V5.016zM6 18.984V5.015h3.984v13.969H6z"
231
+ />
232
+ </svg>
233
+ `;
234
+
164
235
  /**
165
236
  * Render Player.
166
237
  */ async function renderPlayer() {
167
238
  if (!this.shadow) {
168
239
  throw new Error('No Shadow Element');
169
240
  }
170
- this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document.documentElement.lang : 'en'}" aria-label="${this.description ?? 'Lottie animation'}" data-loaded="${this._playerState.loaded}"><figure class="animation" style="background:${this.background}">${this.playerState === PlayerState.Error ? /* HTML */ `<div class="error"><svg preserveAspectRatio="xMidYMid slice" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="1920" height="1080" viewBox="0 0 1920 1080"><path fill="#fff" d="M0 0h1920v1080H0z"/><path fill="#3a6d8b" d="M1190.2 531 1007 212.4c-22-38.2-77.2-38-98.8.5L729.5 531.3c-21.3 37.9 6.1 84.6 49.5 84.6l361.9.3c43.7 0 71.1-47.3 49.3-85.2zM937.3 288.7c.2-7.5 3.3-23.9 23.2-23.9 16.3 0 23 16.1 23 23.5 0 55.3-10.7 197.2-12.2 214.5-.1 1-.9 1.7-1.9 1.7h-18.3c-1 0-1.8-.7-1.9-1.7-1.4-17.5-13.4-162.9-11.9-214.1zm24.2 283.8c-13.1 0-23.7-10.6-23.7-23.7s10.6-23.7 23.7-23.7 23.7 10.6 23.7 23.7-10.6 23.7-23.7 23.7zM722.1 644h112.6v34.4h-70.4V698h58.8v31.7h-58.8v22.6h72.4v36.2H722.1V644zm162 57.1h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6zm78.9 0h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5H963v15.6zm39.5 36.2c0-31.3 22.2-54.8 56.6-54.8 34.4 0 56.2 23.5 56.2 54.8s-21.8 54.6-56.2 54.6c-34.4-.1-56.6-23.3-56.6-54.6zm74 0c0-17.4-6.1-29.1-17.8-29.1-11.7 0-17.4 11.7-17.4 29.1 0 17.4 5.7 29.1 17.4 29.1s17.8-11.8 17.8-29.1zm83.1-36.2h.6c8.3-12.9 18.2-17.8 31.3-17.8 3 0 5.1.4 6.3 1v32.6h-.8c-22.4-3.8-35.6 6.3-35.6 29.5v42.3h-38.2V685.5h36.4v15.6z"/><path fill="none" d="M718.9 807.7h645v285.4h-645z"/><text fill="#3a6d8b" style="text-align:center;position:absolute;left:100%;font-size:47px;font-family:system-ui,-apple-system,BlinkMacSystemFont,'.SFNSText-Regular',sans-serif" x="50%" y="848.017" text-anchor="middle">${this._errorMessage}</text></svg></div>` : ''}</figure><slot name="controls"></slot></div>`;
241
+ this.template.innerHTML = /* HTML */ `<div class="animation-container main" data-controls="${this.controls ?? false}" lang="${this.description ? document.documentElement.lang : 'en'}" aria-label="${this.description ?? 'Lottie animation'}" data-loaded="${this._playerState.loaded}"><figure class="animation" style="background:${this.background}">${this.playerState === PlayerState.Error ? /* HTML */ `<div class="error"><svg preserveAspectRatio="${PreserveAspectRatio.Cover}" xmlns="${namespaceSVG}" width="1920" height="1080" viewBox="0 0 1920 1080" style="white-space:preserve"><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>`;
171
242
  this.shadow.adoptedStyleSheets = [
172
243
  await DotLottiePlayer.styles()
173
244
  ];
174
245
  this.shadow.appendChild(this.template.content.cloneNode(true));
175
246
  }
176
247
 
177
- const hasExt = (path)=>{
178
- const lastDotIndex = path?.split('/').pop()?.lastIndexOf('.');
179
- return (lastDotIndex ?? 0) > 1 && path && path.length - 1 > (lastDotIndex ?? 0);
180
- };
181
248
  /**
182
249
  * Get extension from filename, URL or path.
183
250
  */ const aspectRatio = (objectFit)=>{
@@ -185,76 +252,25 @@ const hasExt = (path)=>{
185
252
  case ObjectFit.Contain:
186
253
  case ObjectFit.ScaleDown:
187
254
  {
188
- return PreserveAspectRatio$1.Contain;
255
+ return PreserveAspectRatio.Contain;
189
256
  }
190
257
  case ObjectFit.Cover:
191
258
  {
192
- return PreserveAspectRatio$1.Cover;
259
+ return PreserveAspectRatio.Cover;
193
260
  }
194
261
  case ObjectFit.Fill:
195
262
  {
196
- return PreserveAspectRatio$1.Initial;
263
+ return PreserveAspectRatio.Initial;
197
264
  }
198
265
  case ObjectFit.None:
199
266
  {
200
- return PreserveAspectRatio$1.None;
267
+ return PreserveAspectRatio.None;
201
268
  }
202
269
  default:
203
270
  {
204
- return PreserveAspectRatio$1.Contain;
271
+ return PreserveAspectRatio.Contain;
205
272
  }
206
273
  }
207
- }, /**
208
- * Download file, either SVG or dotLottie.
209
- */ download = (data, options)=>{
210
- const blob = new Blob([
211
- data
212
- ], {
213
- type: options?.mimeType
214
- }), fileName = options?.name || createElementID(), dataURL = URL.createObjectURL(blob), link = document.createElement('a');
215
- link.href = dataURL;
216
- link.download = fileName;
217
- link.hidden = true;
218
- document.body.appendChild(link);
219
- link.click();
220
- setTimeout(()=>{
221
- link.remove();
222
- URL.revokeObjectURL(dataURL);
223
- }, 1000);
224
- }, getExt = (str)=>{
225
- if (typeof str !== 'string' || !str || !hasExt(str)) {
226
- return;
227
- }
228
- return str.split('.').pop()?.toLowerCase();
229
- }, /**
230
- * Parse URL to get filename.
231
- *
232
- * @param src - The url string.
233
- * @param keepExt - Whether to include file extension.
234
- * @returns Filename, in lowercase.
235
- */ getFilename = (src, keepExt)=>{
236
- // Because the regex strips all special characters, we need to extract the file extension, so we can add it later if we need it
237
- getExt(src);
238
- return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replaceAll(/\W+/g, '-')}${''}`;
239
- }, addExt = (ext, str)=>{
240
- if (!str) {
241
- return;
242
- }
243
- if (getExt(str)) {
244
- if (getExt(str) === ext) {
245
- return str;
246
- }
247
- return `${getFilename(str)}.${ext}`;
248
- }
249
- return `${str}.${ext}`;
250
- }, parseBase64 = (str)=>str.slice(Math.max(0, str.indexOf(',') + 1)), /**
251
- * Convert Base64 encoded string to Uint8Array.
252
- *
253
- * @param str - Base64 encoded string.
254
- * @returns UTF-8/Latin-1 binary.
255
- */ base64ToU8 = (str)=>strToU8(isServer ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), getExtFromB64 = (str)=>{
256
- const mime = str.split(':')[1].split(';')[0], ext = mime.split('/')[1].split('+')[0];
257
- return ext;
258
274
  }, handleErrors = (err)=>{
259
275
  const res = {
260
276
  message: 'Unknown error',
@@ -269,360 +285,8 @@ const hasExt = (path)=>{
269
285
  }
270
286
  }
271
287
  return res;
272
- }, isAudio = (asset)=>!('h' in asset) && !('w' in asset) && 'p' in asset && 'e' in asset && 'u' in asset && 'id' in asset, isImage = (asset)=>'w' in asset && 'h' in asset && !('xt' in asset) && 'p' in asset, frameOutput = (frame)=>((frame ?? 0) + 1).toString().padStart(3, '0');
273
-
274
- const getArrayBuffer = async (zippable)=>{
275
- const arrayBuffer = await new Promise((resolve, reject)=>{
276
- zip(zippable, {
277
- level: 9
278
- }, (err, data)=>{
279
- if (err) {
280
- reject(err);
281
- return;
282
- }
283
- if (!(data.buffer instanceof ArrayBuffer)) {
284
- reject(new Error('Data is not transferable'));
285
- return;
286
- }
287
- resolve(data.buffer);
288
- });
289
- });
290
- return arrayBuffer;
291
- }, fileToBase64 = async (url)=>{
292
- const response = await fetch(url), blob = await response.blob();
293
- return new Promise((resolve, reject)=>{
294
- try {
295
- const reader = new FileReader();
296
- reader.onload = ()=>{
297
- if (typeof reader.result === 'string') {
298
- resolve(reader.result);
299
- return;
300
- }
301
- reject(new Error('Could not create bas64'));
302
- };
303
- reader.readAsDataURL(blob);
304
- } catch (error) {
305
- reject(error);
306
- }
307
- });
308
- };
309
- /**
310
- * Convert a JSON Lottie to dotLottie or combine several animations and download new dotLottie file in your browser.
311
- */ async function createDotLottie({ animations = [], fileName, manifest, shouldDownload = true }) {
312
- try {
313
- // Input validation
314
- if (animations.length === 0 || !manifest) {
315
- throw new Error(`Missing or malformed required parameter(s):\n ${animations.length > 0 ? '- manifest\n' : ''} ${manifest ? '- animations\n' : ''}`);
316
- }
317
- const manifestCompressionLevel = 0, animationCompressionLevel = 9, /**
318
- * Prepare the dotLottie file.
319
- */ name = addExt('lottie', fileName) || `${createElementID()}.lottie`, dotlottie = {
320
- 'manifest.json': [
321
- strToU8(JSON.stringify(manifest), true),
322
- {
323
- level: manifestCompressionLevel
324
- }
325
- ]
326
- };
327
- // Add animations and assets to the dotLottie file
328
- const { length } = animations;
329
- for(let i = 0; i < length; i++){
330
- const { length: jLen } = animations[i].assets;
331
- // Prepare assets
332
- for(let j = 0; j < jLen; j++){
333
- const asset = animations[i].assets[j];
334
- if (!asset.p || !isImage(asset) && !isAudio(asset)) {
335
- continue;
336
- }
337
- const { p: file, u: path } = asset;
338
- if (!file) {
339
- continue;
340
- }
341
- // Original asset.id caused issues with multianimations
342
- const assetId = createElementID(), isEncoded = file.startsWith('data:'), ext = isEncoded ? getExtFromB64(file) : getExt(file), /**
343
- * Check if the asset is already base64-encoded. If not, get path, fetch it, and encode it.
344
- */ dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
345
- // Asset is encoded
346
- // eslint-disable-next-line require-atomic-updates
347
- animations[i].assets[j].e = 1;
348
- // eslint-disable-next-line require-atomic-updates
349
- animations[i].assets[j].p = `${assetId}.${ext}`;
350
- // Asset is embedded, so path empty string
351
- // eslint-disable-next-line require-atomic-updates
352
- animations[i].assets[j].u = '';
353
- dotlottie[`${isAudio(asset) ? 'audio' : 'images'}/${assetId}.${ext}`] = [
354
- base64ToU8(dataURL),
355
- {
356
- level: animationCompressionLevel
357
- }
358
- ];
359
- }
360
- // Prepare expressions
361
- const { length: kLen } = animations[i].layers;
362
- for(let k = 0; k < kLen; k++){
363
- const { ks: shape } = animations[i].layers[k], props = Object.keys(shape), { length: pLen } = props;
364
- for(let p = 0; p < pLen; p++){
365
- const { x: expression } = shape[props[p]];
366
- if (!expression) {
367
- continue;
368
- }
369
- // Base64 Encode to handle compression
370
- // @ts-expect-error: We have checked this property is set
371
- animations[i].layers[k].ks[props[p]].x = btoa(expression);
372
- // Set e (encoded) to 1
373
- // @ts-expect-error: We have checked this property is set
374
- animations[i].layers[k].ks[props[p]].e = 1;
375
- }
376
- }
377
- dotlottie[`a/${manifest.animations[i].id}.json`] = [
378
- strToU8(JSON.stringify(animations[i]), true),
379
- {
380
- level: animationCompressionLevel
381
- }
382
- ];
383
- }
384
- const buffer = await getArrayBuffer(dotlottie);
385
- if (shouldDownload) {
386
- download(buffer, {
387
- mimeType: 'application/zip',
388
- name
389
- });
390
- return null;
391
- }
392
- return buffer;
393
- } catch (error) {
394
- console.error(handleErrors(error).message);
395
- return null;
396
- }
397
- }
398
-
399
- function createJSON({ animation, fileName, shouldDownload }) {
400
- try {
401
- if (!animation) {
402
- throw new Error('createJSON: Missing or malformed required parameter(s):\n - animation\n\'');
403
- }
404
- const name = addExt('json', fileName) || `${createElementID()}.json`, jsonString = JSON.stringify(animation);
405
- if (shouldDownload) {
406
- download(jsonString, {
407
- mimeType: 'application/json',
408
- name
409
- });
410
- return null;
411
- }
412
- return jsonString;
413
- } catch (error) {
414
- console.error(handleErrors(error).message);
415
- return null;
416
- }
417
- }
418
-
419
- const getMimeFromExt = (ext)=>{
420
- switch(ext){
421
- case 'svg':
422
- case 'svg+xml':
423
- {
424
- return 'image/svg+xml';
425
- }
426
- case 'jpg':
427
- case 'jpeg':
428
- {
429
- return 'image/jpeg';
430
- }
431
- case 'png':
432
- case 'gif':
433
- case 'webp':
434
- case 'avif':
435
- {
436
- return `image/${ext}`;
437
- }
438
- case 'mp3':
439
- case 'mpeg':
440
- case 'wav':
441
- {
442
- return `audio/${ext}`;
443
- }
444
- default:
445
- {
446
- return '';
447
- }
448
- }
449
- }, isBase64 = (str)=>{
450
- if (!str) {
451
- return false;
452
- }
453
- const regex = /^(?:[0-9a-z+/]{4})*(?:[0-9a-z+/]{2}==|[0-9a-z+/]{3}=)?$/i;
454
- return regex.test(parseBase64(str));
455
- };
456
- async function resolveAssets(unzipped, assets) {
457
- if (!Array.isArray(assets)) {
458
- return;
459
- }
460
- const toResolve = [], { length } = assets;
461
- for(let i = 0; i < length; i++){
462
- if (!isAudio(assets[i]) && !isImage(assets[i])) {
463
- continue;
464
- }
465
- const type = isImage(assets[i]) ? 'images' : 'audio', u8 = unzipped?.[`${type}/${assets[i].p}`];
466
- if (!u8) {
467
- continue;
468
- }
469
- toResolve.push(new Promise((resolveAsset)=>{
470
- let assetB64;
471
- if (isServer) {
472
- assetB64 = Buffer.from(u8).toString('base64');
473
- } else {
474
- let result = '';
475
- const { length: jLen } = u8;
476
- for(let j = 0; j < jLen; j++){
477
- result += String.fromCharCode(u8[j]);
478
- }
479
- assetB64 = btoa(result);
480
- }
481
- assets[i].p = assets[i].p?.startsWith('data:') || isBase64(assets[i].p) ? assets[i].p : `data:${getMimeFromExt(getExt(assets[i].p))};base64,${assetB64}`;
482
- assets[i].e = 1;
483
- assets[i].u = '';
484
- resolveAsset();
485
- }));
486
- }
487
- await Promise.all(toResolve);
488
- }
489
-
490
- const unzip = async (resp)=>{
491
- const u8 = new Uint8Array(await resp.arrayBuffer()), unzipped = await new Promise((resolve, reject)=>{
492
- unzip$1(u8, (err, file)=>{
493
- if (err) {
494
- reject(err);
495
- }
496
- resolve(file);
497
- });
498
- });
499
- return unzipped;
500
- }, getManifest = (unzipped)=>{
501
- const file = strFromU8(unzipped['manifest.json'], false), manifest = JSON.parse(file);
502
- if (!('animations' in manifest)) {
503
- throw new Error('Manifest not found');
504
- }
505
- if (manifest.animations.length === 0) {
506
- throw new Error('No animations listed in manifest');
507
- }
508
- return manifest;
509
- }, prepareString = (str)=>str.replaceAll(new RegExp(/"""/, 'g'), '""').replaceAll(/(["'])(.*?)\1/g, (_match, quote, content)=>{
510
- /**
511
- * TODO: This caused text layers and expressions to be mangled
512
- * Consider a more nuanced sanitaiton, if at all.
513
- */ // const replacedContent = content.replaceAll(/[^\w\s.#]/g, '')
514
- return `${quote}${content}${quote}`;
515
- });
516
- async function getLottieJSON(resp) {
517
- const unzipped = await unzip(resp), manifest = getManifest(unzipped), data = [], toResolve = [], { length } = manifest.animations;
518
- /**
519
- * Check whether Lottie animations folder is abbreviated.
520
- */ let animationsFolder = 'animations';
521
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
522
- if (unzipped[`a/${manifest.animations[0].id}.json`]) {
523
- animationsFolder = 'a';
524
- }
525
- for(let i = 0; i < length; i++){
526
- const str = strFromU8(unzipped[`${animationsFolder}/${manifest.animations[i].id}.json`]), lottie = JSON.parse(prepareString(str));
527
- // Handle Expressions
528
- const { length: jLen } = lottie.layers;
529
- for(let j = 0; j < jLen; j++){
530
- const { ks: shape } = lottie.layers[j], props = Object.keys(shape), { length: pLen } = props;
531
- for(let p = 0; p < pLen; p++){
532
- const { e: isEncoded, x: expression } = shape[props[p]];
533
- if (!expression || !isEncoded) {
534
- continue;
535
- }
536
- // Base64 Decode to handle compression
537
- // @ts-expect-error
538
- lottie.layers[j].ks[props[p]].x = atob(expression);
539
- }
540
- }
541
- toResolve.push(resolveAssets(unzipped, lottie.assets));
542
- data.push(lottie);
543
- }
544
- await Promise.all(toResolve);
545
- return {
546
- data,
547
- manifest
548
- };
549
- }
550
-
551
- async function getAnimationData(input) {
552
- try {
553
- if (!input || typeof input !== 'string' && typeof input !== 'object') {
554
- throw new Error('Broken file or invalid file format');
555
- }
556
- if (typeof input !== 'string') {
557
- const animations = Array.isArray(input) ? input : [
558
- input
559
- ];
560
- return {
561
- animations,
562
- isDotLottie: false,
563
- manifest: null
564
- };
565
- }
566
- const result = await fetch(input, {
567
- headers: {
568
- 'Content-Type': 'application/json; charset=UTF-8'
569
- }
570
- });
571
- if (!result.ok) {
572
- const error = new Error(result.statusText);
573
- throw error;
574
- }
575
- /**
576
- * Check if file is JSON, first by parsing headers for content-type,
577
- * than by parsing filename, then – if filename has no extension – by
578
- * cloning the response and parsing response for content.
579
- */ let isJSON = true;
580
- const contentType = result.headers.get('content-type');
581
- if (contentType === 'application/zip+dotlottie') {
582
- isJSON = false;
583
- }
584
- if (isJSON) {
585
- const ext = getExt(input);
586
- if (ext === 'json') {
587
- const lottie = await result.json();
588
- return {
589
- animations: [
590
- lottie
591
- ],
592
- isDotLottie: false,
593
- manifest: null
594
- };
595
- }
596
- const text = await result.clone().text();
597
- try {
598
- const lottie = JSON.parse(text);
599
- return {
600
- animations: [
601
- lottie
602
- ],
603
- isDotLottie: false,
604
- manifest: null
605
- };
606
- } catch (error) {
607
- /* empty */ }
608
- }
609
- const { data, manifest } = await getLottieJSON(result);
610
- return {
611
- animations: data,
612
- isDotLottie: true,
613
- manifest
614
- };
615
- } catch (error) {
616
- console.error(handleErrors(error).message);
617
- return {
618
- animations: undefined,
619
- isDotLottie: false,
620
- manifest: null
621
- };
622
- }
623
- }
288
+ }, frameOutput = (frame)=>((frame ?? 0) + 1).toString().padStart(3, '0');
624
289
 
625
- const generator = '@aarsteinmedia/dotlottie-player';
626
290
  /**
627
291
  * DotLottie Player Web Component.
628
292
  */ class DotLottiePlayer extends PropertyCallbackElement {
@@ -750,6 +414,9 @@ const generator = '@aarsteinmedia/dotlottie-player';
750
414
  }
751
415
  return 0;
752
416
  }
417
+ get isDotLottie() {
418
+ return this._isDotLottie;
419
+ }
753
420
  /**
754
421
  * Loop animation.
755
422
  */ set loop(value) {
@@ -846,7 +513,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
846
513
  return Boolean(val === 'true' || val === '' || val === '1');
847
514
  }
848
515
  constructor(){
849
- super(), /**
516
+ super(), this.addAnimation = addAnimation, this.convert = convert, /**
850
517
  * Player state.
851
518
  */ this.playerState = PlayerState.Loading, /**
852
519
  * Animation Container.
@@ -894,7 +561,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
894
561
  this.snapshot = this.snapshot.bind(this);
895
562
  this.toggleLoop = this.toggleLoop.bind(this);
896
563
  this.toggleBoomerang = this.toggleBoomerang.bind(this);
897
- this.convert = this.convert.bind(this);
898
564
  this.destroy = this.destroy.bind(this);
899
565
  this.template = document.createElement('template');
900
566
  this.shadow = this.attachShadow({
@@ -902,57 +568,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
902
568
  });
903
569
  }
904
570
  /**
905
- * Creates a new dotLottie file, by combinig several animations.
906
- * If set to false the function returns an ArrayBuffer. Defaults to true.
907
- */ async addAnimation(configs, fileName, shouldDownload = true) {
908
- // Initialize meta object for animation, with fallbacks for
909
- // when the method is called indepenently
910
- const { animations = [], manifest = {
911
- animations: this.src ? [
912
- {
913
- id: this._identifier
914
- }
915
- ] : []
916
- } } = this.src ? await getAnimationData(this.src) : {};
917
- try {
918
- if (!manifest) {
919
- throw new Error('Manifest is not set');
920
- }
921
- manifest.generator = generator;
922
- const { length } = configs;
923
- for(let i = 0; i < length; i++){
924
- const { url } = configs[i], { animations: animationsToAdd } = await getAnimationData(url);
925
- if (!animationsToAdd) {
926
- throw new Error('No animation loaded');
927
- }
928
- if (manifest.animations.some(({ id })=>id === configs[i].id)) {
929
- throw new Error('Duplicate id for animation');
930
- }
931
- manifest.animations = [
932
- ...manifest.animations,
933
- {
934
- id: configs[i].id
935
- }
936
- ];
937
- animations.push(...animationsToAdd);
938
- }
939
- return {
940
- result: await createDotLottie({
941
- animations,
942
- fileName,
943
- manifest,
944
- shouldDownload
945
- }),
946
- success: true
947
- };
948
- } catch (error) {
949
- return {
950
- error: handleErrors(error).message,
951
- success: false
952
- };
953
- }
954
- }
955
- /**
956
571
  * Runs when the value of an attribute is changed on the component.
957
572
  */ async attributeChangedCallback(name, _oldValue, value) {
958
573
  if (!this._lottieInstance || !this.shadow) {
@@ -1027,50 +642,29 @@ const generator = '@aarsteinmedia/dotlottie-player';
1027
642
  }
1028
643
  /**
1029
644
  * Initialize everything on component first render.
1030
- */ async connectedCallback() {
1031
- await super.connectedCallback();
1032
- await this._render();
1033
- if (!this.shadow) {
1034
- throw new Error('Missing Shadow element');
1035
- }
1036
- this._container = this.shadow.querySelector('.animation');
1037
- this._renderControls();
1038
- // Add listener for Visibility API's change event.
1039
- if (typeof document.hidden !== 'undefined') {
1040
- document.addEventListener('visibilitychange', this._onVisibilityChange);
1041
- }
1042
- // Add intersection observer for detecting component being out-of-view.
1043
- this._addIntersectionObserver();
1044
- // Setup lottie player
1045
- await this.load(this.src);
1046
- this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
1047
- }
1048
- async convert({ animations: animationsFromProps, fileName, manifest, shouldDownload = true, src: srcFromProps, typeCheck }) {
1049
- const src = srcFromProps || this.src || this.source;
1050
- if (!src && !animationsFromProps?.length) {
1051
- throw new Error('No animation to convert');
1052
- }
1053
- let animations = animationsFromProps;
1054
- if (!animations) {
1055
- const animationData = await getAnimationData(src);
1056
- animations = animationData.animations;
1057
- }
1058
- if (typeCheck || this._isDotLottie) {
1059
- return createJSON({
1060
- animation: animations?.[0],
1061
- fileName: `${getFilename(fileName || src || 'converted')}.json`,
1062
- shouldDownload
1063
- });
645
+ */ connectedCallback() {
646
+ super.connectedCallback();
647
+ try {
648
+ void (async ()=>{
649
+ await this._render();
650
+ if (!this.shadow) {
651
+ throw new Error('Missing Shadow element');
652
+ }
653
+ this._container = this.shadow.querySelector('.animation');
654
+ // Add listener for Visibility API's change event.
655
+ if (typeof document.hidden !== 'undefined') {
656
+ document.addEventListener('visibilitychange', this._onVisibilityChange);
657
+ }
658
+ // Add intersection observer for detecting component being out-of-view.
659
+ this._addIntersectionObserver();
660
+ // Setup lottie player
661
+ await this.load(this.src);
662
+ this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
663
+ })();
664
+ } catch (error) {
665
+ console.error(error);
666
+ this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1064
667
  }
1065
- return createDotLottie({
1066
- animations,
1067
- fileName: `${getFilename(fileName || src || 'converted')}.lottie`,
1068
- manifest: {
1069
- ...manifest ?? this._manifest,
1070
- generator
1071
- },
1072
- shouldDownload
1073
- });
1074
668
  }
1075
669
  /**
1076
670
  * Destroy animation and element.
@@ -1121,12 +715,12 @@ const generator = '@aarsteinmedia/dotlottie-player';
1121
715
  /**
1122
716
  * Initialize Lottie Web player.
1123
717
  */ async load(src) {
1124
- if (!this.shadowRoot || !src) {
1125
- return;
1126
- }
1127
- this.source = src;
1128
- // Load the resource
1129
718
  try {
719
+ if (!this.shadowRoot || !src) {
720
+ return;
721
+ }
722
+ this.source = src;
723
+ // Load the resource
1130
724
  const { animations, isDotLottie, manifest } = await getAnimationData(src);
1131
725
  if (!animations || animations.some((animation)=>!this._isLottie(animation))) {
1132
726
  throw new Error('Broken or corrupted file');
@@ -1139,7 +733,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1139
733
  manifest.animations[0].autoplay = this.autoplay;
1140
734
  manifest.animations[0].loop = this.loop;
1141
735
  }
1142
- this._isDotLottie = Boolean(isDotLottie);
736
+ this._isDotLottie = isDotLottie;
1143
737
  this._animations = animations;
1144
738
  this._manifest = manifest ?? {
1145
739
  animations: [
@@ -1164,30 +758,37 @@ const generator = '@aarsteinmedia/dotlottie-player';
1164
758
  ...this._getOptions(),
1165
759
  animationData: animations[this._currentAnimation]
1166
760
  });
761
+ this._addEventListeners();
762
+ const speed = this._multiAnimationSettings[this._currentAnimation]?.speed ?? this.speed, direction = this._multiAnimationSettings[this._currentAnimation]?.direction ?? this.direction;
763
+ // Set initial playback speed and direction
764
+ this._lottieInstance.setSpeed(speed);
765
+ this._lottieInstance.setDirection(direction);
766
+ this._lottieInstance.setSubframe(Boolean(this.subframe));
767
+ // Start playing if autoplay is enabled
768
+ if (this.autoplay || this.animateOnScroll) {
769
+ if (this.direction === -1) {
770
+ this.seek('99%');
771
+ }
772
+ if (!('IntersectionObserver' in window)) {
773
+ if (!this.animateOnScroll) {
774
+ this.play();
775
+ }
776
+ this._playerState.visible = true;
777
+ }
778
+ this._addIntersectionObserver();
779
+ }
780
+ this._renderControls();
781
+ if (this.autoplay) {
782
+ const togglePlay = this.shadow?.querySelector('.togglePlay');
783
+ if (togglePlay) {
784
+ togglePlay.innerHTML = pauseIcon;
785
+ }
786
+ }
1167
787
  } catch (error) {
788
+ console.error(error);
1168
789
  this._errorMessage = handleErrors(error).message;
1169
790
  this.playerState = PlayerState.Error;
1170
791
  this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1171
- return;
1172
- }
1173
- this._addEventListeners();
1174
- const speed = this._multiAnimationSettings[this._currentAnimation]?.speed ?? this.speed, direction = this._multiAnimationSettings[this._currentAnimation]?.direction ?? this.direction;
1175
- // Set initial playback speed and direction
1176
- this._lottieInstance.setSpeed(speed);
1177
- this._lottieInstance.setDirection(direction);
1178
- this._lottieInstance.setSubframe(Boolean(this.subframe));
1179
- // Start playing if autoplay is enabled
1180
- if (this.autoplay || this.animateOnScroll) {
1181
- if (this.direction === -1) {
1182
- this.seek('99%');
1183
- }
1184
- if (!('IntersectionObserver' in window)) {
1185
- if (!this.animateOnScroll) {
1186
- this.play();
1187
- }
1188
- this._playerState.visible = true;
1189
- }
1190
- this._addIntersectionObserver();
1191
792
  }
1192
793
  }
1193
794
  /**
@@ -1236,7 +837,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1236
837
  if (!this.shadow) {
1237
838
  return;
1238
839
  }
1239
- const togglePlay = this.shadow.querySelector('.togglePlay'), stop = this.shadow.querySelector('.stop'), prev = this.shadow.querySelector('.prev'), next = this.shadow.querySelector('.next'), seeker = this.shadow.querySelector('.seeker'), progress = this.shadow.querySelector('progress'), popover = this.shadow.querySelector('.popover'), convert = this.shadow.querySelector('.convert'), snapshot = this.shadow.querySelector('.snapshot');
840
+ const togglePlay = this.shadow.querySelector('.togglePlay'), stop = this.shadow.querySelector('.stop'), prev = this.shadow.querySelector('.prev'), next = this.shadow.querySelector('.next'), seeker = this.shadow.querySelector('.seeker'), progress = this.shadow.querySelector('progress'), popover = this.shadow.querySelector('.popover'), convertButton = this.shadow.querySelector('.convert'), snapshot = this.shadow.querySelector('.snapshot');
1240
841
  if (!(togglePlay instanceof HTMLButtonElement) || !(stop instanceof HTMLButtonElement) || !(next instanceof HTMLButtonElement) || !(prev instanceof HTMLButtonElement) || !(seeker instanceof HTMLInputElement) || !(progress instanceof HTMLProgressElement)) {
1241
842
  return;
1242
843
  }
@@ -1244,9 +845,9 @@ const generator = '@aarsteinmedia/dotlottie-player';
1244
845
  togglePlay.dataset.active = (value === PlayerState.Playing || value === PlayerState.Paused).toString();
1245
846
  stop.dataset.active = (value === PlayerState.Stopped).toString();
1246
847
  if (value === PlayerState.Playing) {
1247
- 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>`;
848
+ togglePlay.innerHTML = pauseIcon;
1248
849
  } else {
1249
- 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>`;
850
+ togglePlay.innerHTML = playIcon;
1250
851
  }
1251
852
  }
1252
853
  if (name === '_seeker' && typeof value === 'number') {
@@ -1261,17 +862,10 @@ const generator = '@aarsteinmedia/dotlottie-player';
1261
862
  next.hidden = value + 1 >= this._animations.length;
1262
863
  prev.hidden = !value;
1263
864
  }
1264
- if (name === '_isSettingsOpen' && typeof value === 'boolean' && popover instanceof HTMLDivElement && convert instanceof HTMLButtonElement && snapshot instanceof HTMLButtonElement) {
865
+ if (name === '_isSettingsOpen' && typeof value === 'boolean' && popover instanceof HTMLDivElement && convertButton instanceof HTMLButtonElement && snapshot instanceof HTMLButtonElement) {
1265
866
  popover.hidden = !value;
1266
- convert.hidden = false;
867
+ convertButton.hidden = false;
1267
868
  snapshot.hidden = this.renderer !== RendererType.SVG;
1268
- if (this._isDotLottie) {
1269
- convert.ariaLabel = 'Convert dotLottie to JSON';
1270
- convert.innerHTML = convert.innerHTML.replace('dotLottie', 'JSON');
1271
- } else {
1272
- convert.ariaLabel = 'Convert JSON animation to dotLottie format';
1273
- convert.innerHTML = convert.innerHTML.replace('JSON', 'dotLottie');
1274
- }
1275
869
  }
1276
870
  }
1277
871
  /**
@@ -1335,13 +929,11 @@ const generator = '@aarsteinmedia/dotlottie-player';
1335
929
  }
1336
930
  /**
1337
931
  * Set Multi-animation settings.
1338
- *
1339
932
  */ setMultiAnimationSettings(settings) {
1340
933
  this._multiAnimationSettings = settings;
1341
934
  }
1342
935
  /**
1343
936
  * Set playback segment.
1344
- *
1345
937
  */ setSegment(segment) {
1346
938
  this._segment = segment;
1347
939
  }
@@ -1411,7 +1003,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1411
1003
  /**
1412
1004
  * Toggle Boomerang.
1413
1005
  */ toggleBoomerang() {
1414
- const curr = this._multiAnimationSettings[this._currentAnimation];
1006
+ const curr = this._multiAnimationSettings[this._currentAnimation] ?? {};
1415
1007
  if (curr.mode !== undefined) {
1416
1008
  if (curr.mode === PlayMode.Normal) {
1417
1009
  curr.mode = PlayMode.Bounce;
@@ -1489,7 +1081,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
1489
1081
  }
1490
1082
  /**
1491
1083
  * Handles click and drag actions on the progress track.
1492
- *
1493
1084
  */ _handleSeekChange({ target }) {
1494
1085
  if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) {
1495
1086
  return;
@@ -1865,11 +1456,10 @@ const generator = '@aarsteinmedia/dotlottie-player';
1865
1456
 
1866
1457
  /**
1867
1458
  * Expose DotLottiePlayer class as global variable.
1868
- *
1869
1459
  */ globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
1870
1460
  const tagName = 'dotlottie-player';
1871
1461
  if (!isServer) {
1872
1462
  customElements.define(tagName, DotLottiePlayer);
1873
1463
  }
1874
1464
 
1875
- export { PlayMode, PlayerState, DotLottiePlayer as default, tagName };
1465
+ export { PlayerState, DotLottiePlayer as default, tagName };