remarqueeble 0.2.0 → 0.4.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.
@@ -1,4 +1,4 @@
1
- /*! remarqueeble v0.2.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
1
+ /*! remarqueeble v0.4.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
2
2
  //#region src/lib/remarqueeble.ts
3
3
  var DEFAULT_DIRECTION = "left";
4
4
  var DEFAULT_BEHAVIOR = "scroll";
@@ -23,6 +23,15 @@ var CSS_VAR_HEIGHT = "--attr-height";
23
23
  var CSS_VAR_HSPACE = "--attr-hspace";
24
24
  var CSS_VAR_VSPACE = "--attr-vspace";
25
25
  var CSS_VAR_BG_COLOR = "--attr-bgcolor";
26
+ var CSS_VAR_ANIMATION_DURATION = "--animation-duration";
27
+ var CSS_VAR_ANIMATION_DIRECTION = "--animation-direction";
28
+ var CSS_VAR_ANIMATION_ITERATION_COUNT = "--animation-iteration-count";
29
+ var CSS_VAR_ANIMATION_PLAY_STATE = "--animation-play-state";
30
+ var CSS_VAR_ANIMATION_TIMING_FUNCTION = "--animation-timing-function";
31
+ var CSS_VAR_TRANSLATE_X_END = "--translate-x-end";
32
+ var CSS_VAR_TRANSLATE_X_START = "--translate-x-start";
33
+ var CSS_VAR_TRANSLATE_Y_END = "--translate-y-end";
34
+ var CSS_VAR_TRANSLATE_Y_START = "--translate-y-start";
26
35
  var HTMLElementBase = globalThis.HTMLElement ?? class {};
27
36
  var parsePresentationalDimension = (value) => {
28
37
  if (value === null) return null;
@@ -83,11 +92,6 @@ var RemarqueebleElement = class extends HTMLElementBase {
83
92
  ];
84
93
  track;
85
94
  running = false;
86
- position = 0;
87
- lastTime = null;
88
- loopsDone = 0;
89
- forward = true;
90
- rafId = null;
91
95
  constructor() {
92
96
  super();
93
97
  const shadowRoot = this.attachShadow({ mode: "open" });
@@ -112,9 +116,32 @@ var RemarqueebleElement = class extends HTMLElementBase {
112
116
  }
113
117
 
114
118
  .track {
119
+ animation: remarqueeble-motion
120
+ var(${CSS_VAR_ANIMATION_DURATION}, 10s)
121
+ var(${CSS_VAR_ANIMATION_TIMING_FUNCTION}, linear)
122
+ var(${CSS_VAR_ANIMATION_ITERATION_COUNT}, infinite)
123
+ var(${CSS_VAR_ANIMATION_DIRECTION}, normal)
124
+ both;
125
+ animation-play-state: var(${CSS_VAR_ANIMATION_PLAY_STATE}, running);
115
126
  display: inline-block;
116
127
  will-change: transform;
117
128
  }
129
+
130
+ @keyframes remarqueeble-motion {
131
+ from {
132
+ transform: translate(
133
+ var(${CSS_VAR_TRANSLATE_X_START}, 100%),
134
+ var(${CSS_VAR_TRANSLATE_Y_START}, 0px)
135
+ );
136
+ }
137
+
138
+ to {
139
+ transform: translate(
140
+ var(${CSS_VAR_TRANSLATE_X_END}, -100%),
141
+ var(${CSS_VAR_TRANSLATE_Y_END}, 0px)
142
+ );
143
+ }
144
+ }
118
145
  </style>
119
146
 
120
147
  <span class="track"><slot></slot></span>
@@ -122,6 +149,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
122
149
  const track = shadowRoot.querySelector(".track");
123
150
  if (!track) throw new Error("Remarqueeble track element was not created.");
124
151
  this.track = track;
152
+ this.track.addEventListener("animationend", () => this.handleAnimationEnd());
125
153
  }
126
154
  connectedCallback() {
127
155
  this.running = true;
@@ -129,16 +157,10 @@ var RemarqueebleElement = class extends HTMLElementBase {
129
157
  requestAnimationFrame(() => {
130
158
  if (!this.isConnected || !this.running) return;
131
159
  this.reset();
132
- this.tick();
133
160
  });
134
161
  }
135
162
  disconnectedCallback() {
136
163
  this.running = false;
137
- this.lastTime = null;
138
- if (this.rafId !== null) {
139
- cancelAnimationFrame(this.rafId);
140
- this.rafId = null;
141
- }
142
164
  }
143
165
  attributeChangedCallback(_name, oldValue, newValue) {
144
166
  if (oldValue === newValue) return;
@@ -176,18 +198,16 @@ var RemarqueebleElement = class extends HTMLElementBase {
176
198
  start() {
177
199
  if (this.running) return;
178
200
  this.running = true;
179
- this.lastTime = null;
180
- this.tick();
201
+ this.reset();
202
+ this.syncAnimationPlayState();
181
203
  }
182
204
  stop() {
183
205
  this.running = false;
184
- if (this.rafId !== null) {
185
- cancelAnimationFrame(this.rafId);
186
- this.rafId = null;
187
- }
206
+ this.syncAnimationPlayState();
188
207
  }
189
208
  syncPresentationalHints() {
190
209
  for (const hint of ATTRIBUTE_HINTS) this.syncVar(hint);
210
+ this.syncAnimationPlayState();
191
211
  }
192
212
  syncVar(hint) {
193
213
  const raw = this.getAttribute(hint.attribute);
@@ -203,10 +223,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
203
223
  reset() {
204
224
  const hostSize = this.getHostSize();
205
225
  const trackSize = this.getTrackSize();
206
- this.loopsDone = 0;
207
- this.forward = true;
208
- this.position = this.behavior === "alternate" ? this.getAlternateStartPosition(hostSize, trackSize) : this.getStartPosition(hostSize, trackSize);
209
- this.render();
226
+ this.syncAnimation(hostSize, trackSize);
210
227
  }
211
228
  getHostSize() {
212
229
  return this.isVerticalDirection ? this.clientHeight : this.clientWidth;
@@ -229,78 +246,63 @@ var RemarqueebleElement = class extends HTMLElementBase {
229
246
  getAlternateStartPosition(hostSize, trackSize) {
230
247
  return this.directionSign < 0 ? hostSize - trackSize : 0;
231
248
  }
232
- tick(time = performance.now()) {
233
- if (!this.running) return;
234
- if (this.lastTime === null) this.lastTime = time;
235
- if (time - this.lastTime >= this.scrollDelay) {
236
- this.step();
237
- this.lastTime = time;
238
- }
239
- if (!this.running) return;
240
- this.rafId = requestAnimationFrame((nextTime) => this.tick(nextTime));
249
+ syncAnimationPlayState() {
250
+ this.style.setProperty(CSS_VAR_ANIMATION_PLAY_STATE, this.running ? "running" : "paused");
241
251
  }
242
- step() {
243
- const hostSize = this.getHostSize();
244
- const trackSize = this.getTrackSize();
245
- const startPosition = this.getStartPosition(hostSize, trackSize);
246
- const flushEndPosition = this.getFlushEndPosition(hostSize, trackSize);
247
- const offEndPosition = this.getOffEndPosition(hostSize, trackSize);
248
- const slideEndPosition = this.getSlideEndPosition(hostSize, trackSize);
249
- const alternateStartPosition = this.getAlternateStartPosition(hostSize, trackSize);
250
- const amount = this.scrollAmount;
251
- const delta = this.directionSign * amount;
252
- if (this.behavior === "alternate") {
253
- this.position += this.forward ? delta : -delta;
254
- if (this.forward) {
255
- if (this.directionSign < 0 && this.position <= flushEndPosition || this.directionSign > 0 && this.position >= flushEndPosition) {
256
- this.position = flushEndPosition;
257
- this.forward = false;
258
- this.incrementLoopCount();
259
- if (this.shouldStopAfterLoop()) this.stop();
260
- }
261
- } else if (this.directionSign < 0 && this.position >= alternateStartPosition || this.directionSign > 0 && this.position <= alternateStartPosition) {
262
- this.position = alternateStartPosition;
263
- this.forward = true;
264
- this.incrementLoopCount();
265
- if (this.shouldStopAfterLoop()) this.stop();
266
- }
267
- } else if (this.behavior === "slide") {
268
- this.position += delta;
269
- if (this.directionSign < 0 && this.position <= slideEndPosition || this.directionSign > 0 && this.position >= slideEndPosition) {
270
- this.position = slideEndPosition;
271
- this.incrementLoopCount();
272
- if (!this.hasAttribute(ATTR_LOOP) || this.loop <= 0) this.stop();
273
- else if (this.shouldStopAfterLoop()) this.stop();
274
- else this.position = startPosition;
275
- }
252
+ syncAnimation(hostSize, trackSize) {
253
+ const startPosition = this.behavior === "alternate" ? this.getAlternateStartPosition(hostSize, trackSize) : this.getStartPosition(hostSize, trackSize);
254
+ const endPosition = this.behavior === "slide" ? this.getSlideEndPosition(hostSize, trackSize) : this.behavior === "alternate" ? this.getFlushEndPosition(hostSize, trackSize) : this.getOffEndPosition(hostSize, trackSize);
255
+ const distance = Math.abs(endPosition - startPosition);
256
+ const steps = Math.max(1, Math.ceil(distance / Math.max(1, this.scrollAmount)));
257
+ const duration = Math.max(1, steps * this.scrollDelay);
258
+ const iterationCount = this.getCssIterationCount();
259
+ this.track.style.removeProperty("transform");
260
+ this.style.setProperty(CSS_VAR_ANIMATION_DURATION, `${duration}ms`);
261
+ this.style.setProperty(CSS_VAR_ANIMATION_DIRECTION, this.behavior === "alternate" ? "alternate" : "normal");
262
+ this.style.setProperty(CSS_VAR_ANIMATION_ITERATION_COUNT, iterationCount);
263
+ this.style.setProperty(CSS_VAR_ANIMATION_TIMING_FUNCTION, `steps(${steps}, end)`);
264
+ if (this.isVerticalDirection) {
265
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_START, "0px");
266
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_END, "0px");
267
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_START, `${startPosition}px`);
268
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_END, `${endPosition}px`);
276
269
  } else {
277
- this.position += delta;
278
- if (this.directionSign < 0 && this.position <= offEndPosition || this.directionSign > 0 && this.position >= offEndPosition) {
279
- this.position = startPosition;
280
- this.incrementLoopCount();
281
- if (this.shouldStopAfterLoop()) this.stop();
282
- }
270
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_START, `${startPosition}px`);
271
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_END, `${endPosition}px`);
272
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_START, "0px");
273
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_END, "0px");
283
274
  }
284
- this.render();
275
+ this.restartAnimation();
285
276
  }
286
- incrementLoopCount() {
287
- this.loopsDone++;
277
+ getCssIterationCount() {
278
+ if (this.behavior === "slide" && !this.hasAttribute(ATTR_LOOP)) return "1";
279
+ if (!this.hasAttribute(ATTR_LOOP)) return "infinite";
280
+ if (Number.isFinite(this.loop) && this.loop > 0) return String(this.loop);
281
+ return "infinite";
282
+ }
283
+ handleAnimationEnd() {
284
+ if (!this.hasFiniteAnimation()) return;
285
+ this.running = false;
286
+ this.syncAnimationPlayState();
288
287
  }
289
- shouldStopAfterLoop() {
290
- return this.hasAttribute(ATTR_LOOP) && this.loop > 0 && this.loopsDone >= this.loop;
288
+ restartAnimation() {
289
+ this.track.style.animationName = "none";
290
+ this.track.offsetWidth;
291
+ this.track.style.removeProperty("animation-name");
291
292
  }
292
- render() {
293
- if (this.isVerticalDirection) this.track.style.transform = `translateY(${this.position}px)`;
294
- else this.track.style.transform = `translateX(${this.position}px)`;
293
+ hasFiniteAnimation() {
294
+ if (this.behavior === "slide" && !this.hasAttribute(ATTR_LOOP)) return true;
295
+ return this.hasAttribute(ATTR_LOOP) && Number.isFinite(this.loop) && this.loop > 0;
295
296
  }
296
297
  };
298
+ var ReMarqueeElement = class extends RemarqueebleElement {};
299
+ var ReMarqueeBleElement = class extends RemarqueebleElement {};
297
300
  var defineRemarqueebleElements = () => {
298
301
  if (typeof customElements === "undefined") return;
299
- if (!customElements.get("re-marquee")) customElements.define("re-marquee", RemarqueebleElement);
300
- if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble", RemarqueebleElement);
302
+ if (!customElements.get("re-marquee")) customElements.define("re-marquee", ReMarqueeElement);
303
+ if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble", ReMarqueeBleElement);
301
304
  };
302
305
  //#endregion
303
306
  //#region src/lib/auto.ts
304
307
  defineRemarqueebleElements();
305
308
  //#endregion
306
- export { defineRemarqueebleElements };
@@ -1,4 +1,4 @@
1
- /*! remarqueeble v0.2.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
1
+ /*! remarqueeble v0.4.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  //#region src/lib/remarqueeble.ts
4
4
  var DEFAULT_DIRECTION = "left";
@@ -24,6 +24,15 @@ var CSS_VAR_HEIGHT = "--attr-height";
24
24
  var CSS_VAR_HSPACE = "--attr-hspace";
25
25
  var CSS_VAR_VSPACE = "--attr-vspace";
26
26
  var CSS_VAR_BG_COLOR = "--attr-bgcolor";
27
+ var CSS_VAR_ANIMATION_DURATION = "--animation-duration";
28
+ var CSS_VAR_ANIMATION_DIRECTION = "--animation-direction";
29
+ var CSS_VAR_ANIMATION_ITERATION_COUNT = "--animation-iteration-count";
30
+ var CSS_VAR_ANIMATION_PLAY_STATE = "--animation-play-state";
31
+ var CSS_VAR_ANIMATION_TIMING_FUNCTION = "--animation-timing-function";
32
+ var CSS_VAR_TRANSLATE_X_END = "--translate-x-end";
33
+ var CSS_VAR_TRANSLATE_X_START = "--translate-x-start";
34
+ var CSS_VAR_TRANSLATE_Y_END = "--translate-y-end";
35
+ var CSS_VAR_TRANSLATE_Y_START = "--translate-y-start";
27
36
  var HTMLElementBase = globalThis.HTMLElement ?? class {};
28
37
  var parsePresentationalDimension = (value) => {
29
38
  if (value === null) return null;
@@ -84,11 +93,6 @@ var RemarqueebleElement = class extends HTMLElementBase {
84
93
  ];
85
94
  track;
86
95
  running = false;
87
- position = 0;
88
- lastTime = null;
89
- loopsDone = 0;
90
- forward = true;
91
- rafId = null;
92
96
  constructor() {
93
97
  super();
94
98
  const shadowRoot = this.attachShadow({ mode: "open" });
@@ -113,9 +117,32 @@ var RemarqueebleElement = class extends HTMLElementBase {
113
117
  }
114
118
 
115
119
  .track {
120
+ animation: remarqueeble-motion
121
+ var(${CSS_VAR_ANIMATION_DURATION}, 10s)
122
+ var(${CSS_VAR_ANIMATION_TIMING_FUNCTION}, linear)
123
+ var(${CSS_VAR_ANIMATION_ITERATION_COUNT}, infinite)
124
+ var(${CSS_VAR_ANIMATION_DIRECTION}, normal)
125
+ both;
126
+ animation-play-state: var(${CSS_VAR_ANIMATION_PLAY_STATE}, running);
116
127
  display: inline-block;
117
128
  will-change: transform;
118
129
  }
130
+
131
+ @keyframes remarqueeble-motion {
132
+ from {
133
+ transform: translate(
134
+ var(${CSS_VAR_TRANSLATE_X_START}, 100%),
135
+ var(${CSS_VAR_TRANSLATE_Y_START}, 0px)
136
+ );
137
+ }
138
+
139
+ to {
140
+ transform: translate(
141
+ var(${CSS_VAR_TRANSLATE_X_END}, -100%),
142
+ var(${CSS_VAR_TRANSLATE_Y_END}, 0px)
143
+ );
144
+ }
145
+ }
119
146
  </style>
120
147
 
121
148
  <span class="track"><slot></slot></span>
@@ -123,6 +150,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
123
150
  const track = shadowRoot.querySelector(".track");
124
151
  if (!track) throw new Error("Remarqueeble track element was not created.");
125
152
  this.track = track;
153
+ this.track.addEventListener("animationend", () => this.handleAnimationEnd());
126
154
  }
127
155
  connectedCallback() {
128
156
  this.running = true;
@@ -130,16 +158,10 @@ var RemarqueebleElement = class extends HTMLElementBase {
130
158
  requestAnimationFrame(() => {
131
159
  if (!this.isConnected || !this.running) return;
132
160
  this.reset();
133
- this.tick();
134
161
  });
135
162
  }
136
163
  disconnectedCallback() {
137
164
  this.running = false;
138
- this.lastTime = null;
139
- if (this.rafId !== null) {
140
- cancelAnimationFrame(this.rafId);
141
- this.rafId = null;
142
- }
143
165
  }
144
166
  attributeChangedCallback(_name, oldValue, newValue) {
145
167
  if (oldValue === newValue) return;
@@ -177,18 +199,16 @@ var RemarqueebleElement = class extends HTMLElementBase {
177
199
  start() {
178
200
  if (this.running) return;
179
201
  this.running = true;
180
- this.lastTime = null;
181
- this.tick();
202
+ this.reset();
203
+ this.syncAnimationPlayState();
182
204
  }
183
205
  stop() {
184
206
  this.running = false;
185
- if (this.rafId !== null) {
186
- cancelAnimationFrame(this.rafId);
187
- this.rafId = null;
188
- }
207
+ this.syncAnimationPlayState();
189
208
  }
190
209
  syncPresentationalHints() {
191
210
  for (const hint of ATTRIBUTE_HINTS) this.syncVar(hint);
211
+ this.syncAnimationPlayState();
192
212
  }
193
213
  syncVar(hint) {
194
214
  const raw = this.getAttribute(hint.attribute);
@@ -204,10 +224,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
204
224
  reset() {
205
225
  const hostSize = this.getHostSize();
206
226
  const trackSize = this.getTrackSize();
207
- this.loopsDone = 0;
208
- this.forward = true;
209
- this.position = this.behavior === "alternate" ? this.getAlternateStartPosition(hostSize, trackSize) : this.getStartPosition(hostSize, trackSize);
210
- this.render();
227
+ this.syncAnimation(hostSize, trackSize);
211
228
  }
212
229
  getHostSize() {
213
230
  return this.isVerticalDirection ? this.clientHeight : this.clientWidth;
@@ -230,75 +247,61 @@ var RemarqueebleElement = class extends HTMLElementBase {
230
247
  getAlternateStartPosition(hostSize, trackSize) {
231
248
  return this.directionSign < 0 ? hostSize - trackSize : 0;
232
249
  }
233
- tick(time = performance.now()) {
234
- if (!this.running) return;
235
- if (this.lastTime === null) this.lastTime = time;
236
- if (time - this.lastTime >= this.scrollDelay) {
237
- this.step();
238
- this.lastTime = time;
239
- }
240
- if (!this.running) return;
241
- this.rafId = requestAnimationFrame((nextTime) => this.tick(nextTime));
250
+ syncAnimationPlayState() {
251
+ this.style.setProperty(CSS_VAR_ANIMATION_PLAY_STATE, this.running ? "running" : "paused");
242
252
  }
243
- step() {
244
- const hostSize = this.getHostSize();
245
- const trackSize = this.getTrackSize();
246
- const startPosition = this.getStartPosition(hostSize, trackSize);
247
- const flushEndPosition = this.getFlushEndPosition(hostSize, trackSize);
248
- const offEndPosition = this.getOffEndPosition(hostSize, trackSize);
249
- const slideEndPosition = this.getSlideEndPosition(hostSize, trackSize);
250
- const alternateStartPosition = this.getAlternateStartPosition(hostSize, trackSize);
251
- const amount = this.scrollAmount;
252
- const delta = this.directionSign * amount;
253
- if (this.behavior === "alternate") {
254
- this.position += this.forward ? delta : -delta;
255
- if (this.forward) {
256
- if (this.directionSign < 0 && this.position <= flushEndPosition || this.directionSign > 0 && this.position >= flushEndPosition) {
257
- this.position = flushEndPosition;
258
- this.forward = false;
259
- this.incrementLoopCount();
260
- if (this.shouldStopAfterLoop()) this.stop();
261
- }
262
- } else if (this.directionSign < 0 && this.position >= alternateStartPosition || this.directionSign > 0 && this.position <= alternateStartPosition) {
263
- this.position = alternateStartPosition;
264
- this.forward = true;
265
- this.incrementLoopCount();
266
- if (this.shouldStopAfterLoop()) this.stop();
267
- }
268
- } else if (this.behavior === "slide") {
269
- this.position += delta;
270
- if (this.directionSign < 0 && this.position <= slideEndPosition || this.directionSign > 0 && this.position >= slideEndPosition) {
271
- this.position = slideEndPosition;
272
- this.incrementLoopCount();
273
- if (!this.hasAttribute(ATTR_LOOP) || this.loop <= 0) this.stop();
274
- else if (this.shouldStopAfterLoop()) this.stop();
275
- else this.position = startPosition;
276
- }
253
+ syncAnimation(hostSize, trackSize) {
254
+ const startPosition = this.behavior === "alternate" ? this.getAlternateStartPosition(hostSize, trackSize) : this.getStartPosition(hostSize, trackSize);
255
+ const endPosition = this.behavior === "slide" ? this.getSlideEndPosition(hostSize, trackSize) : this.behavior === "alternate" ? this.getFlushEndPosition(hostSize, trackSize) : this.getOffEndPosition(hostSize, trackSize);
256
+ const distance = Math.abs(endPosition - startPosition);
257
+ const steps = Math.max(1, Math.ceil(distance / Math.max(1, this.scrollAmount)));
258
+ const duration = Math.max(1, steps * this.scrollDelay);
259
+ const iterationCount = this.getCssIterationCount();
260
+ this.track.style.removeProperty("transform");
261
+ this.style.setProperty(CSS_VAR_ANIMATION_DURATION, `${duration}ms`);
262
+ this.style.setProperty(CSS_VAR_ANIMATION_DIRECTION, this.behavior === "alternate" ? "alternate" : "normal");
263
+ this.style.setProperty(CSS_VAR_ANIMATION_ITERATION_COUNT, iterationCount);
264
+ this.style.setProperty(CSS_VAR_ANIMATION_TIMING_FUNCTION, `steps(${steps}, end)`);
265
+ if (this.isVerticalDirection) {
266
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_START, "0px");
267
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_END, "0px");
268
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_START, `${startPosition}px`);
269
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_END, `${endPosition}px`);
277
270
  } else {
278
- this.position += delta;
279
- if (this.directionSign < 0 && this.position <= offEndPosition || this.directionSign > 0 && this.position >= offEndPosition) {
280
- this.position = startPosition;
281
- this.incrementLoopCount();
282
- if (this.shouldStopAfterLoop()) this.stop();
283
- }
271
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_START, `${startPosition}px`);
272
+ this.style.setProperty(CSS_VAR_TRANSLATE_X_END, `${endPosition}px`);
273
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_START, "0px");
274
+ this.style.setProperty(CSS_VAR_TRANSLATE_Y_END, "0px");
284
275
  }
285
- this.render();
276
+ this.restartAnimation();
286
277
  }
287
- incrementLoopCount() {
288
- this.loopsDone++;
278
+ getCssIterationCount() {
279
+ if (this.behavior === "slide" && !this.hasAttribute(ATTR_LOOP)) return "1";
280
+ if (!this.hasAttribute(ATTR_LOOP)) return "infinite";
281
+ if (Number.isFinite(this.loop) && this.loop > 0) return String(this.loop);
282
+ return "infinite";
283
+ }
284
+ handleAnimationEnd() {
285
+ if (!this.hasFiniteAnimation()) return;
286
+ this.running = false;
287
+ this.syncAnimationPlayState();
289
288
  }
290
- shouldStopAfterLoop() {
291
- return this.hasAttribute(ATTR_LOOP) && this.loop > 0 && this.loopsDone >= this.loop;
289
+ restartAnimation() {
290
+ this.track.style.animationName = "none";
291
+ this.track.offsetWidth;
292
+ this.track.style.removeProperty("animation-name");
292
293
  }
293
- render() {
294
- if (this.isVerticalDirection) this.track.style.transform = `translateY(${this.position}px)`;
295
- else this.track.style.transform = `translateX(${this.position}px)`;
294
+ hasFiniteAnimation() {
295
+ if (this.behavior === "slide" && !this.hasAttribute(ATTR_LOOP)) return true;
296
+ return this.hasAttribute(ATTR_LOOP) && Number.isFinite(this.loop) && this.loop > 0;
296
297
  }
297
298
  };
299
+ var ReMarqueeElement = class extends RemarqueebleElement {};
300
+ var ReMarqueeBleElement = class extends RemarqueebleElement {};
298
301
  var defineRemarqueebleElements = () => {
299
302
  if (typeof customElements === "undefined") return;
300
- if (!customElements.get("re-marquee")) customElements.define("re-marquee", RemarqueebleElement);
301
- if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble", RemarqueebleElement);
303
+ if (!customElements.get("re-marquee")) customElements.define("re-marquee", ReMarqueeElement);
304
+ if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble", ReMarqueeBleElement);
302
305
  };
303
306
  //#endregion
304
307
  exports.RemarqueebleElement = RemarqueebleElement;
@@ -8,11 +8,6 @@ export declare class RemarqueebleElement extends HTMLElementBase {
8
8
  static observedAttributes: string[];
9
9
  private readonly track;
10
10
  private running;
11
- private position;
12
- private lastTime;
13
- private loopsDone;
14
- private forward;
15
- private rafId;
16
11
  constructor();
17
12
  connectedCallback(): void;
18
13
  disconnectedCallback(): void;
@@ -36,11 +31,12 @@ export declare class RemarqueebleElement extends HTMLElementBase {
36
31
  private getOffEndPosition;
37
32
  private getSlideEndPosition;
38
33
  private getAlternateStartPosition;
39
- private tick;
40
- private step;
41
- private incrementLoopCount;
42
- private shouldStopAfterLoop;
43
- private render;
34
+ private syncAnimationPlayState;
35
+ private syncAnimation;
36
+ private getCssIterationCount;
37
+ private handleAnimationEnd;
38
+ private restartAnimation;
39
+ private hasFiniteAnimation;
44
40
  }
45
41
  export declare const defineRemarqueebleElements: () => void;
46
42
  declare global {