@3r1s_s/erisui 1.0.5

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.
@@ -0,0 +1,1694 @@
1
+ class C extends HTMLElement {
2
+ static get observedAttributes() {
3
+ return ["size", "border-radius", "name", "color"];
4
+ }
5
+ constructor() {
6
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
7
+ <style>
8
+ :host {
9
+ aspect-ratio: 1 / 1;
10
+ width: fit-content;
11
+
12
+ user-select: none;
13
+ -webkit-user-select: none;
14
+ -webkit-user-drag: none;
15
+ -webkit-user-modify: none;
16
+ -webkit-highlight: none;
17
+ -webkit-tap-highlight-color: transparent;
18
+ }
19
+
20
+ .avatar {
21
+ width: 32px;
22
+ height: 100%;
23
+ aspect-ratio: 1 / 1;
24
+
25
+ border-radius: var(--border-radius, 50%);
26
+ overflow: hidden;
27
+ box-shadow: inset 0 0 0 1px #ffffff25;
28
+
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ background-color: #000;
33
+ color: #fff;
34
+ font-weight: 500;
35
+ font-size: 1.2rem;
36
+ text-transform: uppercase;
37
+ }
38
+
39
+ ::slotted(img) {
40
+ width: 100%;
41
+ height: 100%;
42
+ border-radius: var(--border-radius, 50%);
43
+ object-fit: cover;
44
+ display: block;
45
+ }
46
+ </style>
47
+ <div class="avatar">
48
+ <slot></slot>
49
+ <span id="initials"></span>
50
+ </div>
51
+ `;
52
+ }
53
+ connectedCallback() {
54
+ this.avatar = this.shadowRoot.querySelector(".avatar"), this.initials = this.shadowRoot.querySelector("#initials");
55
+ const t = this.shadowRoot.querySelector("slot"), i = t && t.assignedNodes().length > 0;
56
+ if (i) {
57
+ const e = t.assignedNodes()[0];
58
+ e && e.tagName === "IMG" && (this.initials.style.display = "none", this.avatar.style.backgroundColor = "transparent");
59
+ } else
60
+ this.hasAttribute("color") && (this.avatar.style.backgroundColor = this.getAttribute("color"));
61
+ if (this.hasAttribute("color") && (this.avatar.style.backgroundColor = this.getAttribute("color")), this.hasAttribute("size")) {
62
+ const e = this.getAttribute("size");
63
+ this.avatar.style.width = e + "px", this.avatar.style.height = e + "px", this.initials.style.fontSize = e / 2 + "px";
64
+ }
65
+ if (this.hasAttribute("border-radius") && (this.avatar.style.borderRadius = this.getAttribute("border-radius") + "px"), this.hasAttribute("name") && (this.avatar.title = this.getAttribute("name")), !i && this.hasAttribute("name")) {
66
+ const r = this.getAttribute("name").trim().split(/\s+/);
67
+ let n = "";
68
+ r.length === 1 ? n = r[0][0] || "" : n = (r[0][0] || "") + (r[r.length - 1][0] || ""), this.initials.textContent = n.toUpperCase();
69
+ }
70
+ }
71
+ }
72
+ customElements.define("eui-avatar", C);
73
+ const x = /* @__PURE__ */ new Map();
74
+ class S extends HTMLElement {
75
+ static get observedAttributes() {
76
+ return ["name", "width", "height"];
77
+ }
78
+ constructor() {
79
+ super(), this.attachShadow({ mode: "open" });
80
+ }
81
+ connectedCallback() {
82
+ this.render();
83
+ }
84
+ attributeChangedCallback(t, i, e) {
85
+ i !== e && this.render();
86
+ }
87
+ async render() {
88
+ const t = this.getAttribute("name");
89
+ if (!t) return;
90
+ let i = x.get(t);
91
+ if (!i)
92
+ try {
93
+ const a = await fetch(`/icons/${t}.svg`);
94
+ if (a.ok)
95
+ i = await a.text(), x.set(t, i);
96
+ else {
97
+ console.error(`Icon "${t}" not found`), this.shadowRoot.innerHTML = '<span style="color:red;">?</span>';
98
+ return;
99
+ }
100
+ } catch (a) {
101
+ console.error(`Error loading icon "${t}":`, a), this.shadowRoot.innerHTML = '<span style="color:red;">?</span>';
102
+ return;
103
+ }
104
+ const e = document.createElement("template");
105
+ e.innerHTML = i.trim();
106
+ const r = e.content.cloneNode(!0), n = r.firstElementChild;
107
+ if (n && n.style) {
108
+ const a = this.getAttribute("width"), l = this.getAttribute("height");
109
+ a && n.setAttribute("width", a), l && n.setAttribute("height", l), n.style.display = "block";
110
+ }
111
+ this.shadowRoot.innerHTML = "", this.shadowRoot.appendChild(r);
112
+ }
113
+ }
114
+ customElements.define("eui-icon", S);
115
+ class L extends HTMLElement {
116
+ static get observedAttributes() {
117
+ return ["label", "value", "id", "type", "filled"];
118
+ }
119
+ constructor() {
120
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
121
+ <style>
122
+ .form {
123
+ display: flex;
124
+ flex-direction: column;
125
+ gap: 12px;
126
+ width: 100%;
127
+ max-width: 300px;
128
+ margin: 0.75rem 0;
129
+ position: relative;
130
+ }
131
+
132
+ .form-input {
133
+ padding: 5px 10px;
134
+ border-radius: 5px;
135
+ width: 100%;
136
+ box-sizing: border-box;
137
+ font-size: 1em;
138
+ font-family: inherit;
139
+ height: 52px;
140
+ background: var(--app-100, #111);
141
+ outline: none;
142
+ border: 1px solid var(--app-300, #2196F3);
143
+ caret-color: var(--app-text);
144
+ color: var(--app-text);
145
+ transition: border .15s ease-out;
146
+ }
147
+
148
+ .filled.form .form-input {
149
+ background: var(--app-200, #222);
150
+ padding-bottom: 0;
151
+ padding-top: 0.6rem;
152
+ border: none;
153
+ border-bottom-left-radius: 0;
154
+ border-bottom-right-radius: 0;
155
+ border-bottom: 1px solid var(--app-300, #333);
156
+ }
157
+
158
+ .form-input:focus {
159
+ border: 1px solid var(--app-blue, #2196F3);
160
+ }
161
+
162
+ .filled.form .form-input:focus {
163
+ border-bottom: 2.5px solid var(--app-blue, #2196F3);
164
+ }
165
+
166
+ .form {
167
+ --form-inactive-top: 14.5px;
168
+ --form-inactive-left: 6px;
169
+
170
+ --form-active-top: -10px;
171
+ --form-active-left: 5px;
172
+ }
173
+
174
+ .filled.form {
175
+ --form-active-top: 3px;
176
+ --form-active-left: 6px;
177
+ }
178
+
179
+ .form label {
180
+ transition: all .15s ease-out;
181
+ color: var(--app-400, #999);
182
+ background: var(--app-100, #111);
183
+ pointer-events: none;
184
+ display: block;
185
+ padding: 0 .25rem;
186
+ position: absolute;
187
+ left: var(--form-inactive-left);
188
+ top: var(--form-inactive-top);
189
+ border-radius: 5px;
190
+ width: fit-content;
191
+
192
+ user-select: none;
193
+ -webkit-user-select: none;
194
+ }
195
+
196
+ .filled.form label {
197
+ background: transparent;
198
+ }
199
+
200
+ .form-input:focus+label,
201
+ .form-input:not(:placeholder-shown)+label,
202
+ .form-input.filled+label,
203
+ .form.always-active label {
204
+ top: var(--form-active-top);
205
+ left: var(--form-active-left);
206
+ font-size: .75em;
207
+ }
208
+
209
+ .form-input:focus+label {
210
+ font-weight: 600;
211
+ color: var(--app-blue, #2196F3);
212
+ width: auto;
213
+ }
214
+ </style>
215
+
216
+ <div class="form">
217
+ <input class="form-input" placeholder=" ">
218
+ <label></label>
219
+ </div>
220
+ `;
221
+ }
222
+ connectedCallback() {
223
+ this.form = this.shadowRoot.querySelector(".form"), this.inputEl = this.shadowRoot.querySelector(".form-input"), this.labelEl = this.shadowRoot.querySelector("label"), this.hasAttribute("value") && (this.inputEl.value = this.getAttribute("value")), this.hasAttribute("id") && (this.inputEl.id = this.getAttribute("id")), this.hasAttribute("label") && (this.labelEl.textContent = this.getAttribute("label")), this.hasAttribute("type") && (this.inputEl.type = this.getAttribute("type")), this.hasAttribute("filled") && this.form.classList.add("filled"), this.inputEl.addEventListener("input", () => {
224
+ this.setAttribute("value", this.inputEl.value);
225
+ });
226
+ }
227
+ attributeChangedCallback(t, i, e) {
228
+ if (!(!this.inputEl || !this.labelEl))
229
+ switch (t) {
230
+ case "value":
231
+ this.inputEl.value !== e && (this.inputEl.value = e);
232
+ break;
233
+ case "id":
234
+ this.inputEl.id = e;
235
+ break;
236
+ case "label":
237
+ this.labelEl.textContent = e;
238
+ break;
239
+ }
240
+ }
241
+ get value() {
242
+ return this.inputEl.value;
243
+ }
244
+ set value(t) {
245
+ this.setAttribute("value", t);
246
+ }
247
+ }
248
+ customElements.define("eui-input", L);
249
+ class T extends HTMLElement {
250
+ constructor() {
251
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
252
+ <style>
253
+ .loader {
254
+ width: 24px;
255
+ height: 24px;
256
+ display: inline-block;
257
+ position: relative;
258
+ }
259
+
260
+ .loader-icon {
261
+ stroke: var(--app-accent, #2196F3);
262
+ fill: none;
263
+ stroke-width: 2px;
264
+ stroke-linecap: round;
265
+ transform-origin: 50% 50%;
266
+ transform: rotate(-90deg);
267
+ transition: all 0.2s ease-in-out 0s;
268
+ animation: 2s linear 0s infinite normal none running loader-spin;
269
+ }
270
+
271
+ .loader-icon {
272
+ stroke: var(--app-text, #F2F3F6);
273
+ }
274
+
275
+ @keyframes loader-spin {
276
+ 0% {
277
+ stroke-dasharray: 0.01px, 43.97px;
278
+ transform: rotate(0deg)
279
+ }
280
+
281
+ 50% {
282
+ stroke-dasharray: 21.99px, 21.99px;
283
+ transform: rotate(450deg)
284
+ }
285
+
286
+ 100% {
287
+ stroke-dasharray: 0.01px, 43.97px;
288
+ transform: rotate(1080deg)
289
+ }
290
+ }
291
+ </style>
292
+
293
+ <span class="loader animate">
294
+ <svg viewBox="0 0 16 16"><circle class="loader-icon" cx="8px" cy="8px" r="7px"></circle></svg>
295
+ </span>
296
+ `;
297
+ }
298
+ }
299
+ customElements.define("eui-loader", T);
300
+ class M extends HTMLElement {
301
+ static get observedAttributes() {
302
+ return ["value", "intermediate", "id"];
303
+ }
304
+ constructor() {
305
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
306
+ <style>
307
+ .progressbar {
308
+ width: 100%;
309
+ height: 5px;
310
+ overflow: hidden;
311
+ position: relative;
312
+ background: var(--app-300, #333);
313
+ border-radius: 4px;
314
+ }
315
+
316
+ .progress {
317
+ display: block;
318
+ height: 100%;
319
+ background: var(--app-accent, #2196F3);
320
+ border-radius: 4px;
321
+ transition: width 0.3s ease-in-out;
322
+ }
323
+
324
+ .progress.intermediate {
325
+ height: 100%;
326
+ transform-origin: 0% 50%;
327
+ transition-property: background;
328
+ animation: progressbar-indeterminate 1s infinite linear;
329
+ }
330
+
331
+ @keyframes progressbar-indeterminate {
332
+ 0% {
333
+ transform: translateX(0) scaleX(0)
334
+ }
335
+
336
+ 40% {
337
+ transform: translateX(0) scaleX(0.5)
338
+ }
339
+
340
+ 100% {
341
+ transform: translateX(100%) scaleX(0.3)
342
+ }
343
+ }
344
+ </style>
345
+
346
+ <div class="progressbar">
347
+ <span class="progress"></span>
348
+ </div>
349
+ `;
350
+ }
351
+ set value(t) {
352
+ this.setAttribute("value", t);
353
+ }
354
+ attributeChangedCallback() {
355
+ this.connectedCallback();
356
+ }
357
+ connectedCallback() {
358
+ const t = this.shadowRoot.querySelector(".progress");
359
+ this.hasAttribute("id") && (this.progress.id = this.getAttribute("id")), this.hasAttribute("intermediate") && t.classList.add("intermediate"), this.hasAttribute("value") && (t.style.width = this.getAttribute("value") + "%");
360
+ }
361
+ }
362
+ customElements.define("eui-progressbar", M);
363
+ const m = {
364
+ is: {
365
+ iPhone: /iPhone/.test(navigator.userAgent),
366
+ iPad: /iPad/.test(navigator.userAgent),
367
+ iOS: /iPhone|iPad|iPod/.test(navigator.userAgent),
368
+ android: /Android/.test(navigator.userAgent),
369
+ mobile: /Mobi|Android/i.test(navigator.userAgent)
370
+ // matches most mobile browsers
371
+ },
372
+ prefers: {
373
+ language: navigator.language || navigator.userLanguage,
374
+ reducedMotion: window.matchMedia("(prefers-reduced-motion: reduce)").matches,
375
+ reducedTransparency: window.matchMedia("(prefers-reduced-transparency: reduce)").matches
376
+ },
377
+ supports: {
378
+ share: typeof navigator.share == "function",
379
+ directDownload: "download" in document.createElement("a"),
380
+ haptics: "vibrate" in navigator || "Vibrate" in window || typeof window.navigator.vibrate == "function"
381
+ },
382
+ userAgent: navigator.userAgent
383
+ }, X = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
384
+ __proto__: null,
385
+ device: m
386
+ }, Symbol.toStringTag, { value: "Module" }));
387
+ function z() {
388
+ try {
389
+ const o = document.createElement("label");
390
+ o.ariaHidden = "true", o.style.display = "none";
391
+ const t = document.createElement("input");
392
+ t.type = "checkbox", t.setAttribute("switch", ""), o.appendChild(t), document.head.appendChild(o), o.click(), document.head.removeChild(o);
393
+ } catch {
394
+ }
395
+ }
396
+ function v(o) {
397
+ m.supports.haptics ? navigator.vibrate(o || 50) : m.is.iPhone && z();
398
+ }
399
+ const W = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
400
+ __proto__: null,
401
+ haptic: v
402
+ }, Symbol.toStringTag, { value: "Module" })), w = (() => {
403
+ let o = {}, t;
404
+ try {
405
+ o = JSON.parse(localStorage.getItem(t) || "{}");
406
+ } catch (i) {
407
+ console.error(i);
408
+ }
409
+ return {
410
+ get(i) {
411
+ return o[i];
412
+ },
413
+ set(i, e) {
414
+ o[i] = e, localStorage.setItem(t, JSON.stringify(o));
415
+ },
416
+ delete(i) {
417
+ delete o[i], localStorage.setItem(t, JSON.stringify(o));
418
+ },
419
+ all() {
420
+ return o;
421
+ },
422
+ clear() {
423
+ o = {}, localStorage.setItem(t, JSON.stringify(o));
424
+ },
425
+ name(i) {
426
+ t = i;
427
+ try {
428
+ o = JSON.parse(localStorage.getItem(t) || "{}");
429
+ } catch (e) {
430
+ console.error(e);
431
+ }
432
+ },
433
+ settings: {
434
+ get(i) {
435
+ return o && o.settings && o.settings[i];
436
+ },
437
+ set(i, e) {
438
+ o.settings || (o.settings = {}), o.settings[i] = e, localStorage.setItem(t, JSON.stringify(o));
439
+ },
440
+ delete(i) {
441
+ o.settings && (delete o.settings[i], localStorage.setItem(t, JSON.stringify(o)));
442
+ },
443
+ all() {
444
+ return o.settings || {};
445
+ },
446
+ clear() {
447
+ o.settings && (o.settings = {}, localStorage.setItem(t, JSON.stringify(o)));
448
+ }
449
+ }
450
+ };
451
+ })(), y = w.settings, J = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
452
+ __proto__: null,
453
+ settings: y,
454
+ storage: w
455
+ }, Symbol.toStringTag, { value: "Module" }));
456
+ class R extends HTMLElement {
457
+ static get observedAttributes() {
458
+ return ["selected"];
459
+ }
460
+ constructor() {
461
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
462
+ <style>
463
+ .switch {
464
+ background-color: var(--app-200);
465
+ border-radius: 16px;
466
+
467
+ box-shadow: inset 0px 0px 0px 2px var(--app-400);
468
+ width: 52px;
469
+ height: 32px;
470
+ display: flex;
471
+ align-items: center;
472
+ justify-content: center;
473
+ cursor: pointer;
474
+ position: relative;
475
+ }
476
+
477
+ .switch.selected {
478
+ background-color: #B8C4FF;
479
+ box-shadow: none;
480
+ }
481
+
482
+ .handle {
483
+ width: 16px;
484
+ height: 16px;
485
+ border-radius: 50%;
486
+ background-color: var(--app-900);
487
+ margin-inline-start: 0;
488
+ margin-inline-end: calc(52px - 32px);
489
+
490
+ transition: margin 300ms cubic-bezier(0.175, 0.885, 0.32, 1.275),
491
+ width 250ms cubic-bezier(0.2, 0, 0, 1),
492
+ height 250ms cubic-bezier(0.2, 0, 0, 1);
493
+
494
+ pointer-events: none;
495
+ user-select: none;
496
+ }
497
+
498
+ .switch.selected .handle {
499
+ background-color: #5F7AFF;
500
+ margin-inline-start: calc(52px - 32px);
501
+ margin-inline-end: 0;
502
+ width: 24px;
503
+ height: 24px;
504
+ }
505
+
506
+ .switch:active .handle {
507
+ width: 28px;
508
+ height: 28px;
509
+ }
510
+
511
+ input {
512
+ appearance: none;
513
+ opacity: 0;
514
+ height: max(100%, var(--eui-switch-touch-target-size, 48px));
515
+ width: max(100%, var(--eui-switch-touch-target-size, 48px));
516
+ position: absolute;
517
+ margin: 0;
518
+ cursor: inherit;
519
+ top: 50%;
520
+ left: 50%;
521
+ transform: translate(-50%, -50%);
522
+ z-index: 2;
523
+ }
524
+ </style>
525
+
526
+ <div class="switch">
527
+ <input type="checkbox" role="switch">
528
+ <span class="handle"></span>
529
+ </div>
530
+ `;
531
+ }
532
+ connectedCallback() {
533
+ this.inputEl = this.shadowRoot.querySelector("input"), this.switchEl = this.shadowRoot.querySelector(".switch"), this.updateFromAttribute(), this.switchEl.addEventListener("click", () => this.toggle());
534
+ }
535
+ toggle() {
536
+ this.selected = !this.selected, v();
537
+ }
538
+ updateFromAttribute() {
539
+ const t = this.hasAttribute("selected");
540
+ this.inputEl.checked = t, this.switchEl.classList.toggle("selected", t);
541
+ }
542
+ attributeChangedCallback(t, i, e) {
543
+ t === "selected" && this.inputEl && this.updateFromAttribute();
544
+ }
545
+ get selected() {
546
+ return this.hasAttribute("selected");
547
+ }
548
+ set selected(t) {
549
+ t ? this.setAttribute("selected", "") : this.removeAttribute("selected");
550
+ }
551
+ }
552
+ customElements.define("eui-switch", R);
553
+ class $ extends HTMLElement {
554
+ constructor() {
555
+ super(), this.attachShadow({ mode: "open" });
556
+ }
557
+ connectedCallback() {
558
+ this.shadowRoot.innerHTML = `
559
+ <style>
560
+ :host {
561
+ display: inline-flex;
562
+ align-items: center;
563
+ gap: 4px;
564
+ padding: 4px 8px;
565
+ border-radius: 8px;
566
+ border: 2px solid var(--app-400);
567
+ font-weight: 500;
568
+ font-size: 1rem;
569
+ position: relative;
570
+ color: var(--app-text);
571
+ overflow: hidden;
572
+ z-index: 1;
573
+
574
+ user-select: none;
575
+ -webkit-user-select: none;
576
+ -webkit-user-drag: none;
577
+ -webkit-user-modify: none;
578
+ -webkit-highlight: none;
579
+ -webkit-tap-highlight-color: transparent;
580
+ }
581
+
582
+ .ripple {
583
+ position: absolute;
584
+ border-radius: 50%;
585
+ transform: scale(0);
586
+ filter: blur(4px);
587
+ opacity: 0.2;
588
+ animation: ripple 600ms linear;
589
+ background-color: var(--app-400);
590
+ pointer-events: none;
591
+ z-index: -1;
592
+ }
593
+
594
+ @keyframes ripple {
595
+ to {
596
+ transform: scale(4);
597
+ opacity: 0;
598
+ filter: blur(10px);
599
+ }
600
+ }
601
+ </style>
602
+ <slot></slot>
603
+ `, this.addEventListener("pointerdown", (t) => {
604
+ const i = document.createElement("span"), e = t.currentTarget, r = Math.max(e.offsetWidth, e.offsetHeight);
605
+ i.classList.add("ripple"), i.style.left = t.clientX - e.getBoundingClientRect().left - r / 2 + "px", i.style.top = t.clientY - e.getBoundingClientRect().top - r / 2 + "px", i.style.width = r + "px", i.style.height = r + "px", this.shadowRoot.appendChild(i), setTimeout(() => {
606
+ i.remove();
607
+ }, 600);
608
+ });
609
+ }
610
+ }
611
+ customElements.define("eui-chip", $);
612
+ const b = "", k = (() => {
613
+ const o = [];
614
+ function t(s, d) {
615
+ const h = [], u = s.replace(/:([^/]+)/g, (g, f) => (h.push(f), "([^/]+)")).replace(/\//g, "\\/"), p = new RegExp(`^${b}${u}$`);
616
+ o.push({ regex: p, paramNames: h, renderFn: d });
617
+ }
618
+ function i(s) {
619
+ for (const { regex: d, paramNames: h, renderFn: u } of o) {
620
+ const p = s.match(d);
621
+ if (p) {
622
+ const g = {};
623
+ return h.forEach((f, A) => {
624
+ g[f] = decodeURIComponent(p[A + 1]);
625
+ }), { renderFn: u, params: g };
626
+ }
627
+ }
628
+ return null;
629
+ }
630
+ function e(s, d = !0) {
631
+ s.startsWith(b) || (s = b + (s.startsWith("/") ? "" : "/") + s);
632
+ const h = s.split(/[?#]/)[0];
633
+ if (h === window.location.pathname && s.includes("#")) {
634
+ d && history.pushState({}, "", s);
635
+ const p = "#" + s.split("#")[1];
636
+ r(p);
637
+ return;
638
+ }
639
+ const u = i(h);
640
+ if (u)
641
+ if (d && history.pushState({}, "", s), u.renderFn(u.params), window.dispatchEvent(new CustomEvent("route-changed", { detail: { path: s } })), s.includes("#")) {
642
+ const p = "#" + s.split("#")[1];
643
+ setTimeout(() => r(p), 100);
644
+ } else {
645
+ const p = document.getElementById("main");
646
+ p && p.scrollTo(0, 0);
647
+ }
648
+ else n ? (d && history.pushState({}, "", s), n()) : console.warn(`No route found for ${h}`);
649
+ }
650
+ function r(s) {
651
+ if (s)
652
+ try {
653
+ const d = document.querySelector(s);
654
+ d && d.scrollIntoView({ behavior: "smooth" });
655
+ } catch {
656
+ console.warn("Invalid hash:", s);
657
+ }
658
+ }
659
+ let n = null;
660
+ function a(s) {
661
+ n = s;
662
+ }
663
+ function l() {
664
+ history.back();
665
+ }
666
+ function c() {
667
+ return window.location.pathname.replace(b, "") || "/";
668
+ }
669
+ return window.addEventListener("popstate", () => {
670
+ const s = window.location.pathname + window.location.search + window.location.hash;
671
+ e(s, !1);
672
+ }), window.addEventListener("click", (s) => {
673
+ if (s.button !== 0 || s.metaKey || s.altKey || s.ctrlKey || s.shiftKey) return;
674
+ const d = s.target.closest("a");
675
+ if (!d || d.hasAttribute("download") || d.getAttribute("target") === "_blank") return;
676
+ const h = d.getAttribute("href");
677
+ if (!(!h || h.startsWith("http") && !h.startsWith(window.location.origin))) {
678
+ if (s.preventDefault(), h.startsWith("#")) {
679
+ history.pushState({}, "", h), r(h);
680
+ return;
681
+ }
682
+ e(h);
683
+ }
684
+ }), { add: t, navigate: e, back: l, location: c, setNotFound: a };
685
+ })();
686
+ async function V(o) {
687
+ try {
688
+ const t = document.getElementById("main");
689
+ t.classList.add("fade-out"), await new Promise((e) => setTimeout(e, 200));
690
+ const i = await fetch(`/src/pages/${o}.html`).then((e) => e.text());
691
+ t.innerHTML = i, t.classList.remove("fade-out"), t.classList.add("fade-in"), window.location.hash ? setTimeout(() => {
692
+ try {
693
+ const e = document.querySelector(window.location.hash);
694
+ e && e.scrollIntoView({ behavior: "smooth" });
695
+ } catch {
696
+ }
697
+ }, 100) : t && t.scrollTo(0, 0), setTimeout(() => {
698
+ t.classList.remove("fade-in");
699
+ }, 200);
700
+ } catch (t) {
701
+ console.error("Page load failed:", t);
702
+ }
703
+ }
704
+ class H extends HTMLElement {
705
+ static get observedAttributes() {
706
+ return ["path", "icon", "label", "badge", "active", "avatar-src", "avatar-name"];
707
+ }
708
+ constructor() {
709
+ super(), this.attachShadow({ mode: "open" });
710
+ }
711
+ connectedCallback() {
712
+ this.hasRendered || (this.render(), this.setupEventListeners(), this.hasRendered = !0), this.updateContent(), this.addEventListener("click", this.handleClick);
713
+ }
714
+ disconnectedCallback() {
715
+ this.removeEventListener("click", this.handleClick);
716
+ }
717
+ attributeChangedCallback(t, i, e) {
718
+ if (i !== e && this.hasRendered) {
719
+ if (t === "active")
720
+ return;
721
+ this.updateContent();
722
+ }
723
+ }
724
+ handleClick = () => {
725
+ const t = this.getAttribute("path");
726
+ t && k.navigate(t);
727
+ };
728
+ setupEventListeners() {
729
+ this.addEventListener("pointerdown", (t) => {
730
+ const i = document.createElement("span"), e = t.currentTarget, r = e.getBoundingClientRect(), n = Math.max(e.offsetWidth, e.offsetHeight), a = n / 2;
731
+ i.classList.add("ripple"), i.style.width = `${n}px`, i.style.height = `${n}px`, i.style.left = `${t.clientX - r.left - a}px`, i.style.top = `${t.clientY - r.top - a}px`, this.shadowRoot.appendChild(i), i.addEventListener("animationend", () => {
732
+ i.remove();
733
+ });
734
+ });
735
+ }
736
+ updateContent() {
737
+ const t = this.getAttribute("icon"), i = this.getAttribute("avatar-src"), e = this.getAttribute("avatar-name"), r = this.getAttribute("label") || "", n = this.getAttribute("badge"), a = this.shadowRoot.querySelector(".badge");
738
+ if (n)
739
+ if (a)
740
+ a.textContent = n;
741
+ else {
742
+ const s = document.createElement("span");
743
+ s.className = "badge", s.textContent = n, this.shadowRoot.appendChild(s);
744
+ }
745
+ else a && a.remove();
746
+ const l = this.shadowRoot.querySelector("slot[name='icon']");
747
+ if (l)
748
+ if (i || e) {
749
+ let s = '<eui-avatar size="24"';
750
+ e && (s += ` name="${e}"`), s += ">", i && (s += `<img src="${i}" alt="${e || "Avatar"}" />`), s += "</eui-avatar>", l.innerHTML = s;
751
+ } else {
752
+ const s = l.querySelector("eui-icon");
753
+ t && s ? s.getAttribute("name") !== t && s.setAttribute("name", t) : t ? l.innerHTML = `<eui-icon width="24" height="24" name="${t}"></eui-icon>` : l.innerHTML = "";
754
+ }
755
+ const c = this.shadowRoot.querySelector(".label");
756
+ c && (c.textContent = r);
757
+ }
758
+ render() {
759
+ this.shadowRoot.innerHTML = `
760
+ <style>
761
+ :host {
762
+ position: relative;
763
+ overflow: hidden;
764
+ z-index: 1;
765
+ display: flex;
766
+ align-items: center;
767
+ height: 50px;
768
+ width: 100%;
769
+ cursor: pointer;
770
+ border-radius: 100px;
771
+ justify-content: flex-start;
772
+ padding: 0 1rem;
773
+ box-sizing: border-box;
774
+ transition: background-color 0.2s cubic-bezier(.4, 0, .2, 1), transform 0.2s cubic-bezier(.4, 0, .2, 1);
775
+ user-select: none;
776
+ -webkit-user-select: none;
777
+ color: var(--app-text);
778
+ }
779
+
780
+ :host(:hover) {
781
+ background-color: var(--app-300);
782
+ }
783
+
784
+ :host(:focus-visible) {
785
+ outline: 2px solid var(--app-link);
786
+ outline-offset: 2px;
787
+ }
788
+
789
+ :host([active]) {
790
+ background-color: color-mix(in srgb, var(--app-link) 25%, transparent 100%);
791
+ color: var(--app-link);
792
+ }
793
+
794
+ :host([active]) .label {
795
+ font-weight: 600;
796
+ }
797
+
798
+ .icon-container {
799
+ display: flex;
800
+ align-items: center;
801
+ justify-content: center;
802
+ width: 28px;
803
+ height: 28px;
804
+ flex-shrink: 0;
805
+ border-radius: 100px;
806
+ }
807
+
808
+ :host([active]) .icon-container eui-avatar {
809
+ outline: 2px solid var(--app-link);
810
+ outline-offset: 1px;
811
+ border-radius: 50%;
812
+ }
813
+
814
+ .label {
815
+ opacity: var(--nav-item-label-opacity, 0);
816
+ margin-left: 1rem;
817
+ display: block;
818
+ transition: opacity 0.1s ease;
819
+ white-space: nowrap;
820
+ }
821
+
822
+ .badge {
823
+ position: absolute;
824
+ top: 4px;
825
+ left: calc(32px + 2px);
826
+ width: 20px;
827
+ height: 20px;
828
+ border-radius: 50%;
829
+ background-color: var(--app-red);
830
+ color: var(--app-white);
831
+ display: flex;
832
+ align-items: center;
833
+ justify-content: center;
834
+ font-size: 14px;
835
+ font-weight: 600;
836
+ }
837
+
838
+ .ripple {
839
+ position: absolute;
840
+ border-radius: 50%;
841
+ transform: scale(0);
842
+ opacity: 0.2;
843
+ animation: ripple 600ms linear forwards;
844
+ background-color: currentColor;
845
+ pointer-events: none;
846
+ z-index: -1;
847
+ will-change: transform, opacity;
848
+ }
849
+
850
+ @keyframes ripple {
851
+ to {
852
+ transform: scale(4);
853
+ opacity: 0;
854
+ }
855
+ }
856
+ </style>
857
+
858
+ <div class="icon-container">
859
+ <slot name="icon">
860
+ <eui-icon width="24" height="24" name=""></eui-icon>
861
+ </slot>
862
+ </div>
863
+ <span class="label"></span>
864
+ `;
865
+ }
866
+ }
867
+ customElements.define("eui-nav-item", H);
868
+ class _ extends HTMLElement {
869
+ constructor() {
870
+ super(), this.attachShadow({ mode: "open" });
871
+ }
872
+ connectedCallback() {
873
+ this.updateActiveState(), window.addEventListener("popstate", () => this.updateActiveState()), window.addEventListener("route-changed", () => this.updateActiveState()), window.addEventListener("toggle-nav", () => this.classList.toggle("expanded"));
874
+ }
875
+ render() {
876
+ this.shadowRoot.innerHTML = `
877
+ <style>
878
+ :host {
879
+ position: fixed;
880
+ top: var(--titlebar-height, 65px);
881
+ left: 0;
882
+ height: calc(100% - var(--titlebar-height, 65px));
883
+ z-index: 100;
884
+
885
+ width: var(--nav-width, 75px);
886
+ transition: width 0.2s cubic-bezier(0.2, 0, 0, 1);
887
+ }
888
+
889
+ :host(.expanded) {
890
+ width: var(--nav-expanded-width, 250px);
891
+ --nav-item-label-opacity: 1;
892
+ }
893
+
894
+ .app-nav-container {
895
+ width: 100%;
896
+ height: 100%;
897
+ box-sizing: border-box;
898
+ background-color: var(--app-200);
899
+ overflow-x: hidden;
900
+ display: flex;
901
+ flex-direction: column;
902
+ }
903
+
904
+ .nav-items {
905
+ display: flex;
906
+ flex-direction: column;
907
+ gap: 0.5rem;
908
+ padding: 0.5rem;
909
+ box-sizing: border-box;
910
+ overflow-y: auto;
911
+ overflow-x: hidden;
912
+ }
913
+
914
+ .menu-button {
915
+ border: none;
916
+ background-color: transparent;
917
+ cursor: pointer;
918
+ width: 42px;
919
+ height: 42px;
920
+ display: flex;
921
+ align-items: center;
922
+ justify-content: center;
923
+ box-sizing: border-box;
924
+ border-radius: 50%;
925
+ color: inherit;
926
+ }
927
+
928
+ .menu-button:hover {
929
+ background-color: var(--app-300);
930
+ box-shadow: 0 0 2px 0 #00000011;
931
+ }
932
+
933
+ .menu-button:active {
934
+ transform: scale(0.95);
935
+ }
936
+
937
+ .menu-button:focus-visible {
938
+ outline: 2px solid var(--app-link);
939
+ outline-offset: 2px;
940
+ }
941
+
942
+ #skip_navigation_link {
943
+ position: fixed;
944
+ top: -100px;
945
+ left: -100px;
946
+ z-index: 1001;
947
+ width: 1px;
948
+ height: 1px;
949
+ overflow: hidden;
950
+ clip: rect(0, 0, 0, 0);
951
+ border: 0;
952
+ padding: 0;
953
+ margin: 0;
954
+ }
955
+
956
+ #skip_navigation_link:focus {
957
+ top: 0;
958
+ left: 0;
959
+ overflow: visible;
960
+ clip: auto;
961
+ border: 1px dotted;
962
+ padding: 4px 8px;
963
+ margin: 4px;
964
+ width: 80px;
965
+ height: auto;
966
+ background-color: var(--app-link);
967
+ color: var(--app-white);
968
+ text-align: center;
969
+ }
970
+ </style>
971
+
972
+ <div class="app-nav-container">
973
+ <a href="#content" id="skip_navigation_link">Skip To Content</a>
974
+ <div class="nav-items">
975
+ ${this.navItems.map((t) => {
976
+ if (t.type === "divider")
977
+ return '<div style="height: 1px; background: var(--app-300); margin: 0.5rem 0;"></div>';
978
+ const i = t.avatar?.src || "", e = t.avatar?.name || "";
979
+ return `<eui-nav-item path="${t.path}" icon="${t.icon}" avatar-src="${i}" avatar-name="${e}" label="${t.label}"></eui-nav-item>`;
980
+ }).join("")}
981
+ </div>
982
+ </div>
983
+ `;
984
+ }
985
+ set navItems(t) {
986
+ this._navItems = t, this.render(), this.updateActiveState();
987
+ }
988
+ get navItems() {
989
+ return this._navItems || [];
990
+ }
991
+ updateActiveState(t) {
992
+ t || (t = k.location()), t.startsWith("/") || (t = "/" + t), this.shadowRoot.querySelectorAll("eui-nav-item").forEach((e) => {
993
+ e.getAttribute("path") === t ? e.setAttribute("active", "") : e.removeAttribute("active");
994
+ });
995
+ }
996
+ }
997
+ customElements.define("eui-app-nav", _);
998
+ class I extends HTMLElement {
999
+ static get observedAttributes() {
1000
+ return ["type", "title", "subtitle", "img"];
1001
+ }
1002
+ constructor() {
1003
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
1004
+ <style>
1005
+ :host {
1006
+ border-radius: 24px;
1007
+ background: var(--app-200, #111);
1008
+ color: var(--app-text, #FFF);
1009
+ overflow: hidden;
1010
+ display: block;
1011
+ }
1012
+
1013
+ .header {
1014
+ min-height: 180px;
1015
+ display: flex;
1016
+ flex-direction: column;
1017
+ justify-content: center;
1018
+ padding: 48px;
1019
+ box-sizing: border-box;
1020
+ position: relative;
1021
+ }
1022
+
1023
+ .hero {
1024
+ min-height: 280px;
1025
+ display: flex;
1026
+ flex-direction: column;
1027
+ justify-content: flex-end;
1028
+ color: #fff;
1029
+ background: #333;
1030
+ }
1031
+
1032
+ .img {
1033
+ position: absolute;
1034
+ inset: 0;
1035
+ background-size: cover;
1036
+ background-position: center;
1037
+ z-index: 0;
1038
+ opacity: .5;
1039
+ }
1040
+
1041
+ .content {
1042
+ position: relative;
1043
+ z-index: 1;
1044
+ }
1045
+
1046
+ h1 {
1047
+ margin: 0 0 8px;
1048
+ font-size: 3rem;
1049
+ }
1050
+
1051
+ .large h1, .hero h1 {
1052
+ font-size: 5.5rem;
1053
+ }
1054
+
1055
+ .small h1 {
1056
+ font-size: 2rem;
1057
+ margin: 0;
1058
+ }
1059
+
1060
+ .small p {
1061
+ margin: 0;
1062
+ }
1063
+ </style>
1064
+
1065
+ <div class="header">
1066
+ <div class="img"></div>
1067
+ <div class="content">
1068
+ <h1></h1>
1069
+ <p></p>
1070
+ </div>
1071
+ </div>
1072
+ `;
1073
+ }
1074
+ connectedCallback() {
1075
+ this.hd = this.shadowRoot.querySelector(".header"), this.hasAttribute("type") && this.hd.classList.add(this.getAttribute("type"));
1076
+ }
1077
+ attributeChangedCallback(t, i, e) {
1078
+ const r = this.shadowRoot.querySelector("h1"), n = this.shadowRoot.querySelector("p"), a = this.shadowRoot.querySelector(".img");
1079
+ t === "title" && (r.textContent = e), t === "subtitle" && (n.textContent = e), t === "img" && (a.style.backgroundImage = e ? `url(${e})` : "");
1080
+ }
1081
+ }
1082
+ customElements.define("eui-header", I);
1083
+ class F extends HTMLElement {
1084
+ static get observedAttributes() {
1085
+ return ["selected"];
1086
+ }
1087
+ constructor() {
1088
+ super(), this.attachShadow({ mode: "open" }), this.shadowRoot.innerHTML = `
1089
+ <style>
1090
+ :host {
1091
+ display: block;
1092
+ position: relative;
1093
+ cursor: pointer;
1094
+ width: 24px;
1095
+ height: 24px;
1096
+ }
1097
+
1098
+ .checkbox {
1099
+ position: relative;
1100
+ width: 24px;
1101
+ height: 24px;
1102
+ display: flex;
1103
+ align-items: center;
1104
+ justify-content: center;
1105
+ border-radius: 4px;
1106
+ box-shadow: inset 0px 0px 0px 2px var(--app-400);
1107
+
1108
+ color: #fff;
1109
+ }
1110
+
1111
+ .checkbox.selected, .checkbox.indeterminate {
1112
+ background-color: var(--app-accent);
1113
+ box-shadow: none;
1114
+ }
1115
+
1116
+ input {
1117
+ appearance: none;
1118
+ opacity: 0;
1119
+ height: max(100%, var(--eui-switch-touch-target-size, 48px));
1120
+ width: max(100%, var(--eui-switch-touch-target-size, 48px));
1121
+ position: absolute;
1122
+ margin: 0;
1123
+ cursor: inherit;
1124
+ top: 50%;
1125
+ left: 50%;
1126
+ transform: translate(-50%, -50%);
1127
+ z-index: 2;
1128
+ }
1129
+
1130
+ .mark.long {
1131
+ height:2px;
1132
+ transition-property:transform,width;
1133
+ width:0px;
1134
+ }
1135
+
1136
+ .mark.short {
1137
+ height: 2px;
1138
+ transition-property: transform,height;
1139
+ width: 0px;
1140
+ }
1141
+
1142
+ .mark {
1143
+ fill: #fff;
1144
+ transform: scaleY(-1) translate(7px, -14px) rotate(45deg);
1145
+ }
1146
+
1147
+ .selected .mark.long {
1148
+ animation-duration: 350ms;
1149
+ animation-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1);
1150
+ transition-duration: 350ms;
1151
+ transition-timing-function: cubic-bezier(0.05, 0.7, 0.1, 1);
1152
+ }
1153
+
1154
+ .selected .mark.short {
1155
+ width: 2px;
1156
+ height: 5.6568542495px;
1157
+ }
1158
+
1159
+ .selected .mark.long{
1160
+ width: 11.313708499px;
1161
+ }
1162
+ </style>
1163
+
1164
+ <div class="checkbox">
1165
+ <input type="checkbox" role="checkbox">
1166
+ <svg class="icon" viewBox="0 0 18 18" aria-hidden="true">
1167
+ <rect class="mark short"></rect>
1168
+ <rect class="mark long"></rect>
1169
+ </svg>
1170
+ </div>
1171
+ `;
1172
+ }
1173
+ connectedCallback() {
1174
+ this.inputEl = this.shadowRoot.querySelector("input"), this.checkEl = this.shadowRoot.querySelector(".checkbox"), this.updateFromAttribute(), this.checkEl.addEventListener("click", () => this.toggle());
1175
+ }
1176
+ toggle() {
1177
+ this.selected = !this.selected, v();
1178
+ const t = this.selected, i = this.dataset.setting;
1179
+ i && y.set(i, t);
1180
+ }
1181
+ updateFromAttribute() {
1182
+ const t = this.hasAttribute("selected");
1183
+ this.inputEl.checked = t, this.checkEl.classList.toggle("selected", t);
1184
+ }
1185
+ attributeChangedCallback(t, i, e) {
1186
+ t === "selected" && this.inputEl && this.updateFromAttribute();
1187
+ }
1188
+ get selected() {
1189
+ return this.hasAttribute("selected");
1190
+ }
1191
+ set selected(t) {
1192
+ t ? this.setAttribute("selected", "") : this.removeAttribute("selected");
1193
+ }
1194
+ }
1195
+ customElements.define("eui-checkbox", F);
1196
+ class q extends HTMLElement {
1197
+ static observedAttributes = ["type", "width", "height", "border-radius", "icon", "link", "href"];
1198
+ constructor() {
1199
+ super(), this.attachShadow({ mode: "open" });
1200
+ }
1201
+ connectedCallback() {
1202
+ this.render();
1203
+ }
1204
+ render() {
1205
+ const t = this.getAttribute("href"), i = t ? "a" : "button";
1206
+ this.shadowRoot.innerHTML = `
1207
+ <style>
1208
+ button, a {
1209
+ display: flex;
1210
+ justify-content: center;
1211
+ align-items: center;
1212
+ gap: 0.25rem;
1213
+ padding: 0.5rem 1rem;
1214
+ font-size: 1rem;
1215
+ font-weight: 600;
1216
+ font-family: inherit;
1217
+ border-radius: 0.6rem;
1218
+ border: none;
1219
+ background: var(--app-300);
1220
+ color: var(--app-text, #FFF);
1221
+ cursor: pointer;
1222
+ box-sizing: border-box;
1223
+ text-decoration: none;
1224
+
1225
+ width: fit-content;
1226
+
1227
+ user-select: none;
1228
+ -webkit-user-select: none;
1229
+ -moz-user-select: none;
1230
+ -ms-user-select: none;
1231
+
1232
+ transition: background 0.2s cubic-bezier(.2,0,0,1);
1233
+
1234
+ position: relative;
1235
+ overflow: hidden;
1236
+ }
1237
+
1238
+ button:hover, a:hover {
1239
+ background: var(--app-400);
1240
+ text-decoration: none;
1241
+ }
1242
+
1243
+ .light button, .light a {
1244
+ background: var(--app-500);
1245
+ }
1246
+
1247
+ button.filled, a.filled {
1248
+ background: var(--app-accent-100);
1249
+ color: #fff;
1250
+ }
1251
+
1252
+ button.filled:hover, a.filled:hover {
1253
+ background: var(--app-accent-50);
1254
+ }
1255
+
1256
+ button.outlined, a.outlined {
1257
+ background: transparent;
1258
+ box-shadow: inset 0 0 0 2px var(--app-400);
1259
+ color: var(--app-accent-100);
1260
+ }
1261
+
1262
+ button.outlined:hover, a.outlined:hover {
1263
+ background: var(--app-300);
1264
+ }
1265
+
1266
+ button.icon, a.icon {
1267
+ padding: 0.5rem;
1268
+ border-radius: 50%;
1269
+ }
1270
+
1271
+ button.transparent, a.transparent {
1272
+ background: transparent;
1273
+ color: var(--app-text);
1274
+ }
1275
+
1276
+ button.transparent:hover, a.transparent:hover {
1277
+ background: var(--app-300);
1278
+ }
1279
+
1280
+ button:disabled, a[disabled] {
1281
+ opacity: 0.5;
1282
+ cursor: not-allowed;
1283
+ }
1284
+
1285
+ button.link, a.link {
1286
+ text-decoration: none;
1287
+ }
1288
+
1289
+ .ripple {
1290
+ position: absolute;
1291
+ border-radius: 50%;
1292
+ transform: scale(0);
1293
+ opacity: 0.2;
1294
+ animation: ripple 600ms linear forwards;
1295
+ background-color: currentColor;
1296
+ pointer-events: none;
1297
+ z-index: 10;
1298
+ will-change: transform, opacity;
1299
+ }
1300
+
1301
+ @keyframes ripple {
1302
+ to {
1303
+ transform: scale(4);
1304
+ opacity: 0;
1305
+ }
1306
+ }
1307
+
1308
+ </style>
1309
+ <${i}>
1310
+ <slot></slot>
1311
+ </${i}>
1312
+ `;
1313
+ const e = this.shadowRoot.querySelector(i);
1314
+ t && e.setAttribute("href", t), this.hasAttribute("type") && e.classList.add(this.getAttribute("type")), this.hasAttribute("icon") && e.classList.add("icon"), this.hasAttribute("width") && (e.style.width = this.getAttribute("width") + "px"), this.hasAttribute("height") && (e.style.height = this.getAttribute("height") + "px"), this.hasAttribute("border-radius") && (e.style.borderRadius = this.getAttribute("border-radius") + "px"), e.addEventListener("pointerdown", (r) => {
1315
+ const n = document.createElement("span"), a = r.currentTarget, l = a.getBoundingClientRect(), c = Math.max(a.offsetWidth, a.offsetHeight), s = c / 2;
1316
+ n.classList.add("ripple"), n.style.width = `${c}px`, n.style.height = `${c}px`, n.style.left = `${r.clientX - l.left - s}px`, n.style.top = `${r.clientY - l.top - s}px`, e.appendChild(n), n.addEventListener("animationend", () => {
1317
+ n.remove();
1318
+ });
1319
+ });
1320
+ }
1321
+ }
1322
+ customElements.define("eui-button", q);
1323
+ class j extends HTMLElement {
1324
+ static get observedAttributes() {
1325
+ return ["type", "anchor"];
1326
+ }
1327
+ constructor() {
1328
+ super(), this.attachShadow({ mode: "open" });
1329
+ }
1330
+ connectedCallback() {
1331
+ this.render(), this.hd = this.shadowRoot.querySelector(".hd"), this.hasAttribute("type") && this.hd.classList.add(this.getAttribute("type"));
1332
+ }
1333
+ render() {
1334
+ this.shadowRoot.innerHTML = `
1335
+ <style>
1336
+ :host {
1337
+ display: block;
1338
+ position: relative;
1339
+ margin: 16px 0;
1340
+ }
1341
+
1342
+ .hd {
1343
+ font-size: 2.5rem;
1344
+ font-weight: 600;
1345
+ margin: 0;
1346
+ }
1347
+
1348
+ .h2 {
1349
+ font-size: 2rem;
1350
+ }
1351
+
1352
+ .h3 {
1353
+ font-size: 1.5rem;
1354
+ }
1355
+
1356
+ .anchor {
1357
+ position: absolute;
1358
+ width: 100%;
1359
+ height: 100%;
1360
+
1361
+ inset: 0;
1362
+ inset-inline-start: -24px;
1363
+ opacity: 0;
1364
+ transition: opacity .25s var(--transition-function);
1365
+
1366
+ display: flex;
1367
+ align-items: center;
1368
+
1369
+ text-decoration: none;
1370
+ color: var(--app-accent);
1371
+ font-size: 1.5rem;
1372
+ }
1373
+
1374
+ .anchor:hover {
1375
+ opacity: 1;
1376
+ }
1377
+
1378
+ .anchor-hash {
1379
+ margin-inline-end: 8px;
1380
+ font-weight: 700;
1381
+ }
1382
+ </style>
1383
+
1384
+ <span class="hd">
1385
+ <slot></slot>
1386
+ </span>
1387
+ ${this.getAttribute("anchor") ? `
1388
+ <a class="anchor" href="#${this.getAttribute("anchor")}" id="${this.getAttribute("anchor")}">
1389
+ <span class="anchor-hash">#</span>
1390
+ </a>
1391
+ ` : ""}
1392
+ `;
1393
+ }
1394
+ }
1395
+ customElements.define("eui-heading", j);
1396
+ function N(o) {
1397
+ const e = Date.now() - o, r = Math.floor(e / 1e3), n = Math.floor(r / 60), a = Math.floor(n / 60), l = Math.floor(a / 24), c = Math.floor(l / 30), s = Math.floor(c / 12);
1398
+ return s > 0 ? `${s}y` : c > 0 ? `${c}mo` : l > 0 ? `${l}d` : a > 0 ? `${a}h` : n > 0 ? `${n}m` : `${r}s`;
1399
+ }
1400
+ function B(o) {
1401
+ const e = Date.now() - o, r = Math.floor(e / 1e3), n = Math.floor(r / 60), a = Math.floor(n / 60), l = Math.floor(a / 24), c = Math.floor(l / 30), s = Math.floor(c / 12);
1402
+ return s > 0 ? `${s} year${s > 1 ? "s" : ""} ago` : c > 0 ? `${c} month${c > 1 ? "s" : ""} ago` : l > 0 ? `${l} day${l > 1 ? "s" : ""} ago` : a > 0 ? `${a} hour${a > 1 ? "s" : ""} ago` : n > 0 ? `${n} minute${n > 1 ? "s" : ""} ago` : `${r} second${r > 1 ? "s" : ""} ago`;
1403
+ }
1404
+ function O(o) {
1405
+ return o.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;").replace(/`/g, "&#96;").replace(/'/g, "&#39;");
1406
+ }
1407
+ function E(o) {
1408
+ const t = document.createElement("input");
1409
+ t.value = o, document.body.appendChild(t), t.select(), document.execCommand("copy"), document.body.removeChild(t);
1410
+ }
1411
+ const Y = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1412
+ __proto__: null,
1413
+ copystr: E,
1414
+ joinedAgo: B,
1415
+ sanitize: O,
1416
+ timeAgo: N
1417
+ }, Symbol.toStringTag, { value: "Module" }));
1418
+ class P extends HTMLElement {
1419
+ static get observedAttributes() {
1420
+ return ["copy", "id", "type"];
1421
+ }
1422
+ constructor() {
1423
+ super(), this.attachShadow({ mode: "open" }), this._boundCopy = this._onCopy.bind(this), this._isRendered = !1;
1424
+ }
1425
+ connectedCallback() {
1426
+ this._isRendered || (this.render(), this._isRendered = !0);
1427
+ }
1428
+ render() {
1429
+ const t = this.hasAttribute("copy");
1430
+ this.shadowRoot.innerHTML = `
1431
+ <style>
1432
+ :host {
1433
+ position: relative;
1434
+ display: block;
1435
+ }
1436
+
1437
+ pre {
1438
+ padding: 20px;
1439
+ background: var(--app-100);
1440
+ border: 1px solid var(--app-300);
1441
+ border-radius: 20px;
1442
+ font-family: 'Reddit Mono', consolas;
1443
+ overflow-x: auto;
1444
+ line-height: 1.25;
1445
+ white-space: pre;
1446
+ }
1447
+
1448
+ .copy {
1449
+ position: absolute;
1450
+ top: 8px;
1451
+ right: 8px;
1452
+ }
1453
+ pre.g {
1454
+ padding-right: 60px;
1455
+ }
1456
+ </style>
1457
+
1458
+ <eui-button class="copy" width="45" height="45" border-radius="100">
1459
+ <eui-icon name="copy" width="24" height="24"></eui-icon>
1460
+ </eui-button>
1461
+
1462
+ <pre class="${t ? "g" : ""}"><code></code></pre>
1463
+ `, this.copyBtn = this.shadowRoot.querySelector(".copy"), this.codeEl = this.shadowRoot.querySelector("code"), this.codeEl.textContent = this._getFormattedText(), t ? this.copyBtn.addEventListener("click", this._boundCopy) : this.copyBtn.style.display = "none";
1464
+ }
1465
+ _getFormattedText() {
1466
+ let t = this.textContent || "";
1467
+ t = t.replace(/^\s*\n/, "").replace(/\n\s*$/, ""), t = t.replace(/[ \t]+$/gm, "");
1468
+ const i = t.split(`
1469
+ `), e = i.filter((n) => n.trim()).map((n) => n.match(/^\s*/)[0].length), r = e.length ? Math.min(...e) : 0;
1470
+ return t = i.map((n) => n.slice(r)).join(`
1471
+ `), t;
1472
+ }
1473
+ _onCopy() {
1474
+ E(this._getFormattedText());
1475
+ }
1476
+ disconnectedCallback() {
1477
+ this.copyBtn && this.copyBtn.removeEventListener("click", this._boundCopy);
1478
+ }
1479
+ }
1480
+ customElements.define("eui-code", P);
1481
+ class U extends HTMLElement {
1482
+ constructor() {
1483
+ super(), this.attachShadow({ mode: "open" });
1484
+ }
1485
+ connectedCallback() {
1486
+ this.render(), this.setupEventListeners();
1487
+ }
1488
+ static get observedAttributes() {
1489
+ return ["name"];
1490
+ }
1491
+ attributeChangedCallback(t, i, e) {
1492
+ t === "name" && (this.render(), this.setupEventListeners());
1493
+ }
1494
+ setupEventListeners() {
1495
+ const t = this.shadowRoot.querySelector("#nav-toggle");
1496
+ t && t.addEventListener("click", () => {
1497
+ window.dispatchEvent(new CustomEvent("toggle-nav"));
1498
+ });
1499
+ }
1500
+ render() {
1501
+ const t = this.getAttribute("name") || "Title";
1502
+ this.shadowRoot.innerHTML = `
1503
+ <style>
1504
+ :host {
1505
+ display: block;
1506
+ width: 100%;
1507
+ height: var(--titlebar-height, 65px);
1508
+ background-color: var(--app-200);
1509
+ flex-shrink: 0;
1510
+ position: fixed;
1511
+ top: 0;
1512
+ left: 0;
1513
+ z-index: 200;
1514
+ box-sizing: border-box;
1515
+ }
1516
+
1517
+ .titlebar {
1518
+ height: 100%;
1519
+ display: flex;
1520
+ align-items: center;
1521
+ justify-content: space-between;
1522
+ box-sizing: border-box;
1523
+ }
1524
+
1525
+ .left-section {
1526
+ display: flex;
1527
+ align-items: center;
1528
+ }
1529
+
1530
+ .title {
1531
+ font-size: 1.25rem;
1532
+ font-weight: 400;
1533
+ color: var(--app-text);
1534
+ margin: 0;
1535
+ user-select: none;
1536
+ }
1537
+
1538
+ .menu-button {
1539
+ border: none;
1540
+ background-color: transparent;
1541
+ cursor: pointer;
1542
+ width: 42px;
1543
+ height: 42px;
1544
+ display: flex;
1545
+ align-items: center;
1546
+ justify-content: center;
1547
+ box-sizing: border-box;
1548
+ border-radius: 50%;
1549
+ color: inherit;
1550
+ padding: 0;
1551
+ }
1552
+
1553
+ .menu-button:hover {
1554
+ background-color: var(--app-300);
1555
+ }
1556
+
1557
+ .menu-button:active {
1558
+ transform: scale(0.95);
1559
+ }
1560
+
1561
+ .menu-button:focus-visible {
1562
+ outline: 2px solid var(--app-link);
1563
+ outline-offset: 2px;
1564
+ }
1565
+
1566
+ .right-section {
1567
+ display: flex;
1568
+ align-items: center;
1569
+ padding-right: 1rem;
1570
+ }
1571
+
1572
+ .nav-section {
1573
+ width: var(--nav-width, 75px);
1574
+
1575
+ display: flex;
1576
+ align-items: center;
1577
+ justify-content: center;
1578
+ }
1579
+ </style>
1580
+
1581
+ <div class="titlebar">
1582
+ <div class="left-section">
1583
+ <div class="nav-section">
1584
+ <eui-button class="menu-button" id="nav-toggle" aria-label="Toggle Navigation" aria-expanded="false" aria-controls="nav-items" tabindex="0" type="transparent" border-radius="100">
1585
+ <eui-icon width="24" height="24" name="menu"></eui-icon>
1586
+ </eui-button>
1587
+ </div>
1588
+ <h2 class="title">${t}</h2>
1589
+ </div>
1590
+ <div class="right-section">
1591
+ <slot></slot>
1592
+ </div>
1593
+ </div>
1594
+ `;
1595
+ }
1596
+ }
1597
+ customElements.define("eui-app-titlebar", U);
1598
+ class D extends HTMLElement {
1599
+ constructor() {
1600
+ super(), this.attachShadow({ mode: "open" }), this._handleMouseDown = this._addRipple.bind(this);
1601
+ }
1602
+ connectedCallback() {
1603
+ this.render(), this.setupEventListeners();
1604
+ }
1605
+ static get observedAttributes() {
1606
+ return ["elevated", "interactive", "ripple"];
1607
+ }
1608
+ attributeChangedCallback(t, i, e) {
1609
+ i !== e && t === "ripple" && this.setupEventListeners();
1610
+ }
1611
+ setupEventListeners() {
1612
+ this.removeEventListener("mousedown", this._handleMouseDown), this.hasAttribute("ripple") && this.addEventListener("mousedown", this._handleMouseDown);
1613
+ }
1614
+ _addRipple(t) {
1615
+ const i = this.getBoundingClientRect(), e = document.createElement("span"), r = Math.max(i.width, i.height), n = r / 2;
1616
+ e.style.width = e.style.height = `${r}px`, e.style.left = `${t.clientX - i.left - n}px`, e.style.top = `${t.clientY - i.top - n}px`, e.classList.add("ripple"), this.shadowRoot.querySelector(".surface").appendChild(e), e.addEventListener("animationend", () => {
1617
+ e.remove();
1618
+ });
1619
+ }
1620
+ render() {
1621
+ this.shadowRoot.innerHTML = `
1622
+ <style>
1623
+ :host {
1624
+ display: block;
1625
+ border-radius: 12px;
1626
+ background-color: var(--app-200);
1627
+ transition: background-color 0.2s cubic-bezier(.4, 0, .2, 1),
1628
+ box-shadow 0.2s cubic-bezier(.4, 0, .2, 1);
1629
+ overflow: hidden;
1630
+ position: relative;
1631
+ height: auto;
1632
+ z-index: 1;
1633
+ }
1634
+
1635
+ :host([elevated]) {
1636
+ background-color: var(--app-100);
1637
+ box-shadow: inset 0 0 0 1px var(--app-300);
1638
+ }
1639
+
1640
+ :host([interactive]) {
1641
+ cursor: pointer;
1642
+ }
1643
+
1644
+ :host([interactive]:hover) {
1645
+ background-color: var(--app-300);
1646
+ }
1647
+
1648
+ :host([interactive][elevated]:hover) {
1649
+ background-color: var(--app-100);
1650
+ box-shadow: inset 0 0 0 1px var(--app-300), 0 4px 12px rgba(0,0,0,0.1);
1651
+ }
1652
+
1653
+ .surface {
1654
+ position: relative;
1655
+ z-index: 2;
1656
+ width: 100%;
1657
+ height: 100%;
1658
+ }
1659
+
1660
+ .ripple {
1661
+ position: absolute;
1662
+ border-radius: 50%;
1663
+ transform: scale(0);
1664
+ opacity: 0.2;
1665
+ animation: ripple 600ms linear forwards;
1666
+ background-color: currentColor;
1667
+ pointer-events: none;
1668
+ z-index: -1;
1669
+ will-change: transform, opacity;
1670
+ }
1671
+
1672
+ @keyframes ripple {
1673
+ to {
1674
+ transform: scale(4);
1675
+ opacity: 0;
1676
+ }
1677
+ }
1678
+ </style>
1679
+ <div class="surface">
1680
+ <slot></slot>
1681
+ </div>
1682
+ `;
1683
+ }
1684
+ }
1685
+ customElements.define("eui-surface", D);
1686
+ typeof window < "u" && console.log("ErisUI loaded successfully");
1687
+ export {
1688
+ X as device,
1689
+ W as haptics,
1690
+ V as loadPage,
1691
+ k as router,
1692
+ J as storage,
1693
+ Y as utils
1694
+ };