rizzo-css 0.0.11 → 0.0.13

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 (233) hide show
  1. package/.env.example +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +17 -3
  4. package/bin/rizzo-css.js +98 -42
  5. package/dist/rizzo.min.css +3 -2
  6. package/package.json +5 -3
  7. package/scaffold/astro-app/README.md +13 -2
  8. package/scaffold/astro-app/src/components/Accordion.astro +178 -0
  9. package/scaffold/astro-app/src/components/Alert.astro +131 -0
  10. package/scaffold/astro-app/src/components/Avatar.astro +59 -0
  11. package/scaffold/astro-app/src/components/Badge.astro +24 -0
  12. package/scaffold/astro-app/src/components/Breadcrumb.astro +61 -0
  13. package/scaffold/astro-app/src/components/Button.astro +3 -0
  14. package/scaffold/astro-app/src/components/Card.astro +18 -0
  15. package/scaffold/astro-app/src/components/Checkbox.astro +38 -0
  16. package/scaffold/astro-app/src/components/CodeBlock.astro +393 -0
  17. package/scaffold/astro-app/src/components/CopyToClipboard.astro +219 -0
  18. package/scaffold/astro-app/src/components/Divider.astro +37 -0
  19. package/scaffold/astro-app/src/components/Dropdown.astro +807 -0
  20. package/scaffold/astro-app/src/components/FormGroup.astro +59 -0
  21. package/scaffold/astro-app/src/components/FrameworkSwitcher.astro +72 -0
  22. package/scaffold/astro-app/src/components/Input.astro +59 -0
  23. package/scaffold/astro-app/src/components/Modal.astro +212 -0
  24. package/scaffold/astro-app/src/components/Navbar.astro +701 -0
  25. package/scaffold/astro-app/src/components/Pagination.astro +240 -0
  26. package/scaffold/astro-app/src/components/ProgressBar.astro +65 -0
  27. package/scaffold/astro-app/src/components/Radio.astro +38 -0
  28. package/scaffold/astro-app/src/components/Search.astro +1259 -0
  29. package/scaffold/astro-app/src/components/Select.astro +49 -0
  30. package/scaffold/astro-app/src/components/Settings.astro +382 -0
  31. package/scaffold/astro-app/src/components/Spinner.astro +30 -0
  32. package/scaffold/astro-app/src/components/Table.astro +181 -0
  33. package/scaffold/astro-app/src/components/Tabs.astro +223 -0
  34. package/scaffold/astro-app/src/components/Textarea.astro +58 -0
  35. package/scaffold/astro-app/src/components/ThemeSwitcher.astro +504 -0
  36. package/scaffold/astro-app/src/components/Toast.astro +30 -0
  37. package/scaffold/astro-app/src/components/Tooltip.astro +32 -0
  38. package/scaffold/astro-app/src/components/icons/Brush.astro +10 -0
  39. package/scaffold/astro-app/src/components/icons/Cake.astro +11 -0
  40. package/scaffold/astro-app/src/components/icons/Check.astro +29 -0
  41. package/scaffold/astro-app/src/components/icons/Cherry.astro +11 -0
  42. package/scaffold/astro-app/src/components/icons/ChevronDown.astro +29 -0
  43. package/scaffold/astro-app/src/components/icons/Circle.astro +29 -0
  44. package/scaffold/astro-app/src/components/icons/Close.astro +30 -0
  45. package/scaffold/astro-app/src/components/icons/Cmd.astro +26 -0
  46. package/scaffold/astro-app/src/components/icons/Copy.astro +30 -0
  47. package/scaffold/astro-app/src/components/icons/Eye.astro +30 -0
  48. package/scaffold/astro-app/src/components/icons/Filter.astro +29 -0
  49. package/scaffold/astro-app/src/components/icons/Flame.astro +28 -0
  50. package/scaffold/astro-app/src/components/icons/Flower.astro +11 -0
  51. package/scaffold/astro-app/src/components/icons/Gear.astro +30 -0
  52. package/scaffold/astro-app/src/components/icons/Heart.astro +28 -0
  53. package/scaffold/astro-app/src/components/icons/IceCream.astro +31 -0
  54. package/scaffold/astro-app/src/components/icons/Leaf.astro +29 -0
  55. package/scaffold/astro-app/src/components/icons/Lemon.astro +11 -0
  56. package/scaffold/astro-app/src/components/icons/Moon.astro +29 -0
  57. package/scaffold/astro-app/src/components/icons/Owl.astro +34 -0
  58. package/scaffold/astro-app/src/components/icons/Palette.astro +33 -0
  59. package/scaffold/astro-app/src/components/icons/Rainbow.astro +31 -0
  60. package/scaffold/astro-app/src/components/icons/Search.astro +30 -0
  61. package/scaffold/astro-app/src/components/icons/Shield.astro +28 -0
  62. package/scaffold/astro-app/src/components/icons/Snowflake.astro +34 -0
  63. package/scaffold/astro-app/src/components/icons/Sort.astro +30 -0
  64. package/scaffold/astro-app/src/components/icons/Sun.astro +29 -0
  65. package/scaffold/astro-app/src/components/icons/Sunset.astro +10 -0
  66. package/scaffold/astro-app/src/components/icons/Zap.astro +9 -0
  67. package/scaffold/astro-app/src/components/icons/devicons/Astro.astro +53 -0
  68. package/scaffold/astro-app/src/components/icons/devicons/Bash.astro +34 -0
  69. package/scaffold/astro-app/src/components/icons/devicons/Css3.astro +29 -0
  70. package/scaffold/astro-app/src/components/icons/devicons/Git.astro +24 -0
  71. package/scaffold/astro-app/src/components/icons/devicons/Html5.astro +27 -0
  72. package/scaffold/astro-app/src/components/icons/devicons/Javascript.astro +25 -0
  73. package/scaffold/astro-app/src/components/icons/devicons/Nodejs.astro +47 -0
  74. package/scaffold/astro-app/src/components/icons/devicons/Plaintext.astro +33 -0
  75. package/scaffold/astro-app/src/components/icons/devicons/React.astro +27 -0
  76. package/scaffold/astro-app/src/components/icons/devicons/Svelte.astro +25 -0
  77. package/scaffold/astro-app/src/components/icons/devicons/Vue.astro +26 -0
  78. package/scaffold/astro-app/src/config/frameworks.ts +26 -0
  79. package/scaffold/astro-app/src/config/themes.ts +54 -0
  80. package/scaffold/astro-app/src/layouts/DocsLayout.astro +204 -0
  81. package/scaffold/astro-app/src/layouts/Layout.astro +11 -2
  82. package/scaffold/astro-app/src/pages/components/accordion.astro +172 -0
  83. package/scaffold/astro-app/src/pages/components/alert.astro +250 -0
  84. package/scaffold/astro-app/src/pages/components/avatar.astro +102 -0
  85. package/scaffold/astro-app/src/pages/components/badge.astro +119 -0
  86. package/scaffold/astro-app/src/pages/components/breadcrumb.astro +124 -0
  87. package/scaffold/astro-app/src/pages/components/button.astro +74 -0
  88. package/scaffold/astro-app/src/pages/components/cards.astro +247 -0
  89. package/scaffold/astro-app/src/pages/components/copy-to-clipboard.astro +49 -0
  90. package/scaffold/astro-app/src/pages/components/divider.astro +74 -0
  91. package/scaffold/astro-app/src/pages/components/dropdown.astro +394 -0
  92. package/scaffold/astro-app/src/pages/components/forms.astro +367 -0
  93. package/scaffold/astro-app/src/pages/components/icons.astro +246 -0
  94. package/scaffold/astro-app/src/pages/components/modal.astro +152 -0
  95. package/scaffold/astro-app/src/pages/components/navbar.astro +80 -0
  96. package/scaffold/astro-app/src/pages/components/pagination.astro +126 -0
  97. package/scaffold/astro-app/src/pages/components/progress-bar.astro +94 -0
  98. package/scaffold/astro-app/src/pages/components/search.astro +155 -0
  99. package/scaffold/astro-app/src/pages/components/settings.astro +78 -0
  100. package/scaffold/astro-app/src/pages/components/spinner.astro +81 -0
  101. package/scaffold/astro-app/src/pages/components/table.astro +144 -0
  102. package/scaffold/astro-app/src/pages/components/tabs.astro +220 -0
  103. package/scaffold/astro-app/src/pages/components/theme-switcher.astro +67 -0
  104. package/scaffold/astro-app/src/pages/components/toast.astro +157 -0
  105. package/scaffold/astro-app/src/pages/components/tooltip.astro +209 -0
  106. package/scaffold/astro-app/src/pages/components.astro +290 -0
  107. package/scaffold/astro-app/src/pages/docs/accessibility.astro +9 -0
  108. package/scaffold/astro-app/src/pages/docs/colors.astro +9 -0
  109. package/scaffold/astro-app/src/pages/docs/design-system.astro +9 -0
  110. package/scaffold/astro-app/src/pages/docs/getting-started.astro +9 -0
  111. package/scaffold/astro-app/src/pages/docs/index.astro +15 -0
  112. package/scaffold/astro-app/src/pages/docs/themes/[theme].astro +14 -0
  113. package/scaffold/astro-app/src/pages/docs/theming.astro +10 -0
  114. package/scaffold/astro-app/src/pages/index.astro +5 -11
  115. package/scaffold/svelte/Table.svelte +6 -5
  116. package/scaffold/svelte/Tabs.svelte +3 -1
  117. package/scaffold/svelte-app/README.md +9 -2
  118. package/scaffold/svelte-app/src/app.html +1 -1
  119. package/scaffold/svelte-app/src/lib/rizzo/Accordion.svelte +128 -0
  120. package/scaffold/svelte-app/src/lib/rizzo/Alert.svelte +85 -0
  121. package/scaffold/svelte-app/src/lib/rizzo/Avatar.svelte +39 -0
  122. package/scaffold/svelte-app/src/lib/rizzo/Badge.svelte +31 -0
  123. package/scaffold/svelte-app/src/lib/rizzo/Breadcrumb.svelte +49 -0
  124. package/scaffold/svelte-app/src/lib/rizzo/Button.svelte +27 -0
  125. package/scaffold/svelte-app/src/lib/rizzo/Card.svelte +17 -0
  126. package/scaffold/svelte-app/src/lib/rizzo/Checkbox.svelte +37 -0
  127. package/scaffold/svelte-app/src/lib/rizzo/CopyToClipboard.svelte +79 -0
  128. package/scaffold/svelte-app/src/lib/rizzo/Divider.svelte +28 -0
  129. package/scaffold/svelte-app/src/lib/rizzo/Dropdown.svelte +254 -0
  130. package/scaffold/svelte-app/src/lib/rizzo/FormGroup.svelte +51 -0
  131. package/scaffold/svelte-app/src/lib/rizzo/Input.svelte +59 -0
  132. package/scaffold/svelte-app/src/lib/rizzo/Modal.svelte +157 -0
  133. package/scaffold/svelte-app/src/lib/rizzo/Pagination.svelte +93 -0
  134. package/scaffold/svelte-app/src/lib/rizzo/ProgressBar.svelte +58 -0
  135. package/scaffold/svelte-app/src/lib/rizzo/Radio.svelte +38 -0
  136. package/scaffold/svelte-app/src/lib/rizzo/Select.svelte +51 -0
  137. package/scaffold/svelte-app/src/lib/rizzo/Spinner.svelte +14 -0
  138. package/scaffold/svelte-app/src/lib/rizzo/Table.svelte +158 -0
  139. package/scaffold/svelte-app/src/lib/rizzo/Tabs.svelte +117 -0
  140. package/scaffold/svelte-app/src/lib/rizzo/Textarea.svelte +59 -0
  141. package/scaffold/svelte-app/src/lib/rizzo/ThemeSwitcher.svelte +315 -0
  142. package/scaffold/svelte-app/src/lib/rizzo/Toast.svelte +33 -0
  143. package/scaffold/svelte-app/src/lib/rizzo/Tooltip.svelte +19 -0
  144. package/scaffold/svelte-app/src/lib/rizzo/icons/Check.svelte +29 -0
  145. package/scaffold/svelte-app/src/lib/rizzo/icons/ChevronDown.svelte +29 -0
  146. package/scaffold/svelte-app/src/lib/rizzo/icons/Circle.svelte +29 -0
  147. package/scaffold/svelte-app/src/lib/rizzo/icons/Close.svelte +30 -0
  148. package/scaffold/svelte-app/src/lib/rizzo/icons/Cmd.svelte +27 -0
  149. package/scaffold/svelte-app/src/lib/rizzo/icons/Copy.svelte +30 -0
  150. package/scaffold/svelte-app/src/lib/rizzo/icons/Eye.svelte +30 -0
  151. package/scaffold/svelte-app/src/lib/rizzo/icons/Filter.svelte +29 -0
  152. package/scaffold/svelte-app/src/lib/rizzo/icons/Gear.svelte +30 -0
  153. package/scaffold/svelte-app/src/lib/rizzo/icons/IceCream.svelte +31 -0
  154. package/scaffold/svelte-app/src/lib/rizzo/icons/Moon.svelte +29 -0
  155. package/scaffold/svelte-app/src/lib/rizzo/icons/Owl.svelte +34 -0
  156. package/scaffold/svelte-app/src/lib/rizzo/icons/Palette.svelte +33 -0
  157. package/scaffold/svelte-app/src/lib/rizzo/icons/Rainbow.svelte +31 -0
  158. package/scaffold/svelte-app/src/lib/rizzo/icons/Search.svelte +30 -0
  159. package/scaffold/svelte-app/src/lib/rizzo/icons/Snowflake.svelte +34 -0
  160. package/scaffold/svelte-app/src/lib/rizzo/icons/Sort.svelte +30 -0
  161. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Astro.svelte +45 -0
  162. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Bash.svelte +28 -0
  163. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Css3.svelte +23 -0
  164. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Git.svelte +18 -0
  165. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Html5.svelte +21 -0
  166. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Javascript.svelte +19 -0
  167. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Nodejs.svelte +44 -0
  168. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Plaintext.svelte +24 -0
  169. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/React.svelte +21 -0
  170. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/SvelteIcon.svelte +19 -0
  171. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Vue.svelte +20 -0
  172. package/scaffold/svelte-app/src/lib/rizzo/index.ts +33 -0
  173. package/scaffold/svelte-app/src/lib/rizzo-docs/CodeBlock.svelte +239 -0
  174. package/scaffold/svelte-app/src/lib/rizzo-docs/SvelteDocPage.svelte +99 -0
  175. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AccordionDoc.svelte +53 -0
  176. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AlertDoc.svelte +114 -0
  177. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AvatarDoc.svelte +92 -0
  178. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BadgeDoc.svelte +60 -0
  179. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BreadcrumbDoc.svelte +55 -0
  180. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ButtonDoc.svelte +55 -0
  181. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CardsDoc.svelte +173 -0
  182. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComingSoon.svelte +12 -0
  183. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComponentsOverview.svelte +92 -0
  184. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CopyToClipboardDoc.svelte +26 -0
  185. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DividerDoc.svelte +105 -0
  186. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DropdownDoc.svelte +161 -0
  187. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/FormsDoc.svelte +375 -0
  188. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/IconsDoc.svelte +246 -0
  189. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Index.svelte +8 -0
  190. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ModalDoc.svelte +50 -0
  191. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/NavbarDoc.svelte +79 -0
  192. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/PaginationDoc.svelte +44 -0
  193. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ProgressBarDoc.svelte +95 -0
  194. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SearchDoc.svelte +147 -0
  195. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SettingsDoc.svelte +158 -0
  196. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SpinnerDoc.svelte +41 -0
  197. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TableDoc.svelte +116 -0
  198. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TabsDoc.svelte +152 -0
  199. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ThemeSwitcherDoc.svelte +181 -0
  200. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Theming.svelte +6 -0
  201. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ToastDoc.svelte +136 -0
  202. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TooltipDoc.svelte +57 -0
  203. package/scaffold/svelte-app/src/routes/+page.svelte +2 -2
  204. package/scaffold/svelte-app/src/routes/components/+page.svelte +4 -0
  205. package/scaffold/svelte-app/src/routes/components/[slug]/+page.svelte +7 -0
  206. package/scaffold/vanilla/README.md +20 -8
  207. package/scaffold/vanilla/components/accordion.html +187 -0
  208. package/scaffold/vanilla/components/alert.html +187 -0
  209. package/scaffold/vanilla/components/avatar.html +187 -0
  210. package/scaffold/vanilla/components/badge.html +187 -0
  211. package/scaffold/vanilla/components/breadcrumb.html +187 -0
  212. package/scaffold/vanilla/components/button.html +187 -0
  213. package/scaffold/vanilla/components/cards.html +187 -0
  214. package/scaffold/vanilla/components/copy-to-clipboard.html +187 -0
  215. package/scaffold/vanilla/components/divider.html +187 -0
  216. package/scaffold/vanilla/components/dropdown.html +187 -0
  217. package/scaffold/vanilla/components/forms.html +187 -0
  218. package/scaffold/vanilla/components/icons.html +187 -0
  219. package/scaffold/vanilla/components/index.html +212 -0
  220. package/scaffold/vanilla/components/modal.html +187 -0
  221. package/scaffold/vanilla/components/navbar.html +187 -0
  222. package/scaffold/vanilla/components/pagination.html +187 -0
  223. package/scaffold/vanilla/components/progress-bar.html +187 -0
  224. package/scaffold/vanilla/components/search.html +187 -0
  225. package/scaffold/vanilla/components/settings.html +187 -0
  226. package/scaffold/vanilla/components/spinner.html +187 -0
  227. package/scaffold/vanilla/components/table.html +187 -0
  228. package/scaffold/vanilla/components/tabs.html +187 -0
  229. package/scaffold/vanilla/components/theme-switcher.html +187 -0
  230. package/scaffold/vanilla/components/toast.html +187 -0
  231. package/scaffold/vanilla/components/tooltip.html +187 -0
  232. package/scaffold/vanilla/index.html +17 -283
  233. package/scaffold/vanilla/js/main.js +748 -0
