@aarsteinmedia/dotlottie-player 5.2.3 → 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, 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,24 +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
- var RendererType = /*#__PURE__*/ function(RendererType) {
99
- RendererType["Canvas"] = "canvas";
100
- RendererType["HTML"] = "html";
101
- RendererType["SVG"] = "svg";
102
- return RendererType;
103
- }({});
104
159
 
105
160
  /**
106
161
  * Render Controls.
@@ -116,7 +171,7 @@ var RendererType = /*#__PURE__*/ function(RendererType) {
116
171
  slot.innerHTML = '';
117
172
  return;
118
173
  }
119
- 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>`;
120
175
  const togglePlay = this.shadow.querySelector('.togglePlay');
121
176
  if (togglePlay instanceof HTMLButtonElement) {
122
177
  togglePlay.onclick = this.togglePlay;
@@ -147,14 +202,16 @@ var RendererType = /*#__PURE__*/ function(RendererType) {
147
202
  if (toggleBoomerang instanceof HTMLButtonElement) {
148
203
  toggleBoomerang.onclick = this.toggleBoomerang;
149
204
  }
150
- const convert = this.shadow.querySelector('.convert');
151
- if (convert instanceof HTMLButtonElement) {
152
- 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
+ };
153
214
  }
154
- // const convertJSON = this.shadow.querySelector('.convert-json')
155
- // if (convertJSON instanceof HTMLButtonElement) {
156
- // convertJSON.onclick = this.convertJSON as unknown as () => void
157
- // }
158
215
  const snapshot = this.shadow.querySelector('.snapshot');
159
216
  if (snapshot instanceof HTMLButtonElement) {
160
217
  snapshot.onclick = ()=>this.snapshot(true);
@@ -167,23 +224,27 @@ var RendererType = /*#__PURE__*/ function(RendererType) {
167
224
  }
168
225
  }
169
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
+
170
235
  /**
171
236
  * Render Player.
172
237
  */ async function renderPlayer() {
173
238
  if (!this.shadow) {
174
239
  throw new Error('No Shadow Element');
175
240
  }
176
- 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>`;
177
242
  this.shadow.adoptedStyleSheets = [
178
243
  await DotLottiePlayer.styles()
179
244
  ];
180
245
  this.shadow.appendChild(this.template.content.cloneNode(true));
181
246
  }
182
247
 
