@ryanhelsing/ry-ui 1.0.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.
Files changed (63) hide show
  1. package/README.md +223 -0
  2. package/dist/components/ry-accordion.d.ts +24 -0
  3. package/dist/components/ry-accordion.d.ts.map +1 -0
  4. package/dist/components/ry-alert.d.ts +19 -0
  5. package/dist/components/ry-alert.d.ts.map +1 -0
  6. package/dist/components/ry-button.d.ts +19 -0
  7. package/dist/components/ry-button.d.ts.map +1 -0
  8. package/dist/components/ry-code.d.ts +27 -0
  9. package/dist/components/ry-code.d.ts.map +1 -0
  10. package/dist/components/ry-color-input.d.ts +28 -0
  11. package/dist/components/ry-color-input.d.ts.map +1 -0
  12. package/dist/components/ry-color-picker.d.ts +52 -0
  13. package/dist/components/ry-color-picker.d.ts.map +1 -0
  14. package/dist/components/ry-drawer.d.ts +28 -0
  15. package/dist/components/ry-drawer.d.ts.map +1 -0
  16. package/dist/components/ry-dropdown.d.ts +24 -0
  17. package/dist/components/ry-dropdown.d.ts.map +1 -0
  18. package/dist/components/ry-example.d.ts +23 -0
  19. package/dist/components/ry-example.d.ts.map +1 -0
  20. package/dist/components/ry-field.d.ts +18 -0
  21. package/dist/components/ry-field.d.ts.map +1 -0
  22. package/dist/components/ry-icon.d.ts +27 -0
  23. package/dist/components/ry-icon.d.ts.map +1 -0
  24. package/dist/components/ry-knob.d.ts +27 -0
  25. package/dist/components/ry-knob.d.ts.map +1 -0
  26. package/dist/components/ry-modal.d.ts +23 -0
  27. package/dist/components/ry-modal.d.ts.map +1 -0
  28. package/dist/components/ry-select.d.ts +29 -0
  29. package/dist/components/ry-select.d.ts.map +1 -0
  30. package/dist/components/ry-slider.d.ts +30 -0
  31. package/dist/components/ry-slider.d.ts.map +1 -0
  32. package/dist/components/ry-switch.d.ts +22 -0
  33. package/dist/components/ry-switch.d.ts.map +1 -0
  34. package/dist/components/ry-tabs.d.ts +21 -0
  35. package/dist/components/ry-tabs.d.ts.map +1 -0
  36. package/dist/components/ry-theme-toggle.d.ts +21 -0
  37. package/dist/components/ry-theme-toggle.d.ts.map +1 -0
  38. package/dist/components/ry-toast.d.ts +31 -0
  39. package/dist/components/ry-toast.d.ts.map +1 -0
  40. package/dist/components/ry-toggle-button.d.ts +31 -0
  41. package/dist/components/ry-toggle-button.d.ts.map +1 -0
  42. package/dist/components/ry-tooltip.d.ts +23 -0
  43. package/dist/components/ry-tooltip.d.ts.map +1 -0
  44. package/dist/core/ry-element.d.ts +66 -0
  45. package/dist/core/ry-element.d.ts.map +1 -0
  46. package/dist/core/ry-icons.d.ts +38 -0
  47. package/dist/core/ry-icons.d.ts.map +1 -0
  48. package/dist/core/ry-transform.d.ts +35 -0
  49. package/dist/core/ry-transform.d.ts.map +1 -0
  50. package/dist/css/ry-base.css +155 -0
  51. package/dist/css/ry-components.css +1195 -0
  52. package/dist/css/ry-layout.css +240 -0
  53. package/dist/css/ry-structure.css +1737 -0
  54. package/dist/css/ry-theme.css +1433 -0
  55. package/dist/css/ry-tokens.css +145 -0
  56. package/dist/css/ry-ui.css +1207 -0
  57. package/dist/ry-ui.d.ts +54 -0
  58. package/dist/ry-ui.d.ts.map +1 -0
  59. package/dist/ry-ui.js +2433 -0
  60. package/dist/ry-ui.js.map +1 -0
  61. package/dist/types.d.ts +33 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/package.json +40 -0