@@ -0,0 +1,748 @@
1
+ /**
2
+ * Rizzo CSS — Vanilla JS component bundle
3
+ * Theme, toast, settings, tabs, modal, dropdown, accordion.
4
+ * Load this script after the DOM (e.g. before </body>).
5
+ */
6
+ (function () {
7
+ 'use strict';
8
+
9
+ if (typeof window === 'undefined') return;
10
+
11
+ // --- Toast (showToast, removeToast, removeAllToasts) ---
12
+ if (!window.showToast) {
13
+ function showToast(message, options) {
14
+ if (!message) return null;
15
+ options = options || {};
16
+ var variant = options.variant || 'info';
17
+ var position = options.position || 'top-right';
18
+ var autoDismiss = options.autoDismiss !== undefined ? options.autoDismiss : 5000;
19
+ var dismissible = options.dismissible !== undefined ? options.dismissible : true;
20
+ var toastId = 'toast-' + Math.random().toString(36).substr(2, 9);
21
+ function createToast() {
22
+ if (!document.body) return;
23
+ var containerId = 'toast-container-' + position;
24
+ var container = document.getElementById(containerId);
25
+ if (!container) {
26
+ container = document.createElement('div');
27
+ container.id = containerId;
28
+ container.className = 'toast-container toast-container--' + position;
29
+ container.style.cssText = 'display:flex;visibility:visible;z-index:1100;';
30
+ document.body.appendChild(container);
31
+ }
32
+ var toast = document.createElement('div');
33
+ toast.id = toastId;
34
+ toast.className = 'alert alert--' + variant;
35
+ toast.setAttribute('role', 'alert');
36
+ toast.setAttribute('aria-live', 'polite');
37
+ toast.style.cssText = 'display:flex;visibility:visible;opacity:0;transition:opacity 0.3s ease-out, transform 0.3s ease-out;';
38
+ var isRight = position.indexOf('right') !== -1;
39
+ var isLeft = position.indexOf('left') !== -1;
40
+ toast.style.transform = isRight ? 'translateX(100%)' : isLeft ? 'translateX(-100%)' : 'translateY(-100%)';
41
+ var content = document.createElement('div');
42
+ content.className = 'alert__content';
43
+ content.textContent = message;
44
+ toast.appendChild(content);
45
+ var closeBtn;
46
+ if (dismissible) {
47
+ closeBtn = document.createElement('button');
48
+ closeBtn.type = 'button';
49
+ closeBtn.className = 'alert__close';
50
+ closeBtn.setAttribute('aria-label', 'Dismiss toast');
51
+ closeBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2"><line x1="4" y1="4" x2="12" y2="12"></line><line x1="12" y1="4" x2="4" y2="12"></line></svg>';
52
+ toast.appendChild(closeBtn);
53
+ closeBtn.addEventListener('click', function () {
54
+ toast.style.opacity = '0';
55
+ toast.style.transform = isRight ? 'translateX(100%)' : isLeft ? 'translateX(-100%)' : 'translateY(-100%)';
56
+ setTimeout(function () {
57
+ if (toast.parentNode) toast.remove();
58
+ if (container.children.length === 0) container.remove();
59
+ }, 300);
60
+ });
61
+ }
62
+ container.appendChild(toast);
63
+ requestAnimationFrame(function () {
64
+ toast.offsetHeight;
65
+ if (variant === 'warning') {
66
+ toast.style.color = 'var(--warning-text)';
67
+ content.style.color = 'var(--warning-text)';
68
+ if (closeBtn) closeBtn.style.color = 'var(--warning-text)';
69
+ }
70
+ setTimeout(function () {
71
+ requestAnimationFrame(function () {
72
+ toast.style.opacity = '1';
73
+ toast.style.transform = isRight || isLeft ? 'translateX(0)' : 'translateY(0)';
74
+ });
75
+ }, 10);
76
+ });
77
+ if (autoDismiss > 0) {
78
+ setTimeout(function () {
79
+ if (toast.parentNode) {
80
+ toast.style.opacity = '0';
81
+ toast.style.transform = isRight ? 'translateX(100%)' : isLeft ? 'translateX(-100%)' : 'translateY(-100%)';
82
+ setTimeout(function () {
83
+ if (toast.parentNode) toast.remove();
84
+ if (container.children.length === 0) container.remove();
85
+ }, 300);
86
+ }
87
+ }, autoDismiss);
88
+ }
89
+ }
90
+ if (document.body) createToast();
91
+ else document.addEventListener('DOMContentLoaded', createToast);
92
+ return toastId;
93
+ }
94
+ function removeToast(toastId) {
95
+ var toast = document.getElementById(toastId);
96
+ if (toast) {
97
+ var container = toast.parentElement;
98
+ var position = container ? container.id.replace('toast-container-', '') : 'top-right';
99
+ toast.style.opacity = '0';
100
+ toast.style.transform = position.indexOf('right') !== -1 ? 'translateX(100%)' : position.indexOf('left') !== -1 ? 'translateX(-100%)' : 'translateY(-100%)';
101
+ setTimeout(function () {
102
+ if (toast.parentNode) toast.remove();
103
+ if (container && container.classList.contains('toast-container') && container.children.length === 0) container.remove();
104
+ }, 300);
105
+ }
106
+ }
107
+ function removeAllToasts() {
108
+ document.querySelectorAll('.toast-container').forEach(function (c) {
109
+ c.querySelectorAll('.alert').forEach(function (t) {
110
+ t.style.opacity = '0';
111
+ t.style.transform = 'translateY(-10px)';
112
+ });
113
+ setTimeout(function () { c.remove(); }, 300);
114
+ });
115
+ }
116
+ window.showToast = showToast;
117
+ window.removeToast = removeToast;
118
+ window.removeAllToasts = removeAllToasts;
119
+ }
120
+
121
+ // --- Theme (applyTheme, sync selects, system listener) ---
122
+ var KEY = 'theme';
123
+ var defaultDark = '{{DEFAULT_DARK}}';
124
+ var defaultLight = '{{DEFAULT_LIGHT}}';
125
+ function resolveSystem() {
126
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? defaultDark : defaultLight;
127
+ }
128
+ function applyTheme(value) {
129
+ var effective = value === 'system' ? resolveSystem() : value;
130
+ document.documentElement.setAttribute('data-theme', effective);
131
+ try { localStorage.setItem(KEY, value); } catch (e) {}
132
+ var headerSelect = document.getElementById('theme-select');
133
+ var settingsSelect = document.getElementById('settings-theme');
134
+ if (headerSelect && headerSelect.value !== value) headerSelect.value = value;
135
+ if (settingsSelect && settingsSelect.value !== value) settingsSelect.value = value;
136
+ try { window.dispatchEvent(new CustomEvent('rizzo-theme-change', { detail: { themeValue: value, effective: effective } })); } catch (e) {}
137
+ }
138
+ function syncThemeSelects() {
139
+ var stored = null;
140
+ try { stored = localStorage.getItem(KEY); } catch (e) {}
141
+ var currentAttr = document.documentElement.getAttribute('data-theme');
142
+ var value = stored || currentAttr || 'system';
143
+ var headerSelect = document.getElementById('theme-select');
144
+ var settingsSelect = document.getElementById('settings-theme');
145
+ if (headerSelect) headerSelect.value = value;
146
+ if (settingsSelect) settingsSelect.value = value;
147
+ }
148
+ function initTheme() {
149
+ var headerSelect = document.getElementById('theme-select');
150
+ var settingsSelect = document.getElementById('settings-theme');
151
+ if (headerSelect) headerSelect.addEventListener('change', function () { applyTheme(headerSelect.value); });
152
+ if (settingsSelect) settingsSelect.addEventListener('change', function () { applyTheme(settingsSelect.value); });
153
+ syncThemeSelects();
154
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
155
+ if ((localStorage.getItem(KEY) || 'system') === 'system') applyTheme('system');
156
+ });
157
+ }
158
+
159
+ // --- Settings panel (openSettings, font size, reduce motion, high contrast, scrollbar) ---
160
+ function initSettings() {
161
+ var settings = document.querySelector('[data-settings]');
162
+ if (!settings) return;
163
+ var overlay = settings.querySelector('[data-settings-overlay]');
164
+ var panel = settings.querySelector('.settings__panel');
165
+ var closeBtn = settings.querySelector('[data-settings-close]');
166
+ var fontSizeSlider = settings.querySelector('[data-font-size-slider]');
167
+ var fontSizeValue = settings.querySelector('[data-font-size-value]');
168
+ var reducedMotion = settings.querySelector('[data-reduced-motion]');
169
+ var highContrast = settings.querySelector('[data-high-contrast]');
170
+ var scrollbarStyleRadios = settings.querySelectorAll('[data-scrollbar-style]');
171
+ var html = document.documentElement;
172
+ if (!panel || !overlay || !closeBtn) return;
173
+ function updateSliderProgress(slider) {
174
+ var min = parseFloat(slider.min), max = parseFloat(slider.max), value = parseFloat(slider.value);
175
+ slider.style.setProperty('--slider-progress', ((value - min) / (max - min)) * 100 + '%');
176
+ }
177
+ function applyFontSize(scale) {
178
+ html.style.setProperty('--font-size-scale', scale);
179
+ if (fontSizeValue) fontSizeValue.textContent = Math.round(scale * 100) + '%';
180
+ }
181
+ function applyScrollbarStyle(style) {
182
+ html.classList.remove('scrollbar-thin', 'scrollbar-thick', 'scrollbar-hidden', 'hide-scrollbars');
183
+ if (style === 'thick') html.classList.add('scrollbar-thick');
184
+ else if (style === 'hidden') html.classList.add('scrollbar-hidden', 'hide-scrollbars');
185
+ }
186
+ function loadSettings() {
187
+ var saved = localStorage.getItem('fontSizeScale');
188
+ if (saved && fontSizeSlider) {
189
+ fontSizeSlider.value = saved;
190
+ applyFontSize(parseFloat(saved));
191
+ }
192
+ if (fontSizeSlider) updateSliderProgress(fontSizeSlider);
193
+ if (reducedMotion) {
194
+ reducedMotion.checked = localStorage.getItem('reducedMotion') === 'true';
195
+ html.classList.toggle('reduced-motion', reducedMotion.checked);
196
+ }
197
+ if (highContrast) {
198
+ highContrast.checked = localStorage.getItem('highContrast') === 'true';
199
+ html.classList.toggle('high-contrast', highContrast.checked);
200
+ }
201
+ var scrollbar = localStorage.getItem('scrollbarStyle') || 'thin';
202
+ for (var i = 0; i < scrollbarStyleRadios.length; i++) {
203
+ if (scrollbarStyleRadios[i].value === scrollbar) scrollbarStyleRadios[i].checked = true;
204
+ }
205
+ applyScrollbarStyle(scrollbar);
206
+ }
207
+ function getFocusable(container) {
208
+ var sel = 'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
209
+ return Array.prototype.slice.call(container.querySelectorAll(sel));
210
+ }
211
+ var previousActive = null;
212
+ function openSettings() {
213
+ previousActive = document.activeElement;
214
+ settings.setAttribute('aria-hidden', 'false');
215
+ overlay.setAttribute('aria-hidden', 'false');
216
+ panel.setAttribute('aria-hidden', 'false');
217
+ panel.removeAttribute('data-open');
218
+ void panel.offsetHeight;
219
+ requestAnimationFrame(function () {
220
+ requestAnimationFrame(function () {
221
+ panel.setAttribute('data-open', 'true');
222
+ if (closeBtn) closeBtn.focus();
223
+ });
224
+ });
225
+ }
226
+ function closeSettings() {
227
+ panel.removeAttribute('data-open');
228
+ var duration = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : 300;
229
+ setTimeout(function () {
230
+ settings.setAttribute('aria-hidden', 'true');
231
+ overlay.setAttribute('aria-hidden', 'true');
232
+ panel.setAttribute('aria-hidden', 'true');
233
+ if (previousActive) {
234
+ previousActive.focus();
235
+ previousActive = null;
236
+ }
237
+ }, duration);
238
+ }
239
+ closeBtn.addEventListener('click', closeSettings);
240
+ overlay.addEventListener('click', closeSettings);
241
+ document.addEventListener('keydown', function (e) {
242
+ if (panel.getAttribute('data-open') !== 'true') return;
243
+ if (e.key === 'Escape') { e.preventDefault(); closeSettings(); return; }
244
+ if (e.key === 'Tab') {
245
+ var els = getFocusable(panel);
246
+ if (els.length === 0) return;
247
+ var first = els[0], last = els[els.length - 1], active = document.activeElement;
248
+ if (e.shiftKey) {
249
+ if (active === first || !panel.contains(active)) { e.preventDefault(); last.focus(); }
250
+ } else {
251
+ if (active === last || !panel.contains(active)) { e.preventDefault(); first.focus(); }
252
+ }
253
+ }
254
+ });
255
+ if (fontSizeSlider) {
256
+ fontSizeSlider.addEventListener('input', function () {
257
+ var scale = parseFloat(this.value);
258
+ applyFontSize(scale);
259
+ updateSliderProgress(this);
260
+ localStorage.setItem('fontSizeScale', scale);
261
+ });
262
+ }
263
+ if (reducedMotion) {
264
+ reducedMotion.addEventListener('change', function () {
265
+ html.classList.toggle('reduced-motion', this.checked);
266
+ localStorage.setItem('reducedMotion', this.checked);
267
+ });
268
+ }
269
+ if (highContrast) {
270
+ highContrast.addEventListener('change', function () {
271
+ html.classList.toggle('high-contrast', this.checked);
272
+ localStorage.setItem('highContrast', this.checked);
273
+ });
274
+ }
275
+ for (var j = 0; j < scrollbarStyleRadios.length; j++) {
276
+ scrollbarStyleRadios[j].addEventListener('change', function () {
277
+ if (this.checked) {
278
+ applyScrollbarStyle(this.value);
279
+ localStorage.setItem('scrollbarStyle', this.value);
280
+ }
281
+ });
282
+ }
283
+ loadSettings();
284
+ window.openSettings = openSettings;
285
+ }
286
+
287
+ // --- Tabs: init all [data-tabs] ---
288
+ function initTabs() {
289
+ document.querySelectorAll('[data-tabs]').forEach(function (tabsContainer) {
290
+ if (tabsContainer.getAttribute('data-rizzo-tabs-inited')) return;
291
+ tabsContainer.setAttribute('data-rizzo-tabs-inited', 'true');
292
+ var tabButtons = tabsContainer.querySelectorAll('[role="tab"]');
293
+ var tabPanels = tabsContainer.querySelectorAll('[role="tabpanel"]');
294
+ if (tabButtons.length === 0 || tabPanels.length === 0) return;
295
+ var activeIndex = -1;
296
+ for (var i = 0; i < tabButtons.length; i++) {
297
+ if (tabButtons[i].classList.contains('tabs__tab--active')) { activeIndex = i; break; }
298
+ }
299
+ if (activeIndex === -1) activeIndex = 0;
300
+ function activateTab(index) {
301
+ if (index < 0 || index >= tabButtons.length) return;
302
+ var targetButton = tabButtons[index];
303
+ var targetTabId = targetButton.getAttribute('data-tab-id');
304
+ if (!targetTabId) return;
305
+ for (var i = 0; i < tabButtons.length; i++) {
306
+ var isActive = i === index;
307
+ tabButtons[i].setAttribute('aria-selected', isActive ? 'true' : 'false');
308
+ tabButtons[i].setAttribute('tabindex', isActive ? '0' : '-1');
309
+ tabButtons[i].classList.toggle('tabs__tab--active', isActive);
310
+ }
311
+ for (var p = 0; p < tabPanels.length; p++) {
312
+ var panelId = tabPanels[p].getAttribute('data-panel-id');
313
+ var isActive = panelId === targetTabId;
314
+ tabPanels[p].setAttribute('aria-hidden', isActive ? 'false' : 'true');
315
+ tabPanels[p].classList.toggle('tabs__panel--active', isActive);
316
+ }
317
+ }
318
+ for (var i = 0; i < tabButtons.length; i++) {
319
+ (function (idx) {
320
+ tabButtons[idx].addEventListener('click', function () { activateTab(idx); });
321
+ tabButtons[idx].addEventListener('keydown', function (e) {
322
+ var targetIndex = idx;
323
+ switch (e.key) {
324
+ case 'ArrowRight':
325
+ case 'ArrowDown':
326
+ e.preventDefault();
327
+ targetIndex = (idx + 1) % tabButtons.length;
328
+ break;
329
+ case 'ArrowLeft':
330
+ case 'ArrowUp':
331
+ e.preventDefault();
332
+ targetIndex = idx === 0 ? tabButtons.length - 1 : idx - 1;
333
+ break;
334
+ case 'Home':
335
+ e.preventDefault();
336
+ targetIndex = 0;
337
+ break;
338
+ case 'End':
339
+ e.preventDefault();
340
+ targetIndex = tabButtons.length - 1;
341
+ break;
342
+ case 'Enter':
343
+ case ' ':
344
+ e.preventDefault();
345
+ activateTab(idx);
346
+ return;
347
+ default:
348
+ return;
349
+ }
350
+ activateTab(targetIndex);
351
+ tabButtons[targetIndex].focus();
352
+ });
353
+ })(i);
354
+ }
355
+ });
356
+ }
357
+
358
+ // --- Modal: [data-modal-open="modalId"] opens #modalId, #modalId-overlay, [data-modal-close] ---
359
+ function initModals() {
360
+ var inited = {};
361
+ function initModal(modalId) {
362
+ if (inited[modalId]) return;
363
+ var modal = document.getElementById(modalId);
364
+ var overlay = document.getElementById(modalId + '-overlay');
365
+ if (!modal || !overlay) return;
366
+ var closeBtn = modal.querySelector('[data-modal-close]');
367
+ if (!closeBtn) return;
368
+ inited[modalId] = true;
369
+ modal.setAttribute('data-rizzo-modal-inited', 'true');
370
+ var focusableSelectors = 'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
371
+ function getFocusable(container) {
372
+ return Array.prototype.slice.call(container.querySelectorAll(focusableSelectors));
373
+ }
374
+ var previousActive = null;
375
+ var focusTrapHandler = null;
376
+ function openModal() {
377
+ previousActive = document.activeElement;
378
+ modal.setAttribute('aria-hidden', 'false');
379
+ overlay.setAttribute('aria-hidden', 'false');
380
+ modal.setAttribute('data-open', 'true');
381
+ var focusable = getFocusable(modal);
382
+ var first = focusable.length ? focusable[0] : closeBtn;
383
+ if (first) setTimeout(function () { first.focus(); }, 0);
384
+ focusTrapHandler = function (e) {
385
+ if (modal.getAttribute('data-open') !== 'true') return;
386
+ if (e.key === 'Escape') { e.preventDefault(); closeModal(); return; }
387
+ if (e.key === 'Tab') {
388
+ var els = getFocusable(modal);
389
+ if (els.length === 0) return;
390
+ var firstEl = els[0], lastEl = els[els.length - 1], active = document.activeElement;
391
+ if (e.shiftKey) {
392
+ if (active === firstEl || !modal.contains(active)) { e.preventDefault(); lastEl.focus(); }
393
+ } else {
394
+ if (active === lastEl || !modal.contains(active)) { e.preventDefault(); firstEl.focus(); }
395
+ }
396
+ }
397
+ };
398
+ document.addEventListener('keydown', focusTrapHandler);
399
+ }
400
+ function closeModal() {
401
+ modal.setAttribute('aria-hidden', 'true');
402
+ overlay.setAttribute('aria-hidden', 'true');
403
+ modal.removeAttribute('data-open');
404
+ if (focusTrapHandler) {
405
+ document.removeEventListener('keydown', focusTrapHandler);
406
+ focusTrapHandler = null;
407
+ }
408
+ if (previousActive) { previousActive.focus(); previousActive = null; }
409
+ }
410
+ closeBtn.addEventListener('click', closeModal);
411
+ overlay.addEventListener('click', function (e) {
412
+ if (e.target === overlay) closeModal();
413
+ });
414
+ var idSafe = modalId.replace(/-/g, '_');
415
+ window['openModal_' + idSafe] = openModal;
416
+ window['closeModal_' + idSafe] = closeModal;
417
+ }
418
+ document.querySelectorAll('[data-modal-close]').forEach(function (closeBtn) {
419
+ var modal = closeBtn.closest ? closeBtn.closest('[role="dialog"]') : null;
420
+ if (modal && modal.id) initModal(modal.id);
421
+ });
422
+ document.querySelectorAll('[data-modal-open]').forEach(function (btn) {
423
+ var modalId = btn.getAttribute('data-modal-open');
424
+ if (!modalId) return;
425
+ initModal(modalId);
426
+ var openModalFn = window['openModal_' + modalId.replace(/-/g, '_')];
427
+ if (openModalFn) btn.addEventListener('click', function () { openModalFn(); });
428
+ });
429
+ }
430
+
431
+ // --- Dropdown: init all [data-dropdown] ---
432
+ function initDropdowns() {
433
+ var dropdowns = document.querySelectorAll('[data-dropdown]');
434
+ dropdowns.forEach(function (dropdown) {
435
+ var dropdownId = dropdown.getAttribute('data-dropdown');
436
+ if (!dropdownId) return;
437
+ if (dropdown.hasAttribute('data-dropdown-initialized')) return;
438
+ dropdown.setAttribute('data-dropdown-initialized', 'true');
439
+ var trigger = dropdown.querySelector('.dropdown__trigger');
440
+ var menu = dropdown.querySelector('.dropdown__menu');
441
+ var items = dropdown.querySelectorAll('.dropdown__item');
442
+ var itemWrappers = dropdown.querySelectorAll('.dropdown__item-wrapper');
443
+ if (!trigger || !menu) return;
444
+ var currentIndex = -1;
445
+ function getVisibleItems() {
446
+ return Array.prototype.filter.call(items, function (item) {
447
+ var disabled = item.getAttribute('aria-disabled') === 'true';
448
+ var wrapper = item.closest('.dropdown__item-wrapper');
449
+ var submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
450
+ if (submenu && item.closest('.dropdown__submenu')) return false;
451
+ return !disabled && (item.offsetParent !== null || menu.classList.contains('dropdown__menu--open'));
452
+ });
453
+ }
454
+ function closeAllSubmenus(exceptWrapper) {
455
+ for (var w = 0; w < itemWrappers.length; w++) {
456
+ if (itemWrappers[w] === exceptWrapper) continue;
457
+ var sub = itemWrappers[w].querySelector('.dropdown__submenu');
458
+ var it = itemWrappers[w].querySelector('.dropdown__item');
459
+ if (sub && it) {
460
+ sub.classList.remove('dropdown__submenu--open');
461
+ sub.setAttribute('aria-hidden', 'true');
462
+ it.setAttribute('aria-expanded', 'false');
463
+ }
464
+ }
465
+ }
466
+ function toggleSubmenu(wrapper, open) {
467
+ var submenu = wrapper.querySelector('.dropdown__submenu');
468
+ var item = wrapper.querySelector('.dropdown__item');
469
+ if (!submenu || !item) return;
470
+ var isOpen = open !== undefined ? open : submenu.classList.contains('dropdown__submenu--open');
471
+ var willBeOpen = !isOpen;
472
+ if (willBeOpen) {
473
+ var parentSub = wrapper.closest('.dropdown__submenu');
474
+ if (parentSub) {
475
+ var siblings = parentSub.querySelectorAll('.dropdown__item-wrapper');
476
+ for (var s = 0; s < siblings.length; s++) {
477
+ if (siblings[s] === wrapper) continue;
478
+ var sSub = siblings[s].querySelector('.dropdown__submenu');
479
+ var sItem = siblings[s].querySelector('.dropdown__item');
480
+ if (sSub && sItem) {
481
+ sSub.classList.remove('dropdown__submenu--open');
482
+ sSub.setAttribute('aria-hidden', 'true');
483
+ sItem.setAttribute('aria-expanded', 'false');
484
+ }
485
+ }
486
+ } else {
487
+ closeAllSubmenus(wrapper);
488
+ }
489
+ }
490
+ if (willBeOpen) {
491
+ submenu.classList.add('dropdown__submenu--open');
492
+ submenu.setAttribute('aria-hidden', 'false');
493
+ item.setAttribute('aria-expanded', 'true');
494
+ } else {
495
+ submenu.classList.remove('dropdown__submenu--open');
496
+ submenu.setAttribute('aria-hidden', 'true');
497
+ item.setAttribute('aria-expanded', 'false');
498
+ }
499
+ }
500
+ function toggleMenu(open) {
501
+ var isOpen = open !== undefined ? open : menu.classList.contains('dropdown__menu--open');
502
+ var willBeOpen = !isOpen;
503
+ menu.classList.toggle('dropdown__menu--open', willBeOpen);
504
+ trigger.setAttribute('aria-expanded', willBeOpen.toString());
505
+ menu.setAttribute('aria-hidden', (!willBeOpen).toString());
506
+ for (var i = 0; i < items.length; i++) items[i].setAttribute('tabindex', willBeOpen ? '0' : '-1');
507
+ if (!willBeOpen) {
508
+ trigger.focus();
509
+ currentIndex = -1;
510
+ closeAllSubmenus();
511
+ } else {
512
+ var vis = getVisibleItems();
513
+ if (vis.length > 0) {
514
+ currentIndex = 0;
515
+ setTimeout(function () { vis[0].focus(); }, 0);
516
+ }
517
+ }
518
+ }
519
+ function closeMenu() {
520
+ menu.classList.remove('dropdown__menu--open');
521
+ trigger.setAttribute('aria-expanded', 'false');
522
+ menu.setAttribute('aria-hidden', 'true');
523
+ for (var i = 0; i < items.length; i++) items[i].setAttribute('tabindex', '-1');
524
+ closeAllSubmenus();
525
+ currentIndex = -1;
526
+ }
527
+ function handleOutsideClick(e) {
528
+ if (e && e.target && !dropdown.contains(e.target)) {
529
+ closeMenu();
530
+ document.removeEventListener('click', handleOutsideClick);
531
+ }
532
+ }
533
+ function wrappedToggle(open) {
534
+ var was = menu.classList.contains('dropdown__menu--open');
535
+ toggleMenu(open);
536
+ var now = menu.classList.contains('dropdown__menu--open');
537
+ if (now && !was) setTimeout(function () { document.addEventListener('click', handleOutsideClick); }, 0);
538
+ else if (!now && was) document.removeEventListener('click', handleOutsideClick);
539
+ }
540
+ trigger.addEventListener('click', function () { wrappedToggle(undefined); });
541
+ menu.addEventListener('click', function (e) {
542
+ var target = e.target;
543
+ var item = target.closest ? target.closest('.dropdown__item') : null;
544
+ if (!item) return;
545
+ e.stopPropagation();
546
+ if (item.getAttribute('aria-disabled') === 'true') { e.preventDefault(); return; }
547
+ var wrapper = item.closest('.dropdown__item-wrapper');
548
+ if (wrapper) {
549
+ var sub = wrapper.querySelector('.dropdown__submenu');
550
+ if (sub) {
551
+ e.preventDefault();
552
+ e.stopImmediatePropagation();
553
+ toggleSubmenu(wrapper, undefined);
554
+ return;
555
+ }
556
+ }
557
+ var href = item.getAttribute('data-dropdown-href');
558
+ if (href) { window.location.href = href; }
559
+ var onClick = item.getAttribute('data-dropdown-onclick');
560
+ if (onClick && typeof window[onClick] === 'function') {
561
+ var val = item.getAttribute('data-dropdown-value') || item.textContent.trim() || '';
562
+ window[onClick](val);
563
+ }
564
+ closeMenu();
565
+ });
566
+ trigger.addEventListener('keydown', function (e) {
567
+ if (e.key === 'Enter' || e.key === ' ') {
568
+ e.preventDefault();
569
+ wrappedToggle(undefined);
570
+ } else if (e.key === 'ArrowDown') {
571
+ e.preventDefault();
572
+ var vis = getVisibleItems();
573
+ if (vis.length > 0) {
574
+ currentIndex = 0;
575
+ wrappedToggle(true);
576
+ setTimeout(function () { vis[0].focus(); }, 0);
577
+ }
578
+ } else if (e.key === 'ArrowUp') {
579
+ e.preventDefault();
580
+ var vis = getVisibleItems();
581
+ if (vis.length > 0) {
582
+ currentIndex = vis.length - 1;
583
+ wrappedToggle(true);
584
+ setTimeout(function () { vis[currentIndex].focus(); }, 0);
585
+ }
586
+ } else if (e.key === 'Escape') {
587
+ e.preventDefault();
588
+ closeMenu();
589
+ }
590
+ });
591
+ menu.addEventListener('keydown', function (e) {
592
+ var vis = getVisibleItems();
593
+ if (e.key === 'Escape') {
594
+ e.preventDefault();
595
+ closeMenu();
596
+ trigger.focus();
597
+ } else if (e.key === 'ArrowDown') {
598
+ e.preventDefault();
599
+ currentIndex = (currentIndex + 1) % vis.length;
600
+ vis[currentIndex].focus();
601
+ } else if (e.key === 'ArrowUp') {
602
+ e.preventDefault();
603
+ currentIndex = currentIndex <= 0 ? vis.length - 1 : currentIndex - 1;
604
+ vis[currentIndex].focus();
605
+ } else if (e.key === 'Home') {
606
+ e.preventDefault();
607
+ currentIndex = 0;
608
+ vis[0].focus();
609
+ } else if (e.key === 'End') {
610
+ e.preventDefault();
611
+ currentIndex = vis.length - 1;
612
+ vis[currentIndex].focus();
613
+ } else if (e.key === 'ArrowRight') {
614
+ var t = e.target;
615
+ if (t && t.closest) {
616
+ var w = t.closest('.dropdown__item-wrapper');
617
+ if (w) {
618
+ var sub = w.querySelector('.dropdown__submenu');
619
+ if (sub) {
620
+ e.preventDefault();
621
+ toggleSubmenu(w, true);
622
+ var first = sub.querySelector('.dropdown__item');
623
+ if (first) setTimeout(function () { first.focus(); }, 0);
624
+ }
625
+ }
626
+ }
627
+ } else if (e.key === 'ArrowLeft') {
628
+ var t = e.target;
629
+ if (t && t.closest) {
630
+ var sub = t.closest('.dropdown__submenu');
631
+ if (sub) {
632
+ e.preventDefault();
633
+ var w = sub.closest('.dropdown__item-wrapper');
634
+ if (w) {
635
+ toggleSubmenu(w, false);
636
+ var p = w.querySelector('.dropdown__item');
637
+ if (p) p.focus();
638
+ }
639
+ }
640
+ }
641
+ } else if (e.key === 'Enter' || e.key === ' ') {
642
+ e.preventDefault();
643
+ var t = e.target;
644
+ if (t && t.getAttribute && t.getAttribute('aria-disabled') !== 'true') {
645
+ var w = t.closest('.dropdown__item-wrapper');
646
+ var sub = w ? w.querySelector('.dropdown__submenu') : null;
647
+ if (sub) toggleSubmenu(w, undefined);
648
+ else {
649
+ if (t.tagName === 'A') t.click();
650
+ else if (t.tagName === 'BUTTON') t.click();
651
+ closeMenu();
652
+ }
653
+ }
654
+ } else if (e.key === 'Tab') {
655
+ closeMenu();
656
+ }
657
+ });
658
+ });
659
+ }
660
+
661
+ // --- Accordion: init all [data-accordion] ---
662
+ function initAccordions() {
663
+ function initOne(accordion) {
664
+ if (accordion.getAttribute('data-accordion-init') === 'true') return;
665
+ accordion.setAttribute('data-accordion-init', 'true');
666
+ var isMultiple = accordion.getAttribute('data-allow-multiple') === 'true';
667
+ var triggers = accordion.querySelectorAll('[data-accordion-trigger]');
668
+ function setExpanded(trigger, expanded) {
669
+ var panelId = trigger.getAttribute('aria-controls');
670
+ var panel = panelId ? accordion.querySelector('#' + CSS.escape(panelId)) : null;
671
+ trigger.setAttribute('aria-expanded', String(expanded));
672
+ trigger.classList.toggle('accordion__trigger--expanded', expanded);
673
+ if (panel) {
674
+ panel.classList.toggle('accordion__panel--expanded', expanded);
675
+ panel.hidden = !expanded;
676
+ }
677
+ }
678
+ function toggle(trigger) {
679
+ var expanded = trigger.getAttribute('aria-expanded') === 'true';
680
+ if (!isMultiple) {
681
+ for (var i = 0; i < triggers.length; i++) setExpanded(triggers[i], false);
682
+ }
683
+ setExpanded(trigger, !expanded);
684
+ }
685
+ for (var i = 0; i < triggers.length; i++) {
686
+ triggers[i].addEventListener('click', function () { toggle(this); });
687
+ }
688
+ for (var i = 0; i < triggers.length; i++) {
689
+ (function (idx) {
690
+ triggers[idx].addEventListener('keydown', function (e) {
691
+ var targetIndex = idx;
692
+ switch (e.key) {
693
+ case 'ArrowDown':
694
+ e.preventDefault();
695
+ targetIndex = Math.min(idx + 1, triggers.length - 1);
696
+ break;
697
+ case 'ArrowUp':
698
+ e.preventDefault();
699
+ targetIndex = Math.max(idx - 1, 0);
700
+ break;
701
+ case 'Home':
702
+ e.preventDefault();
703
+ targetIndex = 0;
704
+ break;
705
+ case 'End':
706
+ e.preventDefault();
707
+ targetIndex = triggers.length - 1;
708
+ break;
709
+ case 'Enter':
710
+ case ' ':
711
+ e.preventDefault();
712
+ toggle(triggers[idx]);
713
+ return;
714
+ default:
715
+ return;
716
+ }
717
+ if (targetIndex !== idx) triggers[targetIndex].focus();
718
+ });
719
+ })(i);
720
+ }
721
+ var slotContent = accordion.querySelector('.accordion__slot-content');
722
+ if (slotContent) {
723
+ var slotChildren = Array.prototype.slice.call(slotContent.children);
724
+ for (var i = 0; i < slotChildren.length; i++) {
725
+ var placeholder = accordion.querySelector('[data-accordion-slot-index="' + i + '"]');
726
+ if (placeholder) placeholder.appendChild(slotChildren[i]);
727
+ }
728
+ slotContent.remove();
729
+ }
730
+ }
731
+ document.querySelectorAll('[data-accordion]').forEach(initOne);
732
+ }
733
+
734
+ function run() {
735
+ initTheme();
736
+ initSettings();
737
+ initTabs();
738
+ initModals();
739
+ initDropdowns();
740
+ initAccordions();
741
+ }
742
+
743
+ if (document.readyState === 'loading') {
744
+ document.addEventListener('DOMContentLoaded', run);
745
+ } else {
746
+ run();
747
+ }
748
+ })();