@phantompixeldev/retrocss 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.
package/dist/retro.js ADDED
@@ -0,0 +1,1251 @@
1
+ var RetroCSS = (() => {
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/js/retro.js
21
+ var retro_exports = {};
22
+ __export(retro_exports, {
23
+ default: () => retro_default
24
+ });
25
+
26
+ // src/js/components/modal.js
27
+ var RetroModal = {
28
+ init(root = document) {
29
+ document.addEventListener("click", (e) => {
30
+ const openTrigger = e.target.closest('[data-toggle="modal"], .modal-demo-btn, [data-retro-modal]');
31
+ if (openTrigger && root.contains(openTrigger)) {
32
+ e.preventDefault();
33
+ const targetId = openTrigger.getAttribute("data-target") || openTrigger.getAttribute("data-retro-modal");
34
+ if (targetId) {
35
+ this.show(targetId);
36
+ } else {
37
+ console.warn("Modal trigger missing target ID", openTrigger);
38
+ }
39
+ return;
40
+ }
41
+ const closeBtn = e.target.closest('.retro-modal-close, [data-close="modal"]');
42
+ if (closeBtn && root.contains(closeBtn)) {
43
+ e.preventDefault();
44
+ const modal = closeBtn.closest(".retro-modal");
45
+ if (modal) this.hide(modal.id);
46
+ return;
47
+ }
48
+ if (e.target.classList.contains("retro-modal")) this.hide(e.target.id);
49
+ });
50
+ document.addEventListener("keydown", (e) => {
51
+ if (e.key === "Escape") {
52
+ const openModal = document.querySelector(".retro-modal.show");
53
+ if (openModal) this.hide(openModal.id);
54
+ }
55
+ });
56
+ console.log("Modal component initialized");
57
+ },
58
+ show(modalId) {
59
+ const modal = document.getElementById(modalId);
60
+ if (modal) {
61
+ modal.classList.add("show");
62
+ document.body.style.overflow = "hidden";
63
+ console.log(`Modal ${modalId} opened`);
64
+ } else {
65
+ console.warn(`Modal with ID ${modalId} not found`);
66
+ }
67
+ },
68
+ hide(modalId) {
69
+ const modal = document.getElementById(modalId);
70
+ if (modal) {
71
+ modal.classList.remove("show");
72
+ document.body.style.overflow = "";
73
+ console.log(`Modal ${modalId} closed`);
74
+ }
75
+ }
76
+ };
77
+ var modal_default = RetroModal;
78
+
79
+ // src/js/components/toast.js
80
+ var RetroToast = {
81
+ show(message, options = {}) {
82
+ let container = document.getElementById("retro-toast-container");
83
+ if (!container) {
84
+ container = document.createElement("div");
85
+ container.id = "retro-toast-container";
86
+ document.body.appendChild(container);
87
+ }
88
+ const toast = document.createElement("div");
89
+ toast.className = "retro-toast";
90
+ if (options.type) {
91
+ toast.classList.add(`retro-toast-${options.type}`);
92
+ }
93
+ if (options.html) {
94
+ toast.classList.add("retro-toast-html");
95
+ toast.innerHTML = message;
96
+ } else {
97
+ toast.textContent = message;
98
+ }
99
+ container.appendChild(toast);
100
+ setTimeout(() => {
101
+ toast.remove();
102
+ }, options.duration || 3e3);
103
+ }
104
+ };
105
+ var toast_default = RetroToast;
106
+
107
+ // src/js/components/form.js
108
+ var RetroForm = {
109
+ init(root = document) {
110
+ root.querySelectorAll(".retro-form").forEach((form) => {
111
+ form.addEventListener("submit", (e) => {
112
+ if (!this.validate(form)) {
113
+ e.preventDefault();
114
+ }
115
+ });
116
+ form.querySelectorAll("input, textarea, select").forEach((field) => {
117
+ field.addEventListener("blur", () => this.validateField(field));
118
+ });
119
+ });
120
+ },
121
+ validate(form) {
122
+ let valid = true;
123
+ form.querySelectorAll("input, textarea, select").forEach((field) => {
124
+ if (!this.validateField(field)) valid = false;
125
+ });
126
+ return valid;
127
+ },
128
+ validateField(field) {
129
+ const errorClass = "retro-form-error";
130
+ let error = field.parentNode.querySelector("." + errorClass);
131
+ if (error) error.remove();
132
+ let valid = true;
133
+ if (field.hasAttribute("required") && !field.value.trim()) {
134
+ valid = false;
135
+ this.showError(field, "This field is required");
136
+ }
137
+ if (field.type === "email" && field.value && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(field.value)) {
138
+ valid = false;
139
+ this.showError(field, "Please enter a valid email");
140
+ }
141
+ field.classList.toggle("invalid", !valid);
142
+ field.classList.toggle("valid", valid);
143
+ return valid;
144
+ },
145
+ showError(field, message) {
146
+ const error = document.createElement("div");
147
+ error.className = "retro-form-error";
148
+ error.textContent = message;
149
+ field.parentNode.appendChild(error);
150
+ }
151
+ };
152
+ var form_default = RetroForm;
153
+
154
+ // src/js/components/table.js
155
+ var RetroTable = {
156
+ init(root = document) {
157
+ root.querySelectorAll(".retro-table-sortable").forEach((table) => {
158
+ table.addEventListener("click", function(e) {
159
+ const th = e.target.closest("th");
160
+ if (!th || !table.contains(th)) return;
161
+ const ths = table.querySelectorAll("th");
162
+ const idx = Array.from(ths).indexOf(th);
163
+ if (idx === -1) return;
164
+ const tbody = table.querySelector("tbody");
165
+ const rows = Array.from(tbody.querySelectorAll("tr"));
166
+ const isAsc = th.classList.toggle("asc");
167
+ th.classList.toggle("desc", !isAsc);
168
+ ths.forEach((oth) => {
169
+ if (oth !== th) oth.classList.remove("asc", "desc");
170
+ });
171
+ rows.sort((a, b) => {
172
+ let t1 = a.children[idx].textContent.trim();
173
+ let t2 = b.children[idx].textContent.trim();
174
+ let n1 = parseFloat(t1), n2 = parseFloat(t2);
175
+ if (!isNaN(n1) && !isNaN(n2)) {
176
+ return isAsc ? n1 - n2 : n2 - n1;
177
+ }
178
+ return isAsc ? t1.localeCompare(t2) : t2.localeCompare(t1);
179
+ });
180
+ rows.forEach((row) => tbody.appendChild(row));
181
+ });
182
+ });
183
+ }
184
+ };
185
+ var table_default = RetroTable;
186
+
187
+ // src/js/components/dropdown.js
188
+ var RetroDropdown = {
189
+ init(root = document) {
190
+ document.addEventListener("click", function(e) {
191
+ const toggle = e.target.closest(".retro-dropdown .retro-dropdown-toggle");
192
+ if (toggle && root.contains(toggle)) {
193
+ e.preventDefault();
194
+ e.stopPropagation();
195
+ const drop = toggle.closest(".retro-dropdown");
196
+ if (drop) {
197
+ root.querySelectorAll(".retro-dropdown.open").forEach((other) => {
198
+ if (other !== drop) other.classList.remove("open");
199
+ });
200
+ drop.classList.toggle("open");
201
+ const menu = drop.querySelector(".retro-dropdown-menu");
202
+ if (menu) {
203
+ if (menu.parentElement !== drop) {
204
+ console.warn("retro-dropdown-menu should be a direct child of retro-dropdown for CSS to work.");
205
+ }
206
+ const toggleRect = toggle.getBoundingClientRect();
207
+ const menuRect = menu.getBoundingClientRect();
208
+ const spaceBelow = window.innerHeight - toggleRect.bottom;
209
+ const spaceAbove = toggleRect.top;
210
+ if (spaceBelow < menuRect.height && spaceAbove > spaceBelow) {
211
+ menu.style.bottom = "100%";
212
+ menu.style.top = "auto";
213
+ } else {
214
+ menu.style.top = "100%";
215
+ menu.style.bottom = "auto";
216
+ }
217
+ }
218
+ }
219
+ return;
220
+ }
221
+ const item = e.target.closest(".retro-dropdown-menu .retro-dropdown-item");
222
+ if (item && root.contains(item)) {
223
+ const drop = item.closest(".retro-dropdown");
224
+ if (drop) drop.classList.remove("open");
225
+ return;
226
+ }
227
+ root.querySelectorAll(".retro-dropdown.open").forEach((drop) => {
228
+ if (!drop.contains(e.target)) {
229
+ drop.classList.remove("open");
230
+ }
231
+ });
232
+ });
233
+ document.addEventListener("keydown", function(e) {
234
+ if (e.key === "Escape") {
235
+ root.querySelectorAll(".retro-dropdown.open").forEach((drop) => {
236
+ drop.classList.remove("open");
237
+ });
238
+ }
239
+ });
240
+ }
241
+ };
242
+ var dropdown_default = RetroDropdown;
243
+
244
+ // src/js/components/file-upload.js
245
+ var RetroFileUpload = {
246
+ init(root = document) {
247
+ root.querySelectorAll(".retro-file-upload").forEach((upload) => {
248
+ const input = upload.querySelector(".retro-file-input");
249
+ const display = upload.querySelector(".retro-file-filename, .retro-file-display");
250
+ const label = upload.querySelector(".retro-file-label");
251
+ const drop = upload.querySelector(".retro-file-drop");
252
+ if (!input || !display) return;
253
+ input.addEventListener("change", function() {
254
+ if (this.files && this.files.length) {
255
+ const fileNames = Array.from(this.files).map((f) => f.name).join(", ");
256
+ display.textContent = fileNames;
257
+ upload.classList.add("has-files");
258
+ } else {
259
+ display.textContent = display.dataset.placeholder || "No file chosen";
260
+ upload.classList.remove("has-files");
261
+ }
262
+ });
263
+ if (label) {
264
+ label.addEventListener("click", (e) => {
265
+ e.preventDefault();
266
+ input.click();
267
+ });
268
+ }
269
+ if (drop) {
270
+ drop.addEventListener("click", (e) => {
271
+ e.preventDefault();
272
+ input.click();
273
+ });
274
+ drop.addEventListener("dragover", (e) => {
275
+ e.preventDefault();
276
+ drop.classList.add("dragover");
277
+ });
278
+ drop.addEventListener("dragleave", () => {
279
+ drop.classList.remove("dragover");
280
+ });
281
+ drop.addEventListener("drop", (e) => {
282
+ e.preventDefault();
283
+ drop.classList.remove("dragover");
284
+ if (e.dataTransfer.files.length) {
285
+ input.files = e.dataTransfer.files;
286
+ const event = new Event("change", { bubbles: true });
287
+ input.dispatchEvent(event);
288
+ }
289
+ });
290
+ }
291
+ });
292
+ console.log("File uploads initialized:", root.querySelectorAll(".retro-file-upload").length);
293
+ }
294
+ };
295
+ var file_upload_default = RetroFileUpload;
296
+
297
+ // src/js/components/events.js
298
+ var RetroEvents = {
299
+ _events: {},
300
+ /**
301
+ * Register an event handler
302
+ * @param {string} event - Event name to listen for
303
+ * @param {function} handler - Handler function to call
304
+ */
305
+ on(event, handler) {
306
+ if (!this._events[event]) this._events[event] = [];
307
+ this._events[event].push(handler);
308
+ },
309
+ /**
310
+ * Remove an event handler
311
+ * @param {string} event - Event name
312
+ * @param {function} handler - Handler function to remove
313
+ */
314
+ off(event, handler) {
315
+ if (this._events[event]) {
316
+ this._events[event] = this._events[event].filter((h) => h !== handler);
317
+ }
318
+ },
319
+ /**
320
+ * Emit an event with optional data
321
+ * @param {string} event - Event name to emit
322
+ * @param {object} detail - Data to pass to handlers
323
+ */
324
+ emit(event, detail = {}) {
325
+ if (this._events[event]) {
326
+ this._events[event].forEach((handler) => handler(detail));
327
+ }
328
+ document.dispatchEvent(new CustomEvent(`retro:${event}`, {
329
+ detail,
330
+ bubbles: true
331
+ }));
332
+ }
333
+ };
334
+ var events_default = RetroEvents;
335
+
336
+ // src/js/carousel.js
337
+ (function() {
338
+ function RetroCarousel(root) {
339
+ this.root = root;
340
+ this.track = root.querySelector(".retro-carousel-track");
341
+ this.slides = Array.from(root.querySelectorAll(".retro-carousel-slide"));
342
+ this.dots = Array.from(root.querySelectorAll(".retro-carousel-dot"));
343
+ this.leftArrow = root.querySelector(".retro-carousel-arrow.left");
344
+ this.rightArrow = root.querySelector(".retro-carousel-arrow.right");
345
+ this.current = 0;
346
+ this.slideWidth = 100;
347
+ if (this.slides.length === 0) return;
348
+ if (this.dots.length === 0 && this.slides.length > 1) {
349
+ this.createDots();
350
+ }
351
+ this.init();
352
+ }
353
+ RetroCarousel.prototype.createDots = function() {
354
+ const dotsContainer = this.root.querySelector(".retro-carousel-dots");
355
+ if (!dotsContainer) {
356
+ const newDotsContainer = document.createElement("div");
357
+ newDotsContainer.className = "retro-carousel-dots";
358
+ this.root.appendChild(newDotsContainer);
359
+ for (let i = 0; i < this.slides.length; i++) {
360
+ const dot = document.createElement("div");
361
+ dot.className = "retro-carousel-dot";
362
+ dot.setAttribute("data-index", i);
363
+ newDotsContainer.appendChild(dot);
364
+ }
365
+ this.dots = Array.from(this.root.querySelectorAll(".retro-carousel-dot"));
366
+ }
367
+ };
368
+ RetroCarousel.prototype.init = function() {
369
+ if (this.leftArrow) {
370
+ this.leftArrow.addEventListener("click", () => {
371
+ this.goTo(this.current - 1);
372
+ });
373
+ }
374
+ if (this.rightArrow) {
375
+ this.rightArrow.addEventListener("click", () => {
376
+ this.goTo(this.current + 1);
377
+ });
378
+ }
379
+ this.dots.forEach((dot, i) => {
380
+ dot.addEventListener("click", () => {
381
+ this.goTo(i);
382
+ });
383
+ });
384
+ this.goTo(0);
385
+ let startX, moveX;
386
+ this.root.addEventListener("touchstart", (e) => {
387
+ startX = e.touches[0].clientX;
388
+ }, { passive: true });
389
+ this.root.addEventListener("touchmove", (e) => {
390
+ moveX = e.touches[0].clientX;
391
+ }, { passive: true });
392
+ this.root.addEventListener("touchend", () => {
393
+ if (startX && moveX) {
394
+ const diff = startX - moveX;
395
+ if (Math.abs(diff) > 50) {
396
+ if (diff > 0) {
397
+ this.goTo(this.current + 1);
398
+ } else {
399
+ this.goTo(this.current - 1);
400
+ }
401
+ }
402
+ }
403
+ startX = null;
404
+ moveX = null;
405
+ });
406
+ console.log("Carousel initialized:", this.slides.length, "slides");
407
+ };
408
+ RetroCarousel.prototype.goTo = function(idx) {
409
+ if (idx < 0) idx = this.slides.length - 1;
410
+ if (idx >= this.slides.length) idx = 0;
411
+ this.current = idx;
412
+ if (this.track) {
413
+ const position = -this.slideWidth * idx;
414
+ this.track.style.transform = `translateX(${position}%)`;
415
+ }
416
+ this.dots.forEach((dot, i) => {
417
+ dot.classList.toggle("active", i === idx);
418
+ });
419
+ };
420
+ RetroCarousel.init = function() {
421
+ document.querySelectorAll(".retro-carousel").forEach(function(root) {
422
+ new RetroCarousel(root);
423
+ });
424
+ };
425
+ window.RetroCarousel = RetroCarousel;
426
+ })();
427
+
428
+ // src/js/tabs.js
429
+ var RetroTabs = class {
430
+ constructor(selector, options = {}) {
431
+ this.tabContainer = document.querySelector(selector);
432
+ if (!this.tabContainer) return;
433
+ this.options = {
434
+ contentSelector: options.contentSelector || ".retro-tab-content",
435
+ activeClass: options.activeClass || "active",
436
+ defaultTab: options.defaultTab || 0,
437
+ ...options
438
+ };
439
+ this.tabs = Array.from(this.tabContainer.querySelectorAll(".retro-nav-item"));
440
+ this.contentElements = this.options.contentContainer ? Array.from(document.querySelector(this.options.contentContainer).children) : Array.from(this.tabContainer.nextElementSibling.querySelectorAll(this.options.contentSelector));
441
+ this.init();
442
+ }
443
+ init() {
444
+ this.contentElements.forEach((content) => {
445
+ content.style.display = "none";
446
+ });
447
+ this.tabs.forEach((tab, index) => {
448
+ tab.addEventListener("click", (e) => {
449
+ e.preventDefault();
450
+ this.activateTab(index);
451
+ });
452
+ tab.addEventListener("keydown", (e) => {
453
+ if (e.key === "Enter" || e.key === " ") {
454
+ e.preventDefault();
455
+ this.activateTab(index);
456
+ }
457
+ if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
458
+ e.preventDefault();
459
+ const direction = e.key === "ArrowLeft" ? -1 : 1;
460
+ let newIndex = index + direction;
461
+ if (newIndex < 0) newIndex = this.tabs.length - 1;
462
+ if (newIndex >= this.tabs.length) newIndex = 0;
463
+ this.tabs[newIndex].focus();
464
+ }
465
+ });
466
+ });
467
+ this.activateTab(this.options.defaultTab);
468
+ }
469
+ activateTab(index) {
470
+ this.tabs.forEach((tab) => {
471
+ tab.classList.remove(this.options.activeClass);
472
+ tab.setAttribute("aria-selected", "false");
473
+ });
474
+ this.tabs[index].classList.add(this.options.activeClass);
475
+ this.tabs[index].setAttribute("aria-selected", "true");
476
+ var visibleContent = null;
477
+ for (var i = 0; i < this.contentElements.length; i++) {
478
+ if (this.contentElements[i].style.display === "block") {
479
+ visibleContent = this.contentElements[i];
480
+ break;
481
+ }
482
+ }
483
+ this.contentElements.forEach((content) => {
484
+ if (content !== this.contentElements[index]) {
485
+ content.style.display = "none";
486
+ }
487
+ });
488
+ var selectedContent = this.contentElements[index];
489
+ selectedContent.style.opacity = "0";
490
+ selectedContent.style.display = "block";
491
+ selectedContent.offsetHeight;
492
+ setTimeout(function() {
493
+ selectedContent.style.opacity = "1";
494
+ }, 10);
495
+ }
496
+ static init() {
497
+ }
498
+ };
499
+ var RetroTabsInit = {
500
+ init: function() {
501
+ const tabbedNavs = document.querySelectorAll(".retro-nav-tabbed");
502
+ tabbedNavs.forEach((nav) => {
503
+ let contentContainer = nav.nextElementSibling;
504
+ if (!contentContainer || !contentContainer.classList.contains("retro-tab-pane")) {
505
+ const existingContent = nav.nextElementSibling;
506
+ if (existingContent) {
507
+ const wrapper = document.createElement("div");
508
+ wrapper.className = "retro-tab-pane";
509
+ nav.parentNode.insertBefore(wrapper, existingContent);
510
+ const tabs = Array.from(nav.querySelectorAll(".retro-nav-item"));
511
+ tabs.forEach((tab, i) => {
512
+ const content = document.createElement("div");
513
+ content.className = "retro-tab-content";
514
+ if (i === 0 && tabs[0].classList.contains("active")) {
515
+ content.appendChild(existingContent);
516
+ } else {
517
+ content.textContent = `Content for ${tab.textContent}`;
518
+ content.style.padding = "20px";
519
+ content.style.border = "2px solid #000";
520
+ content.style.borderTop = "0";
521
+ content.style.background = "#fff";
522
+ }
523
+ wrapper.appendChild(content);
524
+ });
525
+ contentContainer = wrapper;
526
+ }
527
+ }
528
+ new RetroTabs(nav, {
529
+ contentContainer: ".retro-tab-pane",
530
+ defaultTab: Array.from(nav.querySelectorAll(".retro-nav-item")).findIndex((tab) => tab.classList.contains("active"))
531
+ });
532
+ });
533
+ const underlinedNavs = document.querySelectorAll(".retro-nav-underlined");
534
+ underlinedNavs.forEach((nav) => {
535
+ let contentContainer = nav.nextElementSibling;
536
+ if (!contentContainer || !contentContainer.classList.contains("retro-tab-pane")) {
537
+ const existingContent = nav.nextElementSibling;
538
+ if (existingContent) {
539
+ const wrapper = document.createElement("div");
540
+ wrapper.className = "retro-tab-pane retro-tab-pane-underlined";
541
+ nav.parentNode.insertBefore(wrapper, existingContent);
542
+ const tabs = Array.from(nav.querySelectorAll(".retro-nav-item"));
543
+ tabs.forEach((tab, i) => {
544
+ const content = document.createElement("div");
545
+ content.className = "retro-tab-content";
546
+ if (i === 0 && tabs[0].classList.contains("active")) {
547
+ content.appendChild(existingContent);
548
+ } else {
549
+ content.textContent = `Content for ${tab.textContent}`;
550
+ content.style.padding = "20px";
551
+ content.style.marginTop = "10px";
552
+ content.style.background = "#f5f5f5";
553
+ }
554
+ wrapper.appendChild(content);
555
+ });
556
+ contentContainer = wrapper;
557
+ }
558
+ }
559
+ new RetroTabs(nav, {
560
+ contentContainer: ".retro-tab-pane-underlined",
561
+ defaultTab: Array.from(nav.querySelectorAll(".retro-nav-item")).findIndex((tab) => tab.classList.contains("active"))
562
+ });
563
+ });
564
+ const buttonNavs = document.querySelectorAll(".retro-nav-buttons");
565
+ buttonNavs.forEach((nav) => {
566
+ const nextEl = nav.nextElementSibling;
567
+ if (nextEl && !nextEl.tagName.match(/^(H[1-6]|NAV)$/i)) {
568
+ let contentContainer = nextEl;
569
+ if (!contentContainer.classList.contains("retro-tab-pane")) {
570
+ const wrapper = document.createElement("div");
571
+ wrapper.className = "retro-tab-pane retro-tab-pane-buttons";
572
+ nav.parentNode.insertBefore(wrapper, nextEl);
573
+ const tabs = Array.from(nav.querySelectorAll(".retro-nav-item"));
574
+ tabs.forEach((tab, i) => {
575
+ const content = document.createElement("div");
576
+ content.className = "retro-tab-content";
577
+ if (i === 0 && tabs[0].classList.contains("active") || tab.classList.contains("active")) {
578
+ content.appendChild(nextEl);
579
+ } else {
580
+ content.textContent = `Content for ${tab.textContent}`;
581
+ content.style.padding = "20px";
582
+ content.style.marginTop = "10px";
583
+ content.style.background = "#f5f5f5";
584
+ }
585
+ wrapper.appendChild(content);
586
+ });
587
+ contentContainer = wrapper;
588
+ }
589
+ new RetroTabs(nav, {
590
+ contentContainer: ".retro-tab-pane-buttons",
591
+ defaultTab: Array.from(nav.querySelectorAll(".retro-nav-item")).findIndex((tab) => tab.classList.contains("active"))
592
+ });
593
+ }
594
+ });
595
+ }
596
+ };
597
+ var RetroAccordion = class _RetroAccordion {
598
+ constructor(selector) {
599
+ const accordions = document.querySelectorAll(selector);
600
+ accordions.forEach((accordion) => {
601
+ const toggles = accordion.querySelectorAll(".retro-accordion-toggle");
602
+ toggles.forEach((toggle) => {
603
+ toggle.addEventListener("click", () => {
604
+ const item = toggle.parentElement;
605
+ const isActive = item.classList.contains("active");
606
+ const content = toggle.nextElementSibling;
607
+ if (!content) return;
608
+ const icon = toggle.querySelector(".retro-accordion-icon");
609
+ if (isActive) {
610
+ item.classList.remove("active");
611
+ content.style.maxHeight = "0";
612
+ if (icon) icon.textContent = "+";
613
+ } else {
614
+ const siblings = accordion.querySelectorAll(".retro-accordion-item.active");
615
+ siblings.forEach((sibling) => {
616
+ sibling.classList.remove("active");
617
+ const siblingContent = sibling.querySelector(".retro-accordion-content");
618
+ if (siblingContent) siblingContent.style.maxHeight = "0";
619
+ const siblingIcon = sibling.querySelector(".retro-accordion-icon");
620
+ if (siblingIcon) siblingIcon.textContent = "+";
621
+ });
622
+ item.classList.add("active");
623
+ content.style.maxHeight = content.scrollHeight + "px";
624
+ if (icon) icon.textContent = "-";
625
+ }
626
+ });
627
+ });
628
+ });
629
+ console.log("Accordion component initialized");
630
+ }
631
+ static init(selector = ".retro-accordion") {
632
+ new _RetroAccordion(selector);
633
+ const observer = new MutationObserver((mutations) => {
634
+ mutations.forEach((mutation) => {
635
+ if (mutation.type === "childList" && mutation.addedNodes.length) {
636
+ mutation.addedNodes.forEach((node) => {
637
+ if (node.nodeType === 1 && (node.matches(selector) || node.querySelector(selector))) {
638
+ new _RetroAccordion(selector);
639
+ }
640
+ });
641
+ }
642
+ });
643
+ });
644
+ observer.observe(document.body, {
645
+ childList: true,
646
+ subtree: true
647
+ });
648
+ }
649
+ };
650
+ window.RetroTabs = RetroTabsInit;
651
+ window.RetroAccordion = RetroAccordion;
652
+
653
+ // src/js/code-copy.js
654
+ var RetroCodeCopy = {
655
+ init() {
656
+ const codeBlocks = document.querySelectorAll(".retro-code");
657
+ codeBlocks.forEach((block) => {
658
+ if (!block.querySelector(".retro-code-copy")) {
659
+ const copyButton = document.createElement("button");
660
+ copyButton.className = "retro-code-copy";
661
+ copyButton.textContent = "Copy";
662
+ block.appendChild(copyButton);
663
+ copyButton.addEventListener("click", async () => {
664
+ const code = block.querySelector("code").textContent;
665
+ try {
666
+ await navigator.clipboard.writeText(code);
667
+ const originalText = copyButton.textContent;
668
+ copyButton.textContent = "Copied!";
669
+ copyButton.style.background = "#c0c0c0";
670
+ setTimeout(() => {
671
+ copyButton.textContent = originalText;
672
+ copyButton.style.background = "";
673
+ }, 2e3);
674
+ } catch (err) {
675
+ console.error("Failed to copy code:", err);
676
+ copyButton.textContent = "Failed to copy";
677
+ copyButton.style.background = "#ffcccc";
678
+ setTimeout(() => {
679
+ copyButton.textContent = "Copy";
680
+ copyButton.style.background = "";
681
+ }, 2e3);
682
+ }
683
+ });
684
+ }
685
+ });
686
+ }
687
+ };
688
+ window.RetroCodeCopy = RetroCodeCopy;
689
+
690
+ // src/js/infinite-scroll.js
691
+ var RetroInfiniteScroll = {
692
+ isLoading: false,
693
+ page: 1,
694
+ itemsPerPage: 5,
695
+ maxPages: 5,
696
+ // For demo purposes
697
+ init() {
698
+ const containers = document.querySelectorAll(".retro-infinite-scroll");
699
+ if (!containers.length) return;
700
+ containers.forEach((container) => {
701
+ this.appendItems(container, 1);
702
+ container.addEventListener("scroll", () => {
703
+ if (this.isNearBottom(container) && !this.isLoading && this.page < this.maxPages) {
704
+ this.loadMoreItems(container);
705
+ }
706
+ });
707
+ });
708
+ },
709
+ isNearBottom(container) {
710
+ return container.scrollHeight - container.scrollTop - container.clientHeight < 50;
711
+ },
712
+ loadMoreItems(container) {
713
+ const loader = container.querySelector(".retro-infinite-loader");
714
+ this.isLoading = true;
715
+ if (loader) loader.style.display = "flex";
716
+ setTimeout(() => {
717
+ this.page++;
718
+ this.appendItems(container, this.page);
719
+ this.isLoading = false;
720
+ if (loader) loader.style.display = "none";
721
+ if (this.page >= this.maxPages) {
722
+ const endMessage = document.createElement("div");
723
+ endMessage.className = "retro-infinite-end";
724
+ endMessage.textContent = "End of content";
725
+ endMessage.style.textAlign = "center";
726
+ endMessage.style.padding = "20px";
727
+ endMessage.style.color = "var(--retro-border-medium)";
728
+ container.appendChild(endMessage);
729
+ }
730
+ }, 800);
731
+ },
732
+ appendItems(container, page) {
733
+ const loader = container.querySelector(".retro-infinite-loader");
734
+ for (let i = 1; i <= this.itemsPerPage; i++) {
735
+ const itemIndex = (page - 1) * this.itemsPerPage + i;
736
+ const item = document.createElement("div");
737
+ item.className = "retro-card retro-mb-3";
738
+ const card = `
739
+ <div class="retro-card-header">
740
+ Item ${itemIndex}
741
+ </div>
742
+ <div class="retro-card-content">
743
+ <p>This is demo content for infinite scroll. Scroll down to load more items.</p>
744
+ <div class="retro-progress" style="margin-top: 10px;">
745
+ <div class="retro-progress-bar" style="width: ${Math.floor(
746
+ Math.random() * 100
747
+ )}%;"></div>
748
+ </div>
749
+ </div>
750
+ `;
751
+ item.innerHTML = card;
752
+ if (loader) {
753
+ container.insertBefore(item, loader);
754
+ } else {
755
+ container.appendChild(item);
756
+ }
757
+ }
758
+ }
759
+ };
760
+ window.RetroInfiniteScroll = RetroInfiniteScroll;
761
+
762
+ // src/js/table-responsive.js
763
+ document.addEventListener("DOMContentLoaded", function() {
764
+ document.querySelectorAll("table.retro-table").forEach(function(table) {
765
+ if (!table.parentElement.classList.contains("retro-table-responsive")) {
766
+ var wrapper = document.createElement("div");
767
+ wrapper.className = "retro-table-responsive";
768
+ table.parentNode.insertBefore(wrapper, table);
769
+ wrapper.appendChild(table);
770
+ }
771
+ });
772
+ });
773
+
774
+ // src/js/sidebar.js
775
+ var RetroSidebar = {
776
+ // Configuration
777
+ config: {
778
+ sidebarSelector: ".retro-sidebar",
779
+ toggleSelector: ".retro-sidebar-toggle",
780
+ overlaySelector: ".retro-sidebar-overlay",
781
+ activeClass: "active",
782
+ mobileBreakpoint: 768,
783
+ transitionDuration: 300,
784
+ // ms
785
+ bodyOpenClass: "sidebar-open"
786
+ },
787
+ // State
788
+ isOpen: false,
789
+ // Initialize the sidebar
790
+ init() {
791
+ const sidebar = document.querySelector(this.config.sidebarSelector);
792
+ if (!sidebar) return;
793
+ sidebar.setAttribute("role", "navigation");
794
+ sidebar.setAttribute("aria-label", "Sidebar Navigation");
795
+ this.setupLinks(sidebar);
796
+ this.setupMobile();
797
+ this.setupScrollTracking();
798
+ this.setupResizeHandler();
799
+ this.setActiveLink();
800
+ },
801
+ // Setup sidebar links
802
+ setupLinks(sidebar) {
803
+ const sidebarLinks = sidebar.querySelectorAll("a");
804
+ sidebarLinks.forEach((link) => {
805
+ link.addEventListener("focus", () => {
806
+ link.style.outline = "1px dotted var(--retro-primary)";
807
+ });
808
+ link.addEventListener("blur", () => {
809
+ link.style.outline = "";
810
+ });
811
+ if (link.getAttribute("href")?.startsWith("#")) {
812
+ link.addEventListener("click", (e) => {
813
+ const targetId = link.getAttribute("href");
814
+ const targetElement = document.querySelector(targetId);
815
+ if (targetElement) {
816
+ e.preventDefault();
817
+ targetElement.scrollIntoView({
818
+ behavior: "smooth",
819
+ block: "start"
820
+ });
821
+ history.pushState(null, "", targetId);
822
+ this.setActiveLink(link);
823
+ if (window.innerWidth < this.config.mobileBreakpoint) {
824
+ this.closeSidebar();
825
+ }
826
+ }
827
+ });
828
+ }
829
+ });
830
+ },
831
+ // Setup mobile functionality
832
+ setupMobile() {
833
+ let toggleBtn = document.querySelector(this.config.toggleSelector);
834
+ if (!toggleBtn) {
835
+ toggleBtn = document.createElement("button");
836
+ toggleBtn.className = "retro-sidebar-toggle";
837
+ toggleBtn.innerHTML = '<div class="retro-sidebar-toggle-icon"><span></span></div>';
838
+ toggleBtn.setAttribute("aria-label", "Toggle Sidebar");
839
+ const sidebar = document.querySelector(this.config.sidebarSelector);
840
+ if (sidebar && sidebar.parentNode) {
841
+ sidebar.parentNode.insertBefore(toggleBtn, sidebar);
842
+ }
843
+ }
844
+ let overlay = document.querySelector(this.config.overlaySelector);
845
+ if (!overlay) {
846
+ overlay = document.createElement("div");
847
+ overlay.className = "retro-sidebar-overlay";
848
+ document.body.appendChild(overlay);
849
+ }
850
+ toggleBtn.addEventListener("click", () => this.toggleSidebar());
851
+ overlay.addEventListener("click", () => this.closeSidebar());
852
+ document.addEventListener("keydown", (e) => {
853
+ if (e.key === "Escape" && this.isOpen) {
854
+ this.closeSidebar();
855
+ }
856
+ });
857
+ },
858
+ // Toggle the sidebar open/closed
859
+ toggleSidebar() {
860
+ const sidebar = document.querySelector(this.config.sidebarSelector);
861
+ const overlay = document.querySelector(this.config.overlaySelector);
862
+ if (!sidebar || !overlay) return;
863
+ if (this.isOpen) {
864
+ this.closeSidebar();
865
+ } else {
866
+ sidebar.classList.add(this.config.activeClass);
867
+ overlay.classList.add(this.config.activeClass);
868
+ document.body.classList.add(this.config.bodyOpenClass);
869
+ this.isOpen = true;
870
+ }
871
+ },
872
+ // Close the sidebar
873
+ closeSidebar() {
874
+ const sidebar = document.querySelector(this.config.sidebarSelector);
875
+ const overlay = document.querySelector(this.config.overlaySelector);
876
+ if (!sidebar || !overlay) return;
877
+ sidebar.classList.remove(this.config.activeClass);
878
+ overlay.classList.remove(this.config.activeClass);
879
+ document.body.classList.remove(this.config.bodyOpenClass);
880
+ this.isOpen = false;
881
+ },
882
+ // Setup scroll position tracking
883
+ setupScrollTracking() {
884
+ const sidebar = document.querySelector(this.config.sidebarSelector);
885
+ if (!sidebar) return;
886
+ window.addEventListener("scroll", () => {
887
+ this.updateActiveOnScroll();
888
+ });
889
+ },
890
+ // Update active link based on scroll position
891
+ updateActiveOnScroll() {
892
+ const sections = document.querySelectorAll("section[id], div[id]");
893
+ if (sections.length === 0) return;
894
+ let currentSection = null;
895
+ let maxVisiblePercentage = 0;
896
+ sections.forEach((section) => {
897
+ const rect = section.getBoundingClientRect();
898
+ const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
899
+ if (isVisible) {
900
+ const visibleHeight = Math.min(rect.bottom, window.innerHeight) - Math.max(rect.top, 0);
901
+ const visiblePercentage = visibleHeight / rect.height;
902
+ if (visiblePercentage > maxVisiblePercentage) {
903
+ maxVisiblePercentage = visiblePercentage;
904
+ currentSection = section;
905
+ }
906
+ }
907
+ });
908
+ if (currentSection) {
909
+ const id = currentSection.getAttribute("id");
910
+ const link = document.querySelector(`.retro-sidebar a[href="#${id}"]`);
911
+ if (link) {
912
+ this.setActiveLink(link);
913
+ }
914
+ }
915
+ },
916
+ // Set active link
917
+ setActiveLink(activeLink = null) {
918
+ const sidebar = document.querySelector(this.config.sidebarSelector);
919
+ if (!sidebar) return;
920
+ if (!activeLink) {
921
+ const hash = window.location.hash;
922
+ if (hash) {
923
+ activeLink = sidebar.querySelector(`a[href="${hash}"]`);
924
+ } else {
925
+ const currentPath = window.location.pathname;
926
+ activeLink = sidebar.querySelector(`a[href="${currentPath}"]`) || sidebar.querySelector("a");
927
+ }
928
+ }
929
+ sidebar.querySelectorAll("a").forEach((link) => {
930
+ link.classList.remove(this.config.activeClass);
931
+ });
932
+ if (activeLink) {
933
+ activeLink.classList.add(this.config.activeClass);
934
+ }
935
+ },
936
+ // Setup resize handler
937
+ setupResizeHandler() {
938
+ window.addEventListener("resize", () => {
939
+ if (window.innerWidth >= this.config.mobileBreakpoint && this.isOpen) {
940
+ this.closeSidebar();
941
+ }
942
+ });
943
+ }
944
+ };
945
+ window.RetroSidebar = RetroSidebar;
946
+
947
+ // src/js/datetime.js
948
+ (function() {
949
+ document.querySelectorAll('input[type="date"], input[type="time"]').forEach(function(input) {
950
+ input.addEventListener("change", function() {
951
+ if (window.RetroCSS && RetroCSS.toast) {
952
+ RetroCSS.toast.show("Selected: " + input.value, { type: "info" });
953
+ }
954
+ });
955
+ });
956
+ })();
957
+
958
+ // src/js/retro.js
959
+ var RetroCSS2 = {
960
+ modal: modal_default,
961
+ toast: toast_default,
962
+ form: form_default,
963
+ table: table_default,
964
+ dropdown: dropdown_default,
965
+ fileUpload: file_upload_default,
966
+ events: events_default,
967
+ // Add references to standalone modules from the window object
968
+ carousel: window.RetroCarousel,
969
+ accordion: window.RetroAccordion,
970
+ tabs: window.RetroTabs,
971
+ infiniteScroll: window.RetroInfiniteScroll,
972
+ // Store theme preference
973
+ theme: localStorage.getItem("retro-theme") || "light",
974
+ // Initialize all components
975
+ init() {
976
+ console.log("RetroCSS initializing components...");
977
+ modal_default.init();
978
+ dropdown_default.init();
979
+ form_default.init();
980
+ table_default.init();
981
+ file_upload_default.init();
982
+ if (window.RetroCarousel && typeof window.RetroCarousel.init === "function") {
983
+ window.RetroCarousel.init();
984
+ console.log("Carousel initialized");
985
+ } else {
986
+ console.warn("RetroCarousel not available");
987
+ }
988
+ if (window.RetroTabsInit && typeof window.RetroTabsInit.init === "function") {
989
+ window.RetroTabsInit.init();
990
+ console.log("Tabs initialized");
991
+ }
992
+ if (window.RetroAccordion && typeof window.RetroAccordion.init === "function") {
993
+ window.RetroAccordion.init();
994
+ console.log("Accordion initialized");
995
+ }
996
+ if (window.RetroInfiniteScroll && typeof window.RetroInfiniteScroll.init === "function") {
997
+ window.RetroInfiniteScroll.init();
998
+ console.log("Infinite Scroll initialized");
999
+ }
1000
+ document.querySelectorAll("[data-retro-modal]").forEach((trigger) => {
1001
+ trigger.addEventListener("click", (e) => {
1002
+ e.preventDefault();
1003
+ const modalId = trigger.getAttribute("data-retro-modal");
1004
+ modal_default.show(modalId);
1005
+ });
1006
+ });
1007
+ this.initTooltips();
1008
+ this.initToastTriggers();
1009
+ this.initSearchBars();
1010
+ this.initTagInputs();
1011
+ this.initThemeToggle();
1012
+ this.applyTheme(this.theme);
1013
+ events_default.emit("init", { timestamp: Date.now() });
1014
+ this.initRatingStars();
1015
+ return this;
1016
+ },
1017
+ // Custom tooltip implementation
1018
+ initTooltips() {
1019
+ const tooltipTriggers = document.querySelectorAll("[data-retro-tooltip]");
1020
+ tooltipTriggers.forEach((trigger) => {
1021
+ const content = trigger.getAttribute("data-retro-tooltip");
1022
+ if (!content) return;
1023
+ const position = trigger.getAttribute("data-tooltip-position") || "top";
1024
+ const variant = trigger.getAttribute("data-tooltip-variant") || "";
1025
+ const tooltip = document.createElement("div");
1026
+ tooltip.className = `retro-tooltip retro-tooltip-${position}`;
1027
+ if (variant) tooltip.classList.add(`retro-tooltip-${variant}`);
1028
+ tooltip.textContent = content;
1029
+ const existingTooltip = trigger.querySelector(".retro-tooltip");
1030
+ if (existingTooltip) existingTooltip.remove();
1031
+ trigger.style.position = "relative";
1032
+ trigger.appendChild(tooltip);
1033
+ trigger.addEventListener("mouseenter", () => {
1034
+ tooltip.classList.add("show");
1035
+ });
1036
+ trigger.addEventListener("mouseleave", () => {
1037
+ tooltip.classList.remove("show");
1038
+ });
1039
+ });
1040
+ console.log("Tooltips initialized:", tooltipTriggers.length);
1041
+ },
1042
+ // Initialize toast trigger elements
1043
+ initToastTriggers() {
1044
+ const toastTriggers = document.querySelectorAll("[data-retro-toast]");
1045
+ toastTriggers.forEach((trigger) => {
1046
+ trigger.addEventListener("click", () => {
1047
+ const message = trigger.getAttribute("data-retro-toast");
1048
+ const type = trigger.getAttribute("data-retro-toast-type") || "";
1049
+ const duration = parseInt(trigger.getAttribute("data-retro-toast-duration")) || 3e3;
1050
+ const html = trigger.hasAttribute("data-retro-toast-html");
1051
+ toast_default.show(message, {
1052
+ type,
1053
+ duration,
1054
+ html
1055
+ });
1056
+ if (message === "Stacked Toast 1") {
1057
+ setTimeout(() => {
1058
+ toast_default.show("Stacked Toast 2", { type: "primary" });
1059
+ setTimeout(() => {
1060
+ toast_default.show("Stacked Toast 3", { type: "success" });
1061
+ }, 600);
1062
+ }, 600);
1063
+ }
1064
+ });
1065
+ });
1066
+ console.log("Toast triggers initialized:", toastTriggers.length);
1067
+ },
1068
+ // Initialize search bar components
1069
+ initSearchBars() {
1070
+ const searchBars = document.querySelectorAll(".retro-search-bar");
1071
+ searchBars.forEach((searchBar) => {
1072
+ const input = searchBar.querySelector(".retro-search-input");
1073
+ const suggestions = searchBar.querySelector(".retro-search-suggestions");
1074
+ if (!input) return;
1075
+ input.addEventListener("focus", () => {
1076
+ if (suggestions) {
1077
+ searchBar.classList.add("active");
1078
+ }
1079
+ });
1080
+ document.addEventListener("click", (e) => {
1081
+ if (!searchBar.contains(e.target)) {
1082
+ searchBar.classList.remove("active");
1083
+ }
1084
+ });
1085
+ if (suggestions) {
1086
+ const suggestionItems = suggestions.querySelectorAll(".retro-search-suggestion");
1087
+ suggestionItems.forEach((item) => {
1088
+ item.addEventListener("click", () => {
1089
+ input.value = item.textContent;
1090
+ searchBar.classList.remove("active");
1091
+ input.dispatchEvent(new Event("change", { bubbles: true }));
1092
+ input.focus();
1093
+ });
1094
+ });
1095
+ }
1096
+ input.addEventListener("input", () => {
1097
+ if (!suggestions) return;
1098
+ const value = input.value.trim().toLowerCase();
1099
+ suggestions.innerHTML = "";
1100
+ if (value) {
1101
+ const demoItems = [
1102
+ `${value} - Result 1`,
1103
+ `${value} - Result 2`,
1104
+ `${value} - Result 3`
1105
+ ];
1106
+ demoItems.forEach((item) => {
1107
+ const suggestion = document.createElement("div");
1108
+ suggestion.className = "retro-search-suggestion";
1109
+ suggestion.textContent = item;
1110
+ suggestion.addEventListener("click", () => {
1111
+ input.value = item;
1112
+ searchBar.classList.remove("active");
1113
+ input.focus();
1114
+ });
1115
+ suggestions.appendChild(suggestion);
1116
+ });
1117
+ searchBar.classList.add("active");
1118
+ } else {
1119
+ searchBar.classList.remove("active");
1120
+ }
1121
+ });
1122
+ });
1123
+ console.log("Search bars initialized:", searchBars.length);
1124
+ },
1125
+ // Initialize tag input components
1126
+ initTagInputs() {
1127
+ const tagInputs = document.querySelectorAll(".retro-tag-input");
1128
+ tagInputs.forEach((container) => {
1129
+ const tagsContainer = container.querySelector(".retro-tags");
1130
+ const input = container.querySelector(".retro-tag-text");
1131
+ if (!tagsContainer || !input) return;
1132
+ const tags = [];
1133
+ tagsContainer.querySelectorAll(".retro-tag").forEach((tag) => {
1134
+ const tagText = tag.textContent.replace("\xD7", "").trim();
1135
+ tags.push(tagText);
1136
+ const removeBtn = tag.querySelector(".retro-tag-remove");
1137
+ if (removeBtn) {
1138
+ removeBtn.addEventListener("click", () => {
1139
+ tag.remove();
1140
+ const index = tags.indexOf(tagText);
1141
+ if (index > -1) {
1142
+ tags.splice(index, 1);
1143
+ }
1144
+ });
1145
+ }
1146
+ });
1147
+ const addTag = (tagText) => {
1148
+ if (!tagText || tags.includes(tagText)) {
1149
+ input.value = "";
1150
+ return;
1151
+ }
1152
+ tags.push(tagText);
1153
+ const tag = document.createElement("span");
1154
+ tag.className = "retro-tag";
1155
+ tag.textContent = tagText;
1156
+ const removeBtn = document.createElement("span");
1157
+ removeBtn.className = "retro-tag-remove";
1158
+ removeBtn.textContent = "\xD7";
1159
+ removeBtn.addEventListener("click", () => {
1160
+ tag.remove();
1161
+ const index = tags.indexOf(tagText);
1162
+ if (index > -1) {
1163
+ tags.splice(index, 1);
1164
+ }
1165
+ });
1166
+ tag.appendChild(removeBtn);
1167
+ tagsContainer.appendChild(tag);
1168
+ input.value = "";
1169
+ };
1170
+ input.addEventListener("keydown", (e) => {
1171
+ if (e.key === "Enter" || e.key === ",") {
1172
+ e.preventDefault();
1173
+ const tagText = input.value.trim().replace(",", "");
1174
+ addTag(tagText);
1175
+ }
1176
+ });
1177
+ input.addEventListener("blur", () => {
1178
+ const tagText = input.value.trim();
1179
+ if (tagText) {
1180
+ addTag(tagText);
1181
+ }
1182
+ });
1183
+ });
1184
+ console.log("Tag inputs initialized:", tagInputs.length);
1185
+ },
1186
+ // Initialize theme toggle button
1187
+ initThemeToggle() {
1188
+ const themeToggles = document.querySelectorAll(".retro-theme-toggle");
1189
+ themeToggles.forEach((toggle) => {
1190
+ toggle.addEventListener("click", () => {
1191
+ this.theme = this.theme === "light" ? "dark" : "light";
1192
+ this.applyTheme(this.theme);
1193
+ localStorage.setItem("retro-theme", this.theme);
1194
+ toast_default.show(`Theme switched to ${this.theme} mode!`, {
1195
+ type: this.theme === "dark" ? "primary" : "light"
1196
+ });
1197
+ });
1198
+ });
1199
+ console.log("Theme toggles initialized:", themeToggles.length);
1200
+ },
1201
+ // Apply theme to document
1202
+ applyTheme(theme) {
1203
+ if (theme === "dark") {
1204
+ document.documentElement.setAttribute("data-theme", "dark");
1205
+ } else {
1206
+ document.documentElement.removeAttribute("data-theme");
1207
+ }
1208
+ },
1209
+ // Interactive rating stars
1210
+ initRatingStars() {
1211
+ const ratings = document.querySelectorAll(".retro-rating");
1212
+ ratings.forEach((rating) => {
1213
+ const stars = rating.querySelectorAll(".retro-rating-star");
1214
+ let selected = -1;
1215
+ if (rating.hasAttribute("data-rating")) {
1216
+ selected = parseInt(rating.getAttribute("data-rating")) - 1;
1217
+ stars.forEach((star, i) => {
1218
+ if (i <= selected) star.classList.add("selected");
1219
+ });
1220
+ }
1221
+ stars.forEach((star, idx) => {
1222
+ star.addEventListener("mouseenter", () => {
1223
+ stars.forEach((s, i) => {
1224
+ s.classList.toggle("active", i <= idx);
1225
+ });
1226
+ });
1227
+ star.addEventListener("mouseleave", () => {
1228
+ stars.forEach((s) => s.classList.remove("active"));
1229
+ });
1230
+ star.addEventListener("click", () => {
1231
+ selected = idx;
1232
+ stars.forEach((s, i) => {
1233
+ s.classList.toggle("selected", i <= idx);
1234
+ });
1235
+ rating.setAttribute("data-rating", idx + 1);
1236
+ rating.dispatchEvent(new CustomEvent("retro:rating", { detail: { rating: idx + 1 } }));
1237
+ });
1238
+ });
1239
+ });
1240
+ console.log("Rating stars initialized:", ratings.length);
1241
+ }
1242
+ };
1243
+ window.RetroCSS = RetroCSS2;
1244
+ if (document.readyState === "loading") {
1245
+ document.addEventListener("DOMContentLoaded", () => RetroCSS2.init());
1246
+ } else {
1247
+ RetroCSS2.init();
1248
+ }
1249
+ var retro_default = RetroCSS2;
1250
+ return __toCommonJS(retro_exports);
1251
+ })();