package/dist/ry-ui.js ADDED
@@ -0,0 +1,2433 @@
1
+ class d extends HTMLElement {
2
+ // Store for cleanup functions
3
+ #t = [];
4
+ // Store for MutationObserver
5
+ #e = null;
6
+ constructor() {
7
+ super();
8
+ }
9
+ /**
10
+ * Called when element is added to DOM.
11
+ * Override setup() in subclass instead of this.
12
+ */
13
+ connectedCallback() {
14
+ this.setAttribute("data-ry-initialized", ""), this.setup?.();
15
+ }
16
+ /**
17
+ * Called when element is removed from DOM.
18
+ * Automatically cleans up event listeners and observers.
19
+ */
20
+ disconnectedCallback() {
21
+ this.#t.forEach((t) => t()), this.#t = [], this.#e && (this.#e.disconnect(), this.#e = null), this.teardown?.();
22
+ }
23
+ on(t, e, s, i = {}) {
24
+ const r = s.bind(this);
25
+ return t.addEventListener(e, r, i), this.#t.push(() => {
26
+ t.removeEventListener(e, r, i);
27
+ }), r;
28
+ }
29
+ /**
30
+ * Emit a custom event with ry: prefix.
31
+ */
32
+ emit(t, e, s = {}) {
33
+ const i = new CustomEvent(`ry:${t}`, {
34
+ bubbles: !0,
35
+ cancelable: !0,
36
+ detail: e,
37
+ ...s
38
+ });
39
+ return this.dispatchEvent(i);
40
+ }
41
+ /**
42
+ * Get/set component state via data attribute.
43
+ */
44
+ get state() {
45
+ return this.dataset.ryState ?? "closed";
46
+ }
47
+ set state(t) {
48
+ const e = this.state;
49
+ e !== t && (this.dataset.ryState = t, this.emit("state-change", { oldState: e, newState: t }));
50
+ }
51
+ /**
52
+ * Query within this element.
53
+ */
54
+ $(t) {
55
+ return this.querySelector(t);
56
+ }
57
+ /**
58
+ * Query all within this element.
59
+ */
60
+ $$(t) {
61
+ return [...this.querySelectorAll(t)];
62
+ }
63
+ /**
64
+ * Setup a MutationObserver on this element.
65
+ */
66
+ observe(t, e = { childList: !0, subtree: !0 }) {
67
+ this.#e && this.#e.disconnect(), this.#e = new MutationObserver(t.bind(this)), this.#e.observe(this, e);
68
+ }
69
+ /**
70
+ * Wait for next animation frame.
71
+ */
72
+ nextFrame() {
73
+ return new Promise((t) => requestAnimationFrame(t));
74
+ }
75
+ /**
76
+ * Trap focus within a container (for modals, dropdowns).
77
+ */
78
+ trapFocus(t) {
79
+ const e = [
80
+ "a[href]",
81
+ "button:not([disabled])",
82
+ "input:not([disabled])",
83
+ "select:not([disabled])",
84
+ "textarea:not([disabled])",
85
+ '[tabindex]:not([tabindex="-1"])'
86
+ ].join(","), s = t.querySelectorAll(e), i = s[0], r = s[s.length - 1], a = (n) => {
87
+ n.key === "Tab" && (n.shiftKey ? document.activeElement === i && (n.preventDefault(), r?.focus()) : document.activeElement === r && (n.preventDefault(), i?.focus()));
88
+ };
89
+ this.on(t, "keydown", a), i?.focus();
90
+ }
91
+ }
92
+ const C = [
93
+ // Layout
94
+ "page",
95
+ "header",
96
+ "main",
97
+ "footer",
98
+ "section",
99
+ "aside",
100
+ "grid",
101
+ "stack",
102
+ "cluster",
103
+ "split",
104
+ "center",
105
+ "nav",
106
+ "logo",
107
+ "actions",
108
+ // Components
109
+ "accordion",
110
+ "accordion-item",
111
+ "tabs",
112
+ "tab",
113
+ "modal",
114
+ "dropdown",
115
+ "menu",
116
+ "menu-item",
117
+ "drawer",
118
+ "toast",
119
+ "alert",
120
+ "card",
121
+ "button",
122
+ "badge",
123
+ "field",
124
+ "switch",
125
+ "tooltip",
126
+ "select",
127
+ "option",
128
+ "theme-toggle",
129
+ "divider",
130
+ "icon",
131
+ "example",
132
+ "toggle-button",
133
+ "slider",
134
+ "knob",
135
+ "color-picker",
136
+ "color-input"
137
+ ], S = new RegExp(
138
+ `<(/?)(${C.join("|")})(\\s|>|/)`,
139
+ "g"
140
+ );
141
+ function k(o) {
142
+ return o.replace(S, "<$1ry-$2$3");
143
+ }
144
+ function _() {
145
+ document.querySelectorAll("ry").forEach((o) => {
146
+ const t = k(o.innerHTML), e = document.createElement("template");
147
+ e.innerHTML = t, o.replaceWith(e.content);
148
+ }), document.querySelectorAll("template[ry]").forEach((o) => {
149
+ const t = k(o.innerHTML), e = document.createElement("template");
150
+ e.innerHTML = t, o.replaceWith(e.content);
151
+ });
152
+ }
153
+ document.readyState === "loading" ? document.addEventListener("DOMContentLoaded", _) : _();
154
+ class T extends d {
155
+ setup() {
156
+ this.#t(), this.$$('[data-ry-target="trigger"]').forEach((t) => {
157
+ this.on(t, "click", this.#i);
158
+ }), this.on(this, "keydown", this.#s), this.#e();
159
+ }
160
+ #t() {
161
+ this.$$("ry-accordion-item").forEach((t) => {
162
+ const e = t.getAttribute("title") ?? "Untitled", s = t.hasAttribute("open"), i = t.innerHTML;
163
+ t.outerHTML = `
164
+ <div data-ry-target="item" class="ry-accordion__item" data-ry-state="${s ? "open" : "closed"}">
165
+ <button data-ry-target="trigger" class="ry-accordion__trigger" aria-expanded="${s}">
166
+ ${e}
167
+ <span data-ry-target="icon" class="ry-accordion__icon">&#9660;</span>
168
+ </button>
169
+ <div data-ry-target="panel" class="ry-accordion__panel">
170
+ <div class="ry-accordion__content">${i}</div>
171
+ </div>
172
+ </div>
173
+ `;
174
+ });
175
+ }
176
+ #e() {
177
+ this.$$('[data-ry-target="item"]').forEach((t, e) => {
178
+ const s = t.querySelector('[data-ry-target="trigger"]'), i = t.querySelector('[data-ry-target="panel"]');
179
+ if (!s || !i) return;
180
+ const r = s.id || `ry-accordion-trigger-${this.id || ""}-${e}`, a = i.id || `ry-accordion-panel-${this.id || ""}-${e}`;
181
+ s.id = r, i.id = a, s.setAttribute("aria-controls", a), i.setAttribute("aria-labelledby", r), i.setAttribute("role", "region");
182
+ const n = t.dataset.ryState === "open";
183
+ s.setAttribute("aria-expanded", String(n));
184
+ });
185
+ }
186
+ #i = (t) => {
187
+ const s = t.currentTarget.closest('[data-ry-target="item"]');
188
+ s && this.toggle(s);
189
+ };
190
+ #s = (t) => {
191
+ const e = this.$$('[data-ry-target="trigger"]'), s = e.indexOf(document.activeElement);
192
+ if (s === -1) return;
193
+ let i;
194
+ switch (t.key) {
195
+ case "ArrowDown":
196
+ t.preventDefault(), i = (s + 1) % e.length, e[i]?.focus();
197
+ break;
198
+ case "ArrowUp":
199
+ t.preventDefault(), i = (s - 1 + e.length) % e.length, e[i]?.focus();
200
+ break;
201
+ case "Home":
202
+ t.preventDefault(), e[0]?.focus();
203
+ break;
204
+ case "End":
205
+ t.preventDefault(), e[e.length - 1]?.focus();
206
+ break;
207
+ }
208
+ };
209
+ toggle(t) {
210
+ t.dataset.ryState === "open" ? this.close(t) : this.open(t);
211
+ }
212
+ open(t) {
213
+ this.hasAttribute("multiple") || this.$$('[data-ry-target="item"][data-ry-state="open"]').forEach((s) => {
214
+ s !== t && this.close(s);
215
+ });
216
+ const e = t.querySelector('[data-ry-target="trigger"]');
217
+ t.dataset.ryState = "open", e?.setAttribute("aria-expanded", "true"), this.emit("open", { item: t });
218
+ }
219
+ close(t) {
220
+ const e = t.querySelector('[data-ry-target="trigger"]');
221
+ t.dataset.ryState = "closed", e?.setAttribute("aria-expanded", "false"), this.emit("close", { item: t });
222
+ }
223
+ openAll() {
224
+ this.$$('[data-ry-target="item"]').forEach((t) => this.open(t));
225
+ }
226
+ closeAll() {
227
+ this.$$('[data-ry-target="item"]').forEach((t) => this.close(t));
228
+ }
229
+ }
230
+ customElements.define("ry-accordion", T);
231
+ customElements.get("ry-accordion-item") || customElements.define("ry-accordion-item", class extends HTMLElement {
232
+ });
233
+ class H extends d {
234
+ #t = null;
235
+ #e = 0;
236
+ setup() {
237
+ this.#i();
238
+ const t = this.id;
239
+ t && (document.querySelectorAll(`[data-ry-modal-trigger="${t}"]`).forEach((s) => {
240
+ this.on(s, "click", () => this.open());
241
+ }), document.querySelectorAll(`ry-button[modal="${t}"], [modal="${t}"]`).forEach((s) => {
242
+ this.on(s, "click", () => this.open());
243
+ })), this.$$("[close]").forEach((s) => {
244
+ this.on(s, "click", () => this.close());
245
+ });
246
+ const e = this.$('[data-ry-target="backdrop"]');
247
+ e && this.on(e, "click", () => this.close()), this.on(document, "keydown", this.#s), this.#e = window.innerWidth - document.documentElement.clientWidth, this.hasAttribute("data-ry-state") || (this.state = "closed");
248
+ }
249
+ #i() {
250
+ if (this.$('[data-ry-target="dialog"]')) return;
251
+ const t = this.getAttribute("title") ?? "", s = this.$('[slot="footer"]')?.innerHTML ?? "", i = Array.from(this.childNodes).filter((r) => !(r instanceof Element && r.getAttribute("slot") === "footer")).map((r) => r instanceof Element ? r.outerHTML : r.textContent).join("");
252
+ this.innerHTML = `
253
+ <div data-ry-target="backdrop" class="ry-modal__backdrop"></div>
254
+ <div data-ry-target="dialog" class="ry-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="ry-modal-title-${this.id}">
255
+ <div data-ry-target="header" class="ry-modal__header">
256
+ <h3 class="ry-modal__title" id="ry-modal-title-${this.id}">${t}</h3>
257
+ <button data-ry-target="close" class="ry-modal__close" close aria-label="Close">&times;</button>
258
+ </div>
259
+ <div data-ry-target="body" class="ry-modal__body">${i}</div>
260
+ ${s ? `<div data-ry-target="footer" class="ry-modal__footer">${s}</div>` : ""}
261
+ </div>
262
+ `;
263
+ }
264
+ #s = (t) => {
265
+ t.key === "Escape" && this.state === "open" && this.close();
266
+ };
267
+ open() {
268
+ if (this.state === "open") return;
269
+ this.#t = document.activeElement, document.body.setAttribute("data-ry-scroll-lock", ""), document.body.style.setProperty("--ry-scrollbar-width", `${this.#e}px`), this.state = "open";
270
+ const t = this.$('[data-ry-target="dialog"]');
271
+ t && this.nextFrame().then(() => {
272
+ this.trapFocus(t);
273
+ }), this.emit("open");
274
+ }
275
+ close() {
276
+ this.state !== "closed" && (document.body.removeAttribute("data-ry-scroll-lock"), document.body.style.removeProperty("--ry-scrollbar-width"), this.state = "closed", this.#t instanceof HTMLElement && (this.#t.focus(), this.#t = null), this.emit("close"));
277
+ }
278
+ toggle() {
279
+ this.state === "open" ? this.close() : this.open();
280
+ }
281
+ }
282
+ customElements.define("ry-modal", H);
283
+ class L extends d {
284
+ setup() {
285
+ this.#t(), this.$$('[data-ry-target="trigger"]').forEach((t) => {
286
+ this.on(t, "click", this.#i);
287
+ }), this.on(this, "keydown", this.#s), this.#e();
288
+ }
289
+ #t() {
290
+ const t = this.$$("ry-tab");
291
+ if (t.length === 0) return;
292
+ const e = t.findIndex((r) => r.hasAttribute("active")), s = e === -1 ? 0 : e, i = document.createElement("div");
293
+ i.setAttribute("data-ry-target", "list"), i.className = "ry-tabs__list", i.setAttribute("role", "tablist"), t.forEach((r, a) => {
294
+ const n = r.getAttribute("title") ?? `Tab ${a + 1}`, l = a === s, h = document.createElement("button");
295
+ h.setAttribute("data-ry-target", "trigger"), h.className = "ry-tabs__trigger", h.setAttribute("role", "tab"), h.setAttribute("aria-selected", String(l)), h.textContent = n, i.appendChild(h), r.setAttribute("data-ry-target", "panel"), r.className = "ry-tabs__panel", r.setAttribute("role", "tabpanel"), r.dataset.ryState = l ? "active" : "", r.removeAttribute("title"), r.removeAttribute("active");
296
+ }), this.insertBefore(i, this.firstChild);
297
+ }
298
+ #e() {
299
+ const t = this.$$('[data-ry-target="trigger"]'), e = this.$$('[data-ry-target="panel"], ry-tab');
300
+ t.forEach((i, r) => {
301
+ const a = e[r];
302
+ if (!a) return;
303
+ const n = i.id || `ry-tab-${this.id || ""}-${r}`, l = a.id || `ry-tabpanel-${this.id || ""}-${r}`;
304
+ i.id = n, a.id = l, i.setAttribute("aria-controls", l), a.setAttribute("aria-labelledby", n), i.setAttribute("tabindex", i.getAttribute("aria-selected") === "true" ? "0" : "-1");
305
+ }), t.findIndex((i) => i.getAttribute("aria-selected") === "true") === -1 && t.length > 0 && this.select(0);
306
+ }
307
+ #i = (t) => {
308
+ const e = t.currentTarget, i = this.$$('[data-ry-target="trigger"]').indexOf(e);
309
+ i !== -1 && this.select(i);
310
+ };
311
+ #s = (t) => {
312
+ const e = this.$$('[data-ry-target="trigger"]'), s = e.indexOf(document.activeElement);
313
+ if (s === -1) return;
314
+ let i;
315
+ switch (t.key) {
316
+ case "ArrowRight":
317
+ t.preventDefault(), i = (s + 1) % e.length, this.select(i), e[i]?.focus();
318
+ break;
319
+ case "ArrowLeft":
320
+ t.preventDefault(), i = (s - 1 + e.length) % e.length, this.select(i), e[i]?.focus();
321
+ break;
322
+ case "Home":
323
+ t.preventDefault(), this.select(0), e[0]?.focus();
324
+ break;
325
+ case "End":
326
+ t.preventDefault(), this.select(e.length - 1), e[e.length - 1]?.focus();
327
+ break;
328
+ }
329
+ };
330
+ select(t) {
331
+ const e = this.$$('[data-ry-target="trigger"]'), s = this.$$('[data-ry-target="panel"], ry-tab');
332
+ if (t < 0 || t >= e.length) return;
333
+ e.forEach((a) => {
334
+ a.setAttribute("aria-selected", "false"), a.setAttribute("tabindex", "-1");
335
+ }), s.forEach((a) => {
336
+ a.dataset.ryState = "", a.removeAttribute("active");
337
+ });
338
+ const i = e[t], r = s[t];
339
+ i && r && (i.setAttribute("aria-selected", "true"), i.setAttribute("tabindex", "0"), r.dataset.ryState = "active", this.emit("change", { index: t, trigger: i, panel: r }));
340
+ }
341
+ get selectedIndex() {
342
+ return this.$$('[data-ry-target="trigger"]').findIndex((e) => e.getAttribute("aria-selected") === "true");
343
+ }
344
+ }
345
+ customElements.define("ry-tabs", L);
346
+ customElements.get("ry-tab") || customElements.define("ry-tab", class extends HTMLElement {
347
+ });
348
+ class I extends d {
349
+ setup() {
350
+ this.#t();
351
+ const t = this.$('[data-ry-target="trigger"]');
352
+ t && (this.on(t, "click", () => this.toggle()), t.setAttribute("aria-haspopup", "true"), t.setAttribute("aria-expanded", "false")), this.on(document, "click", this.#e), this.on(document, "keydown", this.#i), this.$$('[data-ry-target="item"], ry-menu-item').forEach((e) => {
353
+ this.on(e, "click", () => this.close());
354
+ }), this.state = "closed";
355
+ }
356
+ #t() {
357
+ const t = this.$('[slot="trigger"], ry-button:first-of-type');
358
+ t && !this.$('[data-ry-target="trigger"]') && t.setAttribute("data-ry-target", "trigger");
359
+ const e = this.$("ry-menu");
360
+ e && !e.hasAttribute("data-ry-target") && (e.setAttribute("data-ry-target", "menu"), e.classList.add("ry-dropdown__menu"), e.setAttribute("role", "menu")), this.$$("ry-menu-item").forEach((s) => {
361
+ s.hasAttribute("data-ry-target") || (s.setAttribute("data-ry-target", "item"), s.classList.add("ry-dropdown__item"), s.setAttribute("role", "menuitem"));
362
+ });
363
+ }
364
+ #e = (t) => {
365
+ const e = t.target;
366
+ this.state === "open" && !this.contains(e) && this.close();
367
+ };
368
+ #i = (t) => {
369
+ if (t.key === "Escape" && this.state === "open" && (this.close(), this.$('[data-ry-target="trigger"]')?.focus()), this.state === "open" && ["ArrowDown", "ArrowUp"].includes(t.key)) {
370
+ t.preventDefault();
371
+ const e = this.$$('[data-ry-target="item"], ry-menu-item'), s = e.indexOf(document.activeElement);
372
+ let i;
373
+ t.key === "ArrowDown" ? i = s < e.length - 1 ? s + 1 : 0 : i = s > 0 ? s - 1 : e.length - 1, e[i]?.focus();
374
+ }
375
+ };
376
+ open() {
377
+ if (this.state === "open") return;
378
+ this.$('[data-ry-target="trigger"]')?.setAttribute("aria-expanded", "true"), this.state = "open", this.nextFrame().then(() => {
379
+ this.$('[data-ry-target="item"], ry-menu-item')?.focus();
380
+ }), this.emit("open");
381
+ }
382
+ close() {
383
+ if (this.state === "closed") return;
384
+ this.$('[data-ry-target="trigger"]')?.setAttribute("aria-expanded", "false"), this.state = "closed", this.emit("close");
385
+ }
386
+ toggle() {
387
+ this.state === "open" ? this.close() : this.open();
388
+ }
389
+ }
390
+ customElements.define("ry-dropdown", I);
391
+ customElements.get("ry-menu") || customElements.define("ry-menu", class extends HTMLElement {
392
+ });
393
+ customElements.get("ry-menu-item") || customElements.define("ry-menu-item", class extends HTMLElement {
394
+ });
395
+ class D extends d {
396
+ setup() {
397
+ this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.setAttribute("role", "button"), this.on(this, "click", this.#t), this.on(this, "keydown", this.#e);
398
+ }
399
+ #t = (t) => {
400
+ if (this.hasAttribute("disabled")) {
401
+ t.preventDefault();
402
+ return;
403
+ }
404
+ this.emit("click", { originalEvent: t });
405
+ };
406
+ #e = (t) => {
407
+ (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this.click());
408
+ };
409
+ }
410
+ customElements.define("ry-button", D);
411
+ class F extends d {
412
+ #t = ["light", "dark"];
413
+ #e = 0;
414
+ setup() {
415
+ const t = this.getAttribute("themes");
416
+ t && (this.#t = t.split(",").map((s) => s.trim()));
417
+ const e = document.documentElement.dataset.ryTheme ?? "light";
418
+ this.#e = this.#t.indexOf(e), this.#e === -1 && (this.#e = 0), this.innerHTML.trim() || (this.innerHTML = `<button data-ry-target="button" class="ry-btn ry-btn--ghost">${this.#i()}</button>`), this.on(this, "click", () => this.toggle());
419
+ }
420
+ #i() {
421
+ switch (this.#t[this.#e]) {
422
+ case "dark":
423
+ return "&#9790;";
424
+ // Moon
425
+ case "ocean":
426
+ return "&#127754;";
427
+ // Wave
428
+ default:
429
+ return "&#9728;";
430
+ }
431
+ }
432
+ toggle() {
433
+ this.#e = (this.#e + 1) % this.#t.length;
434
+ const t = this.#t[this.#e];
435
+ document.documentElement.dataset.ryTheme = t;
436
+ const e = this.$('[data-ry-target="button"]');
437
+ e && (e.innerHTML = this.#i()), this.emit("theme-change", { theme: t });
438
+ }
439
+ get theme() {
440
+ return this.#t[this.#e] ?? "light";
441
+ }
442
+ set theme(t) {
443
+ const e = this.#t.indexOf(t);
444
+ if (e !== -1) {
445
+ this.#e = e, document.documentElement.dataset.ryTheme = t;
446
+ const s = this.$('[data-ry-target="button"]');
447
+ s && (s.innerHTML = this.#i());
448
+ }
449
+ }
450
+ }
451
+ customElements.define("ry-theme-toggle", F);
452
+ class B extends d {
453
+ setup() {
454
+ this.#t();
455
+ const t = this.$("[close]");
456
+ t && this.on(t, "click", () => this.dismiss());
457
+ }
458
+ #t() {
459
+ if (this.$('[data-ry-target="content"]')) return;
460
+ const t = this.getAttribute("variant") ?? "info", e = this.hasAttribute("dismissible"), s = this.innerHTML;
461
+ this.innerHTML = `
462
+ <div data-ry-target="content" class="ry-alert__content">${s}</div>
463
+ ${e ? '<button data-ry-target="close" class="ry-alert__close" close aria-label="Dismiss">&times;</button>' : ""}
464
+ `, this.setAttribute("role", "alert"), this.setAttribute("data-variant", t);
465
+ }
466
+ dismiss() {
467
+ this.state = "closed", setTimeout(() => {
468
+ this.remove();
469
+ }, 200), this.emit("close");
470
+ }
471
+ }
472
+ customElements.define("ry-alert", B);
473
+ class j extends d {
474
+ setup() {
475
+ this.#t();
476
+ }
477
+ #t() {
478
+ if (this.$('[data-ry-target="label"]')) return;
479
+ const t = this.getAttribute("label");
480
+ if (!t) return;
481
+ const e = this.$("input, textarea, select");
482
+ if (!e) return;
483
+ const s = e.id || `ry-field-${Math.random().toString(36).slice(2, 9)}`;
484
+ e.id = s;
485
+ const i = document.createElement("label");
486
+ i.setAttribute("data-ry-target", "label"), i.className = "ry-label", i.setAttribute("for", s), i.textContent = t, this.insertBefore(i, e);
487
+ }
488
+ }
489
+ customElements.define("ry-field", j);
490
+ let R = 0;
491
+ class P extends d {
492
+ #t = null;
493
+ static observedAttributes = ["checked", "disabled"];
494
+ setup() {
495
+ this.#e(), this.#t = this.$('input[type="checkbox"]'), this.#t && this.on(this.#t, "change", this.#i), this.on(this, "keydown", this.#s);
496
+ }
497
+ #e() {
498
+ if (this.$('[data-ry-target="track"]')) return;
499
+ const t = `ry-switch-${++R}`, e = this.getAttribute("name") ?? "", s = this.hasAttribute("checked"), i = this.hasAttribute("disabled"), r = this.textContent?.trim() ?? "";
500
+ this.innerHTML = `
501
+ <label data-ry-target="wrapper" class="ry-switch__wrapper" for="${t}">
502
+ <input
503
+ type="checkbox"
504
+ id="${t}"
505
+ data-ry-target="input"
506
+ class="ry-switch__input"
507
+ ${e ? `name="${e}"` : ""}
508
+ ${s ? "checked" : ""}
509
+ ${i ? "disabled" : ""}
510
+ role="switch"
511
+ aria-checked="${s}"
512
+ >
513
+ <span data-ry-target="track" class="ry-switch__track">
514
+ <span data-ry-target="thumb" class="ry-switch__thumb"></span>
515
+ </span>
516
+ ${r ? `<span data-ry-target="label" class="ry-switch__label">${r}</span>` : ""}
517
+ </label>
518
+ `;
519
+ }
520
+ #i = () => {
521
+ if (!this.#t) return;
522
+ const t = this.#t.checked;
523
+ this.#t.setAttribute("aria-checked", String(t)), t ? this.setAttribute("checked", "") : this.removeAttribute("checked"), this.emit("change", {
524
+ value: String(t),
525
+ label: t ? "on" : "off"
526
+ });
527
+ };
528
+ #s = (t) => {
529
+ (t.key === " " || t.key === "Enter") && (t.preventDefault(), this.#t?.click());
530
+ };
531
+ get checked() {
532
+ return this.#t?.checked ?? !1;
533
+ }
534
+ set checked(t) {
535
+ this.#t && (this.#t.checked = t, this.#t.setAttribute("aria-checked", String(t)), t ? this.setAttribute("checked", "") : this.removeAttribute("checked"));
536
+ }
537
+ get value() {
538
+ return this.#t?.value ?? "";
539
+ }
540
+ set value(t) {
541
+ this.#t && (this.#t.value = t);
542
+ }
543
+ }
544
+ customElements.define("ry-switch", P);
545
+ let O = 0;
546
+ class K extends d {
547
+ #t = null;
548
+ #e = null;
549
+ #i = null;
550
+ setup() {
551
+ this.#i = `ry-tooltip-${++O}`, this.#s();
552
+ const t = this.firstElementChild;
553
+ t && (t.setAttribute("aria-describedby", this.#i), this.on(t, "mouseenter", this.#r), this.on(t, "mouseleave", this.#l), this.on(t, "focusin", this.#r), this.on(t, "focusout", this.#l)), this.on(document, "keydown", this.#c);
554
+ }
555
+ #s() {
556
+ this.#e = document.createElement("div"), this.#e.id = this.#i, this.#e.setAttribute("data-ry-target", "content"), this.#e.className = "ry-tooltip__content", this.#e.setAttribute("role", "tooltip"), this.#e.textContent = this.getAttribute("content") ?? "", this.appendChild(this.#e);
557
+ }
558
+ #r = () => {
559
+ this.#t && clearTimeout(this.#t), this.#t = setTimeout(() => {
560
+ this.#n();
561
+ }, 200);
562
+ };
563
+ #n = () => {
564
+ const t = this.getAttribute("position") ?? "top";
565
+ this.setAttribute("data-ry-position", t), this.state = "open";
566
+ };
567
+ #l = () => {
568
+ this.#t && (clearTimeout(this.#t), this.#t = null), this.state = "closed";
569
+ };
570
+ #c = (t) => {
571
+ t.key === "Escape" && this.state === "open" && this.#l();
572
+ };
573
+ teardown() {
574
+ this.#t && clearTimeout(this.#t);
575
+ }
576
+ }
577
+ customElements.define("ry-tooltip", K);
578
+ class W extends d {
579
+ #t = null;
580
+ #e = 0;
581
+ setup() {
582
+ this.#i();
583
+ const t = this.id;
584
+ t && document.querySelectorAll(`ry-button[drawer="${t}"], [drawer="${t}"]`).forEach((s) => {
585
+ this.on(s, "click", () => this.open());
586
+ }), this.$$("[close]").forEach((s) => {
587
+ this.on(s, "click", () => this.close());
588
+ });
589
+ const e = this.$('[data-ry-target="backdrop"]');
590
+ e && this.on(e, "click", () => this.close()), this.on(document, "keydown", this.#s), this.#e = window.innerWidth - document.documentElement.clientWidth, this.hasAttribute("open") ? this.state = "open" : this.hasAttribute("data-ry-state") || (this.state = "closed");
591
+ }
592
+ #i() {
593
+ if (this.$('[data-ry-target="panel"]')) return;
594
+ const t = this.getAttribute("side") ?? "left", e = this.innerHTML;
595
+ this.innerHTML = `
596
+ <div data-ry-target="backdrop" class="ry-drawer__backdrop"></div>
597
+ <div data-ry-target="panel" class="ry-drawer__panel" role="dialog" aria-modal="true" data-ry-side="${t}">
598
+ <button data-ry-target="close" class="ry-drawer__close" close aria-label="Close">&times;</button>
599
+ <div data-ry-target="content" class="ry-drawer__content">
600
+ ${e}
601
+ </div>
602
+ </div>
603
+ `, this.setAttribute("data-ry-side", t);
604
+ }
605
+ #s = (t) => {
606
+ t.key === "Escape" && this.state === "open" && this.close();
607
+ };
608
+ open() {
609
+ if (this.state === "open") return;
610
+ this.#t = document.activeElement, document.body.setAttribute("data-ry-scroll-lock", ""), document.body.style.setProperty("--ry-scrollbar-width", `${this.#e}px`), this.state = "open";
611
+ const t = this.$('[data-ry-target="panel"]');
612
+ t && this.nextFrame().then(() => {
613
+ this.trapFocus(t);
614
+ }), this.emit("open");
615
+ }
616
+ close() {
617
+ this.state !== "closed" && (document.body.removeAttribute("data-ry-scroll-lock"), document.body.style.removeProperty("--ry-scrollbar-width"), this.state = "closed", this.#t instanceof HTMLElement && (this.#t.focus(), this.#t = null), this.emit("close"));
618
+ }
619
+ toggle() {
620
+ this.state === "open" ? this.close() : this.open();
621
+ }
622
+ }
623
+ customElements.define("ry-drawer", W);
624
+ const V = 4e3;
625
+ class p extends d {
626
+ #t = null;
627
+ static observedAttributes = ["variant", "duration"];
628
+ // Static container for programmatic toasts
629
+ static #e = null;
630
+ static #i() {
631
+ return p.#e || (p.#e = document.createElement("div"), p.#e.setAttribute("data-ry-target", "toast-container"), p.#e.className = "ry-toast-container", document.body.appendChild(p.#e)), p.#e;
632
+ }
633
+ // Static API
634
+ static show(t) {
635
+ const e = document.createElement("ry-toast");
636
+ return e.textContent = t.message, t.variant && e.setAttribute("variant", t.variant), t.duration !== void 0 && e.setAttribute("duration", String(t.duration)), p.#i().appendChild(e), e;
637
+ }
638
+ static success(t, e) {
639
+ return p.show({ message: t, variant: "success", duration: e });
640
+ }
641
+ static error(t, e) {
642
+ return p.show({ message: t, variant: "error", duration: e });
643
+ }
644
+ static info(t, e) {
645
+ return p.show({ message: t, variant: "info", duration: e });
646
+ }
647
+ static warning(t, e) {
648
+ return p.show({ message: t, variant: "warning", duration: e });
649
+ }
650
+ setup() {
651
+ this.#s();
652
+ const t = this.$("[close]");
653
+ t && this.on(t, "click", () => this.dismiss());
654
+ const e = parseInt(this.getAttribute("duration") ?? String(V), 10);
655
+ e > 0 && (this.#t = setTimeout(() => this.dismiss(), e)), requestAnimationFrame(() => {
656
+ this.state = "visible";
657
+ });
658
+ }
659
+ #s() {
660
+ if (this.$('[data-ry-target="content"]')) return;
661
+ const t = this.getAttribute("variant") ?? "info", e = this.textContent?.trim() ?? "", s = this.#r(t);
662
+ this.innerHTML = `
663
+ <div data-ry-target="icon" class="ry-toast__icon">${s}</div>
664
+ <div data-ry-target="content" class="ry-toast__content">${e}</div>
665
+ <button data-ry-target="close" class="ry-toast__close" close aria-label="Dismiss">&times;</button>
666
+ `;
667
+ }
668
+ #r(t) {
669
+ const e = {
670
+ info: "ℹ",
671
+ success: "✓",
672
+ warning: "⚠",
673
+ error: "✕"
674
+ };
675
+ return e[t] ?? e.info;
676
+ }
677
+ dismiss() {
678
+ this.#t && (clearTimeout(this.#t), this.#t = null), this.state = "hiding", setTimeout(() => {
679
+ this.remove();
680
+ }, 300), this.emit("close");
681
+ }
682
+ teardown() {
683
+ this.#t && clearTimeout(this.#t);
684
+ }
685
+ }
686
+ customElements.define("ry-toast", p);
687
+ let q = 0;
688
+ class N extends d {
689
+ #t = null;
690
+ #e = -1;
691
+ #i = "";
692
+ #s = null;
693
+ // Store options reference
694
+ _options = [];
695
+ static observedAttributes = ["value", "disabled"];
696
+ setup() {
697
+ this.#t = `ry-select-${++q}`, this.#r(), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.on(this, "click", this.#n), this.on(this, "keydown", this.#l), this.on(document, "click", this.#c), this.hasAttribute("data-ry-state") || (this.state = "closed");
698
+ const t = this.getAttribute("value");
699
+ t && (this.value = t);
700
+ }
701
+ #r() {
702
+ const t = [...this.querySelectorAll("ry-option")].map((n) => ({
703
+ value: n.getAttribute("value") ?? n.textContent?.trim() ?? "",
704
+ label: n.textContent?.trim() ?? "",
705
+ disabled: n.hasAttribute("disabled")
706
+ })), e = this.getAttribute("placeholder") ?? "Select...", s = this.getAttribute("name") ?? "", i = this.hasAttribute("disabled"), r = t.map(
707
+ (n) => `<option value="${n.value}"${n.disabled ? " disabled" : ""}>${n.label}</option>`
708
+ ).join(""), a = t.map((n, l) => `
709
+ <div data-ry-target="option" class="ry-select__option"
710
+ role="option"
711
+ id="${this.#t}-option-${l}"
712
+ data-value="${n.value}"
713
+ ${n.disabled ? "data-disabled" : ""}
714
+ aria-disabled="${n.disabled}">
715
+ ${n.label}
716
+ </div>
717
+ `).join("");
718
+ this.innerHTML = `
719
+ <div data-ry-target="trigger" class="ry-select__trigger" aria-haspopup="listbox" aria-expanded="false">
720
+ <span data-ry-target="value" class="ry-select__value">${e}</span>
721
+ <span data-ry-target="arrow" class="ry-select__arrow">▾</span>
722
+ </div>
723
+ <div data-ry-target="dropdown" class="ry-select__dropdown" role="listbox" id="${this.#t}-listbox" tabindex="-1">
724
+ ${a}
725
+ </div>
726
+ <select data-ry-target="native" class="ry-select__native" ${s ? `name="${s}"` : ""} tabindex="-1" aria-hidden="true" ${i ? "disabled" : ""}>
727
+ <option value="">${e}</option>
728
+ ${r}
729
+ </select>
730
+ `, this._options = t;
731
+ }
732
+ #n = (t) => {
733
+ if (this.hasAttribute("disabled")) return;
734
+ const e = t.target, s = e.closest('[data-ry-target="option"]');
735
+ if (s instanceof HTMLElement && !s.hasAttribute("data-disabled")) {
736
+ this.#o(s), this.close();
737
+ return;
738
+ }
739
+ e.closest('[data-ry-target="trigger"]') && this.toggle();
740
+ };
741
+ #l = (t) => {
742
+ if (this.hasAttribute("disabled")) return;
743
+ const e = this.state === "open";
744
+ switch (t.key) {
745
+ case "Enter":
746
+ case " ":
747
+ if (t.preventDefault(), e && this.#e >= 0) {
748
+ const i = this.$$('[data-ry-target="option"]:not([data-disabled])')[this.#e];
749
+ i && (this.#o(i), this.close());
750
+ } else
751
+ this.toggle();
752
+ break;
753
+ case "Escape":
754
+ e && (t.preventDefault(), this.close());
755
+ break;
756
+ case "ArrowDown":
757
+ t.preventDefault(), e ? this.#u() : this.open();
758
+ break;
759
+ case "ArrowUp":
760
+ t.preventDefault(), e && this.#b();
761
+ break;
762
+ case "Home":
763
+ e && (t.preventDefault(), this.#f());
764
+ break;
765
+ case "End":
766
+ e && (t.preventDefault(), this.#g());
767
+ break;
768
+ default:
769
+ t.key.length === 1 && !t.ctrlKey && !t.metaKey && this.#p(t.key);
770
+ break;
771
+ }
772
+ };
773
+ #c = (t) => {
774
+ const e = t.target;
775
+ !this.contains(e) && this.state === "open" && this.close();
776
+ };
777
+ #p(t) {
778
+ this.#s && clearTimeout(this.#s), this.#i += t.toLowerCase();
779
+ const e = this.$$('[data-ry-target="option"]:not([data-disabled])'), s = e.findIndex(
780
+ (i) => i.textContent?.trim().toLowerCase().startsWith(this.#i)
781
+ );
782
+ if (s >= 0)
783
+ if (this.state === "open")
784
+ this.#a(s);
785
+ else {
786
+ const i = e[s];
787
+ i && this.#o(i);
788
+ }
789
+ this.#s = setTimeout(() => {
790
+ this.#i = "";
791
+ }, 500);
792
+ }
793
+ #a(t) {
794
+ const e = this.$$('[data-ry-target="option"]:not([data-disabled])');
795
+ if (t < 0 || t >= e.length) return;
796
+ this.$$('[data-ry-target="option"][data-highlighted]').forEach((r) => {
797
+ r.removeAttribute("data-highlighted");
798
+ });
799
+ const s = e[t];
800
+ if (!s) return;
801
+ s.setAttribute("data-highlighted", ""), s.scrollIntoView({ block: "nearest" }), this.#e = t;
802
+ const i = this.$('[data-ry-target="trigger"]');
803
+ i && i.setAttribute("aria-activedescendant", s.id);
804
+ }
805
+ #u() {
806
+ const t = this.$$('[data-ry-target="option"]:not([data-disabled])'), e = Math.min(this.#e + 1, t.length - 1);
807
+ this.#a(e);
808
+ }
809
+ #b() {
810
+ const t = Math.max(this.#e - 1, 0);
811
+ this.#a(t);
812
+ }
813
+ #f() {
814
+ this.#a(0);
815
+ }
816
+ #g() {
817
+ const t = this.$$('[data-ry-target="option"]:not([data-disabled])');
818
+ this.#a(t.length - 1);
819
+ }
820
+ #o(t) {
821
+ const e = t.dataset.value ?? "", s = t.textContent?.trim() ?? "", i = this.$('[data-ry-target="value"]');
822
+ i && (i.textContent = s, i.setAttribute("data-selected", ""));
823
+ const r = this.$('[data-ry-target="native"]');
824
+ r && (r.value = e), this.setAttribute("value", e), this.$$('[data-ry-target="option"]').forEach((a) => {
825
+ a.removeAttribute("aria-selected");
826
+ }), t.setAttribute("aria-selected", "true"), this.emit("change", { value: e, label: s });
827
+ }
828
+ open() {
829
+ if (this.state === "open") return;
830
+ this.state = "open";
831
+ const t = this.$('[data-ry-target="trigger"]');
832
+ t && t.setAttribute("aria-expanded", "true"), this.#w();
833
+ const e = this.getAttribute("value");
834
+ if (e) {
835
+ const i = this.$$('[data-ry-target="option"]:not([data-disabled])').findIndex((r) => r.dataset.value === e);
836
+ i >= 0 && this.#a(i);
837
+ } else
838
+ this.#a(0);
839
+ this.emit("open");
840
+ }
841
+ #w() {
842
+ const t = this.$('[data-ry-target="dropdown"]');
843
+ if (!t) return;
844
+ this.removeAttribute("data-ry-position");
845
+ const e = this.getBoundingClientRect(), s = t.scrollHeight || 240, i = window.innerHeight - e.bottom, r = e.top;
846
+ i < s && r > i && this.setAttribute("data-ry-position", "top");
847
+ }
848
+ close() {
849
+ if (this.state === "closed") return;
850
+ this.state = "closed";
851
+ const t = this.$('[data-ry-target="trigger"]');
852
+ t && t.setAttribute("aria-expanded", "false"), this.$$('[data-ry-target="option"][data-highlighted]').forEach((e) => {
853
+ e.removeAttribute("data-highlighted");
854
+ }), this.#e = -1, this.emit("close");
855
+ }
856
+ toggle() {
857
+ this.state === "open" ? this.close() : this.open();
858
+ }
859
+ get value() {
860
+ return this.getAttribute("value") ?? "";
861
+ }
862
+ set value(t) {
863
+ const e = this.$(`[data-ry-target="option"][data-value="${t}"]`);
864
+ e && this.#o(e);
865
+ }
866
+ teardown() {
867
+ this.#s && clearTimeout(this.#s);
868
+ }
869
+ }
870
+ class U extends HTMLElement {
871
+ }
872
+ customElements.define("ry-option", U);
873
+ customElements.define("ry-select", N);
874
+ const v = {
875
+ // Close / X
876
+ close: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18"/><path d="M6 6l12 12"/></svg>',
877
+ // Chevron down
878
+ "chevron-down": '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>',
879
+ // Chevron up
880
+ "chevron-up": '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 15l-6-6-6 6"/></svg>',
881
+ // Chevron right
882
+ "chevron-right": '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18l6-6-6-6"/></svg>',
883
+ // Chevron left
884
+ "chevron-left": '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 18l-6-6 6-6"/></svg>',
885
+ // Check / Checkmark
886
+ check: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>',
887
+ // Copy
888
+ copy: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>',
889
+ // Sun (light mode)
890
+ sun: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="M4.93 4.93l1.41 1.41"/><path d="M17.66 17.66l1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="M6.34 17.66l-1.41 1.41"/><path d="M19.07 4.93l-1.41 1.41"/></svg>',
891
+ // Moon (dark mode)
892
+ moon: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"/></svg>',
893
+ // Info
894
+ info: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>',
895
+ // Warning / Alert triangle
896
+ warning: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>',
897
+ // Error / X circle
898
+ error: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M15 9l-6 6"/><path d="M9 9l6 6"/></svg>',
899
+ // Success / Check circle
900
+ success: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9 12l2 2 4-4"/></svg>',
901
+ // Search
902
+ search: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>',
903
+ // Menu / Hamburger
904
+ menu: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12h18"/><path d="M3 6h18"/><path d="M3 18h18"/></svg>',
905
+ // Plus
906
+ plus: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5v14"/><path d="M5 12h14"/></svg>',
907
+ // Minus
908
+ minus: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/></svg>',
909
+ // Settings / Gear
910
+ settings: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-2 2 2 2 0 01-2-2v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83 0 2 2 0 010-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 01-2-2 2 2 0 012-2h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 010-2.83 2 2 0 012.83 0l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 012-2 2 2 0 012 2v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 0 2 2 0 010 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 012 2 2 2 0 01-2 2h-.09a1.65 1.65 0 00-1.51 1z"/></svg>',
911
+ // User
912
+ user: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
913
+ // Heart
914
+ heart: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>',
915
+ // Star
916
+ star: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>',
917
+ // Trash
918
+ trash: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>',
919
+ // Edit / Pencil
920
+ edit: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>',
921
+ // External link
922
+ "external-link": '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>',
923
+ // Download
924
+ download: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>',
925
+ // Upload
926
+ upload: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>'
927
+ };
928
+ function y(o) {
929
+ return v[o] ?? "";
930
+ }
931
+ function ot(o, t) {
932
+ v[o] = t;
933
+ }
934
+ function ht(o) {
935
+ Object.assign(v, o);
936
+ }
937
+ function lt() {
938
+ return Object.keys(v);
939
+ }
940
+ class z extends d {
941
+ #t = "";
942
+ static get observedAttributes() {
943
+ return ["language", "title", "line-numbers"];
944
+ }
945
+ setup() {
946
+ const t = this.querySelector("template");
947
+ t ? this.#t = this.#u(t.innerHTML) : this.#t = this.textContent?.trim() ?? "", this.#e();
948
+ const e = this.$('[data-ry-target="copy"]');
949
+ e && this.on(e, "click", this.#i);
950
+ }
951
+ #e() {
952
+ const t = this.getAttribute("language") ?? "text", e = this.getAttribute("title") ?? t.toUpperCase(), s = this.hasAttribute("line-numbers"), i = this.#s(this.#t, t), r = i.split(`
953
+ `);
954
+ this.innerHTML = `
955
+ <div data-ry-target="header" class="ry-code__header">
956
+ <span data-ry-target="title" class="ry-code__title">${e}</span>
957
+ <button data-ry-target="copy" class="ry-code__copy" type="button" aria-label="Copy code">
958
+ ${y("copy")}
959
+ </button>
960
+ </div>
961
+ <div data-ry-target="content" class="ry-code__content">
962
+ <pre data-ry-target="pre" class="ry-code__pre"><code data-ry-target="code" class="ry-code__code">${s ? r.map((a, n) => `<span class="ry-code__line"><span class="ry-code__line-number">${n + 1}</span><span class="ry-code__line-content">${a || " "}</span></span>`).join("") : i}</code></pre>
963
+ </div>
964
+ `;
965
+ }
966
+ #i = async () => {
967
+ const t = this.$('[data-ry-target="copy"]');
968
+ if (t)
969
+ try {
970
+ await navigator.clipboard.writeText(this.#t), t.innerHTML = y("check"), t.classList.add("ry-code__copy--success"), this.emit("copy", { code: this.#t }), setTimeout(() => {
971
+ t.innerHTML = y("copy"), t.classList.remove("ry-code__copy--success");
972
+ }, 2e3);
973
+ } catch {
974
+ this.emit("copy-error");
975
+ }
976
+ };
977
+ #s(t, e) {
978
+ switch (e) {
979
+ case "css":
980
+ return this.#r(t);
981
+ case "js":
982
+ case "javascript":
983
+ return this.#n(t);
984
+ case "html":
985
+ return this.#l(t);
986
+ case "json":
987
+ return this.#c(t);
988
+ default:
989
+ return this.#a(t);
990
+ }
991
+ }
992
+ #r(t) {
993
+ const e = [];
994
+ let s = t;
995
+ for (; s.length > 0; ) {
996
+ if (s.startsWith("/*")) {
997
+ const f = s.indexOf("*/");
998
+ if (f !== -1) {
999
+ e.push({ type: "comment", value: s.slice(0, f + 2) }), s = s.slice(f + 2);
1000
+ continue;
1001
+ }
1002
+ }
1003
+ const i = s.match(/^([.#]?[\w-]+(?:\s*,\s*[.#]?[\w-]+)*)\s*(?=\{)/);
1004
+ if (i?.[1]) {
1005
+ e.push({ type: "selector", value: i[1] }), s = s.slice(i[0].length);
1006
+ continue;
1007
+ }
1008
+ const r = s.match(/^([\w-]+)\s*:/);
1009
+ if (r?.[1]) {
1010
+ e.push({ type: "property", value: r[1] }), e.push({ type: "punctuation", value: ":" }), s = s.slice(r[0].length);
1011
+ continue;
1012
+ }
1013
+ const a = s.match(/^(#[0-9a-fA-F]{3,8})/);
1014
+ if (a?.[1]) {
1015
+ e.push({ type: "color", value: a[1], color: a[1] }), s = s.slice(a[1].length);
1016
+ continue;
1017
+ }
1018
+ const n = s.match(/^(rgba?\([^)]+\)|hsla?\([^)]+\))/i);
1019
+ if (n?.[1]) {
1020
+ e.push({ type: "color", value: n[1], color: n[1] }), s = s.slice(n[1].length);
1021
+ continue;
1022
+ }
1023
+ const l = s.match(/^(-?[\d.]+(?:px|em|rem|%|vh|vw|deg|s|ms)?)/);
1024
+ if (l?.[1]) {
1025
+ e.push({ type: "number", value: l[1] }), s = s.slice(l[1].length);
1026
+ continue;
1027
+ }
1028
+ const h = s.match(/^(['"])((?:[^\\]|\\.)*?)\1/);
1029
+ if (h) {
1030
+ e.push({ type: "string", value: h[0] }), s = s.slice(h[0].length);
1031
+ continue;
1032
+ }
1033
+ const c = s[0];
1034
+ if (c && /^[{};,()]/.test(c)) {
1035
+ e.push({ type: "punctuation", value: c }), s = s.slice(1);
1036
+ continue;
1037
+ }
1038
+ const u = s.match(/^(\s+)/);
1039
+ if (u?.[1]) {
1040
+ e.push({ type: "text", value: u[1] }), s = s.slice(u[1].length);
1041
+ continue;
1042
+ }
1043
+ const $ = s.match(/^([\w-]+)/);
1044
+ if ($?.[1]) {
1045
+ const f = $[1];
1046
+ ["inherit", "initial", "unset", "none", "auto", "transparent", "solid", "dashed", "dotted", "flex", "grid", "block", "inline", "inline-block", "absolute", "relative", "fixed", "sticky"].includes(f) ? e.push({ type: "keyword", value: f }) : e.push({ type: "value", value: f }), s = s.slice(f.length);
1047
+ continue;
1048
+ }
1049
+ const x = s[0];
1050
+ x && e.push({ type: "text", value: x }), s = s.slice(1);
1051
+ }
1052
+ return e.map((i) => this.#p(i)).join("");
1053
+ }
1054
+ #n(t) {
1055
+ const e = [];
1056
+ let s = t;
1057
+ const i = ["const", "let", "var", "function", "return", "if", "else", "for", "while", "do", "switch", "case", "break", "continue", "try", "catch", "finally", "throw", "new", "class", "extends", "import", "export", "default", "from", "async", "await", "typeof", "instanceof", "in", "of", "true", "false", "null", "undefined", "this", "super", "static", "get", "set"];
1058
+ for (; s.length > 0; ) {
1059
+ if (s.startsWith("//")) {
1060
+ const u = s.indexOf(`
1061
+ `);
1062
+ if (u !== -1) {
1063
+ e.push({ type: "comment", value: s.slice(0, u) }), s = s.slice(u);
1064
+ continue;
1065
+ } else {
1066
+ e.push({ type: "comment", value: s });
1067
+ break;
1068
+ }
1069
+ }
1070
+ if (s.startsWith("/*")) {
1071
+ const u = s.indexOf("*/");
1072
+ if (u !== -1) {
1073
+ e.push({ type: "comment", value: s.slice(0, u + 2) }), s = s.slice(u + 2);
1074
+ continue;
1075
+ }
1076
+ }
1077
+ const r = s.match(/^(['"`])((?:[^\\]|\\.)*?)\1/);
1078
+ if (r) {
1079
+ e.push({ type: "string", value: r[0] }), s = s.slice(r[0].length);
1080
+ continue;
1081
+ }
1082
+ const a = s.match(/^(-?\d+\.?\d*(?:e[+-]?\d+)?)/i);
1083
+ if (a?.[1]) {
1084
+ e.push({ type: "number", value: a[1] }), s = s.slice(a[1].length);
1085
+ continue;
1086
+ }
1087
+ const n = s.match(/^([a-zA-Z_$][\w$]*)/);
1088
+ if (n?.[1]) {
1089
+ const u = n[1];
1090
+ i.includes(u) ? e.push({ type: "keyword", value: u }) : e.push({ type: "text", value: u }), s = s.slice(u.length);
1091
+ continue;
1092
+ }
1093
+ const l = s[0];
1094
+ if (l && /^[{}[\]();,.:?!<>=+\-*/&|^%~@#]/.test(l)) {
1095
+ e.push({ type: "punctuation", value: l }), s = s.slice(1);
1096
+ continue;
1097
+ }
1098
+ const h = s.match(/^(\s+)/);
1099
+ if (h?.[1]) {
1100
+ e.push({ type: "text", value: h[1] }), s = s.slice(h[1].length);
1101
+ continue;
1102
+ }
1103
+ const c = s[0];
1104
+ c && e.push({ type: "text", value: c }), s = s.slice(1);
1105
+ }
1106
+ return e.map((r) => this.#p(r)).join("");
1107
+ }
1108
+ #l(t) {
1109
+ const e = [];
1110
+ let s = t;
1111
+ for (; s.length > 0; ) {
1112
+ if (s.startsWith("<!--")) {
1113
+ const c = s.indexOf("-->");
1114
+ if (c !== -1) {
1115
+ e.push({ type: "comment", value: s.slice(0, c + 3) }), s = s.slice(c + 3);
1116
+ continue;
1117
+ }
1118
+ }
1119
+ const i = s.match(/^(<\/?)([\w-]+)/);
1120
+ if (i?.[1] && i[2]) {
1121
+ e.push({ type: "punctuation", value: i[1] }), e.push({ type: "tag", value: i[2] }), s = s.slice(i[0].length);
1122
+ continue;
1123
+ }
1124
+ const r = s.match(/^([\w-]+)(=)/);
1125
+ if (r?.[1]) {
1126
+ e.push({ type: "attribute", value: r[1] }), e.push({ type: "punctuation", value: "=" }), s = s.slice(r[0].length);
1127
+ continue;
1128
+ }
1129
+ const a = s.match(/^(['"])((?:[^\\]|\\.)*?)\1/);
1130
+ if (a) {
1131
+ e.push({ type: "string", value: a[0] }), s = s.slice(a[0].length);
1132
+ continue;
1133
+ }
1134
+ if (s[0] === ">" || s.startsWith("/>")) {
1135
+ const c = s.startsWith("/>") ? "/>" : ">";
1136
+ e.push({ type: "punctuation", value: c }), s = s.slice(c.length);
1137
+ continue;
1138
+ }
1139
+ const n = s.match(/^(\s+)/);
1140
+ if (n?.[1]) {
1141
+ e.push({ type: "text", value: n[1] }), s = s.slice(n[1].length);
1142
+ continue;
1143
+ }
1144
+ const l = s.match(/^([^<]+)/);
1145
+ if (l?.[1]) {
1146
+ e.push({ type: "text", value: l[1] }), s = s.slice(l[1].length);
1147
+ continue;
1148
+ }
1149
+ const h = s[0];
1150
+ h && e.push({ type: "text", value: h }), s = s.slice(1);
1151
+ }
1152
+ return e.map((i) => this.#p(i)).join("");
1153
+ }
1154
+ #c(t) {
1155
+ const e = [];
1156
+ let s = t;
1157
+ for (; s.length > 0; ) {
1158
+ const i = s.match(/^("(?:[^\\"]|\\.)*")/);
1159
+ if (i?.[1]) {
1160
+ s.slice(i[0].length).trimStart().startsWith(":") ? e.push({ type: "property", value: i[1] }) : e.push({ type: "string", value: i[1] }), s = s.slice(i[0].length);
1161
+ continue;
1162
+ }
1163
+ const r = s.match(/^(-?\d+\.?\d*(?:e[+-]?\d+)?)/i);
1164
+ if (r?.[1]) {
1165
+ e.push({ type: "number", value: r[1] }), s = s.slice(r[1].length);
1166
+ continue;
1167
+ }
1168
+ const a = s.match(/^(true|false|null)/);
1169
+ if (a?.[1]) {
1170
+ e.push({ type: "keyword", value: a[1] }), s = s.slice(a[1].length);
1171
+ continue;
1172
+ }
1173
+ const n = s[0];
1174
+ if (n && /^[{}[\]:,]/.test(n)) {
1175
+ e.push({ type: "punctuation", value: n }), s = s.slice(1);
1176
+ continue;
1177
+ }
1178
+ const l = s.match(/^(\s+)/);
1179
+ if (l?.[1]) {
1180
+ e.push({ type: "text", value: l[1] }), s = s.slice(l[1].length);
1181
+ continue;
1182
+ }
1183
+ const h = s[0];
1184
+ h && e.push({ type: "text", value: h }), s = s.slice(1);
1185
+ }
1186
+ return e.map((i) => this.#p(i)).join("");
1187
+ }
1188
+ #p(t) {
1189
+ const e = this.#a(t.value);
1190
+ switch (t.type) {
1191
+ case "keyword":
1192
+ return `<span class="ry-code__keyword">${e}</span>`;
1193
+ case "property":
1194
+ return `<span class="ry-code__property">${e}</span>`;
1195
+ case "value":
1196
+ return `<span class="ry-code__value">${e}</span>`;
1197
+ case "string":
1198
+ return `<span class="ry-code__string">${e}</span>`;
1199
+ case "number":
1200
+ return `<span class="ry-code__number">${e}</span>`;
1201
+ case "comment":
1202
+ return `<span class="ry-code__comment">${e}</span>`;
1203
+ case "selector":
1204
+ return `<span class="ry-code__selector">${e}</span>`;
1205
+ case "punctuation":
1206
+ return `<span class="ry-code__punctuation">${e}</span>`;
1207
+ case "tag":
1208
+ return `<span class="ry-code__tag">${e}</span>`;
1209
+ case "attribute":
1210
+ return `<span class="ry-code__attribute">${e}</span>`;
1211
+ case "color":
1212
+ return `<span class="ry-code__color"><span class="ry-code__color-preview" style="background-color: ${t.color}"></span>${e}</span>`;
1213
+ default:
1214
+ return e;
1215
+ }
1216
+ }
1217
+ #a(t) {
1218
+ return t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
1219
+ }
1220
+ #u(t) {
1221
+ const e = t.split(`
1222
+ `);
1223
+ for (; e.length && !e[0]?.trim(); ) e.shift();
1224
+ for (; e.length && !e[e.length - 1]?.trim(); ) e.pop();
1225
+ if (e.length === 0) return "";
1226
+ const s = Math.min(
1227
+ ...e.filter((i) => i.trim()).map((i) => i.match(/^(\s*)/)?.[1]?.length ?? 0)
1228
+ );
1229
+ return e.map((i) => i.slice(s)).join(`
1230
+ `).trim();
1231
+ }
1232
+ get code() {
1233
+ return this.#t;
1234
+ }
1235
+ set code(t) {
1236
+ this.#t = t, this.#e();
1237
+ }
1238
+ }
1239
+ customElements.define("ry-code", z);
1240
+ class Y extends d {
1241
+ setup() {
1242
+ const t = this.$("template");
1243
+ if (!t) return;
1244
+ const e = this.#t(t.innerHTML), s = k(e), i = this.hasAttribute("stacked");
1245
+ this.innerHTML = `
1246
+ <div data-ry-target="preview" class="ry-example__preview"></div>
1247
+ <div data-ry-target="code" class="ry-example__code"></div>
1248
+ `, i && this.setAttribute("data-stacked", "");
1249
+ const r = document.createElement("ry-code");
1250
+ r.setAttribute("language", "html"), r.setAttribute("title", this.getAttribute("title") ?? "Example"), r.textContent = e, this.$('[data-ry-target="code"]').appendChild(r);
1251
+ const a = document.createElement("template");
1252
+ a.innerHTML = s, this.$('[data-ry-target="preview"]').appendChild(a.content);
1253
+ }
1254
+ /**
1255
+ * Normalize indentation by removing common leading whitespace
1256
+ */
1257
+ #t(t) {
1258
+ const e = t.split(`
1259
+ `);
1260
+ for (; e.length && !e[0].trim(); ) e.shift();
1261
+ for (; e.length && !e[e.length - 1].trim(); ) e.pop();
1262
+ if (e.length === 0) return "";
1263
+ const s = Math.min(
1264
+ ...e.filter((i) => i.trim()).map((i) => i.match(/^(\s*)/)?.[1]?.length ?? 0)
1265
+ );
1266
+ return e.map((i) => i.slice(s)).join(`
1267
+ `).trim();
1268
+ }
1269
+ }
1270
+ customElements.define("ry-example", Y);
1271
+ class G extends d {
1272
+ static get observedAttributes() {
1273
+ return ["name", "size", "label"];
1274
+ }
1275
+ setup() {
1276
+ this.#t();
1277
+ }
1278
+ attributeChangedCallback(t, e, s) {
1279
+ e !== s && this.hasAttribute("data-ry-initialized") && this.#t();
1280
+ }
1281
+ #t() {
1282
+ const t = this.getAttribute("name") ?? "", e = this.getAttribute("size") ?? "24", s = this.getAttribute("label"), i = y(t);
1283
+ if (!i) {
1284
+ this.innerHTML = "";
1285
+ return;
1286
+ }
1287
+ this.innerHTML = i;
1288
+ const r = this.querySelector("svg");
1289
+ r && (r.setAttribute("width", e), r.setAttribute("height", e), s ? (r.setAttribute("role", "img"), r.setAttribute("aria-label", s)) : r.setAttribute("aria-hidden", "true"));
1290
+ }
1291
+ get name() {
1292
+ return this.getAttribute("name") ?? "";
1293
+ }
1294
+ set name(t) {
1295
+ this.setAttribute("name", t);
1296
+ }
1297
+ get size() {
1298
+ return parseInt(this.getAttribute("size") ?? "24", 10);
1299
+ }
1300
+ set size(t) {
1301
+ this.setAttribute("size", String(t));
1302
+ }
1303
+ }
1304
+ customElements.define("ry-icon", G);
1305
+ const X = ["form", "section", "fieldset", "ry-section"], g = /* @__PURE__ */ new Map(), A = /* @__PURE__ */ new Set();
1306
+ function J(o) {
1307
+ let t = o.parentElement;
1308
+ for (; t; ) {
1309
+ if (X.some((e) => t.matches(e)))
1310
+ return t;
1311
+ t = t.parentElement;
1312
+ }
1313
+ return null;
1314
+ }
1315
+ function Z(o) {
1316
+ if (A.has(o)) return;
1317
+ const t = g.get(o);
1318
+ if (!t || t.size < 2) return;
1319
+ const e = /* @__PURE__ */ new Map();
1320
+ for (const s of t) {
1321
+ const i = J(s), r = e.get(i) ?? [];
1322
+ r.push(s), e.set(i, r);
1323
+ }
1324
+ if (e.size > 1) {
1325
+ const s = [];
1326
+ for (const [i] of e)
1327
+ if (i) {
1328
+ const r = i.id ? `#${i.id}` : "", a = i.tagName.toLowerCase();
1329
+ s.push(`${a}${r}`);
1330
+ } else
1331
+ s.push("(no container)");
1332
+ console.warn(
1333
+ `ry-toggle-button: Buttons with name="${o}" span multiple containers (${s.join(", ")}). Intentional?`
1334
+ ), A.add(o);
1335
+ }
1336
+ }
1337
+ class Q extends d {
1338
+ static observedAttributes = ["pressed", "disabled", "name", "value"];
1339
+ #t = !1;
1340
+ setup() {
1341
+ this.setAttribute("role", "button"), this.setAttribute("aria-pressed", String(this.pressed)), this.hasAttribute("tabindex") || this.setAttribute("tabindex", "0"), this.#e(), this.on(this, "click", this.#s), this.on(this, "keydown", this.#r);
1342
+ }
1343
+ teardown() {
1344
+ this.#i();
1345
+ }
1346
+ #e() {
1347
+ const t = this.name;
1348
+ t && (g.has(t) || g.set(t, /* @__PURE__ */ new Set()), g.get(t).add(this), this.#t = !0, queueMicrotask(() => Z(t)));
1349
+ }
1350
+ #i() {
1351
+ if (!this.#t) return;
1352
+ const t = this.name;
1353
+ t && g.has(t) && (g.get(t).delete(this), g.get(t).size === 0 && (g.delete(t), A.delete(t))), this.#t = !1;
1354
+ }
1355
+ #s = (t) => {
1356
+ if (this.disabled) {
1357
+ t.preventDefault();
1358
+ return;
1359
+ }
1360
+ this.pressed || (this.pressed = !0);
1361
+ };
1362
+ #r = (t) => {
1363
+ (t.key === "Enter" || t.key === " ") && (t.preventDefault(), this.click());
1364
+ };
1365
+ #n() {
1366
+ const t = this.name;
1367
+ if (!t) return;
1368
+ const e = g.get(t);
1369
+ if (e)
1370
+ for (const s of e)
1371
+ s !== this && s.pressed && (s.pressed = !1);
1372
+ }
1373
+ // --- Public API ---
1374
+ get pressed() {
1375
+ return this.hasAttribute("pressed");
1376
+ }
1377
+ set pressed(t) {
1378
+ const e = this.pressed;
1379
+ t ? (this.setAttribute("pressed", ""), this.setAttribute("aria-pressed", "true"), this.#n()) : (this.removeAttribute("pressed"), this.setAttribute("aria-pressed", "false")), e !== t && this.emit("change", {
1380
+ value: this.value,
1381
+ label: t ? "pressed" : "unpressed"
1382
+ });
1383
+ }
1384
+ get disabled() {
1385
+ return this.hasAttribute("disabled");
1386
+ }
1387
+ set disabled(t) {
1388
+ t ? (this.setAttribute("disabled", ""), this.setAttribute("aria-disabled", "true"), this.setAttribute("tabindex", "-1")) : (this.removeAttribute("disabled"), this.removeAttribute("aria-disabled"), this.setAttribute("tabindex", "0"));
1389
+ }
1390
+ get name() {
1391
+ return this.getAttribute("name") ?? "";
1392
+ }
1393
+ set name(t) {
1394
+ this.name !== t && (this.#i(), t ? this.setAttribute("name", t) : this.removeAttribute("name"), this.#e());
1395
+ }
1396
+ get value() {
1397
+ return this.getAttribute("value") ?? "";
1398
+ }
1399
+ set value(t) {
1400
+ this.setAttribute("value", t);
1401
+ }
1402
+ get icon() {
1403
+ return this.getAttribute("icon") ?? "";
1404
+ }
1405
+ set icon(t) {
1406
+ this.setAttribute("icon", t);
1407
+ }
1408
+ }
1409
+ customElements.define("ry-toggle-button", Q);
1410
+ class tt extends d {
1411
+ #t = !1;
1412
+ #e = null;
1413
+ #i = null;
1414
+ #s = null;
1415
+ #r = /* @__PURE__ */ new Map();
1416
+ #n = /* @__PURE__ */ new Map();
1417
+ static observedAttributes = ["min", "max", "step", "value", "start", "end", "disabled"];
1418
+ setup() {
1419
+ this.#l(), this.#p(), this.#k();
1420
+ }
1421
+ #l() {
1422
+ const t = this.hasAttribute("range"), e = this.hasAttribute("labeled"), s = this.hasAttribute("tooltip");
1423
+ this.hasAttribute("vertical");
1424
+ let i = `
1425
+ <div data-ry-target="track" class="ry-slider__track">
1426
+ <div data-ry-target="fill" class="ry-slider__fill"></div>
1427
+ `;
1428
+ t ? i += `
1429
+ <div data-ry-target="thumb-start" class="ry-slider__thumb" tabindex="0" role="slider" aria-label="Start value">
1430
+ ${s ? '<span data-ry-target="tooltip-start" class="ry-slider__tooltip"></span>' : ""}
1431
+ </div>
1432
+ <div data-ry-target="thumb-end" class="ry-slider__thumb" tabindex="0" role="slider" aria-label="End value">
1433
+ ${s ? '<span data-ry-target="tooltip-end" class="ry-slider__tooltip"></span>' : ""}
1434
+ </div>
1435
+ ` : i += `
1436
+ <div data-ry-target="thumb-value" class="ry-slider__thumb" tabindex="0" role="slider" aria-label="Value">
1437
+ ${s ? '<span data-ry-target="tooltip-value" class="ry-slider__tooltip"></span>' : ""}
1438
+ </div>
1439
+ `, i += "</div>", e && (i += this.#c()), this.innerHTML = i, this.#i = this.$('[data-ry-target="track"]'), this.#s = this.$('[data-ry-target="fill"]'), t ? (this.#r.set("start", this.$('[data-ry-target="thumb-start"]')), this.#r.set("end", this.$('[data-ry-target="thumb-end"]')), s && (this.#n.set("start", this.$('[data-ry-target="tooltip-start"]')), this.#n.set("end", this.$('[data-ry-target="tooltip-end"]')))) : (this.#r.set("value", this.$('[data-ry-target="thumb-value"]')), s && this.#n.set("value", this.$('[data-ry-target="tooltip-value"]')));
1440
+ }
1441
+ #c() {
1442
+ const t = this.min, e = this.max, s = this.getAttribute("labels")?.split(","), i = this.getAttribute("label-type") || "number";
1443
+ let r = [];
1444
+ if (s)
1445
+ r = s;
1446
+ else
1447
+ for (let n = 0; n < 5; n++) {
1448
+ const l = n / 4, h = t + l * (e - t);
1449
+ if (i === "letter")
1450
+ r.push(String.fromCharCode(65 + n));
1451
+ else {
1452
+ const c = Math.round(h * 100) / 100;
1453
+ r.push(String(Number.isInteger(c) ? c : c.toFixed(1)));
1454
+ }
1455
+ }
1456
+ return `
1457
+ <div data-ry-target="labels" class="ry-slider__labels">
1458
+ ${r.map((a) => `<span>${a}</span>`).join("")}
1459
+ </div>
1460
+ `;
1461
+ }
1462
+ #p() {
1463
+ this.#i && this.on(this.#i, "pointerdown", this.#a);
1464
+ for (const [t, e] of this.#r)
1465
+ this.on(e, "pointerdown", (s) => this.#u(s, t)), this.on(e, "keydown", (s) => this.#g(s, t));
1466
+ this.on(document, "pointermove", this.#b), this.on(document, "pointerup", this.#f);
1467
+ }
1468
+ #a = (t) => {
1469
+ if (this.disabled) return;
1470
+ const e = this.#w(t);
1471
+ if (this.hasAttribute("range")) {
1472
+ const i = Math.abs(e - this.start), r = Math.abs(e - this.end);
1473
+ i < r ? (this.start = e, this.#e = "start") : (this.end = e, this.#e = "end");
1474
+ } else
1475
+ this.value = e, this.#e = "value";
1476
+ this.#t = !0, this.#k(), this.#m();
1477
+ };
1478
+ #u = (t, e) => {
1479
+ this.disabled || (t.stopPropagation(), this.#t = !0, this.#e = e, t.target.setPointerCapture(t.pointerId));
1480
+ };
1481
+ #b = (t) => {
1482
+ if (!this.#t || !this.#e) return;
1483
+ const e = this.#w(t);
1484
+ this.hasAttribute("range") ? this.#e === "start" ? this.start = Math.min(e, this.end) : this.#e === "end" && (this.end = Math.max(e, this.start)) : this.value = e, this.#k(), this.#m();
1485
+ };
1486
+ #f = () => {
1487
+ this.#t && (this.#t = !1, this.#e = null, this.#x());
1488
+ };
1489
+ #g = (t, e) => {
1490
+ if (this.disabled) return;
1491
+ const s = this.step || 1, i = (this.max - this.min) / 10;
1492
+ let r = 0;
1493
+ switch (t.key) {
1494
+ case "ArrowRight":
1495
+ case "ArrowUp":
1496
+ r = this.hasAttribute("reversed") ? -s : s;
1497
+ break;
1498
+ case "ArrowLeft":
1499
+ case "ArrowDown":
1500
+ r = this.hasAttribute("reversed") ? s : -s;
1501
+ break;
1502
+ case "PageUp":
1503
+ r = i;
1504
+ break;
1505
+ case "PageDown":
1506
+ r = -i;
1507
+ break;
1508
+ case "Home":
1509
+ r = this.min - this.#o(e);
1510
+ break;
1511
+ case "End":
1512
+ r = this.max - this.#o(e);
1513
+ break;
1514
+ default:
1515
+ return;
1516
+ }
1517
+ t.preventDefault();
1518
+ const a = this.#d(this.#o(e) + r);
1519
+ e === "start" ? this.start = Math.min(a, this.end) : e === "end" ? this.end = Math.max(a, this.start) : this.value = a, this.#k(), this.#m(), this.#x();
1520
+ };
1521
+ #o(t) {
1522
+ return t === "start" ? this.start : t === "end" ? this.end : this.value;
1523
+ }
1524
+ #w(t) {
1525
+ if (!this.#i) return this.min;
1526
+ const e = this.#i.getBoundingClientRect(), s = this.hasAttribute("vertical"), i = this.hasAttribute("reversed");
1527
+ let r;
1528
+ s ? r = (e.bottom - t.clientY) / e.height : r = (t.clientX - e.left) / e.width, i && (r = 1 - r), r = Math.max(0, Math.min(1, r));
1529
+ const a = this.min + r * (this.max - this.min);
1530
+ return this.#h(a);
1531
+ }
1532
+ #h(t) {
1533
+ const e = this.step;
1534
+ if (e === 0) return this.#d(t);
1535
+ const s = Math.round((t - this.min) / e) * e + this.min;
1536
+ return this.#d(s);
1537
+ }
1538
+ #d(t) {
1539
+ return Math.max(this.min, Math.min(this.max, t));
1540
+ }
1541
+ #k() {
1542
+ const t = this.hasAttribute("range"), e = this.hasAttribute("vertical"), s = this.hasAttribute("reversed"), i = (r) => {
1543
+ let a = (r - this.min) / (this.max - this.min) * 100;
1544
+ return s && (a = 100 - a), a;
1545
+ };
1546
+ if (t) {
1547
+ const r = i(this.start), a = i(this.end), n = Math.min(r, a), l = Math.max(r, a);
1548
+ this.#s && (e ? (this.#s.style.bottom = `${n}%`, this.#s.style.height = `${l - n}%`, this.#s.style.left = "", this.#s.style.width = "") : (this.#s.style.left = `${n}%`, this.#s.style.width = `${l - n}%`, this.#s.style.bottom = "", this.#s.style.height = ""));
1549
+ const h = this.#r.get("start"), c = this.#r.get("end");
1550
+ h && (e ? (h.style.bottom = `${r}%`, h.style.left = "") : (h.style.left = `${r}%`, h.style.bottom = "")), c && (e ? (c.style.bottom = `${a}%`, c.style.left = "") : (c.style.left = `${a}%`, c.style.bottom = "")), this.#v("start", this.start), this.#v("end", this.end), h?.setAttribute("aria-valuenow", String(this.start)), h?.setAttribute("aria-valuemin", String(this.min)), h?.setAttribute("aria-valuemax", String(this.end)), c?.setAttribute("aria-valuenow", String(this.end)), c?.setAttribute("aria-valuemin", String(this.start)), c?.setAttribute("aria-valuemax", String(this.max));
1551
+ } else {
1552
+ const r = i(this.value);
1553
+ this.#s && (e ? (this.#s.style.bottom = "0", this.#s.style.height = `${r}%`, this.#s.style.left = "", this.#s.style.width = "") : (this.#s.style.left = "0", this.#s.style.width = `${r}%`, this.#s.style.bottom = "", this.#s.style.height = ""));
1554
+ const a = this.#r.get("value");
1555
+ a && (e ? (a.style.bottom = `${r}%`, a.style.left = "") : (a.style.left = `${r}%`, a.style.bottom = "")), this.#v("value", this.value), a?.setAttribute("aria-valuenow", String(this.value)), a?.setAttribute("aria-valuemin", String(this.min)), a?.setAttribute("aria-valuemax", String(this.max));
1556
+ }
1557
+ }
1558
+ #v(t, e) {
1559
+ const s = this.#n.get(t);
1560
+ if (s) {
1561
+ const i = this.step === 0 ? 2 : String(this.step).split(".")[1]?.length || 0;
1562
+ s.textContent = e.toFixed(i);
1563
+ }
1564
+ }
1565
+ #m() {
1566
+ this.hasAttribute("range") ? this.emit("input", { start: this.start, end: this.end }) : this.emit("input", { value: this.value });
1567
+ }
1568
+ #x() {
1569
+ this.hasAttribute("range") ? this.emit("change", { start: this.start, end: this.end }) : this.emit("change", { value: this.value });
1570
+ }
1571
+ // --- Public API ---
1572
+ get min() {
1573
+ return parseFloat(this.getAttribute("min") ?? "0");
1574
+ }
1575
+ set min(t) {
1576
+ this.setAttribute("min", String(t));
1577
+ }
1578
+ get max() {
1579
+ return parseFloat(this.getAttribute("max") ?? "100");
1580
+ }
1581
+ set max(t) {
1582
+ this.setAttribute("max", String(t));
1583
+ }
1584
+ get step() {
1585
+ return parseFloat(this.getAttribute("step") ?? "1");
1586
+ }
1587
+ set step(t) {
1588
+ this.setAttribute("step", String(t));
1589
+ }
1590
+ get value() {
1591
+ return parseFloat(this.getAttribute("value") ?? String(this.min));
1592
+ }
1593
+ set value(t) {
1594
+ this.setAttribute("value", String(this.#d(t)));
1595
+ }
1596
+ get start() {
1597
+ return parseFloat(this.getAttribute("start") ?? String(this.min));
1598
+ }
1599
+ set start(t) {
1600
+ this.setAttribute("start", String(this.#d(t)));
1601
+ }
1602
+ get end() {
1603
+ return parseFloat(this.getAttribute("end") ?? String(this.max));
1604
+ }
1605
+ set end(t) {
1606
+ this.setAttribute("end", String(this.#d(t)));
1607
+ }
1608
+ get disabled() {
1609
+ return this.hasAttribute("disabled");
1610
+ }
1611
+ set disabled(t) {
1612
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
1613
+ }
1614
+ }
1615
+ customElements.define("ry-slider", tt);
1616
+ class et extends d {
1617
+ #t = !1;
1618
+ #e = 0;
1619
+ #i = 0;
1620
+ #s = null;
1621
+ #r = null;
1622
+ #n = null;
1623
+ static observedAttributes = ["min", "max", "step", "value", "disabled", "label", "labels", "description"];
1624
+ setup() {
1625
+ this.#l(), this.#c(), this.#d();
1626
+ }
1627
+ #l() {
1628
+ const t = this.getAttribute("label"), e = this.getAttribute("description"), s = e ? ` title="${e}"` : "";
1629
+ this.innerHTML = `
1630
+ <div data-ry-target="ring" class="ry-knob__ring"${s}>
1631
+ <div data-ry-target="cap" class="ry-knob__cap">
1632
+ <div data-ry-target="indicator" class="ry-knob__indicator"></div>
1633
+ </div>
1634
+ </div>
1635
+ <span data-ry-target="display" class="ry-knob__value"></span>
1636
+ ${t ? `<span data-ry-target="label" class="ry-knob__label"${s}>${t}</span>` : ""}
1637
+ `, this.#s = this.$('[data-ry-target="ring"]'), this.#r = this.$('[data-ry-target="indicator"]'), this.#n = this.$('[data-ry-target="display"]');
1638
+ }
1639
+ #c() {
1640
+ this.#s && (this.on(this.#s, "mousedown", this.#p), this.on(document, "mousemove", this.#a), this.on(document, "mouseup", this.#u), this.on(this.#s, "touchstart", this.#b), this.on(document, "touchmove", this.#f), this.on(document, "touchend", this.#g), this.on(this.#s, "wheel", this.#o), this.on(this, "keydown", this.#w));
1641
+ }
1642
+ #p = (t) => {
1643
+ this.disabled || (t.preventDefault(), this.#t = !0, this.#e = t.clientY, this.#i = this.value, this.#s?.classList.add("ry-knob__ring--dragging"), this.setAttribute("data-dragging", ""));
1644
+ };
1645
+ #a = (t) => {
1646
+ if (!this.#t) return;
1647
+ const e = this.#e - t.clientY, s = (this.max - this.min) / 100;
1648
+ this.#h(this.#i + e * s);
1649
+ };
1650
+ #u = () => {
1651
+ this.#t && (this.#t = !1, this.#s?.classList.remove("ry-knob__ring--dragging"), this.removeAttribute("data-dragging"), this.#m());
1652
+ };
1653
+ #b = (t) => {
1654
+ this.disabled || (t.preventDefault(), this.#t = !0, this.#e = t.touches[0]?.clientY ?? 0, this.#i = this.value, this.#s?.classList.add("ry-knob__ring--dragging"), this.setAttribute("data-dragging", ""));
1655
+ };
1656
+ #f = (t) => {
1657
+ if (!this.#t) return;
1658
+ t.preventDefault();
1659
+ const e = t.touches[0];
1660
+ if (!e) return;
1661
+ const s = this.#e - e.clientY, i = (this.max - this.min) / 100;
1662
+ this.#h(this.#i + s * i);
1663
+ };
1664
+ #g = () => {
1665
+ this.#t && (this.#t = !1, this.#s?.classList.remove("ry-knob__ring--dragging"), this.removeAttribute("data-dragging"), this.#m());
1666
+ };
1667
+ #o = (t) => {
1668
+ if (this.disabled) return;
1669
+ t.preventDefault();
1670
+ const e = this.step || (this.max - this.min) / 50, s = t.deltaY < 0 ? e : -e;
1671
+ this.#h(this.value + s), this.#m();
1672
+ };
1673
+ #w = (t) => {
1674
+ if (this.disabled) return;
1675
+ const e = this.step || 1, s = (this.max - this.min) / 10;
1676
+ let i = 0;
1677
+ switch (t.key) {
1678
+ case "ArrowUp":
1679
+ case "ArrowRight":
1680
+ i = e;
1681
+ break;
1682
+ case "ArrowDown":
1683
+ case "ArrowLeft":
1684
+ i = -e;
1685
+ break;
1686
+ case "PageUp":
1687
+ i = s;
1688
+ break;
1689
+ case "PageDown":
1690
+ i = -s;
1691
+ break;
1692
+ case "Home":
1693
+ this.#h(this.min), this.#m();
1694
+ return;
1695
+ case "End":
1696
+ this.#h(this.max), this.#m();
1697
+ return;
1698
+ default:
1699
+ return;
1700
+ }
1701
+ t.preventDefault(), this.#h(this.value + i), this.#m();
1702
+ };
1703
+ #h(t) {
1704
+ let e = Math.max(this.min, Math.min(this.max, t));
1705
+ const s = this.step;
1706
+ s > 0 && (e = Math.round((e - this.min) / s) * s + this.min, e = Math.max(this.min, Math.min(this.max, e))), this.value = e, this.#d(), this.#v();
1707
+ }
1708
+ #d() {
1709
+ const t = (this.value - this.min) / (this.max - this.min), e = -135 + t * 270;
1710
+ this.#s && (this.#s.style.setProperty("--knob-rotation", `${e}deg`), this.#s.style.setProperty("--knob-percent", String(t))), this.#n && (this.#n.textContent = this.#k(this.value)), this.setAttribute("aria-valuenow", String(this.value)), this.setAttribute("aria-valuemin", String(this.min)), this.setAttribute("aria-valuemax", String(this.max));
1711
+ }
1712
+ #k(t) {
1713
+ const e = this.getAttribute("labels");
1714
+ if (e) {
1715
+ const i = e.split(","), r = Math.round(t);
1716
+ return i[r] ?? String(r);
1717
+ }
1718
+ return this.step >= 1 ? Math.round(t).toString() : Math.abs(t) >= 1e3 ? (t / 1e3).toFixed(1) + "k" : Math.abs(t) >= 100 ? Math.round(t).toString() : Math.abs(t) >= 10 ? t.toFixed(1) : t.toFixed(2);
1719
+ }
1720
+ #v() {
1721
+ const t = (this.value - this.min) / (this.max - this.min);
1722
+ this.emit("input", { value: this.value, percent: t });
1723
+ }
1724
+ #m() {
1725
+ const t = (this.value - this.min) / (this.max - this.min);
1726
+ this.emit("change", { value: this.value, percent: t });
1727
+ }
1728
+ attributeChangedCallback(t, e, s) {
1729
+ e !== s && t === "value" && this.#s && this.#d();
1730
+ }
1731
+ // --- Public API ---
1732
+ get min() {
1733
+ return parseFloat(this.getAttribute("min") ?? "0");
1734
+ }
1735
+ set min(t) {
1736
+ this.setAttribute("min", String(t));
1737
+ }
1738
+ get max() {
1739
+ return parseFloat(this.getAttribute("max") ?? "100");
1740
+ }
1741
+ set max(t) {
1742
+ this.setAttribute("max", String(t));
1743
+ }
1744
+ get step() {
1745
+ return parseFloat(this.getAttribute("step") ?? "0");
1746
+ }
1747
+ set step(t) {
1748
+ this.setAttribute("step", String(t));
1749
+ }
1750
+ get value() {
1751
+ return parseFloat(this.getAttribute("value") ?? String(this.min));
1752
+ }
1753
+ set value(t) {
1754
+ this.setAttribute("value", String(t));
1755
+ }
1756
+ get disabled() {
1757
+ return this.hasAttribute("disabled");
1758
+ }
1759
+ set disabled(t) {
1760
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
1761
+ }
1762
+ }
1763
+ customElements.define("ry-knob", et);
1764
+ function b(o) {
1765
+ const t = o.h / 360, e = o.s / 100, s = o.v / 100;
1766
+ let i = 0, r = 0, a = 0;
1767
+ const n = Math.floor(t * 6), l = t * 6 - n, h = s * (1 - e), c = s * (1 - l * e), u = s * (1 - (1 - l) * e);
1768
+ switch (n % 6) {
1769
+ case 0:
1770
+ i = s, r = u, a = h;
1771
+ break;
1772
+ case 1:
1773
+ i = c, r = s, a = h;
1774
+ break;
1775
+ case 2:
1776
+ i = h, r = s, a = u;
1777
+ break;
1778
+ case 3:
1779
+ i = h, r = c, a = s;
1780
+ break;
1781
+ case 4:
1782
+ i = u, r = h, a = s;
1783
+ break;
1784
+ case 5:
1785
+ i = s, r = h, a = c;
1786
+ break;
1787
+ }
1788
+ return {
1789
+ r: Math.round(i * 255),
1790
+ g: Math.round(r * 255),
1791
+ b: Math.round(a * 255)
1792
+ };
1793
+ }
1794
+ function w(o) {
1795
+ const t = o.r / 255, e = o.g / 255, s = o.b / 255, i = Math.max(t, e, s), r = Math.min(t, e, s), a = i - r;
1796
+ let n = 0;
1797
+ const l = i === 0 ? 0 : a / i, h = i;
1798
+ if (i !== r)
1799
+ switch (i) {
1800
+ case t:
1801
+ n = ((e - s) / a + (e < s ? 6 : 0)) / 6;
1802
+ break;
1803
+ case e:
1804
+ n = ((s - t) / a + 2) / 6;
1805
+ break;
1806
+ case s:
1807
+ n = ((t - e) / a + 4) / 6;
1808
+ break;
1809
+ }
1810
+ return {
1811
+ h: Math.round(n * 360),
1812
+ s: Math.round(l * 100),
1813
+ v: Math.round(h * 100)
1814
+ };
1815
+ }
1816
+ function M(o) {
1817
+ const t = o.s / 100, e = o.v / 100, s = e * (1 - t / 2), i = s === 0 || s === 1 ? 0 : (e - s) / Math.min(s, 1 - s);
1818
+ return {
1819
+ h: o.h,
1820
+ s: Math.round(i * 100),
1821
+ l: Math.round(s * 100)
1822
+ };
1823
+ }
1824
+ function st(o) {
1825
+ const t = o.s / 100, e = o.l / 100, s = e + t * Math.min(e, 1 - e), i = s === 0 ? 0 : 2 * (1 - e / s);
1826
+ return {
1827
+ h: o.h,
1828
+ s: Math.round(i * 100),
1829
+ v: Math.round(s * 100)
1830
+ };
1831
+ }
1832
+ function E(o) {
1833
+ const t = (e) => e.toString(16).padStart(2, "0");
1834
+ return `#${t(o.r)}${t(o.g)}${t(o.b)}`;
1835
+ }
1836
+ function it(o) {
1837
+ const t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(o);
1838
+ if (!t) {
1839
+ const e = /^#?([a-f\d])([a-f\d])([a-f\d])$/i.exec(o);
1840
+ return e ? {
1841
+ r: parseInt(e[1] + e[1], 16),
1842
+ g: parseInt(e[2] + e[2], 16),
1843
+ b: parseInt(e[3] + e[3], 16)
1844
+ } : null;
1845
+ }
1846
+ return {
1847
+ r: parseInt(t[1], 16),
1848
+ g: parseInt(t[2], 16),
1849
+ b: parseInt(t[3], 16)
1850
+ };
1851
+ }
1852
+ function m(o) {
1853
+ const t = o.trim().toLowerCase();
1854
+ if (t.startsWith("#")) {
1855
+ const i = /^#([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);
1856
+ if (i) {
1857
+ const a = {
1858
+ r: parseInt(i[1], 16),
1859
+ g: parseInt(i[2], 16),
1860
+ b: parseInt(i[3], 16)
1861
+ }, n = parseInt(i[4], 16) / 255;
1862
+ return { hsv: w(a), alpha: Math.round(n * 100) };
1863
+ }
1864
+ const r = it(t);
1865
+ return r ? { hsv: w(r), alpha: 100 } : null;
1866
+ }
1867
+ const e = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)$/.exec(t);
1868
+ if (e) {
1869
+ const i = {
1870
+ r: parseInt(e[1], 10),
1871
+ g: parseInt(e[2], 10),
1872
+ b: parseInt(e[3], 10)
1873
+ }, r = e[4] ? parseFloat(e[4]) * 100 : 100;
1874
+ return { hsv: w(i), alpha: r };
1875
+ }
1876
+ const s = /^hsla?\(\s*([\d.]+)\s*,\s*([\d.]+)%\s*,\s*([\d.]+)%\s*(?:,\s*([\d.]+))?\s*\)$/.exec(t);
1877
+ if (s) {
1878
+ const i = {
1879
+ h: parseFloat(s[1]),
1880
+ s: parseFloat(s[2]),
1881
+ l: parseFloat(s[3])
1882
+ }, r = s[4] ? parseFloat(s[4]) * 100 : 100;
1883
+ return { hsv: st(i), alpha: r };
1884
+ }
1885
+ return null;
1886
+ }
1887
+ class rt extends d {
1888
+ #t = 0;
1889
+ #e = 100;
1890
+ #i = 100;
1891
+ #s = 100;
1892
+ #r = !1;
1893
+ #n = !1;
1894
+ #l = !1;
1895
+ #c = null;
1896
+ #p = null;
1897
+ #a = null;
1898
+ #u = null;
1899
+ #b = null;
1900
+ #f = null;
1901
+ #g = null;
1902
+ #o = null;
1903
+ #w = null;
1904
+ #h = null;
1905
+ static observedAttributes = ["value", "format", "opacity", "disabled", "swatches", "inline"];
1906
+ setup() {
1907
+ this.#d(), this.#k(), this.#v(), this.#y();
1908
+ }
1909
+ #d() {
1910
+ const t = this.hasAttribute("inline"), e = this.hasAttribute("opacity"), s = this.getAttribute("swatches");
1911
+ let i = `
1912
+ <div data-ry-target="grid" class="ry-color-picker__grid">
1913
+ <div data-ry-target="grid-handle" class="ry-color-picker__grid-handle" tabindex="0"></div>
1914
+ </div>
1915
+ <div data-ry-target="controls" class="ry-color-picker__controls">
1916
+ <div data-ry-target="sliders" class="ry-color-picker__sliders">
1917
+ <div data-ry-target="hue-slider" class="ry-color-picker__slider ry-color-picker__hue">
1918
+ <div data-ry-target="hue-handle" class="ry-color-picker__slider-handle" tabindex="0"></div>
1919
+ </div>
1920
+ ${e ? `
1921
+ <div data-ry-target="alpha-slider" class="ry-color-picker__slider ry-color-picker__alpha">
1922
+ <div data-ry-target="alpha-handle" class="ry-color-picker__slider-handle" tabindex="0"></div>
1923
+ </div>
1924
+ ` : ""}
1925
+ </div>
1926
+ <div data-ry-target="preview" class="ry-color-picker__preview">
1927
+ <span data-ry-target="preview-color" class="ry-color-picker__preview-color"></span>
1928
+ </div>
1929
+ </div>
1930
+ <div data-ry-target="input-row" class="ry-color-picker__input-row">
1931
+ <input data-ry-target="input" type="text" class="ry-color-picker__input" spellcheck="false" />
1932
+ <button data-ry-target="format-toggle" type="button" class="ry-color-picker__format-toggle">${this.format.toUpperCase()}</button>
1933
+ </div>
1934
+ `;
1935
+ if (s) {
1936
+ const r = s.split(";").map((a) => a.trim()).filter(Boolean);
1937
+ if (r.length > 0) {
1938
+ i += '<div data-ry-target="swatches" class="ry-color-picker__swatches">';
1939
+ for (const a of r)
1940
+ i += `<button type="button" class="ry-color-picker__swatch" data-color="${a}" style="background-color: ${a}"></button>`;
1941
+ i += "</div>";
1942
+ }
1943
+ }
1944
+ t ? this.innerHTML = `<div data-ry-target="panel" class="ry-color-picker__panel ry-color-picker__panel--inline">${i}</div>` : this.innerHTML = `
1945
+ <button data-ry-target="trigger" type="button" class="ry-color-picker__trigger">
1946
+ <span data-ry-target="trigger-color" class="ry-color-picker__trigger-color"></span>
1947
+ </button>
1948
+ <div data-ry-target="panel" class="ry-color-picker__panel">${i}</div>
1949
+ `, this.#c = this.$('[data-ry-target="trigger"]'), this.#p = this.$('[data-ry-target="panel"]'), this.#a = this.$('[data-ry-target="grid"]'), this.#u = this.$('[data-ry-target="grid-handle"]'), this.#b = this.$('[data-ry-target="hue-slider"]'), this.#f = this.$('[data-ry-target="hue-handle"]'), this.#g = this.$('[data-ry-target="alpha-slider"]'), this.#o = this.$('[data-ry-target="alpha-handle"]'), this.#w = this.$('[data-ry-target="preview"]'), this.#h = this.$('[data-ry-target="input"]');
1950
+ }
1951
+ #k() {
1952
+ this.#c && this.on(this.#c, "click", this.#m), this.on(document, "click", this.#x), this.on(document, "keydown", this.#B), this.#a && this.on(this.#a, "pointerdown", this.#R), this.#u && this.on(this.#u, "keydown", this.#P), this.#b && this.on(this.#b, "pointerdown", this.#O), this.#f && this.on(this.#f, "keydown", this.#K), this.#g && this.on(this.#g, "pointerdown", this.#W), this.#o && this.on(this.#o, "keydown", this.#V), this.on(document, "pointermove", this.#q), this.on(document, "pointerup", this.#N), this.#h && (this.on(this.#h, "change", this.#T), this.on(this.#h, "keydown", this.#U));
1953
+ const t = this.$('[data-ry-target="format-toggle"]');
1954
+ t && this.on(t, "click", this.#z);
1955
+ const e = this.$('[data-ry-target="swatches"]');
1956
+ e && this.on(e, "click", this.#Y);
1957
+ }
1958
+ #v() {
1959
+ const t = this.getAttribute("value");
1960
+ if (t) {
1961
+ const e = m(t);
1962
+ e && (this.#t = e.hsv.h, this.#e = e.hsv.s, this.#i = e.hsv.v, this.#s = e.alpha);
1963
+ }
1964
+ }
1965
+ // ───────────────────────────────────────────────────────────────────────────
1966
+ // Dropdown handlers
1967
+ // ───────────────────────────────────────────────────────────────────────────
1968
+ #m = () => {
1969
+ this.disabled || (this.state === "open" ? this.close() : this.open());
1970
+ };
1971
+ #x = (t) => {
1972
+ this.state === "open" && (this.contains(t.target) || this.close());
1973
+ };
1974
+ #B = (t) => {
1975
+ t.key === "Escape" && this.state === "open" && (this.close(), this.#c?.focus());
1976
+ };
1977
+ open() {
1978
+ this.hasAttribute("inline") || (this.#j(), this.state = "open");
1979
+ }
1980
+ close() {
1981
+ this.hasAttribute("inline") || (this.state = "closed", this.removeAttribute("data-ry-position"));
1982
+ }
1983
+ #j() {
1984
+ if (!this.#p || !this.#c) return;
1985
+ const t = this.#c.getBoundingClientRect(), e = 320, i = window.innerHeight - t.bottom, r = t.top;
1986
+ i < e && r > i ? this.setAttribute("data-ry-position", "top") : this.setAttribute("data-ry-position", "bottom");
1987
+ }
1988
+ // ───────────────────────────────────────────────────────────────────────────
1989
+ // Grid handlers
1990
+ // ───────────────────────────────────────────────────────────────────────────
1991
+ #R = (t) => {
1992
+ this.disabled || (t.preventDefault(), this.#r = !0, this.#u?.focus(), this.#E(t));
1993
+ };
1994
+ #E(t) {
1995
+ if (!this.#a) return;
1996
+ const e = this.#a.getBoundingClientRect(), s = Math.max(0, Math.min(1, (t.clientX - e.left) / e.width)), i = Math.max(0, Math.min(1, (t.clientY - e.top) / e.height));
1997
+ this.#e = Math.round(s * 100), this.#i = Math.round((1 - i) * 100), this.#y(), this.#A();
1998
+ }
1999
+ #P = (t) => {
2000
+ if (this.disabled) return;
2001
+ const e = t.shiftKey ? 10 : 1;
2002
+ let s = !1;
2003
+ switch (t.key) {
2004
+ case "ArrowRight":
2005
+ this.#e = Math.min(100, this.#e + e), s = !0;
2006
+ break;
2007
+ case "ArrowLeft":
2008
+ this.#e = Math.max(0, this.#e - e), s = !0;
2009
+ break;
2010
+ case "ArrowUp":
2011
+ this.#i = Math.min(100, this.#i + e), s = !0;
2012
+ break;
2013
+ case "ArrowDown":
2014
+ this.#i = Math.max(0, this.#i - e), s = !0;
2015
+ break;
2016
+ }
2017
+ s && (t.preventDefault(), this.#y(), this.#A(), this.#$());
2018
+ };
2019
+ // ───────────────────────────────────────────────────────────────────────────
2020
+ // Hue handlers
2021
+ // ───────────────────────────────────────────────────────────────────────────
2022
+ #O = (t) => {
2023
+ this.disabled || (t.preventDefault(), this.#n = !0, this.#f?.focus(), this.#C(t));
2024
+ };
2025
+ #C(t) {
2026
+ if (!this.#b) return;
2027
+ const e = this.#b.getBoundingClientRect(), s = Math.max(0, Math.min(1, (t.clientX - e.left) / e.width));
2028
+ this.#t = Math.round(s * 360), this.#y(), this.#A();
2029
+ }
2030
+ #K = (t) => {
2031
+ if (this.disabled) return;
2032
+ const e = t.shiftKey ? 10 : 1;
2033
+ let s = !1;
2034
+ switch (t.key) {
2035
+ case "ArrowRight":
2036
+ case "ArrowUp":
2037
+ this.#t = (this.#t + e) % 360, s = !0;
2038
+ break;
2039
+ case "ArrowLeft":
2040
+ case "ArrowDown":
2041
+ this.#t = (this.#t - e + 360) % 360, s = !0;
2042
+ break;
2043
+ }
2044
+ s && (t.preventDefault(), this.#y(), this.#A(), this.#$());
2045
+ };
2046
+ // ───────────────────────────────────────────────────────────────────────────
2047
+ // Alpha handlers
2048
+ // ───────────────────────────────────────────────────────────────────────────
2049
+ #W = (t) => {
2050
+ this.disabled || (t.preventDefault(), this.#l = !0, this.#o?.focus(), this.#S(t));
2051
+ };
2052
+ #S(t) {
2053
+ if (!this.#g) return;
2054
+ const e = this.#g.getBoundingClientRect(), s = Math.max(0, Math.min(1, (t.clientX - e.left) / e.width));
2055
+ this.#s = Math.round(s * 100), this.#y(), this.#A();
2056
+ }
2057
+ #V = (t) => {
2058
+ if (this.disabled) return;
2059
+ const e = t.shiftKey ? 10 : 1;
2060
+ let s = !1;
2061
+ switch (t.key) {
2062
+ case "ArrowRight":
2063
+ case "ArrowUp":
2064
+ this.#s = Math.min(100, this.#s + e), s = !0;
2065
+ break;
2066
+ case "ArrowLeft":
2067
+ case "ArrowDown":
2068
+ this.#s = Math.max(0, this.#s - e), s = !0;
2069
+ break;
2070
+ }
2071
+ s && (t.preventDefault(), this.#y(), this.#A(), this.#$());
2072
+ };
2073
+ // ───────────────────────────────────────────────────────────────────────────
2074
+ // Pointer move/up
2075
+ // ───────────────────────────────────────────────────────────────────────────
2076
+ #q = (t) => {
2077
+ this.#r ? this.#E(t) : this.#n ? this.#C(t) : this.#l && this.#S(t);
2078
+ };
2079
+ #N = () => {
2080
+ (this.#r || this.#n || this.#l) && (this.#r = !1, this.#n = !1, this.#l = !1, this.#$());
2081
+ };
2082
+ // ───────────────────────────────────────────────────────────────────────────
2083
+ // Input handlers
2084
+ // ───────────────────────────────────────────────────────────────────────────
2085
+ #T = () => {
2086
+ if (!this.#h) return;
2087
+ const t = m(this.#h.value);
2088
+ t ? (this.#t = t.hsv.h, this.#e = t.hsv.s, this.#i = t.hsv.v, this.hasAttribute("opacity") && (this.#s = t.alpha), this.#y(), this.#$()) : this.#M();
2089
+ };
2090
+ #U = (t) => {
2091
+ t.key === "Enter" && (t.preventDefault(), this.#T());
2092
+ };
2093
+ // ───────────────────────────────────────────────────────────────────────────
2094
+ // Format toggle
2095
+ // ───────────────────────────────────────────────────────────────────────────
2096
+ #z = () => {
2097
+ const t = ["hex", "rgb", "hsl"], e = this.format, s = t.indexOf(e), i = t[(s + 1) % t.length];
2098
+ this.format = i;
2099
+ const r = this.$('[data-ry-target="format-toggle"]');
2100
+ r && (r.textContent = i.toUpperCase()), this.#M();
2101
+ };
2102
+ // ───────────────────────────────────────────────────────────────────────────
2103
+ // Swatches
2104
+ // ───────────────────────────────────────────────────────────────────────────
2105
+ #Y = (t) => {
2106
+ const e = t.target;
2107
+ if (e.classList.contains("ry-color-picker__swatch")) {
2108
+ const s = e.dataset.color;
2109
+ if (s) {
2110
+ const i = m(s);
2111
+ i && (this.#t = i.hsv.h, this.#e = i.hsv.s, this.#i = i.hsv.v, this.hasAttribute("opacity") && (this.#s = i.alpha), this.#y(), this.#A(), this.#$());
2112
+ }
2113
+ }
2114
+ };
2115
+ // ───────────────────────────────────────────────────────────────────────────
2116
+ // Update methods
2117
+ // ───────────────────────────────────────────────────────────────────────────
2118
+ #y() {
2119
+ this.#H(), this.#L(), this.#I(), this.#D(), this.#F(), this.#M(), this.#G();
2120
+ }
2121
+ #H() {
2122
+ const t = this.$('[data-ry-target="trigger-color"]');
2123
+ if (t) {
2124
+ const e = b({ h: this.#t, s: this.#e, v: this.#i }), s = this.hasAttribute("opacity") ? this.#s / 100 : 1;
2125
+ t.style.backgroundColor = `rgba(${e.r}, ${e.g}, ${e.b}, ${s})`;
2126
+ }
2127
+ }
2128
+ #L() {
2129
+ if (this.#a) {
2130
+ const t = b({ h: this.#t, s: 100, v: 100 });
2131
+ this.#a.style.setProperty("--grid-hue-color", `rgb(${t.r}, ${t.g}, ${t.b})`);
2132
+ }
2133
+ this.#u && (this.#u.style.left = `${this.#e}%`, this.#u.style.top = `${100 - this.#i}%`);
2134
+ }
2135
+ #I() {
2136
+ this.#f && (this.#f.style.left = `${this.#t / 360 * 100}%`);
2137
+ }
2138
+ #D() {
2139
+ if (this.#g) {
2140
+ const t = b({ h: this.#t, s: this.#e, v: this.#i });
2141
+ this.#g.style.setProperty("--alpha-color", `rgb(${t.r}, ${t.g}, ${t.b})`);
2142
+ }
2143
+ this.#o && (this.#o.style.left = `${this.#s}%`);
2144
+ }
2145
+ #F() {
2146
+ const t = this.$('[data-ry-target="preview-color"]');
2147
+ if (t) {
2148
+ const e = b({ h: this.#t, s: this.#e, v: this.#i }), s = this.hasAttribute("opacity") ? this.#s / 100 : 1;
2149
+ t.style.backgroundColor = `rgba(${e.r}, ${e.g}, ${e.b}, ${s})`;
2150
+ }
2151
+ }
2152
+ #M() {
2153
+ this.#h && (this.#h.value = this.#_());
2154
+ }
2155
+ #G() {
2156
+ const t = this.#_();
2157
+ this.getAttribute("value") !== t && this.setAttribute("value", t);
2158
+ }
2159
+ #_() {
2160
+ const t = this.format, e = b({ h: this.#t, s: this.#e, v: this.#i }), s = this.hasAttribute("opacity");
2161
+ switch (t) {
2162
+ case "hex": {
2163
+ const i = E(e);
2164
+ if (s && this.#s < 100) {
2165
+ const r = Math.round(this.#s / 100 * 255).toString(16).padStart(2, "0");
2166
+ return i + r;
2167
+ }
2168
+ return i;
2169
+ }
2170
+ case "rgb":
2171
+ return s ? `rgba(${e.r}, ${e.g}, ${e.b}, ${(this.#s / 100).toFixed(2)})` : `rgb(${e.r}, ${e.g}, ${e.b})`;
2172
+ case "hsl": {
2173
+ const i = M({ h: this.#t, s: this.#e, v: this.#i });
2174
+ return s ? `hsla(${i.h}, ${i.s}%, ${i.l}%, ${(this.#s / 100).toFixed(2)})` : `hsl(${i.h}, ${i.s}%, ${i.l}%)`;
2175
+ }
2176
+ default:
2177
+ return E(e);
2178
+ }
2179
+ }
2180
+ // ───────────────────────────────────────────────────────────────────────────
2181
+ // Events
2182
+ // ───────────────────────────────────────────────────────────────────────────
2183
+ #A() {
2184
+ this.emit("input", { value: this.value, hsv: this.hsv, rgb: this.rgb });
2185
+ }
2186
+ #$() {
2187
+ this.emit("change", { value: this.value, hsv: this.hsv, rgb: this.rgb });
2188
+ }
2189
+ // ───────────────────────────────────────────────────────────────────────────
2190
+ // Attribute changed
2191
+ // ───────────────────────────────────────────────────────────────────────────
2192
+ attributeChangedCallback(t, e, s) {
2193
+ if (e !== s && t === "value" && this.#a && s) {
2194
+ const i = m(s);
2195
+ i && (this.#t = i.hsv.h, this.#e = i.hsv.s, this.#i = i.hsv.v, this.hasAttribute("opacity") && (this.#s = i.alpha), this.#H(), this.#L(), this.#I(), this.#D(), this.#F());
2196
+ }
2197
+ }
2198
+ // ───────────────────────────────────────────────────────────────────────────
2199
+ // Public API
2200
+ // ───────────────────────────────────────────────────────────────────────────
2201
+ get value() {
2202
+ return this.#_();
2203
+ }
2204
+ set value(t) {
2205
+ const e = m(t);
2206
+ e && (this.#t = e.hsv.h, this.#e = e.hsv.s, this.#i = e.hsv.v, this.hasAttribute("opacity") && (this.#s = e.alpha), this.#y());
2207
+ }
2208
+ get format() {
2209
+ return this.getAttribute("format") || "hex";
2210
+ }
2211
+ set format(t) {
2212
+ this.setAttribute("format", t);
2213
+ }
2214
+ get disabled() {
2215
+ return this.hasAttribute("disabled");
2216
+ }
2217
+ set disabled(t) {
2218
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
2219
+ }
2220
+ get hsv() {
2221
+ return { h: this.#t, s: this.#e, v: this.#i };
2222
+ }
2223
+ get rgb() {
2224
+ return b(this.hsv);
2225
+ }
2226
+ get hsl() {
2227
+ return M(this.hsv);
2228
+ }
2229
+ get alpha() {
2230
+ return this.#s;
2231
+ }
2232
+ set alpha(t) {
2233
+ this.#s = Math.max(0, Math.min(100, t)), this.#y();
2234
+ }
2235
+ /** Set color from any valid color string */
2236
+ setColor(t) {
2237
+ const e = m(t);
2238
+ return e ? (this.#t = e.hsv.h, this.#e = e.hsv.s, this.#i = e.hsv.v, this.hasAttribute("opacity") && (this.#s = e.alpha), this.#y(), !0) : !1;
2239
+ }
2240
+ /** Get color in specific format */
2241
+ getFormattedValue(t) {
2242
+ const e = this.format;
2243
+ this.format = t;
2244
+ const s = this.#_();
2245
+ return this.format = e, s;
2246
+ }
2247
+ }
2248
+ customElements.define("ry-color-picker", rt);
2249
+ class at extends d {
2250
+ #t = null;
2251
+ #e = null;
2252
+ #i = null;
2253
+ #s = null;
2254
+ static observedAttributes = ["value", "format", "opacity", "disabled", "placeholder"];
2255
+ setup() {
2256
+ this.#r(), this.#n(), this.#k(), this.state = "closed";
2257
+ }
2258
+ #r() {
2259
+ const t = this.hasAttribute("opacity"), e = this.getAttribute("format") || "hex", s = this.getAttribute("value") || "#000000", i = this.getAttribute("placeholder") || "#000000";
2260
+ this.innerHTML = `
2261
+ <div data-ry-target="trigger" class="ry-color-input__trigger">
2262
+ <button data-ry-target="swatch" type="button" class="ry-color-input__swatch">
2263
+ <span data-ry-target="swatch-color" class="ry-color-input__swatch-color"></span>
2264
+ </button>
2265
+ <input
2266
+ data-ry-target="input"
2267
+ type="text"
2268
+ class="ry-color-input__input"
2269
+ value="${s.startsWith("#") ? s : "#" + s}"
2270
+ placeholder="${i.startsWith("#") ? i : "#" + i}"
2271
+ spellcheck="false"
2272
+ autocomplete="off"
2273
+ maxlength="7"
2274
+ />
2275
+ </div>
2276
+ <div data-ry-target="panel" class="ry-color-input__panel">
2277
+ <ry-color-picker
2278
+ data-ry-target="picker"
2279
+ inline
2280
+ value="${s}"
2281
+ format="${e}"
2282
+ ${t ? "opacity" : ""}
2283
+ ></ry-color-picker>
2284
+ </div>
2285
+ `, this.#t = this.$('[data-ry-target="swatch"]'), this.#e = this.$('[data-ry-target="input"]'), this.#i = this.$('[data-ry-target="panel"]'), this.#s = this.$('[data-ry-target="picker"]');
2286
+ }
2287
+ #n() {
2288
+ this.#t && this.on(this.#t, "click", this.#l), this.#e && (this.on(this.#e, "input", this.#p), this.on(this.#e, "keydown", this.#b), this.on(this.#e, "focus", this.#c)), this.#s && (this.on(this.#s, "ry:input", this.#f), this.on(this.#s, "ry:change", this.#g)), this.on(document, "click", this.#o), this.on(document, "keydown", this.#w);
2289
+ }
2290
+ #l = () => {
2291
+ this.disabled || (this.state === "open" ? this.close() : this.open());
2292
+ };
2293
+ #c = () => {
2294
+ this.disabled || this.open();
2295
+ };
2296
+ #p = () => {
2297
+ if (!this.#e || !this.#s) return;
2298
+ let t = this.#e.value;
2299
+ const e = this.#e.selectionStart ?? t.length, r = "#" + t.replace(/[^#a-fA-F0-9]/g, "").replace(/#/g, "").slice(0, 6);
2300
+ if (t !== r) {
2301
+ this.#e.value = r;
2302
+ const n = Math.min(e, r.length);
2303
+ this.#e.setSelectionRange(n, n);
2304
+ }
2305
+ const a = this.#a(r);
2306
+ a && (this.#s.setColor(a), this.#d(), this.#u(r) && this.#v(), this.emit("input", { value: this.value }));
2307
+ };
2308
+ #a(t) {
2309
+ let e = t;
2310
+ e.startsWith("#") || (e = "#" + e);
2311
+ const s = e.slice(1);
2312
+ if (!/^[a-fA-F0-9]+$/.test(s) || s.length === 0)
2313
+ return null;
2314
+ if (s.length === 6)
2315
+ return e;
2316
+ if (s.length <= 3) {
2317
+ const i = s.padEnd(3, s[s.length - 1]), [r, a, n] = i.split("");
2318
+ return `#${r}${r}${a}${a}${n}${n}`;
2319
+ }
2320
+ return "#" + s.padEnd(6, "0");
2321
+ }
2322
+ #u(t) {
2323
+ return !!(/^#[a-fA-F0-9]{6}$/.test(t) || /^#[a-fA-F0-9]{3}$/.test(t));
2324
+ }
2325
+ #b = (t) => {
2326
+ t.key === "Enter" && (t.preventDefault(), this.#p(), this.emit("change", { value: this.value }));
2327
+ };
2328
+ #f = () => {
2329
+ !this.#s || !this.#e || (document.activeElement !== this.#e && (this.#e.value = this.#s.value), this.#d(), this.#v(), this.emit("input", { value: this.value }));
2330
+ };
2331
+ #g = () => {
2332
+ this.emit("change", { value: this.value });
2333
+ };
2334
+ #o = (t) => {
2335
+ this.state === "open" && (this.contains(t.target) || this.close());
2336
+ };
2337
+ #w = (t) => {
2338
+ t.key === "Escape" && this.state === "open" && (this.close(), this.#t?.focus());
2339
+ };
2340
+ open() {
2341
+ this.#h(), this.state = "open";
2342
+ }
2343
+ close() {
2344
+ this.state = "closed", this.removeAttribute("data-ry-position");
2345
+ }
2346
+ #h() {
2347
+ if (!this.#i) return;
2348
+ const t = this.getBoundingClientRect(), e = 280, i = window.innerHeight - t.bottom, r = t.top;
2349
+ i < e && r > i ? this.setAttribute("data-ry-position", "top") : this.setAttribute("data-ry-position", "bottom");
2350
+ }
2351
+ #d() {
2352
+ const t = this.$('[data-ry-target="swatch-color"]');
2353
+ if (t && this.#s) {
2354
+ const e = this.#s.rgb, s = this.hasAttribute("opacity") ? this.#s.alpha / 100 : 1;
2355
+ t.style.backgroundColor = `rgba(${e.r}, ${e.g}, ${e.b}, ${s})`;
2356
+ }
2357
+ }
2358
+ #k() {
2359
+ const t = this.getAttribute("value") || "#000000";
2360
+ if (this.#s) {
2361
+ if (this.#s.setColor(t), this.#e) {
2362
+ const e = this.#s.value;
2363
+ this.#e.value = e.startsWith("#") ? e : "#" + e;
2364
+ }
2365
+ this.#d();
2366
+ }
2367
+ }
2368
+ #v() {
2369
+ if (this.#s) {
2370
+ const t = this.#s.value;
2371
+ this.getAttribute("value") !== t && this.setAttribute("value", t);
2372
+ }
2373
+ }
2374
+ attributeChangedCallback(t, e, s) {
2375
+ e !== s && (t === "value" && this.#s && this.#e && s && (this.#s.setColor(s), document.activeElement !== this.#e && (this.#e.value = this.#s.value), this.#d()), t === "disabled" && this.#e && (s !== null ? this.#e.setAttribute("disabled", "") : this.#e.removeAttribute("disabled")));
2376
+ }
2377
+ // Public API
2378
+ get value() {
2379
+ return this.#s?.value ?? this.getAttribute("value") ?? "#000000";
2380
+ }
2381
+ set value(t) {
2382
+ this.#s?.setColor(t) && (this.#e && (this.#e.value = this.#s.value), this.#d(), this.#v());
2383
+ }
2384
+ get disabled() {
2385
+ return this.hasAttribute("disabled");
2386
+ }
2387
+ set disabled(t) {
2388
+ t ? this.setAttribute("disabled", "") : this.removeAttribute("disabled");
2389
+ }
2390
+ get rgb() {
2391
+ return this.#s?.rgb ?? { r: 0, g: 0, b: 0 };
2392
+ }
2393
+ get hsl() {
2394
+ return this.#s?.hsl ?? { h: 0, s: 0, l: 0 };
2395
+ }
2396
+ get hsv() {
2397
+ return this.#s?.hsv ?? { h: 0, s: 0, v: 0 };
2398
+ }
2399
+ }
2400
+ customElements.define("ry-color-input", at);
2401
+ window.RyToast = p;
2402
+ console.log("ry-ui loaded");
2403
+ export {
2404
+ T as RyAccordion,
2405
+ B as RyAlert,
2406
+ D as RyButton,
2407
+ z as RyCode,
2408
+ at as RyColorInput,
2409
+ rt as RyColorPicker,
2410
+ W as RyDrawer,
2411
+ I as RyDropdown,
2412
+ d as RyElement,
2413
+ Y as RyExample,
2414
+ j as RyField,
2415
+ G as RyIcon,
2416
+ et as RyKnob,
2417
+ H as RyModal,
2418
+ N as RySelect,
2419
+ tt as RySlider,
2420
+ P as RySwitch,
2421
+ L as RyTabs,
2422
+ F as RyThemeToggle,
2423
+ p as RyToast,
2424
+ Q as RyToggleButton,
2425
+ K as RyTooltip,
2426
+ y as getIcon,
2427
+ lt as getIconNames,
2428
+ _ as processTransforms,
2429
+ ot as registerIcon,
2430
+ ht as registerIcons,
2431
+ k as transform
2432
+ };
2433
+ //# sourceMappingURL=ry-ui.js.map