@profpowell/blink-wc 0.0.0-stage → 1.5.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/LICENSE +21 -0
- package/README.md +314 -2
- package/blink-wc.d.ts +113 -0
- package/custom-elements.json +278 -0
- package/dist/blink-wc.css +741 -0
- package/dist/blink-wc.js +411 -0
- package/dist/blink-wc.js.map +1 -0
- package/package.json +61 -4
package/dist/blink-wc.js
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
const M = [
|
|
2
|
+
"wave",
|
|
3
|
+
"twinkle",
|
|
4
|
+
"sparkle",
|
|
5
|
+
"rainbow",
|
|
6
|
+
"chase",
|
|
7
|
+
"glitch",
|
|
8
|
+
"cascade",
|
|
9
|
+
"typewriter",
|
|
10
|
+
"zoom",
|
|
11
|
+
"flip3d",
|
|
12
|
+
"swing",
|
|
13
|
+
"shake",
|
|
14
|
+
"heartbeat",
|
|
15
|
+
"decode"
|
|
16
|
+
], w = ["extrude", "collapse", "outline", "morph", "depth", "revolve"], C = { morph: 4, revolve: 4 }, E = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&*+=?<>/~^|", S = {
|
|
17
|
+
a: ".-",
|
|
18
|
+
b: "-...",
|
|
19
|
+
c: "-.-.",
|
|
20
|
+
d: "-..",
|
|
21
|
+
e: ".",
|
|
22
|
+
f: "..-.",
|
|
23
|
+
g: "--.",
|
|
24
|
+
h: "....",
|
|
25
|
+
i: "..",
|
|
26
|
+
j: ".---",
|
|
27
|
+
k: "-.-",
|
|
28
|
+
l: ".-..",
|
|
29
|
+
m: "--",
|
|
30
|
+
n: "-.",
|
|
31
|
+
o: "---",
|
|
32
|
+
p: ".--.",
|
|
33
|
+
q: "--.-",
|
|
34
|
+
r: ".-.",
|
|
35
|
+
s: "...",
|
|
36
|
+
t: "-",
|
|
37
|
+
u: "..-",
|
|
38
|
+
v: "...-",
|
|
39
|
+
w: ".--",
|
|
40
|
+
x: "-..-",
|
|
41
|
+
y: "-.--",
|
|
42
|
+
z: "--..",
|
|
43
|
+
0: "-----",
|
|
44
|
+
1: ".----",
|
|
45
|
+
2: "..---",
|
|
46
|
+
3: "...--",
|
|
47
|
+
4: "....-",
|
|
48
|
+
5: ".....",
|
|
49
|
+
6: "-....",
|
|
50
|
+
7: "--...",
|
|
51
|
+
8: "---..",
|
|
52
|
+
9: "----.",
|
|
53
|
+
".": ".-.-.-",
|
|
54
|
+
",": "--..--",
|
|
55
|
+
"?": "..--..",
|
|
56
|
+
"'": ".----.",
|
|
57
|
+
"!": "-.-.--",
|
|
58
|
+
"/": "-..-.",
|
|
59
|
+
"(": "-.--.",
|
|
60
|
+
")": "-.--.-",
|
|
61
|
+
"&": ".-...",
|
|
62
|
+
":": "---...",
|
|
63
|
+
"=": "-...-",
|
|
64
|
+
"+": ".-.-.",
|
|
65
|
+
"-": "-....-",
|
|
66
|
+
"@": ".--.-."
|
|
67
|
+
}, F = matchMedia("(prefers-reduced-motion: reduce)"), v = /* @__PURE__ */ new Set();
|
|
68
|
+
let y = null;
|
|
69
|
+
const T = () => F.matches || document.documentElement.hasAttribute("data-motion-reduced"), k = () => v.forEach((g) => g._update());
|
|
70
|
+
function x(g) {
|
|
71
|
+
v.add(g), !y && (F.addEventListener("change", k), y = new MutationObserver(k), y.observe(document.documentElement, {
|
|
72
|
+
attributes: !0,
|
|
73
|
+
attributeFilter: ["data-motion-reduced"]
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
function L(g) {
|
|
77
|
+
v.delete(g), !(v.size || !y) && (F.removeEventListener("change", k), y.disconnect(), y = null);
|
|
78
|
+
}
|
|
79
|
+
class R extends HTMLElement {
|
|
80
|
+
static get observedAttributes() {
|
|
81
|
+
return [
|
|
82
|
+
"rate",
|
|
83
|
+
"behavior",
|
|
84
|
+
"min-opacity",
|
|
85
|
+
"count",
|
|
86
|
+
"steps",
|
|
87
|
+
"step-durations",
|
|
88
|
+
"step-by",
|
|
89
|
+
"play-state",
|
|
90
|
+
"pause-on-hover",
|
|
91
|
+
"reduced-motion",
|
|
92
|
+
"mode",
|
|
93
|
+
"unit"
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
// ── Functional core: pure getters ──────────────────────────────────────
|
|
97
|
+
get rate() {
|
|
98
|
+
return this.getAttribute("rate") || "1s";
|
|
99
|
+
}
|
|
100
|
+
get behavior() {
|
|
101
|
+
const t = this.getAttribute("behavior");
|
|
102
|
+
return ["pulse", "flicker", "steps"].includes(t) ? t : "blink";
|
|
103
|
+
}
|
|
104
|
+
get minOpacity() {
|
|
105
|
+
const t = this.getAttribute("min-opacity");
|
|
106
|
+
return t == null || t === "" ? null : t;
|
|
107
|
+
}
|
|
108
|
+
get count() {
|
|
109
|
+
return this.getAttribute("count") || "infinite";
|
|
110
|
+
}
|
|
111
|
+
get steps() {
|
|
112
|
+
const t = parseInt(this.getAttribute("steps"), 10);
|
|
113
|
+
return Number.isFinite(t) && t >= 2 ? t : C[this.mode] || 2;
|
|
114
|
+
}
|
|
115
|
+
get stepDurations() {
|
|
116
|
+
return this.getAttribute("step-durations") || null;
|
|
117
|
+
}
|
|
118
|
+
get stepBy() {
|
|
119
|
+
const t = this.getAttribute("step-by");
|
|
120
|
+
return t === "letter" || t === "word" ? t : "element";
|
|
121
|
+
}
|
|
122
|
+
get playState() {
|
|
123
|
+
return this.getAttribute("play-state") || "running";
|
|
124
|
+
}
|
|
125
|
+
get mode() {
|
|
126
|
+
return this.getAttribute("mode") || "";
|
|
127
|
+
}
|
|
128
|
+
get unit() {
|
|
129
|
+
return this.getAttribute("unit") === "word" ? "word" : "letter";
|
|
130
|
+
}
|
|
131
|
+
// ── Imperative shell ───────────────────────────────────────────────────
|
|
132
|
+
connectedCallback() {
|
|
133
|
+
if (x(this), this._built) {
|
|
134
|
+
this._observe(), this._update();
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
this._build(), this._observe(), this._update(), this._built = !0, this._dispatch("blink-start");
|
|
138
|
+
}
|
|
139
|
+
disconnectedCallback() {
|
|
140
|
+
var t, e;
|
|
141
|
+
L(this), (t = this._intersectionObserver) == null || t.disconnect(), (e = this._content) == null || e.removeEventListener("animationiteration", this._onIteration), document.removeEventListener("visibilitychange", this._onVisibility), this._stopMorse(), this._stopSteps(), this._stopDecode();
|
|
142
|
+
}
|
|
143
|
+
attributeChangedCallback(t, e, s) {
|
|
144
|
+
e === s || !this._built || ((t === "mode" || t === "unit" || t === "step-by" || t === "behavior") && this._renderContent(), this._update(), t === "play-state" && this._dispatch(s === "paused" ? "blink-pause" : "blink-start"));
|
|
145
|
+
}
|
|
146
|
+
// ── Public API (legacy <blink> compat) ──────────────────────────────────
|
|
147
|
+
start() {
|
|
148
|
+
this.setAttribute("play-state", "running");
|
|
149
|
+
}
|
|
150
|
+
stop() {
|
|
151
|
+
this.setAttribute("play-state", "paused");
|
|
152
|
+
}
|
|
153
|
+
toggle() {
|
|
154
|
+
this.playState === "paused" ? this.start() : this.stop();
|
|
155
|
+
}
|
|
156
|
+
refresh() {
|
|
157
|
+
this._renderContent(), this._update();
|
|
158
|
+
}
|
|
159
|
+
// ── Private ────────────────────────────────────────────────────────────
|
|
160
|
+
_build() {
|
|
161
|
+
const t = [...this.childNodes];
|
|
162
|
+
this.textContent = "";
|
|
163
|
+
const e = document.createElement("span");
|
|
164
|
+
e.className = "blink-content", t.forEach((s) => e.appendChild(s)), this.appendChild(e), this._content = e, this._sourceHTML = e.innerHTML, this._renderContent();
|
|
165
|
+
}
|
|
166
|
+
// Restore authored markup, then split into units if the mode needs it. Per-unit
|
|
167
|
+
// motion modes split by `unit`; per-unit step sequences split by `step-by`.
|
|
168
|
+
_renderContent() {
|
|
169
|
+
if (this._sourceHTML == null) return;
|
|
170
|
+
this._content.innerHTML = this._sourceHTML;
|
|
171
|
+
const t = this._usesSteps() && this.stepBy !== "element";
|
|
172
|
+
if (M.includes(this.mode) || t) {
|
|
173
|
+
const e = t ? this.stepBy === "word" : this.unit === "word";
|
|
174
|
+
this._splitLetters(e), this.dataset.split = "";
|
|
175
|
+
} else
|
|
176
|
+
delete this.dataset.split;
|
|
177
|
+
}
|
|
178
|
+
// Wrap each unit in a <span class="blink-char"> with a stagger index, so CSS
|
|
179
|
+
// can animate units individually (wave, twinkle, …) and the step engine can
|
|
180
|
+
// advance each unit's data-step on its own staggered clock.
|
|
181
|
+
_splitLetters(t = this.unit === "word") {
|
|
182
|
+
const e = document.createTreeWalker(this._content, NodeFilter.SHOW_TEXT), s = [];
|
|
183
|
+
for (; e.nextNode(); ) s.push(e.currentNode);
|
|
184
|
+
const r = this.mode === "twinkle" || this.mode === "sparkle", u = this.mode === "decode", d = (o) => o.trim() === "";
|
|
185
|
+
let p = 0;
|
|
186
|
+
for (const o of s) {
|
|
187
|
+
const _ = document.createDocumentFragment(), h = t ? this._tokenizeWords(o.textContent) : [...o.textContent];
|
|
188
|
+
for (const a of h) {
|
|
189
|
+
if (a === "") continue;
|
|
190
|
+
const m = d(a), c = document.createElement("span");
|
|
191
|
+
c.className = "blink-char", c.style.setProperty("--i", p++), r && (c.style.setProperty("--rate", `${(0.4 + Math.random() * 1.6).toFixed(2)}s`), c.style.setProperty("--delay", `${Math.random().toFixed(2)}s`)), m ? (c.classList.add("blink-space"), c.textContent = " ") : (c.textContent = a, u && (c.dataset.ch = a)), _.appendChild(c);
|
|
192
|
+
}
|
|
193
|
+
o.replaceWith(_);
|
|
194
|
+
}
|
|
195
|
+
this._content.style.setProperty("--n", p);
|
|
196
|
+
}
|
|
197
|
+
// Split text into word and whitespace-run tokens (no regex escapes needed).
|
|
198
|
+
_tokenizeWords(t) {
|
|
199
|
+
const e = [];
|
|
200
|
+
let s = "", r = null;
|
|
201
|
+
for (const u of t) {
|
|
202
|
+
const d = u.trim() === "";
|
|
203
|
+
s !== "" && d !== r && (e.push(s), s = ""), s += u, r = d;
|
|
204
|
+
}
|
|
205
|
+
return s !== "" && e.push(s), e;
|
|
206
|
+
}
|
|
207
|
+
// Whether motion should be suppressed: OS preference or VB's data-motion-reduced,
|
|
208
|
+
// unless this instance opts out with reduced-motion="ignore".
|
|
209
|
+
_reduceMotion() {
|
|
210
|
+
return this.getAttribute("reduced-motion") !== "ignore" && T();
|
|
211
|
+
}
|
|
212
|
+
// Whether playback is currently paused (state, off-screen, tab-hidden, or hover).
|
|
213
|
+
_isPaused() {
|
|
214
|
+
return this.hasAttribute("pause-on-hover") && this.matches(":hover, :focus-within") ? !0 : this.playState === "paused" || this.dataset.visible === "false" || this.dataset.tabVisible === "false";
|
|
215
|
+
}
|
|
216
|
+
_stopMorse() {
|
|
217
|
+
this._morseRAF && cancelAnimationFrame(this._morseRAF), this._morseRAF = null;
|
|
218
|
+
}
|
|
219
|
+
// morse mode: blink the text out as Morse code. CSS keys off data-lit to light
|
|
220
|
+
// the text; we also expose the dot/dash string via data-morse for a caption.
|
|
221
|
+
_syncMorse() {
|
|
222
|
+
var h;
|
|
223
|
+
if (this._stopMorse(), this.mode !== "morse") {
|
|
224
|
+
delete this.dataset.lit, delete this.dataset.morse;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const t = (((h = this._content) == null ? void 0 : h.textContent) || "").trim();
|
|
228
|
+
if (this.dataset.morse = this._toMorse(t), this._reduceMotion()) {
|
|
229
|
+
this.dataset.lit = "true";
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const s = this._morseSegments(t);
|
|
233
|
+
if (s.length === 0) {
|
|
234
|
+
this.dataset.lit = "true";
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const r = parseFloat(getComputedStyle(this).getPropertyValue("--blink-dot")), u = Number.isFinite(r) && r > 0 ? r : 170, d = s.reduce((a, m) => a + m.dur, 0) + 7;
|
|
238
|
+
let p = 0, o = null;
|
|
239
|
+
const _ = (a) => {
|
|
240
|
+
this._morseRAF = requestAnimationFrame(_), o == null && (o = a);
|
|
241
|
+
const m = a - o;
|
|
242
|
+
if (o = a, this._isPaused()) return;
|
|
243
|
+
p += m;
|
|
244
|
+
const c = p / u % d;
|
|
245
|
+
let n = 0, f = !1;
|
|
246
|
+
for (const l of s) {
|
|
247
|
+
if (c < n + l.dur) {
|
|
248
|
+
f = l.lit;
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
n += l.dur;
|
|
252
|
+
}
|
|
253
|
+
const i = f ? "true" : "false";
|
|
254
|
+
this.dataset.lit !== i && (this.dataset.lit = i);
|
|
255
|
+
};
|
|
256
|
+
this.dataset.lit = "false", this._morseRAF = requestAnimationFrame(_);
|
|
257
|
+
}
|
|
258
|
+
// Build an on/off timeline (durations in Morse "units") for a string.
|
|
259
|
+
_morseSegments(t) {
|
|
260
|
+
const e = [], s = t.toLowerCase().split(/\s+/).filter(Boolean);
|
|
261
|
+
return s.forEach((r, u) => {
|
|
262
|
+
const d = [...r].filter((p) => S[p]);
|
|
263
|
+
d.forEach((p, o) => {
|
|
264
|
+
const _ = S[p];
|
|
265
|
+
[..._].forEach((h, a) => {
|
|
266
|
+
e.push({ lit: !0, dur: h === "-" ? 3 : 1 }), a < _.length - 1 && e.push({ lit: !1, dur: 1 });
|
|
267
|
+
}), o < d.length - 1 && e.push({ lit: !1, dur: 3 });
|
|
268
|
+
}), u < s.length - 1 && e.push({ lit: !1, dur: 7 });
|
|
269
|
+
}), e;
|
|
270
|
+
}
|
|
271
|
+
// Human-readable dot/dash string, words separated by " / ".
|
|
272
|
+
_toMorse(t) {
|
|
273
|
+
return t.toLowerCase().split(/\s+/).filter(Boolean).map(
|
|
274
|
+
(e) => [...e].map((s) => S[s] || "").filter(Boolean).join(" ")
|
|
275
|
+
).filter(Boolean).join(" / ");
|
|
276
|
+
}
|
|
277
|
+
_observe() {
|
|
278
|
+
this._intersectionObserver = new IntersectionObserver(
|
|
279
|
+
(t) => t.forEach((e) => {
|
|
280
|
+
this.dataset.visible = String(e.isIntersecting);
|
|
281
|
+
}),
|
|
282
|
+
{ rootMargin: "100px" }
|
|
283
|
+
), this._intersectionObserver.observe(this), this._onVisibility = () => {
|
|
284
|
+
this.dataset.tabVisible = String(!document.hidden);
|
|
285
|
+
}, document.addEventListener("visibilitychange", this._onVisibility), this.dataset.tabVisible = String(!document.hidden), this._onIteration = () => this._dispatch("blink-cycle"), this._content.addEventListener("animationiteration", this._onIteration);
|
|
286
|
+
}
|
|
287
|
+
_update() {
|
|
288
|
+
!this._built && !this._content || (this.dataset.behavior = this.behavior, this.dataset.state = this.playState, this.dataset.ready = "", this.style.setProperty("--blink-rate", this.rate), this.minOpacity != null ? this.style.setProperty("--blink-min-opacity", this.minOpacity) : this.style.removeProperty("--blink-min-opacity"), this.count !== "infinite" ? this.style.setProperty("--blink-count", this.count) : this.style.removeProperty("--blink-count"), this._syncMorse(), this._syncSteps(), this._syncDecode());
|
|
289
|
+
}
|
|
290
|
+
_stopDecode() {
|
|
291
|
+
this._decodeRAF && cancelAnimationFrame(this._decodeRAF), this._decodeRAF = null;
|
|
292
|
+
}
|
|
293
|
+
// decode mode: each unit flickers through random glyphs, then locks onto its
|
|
294
|
+
// real character (stored in data-ch), staggered left-to-right, then
|
|
295
|
+
// re-scrambles on a loop. Monospace keeps the width stable as glyphs change.
|
|
296
|
+
// Freezes when paused; shows the plain text under reduced motion.
|
|
297
|
+
_syncDecode() {
|
|
298
|
+
if (this._stopDecode(), this.mode !== "decode") return;
|
|
299
|
+
const t = [...this.querySelectorAll(".blink-char")].filter(
|
|
300
|
+
(n) => !n.classList.contains("blink-space") && n.dataset.ch != null
|
|
301
|
+
);
|
|
302
|
+
if (t.length === 0) return;
|
|
303
|
+
if (this._reduceMotion()) {
|
|
304
|
+
for (const n of t) n.textContent = n.dataset.ch;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
const s = () => E[Math.random() * E.length | 0], r = 650, u = 45, d = 1800, p = 55;
|
|
308
|
+
let o = 0;
|
|
309
|
+
const _ = t.map((n) => {
|
|
310
|
+
const f = Number(n.style.getPropertyValue("--i")) || 0, i = r + f * u;
|
|
311
|
+
return i > o && (o = i), { s: n, settleAt: i, target: n.dataset.ch };
|
|
312
|
+
});
|
|
313
|
+
let h = 0, a = null, m = 0;
|
|
314
|
+
const c = (n) => {
|
|
315
|
+
this._decodeRAF = requestAnimationFrame(c), a == null && (a = n);
|
|
316
|
+
const f = n - a;
|
|
317
|
+
if (a = n, this._isPaused()) return;
|
|
318
|
+
h += f;
|
|
319
|
+
const i = h - m >= p;
|
|
320
|
+
i && (m = h);
|
|
321
|
+
for (const l of _)
|
|
322
|
+
h >= l.settleAt ? l.s.textContent !== l.target && (l.s.textContent = l.target) : i && (l.s.textContent = s());
|
|
323
|
+
h > o + d && (h = 0, m = 0);
|
|
324
|
+
};
|
|
325
|
+
this._decodeRAF = requestAnimationFrame(c);
|
|
326
|
+
}
|
|
327
|
+
// Whether the multi-step engine should drive this element.
|
|
328
|
+
_usesSteps() {
|
|
329
|
+
return this.behavior === "steps" || w.includes(this.mode);
|
|
330
|
+
}
|
|
331
|
+
// Parse a CSS time (e.g. "1s", "800ms", or a bare number of seconds) to ms.
|
|
332
|
+
_parseTime(t) {
|
|
333
|
+
const e = String(t).trim();
|
|
334
|
+
let s;
|
|
335
|
+
return e.endsWith("ms") ? s = parseFloat(e) : (e.endsWith("s"), s = parseFloat(e) * 1e3), Number.isFinite(s) && s > 0 ? s : 1e3;
|
|
336
|
+
}
|
|
337
|
+
_stopSteps() {
|
|
338
|
+
this._stepRAF && cancelAnimationFrame(this._stepRAF), this._stepRAF = null;
|
|
339
|
+
}
|
|
340
|
+
// Parse `step-durations` into per-step weights, one per step. Accepts a
|
|
341
|
+
// space- or comma-separated list (e.g. "3 1 1" or "2,1"); the list is cycled
|
|
342
|
+
// or truncated to fit the step count. Absent/invalid → equal weights.
|
|
343
|
+
_stepWeights(t) {
|
|
344
|
+
const e = this.stepDurations;
|
|
345
|
+
if (!e) return Array(t).fill(1);
|
|
346
|
+
const s = e.split(/[\s,]+/).map(Number).filter((r) => Number.isFinite(r) && r > 0);
|
|
347
|
+
return s.length === 0 ? Array(t).fill(1) : Array.from({ length: t }, (r, u) => s[u % s.length]);
|
|
348
|
+
}
|
|
349
|
+
// The element(s) that carry data-step: the whole content for step-by="element",
|
|
350
|
+
// or each unit span for step-by="letter"/"word".
|
|
351
|
+
_stepTargets() {
|
|
352
|
+
return this.stepBy !== "element" && this.dataset.split != null ? [...this.querySelectorAll(".blink-char")] : this._content ? [this._content] : [];
|
|
353
|
+
}
|
|
354
|
+
// Clear any data-step left on the content or unit spans (when stepping stops).
|
|
355
|
+
_clearStepTargets() {
|
|
356
|
+
var t;
|
|
357
|
+
(t = this._content) == null || delete t.dataset.step, this.querySelectorAll(".blink-char[data-step]").forEach((e) => delete e.dataset.step);
|
|
358
|
+
}
|
|
359
|
+
// Multi-step engine: advance data-step="0..N-1" across one cycle (`rate`). Each
|
|
360
|
+
// step holds for a slice of the cycle — equal by default, or weighted by
|
|
361
|
+
// `step-durations`. CSS styles each step (colour, transform, outline, …) and
|
|
362
|
+
// can give each step its own transition timing (--blink-step-ease /
|
|
363
|
+
// --blink-step-timing); a plain blink is the 2-step case. With step-by="letter"
|
|
364
|
+
// (or "word") every unit runs the sequence offset by its index, so the states
|
|
365
|
+
// ripple across the text. Freezes when paused/off-screen/tab-hidden; rests at
|
|
366
|
+
// step 0 under reduced motion.
|
|
367
|
+
_syncSteps() {
|
|
368
|
+
if (this._stopSteps(), !this._usesSteps()) {
|
|
369
|
+
delete this.dataset.stepping, this._clearStepTargets();
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
this.dataset.stepping = "";
|
|
373
|
+
const t = this.steps, e = this._stepTargets();
|
|
374
|
+
if (e.length === 0) return;
|
|
375
|
+
if (this._reduceMotion()) {
|
|
376
|
+
for (const i of e) i.dataset.step = "0";
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
const r = this._stepWeights(t), u = r.reduce((i, l) => i + l, 0), d = this._parseTime(this.rate), p = [];
|
|
380
|
+
let o = 0;
|
|
381
|
+
for (const i of r)
|
|
382
|
+
o += i, p.push(o / u * d);
|
|
383
|
+
const h = e.length > 1 ? (parseFloat(getComputedStyle(this).getPropertyValue("--blink-stagger")) || 0.08) * 1e3 : 0, a = (i) => {
|
|
384
|
+
let l = 0;
|
|
385
|
+
for (; l < t - 1 && i >= p[l]; ) l++;
|
|
386
|
+
return l;
|
|
387
|
+
}, m = new Array(e.length).fill(0);
|
|
388
|
+
e.forEach((i) => i.dataset.step = "0");
|
|
389
|
+
let c = 0, n = null;
|
|
390
|
+
const f = (i) => {
|
|
391
|
+
this._stepRAF = requestAnimationFrame(f), n == null && (n = i);
|
|
392
|
+
const l = i - n;
|
|
393
|
+
if (n = i, !this._isPaused()) {
|
|
394
|
+
c += l;
|
|
395
|
+
for (let b = 0; b < e.length; b++) {
|
|
396
|
+
const A = a((c + b * h) % d);
|
|
397
|
+
A !== m[b] && (e[b].dataset.step = String(A), b === 0 && A < m[b] && this._dispatch("blink-cycle"), m[b] = A);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
this._stepRAF = requestAnimationFrame(f);
|
|
402
|
+
}
|
|
403
|
+
_dispatch(t) {
|
|
404
|
+
this.dispatchEvent(new CustomEvent(t, { bubbles: !0 }));
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
customElements.define("blink-wc", R);
|
|
408
|
+
export {
|
|
409
|
+
R as BlinkWc
|
|
410
|
+
};
|
|
411
|
+
//# sourceMappingURL=blink-wc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blink-wc.js","sources":["../src/blink-wc.js"],"sourcesContent":["/**\n * @class BlinkWc\n * @extends HTMLElement\n * @description Vanilla Breeze blink component. The deprecated <blink> element,\n * reborn for 2026 — light DOM, CSS-driven, themeable, accessible, and it\n * pauses when offscreen or tab-hidden. Blinking content is a real\n * accessibility hazard, so it stops entirely under prefers-reduced-motion\n * (unless you explicitly opt out) and is always pausable.\n *\n * @attr rate - CSS time for one blink cycle (default: 1s)\n * @attr behavior - blink | pulse | flicker (default: blink)\n * @attr min-opacity - opacity of the \"off\" phase, 0–1 (default per behavior)\n * @attr count - number of blinks, then stop, or `infinite` (default: infinite)\n * @attr pause-on-hover - boolean; also pauses on focus-within\n * @attr play-state - running | paused\n * @attr reduced-motion - respect | ignore (default: respect)\n * @attr mode - visual/motion preset. Surface themes: neon | crt | terminal |\n * warning | alert | police | vegas. Per-unit motion: wave | twinkle |\n * sparkle | rainbow | chase | glitch | cascade | typewriter. Special: morse.\n * @attr unit - letter | word (default: letter) — granularity for the motion modes\n *\n * @fires blink-start\n * @fires blink-pause\n * @fires blink-cycle - fires on each blink iteration\n */\n\n// Modes that split text into per-unit spans for letter/word-level effects.\nconst LETTER_MODES = [\n 'wave',\n 'twinkle',\n 'sparkle',\n 'rainbow',\n 'chase',\n 'glitch',\n 'cascade',\n 'typewriter',\n 'zoom',\n 'flip3d',\n 'swing',\n 'shake',\n 'heartbeat',\n 'decode',\n];\n\n// Modes driven by the multi-step engine: JS advances data-step=\"0..N-1\" across\n// the cycle and CSS styles each step. A plain blink is just the 2-step case.\nconst STEP_MODES = ['extrude', 'collapse', 'outline', 'morph', 'depth', 'revolve'];\n\n// Default step count per step-mode (overridable with the `steps` attribute).\nconst STEP_COUNTS = { morph: 4, revolve: 4 };\n\n// Glyphs the `decode` scramble cycles through before locking onto the text.\nconst DECODE_GLYPHS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&*+=?<>/~^|';\n\n// International Morse code, plus digits and a little punctuation.\nconst MORSE = {\n a: '.-',\n b: '-...',\n c: '-.-.',\n d: '-..',\n e: '.',\n f: '..-.',\n g: '--.',\n h: '....',\n i: '..',\n j: '.---',\n k: '-.-',\n l: '.-..',\n m: '--',\n n: '-.',\n o: '---',\n p: '.--.',\n q: '--.-',\n r: '.-.',\n s: '...',\n t: '-',\n u: '..-',\n v: '...-',\n w: '.--',\n x: '-..-',\n y: '-.--',\n z: '--..',\n 0: '-----',\n 1: '.----',\n 2: '..---',\n 3: '...--',\n 4: '....-',\n 5: '.....',\n 6: '-....',\n 7: '--...',\n 8: '---..',\n 9: '----.',\n '.': '.-.-.-',\n ',': '--..--',\n '?': '..--..',\n \"'\": '.----.',\n '!': '-.-.--',\n '/': '-..-.',\n '(': '-.--.',\n ')': '-.--.-',\n '&': '.-...',\n ':': '---...',\n '=': '-...-',\n '+': '.-.-.',\n '-': '-....-',\n '@': '.--.-.',\n};\n\n// ── Reduced-motion watcher (shared by every instance) ──────────────────────\n// Motion is reduced when the OS asks for it OR when Vanilla Breeze's theme\n// picker has turned \"Motion Effects\" off, which sets :root[data-motion-reduced].\n// One media-query listener and one MutationObserver serve all instances, and\n// re-sync the JS-driven modes (morse, steps, decode) when either flips.\nconst REDUCED_MQ = matchMedia('(prefers-reduced-motion: reduce)');\nconst INSTANCES = new Set();\nlet rootObserver = null;\n\nconst systemReducesMotion = () =>\n REDUCED_MQ.matches || document.documentElement.hasAttribute('data-motion-reduced');\n\nconst resyncAll = () => INSTANCES.forEach((el) => el._update());\n\nfunction watchMotion(el) {\n INSTANCES.add(el);\n if (rootObserver) return;\n REDUCED_MQ.addEventListener('change', resyncAll);\n rootObserver = new MutationObserver(resyncAll);\n rootObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['data-motion-reduced'],\n });\n}\n\nfunction unwatchMotion(el) {\n INSTANCES.delete(el);\n if (INSTANCES.size || !rootObserver) return;\n REDUCED_MQ.removeEventListener('change', resyncAll);\n rootObserver.disconnect();\n rootObserver = null;\n}\n\nclass BlinkWc extends HTMLElement {\n static get observedAttributes() {\n return [\n 'rate',\n 'behavior',\n 'min-opacity',\n 'count',\n 'steps',\n 'step-durations',\n 'step-by',\n 'play-state',\n 'pause-on-hover',\n 'reduced-motion',\n 'mode',\n 'unit',\n ];\n }\n\n // ── Functional core: pure getters ──────────────────────────────────────\n get rate() {\n return this.getAttribute('rate') || '1s';\n }\n get behavior() {\n const b = this.getAttribute('behavior');\n return ['pulse', 'flicker', 'steps'].includes(b) ? b : 'blink';\n }\n get minOpacity() {\n const v = this.getAttribute('min-opacity');\n return v == null || v === '' ? null : v;\n }\n get count() {\n return this.getAttribute('count') || 'infinite';\n }\n get steps() {\n const v = parseInt(this.getAttribute('steps'), 10);\n if (Number.isFinite(v) && v >= 2) return v;\n return STEP_COUNTS[this.mode] || 2;\n }\n get stepDurations() {\n return this.getAttribute('step-durations') || null;\n }\n get stepBy() {\n const v = this.getAttribute('step-by');\n return v === 'letter' || v === 'word' ? v : 'element';\n }\n get playState() {\n return this.getAttribute('play-state') || 'running';\n }\n get mode() {\n return this.getAttribute('mode') || '';\n }\n get unit() {\n return this.getAttribute('unit') === 'word' ? 'word' : 'letter';\n }\n\n // ── Imperative shell ───────────────────────────────────────────────────\n connectedCallback() {\n watchMotion(this);\n if (this._built) {\n // Re-attached (e.g. moved in the DOM): disconnectedCallback tore down the\n // observers and stopped the JS drivers, so bring them back.\n this._observe();\n this._update();\n return;\n }\n this._build();\n this._observe();\n this._update();\n this._built = true;\n this._dispatch('blink-start');\n }\n\n disconnectedCallback() {\n unwatchMotion(this);\n this._intersectionObserver?.disconnect();\n this._content?.removeEventListener('animationiteration', this._onIteration);\n document.removeEventListener('visibilitychange', this._onVisibility);\n this._stopMorse();\n this._stopSteps();\n this._stopDecode();\n }\n\n attributeChangedCallback(name, oldValue, newValue) {\n if (oldValue === newValue || !this._built) return;\n if (name === 'mode' || name === 'unit' || name === 'step-by' || name === 'behavior') {\n this._renderContent();\n }\n this._update();\n if (name === 'play-state') {\n this._dispatch(newValue === 'paused' ? 'blink-pause' : 'blink-start');\n }\n }\n\n // ── Public API (legacy <blink> compat) ──────────────────────────────────\n start() {\n this.setAttribute('play-state', 'running');\n }\n stop() {\n this.setAttribute('play-state', 'paused');\n }\n toggle() {\n this.playState === 'paused' ? this.start() : this.stop();\n }\n refresh() {\n this._renderContent();\n this._update();\n }\n\n // ── Private ────────────────────────────────────────────────────────────\n _build() {\n const items = [...this.childNodes];\n this.textContent = '';\n\n const content = document.createElement('span');\n content.className = 'blink-content';\n items.forEach((n) => content.appendChild(n));\n this.appendChild(content);\n\n this._content = content;\n // Snapshot the authored markup so we can re-render when `mode` changes.\n this._sourceHTML = content.innerHTML;\n this._renderContent();\n }\n\n // Restore authored markup, then split into units if the mode needs it. Per-unit\n // motion modes split by `unit`; per-unit step sequences split by `step-by`.\n _renderContent() {\n if (this._sourceHTML == null) return;\n this._content.innerHTML = this._sourceHTML;\n const perUnitSteps = this._usesSteps() && this.stepBy !== 'element';\n if (LETTER_MODES.includes(this.mode) || perUnitSteps) {\n const byWord = perUnitSteps ? this.stepBy === 'word' : this.unit === 'word';\n this._splitLetters(byWord);\n this.dataset.split = '';\n } else {\n delete this.dataset.split;\n }\n }\n\n // Wrap each unit in a <span class=\"blink-char\"> with a stagger index, so CSS\n // can animate units individually (wave, twinkle, …) and the step engine can\n // advance each unit's data-step on its own staggered clock.\n _splitLetters(byWord = this.unit === 'word') {\n const walker = document.createTreeWalker(this._content, NodeFilter.SHOW_TEXT);\n const textNodes = [];\n while (walker.nextNode()) textNodes.push(walker.currentNode);\n\n // Per-unit randomized clocks: each unit blinks on its own timer.\n const twinkle = this.mode === 'twinkle' || this.mode === 'sparkle';\n const decode = this.mode === 'decode';\n const isWs = (c) => c.trim() === '';\n let i = 0;\n for (const node of textNodes) {\n const frag = document.createDocumentFragment();\n const tokens = byWord ? this._tokenizeWords(node.textContent) : [...node.textContent];\n for (const ch of tokens) {\n if (ch === '') continue;\n const space = isWs(ch);\n const span = document.createElement('span');\n span.className = 'blink-char';\n span.style.setProperty('--i', i++);\n if (twinkle) {\n span.style.setProperty('--rate', `${(0.4 + Math.random() * 1.6).toFixed(2)}s`);\n span.style.setProperty('--delay', `${Math.random().toFixed(2)}s`);\n }\n if (space) {\n span.classList.add('blink-space');\n span.textContent = ' ';\n } else {\n span.textContent = ch;\n // decode: remember the real glyph so the scramble loop can settle on it\n if (decode) span.dataset.ch = ch;\n }\n frag.appendChild(span);\n }\n node.replaceWith(frag);\n }\n this._content.style.setProperty('--n', i);\n }\n\n // Split text into word and whitespace-run tokens (no regex escapes needed).\n _tokenizeWords(text) {\n const tokens = [];\n let buf = '';\n let bufWs = null;\n for (const c of text) {\n const ws = c.trim() === '';\n if (buf !== '' && ws !== bufWs) {\n tokens.push(buf);\n buf = '';\n }\n buf += c;\n bufWs = ws;\n }\n if (buf !== '') tokens.push(buf);\n return tokens;\n }\n\n // Whether motion should be suppressed: OS preference or VB's data-motion-reduced,\n // unless this instance opts out with reduced-motion=\"ignore\".\n _reduceMotion() {\n return this.getAttribute('reduced-motion') !== 'ignore' && systemReducesMotion();\n }\n\n // Whether playback is currently paused (state, off-screen, tab-hidden, or hover).\n _isPaused() {\n if (this.hasAttribute('pause-on-hover') && this.matches(':hover, :focus-within')) return true;\n return (\n this.playState === 'paused' ||\n this.dataset.visible === 'false' ||\n this.dataset.tabVisible === 'false'\n );\n }\n\n _stopMorse() {\n if (this._morseRAF) cancelAnimationFrame(this._morseRAF);\n this._morseRAF = null;\n }\n\n // morse mode: blink the text out as Morse code. CSS keys off data-lit to light\n // the text; we also expose the dot/dash string via data-morse for a caption.\n _syncMorse() {\n this._stopMorse();\n if (this.mode !== 'morse') {\n delete this.dataset.lit;\n delete this.dataset.morse;\n return;\n }\n\n const text = (this._content?.textContent || '').trim();\n this.dataset.morse = this._toMorse(text);\n\n // Respect reduced motion: leave the text fully lit, no blinking.\n const reduce = this._reduceMotion();\n if (reduce) {\n this.dataset.lit = 'true';\n return;\n }\n\n const segments = this._morseSegments(text);\n if (segments.length === 0) {\n this.dataset.lit = 'true';\n return;\n }\n\n // Read the dot unit (ms) from a CSS var so it can be themed; default 170ms.\n const dotRaw = parseFloat(getComputedStyle(this).getPropertyValue('--blink-dot'));\n const DOT = Number.isFinite(dotRaw) && dotRaw > 0 ? dotRaw : 170;\n const totalUnits = segments.reduce((a, s) => a + s.dur, 0) + 7; // trailing word gap\n\n let elapsed = 0;\n let lastT = null;\n const tick = (t) => {\n this._morseRAF = requestAnimationFrame(tick);\n if (lastT == null) lastT = t;\n const dt = t - lastT;\n lastT = t;\n if (this._isPaused()) return; // freeze the timeline while paused\n elapsed += dt;\n const cycle = (elapsed / DOT) % totalUnits;\n let acc = 0;\n let lit = false;\n for (const s of segments) {\n if (cycle < acc + s.dur) {\n lit = s.lit;\n break;\n }\n acc += s.dur;\n }\n const next = lit ? 'true' : 'false';\n if (this.dataset.lit !== next) this.dataset.lit = next;\n };\n this.dataset.lit = 'false';\n this._morseRAF = requestAnimationFrame(tick);\n }\n\n // Build an on/off timeline (durations in Morse \"units\") for a string.\n _morseSegments(text) {\n const segments = [];\n const words = text.toLowerCase().split(/\\s+/).filter(Boolean);\n words.forEach((word, wi) => {\n const chars = [...word].filter((c) => MORSE[c]);\n chars.forEach((c, ci) => {\n const symbols = MORSE[c];\n [...symbols].forEach((sym, si) => {\n segments.push({ lit: true, dur: sym === '-' ? 3 : 1 });\n if (si < symbols.length - 1) segments.push({ lit: false, dur: 1 });\n });\n if (ci < chars.length - 1) segments.push({ lit: false, dur: 3 }); // inter-char gap\n });\n if (wi < words.length - 1) segments.push({ lit: false, dur: 7 }); // inter-word gap\n });\n return segments;\n }\n\n // Human-readable dot/dash string, words separated by \" / \".\n _toMorse(text) {\n return text\n .toLowerCase()\n .split(/\\s+/)\n .filter(Boolean)\n .map((word) =>\n [...word]\n .map((c) => MORSE[c] || '')\n .filter(Boolean)\n .join(' ')\n )\n .filter(Boolean)\n .join(' / ');\n }\n\n _observe() {\n this._intersectionObserver = new IntersectionObserver(\n (entries) =>\n entries.forEach((e) => {\n this.dataset.visible = String(e.isIntersecting);\n }),\n { rootMargin: '100px' }\n );\n this._intersectionObserver.observe(this);\n\n this._onVisibility = () => {\n this.dataset.tabVisible = String(!document.hidden);\n };\n document.addEventListener('visibilitychange', this._onVisibility);\n this.dataset.tabVisible = String(!document.hidden);\n\n this._onIteration = () => this._dispatch('blink-cycle');\n this._content.addEventListener('animationiteration', this._onIteration);\n }\n\n _update() {\n if (!this._built && !this._content) return;\n\n // Reflect state to data-* hooks the CSS keys off.\n this.dataset.behavior = this.behavior;\n this.dataset.state = this.playState;\n this.dataset.ready = '';\n\n this.style.setProperty('--blink-rate', this.rate);\n if (this.minOpacity != null) {\n this.style.setProperty('--blink-min-opacity', this.minOpacity);\n } else {\n this.style.removeProperty('--blink-min-opacity');\n }\n if (this.count !== 'infinite') {\n this.style.setProperty('--blink-count', this.count);\n } else {\n this.style.removeProperty('--blink-count');\n }\n\n this._syncMorse();\n this._syncSteps();\n this._syncDecode();\n }\n\n _stopDecode() {\n if (this._decodeRAF) cancelAnimationFrame(this._decodeRAF);\n this._decodeRAF = null;\n }\n\n // decode mode: each unit flickers through random glyphs, then locks onto its\n // real character (stored in data-ch), staggered left-to-right, then\n // re-scrambles on a loop. Monospace keeps the width stable as glyphs change.\n // Freezes when paused; shows the plain text under reduced motion.\n _syncDecode() {\n this._stopDecode();\n if (this.mode !== 'decode') return;\n\n const units = [...this.querySelectorAll('.blink-char')].filter(\n (s) => !s.classList.contains('blink-space') && s.dataset.ch != null\n );\n if (units.length === 0) return;\n\n const reduce = this._reduceMotion();\n if (reduce) {\n for (const s of units) s.textContent = s.dataset.ch;\n return;\n }\n\n const randGlyph = () => DECODE_GLYPHS[(Math.random() * DECODE_GLYPHS.length) | 0];\n\n const SCRAMBLE_MS = 650;\n const STAGGER_MS = 45;\n const HOLD_MS = 1800;\n const FLIP_MS = 55;\n let maxSettle = 0;\n const items = units.map((s) => {\n const i = Number(s.style.getPropertyValue('--i')) || 0;\n const settleAt = SCRAMBLE_MS + i * STAGGER_MS;\n if (settleAt > maxSettle) maxSettle = settleAt;\n return { s, settleAt, target: s.dataset.ch };\n });\n\n let elapsed = 0;\n let lastT = null;\n let lastFlip = 0;\n const tick = (t) => {\n this._decodeRAF = requestAnimationFrame(tick);\n if (lastT == null) lastT = t;\n const dt = t - lastT;\n lastT = t;\n if (this._isPaused()) return; // freeze the timeline while paused\n elapsed += dt;\n const flip = elapsed - lastFlip >= FLIP_MS;\n if (flip) lastFlip = elapsed;\n for (const it of items) {\n if (elapsed >= it.settleAt) {\n if (it.s.textContent !== it.target) it.s.textContent = it.target;\n } else if (flip) {\n it.s.textContent = randGlyph();\n }\n }\n if (elapsed > maxSettle + HOLD_MS) {\n elapsed = 0;\n lastFlip = 0;\n }\n };\n this._decodeRAF = requestAnimationFrame(tick);\n }\n\n // Whether the multi-step engine should drive this element.\n _usesSteps() {\n return this.behavior === 'steps' || STEP_MODES.includes(this.mode);\n }\n\n // Parse a CSS time (e.g. \"1s\", \"800ms\", or a bare number of seconds) to ms.\n _parseTime(value) {\n const t = String(value).trim();\n let ms;\n if (t.endsWith('ms')) ms = parseFloat(t);\n else if (t.endsWith('s')) ms = parseFloat(t) * 1000;\n else ms = parseFloat(t) * 1000;\n return Number.isFinite(ms) && ms > 0 ? ms : 1000;\n }\n\n _stopSteps() {\n if (this._stepRAF) cancelAnimationFrame(this._stepRAF);\n this._stepRAF = null;\n }\n\n // Parse `step-durations` into per-step weights, one per step. Accepts a\n // space- or comma-separated list (e.g. \"3 1 1\" or \"2,1\"); the list is cycled\n // or truncated to fit the step count. Absent/invalid → equal weights.\n _stepWeights(n) {\n const raw = this.stepDurations;\n if (!raw) return Array(n).fill(1);\n const parts = raw\n .split(/[\\s,]+/)\n .map(Number)\n .filter((v) => Number.isFinite(v) && v > 0);\n if (parts.length === 0) return Array(n).fill(1);\n return Array.from({ length: n }, (_, i) => parts[i % parts.length]);\n }\n\n // The element(s) that carry data-step: the whole content for step-by=\"element\",\n // or each unit span for step-by=\"letter\"/\"word\".\n _stepTargets() {\n if (this.stepBy !== 'element' && this.dataset.split != null) {\n return [...this.querySelectorAll('.blink-char')];\n }\n return this._content ? [this._content] : [];\n }\n\n // Clear any data-step left on the content or unit spans (when stepping stops).\n _clearStepTargets() {\n delete this._content?.dataset.step;\n this.querySelectorAll('.blink-char[data-step]').forEach((el) => delete el.dataset.step);\n }\n\n // Multi-step engine: advance data-step=\"0..N-1\" across one cycle (`rate`). Each\n // step holds for a slice of the cycle — equal by default, or weighted by\n // `step-durations`. CSS styles each step (colour, transform, outline, …) and\n // can give each step its own transition timing (--blink-step-ease /\n // --blink-step-timing); a plain blink is the 2-step case. With step-by=\"letter\"\n // (or \"word\") every unit runs the sequence offset by its index, so the states\n // ripple across the text. Freezes when paused/off-screen/tab-hidden; rests at\n // step 0 under reduced motion.\n _syncSteps() {\n this._stopSteps();\n if (!this._usesSteps()) {\n delete this.dataset.stepping;\n this._clearStepTargets();\n return;\n }\n this.dataset.stepping = '';\n\n const n = this.steps;\n const targets = this._stepTargets();\n if (targets.length === 0) return;\n\n const reduce = this._reduceMotion();\n if (reduce) {\n for (const el of targets) el.dataset.step = '0';\n return;\n }\n\n // Build cumulative time boundaries (ms) for each step from its weight.\n const weights = this._stepWeights(n);\n const total = weights.reduce((a, b) => a + b, 0);\n const cycleMs = this._parseTime(this.rate);\n const bounds = [];\n let acc = 0;\n for (const w of weights) {\n acc += w;\n bounds.push((acc / total) * cycleMs);\n }\n\n // Per-unit stepping offsets each unit's phase by a stagger so the states\n // travel across the text. Read --blink-stagger (seconds) for the step.\n const perUnit = targets.length > 1;\n const staggerMs = perUnit\n ? (parseFloat(getComputedStyle(this).getPropertyValue('--blink-stagger')) || 0.08) * 1000\n : 0;\n\n const stepAt = (pos) => {\n let idx = 0;\n while (idx < n - 1 && pos >= bounds[idx]) idx++;\n return idx;\n };\n\n const prev = new Array(targets.length).fill(0);\n targets.forEach((el) => (el.dataset.step = '0'));\n let elapsed = 0;\n let lastT = null;\n const tick = (t) => {\n this._stepRAF = requestAnimationFrame(tick);\n if (lastT == null) lastT = t;\n const dt = t - lastT;\n lastT = t;\n if (this._isPaused()) return; // freeze the timeline while paused\n elapsed += dt;\n for (let k = 0; k < targets.length; k++) {\n const idx = stepAt((elapsed + k * staggerMs) % cycleMs);\n if (idx !== prev[k]) {\n targets[k].dataset.step = String(idx);\n if (k === 0 && idx < prev[k]) this._dispatch('blink-cycle'); // wrapped to start\n prev[k] = idx;\n }\n }\n };\n this._stepRAF = requestAnimationFrame(tick);\n }\n\n _dispatch(name) {\n this.dispatchEvent(new CustomEvent(name, { bubbles: true }));\n }\n}\n\ncustomElements.define('blink-wc', BlinkWc);\n\nexport { BlinkWc };\n"],"names":["LETTER_MODES","STEP_MODES","STEP_COUNTS","DECODE_GLYPHS","MORSE","REDUCED_MQ","INSTANCES","rootObserver","systemReducesMotion","resyncAll","el","watchMotion","unwatchMotion","BlinkWc","b","v","_a","_b","name","oldValue","newValue","items","content","n","perUnitSteps","byWord","walker","textNodes","twinkle","decode","isWs","c","i","node","frag","tokens","ch","space","span","text","buf","bufWs","ws","segments","dotRaw","DOT","totalUnits","s","elapsed","lastT","tick","t","dt","cycle","acc","lit","next","words","word","wi","chars","ci","symbols","sym","si","entries","units","randGlyph","SCRAMBLE_MS","STAGGER_MS","HOLD_MS","FLIP_MS","maxSettle","settleAt","lastFlip","flip","it","value","ms","raw","parts","_","targets","weights","total","a","cycleMs","bounds","w","staggerMs","stepAt","pos","idx","prev","k"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profpowell/blink-wc",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "A vanilla JavaScript web component: the <blink> tag reborn for 2026 — accessible, themeable, CSS-driven, and Vanilla Breeze aware",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "dist/blink-wc.js",
|
|
10
|
+
"module": "dist/blink-wc.js",
|
|
11
|
+
"types": "blink-wc.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./blink-wc.d.ts",
|
|
15
|
+
"import": "./dist/blink-wc.js"
|
|
16
|
+
},
|
|
17
|
+
"./style.css": "./dist/blink-wc.css",
|
|
18
|
+
"./blink-wc.css": "./dist/blink-wc.css"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"blink-wc.d.ts",
|
|
23
|
+
"custom-elements.json"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"dev": "vite",
|
|
27
|
+
"build": "vite build && cp src/blink-wc.css dist/blink-wc.css && cp dist/blink-wc.js dist/blink-wc.js.map docs/ && cp src/blink-wc.css docs/blink-wc.css",
|
|
28
|
+
"preview": "vite preview",
|
|
29
|
+
"test": "playwright test",
|
|
30
|
+
"test:ui": "playwright test --ui",
|
|
31
|
+
"lint": "eslint src/",
|
|
32
|
+
"format": "prettier --write .",
|
|
33
|
+
"analyze": "cem analyze",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"web-component",
|
|
38
|
+
"custom-element",
|
|
39
|
+
"blink",
|
|
40
|
+
"marquee",
|
|
41
|
+
"vanilla-breeze",
|
|
42
|
+
"retro",
|
|
43
|
+
"animation"
|
|
44
|
+
],
|
|
45
|
+
"author": "ProfPowell",
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@custom-elements-manifest/analyzer": "^0.10.3",
|
|
49
|
+
"@playwright/test": "^1.48.0",
|
|
50
|
+
"eslint": "^9.12.0",
|
|
51
|
+
"prettier": "^3.3.3",
|
|
52
|
+
"vite": "^5.4.8"
|
|
53
|
+
},
|
|
54
|
+
"customElements": "custom-elements.json",
|
|
55
|
+
"repository": {
|
|
56
|
+
"type": "git",
|
|
57
|
+
"url": "git+https://github.com/ProfPowell/blink-wc.git"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://profpowell.github.io/blink-wc/",
|
|
60
|
+
"bugs": {
|
|
61
|
+
"url": "https://github.com/ProfPowell/blink-wc/issues"
|
|
62
|
+
}
|
|
63
|
+
}
|