arekui 1.0.2 → 2.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 (98) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +16 -188
  3. package/arekui.css +3018 -367
  4. package/arekui.d.ts +47 -47
  5. package/arekui.js +402 -35
  6. package/assets/img/grunge-wall-texture-freepick-kues1.webp +0 -0
  7. package/assets/img/logo.png +0 -0
  8. package/dist/css/arekui.base.min.css +1 -0
  9. package/dist/css/arekui.broadsheet.min.css +1 -0
  10. package/dist/css/arekui.brutalist.min.css +1 -0
  11. package/dist/css/arekui.default.min.css +1 -0
  12. package/dist/css/arekui.full.min.css +1 -0
  13. package/dist/css/arekui.min.css +1 -0
  14. package/dist/css/arekui.neo.min.css +1 -0
  15. package/dist/css/arekui.pixel.min.css +1 -0
  16. package/dist/js/arekui.min.js +2 -0
  17. package/package.json +14 -9
  18. package/scripts/build-css.js +95 -0
  19. package/scripts/build-custom.js +65 -96
  20. package/scripts/build-js.js +68 -0
  21. package/scripts/clean.js +13 -0
  22. package/scripts/dev.js +97 -0
  23. package/scripts/imports.js +18 -0
  24. package/scripts/split.js +256 -0
  25. package/src/arekui.base.css +63 -0
  26. package/src/arekui.broadsheet.css +6 -0
  27. package/src/arekui.brutalist.css +8 -0
  28. package/src/arekui.core.css +64 -0
  29. package/src/arekui.css +73 -56
  30. package/src/arekui.default.css +6 -0
  31. package/src/arekui.neo.css +8 -0
  32. package/src/arekui.pixel.css +8 -0
  33. package/src/base/brutalist-overrides.css +254 -0
  34. package/src/base/neo-overrides.css +46 -31
  35. package/src/base/pixel-overrides.css +336 -0
  36. package/src/base/reset.css +118 -4
  37. package/src/base/theme-brutalist.css +111 -0
  38. package/src/base/theme-default.css +184 -0
  39. package/src/base/theme-neo.css +108 -0
  40. package/src/base/theme-pixel.css +111 -0
  41. package/src/base/tokens.css +10 -253
  42. package/src/components/accordion.css +1 -2
  43. package/src/components/alert.css +1 -2
  44. package/src/components/badge.css +1 -2
  45. package/src/components/breadcrumb.css +2 -3
  46. package/src/components/broadsheet.css +264 -0
  47. package/src/components/button.css +3 -2
  48. package/src/components/card.css +1 -2
  49. package/src/components/carousel.css +37 -1
  50. package/src/components/chat.css +5 -4
  51. package/src/components/description-list.css +34 -0
  52. package/src/components/docs.css +252 -0
  53. package/src/components/empty.css +36 -0
  54. package/src/components/file-upload.css +2 -3
  55. package/src/components/footer.css +16 -1
  56. package/src/components/forms.css +1 -2
  57. package/src/components/heading.css +27 -0
  58. package/src/components/hero.css +1 -2
  59. package/src/components/join.css +1 -2
  60. package/src/components/kbd.css +15 -0
  61. package/src/components/link.css +2 -3
  62. package/src/components/loading.css +109 -0
  63. package/src/components/menu.css +51 -1
  64. package/src/components/misc.css +40 -1
  65. package/src/components/modal.css +1 -2
  66. package/src/components/navbar.css +131 -1
  67. package/src/components/pagination.css +7 -2
  68. package/src/components/popover.css +5 -6
  69. package/src/components/progress.css +1 -2
  70. package/src/components/prose.css +2 -2
  71. package/src/components/rating.css +1 -2
  72. package/src/components/scroll-top.css +2 -2
  73. package/src/components/segmented.css +44 -0
  74. package/src/components/sidebar.css +377 -0
  75. package/src/components/skeleton.css +2 -2
  76. package/src/components/spinner.css +36 -0
  77. package/src/components/swap.css +2 -2
  78. package/src/components/table.css +1 -2
  79. package/src/components/tabs.css +2 -3
  80. package/src/components/tag.css +10 -10
  81. package/src/components/textured.css +22 -2
  82. package/src/components/timeline.css +1 -2
  83. package/src/components/toast.css +2 -2
  84. package/src/components/tooltip.css +1 -2
  85. package/src/utilities/borders.css +2 -2
  86. package/src/utilities/brutalist-utilities.css +49 -0
  87. package/src/utilities/colors.css +11 -3
  88. package/src/utilities/hover.css +2 -2
  89. package/src/utilities/layout.css +2 -2
  90. package/src/utilities/neo-utilities.css +2 -9
  91. package/src/utilities/pixel-utilities.css +88 -0
  92. package/src/utilities/responsive.css +7 -2
  93. package/src/utilities/sizing.css +16 -7
  94. package/src/utilities/spacing.css +5 -2
  95. package/src/utilities/typography.css +5 -2
  96. package/dist/arekui.min.css +0 -1
  97. package/dist/arekui.min.js +0 -2
  98. package/src/components/drawer.css +0 -53
