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.
package/README.md CHANGED
@@ -15,9 +15,13 @@ By Rémino Rem
15
15
  <!-- mtoc-start -->
16
16
 
17
17
  - [Installation](#installation)
18
+ - [HTML (CDN)](#html-cdn)
19
+ - [npm](#npm)
20
+ - [Direct download](#direct-download)
18
21
  - [Usage](#usage)
19
22
  - [Attributes](#attributes)
20
23
  - [API](#api)
24
+ - [Remarquee Lite](#remarquee-lite)
21
25
  - [Development](#development)
22
26
  - [Contributing](#contributing)
23
27
  - [Licence](#licence)
@@ -28,23 +32,50 @@ By Rémino Rem
28
32
 
29
33
  ## Installation
30
34
 
31
- ```sh
32
- npm install remarqueeble
35
+ ### HTML (CDN)
36
+
37
+ Register the custom elements automatically from a CDN:
38
+
39
+ ```html
40
+ <script src="https://unpkg.com/remarqueeble"></script>
33
41
  ```
34
42
 
35
- [Back to top](#)
43
+ Mirrors:
36
44
 
37
- ---
45
+ - https://unpkg.com/remarqueeble
46
+ - https://cdn.jsdelivr.net/npm/remarqueeble
38
47
 
39
- ## Usage
48
+ Use a pinned version in production:
49
+
50
+ ```html
51
+ <script src="https://unpkg.com/remarqueeble@0.3.0"></script>
52
+ ```
53
+
54
+ If you want the API instead of auto-registration, import the ES module directly:
40
55
 
41
- Register the custom elements automatically:
56
+ ```html
57
+ <script type="module">
58
+ import { defineRemarqueebleElements } from 'https://unpkg.com/remarqueeble@0.3.0/dist/remarqueeble.mjs'
59
+
60
+ defineRemarqueebleElements()
61
+ </script>
62
+ ```
63
+
64
+ ### npm
65
+
66
+ Install the package first:
67
+
68
+ ```sh
69
+ npm install remarqueeble
70
+ ```
71
+
72
+ Then register the custom elements automatically:
42
73
 
43
74
  ```js
44
75
  import 'remarqueeble/auto'
45
76
  ```
46
77
 
47
- Or register them explicitly:
78
+ Or import the explicit API:
48
79
 
49
80
  ```js
50
81
  import { defineRemarqueebleElements } from 'remarqueeble'
@@ -52,7 +83,36 @@ import { defineRemarqueebleElements } from 'remarqueeble'
52
83
  defineRemarqueebleElements()
53
84
  ```
54
85
 
55
- Then use either element name:
86
+ TypeScript declarations are included with the package.
87
+
88
+ Bundlers normally minify production builds for you, so npm users should prefer
89
+ the package exports above instead of importing files from `dist/` directly.
90
+
91
+ ### Direct download
92
+
93
+ Download the package tarball or individual files from npm/CDN:
94
+
95
+ - https://www.npmjs.com/package/remarqueeble
96
+ - https://unpkg.com/remarqueeble/dist/
97
+ - https://cdn.jsdelivr.net/npm/remarqueeble/dist/
98
+
99
+ The browser-ready auto-registration file is `dist/remarqueeble-auto.min.js`.
100
+
101
+ Distribution files:
102
+
103
+ - `dist/remarqueeble.mjs`: ES module library API.
104
+ - `dist/remarqueeble.cjs`: CommonJS library API.
105
+ - `dist/remarqueeble-auto.mjs`: ES module auto-registration entry.
106
+ - `dist/remarqueeble-auto.cjs`: CommonJS auto-registration entry.
107
+ - `dist/remarqueeble-auto.min.js`: minified classic browser auto-registration.
108
+
109
+ [Back to top](#)
110
+
111
+ ---
112
+
113
+ ## Usage
114
+
115
+ After registration, use either element name:
56
116
 
57
117
  ```html
58
118
  <re-marquee>Default marquee behaviour.</re-marquee>
@@ -96,6 +156,34 @@ marquee.start()
96
156
 
97
157
  ---
98
158
 
159
+ ## Remarquee Lite
160
+
161
+ For a CSS-only marquee, import `remarqueeble/lite.css` or load
162
+ `dist/lite.css` directly:
163
+
164
+ ```html
165
+ <link rel="stylesheet" href="https://unpkg.com/remarqueeble/dist/lite.css" />
166
+
167
+ <div class="re-marquee" style="--re-marquee-duration: 12s;">
168
+ <div class="re-marquee__track">CSS-only marquee</div>
169
+ </div>
170
+ ```
171
+
172
+ The lite CSS follows the simpler pure-CSS pattern and does not require
173
+ duplicated content. It does not emulate legacy `<marquee>` measurement,
174
+ `behavior`, `scrollamount`, `scrolldelay`, or finite `loop` handling.
175
+
176
+ Optional classes:
177
+
178
+ - `re-marquee--reverse`: scroll in the opposite direction.
179
+ - `re-marquee--vertical`: scroll vertically.
180
+ - `re-marquee--paused`: pause the animation.
181
+ - `re-marquee--pause-on-hover`: pause while hovered.
182
+
183
+ [Back to top](#)
184
+
185
+ ---
186
+
99
187
  ## Development
100
188
 
101
189
  ```sh
package/dist/auto.d.ts CHANGED
@@ -1 +1 @@
1
- export { defineRemarqueebleElements } from './remarqueeble';
1
+ export {};
package/dist/lite.css ADDED
@@ -0,0 +1,73 @@
1
+ /*! remarqueeble v0.4.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
2
+ .re-marquee {
3
+ --re-marquee-duration: 20s;
4
+ --re-marquee-play-state: running;
5
+ --re-marquee-timing-function: linear;
6
+
7
+ display: block;
8
+ overflow: hidden;
9
+ white-space: nowrap;
10
+ }
11
+
12
+ .re-marquee__track {
13
+ animation: re-marquee-scroll var(--re-marquee-duration)
14
+ var(--re-marquee-timing-function) infinite;
15
+ animation-play-state: var(--re-marquee-play-state);
16
+ display: inline-block;
17
+ min-inline-size: max-content;
18
+ will-change: transform;
19
+ }
20
+
21
+ .re-marquee--reverse > .re-marquee__track {
22
+ animation-direction: reverse;
23
+ }
24
+
25
+ .re-marquee--paused {
26
+ --re-marquee-play-state: paused;
27
+ }
28
+
29
+ .re-marquee--pause-on-hover:hover {
30
+ --re-marquee-play-state: paused;
31
+ }
32
+
33
+ .re-marquee--vertical {
34
+ block-size: 12rem;
35
+ white-space: normal;
36
+ }
37
+
38
+ .re-marquee--vertical > .re-marquee__track {
39
+ animation-name: re-marquee-scroll-y;
40
+ display: inline-flex;
41
+ flex-direction: column;
42
+ min-inline-size: auto;
43
+ }
44
+
45
+ @media (prefers-reduced-motion: reduce) {
46
+ .re-marquee {
47
+ overflow: auto;
48
+ }
49
+
50
+ .re-marquee__track {
51
+ animation: none;
52
+ }
53
+ }
54
+
55
+ @keyframes re-marquee-scroll {
56
+ from {
57
+ transform: translateX(clamp(100%, 40rem, 100vw));
58
+ }
59
+
60
+ to {
61
+ transform: translateX(var(--re-marquee-end-pos, -100%));
62
+ }
63
+ }
64
+
65
+ @keyframes re-marquee-scroll-y {
66
+ from {
67
+ transform: translateY(clamp(100%, 40rem, 100vh));
68
+ }
69
+
70
+ to {
71
+ transform: translateY(var(--re-marquee-end-pos, -100%));
72
+ }
73
+ }
@@ -1,5 +1,4 @@
1
- /*! remarqueeble v0.2.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
1
+ /*! remarqueeble v0.4.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
3
2
  //#region src/lib/remarqueeble.ts
4
3
  var DEFAULT_DIRECTION = "left";
5
4
  var DEFAULT_BEHAVIOR = "scroll";
@@ -24,6 +23,15 @@ var CSS_VAR_HEIGHT = "--attr-height";
24
23
  var CSS_VAR_HSPACE = "--attr-hspace";
25
24
  var CSS_VAR_VSPACE = "--attr-vspace";
26
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";
27
35
  var HTMLElementBase = globalThis.HTMLElement ?? class {};
28
36
  var parsePresentationalDimension = (value) => {
29
37
  if (value === null) return null;
@@ -84,11 +92,6 @@ var RemarqueebleElement = class extends HTMLElementBase {
84
92
  ];
85
93
  track;
86
94
  running = false;
87
- position = 0;
88
- lastTime = null;
89
- loopsDone = 0;
90
- forward = true;
91
- rafId = null;
92
95
  constructor() {
93
96
  super();
94
97
  const shadowRoot = this.attachShadow({ mode: "open" });
@@ -113,9 +116,32 @@ var RemarqueebleElement = class extends HTMLElementBase {
113
116
  }
114
117
 
115
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);
116
126
  display: inline-block;
117
127
  will-change: transform;
118
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
+ }
119
145
  </style>
120
146
 
121
147
  <span class="track"><slot></slot></span>
@@ -123,6 +149,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
123
149
  const track = shadowRoot.querySelector(".track");
124
150
  if (!track) throw new Error("Remarqueeble track element was not created.");
125
151
  this.track = track;
152
+ this.track.addEventListener("animationend", () => this.handleAnimationEnd());
126
153
  }
127
154
  connectedCallback() {
128
155
  this.running = true;
@@ -130,16 +157,10 @@ var RemarqueebleElement = class extends HTMLElementBase {
130
157
  requestAnimationFrame(() => {
131
158
  if (!this.isConnected || !this.running) return;
132
159
  this.reset();
133
- this.tick();
134
160
  });
135
161
  }
136
162
  disconnectedCallback() {
137
163
  this.running = false;
138
- this.lastTime = null;
139
- if (this.rafId !== null) {
140
- cancelAnimationFrame(this.rafId);
141
- this.rafId = null;
142
- }
143
164
  }
144
165
  attributeChangedCallback(_name, oldValue, newValue) {
145
166
  if (oldValue === newValue) return;
@@ -177,18 +198,16 @@ var RemarqueebleElement = class extends HTMLElementBase {
177
198
  start() {
178
199
  if (this.running) return;
179
200
  this.running = true;
180
- this.lastTime = null;
181
- this.tick();
201
+ this.reset();
202
+ this.syncAnimationPlayState();
182
203
  }
183
204
  stop() {
184
205
  this.running = false;
185
- if (this.rafId !== null) {
186
- cancelAnimationFrame(this.rafId);
187
- this.rafId = null;
188
- }
206
+ this.syncAnimationPlayState();
189
207
  }
190
208
  syncPresentationalHints() {
191
209
  for (const hint of ATTRIBUTE_HINTS) this.syncVar(hint);
210
+ this.syncAnimationPlayState();
192
211
  }
193
212
  syncVar(hint) {
194
213
  const raw = this.getAttribute(hint.attribute);
@@ -204,10 +223,7 @@ var RemarqueebleElement = class extends HTMLElementBase {
204
223
  reset() {
205
224
  const hostSize = this.getHostSize();
206
225
  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();
226
+ this.syncAnimation(hostSize, trackSize);
211
227
  }
212
228
  getHostSize() {
213
229
  return this.isVerticalDirection ? this.clientHeight : this.clientWidth;
@@ -230,78 +246,63 @@ var RemarqueebleElement = class extends HTMLElementBase {
230
246
  getAlternateStartPosition(hostSize, trackSize) {
231
247
  return this.directionSign < 0 ? hostSize - trackSize : 0;
232
248
  }
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));
249
+ syncAnimationPlayState() {
250
+ this.style.setProperty(CSS_VAR_ANIMATION_PLAY_STATE, this.running ? "running" : "paused");
242
251
  }
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
- }
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`);
277
269
  } 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
- }
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");
284
274
  }
285
- this.render();
275
+ this.restartAnimation();
286
276
  }
287
- incrementLoopCount() {
288
- 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();
289
287
  }
290
- shouldStopAfterLoop() {
291
- 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");
292
292
  }
293
- render() {
294
- if (this.isVerticalDirection) this.track.style.transform = `translateY(${this.position}px)`;
295
- 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;
296
296
  }
297
297
  };
298
+ var ReMarqueeElement = class extends RemarqueebleElement {};
299
+ var ReMarqueeBleElement = class extends RemarqueebleElement {};
298
300
  var defineRemarqueebleElements = () => {
299
301
  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);
302
+ if (!customElements.get("re-marquee")) customElements.define("re-marquee", ReMarqueeElement);
303
+ if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble", ReMarqueeBleElement);
302
304
  };
303
305
  //#endregion
304
306
  //#region src/lib/auto.ts
305
307
  defineRemarqueebleElements();
306
308
  //#endregion
307
- exports.defineRemarqueebleElements = defineRemarqueebleElements;
@@ -0,0 +1,52 @@
1
+ /*! remarqueeble v0.4.0 | (c) 2026 Rémino Rem <https://remino.net/> | ISC Licence */
2
+ (function(){var e=`direction`,t=`behavior`,n=`scrollamount`,r=`scrolldelay`,i=`truespeed`,a=`loop`,o=`bgcolor`,s=`width`,c=`height`,l=`hspace`,u=`vspace`,d=`--attr-width`,f=`--attr-height`,p=`--attr-hspace`,m=`--attr-vspace`,h=`--attr-bgcolor`,g=`--animation-duration`,_=`--animation-direction`,v=`--animation-iteration-count`,y=`--animation-play-state`,b=`--animation-timing-function`,x=`--translate-x-end`,S=`--translate-x-start`,C=`--translate-y-end`,w=`--translate-y-start`,T=globalThis.HTMLElement??class{},E=e=>{if(e===null)return null;let t=e.trim();return t===``?null:/^[+-]?(?:\d+|\d*\.\d+)$/.test(t)?`${t}px`:globalThis.CSS?.supports(`width`,t)?t:null},D=[{attribute:s,cssVar:d,parser:E},{attribute:c,cssVar:f,parser:E,fallback(e){return e.isVerticalDirection&&!e.hasAttribute(c)?`200px`:null}},{attribute:l,cssVar:p,parser:E},{attribute:u,cssVar:m,parser:E},{attribute:o,cssVar:h,parser:e=>{if(e===null)return null;let t=e.trim();return t===``?null:globalThis.CSS?.supports(`background-color`,t)?t:null}}],O=class extends T{static observedAttributes=[e,t,n,r,i,a,o,s,c,l,u];track;running=!1;constructor(){super();let e=this.attachShadow({mode:`open`});e.innerHTML=`
3
+ <style>
4
+ :host {
5
+ display: inline-block;
6
+ text-align: initial;
7
+ overflow: hidden !important;
8
+ white-space: nowrap;
9
+ width: var(${d}, calc(100% - (var(--attr-hspace, 0px) * 2)));
10
+ height: var(${f}, auto);
11
+ margin-inline: var(${p}, 0px);
12
+ margin-block: var(${m}, 0px);
13
+ background-color: var(${h}, transparent);
14
+ box-sizing: border-box;
15
+ }
16
+
17
+ :host([direction="up"]),
18
+ :host([direction="down"]) {
19
+ white-space: normal;
20
+ }
21
+
22
+ .track {
23
+ animation: remarqueeble-motion
24
+ var(${g}, 10s)
25
+ var(${b}, linear)
26
+ var(${v}, infinite)
27
+ var(${_}, normal)
28
+ both;
29
+ animation-play-state: var(${y}, running);
30
+ display: inline-block;
31
+ will-change: transform;
32
+ }
33
+
34
+ @keyframes remarqueeble-motion {
35
+ from {
36
+ transform: translate(
37
+ var(${S}, 100%),
38
+ var(${w}, 0px)
39
+ );
40
+ }
41
+
42
+ to {
43
+ transform: translate(
44
+ var(${x}, -100%),
45
+ var(${C}, 0px)
46
+ );
47
+ }
48
+ }
49
+ </style>
50
+
51
+ <span class="track"><slot></slot></span>
52
+ `;let t=e.querySelector(`.track`);if(!t)throw Error(`Remarqueeble track element was not created.`);this.track=t,this.track.addEventListener(`animationend`,()=>this.handleAnimationEnd())}connectedCallback(){this.running=!0,this.syncPresentationalHints(),requestAnimationFrame(()=>{!this.isConnected||!this.running||this.reset()})}disconnectedCallback(){this.running=!1}attributeChangedCallback(e,t,n){t!==n&&(this.syncPresentationalHints(),this.isConnected&&this.reset())}get direction(){return this.getAttribute(e)||`left`}get behavior(){return this.getAttribute(t)||`scroll`}get scrollAmount(){let e=this.getAttribute(n),t=e===null||e.trim()===``?NaN:Number(e);return Number.isFinite(t)&&t>=0?t:6}get scrollDelay(){let e=this.getAttribute(r),t=e===null||e.trim()===``?NaN:Number(e),n=Number.isFinite(t)&&t>=0?t:85;return this.hasAttribute(i)?n:Math.max(n,60)}get loop(){let e=this.getAttribute(a);return e===null?-1:Number(e)}get directionSign(){return this.direction===`right`||this.direction===`down`?1:-1}get isVerticalDirection(){return this.direction===`up`||this.direction===`down`}start(){this.running||(this.running=!0,this.reset(),this.syncAnimationPlayState())}stop(){this.running=!1,this.syncAnimationPlayState()}syncPresentationalHints(){for(let e of D)this.syncVar(e);this.syncAnimationPlayState()}syncVar(e){let t=this.getAttribute(e.attribute),n=e.parser(t),r=e.fallback?e.fallback(this):null;if(n==null){r==null?this.style.removeProperty(e.cssVar):this.style.setProperty(e.cssVar,r);return}this.style.setProperty(e.cssVar,n)}reset(){let e=this.getHostSize(),t=this.getTrackSize();this.syncAnimation(e,t)}getHostSize(){return this.isVerticalDirection?this.clientHeight:this.clientWidth}getTrackSize(){return this.isVerticalDirection?this.track.offsetHeight:this.track.offsetWidth}getStartPosition(e,t){return this.directionSign<0?e:-t}getFlushEndPosition(e,t){return this.directionSign<0?0:e-t}getOffEndPosition(e,t){return this.directionSign<0?-t:e}getSlideEndPosition(e,t){return this.directionSign<0?0:e-t}getAlternateStartPosition(e,t){return this.directionSign<0?e-t:0}syncAnimationPlayState(){this.style.setProperty(y,this.running?`running`:`paused`)}syncAnimation(e,t){let n=this.behavior===`alternate`?this.getAlternateStartPosition(e,t):this.getStartPosition(e,t),r=this.behavior===`slide`?this.getSlideEndPosition(e,t):this.behavior===`alternate`?this.getFlushEndPosition(e,t):this.getOffEndPosition(e,t),i=Math.abs(r-n),a=Math.max(1,Math.ceil(i/Math.max(1,this.scrollAmount))),o=Math.max(1,a*this.scrollDelay),s=this.getCssIterationCount();this.track.style.removeProperty(`transform`),this.style.setProperty(g,`${o}ms`),this.style.setProperty(_,this.behavior===`alternate`?`alternate`:`normal`),this.style.setProperty(v,s),this.style.setProperty(b,`steps(${a}, end)`),this.isVerticalDirection?(this.style.setProperty(S,`0px`),this.style.setProperty(x,`0px`),this.style.setProperty(w,`${n}px`),this.style.setProperty(C,`${r}px`)):(this.style.setProperty(S,`${n}px`),this.style.setProperty(x,`${r}px`),this.style.setProperty(w,`0px`),this.style.setProperty(C,`0px`)),this.restartAnimation()}getCssIterationCount(){return this.behavior===`slide`&&!this.hasAttribute(a)?`1`:this.hasAttribute(a)&&Number.isFinite(this.loop)&&this.loop>0?String(this.loop):`infinite`}handleAnimationEnd(){this.hasFiniteAnimation()&&(this.running=!1,this.syncAnimationPlayState())}restartAnimation(){this.track.style.animationName=`none`,this.track.offsetWidth,this.track.style.removeProperty(`animation-name`)}hasFiniteAnimation(){return this.behavior===`slide`&&!this.hasAttribute(a)?!0:this.hasAttribute(a)&&Number.isFinite(this.loop)&&this.loop>0}},k=class extends O{},A=class extends O{};typeof customElements>`u`||(customElements.get(`re-marquee`)||customElements.define(`re-marquee`,k),customElements.get(`re-marquee-ble`)||customElements.define(`re-marquee-ble`,A))})();