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 +96 -8
- package/dist/auto.d.ts +1 -1
- package/dist/lite.css +73 -0
- package/dist/remarqueeble-auto.cjs +84 -83
- package/dist/remarqueeble-auto.min.js +52 -0
- package/dist/remarqueeble-auto.mjs +84 -82
- package/dist/remarqueeble.cjs +84 -81
- package/dist/remarqueeble.d.ts +6 -10
- package/dist/remarqueeble.mjs +84 -81
- package/package.json +19 -9
- package/dist/remarqueeble.umd.js +0 -29
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
43
|
+
Mirrors:
|
|
36
44
|
|
|
37
|
-
|
|
45
|
+
- https://unpkg.com/remarqueeble
|
|
46
|
+
- https://cdn.jsdelivr.net/npm/remarqueeble
|
|
38
47
|
|
|
39
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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 {
|
|
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
|
-
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.
|
|
181
|
-
this.
|
|
201
|
+
this.reset();
|
|
202
|
+
this.syncAnimationPlayState();
|
|
182
203
|
}
|
|
183
204
|
stop() {
|
|
184
205
|
this.running = false;
|
|
185
|
-
|
|
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.
|
|
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
|
-
|
|
234
|
-
|
|
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
|
-
|
|
244
|
-
const
|
|
245
|
-
const
|
|
246
|
-
const
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
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.
|
|
275
|
+
this.restartAnimation();
|
|
286
276
|
}
|
|
287
|
-
|
|
288
|
-
this.
|
|
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
|
-
|
|
291
|
-
|
|
288
|
+
restartAnimation() {
|
|
289
|
+
this.track.style.animationName = "none";
|
|
290
|
+
this.track.offsetWidth;
|
|
291
|
+
this.track.style.removeProperty("animation-name");
|
|
292
292
|
}
|
|
293
|
-
|
|
294
|
-
if (this.
|
|
295
|
-
|
|
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",
|
|
301
|
-
if (!customElements.get("re-marquee-ble")) customElements.define("re-marquee-ble",
|
|
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))})();
|