183
- const hasExt = (path)=>{
184
- const lastDotIndex = path?.split('/').pop()?.lastIndexOf('.');
185
- return (lastDotIndex ?? 0) > 1 && path && path.length - 1 > (lastDotIndex ?? 0);
186
- };
187
248
  /**
188
249
  * Get extension from filename, URL or path.
189
250
  */ const aspectRatio = (objectFit)=>{
@@ -191,76 +252,25 @@ const hasExt = (path)=>{
191
252
  case ObjectFit.Contain:
192
253
  case ObjectFit.ScaleDown:
193
254
  {
194
- return PreserveAspectRatio$1.Contain;
255
+ return PreserveAspectRatio.Contain;
195
256
  }
196
257
  case ObjectFit.Cover:
197
258
  {
198
- return PreserveAspectRatio$1.Cover;
259
+ return PreserveAspectRatio.Cover;
199
260
  }
200
261
  case ObjectFit.Fill:
201
262
  {
202
- return PreserveAspectRatio$1.Initial;
263
+ return PreserveAspectRatio.Initial;
203
264
  }
204
265
  case ObjectFit.None:
205
266
  {
206
- return PreserveAspectRatio$1.None;
267
+ return PreserveAspectRatio.None;
207
268
  }
208
269
  default:
209
270
  {
210
- return PreserveAspectRatio$1.Contain;
271
+ return PreserveAspectRatio.Contain;
211
272
  }
212
273
  }
213
- }, /**
214
- * Download file, either SVG or dotLottie.
215
- */ download = (data, options)=>{
216
- const blob = new Blob([
217
- data
218
- ], {
219
- type: options?.mimeType
220
- }), fileName = options?.name || createElementID(), dataURL = URL.createObjectURL(blob), link = document.createElement('a');
221
- link.href = dataURL;
222
- link.download = fileName;
223
- link.hidden = true;
224
- document.body.appendChild(link);
225
- link.click();
226
- setTimeout(()=>{
227
- link.remove();
228
- URL.revokeObjectURL(dataURL);
229
- }, 1000);
230
- }, getExt = (str)=>{
231
- if (typeof str !== 'string' || !str || !hasExt(str)) {
232
- return;
233
- }
234
- return str.split('.').pop()?.toLowerCase();
235
- }, /**
236
- * Parse URL to get filename.
237
- *
238
- * @param src - The url string.
239
- * @param keepExt - Whether to include file extension.
240
- * @returns Filename, in lowercase.
241
- */ getFilename = (src, keepExt)=>{
242
- // Because the regex strips all special characters, we need to extract the file extension, so we can add it later if we need it
243
- getExt(src);
244
- return `${src.split('/').pop()?.replace(/\.[^.]*$/, '').replaceAll(/\W+/g, '-')}${''}`;
245
- }, addExt = (ext, str)=>{
246
- if (!str) {
247
- return;
248
- }
249
- if (getExt(str)) {
250
- if (getExt(str) === ext) {
251
- return str;
252
- }
253
- return `${getFilename(str)}.${ext}`;
254
- }
255
- return `${str}.${ext}`;
256
- }, parseBase64 = (str)=>str.slice(Math.max(0, str.indexOf(',') + 1)), /**
257
- * Convert Base64 encoded string to Uint8Array.
258
- *
259
- * @param str - Base64 encoded string.
260
- * @returns UTF-8/Latin-1 binary.
261
- */ base64ToU8 = (str)=>strToU8(isServer ? Buffer.from(parseBase64(str), 'base64').toString('binary') : atob(parseBase64(str)), true), getExtFromB64 = (str)=>{
262
- const mime = str.split(':')[1].split(';')[0], ext = mime.split('/')[1].split('+')[0];
263
- return ext;
264
274
  }, handleErrors = (err)=>{
265
275
  const res = {
266
276
  message: 'Unknown error',
@@ -275,360 +285,8 @@ const hasExt = (path)=>{
275
285
  }
276
286
  }
277
287
  return res;
278
- }, 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');
279
-
280
- const getArrayBuffer = async (zippable)=>{
281
- const arrayBuffer = await new Promise((resolve, reject)=>{
282
- zip(zippable, {
283
- level: 9
284
- }, (err, data)=>{
285
- if (err) {
286
- reject(err);
287
- return;
288
- }
289
- if (!(data.buffer instanceof ArrayBuffer)) {
290
- reject(new Error('Data is not transferable'));
291
- return;
292
- }
293
- resolve(data.buffer);
294
- });
295
- });
296
- return arrayBuffer;
297
- }, fileToBase64 = async (url)=>{
298
- const response = await fetch(url), blob = await response.blob();
299
- return new Promise((resolve, reject)=>{
300
- try {
301
- const reader = new FileReader();
302
- reader.onload = ()=>{
303
- if (typeof reader.result === 'string') {
304
- resolve(reader.result);
305
- return;
306
- }
307
- reject(new Error('Could not create bas64'));
308
- };
309
- reader.readAsDataURL(blob);
310
- } catch (error) {
311
- reject(error);
312
- }
313
- });
314
- };
315
- /**
316
- * Convert a JSON Lottie to dotLottie or combine several animations and download new dotLottie file in your browser.
317
- */ async function createDotLottie({ animations = [], fileName, manifest, shouldDownload = true }) {
318
- try {
319
- // Input validation
320
- if (animations.length === 0 || !manifest) {
321
- throw new Error(`Missing or malformed required parameter(s):\n ${animations.length > 0 ? '- manifest\n' : ''} ${manifest ? '- animations\n' : ''}`);
322
- }
323
- const manifestCompressionLevel = 0, animationCompressionLevel = 9, /**
324
- * Prepare the dotLottie file.
325
- */ name = addExt('lottie', fileName) || `${createElementID()}.lottie`, dotlottie = {
326
- 'manifest.json': [
327
- strToU8(JSON.stringify(manifest), true),
328
- {
329
- level: manifestCompressionLevel
330
- }
331
- ]
332
- };
333
- // Add animations and assets to the dotLottie file
334
- const { length } = animations;
335
- for(let i = 0; i < length; i++){
336
- const { length: jLen } = animations[i].assets;
337
- // Prepare assets
338
- for(let j = 0; j < jLen; j++){
339
- const asset = animations[i].assets[j];
340
- if (!asset.p || !isImage(asset) && !isAudio(asset)) {
341
- continue;
342
- }
343
- const { p: file, u: path } = asset;
344
- if (!file) {
345
- continue;
346
- }
347
- // Original asset.id caused issues with multianimations
348
- const assetId = createElementID(), isEncoded = file.startsWith('data:'), ext = isEncoded ? getExtFromB64(file) : getExt(file), /**
349
- * Check if the asset is already base64-encoded. If not, get path, fetch it, and encode it.
350
- */ dataURL = isEncoded ? file : await fileToBase64(path ? path.endsWith('/') && `${path}${file}` || `${path}/${file}` : file);
351
- // Asset is encoded
352
- // eslint-disable-next-line require-atomic-updates
353
- animations[i].assets[j].e = 1;
354
- // eslint-disable-next-line require-atomic-updates
355
- animations[i].assets[j].p = `${assetId}.${ext}`;
356
- // Asset is embedded, so path empty string
357
- // eslint-disable-next-line require-atomic-updates
358
- animations[i].assets[j].u = '';
359
- dotlottie[`${isAudio(asset) ? 'audio' : 'images'}/${assetId}.${ext}`] = [
360
- base64ToU8(dataURL),
361
- {
362
- level: animationCompressionLevel
363
- }
364
- ];
365
- }
366
- // Prepare expressions
367
- const { length: kLen } = animations[i].layers;
368
- for(let k = 0; k < kLen; k++){
369
- const { ks: shape } = animations[i].layers[k], props = Object.keys(shape), { length: pLen } = props;
370
- for(let p = 0; p < pLen; p++){
371
- const { x: expression } = shape[props[p]];
372
- if (!expression) {
373
- continue;
374
- }
375
- // Base64 Encode to handle compression
376
- // @ts-expect-error: We have checked this property is set
377
- animations[i].layers[k].ks[props[p]].x = btoa(expression);
378
- // Set e (encoded) to 1
379
- // @ts-expect-error: We have checked this property is set
380
- animations[i].layers[k].ks[props[p]].e = 1;
381
- }
382
- }
383
- dotlottie[`a/${manifest.animations[i].id}.json`] = [
384
- strToU8(JSON.stringify(animations[i]), true),
385
- {
386
- level: animationCompressionLevel
387
- }
388
- ];
389
- }
390
- const buffer = await getArrayBuffer(dotlottie);
391
- if (shouldDownload) {
392
- download(buffer, {
393
- mimeType: 'application/zip',
394
- name
395
- });
396
- return null;
397
- }
398
- return buffer;
399
- } catch (error) {
400
- console.error(handleErrors(error).message);
401
- return null;
402
- }
403
- }
404
-
405
- function createJSON({ animation, fileName, shouldDownload }) {
406
- try {
407
- if (!animation) {
408
- throw new Error('createJSON: Missing or malformed required parameter(s):\n - animation\n\'');
409
- }
410
- const name = addExt('json', fileName) || `${createElementID()}.json`, jsonString = JSON.stringify(animation);
411
- if (shouldDownload) {
412
- download(jsonString, {
413
- mimeType: 'application/json',
414
- name
415
- });
416
- return null;
417
- }
418
- return jsonString;
419
- } catch (error) {
420
- console.error(handleErrors(error).message);
421
- return null;
422
- }
423
- }
424
-
425
- const getMimeFromExt = (ext)=>{
426
- switch(ext){
427
- case 'svg':
428
- case 'svg+xml':
429
- {
430
- return 'image/svg+xml';
431
- }
432
- case 'jpg':
433
- case 'jpeg':
434
- {
435
- return 'image/jpeg';
436
- }
437
- case 'png':
438
- case 'gif':
439
- case 'webp':
440
- case 'avif':
441
- {
442
- return `image/${ext}`;
443
- }
444
- case 'mp3':
445
- case 'mpeg':
446
- case 'wav':
447
- {
448
- return `audio/${ext}`;
449
- }
450
- default:
451
- {
452
- return '';
453
- }
454
- }
455
- }, isBase64 = (str)=>{
456
- if (!str) {
457
- return false;
458
- }
459
- const regex = /^(?:[0-9a-z+/]{4})*(?:[0-9a-z+/]{2}==|[0-9a-z+/]{3}=)?$/i;
460
- return regex.test(parseBase64(str));
461
- };
462
- async function resolveAssets(unzipped, assets) {
463
- if (!Array.isArray(assets)) {
464
- return;
465
- }
466
- const toResolve = [], { length } = assets;
467
- for(let i = 0; i < length; i++){
468
- if (!isAudio(assets[i]) && !isImage(assets[i])) {
469
- continue;
470
- }
471
- const type = isImage(assets[i]) ? 'images' : 'audio', u8 = unzipped?.[`${type}/${assets[i].p}`];
472
- if (!u8) {
473
- continue;
474
- }
475
- toResolve.push(new Promise((resolveAsset)=>{
476
- let assetB64;
477
- if (isServer) {
478
- assetB64 = Buffer.from(u8).toString('base64');
479
- } else {
480
- let result = '';
481
- const { length: jLen } = u8;
482
- for(let j = 0; j < jLen; j++){
483
- result += String.fromCharCode(u8[j]);
484
- }
485
- assetB64 = btoa(result);
486
- }
487
- assets[i].p = assets[i].p?.startsWith('data:') || isBase64(assets[i].p) ? assets[i].p : `data:${getMimeFromExt(getExt(assets[i].p))};base64,${assetB64}`;
488
- assets[i].e = 1;
489
- assets[i].u = '';
490
- resolveAsset();
491
- }));
492
- }
493
- await Promise.all(toResolve);
494
- }
495
-
496
- const unzip = async (resp)=>{
497
- const u8 = new Uint8Array(await resp.arrayBuffer()), unzipped = await new Promise((resolve, reject)=>{
498
- unzip$1(u8, (err, file)=>{
499
- if (err) {
500
- reject(err);
501
- }
502
- resolve(file);
503
- });
504
- });
505
- return unzipped;
506
- }, getManifest = (unzipped)=>{
507
- const file = strFromU8(unzipped['manifest.json'], false), manifest = JSON.parse(file);
508
- if (!('animations' in manifest)) {
509
- throw new Error('Manifest not found');
510
- }
511
- if (manifest.animations.length === 0) {
512
- throw new Error('No animations listed in manifest');
513
- }
514
- return manifest;
515
- }, prepareString = (str)=>str.replaceAll(new RegExp(/"""/, 'g'), '""').replaceAll(/(["'])(.*?)\1/g, (_match, quote, content)=>{
516
- /**
517
- * TODO: This caused text layers and expressions to be mangled
518
- * Consider a more nuanced sanitaiton, if at all.
519
- */ // const replacedContent = content.replaceAll(/[^\w\s.#]/g, '')
520
- return `${quote}${content}${quote}`;
521
- });
522
- async function getLottieJSON(resp) {
523
- const unzipped = await unzip(resp), manifest = getManifest(unzipped), data = [], toResolve = [], { length } = manifest.animations;
524
- /**
525
- * Check whether Lottie animations folder is abbreviated.
526
- */ let animationsFolder = 'animations';
527
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
528
- if (unzipped[`a/${manifest.animations[0].id}.json`]) {
529
- animationsFolder = 'a';
530
- }
531
- for(let i = 0; i < length; i++){
532
- const str = strFromU8(unzipped[`${animationsFolder}/${manifest.animations[i].id}.json`]), lottie = JSON.parse(prepareString(str));
533
- // Handle Expressions
534
- const { length: jLen } = lottie.layers;
535
- for(let j = 0; j < jLen; j++){
536
- const { ks: shape } = lottie.layers[j], props = Object.keys(shape), { length: pLen } = props;
537
- for(let p = 0; p < pLen; p++){
538
- const { e: isEncoded, x: expression } = shape[props[p]];
539
- if (!expression || !isEncoded) {
540
- continue;
541
- }
542
- // Base64 Decode to handle compression
543
- // @ts-expect-error
544
- lottie.layers[j].ks[props[p]].x = atob(expression);
545
- }
546
- }
547
- toResolve.push(resolveAssets(unzipped, lottie.assets));
548
- data.push(lottie);
549
- }
550
- await Promise.all(toResolve);
551
- return {
552
- data,
553
- manifest
554
- };
555
- }
556
-
557
- async function getAnimationData(input) {
558
- try {
559
- if (!input || typeof input !== 'string' && typeof input !== 'object') {
560
- throw new Error('Broken file or invalid file format');
561
- }
562
- if (typeof input !== 'string') {
563
- const animations = Array.isArray(input) ? input : [
564
- input
565
- ];
566
- return {
567
- animations,
568
- isDotLottie: false,
569
- manifest: null
570
- };
571
- }
572
- const result = await fetch(input, {
573
- headers: {
574
- 'Content-Type': 'application/json; charset=UTF-8'
575
- }
576
- });
577
- if (!result.ok) {
578
- const error = new Error(result.statusText);
579
- throw error;
580
- }
581
- /**
582
- * Check if file is JSON, first by parsing headers for content-type,
583
- * than by parsing filename, then – if filename has no extension – by
584
- * cloning the response and parsing response for content.
585
- */ let isJSON = true;
586
- const contentType = result.headers.get('content-type');
587
- if (contentType === 'application/zip+dotlottie') {
588
- isJSON = false;
589
- }
590
- if (isJSON) {
591
- const ext = getExt(input);
592
- if (ext === 'json') {
593
- const lottie = await result.json();
594
- return {
595
- animations: [
596
- lottie
597
- ],
598
- isDotLottie: false,
599
- manifest: null
600
- };
601
- }
602
- const text = await result.clone().text();
603
- try {
604
- const lottie = JSON.parse(text);
605
- return {
606
- animations: [
607
- lottie
608
- ],
609
- isDotLottie: false,
610
- manifest: null
611
- };
612
- } catch (error) {
613
- /* empty */ }
614
- }
615
- const { data, manifest } = await getLottieJSON(result);
616
- return {
617
- animations: data,
618
- isDotLottie: true,
619
- manifest
620
- };
621
- } catch (error) {
622
- console.error(handleErrors(error).message);
623
- return {
624
- animations: undefined,
625
- isDotLottie: false,
626
- manifest: null
627
- };
628
- }
629
- }
288
+ }, frameOutput = (frame)=>((frame ?? 0) + 1).toString().padStart(3, '0');
630
289
 
631
- const generator = '@aarsteinmedia/dotlottie-player';
632
290
  /**
633
291
  * DotLottie Player Web Component.
634
292
  */ class DotLottiePlayer extends PropertyCallbackElement {
@@ -756,6 +414,9 @@ const generator = '@aarsteinmedia/dotlottie-player';
756
414
  }
757
415
  return 0;
758
416
  }
417
+ get isDotLottie() {
418
+ return this._isDotLottie;
419
+ }
759
420
  /**
760
421
  * Loop animation.
761
422
  */ set loop(value) {
@@ -852,7 +513,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
852
513
  return Boolean(val === 'true' || val === '' || val === '1');
853
514
  }
854
515
  constructor(){
855
- super(), /**
516
+ super(), this.addAnimation = addAnimation, this.convert = convert, /**
856
517
  * Player state.
857
518
  */ this.playerState = PlayerState.Loading, /**
858
519
  * Animation Container.
@@ -875,15 +536,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
875
536
  * Which animation to show, if several.
876
537
  */ this._currentAnimation = 0, this._isBounce = false, this._isDotLottie = false, this._lottieInstance = null, /**
877
538
  * Multi-animation settings.
878
- */ this._multiAnimationSettings = [], /**
879
- * Handle settings click event.
880
- */ this._handleSettingsClick = ({ target })=>{
881
- this._toggleSettings();
882
- // Because Safari does not add focus on click, we need to add it manually, so the onblur event will fire
883
- if (target instanceof HTMLElement) {
884
- target.focus();
885
- }
886
- };
539
+ */ this._multiAnimationSettings = [];
887
540
  this._complete = this._complete.bind(this);
888
541
  this._dataFailed = this._dataFailed.bind(this);
889
542
  this._dataReady = this._dataReady.bind(this);
@@ -899,6 +552,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
899
552
  this._mouseLeave = this._mouseLeave.bind(this);
900
553
  this._onVisibilityChange = this._onVisibilityChange.bind(this);
901
554
  this._switchInstance = this._switchInstance.bind(this);
555
+ this._handleSettingsClick = this._handleSettingsClick.bind(this);
902
556
  this.togglePlay = this.togglePlay.bind(this);
903
557
  this.stop = this.stop.bind(this);
904
558
  this.prev = this.prev.bind(this);
@@ -907,7 +561,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
907
561
  this.snapshot = this.snapshot.bind(this);
908
562
  this.toggleLoop = this.toggleLoop.bind(this);
909
563
  this.toggleBoomerang = this.toggleBoomerang.bind(this);
910
- this.convert = this.convert.bind(this);
911
564
  this.destroy = this.destroy.bind(this);
912
565
  this.template = document.createElement('template');
913
566
  this.shadow = this.attachShadow({
@@ -915,57 +568,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
915
568
  });
916
569
  }
917
570
  /**
918
- * Creates a new dotLottie file, by combinig several animations.
919
- * If set to false the function returns an ArrayBuffer. Defaults to true.
920
- */ async addAnimation(configs, fileName, shouldDownload = true) {
921
- // Initialize meta object for animation, with fallbacks for
922
- // when the method is called indepenently
923
- const { animations = [], manifest = {
924
- animations: this.src ? [
925
- {
926
- id: this._identifier
927
- }
928
- ] : []
929
- } } = this.src ? await getAnimationData(this.src) : {};
930
- try {
931
- if (!manifest) {
932
- throw new Error('Manifest is not set');
933
- }
934
- manifest.generator = generator;
935
- const { length } = configs;
936
- for(let i = 0; i < length; i++){
937
- const { url } = configs[i], { animations: animationsToAdd } = await getAnimationData(url);
938
- if (!animationsToAdd) {
939
- throw new Error('No animation loaded');
940
- }
941
- if (manifest.animations.some(({ id })=>id === configs[i].id)) {
942
- throw new Error('Duplicate id for animation');
943
- }
944
- manifest.animations = [
945
- ...manifest.animations,
946
- {
947
- id: configs[i].id
948
- }
949
- ];
950
- animations.push(...animationsToAdd);
951
- }
952
- return {
953
- result: await createDotLottie({
954
- animations,
955
- fileName,
956
- manifest,
957
- shouldDownload
958
- }),
959
- success: true
960
- };
961
- } catch (error) {
962
- return {
963
- error: handleErrors(error).message,
964
- success: false
965
- };
966
- }
967
- }
968
- /**
969
571
  * Runs when the value of an attribute is changed on the component.
970
572
  */ async attributeChangedCallback(name, _oldValue, value) {
971
573
  if (!this._lottieInstance || !this.shadow) {
@@ -1040,50 +642,29 @@ const generator = '@aarsteinmedia/dotlottie-player';
1040
642
  }
1041
643
  /**
1042
644
  * Initialize everything on component first render.
1043
- */ async connectedCallback() {
1044
- await super.connectedCallback();
1045
- await this._render();
1046
- if (!this.shadow) {
1047
- throw new Error('Missing Shadow element');
1048
- }
1049
- this._container = this.shadow.querySelector('.animation');
1050
- this._renderControls();
1051
- // Add listener for Visibility API's change event.
1052
- if (typeof document.hidden !== 'undefined') {
1053
- document.addEventListener('visibilitychange', this._onVisibilityChange);
1054
- }
1055
- // Add intersection observer for detecting component being out-of-view.
1056
- this._addIntersectionObserver();
1057
- // Setup lottie player
1058
- await this.load(this.src);
1059
- this.dispatchEvent(new CustomEvent(PlayerEvents.Rendered));
1060
- }
1061
- async convert({ animations: animationsFromProps, fileName, manifest, shouldDownload = true, src: srcFromProps, typeCheck }) {
1062
- const src = srcFromProps || this.src || this.source;
1063
- if (!src && !animationsFromProps?.length) {
1064
- throw new Error('No animation to convert');
1065
- }
1066
- let animations = animationsFromProps;
1067
- if (!animations) {
1068
- const animationData = await getAnimationData(src);
1069
- animations = animationData.animations;
1070
- }
1071
- if (typeCheck || this._isDotLottie) {
1072
- return createJSON({
1073
- animation: animations?.[0],
1074
- fileName: `${getFilename(fileName || src || 'converted')}.json`,
1075
- shouldDownload
1076
- });
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));
1077
667
  }
1078
- return createDotLottie({
1079
- animations,
1080
- fileName: `${getFilename(fileName || src || 'converted')}.lottie`,
1081
- manifest: {
1082
- ...manifest ?? this._manifest,
1083
- generator
1084
- },
1085
- shouldDownload
1086
- });
1087
668
  }
1088
669
  /**
1089
670
  * Destroy animation and element.
@@ -1123,25 +704,23 @@ const generator = '@aarsteinmedia/dotlottie-player';
1123
704
  }
1124
705
  /**
1125
706
  * Get Multi-animation settings.
1126
- *
1127
707
  */ getMultiAnimationSettings() {
1128
708
  return this._multiAnimationSettings;
1129
709
  }
1130
710
  /**
1131
711
  * Get playback segment.
1132
- *
1133
712
  */ getSegment() {
1134
713
  return this._segment;
1135
714
  }
1136
715
  /**
1137
716
  * Initialize Lottie Web player.
1138
717
  */ async load(src) {
1139
- if (!this.shadowRoot || !src) {
1140
- return;
1141
- }
1142
- this.source = src;
1143
- // Load the resource
1144
718
  try {
719
+ if (!this.shadowRoot || !src) {
720
+ return;
721
+ }
722
+ this.source = src;
723
+ // Load the resource
1145
724
  const { animations, isDotLottie, manifest } = await getAnimationData(src);
1146
725
  if (!animations || animations.some((animation)=>!this._isLottie(animation))) {
1147
726
  throw new Error('Broken or corrupted file');
@@ -1154,7 +733,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1154
733
  manifest.animations[0].autoplay = this.autoplay;
1155
734
  manifest.animations[0].loop = this.loop;
1156
735
  }
1157
- this._isDotLottie = Boolean(isDotLottie);
736
+ this._isDotLottie = isDotLottie;
1158
737
  this._animations = animations;
1159
738
  this._manifest = manifest ?? {
1160
739
  animations: [
@@ -1179,30 +758,37 @@ const generator = '@aarsteinmedia/dotlottie-player';
1179
758
  ...this._getOptions(),
1180
759
  animationData: animations[this._currentAnimation]
1181
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
+ }
1182
787
  } catch (error) {
788
+ console.error(error);
1183
789
  this._errorMessage = handleErrors(error).message;
1184
790
  this.playerState = PlayerState.Error;
1185
791
  this.dispatchEvent(new CustomEvent(PlayerEvents.Error));
1186
- return;
1187
- }
1188
- this._addEventListeners();
1189
- const speed = this._multiAnimationSettings[this._currentAnimation]?.speed ?? this.speed, direction = this._multiAnimationSettings[this._currentAnimation]?.direction ?? this.direction;
1190
- // Set initial playback speed and direction
1191
- this._lottieInstance.setSpeed(speed);
1192
- this._lottieInstance.setDirection(direction);
1193
- this._lottieInstance.setSubframe(Boolean(this.subframe));
1194
- // Start playing if autoplay is enabled
1195
- if (this.autoplay || this.animateOnScroll) {
1196
- if (this.direction === -1) {
1197
- this.seek('99%');
1198
- }
1199
- if (!('IntersectionObserver' in window)) {
1200
- if (!this.animateOnScroll) {
1201
- this.play();
1202
- }
1203
- this._playerState.visible = true;
1204
- }
1205
- this._addIntersectionObserver();
1206
792
  }
1207
793
  }
1208
794
  /**
@@ -1251,7 +837,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1251
837
  if (!this.shadow) {
1252
838
  return;
1253
839
  }
1254
- 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');
1255
841
  if (!(togglePlay instanceof HTMLButtonElement) || !(stop instanceof HTMLButtonElement) || !(next instanceof HTMLButtonElement) || !(prev instanceof HTMLButtonElement) || !(seeker instanceof HTMLInputElement) || !(progress instanceof HTMLProgressElement)) {
1256
842
  return;
1257
843
  }
@@ -1259,9 +845,9 @@ const generator = '@aarsteinmedia/dotlottie-player';
1259
845
  togglePlay.dataset.active = (value === PlayerState.Playing || value === PlayerState.Paused).toString();
1260
846
  stop.dataset.active = (value === PlayerState.Stopped).toString();
1261
847
  if (value === PlayerState.Playing) {
1262
- 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;
1263
849
  } else {
1264
- 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;
1265
851
  }
1266
852
  }
1267
853
  if (name === '_seeker' && typeof value === 'number') {
@@ -1276,17 +862,10 @@ const generator = '@aarsteinmedia/dotlottie-player';
1276
862
  next.hidden = value + 1 >= this._animations.length;
1277
863
  prev.hidden = !value;
1278
864
  }
1279
- 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) {
1280
866
  popover.hidden = !value;
1281
- convert.hidden = false;
867
+ convertButton.hidden = false;
1282
868
  snapshot.hidden = this.renderer !== RendererType.SVG;
1283
- if (this._isDotLottie) {
1284
- convert.ariaLabel = 'Convert dotLottie to JSON';
1285
- convert.innerHTML = convert.innerHTML.replace('dotLottie', 'JSON');
1286
- } else {
1287
- convert.ariaLabel = 'Convert JSON animation to dotLottie format';
1288
- convert.innerHTML = convert.innerHTML.replace('JSON', 'dotLottie');
1289
- }
1290
869
  }
1291
870
  }
1292
871
  /**
@@ -1350,13 +929,11 @@ const generator = '@aarsteinmedia/dotlottie-player';
1350
929
  }
1351
930
  /**
1352
931
  * Set Multi-animation settings.
1353
- *
1354
932
  */ setMultiAnimationSettings(settings) {
1355
933
  this._multiAnimationSettings = settings;
1356
934
  }
1357
935
  /**
1358
936
  * Set playback segment.
1359
- *
1360
937
  */ setSegment(segment) {
1361
938
  this._segment = segment;
1362
939
  }
@@ -1426,7 +1003,7 @@ const generator = '@aarsteinmedia/dotlottie-player';
1426
1003
  /**
1427
1004
  * Toggle Boomerang.
1428
1005
  */ toggleBoomerang() {
1429
- const curr = this._multiAnimationSettings[this._currentAnimation];
1006
+ const curr = this._multiAnimationSettings[this._currentAnimation] ?? {};
1430
1007
  if (curr.mode !== undefined) {
1431
1008
  if (curr.mode === PlayMode.Normal) {
1432
1009
  curr.mode = PlayMode.Bounce;
@@ -1504,7 +1081,6 @@ const generator = '@aarsteinmedia/dotlottie-player';
1504
1081
  }
1505
1082
  /**
1506
1083
  * Handles click and drag actions on the progress track.
1507
- *
1508
1084
  */ _handleSeekChange({ target }) {
1509
1085
  if (!(target instanceof HTMLInputElement) || !this._lottieInstance || isNaN(Number(target.value))) {
1510
1086
  return;
@@ -1512,6 +1088,15 @@ const generator = '@aarsteinmedia/dotlottie-player';
1512
1088
  this.seek(Math.round(Number(target.value) / 100 * this._lottieInstance.totalFrames));
1513
1089
  }
1514
1090
  /**
1091
+ * Handle settings click event.
1092
+ */ _handleSettingsClick({ target }) {
1093
+ this._toggleSettings();
1094
+ // Because Safari does not add focus on click, we need to add it manually, so the onblur event will fire
1095
+ if (target instanceof HTMLElement) {
1096
+ target.focus();
1097
+ }
1098
+ }
1099
+ /**
1515
1100
  * Add event listeners.
1516
1101
  */ _addEventListeners() {
1517
1102
  this._toggleEventListeners('add');
@@ -1871,11 +1456,10 @@ const generator = '@aarsteinmedia/dotlottie-player';
1871
1456
 
1872
1457
  /**
1873
1458
  * Expose DotLottiePlayer class as global variable.
1874
- *
1875
1459
  */ globalThis.dotLottiePlayer = ()=>new DotLottiePlayer();
1876
1460
  const tagName = 'dotlottie-player';
1877
1461
  if (!isServer) {
1878
1462
  customElements.define(tagName, DotLottiePlayer);
1879
1463
  }
1880
1464
 
1881
- export { PlayMode, PlayerState, DotLottiePlayer as default, tagName };
1465
+ export { PlayerState, DotLottiePlayer as default, tagName };