package/arekui.js CHANGED
@@ -1,12 +1,18 @@
1
1
  /*!
2
- * Arekui v1.0.0 — optional vanilla JS (no dependencies).
3
- * data-ar-* driven behaviors: theme toggle, modal, drawer, tabs, dropdown, accordion, toast, rating, popover, file upload, scroll-to-top.
2
+ * ArekUI v2.0.0 — optional vanilla JS (no browser runtime dependencies).
3
+ * data-ar-* driven behaviors: theme toggle, modal, sidebar, tabs, dropdown, accordion, toast, rating, popover, file upload, scroll-to-top, carousel controls.
4
4
  */
5
5
  (() => {
6
6
  var STORAGE_KEY = "arekui-theme";
7
7
 
8
- var THEMES_LIGHT_DARK = ["light", "dark"];
9
- var THEMES_DEFAULT_NEO = ["light", "neo"];
8
+ var KNOWN_THEMES = ["light", "dark", "neo", "pixel", "brutalist"];
9
+ var THEME_LABELS = {
10
+ light: "Default",
11
+ dark: "Dark",
12
+ neo: "Neo",
13
+ pixel: "Pixel",
14
+ brutalist: "Brutalist",
15
+ };
10
16
 
11
17
  function getTheme() {
12
18
  return document.documentElement.getAttribute("data-theme");
@@ -15,12 +21,15 @@
15
21
  function setTheme(theme) {
16
22
  document.documentElement.setAttribute("data-theme", theme);
17
23
  document.documentElement.classList.toggle("dark", theme === "dark");
24
+ document.dispatchEvent(
25
+ new CustomEvent("ar-themechange", { detail: { theme: theme } }),
26
+ );
27
+ syncToggles();
18
28
  }
19
29
 
20
30
  function initTheme() {
21
31
  var stored = localStorage.getItem(STORAGE_KEY);
22
- var allThemes = THEMES_LIGHT_DARK.concat(THEMES_DEFAULT_NEO);
23
- if (stored && allThemes.indexOf(stored) !== -1) {
32
+ if (stored && KNOWN_THEMES.indexOf(stored) !== -1) {
24
33
  setTheme(stored);
25
34
  } else {
26
35
  var prefersDark = window.matchMedia(
@@ -30,6 +39,24 @@
30
39
  }
31
40
  }
32
41
 
42
+ function setToggleLabel(el, whenOn, whenOff, isOn) {
43
+ if (el.children.length > 0) return;
44
+ var current = (el.textContent || "").trim();
45
+ if (current !== whenOn && current !== whenOff) return;
46
+ el.textContent = isOn ? whenOn : whenOff;
47
+ }
48
+
49
+ function toggleCycle(el, attr, own) {
50
+ var other = (el.getAttribute(attr) || "").trim();
51
+ if (!THEME_LABELS[other] || other === own) other = "light";
52
+ return [other, own];
53
+ }
54
+
55
+ function nextTheme(cycle, current) {
56
+ var idx = cycle.indexOf(current);
57
+ return idx === -1 ? cycle[cycle.length - 1] : cycle[(idx + 1) % cycle.length];
58
+ }
59
+
33
60
  function syncToggles() {
34
61
  var current = getTheme();
35
62
  document.querySelectorAll("[data-ar-theme-toggle]").forEach((el) => {
@@ -45,7 +72,28 @@
45
72
  el.checked = isNeo;
46
73
  } else {
47
74
  el.setAttribute("aria-pressed", String(isNeo));
48
- el.textContent = isNeo ? "Default" : "Neo";
75
+ var cycle = toggleCycle(el, "data-ar-neo-toggle", "neo");
76
+ setToggleLabel(el, THEME_LABELS[cycle[0]], THEME_LABELS[cycle[1]], isNeo);
77
+ }
78
+ });
79
+ document.querySelectorAll("[data-ar-pixel-toggle]").forEach((el) => {
80
+ var isPixel = current === "pixel";
81
+ if (el.matches('input[type="checkbox"]')) {
82
+ el.checked = isPixel;
83
+ } else {
84
+ el.setAttribute("aria-pressed", String(isPixel));
85
+ var cycle = toggleCycle(el, "data-ar-pixel-toggle", "pixel");
86
+ setToggleLabel(el, THEME_LABELS[cycle[0]], THEME_LABELS[cycle[1]], isPixel);
87
+ }
88
+ });
89
+ document.querySelectorAll("[data-ar-brutalist-toggle]").forEach((el) => {
90
+ var isBrutalist = current === "brutalist";
91
+ if (el.matches('input[type="checkbox"]')) {
92
+ el.checked = isBrutalist;
93
+ } else {
94
+ el.setAttribute("aria-pressed", String(isBrutalist));
95
+ var cycle = toggleCycle(el, "data-ar-brutalist-toggle", "brutalist");
96
+ setToggleLabel(el, THEME_LABELS[cycle[0]], THEME_LABELS[cycle[1]], isBrutalist);
49
97
  }
50
98
  });
51
99
  }
@@ -55,8 +103,7 @@
55
103
  var toggle = e.target.closest("[data-ar-theme-toggle]");
56
104
  if (!toggle) return;
57
105
  var current = getTheme() || "light";
58
- var idx = THEMES_LIGHT_DARK.indexOf(current);
59
- var next = THEMES_LIGHT_DARK[(idx + 1) % THEMES_LIGHT_DARK.length];
106
+ var next = nextTheme(toggleCycle(toggle, "data-ar-theme-toggle", "dark"), current);
60
107
  setTheme(next);
61
108
  localStorage.setItem(STORAGE_KEY, next);
62
109
  syncToggles();
@@ -68,8 +115,31 @@
68
115
  var toggle = e.target.closest("[data-ar-neo-toggle]");
69
116
  if (!toggle) return;
70
117
  var current = getTheme() || "light";
71
- var idx = THEMES_DEFAULT_NEO.indexOf(current);
72
- var next = THEMES_DEFAULT_NEO[(idx + 1) % THEMES_DEFAULT_NEO.length];
118
+ var next = nextTheme(toggleCycle(toggle, "data-ar-neo-toggle", "neo"), current);
119
+ setTheme(next);
120
+ localStorage.setItem(STORAGE_KEY, next);
121
+ syncToggles();
122
+ });
123
+ }
124
+
125
+ function initPixelToggle() {
126
+ document.addEventListener("click", (e) => {
127
+ var toggle = e.target.closest("[data-ar-pixel-toggle]");
128
+ if (!toggle) return;
129
+ var current = getTheme() || "light";
130
+ var next = nextTheme(toggleCycle(toggle, "data-ar-pixel-toggle", "pixel"), current);
131
+ setTheme(next);
132
+ localStorage.setItem(STORAGE_KEY, next);
133
+ syncToggles();
134
+ });
135
+ }
136
+
137
+ function initBrutalistToggle() {
138
+ document.addEventListener("click", (e) => {
139
+ var toggle = e.target.closest("[data-ar-brutalist-toggle]");
140
+ if (!toggle) return;
141
+ var current = getTheme() || "light";
142
+ var next = nextTheme(toggleCycle(toggle, "data-ar-brutalist-toggle", "brutalist"), current);
73
143
  setTheme(next);
74
144
  localStorage.setItem(STORAGE_KEY, next);
75
145
  syncToggles();
@@ -102,32 +172,260 @@
102
172
  });
103
173
  }
104
174
 
105
- function initDrawers() {
106
- document.querySelectorAll("[data-ar-drawer-toggle]").forEach((btn) => {
175
+ var SIDEBAR_FOCUSABLE =
176
+ 'a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]),' +
177
+ ' textarea:not([disabled]), [tabindex]:not([tabindex="-1"])';
178
+
179
+ var SIDEBAR_BREAKPOINTS = { "ar-sidebar-bp-md": 768 };
180
+ var SIDEBAR_DEFAULT_BP = 1024;
181
+ var SIDEBAR_MEDIA = {};
182
+ function sidebarMedia(px) {
183
+ if (!SIDEBAR_MEDIA[px]) {
184
+ SIDEBAR_MEDIA[px] = window.matchMedia("(min-width: " + px + "px)");
185
+ }
186
+ return SIDEBAR_MEDIA[px];
187
+ }
188
+ function sidebarBreakpoint(sidebar) {
189
+ var px = SIDEBAR_DEFAULT_BP;
190
+ if (sidebar) {
191
+ Object.keys(SIDEBAR_BREAKPOINTS).forEach(function (name) {
192
+ if (sidebar.classList.contains(name)) px = SIDEBAR_BREAKPOINTS[name];
193
+ });
194
+ }
195
+ return px;
196
+ }
197
+ function isPersistentSidebar(sidebar) {
198
+ if (!sidebar || !sidebarMedia(sidebarBreakpoint(sidebar)).matches)
199
+ return false;
200
+ return (
201
+ sidebar.classList.contains("ar-sidebar-responsive") ||
202
+ sidebar.classList.contains("ar-sidebar-compact") ||
203
+ sidebar.classList.contains("ar-sidebar-nav")
204
+ );
205
+ }
206
+ function sidebarMediaAll() {
207
+ return [SIDEBAR_DEFAULT_BP]
208
+ .concat(
209
+ Object.keys(SIDEBAR_BREAKPOINTS).map(function (name) {
210
+ return SIDEBAR_BREAKPOINTS[name];
211
+ }),
212
+ )
213
+ .map(sidebarMedia);
214
+ }
215
+
216
+ function setSidebarState(sidebar, open) {
217
+ if (!sidebar) return;
218
+ sidebar.classList.toggle("ar-sidebar-is-open", !!open);
219
+ sidebar.classList.toggle("ar-sidebar-is-close", !open);
220
+ }
221
+
222
+ function trapFocus(panel, e) {
223
+ if (e.key !== "Tab") return;
224
+ var items = Array.prototype.filter.call(
225
+ panel.querySelectorAll(SIDEBAR_FOCUSABLE),
226
+ (el) => el.getClientRects().length > 0,
227
+ );
228
+ if (!items.length) {
229
+ e.preventDefault();
230
+ return;
231
+ }
232
+ var first = items[0];
233
+ var last = items[items.length - 1];
234
+ if (!panel.contains(document.activeElement)) {
235
+ e.preventDefault();
236
+ first.focus();
237
+ return;
238
+ }
239
+ if (e.shiftKey && document.activeElement === first) {
240
+ e.preventDefault();
241
+ last.focus();
242
+ return;
243
+ }
244
+ if (!e.shiftKey && document.activeElement === last) {
245
+ e.preventDefault();
246
+ first.focus();
247
+ }
248
+ }
249
+
250
+ function syncSidebar(cb) {
251
+ if (!cb) return;
252
+ var sidebar = cb.closest(".ar-sidebar");
253
+ if (!sidebar) return;
254
+ var panel = sidebar.querySelector(".ar-sidebar-panel");
255
+ var persistent = isPersistentSidebar(sidebar);
256
+ setSidebarState(sidebar, cb.checked || persistent);
257
+ if (persistent) {
258
+ cb.checked = false;
259
+ cb._arOpener = null;
260
+ if (panel) {
261
+ panel.removeAttribute("role");
262
+ panel.removeAttribute("aria-modal");
263
+ }
264
+ document.body.style.overflow = "";
265
+ document
266
+ .querySelectorAll('[data-ar-sidebar-toggle="' + cb.id + '"]')
267
+ .forEach((btn) => btn.setAttribute("aria-expanded", "false"));
268
+ return;
269
+ }
270
+ if (cb.checked && !cb._arOpener) {
271
+ var active = document.activeElement;
272
+ if (active && active !== document.body && !sidebar.contains(active))
273
+ cb._arOpener = active;
274
+ }
275
+ if (panel) {
276
+ if (cb.checked) {
277
+ panel.setAttribute("role", "dialog");
278
+ panel.setAttribute("aria-modal", "true");
279
+ panel.focus();
280
+ } else {
281
+ panel.removeAttribute("role");
282
+ panel.removeAttribute("aria-modal");
283
+ }
284
+ }
285
+ document.body.style.overflow = cb.checked ? "hidden" : "";
286
+ document
287
+ .querySelectorAll('[data-ar-sidebar-toggle="' + cb.id + '"]')
288
+ .forEach((btn) => {
289
+ btn.setAttribute("aria-expanded", cb.checked ? "true" : "false");
290
+ });
291
+ if (!cb.checked) {
292
+ var restore = cb._arOpener;
293
+ cb._arOpener = null;
294
+ if (restore && document.contains(restore)) restore.focus();
295
+ }
296
+ }
297
+
298
+ function initSidebars() {
299
+ document.querySelectorAll(".ar-sidebar-toggle").forEach((cb) => {
300
+ var sidebar = cb.closest(".ar-sidebar");
301
+ if (!sidebar) return;
302
+ var panel = sidebar.querySelector(".ar-sidebar-panel");
303
+ if (!panel) return;
304
+ panel.setAttribute("tabindex", "-1");
305
+ setSidebarState(sidebar, cb.checked || isPersistentSidebar(sidebar));
306
+ cb.addEventListener("change", () => syncSidebar(cb));
307
+ panel.addEventListener("keydown", (e) => {
308
+ if (e.key === "Escape" && cb.checked) {
309
+ cb.checked = false;
310
+ syncSidebar(cb);
311
+ return;
312
+ }
313
+ if (isPersistentSidebar(sidebar)) return;
314
+ trapFocus(panel, e);
315
+ });
316
+ panel.querySelectorAll("a[href]").forEach((link) => {
317
+ link.addEventListener("click", () => {
318
+ if (!cb.checked) return;
319
+ cb.checked = false;
320
+ syncSidebar(cb);
321
+ });
322
+ });
323
+ document
324
+ .querySelectorAll('[data-ar-sidebar-toggle="' + cb.id + '"]')
325
+ .forEach((btn) => {
326
+ btn.setAttribute("aria-controls", cb.id);
327
+ btn.setAttribute("aria-expanded", cb.checked ? "true" : "false");
328
+ });
329
+ });
330
+
331
+ document.querySelectorAll("[data-ar-sidebar-toggle]").forEach((btn) => {
107
332
  btn.addEventListener("click", () => {
108
- var id = btn.getAttribute("data-ar-drawer-toggle");
109
- var checkbox = document.getElementById(id);
110
- if (checkbox) checkbox.checked = !checkbox.checked;
333
+ var id = btn.getAttribute("data-ar-sidebar-toggle");
334
+ var cb = document.getElementById(id);
335
+ if (!cb) {
336
+ console.error(
337
+ '[ArekUI] data-ar-sidebar-toggle="' + id + '" matched no element',
338
+ );
339
+ return;
340
+ }
341
+ cb._arOpener = btn;
342
+ cb.checked = !cb.checked;
343
+ syncSidebar(cb);
111
344
  });
112
345
  });
346
+
347
+ document.querySelectorAll("[data-ar-sidebar-close]").forEach((closer) => {
348
+ closer.addEventListener("click", () => {
349
+ var sidebar = closer.closest(".ar-sidebar");
350
+ var cb = sidebar && sidebar.querySelector(".ar-sidebar-toggle");
351
+ if (!cb) return;
352
+ cb.checked = false;
353
+ syncSidebar(cb);
354
+ });
355
+ });
356
+
357
+ var onBreakpoint = () => {
358
+ document.querySelectorAll(".ar-sidebar-toggle").forEach((cb) => {
359
+ var sidebar = cb.closest(".ar-sidebar");
360
+ if (!sidebar) return;
361
+ setSidebarState(sidebar, cb.checked || isPersistentSidebar(sidebar));
362
+ if (cb.checked) syncSidebar(cb);
363
+ });
364
+ };
365
+ sidebarMediaAll().forEach((mql) => {
366
+ if (mql.addEventListener) mql.addEventListener("change", onBreakpoint);
367
+ else if (mql.addListener) mql.addListener(onBreakpoint);
368
+ });
369
+ }
370
+
371
+ function activateTab(tab, group) {
372
+ var panelId = tab.getAttribute("data-ar-tab");
373
+ group.querySelectorAll("[data-ar-tab]").forEach((t) => {
374
+ var isOn = t === tab;
375
+ t.classList.toggle("ar-tab-active", isOn);
376
+ t.setAttribute("aria-selected", String(isOn));
377
+ t.setAttribute("tabindex", isOn ? "0" : "-1");
378
+ });
379
+ var groupPanel = group.getAttribute("data-ar-tabs-panel");
380
+ if (groupPanel) {
381
+ var scope = group.parentElement || document;
382
+ var scoped = scope.querySelectorAll("[" + groupPanel + "]");
383
+ (scoped.length ? scoped : document.querySelectorAll("[" + groupPanel + "]")).forEach((p) => {
384
+ p.style.display = p.id === panelId ? "" : "none";
385
+ });
386
+ }
113
387
  }
114
388
 
115
389
  function initTabs() {
390
+ document.querySelectorAll(".ar-tabs").forEach((group) => {
391
+ group.setAttribute("role", "tablist");
392
+ });
116
393
  document.querySelectorAll("[data-ar-tab]").forEach((tab) => {
394
+ var panelId = tab.getAttribute("data-ar-tab");
395
+ var panel = document.getElementById(panelId);
396
+ if (panel && !tab.id) tab.id = panelId + "-tab";
397
+ tab.setAttribute("role", "tab");
398
+ if (panel) {
399
+ tab.setAttribute("aria-controls", panelId);
400
+ panel.setAttribute("role", "tabpanel");
401
+ panel.setAttribute("aria-labelledby", tab.id);
402
+ }
403
+ var isActive = tab.classList.contains("ar-tab-active");
404
+ tab.setAttribute("aria-selected", String(isActive));
405
+ tab.setAttribute("tabindex", isActive ? "0" : "-1");
406
+
117
407
  tab.addEventListener("click", () => {
408
+ var group = tab.closest(".ar-tabs");
409
+ if (group) activateTab(tab, group);
410
+ });
411
+
412
+ tab.addEventListener("keydown", (e) => {
118
413
  var group = tab.closest(".ar-tabs");
119
414
  if (!group) return;
120
- group.querySelectorAll("[data-ar-tab]").forEach((t) => {
121
- t.classList.remove("ar-tab-active");
122
- });
123
- tab.classList.add("ar-tab-active");
124
- var panelId = tab.getAttribute("data-ar-tab");
125
- var groupPanel = group.getAttribute("data-ar-tabs-panel");
126
- if (groupPanel) {
127
- document.querySelectorAll("[" + groupPanel + "]").forEach((p) => {
128
- p.style.display = p.id === panelId ? "" : "none";
129
- });
130
- }
415
+ var tabs = Array.from(group.querySelectorAll("[data-ar-tab]"));
416
+ if (!tabs.length) return;
417
+ var i = tabs.indexOf(tab);
418
+ var target;
419
+ if (e.key === "ArrowRight") target = (i + 1) % tabs.length;
420
+ else if (e.key === "ArrowLeft")
421
+ target = (i - 1 + tabs.length) % tabs.length;
422
+ else if (e.key === "Home") target = 0;
423
+ else if (e.key === "End") target = tabs.length - 1;
424
+ else return;
425
+ e.preventDefault();
426
+ var next = tabs[target];
427
+ activateTab(next, group);
428
+ next.focus();
131
429
  });
132
430
  });
133
431
  }
@@ -135,13 +433,24 @@
135
433
  function closeDropdown(dropdown) {
136
434
  dropdown.classList.remove("ar-dropdown-open");
137
435
  var trigger = dropdown.querySelector(":scope > button, :scope > a");
138
- if (trigger) trigger.blur();
436
+ if (trigger) {
437
+ trigger.setAttribute("aria-expanded", "false");
438
+ trigger.blur();
439
+ }
440
+ }
441
+
442
+ function openDropdown(dropdown) {
443
+ dropdown.classList.add("ar-dropdown-open");
444
+ var trigger = dropdown.querySelector(":scope > button, :scope > a");
445
+ if (trigger) trigger.setAttribute("aria-expanded", "true");
139
446
  }
140
447
 
141
448
  function initDropdowns() {
142
449
  document.querySelectorAll(".ar-dropdown").forEach((dropdown) => {
143
450
  var content = dropdown.querySelector(".ar-dropdown-content");
144
451
  if (!content) return;
452
+ var trigger = dropdown.querySelector(":scope > button, :scope > a");
453
+ if (trigger) trigger.setAttribute("aria-expanded", "false");
145
454
 
146
455
  dropdown.addEventListener("click", (e) => {
147
456
  if (content.contains(e.target)) {
@@ -151,7 +460,7 @@
151
460
  if (dropdown.classList.contains("ar-dropdown-open")) {
152
461
  closeDropdown(dropdown);
153
462
  } else {
154
- dropdown.classList.add("ar-dropdown-open");
463
+ openDropdown(dropdown);
155
464
  }
156
465
  });
157
466
  });
@@ -160,7 +469,7 @@
160
469
  document
161
470
  .querySelectorAll(".ar-dropdown.ar-dropdown-open")
162
471
  .forEach((dd) => {
163
- if (!dd.contains(e.target)) dd.classList.remove("ar-dropdown-open");
472
+ if (!dd.contains(e.target)) closeDropdown(dd);
164
473
  });
165
474
  });
166
475
 
@@ -178,9 +487,9 @@
178
487
  var first = d.querySelector("summary");
179
488
  if (first)
180
489
  first.addEventListener("click", () => {
181
- if (d.getAttribute("data-ar-exclusive") !== null) return;
182
490
  var parent = d.closest(".ar-accordion");
183
491
  if (!parent) return;
492
+ if (parent.getAttribute("data-ar-exclusive") === null) return;
184
493
  parent.querySelectorAll("details[open]").forEach((other) => {
185
494
  if (other !== d) other.removeAttribute("open");
186
495
  });
@@ -188,6 +497,38 @@
188
497
  });
189
498
  }
190
499
 
500
+ function scrollCarousel(carousel, direction) {
501
+ if (!carousel) return;
502
+ var amount = carousel.clientWidth || 300;
503
+ var reduce =
504
+ window.matchMedia &&
505
+ window.matchMedia("(prefers-reduced-motion: reduce)").matches;
506
+ carousel.scrollBy({
507
+ left: direction * amount,
508
+ behavior: reduce ? "auto" : "smooth",
509
+ });
510
+ }
511
+
512
+ function findCarousel(btn, attrName) {
513
+ var id = btn.getAttribute(attrName);
514
+ if (id) return document.getElementById(id);
515
+ var frame = btn.closest(".ar-carousel-frame") || btn.parentElement;
516
+ return frame ? frame.querySelector(".ar-carousel") : null;
517
+ }
518
+
519
+ function initCarouselControls() {
520
+ document.querySelectorAll("[data-ar-carousel-prev]").forEach((btn) => {
521
+ btn.addEventListener("click", () => {
522
+ scrollCarousel(findCarousel(btn, "data-ar-carousel-prev"), -1);
523
+ });
524
+ });
525
+ document.querySelectorAll("[data-ar-carousel-next]").forEach((btn) => {
526
+ btn.addEventListener("click", () => {
527
+ scrollCarousel(findCarousel(btn, "data-ar-carousel-next"), 1);
528
+ });
529
+ });
530
+ }
531
+
191
532
  var toastContainers = {};
192
533
 
193
534
  function getToastContainer(position) {
@@ -202,7 +543,7 @@
202
543
 
203
544
  function toast(message, options) {
204
545
  var opts = options || {};
205
- var type = opts.type || "";
546
+ var type = opts.type || "info";
206
547
  var duration = typeof opts.duration === "number" ? opts.duration : 4000;
207
548
  var position = opts.position || "top-right";
208
549
  var closable = opts.closable !== false;
@@ -312,7 +653,6 @@
312
653
  }
313
654
 
314
655
  function initPopovers() {
315
- // Click toggle
316
656
  document.addEventListener("click", (e) => {
317
657
  var trigger = e.target.closest("[data-ar-popover]");
318
658
  if (trigger) {
@@ -409,6 +749,29 @@
409
749
  });
410
750
  }
411
751
 
752
+ function initReveal() {
753
+ var els = document.querySelectorAll("[data-ar-reveal]");
754
+ if (!els.length) return;
755
+ if (!("IntersectionObserver" in window)) {
756
+ els.forEach((el) => el.classList.add("ar-reveal", "ar-reveal-in"));
757
+ return;
758
+ }
759
+ var io = new IntersectionObserver(
760
+ (entries) => {
761
+ entries.forEach((entry) => {
762
+ if (!entry.isIntersecting) return;
763
+ entry.target.classList.add("ar-reveal-in");
764
+ io.unobserve(entry.target);
765
+ });
766
+ },
767
+ { rootMargin: "0px 0px -10% 0px", threshold: 0 },
768
+ );
769
+ els.forEach((el) => {
770
+ el.classList.add("ar-reveal");
771
+ io.observe(el);
772
+ });
773
+ }
774
+
412
775
  function init() {
413
776
  if (document.readyState === "loading") {
414
777
  document.addEventListener("DOMContentLoaded", ready);
@@ -422,8 +785,10 @@
422
785
  syncToggles();
423
786
  initThemeToggle();
424
787
  initNeoToggle();
788
+ initPixelToggle();
789
+ initBrutalistToggle();
425
790
  initModals();
426
- initDrawers();
791
+ initSidebars();
427
792
  initTabs();
428
793
  initDropdowns();
429
794
  initAccordion();
@@ -431,9 +796,11 @@
431
796
  initPopovers();
432
797
  initFileUploads();
433
798
  initScrollTop();
799
+ initCarouselControls();
800
+ initReveal();
434
801
  }
435
802
 
436
- window.ARStyle = {
803
+ window.ArekUI = {
437
804
  setTheme: setTheme,
438
805
  getTheme: getTheme,
439
806
  initTheme: initTheme,
Binary file