rizzo-css 0.0.54 → 0.0.55

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 (250) hide show
  1. package/README.md +11 -7
  2. package/bin/rizzo-css.js +273 -118
  3. package/dist/rizzo.min.css +40 -16
  4. package/package.json +6 -6
  5. package/scaffold/astro/AlertDialog.astro +86 -0
  6. package/scaffold/astro/AspectRatio.astro +22 -0
  7. package/scaffold/astro/ButtonGroup.astro +16 -0
  8. package/scaffold/astro/Collapsible.astro +69 -0
  9. package/scaffold/astro/ContextMenu.astro +58 -0
  10. package/scaffold/astro/CopyToClipboard.astro +4 -0
  11. package/scaffold/astro/Dashboard.astro +74 -0
  12. package/scaffold/astro/Empty.astro +23 -0
  13. package/scaffold/astro/HoverCard.astro +64 -0
  14. package/scaffold/astro/Kbd.astro +14 -0
  15. package/scaffold/astro/Label.astro +24 -0
  16. package/scaffold/astro/Modal.astro +17 -2
  17. package/scaffold/astro/Popover.astro +62 -0
  18. package/scaffold/astro/ResizableHandle.astro +16 -0
  19. package/scaffold/astro/ResizablePane.astro +20 -0
  20. package/scaffold/astro/ResizablePaneGroup.astro +84 -0
  21. package/scaffold/astro/ScrollArea.astro +19 -0
  22. package/scaffold/astro/Separator.astro +18 -0
  23. package/scaffold/astro/Settings.astro +10 -2
  24. package/scaffold/astro/Sheet.astro +90 -0
  25. package/scaffold/astro/Skeleton.astro +16 -0
  26. package/scaffold/astro/Slider.astro +75 -0
  27. package/scaffold/astro/SoundEffects.astro +1 -0
  28. package/scaffold/astro/Switch.astro +37 -0
  29. package/scaffold/astro/Tabs.astro +1 -1
  30. package/scaffold/astro/ThemeSwitcher.astro +11 -4
  31. package/scaffold/astro/Toggle.astro +35 -0
  32. package/scaffold/astro/ToggleGroup.astro +24 -0
  33. package/scaffold/astro/base/README-RIZZO.md +55 -0
  34. package/scaffold/{astro-core → astro/base}/src/pages/index.astro +1 -1
  35. package/scaffold/astro/variants/dashboard/src/layouts/Layout.astro +85 -0
  36. package/scaffold/astro/variants/dashboard/src/pages/index.astro +110 -0
  37. package/scaffold/astro/variants/docs/src/layouts/Layout.astro +81 -0
  38. package/scaffold/astro/variants/docs/src/pages/docs/getting-started.astro +36 -0
  39. package/scaffold/astro/variants/docs/src/pages/index.astro +38 -0
  40. package/scaffold/{astro-core → astro/variants/full}/README-RIZZO.md +2 -1
  41. package/scaffold/astro/variants/full/astro.config.mjs +5 -0
  42. package/scaffold/astro/variants/full/dist/_noop-middleware.mjs +3 -0
  43. package/scaffold/astro/variants/full/dist/chunks/astro/server_9Mzx7luy.mjs +6023 -0
  44. package/scaffold/astro/variants/full/dist/chunks/astro_BOYUKg7r.mjs +1 -0
  45. package/scaffold/astro/variants/full/dist/favicon.svg +18 -0
  46. package/scaffold/astro/variants/full/dist/manifest_DXpJmqSX.mjs +154 -0
  47. package/scaffold/astro/variants/full/dist/noop-entrypoint.mjs +3 -0
  48. package/scaffold/astro/variants/full/dist/pages/index.astro.mjs +87 -0
  49. package/scaffold/astro/variants/full/dist/renderers.mjs +3 -0
  50. package/scaffold/astro/variants/full/gitignore +24 -0
  51. package/scaffold/astro/variants/full/node_modules/.astro/data-store.json +1 -0
  52. package/scaffold/astro/variants/full/node_modules/.vite/deps/_metadata.json +31 -0
  53. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___aria-query.js +6776 -0
  54. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___aria-query.js.map +7 -0
  55. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___axobject-query.js +3754 -0
  56. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___axobject-query.js.map +7 -0
  57. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___cssesc.js +99 -0
  58. package/scaffold/astro/variants/full/node_modules/.vite/deps/astro___cssesc.js.map +7 -0
  59. package/scaffold/astro/variants/full/node_modules/.vite/deps/chunk-BUSYA2B4.js +8 -0
  60. package/scaffold/astro/variants/full/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +7 -0
  61. package/scaffold/astro/variants/full/node_modules/.vite/deps/package.json +3 -0
  62. package/scaffold/astro/variants/full/package.json +13 -0
  63. package/scaffold/astro/variants/full/public/.gitkeep +0 -0
  64. package/scaffold/astro/variants/full/public/favicon.svg +18 -0
  65. package/scaffold/astro/variants/full/src/components/rizzo/CopyToClipboard.astro +157 -0
  66. package/scaffold/astro/variants/full/src/components/rizzo/icons/Check.astro +29 -0
  67. package/scaffold/astro/variants/full/src/components/rizzo/icons/Copy.astro +30 -0
  68. package/scaffold/astro/variants/full/src/layouts/Layout.astro +34 -0
  69. package/scaffold/astro/variants/full/src/pages/index.astro +107 -0
  70. package/scaffold/astro/variants/full/tsconfig.json +5 -0
  71. package/scaffold/landing/index.html +13 -0
  72. package/scaffold/shared/navbar-vanilla.html +59 -0
  73. package/scaffold/shared/sound-effects-inline.js +6 -1
  74. package/scaffold/svelte/AlertDialog.svelte +55 -0
  75. package/scaffold/svelte/AspectRatio.svelte +21 -0
  76. package/scaffold/svelte/BackToTop.svelte +1 -0
  77. package/scaffold/svelte/ButtonGroup.svelte +16 -0
  78. package/scaffold/svelte/Collapsible.svelte +57 -0
  79. package/scaffold/svelte/ContextMenu.svelte +60 -0
  80. package/scaffold/svelte/Dashboard.svelte +87 -0
  81. package/scaffold/svelte/Empty.svelte +36 -0
  82. package/scaffold/svelte/HoverCard.svelte +55 -0
  83. package/scaffold/svelte/Kbd.svelte +13 -0
  84. package/scaffold/svelte/Label.svelte +19 -0
  85. package/scaffold/svelte/Popover.svelte +59 -0
  86. package/scaffold/svelte/ResizableHandle.svelte +13 -0
  87. package/scaffold/svelte/ResizablePane.svelte +16 -0
  88. package/scaffold/svelte/ResizablePaneGroup.svelte +92 -0
  89. package/scaffold/svelte/ScrollArea.svelte +18 -0
  90. package/scaffold/svelte/Separator.svelte +14 -0
  91. package/scaffold/svelte/Sheet.svelte +62 -0
  92. package/scaffold/svelte/Skeleton.svelte +19 -0
  93. package/scaffold/svelte/Slider.svelte +57 -0
  94. package/scaffold/svelte/SoundEffects.svelte +3 -0
  95. package/scaffold/svelte/Switch.svelte +35 -0
  96. package/scaffold/svelte/Tabs.svelte +1 -1
  97. package/scaffold/svelte/Toggle.svelte +41 -0
  98. package/scaffold/svelte/ToggleGroup.svelte +30 -0
  99. package/scaffold/svelte/base/README-RIZZO.md +55 -0
  100. package/scaffold/{svelte-core → svelte/base}/src/routes/+page.svelte +1 -1
  101. package/scaffold/svelte/base/static/.gitkeep +0 -0
  102. package/scaffold/svelte/index.ts +21 -0
  103. package/scaffold/svelte/variants/dashboard/src/routes/+layout.svelte +64 -0
  104. package/scaffold/svelte/variants/dashboard/src/routes/+page.svelte +104 -0
  105. package/scaffold/svelte/variants/docs/src/routes/+layout.svelte +60 -0
  106. package/scaffold/svelte/variants/docs/src/routes/+page.svelte +34 -0
  107. package/scaffold/svelte/variants/docs/src/routes/docs/getting-started/+page.svelte +31 -0
  108. package/scaffold/{svelte-core → svelte/variants/full}/README-RIZZO.md +2 -1
  109. package/scaffold/svelte/variants/full/gitignore +10 -0
  110. package/scaffold/svelte/variants/full/package.json +20 -0
  111. package/scaffold/svelte/variants/full/src/app.d.ts +11 -0
  112. package/scaffold/svelte/variants/full/src/app.html +16 -0
  113. package/scaffold/svelte/variants/full/src/routes/+layout.svelte +1 -0
  114. package/scaffold/svelte/variants/full/src/routes/+page.svelte +105 -0
  115. package/scaffold/svelte/variants/full/static/.gitkeep +0 -0
  116. package/scaffold/svelte/variants/full/svelte.config.js +10 -0
  117. package/scaffold/svelte/variants/full/tsconfig.json +11 -0
  118. package/scaffold/vanilla/README-RIZZO.md +6 -5
  119. package/scaffold/vanilla/components/accordion.html +59 -64
  120. package/scaffold/vanilla/components/alert-dialog.html +640 -0
  121. package/scaffold/vanilla/components/alert.html +59 -64
  122. package/scaffold/vanilla/components/aspect-ratio.html +640 -0
  123. package/scaffold/vanilla/components/avatar.html +59 -64
  124. package/scaffold/vanilla/components/back-to-top.html +59 -64
  125. package/scaffold/vanilla/components/badge.html +59 -64
  126. package/scaffold/vanilla/components/breadcrumb.html +59 -64
  127. package/scaffold/vanilla/components/button-group.html +640 -0
  128. package/scaffold/vanilla/components/button.html +59 -64
  129. package/scaffold/vanilla/components/cards.html +59 -64
  130. package/scaffold/vanilla/components/collapsible.html +640 -0
  131. package/scaffold/vanilla/components/context-menu.html +640 -0
  132. package/scaffold/vanilla/components/copy-to-clipboard.html +59 -64
  133. package/scaffold/vanilla/components/dashboard.html +640 -0
  134. package/scaffold/vanilla/components/divider.html +59 -64
  135. package/scaffold/vanilla/components/docs-sidebar.html +59 -64
  136. package/scaffold/vanilla/components/dropdown.html +59 -64
  137. package/scaffold/vanilla/components/empty.html +640 -0
  138. package/scaffold/vanilla/components/font-switcher.html +59 -64
  139. package/scaffold/vanilla/components/footer.html +59 -64
  140. package/scaffold/vanilla/components/forms.html +59 -64
  141. package/scaffold/vanilla/components/hover-card.html +640 -0
  142. package/scaffold/vanilla/components/icons.html +59 -64
  143. package/scaffold/vanilla/components/index.html +79 -64
  144. package/scaffold/vanilla/components/kbd.html +640 -0
  145. package/scaffold/vanilla/components/label.html +640 -0
  146. package/scaffold/vanilla/components/modal.html +59 -64
  147. package/scaffold/vanilla/components/navbar.html +59 -64
  148. package/scaffold/vanilla/components/pagination.html +59 -64
  149. package/scaffold/vanilla/components/popover.html +640 -0
  150. package/scaffold/vanilla/components/progress-bar.html +59 -64
  151. package/scaffold/vanilla/components/resizable.html +640 -0
  152. package/scaffold/vanilla/components/scroll-area.html +640 -0
  153. package/scaffold/vanilla/components/search.html +59 -64
  154. package/scaffold/vanilla/components/separator.html +640 -0
  155. package/scaffold/vanilla/components/settings.html +59 -64
  156. package/scaffold/vanilla/components/sheet.html +640 -0
  157. package/scaffold/vanilla/components/skeleton.html +640 -0
  158. package/scaffold/vanilla/components/slider.html +640 -0
  159. package/scaffold/vanilla/components/sound-effects.html +59 -64
  160. package/scaffold/vanilla/components/spinner.html +59 -64
  161. package/scaffold/vanilla/components/switch.html +640 -0
  162. package/scaffold/vanilla/components/table.html +59 -64
  163. package/scaffold/vanilla/components/tabs.html +59 -64
  164. package/scaffold/vanilla/components/theme-switcher.html +59 -64
  165. package/scaffold/vanilla/components/toast.html +59 -64
  166. package/scaffold/vanilla/components/toggle-group.html +640 -0
  167. package/scaffold/vanilla/components/toggle.html +640 -0
  168. package/scaffold/vanilla/components/tooltip.html +59 -64
  169. package/scaffold/vanilla/index.html +61 -66
  170. package/scaffold/vanilla/variants/dashboard/index.html +45 -0
  171. package/scaffold/vanilla/variants/docs/index.html +36 -0
  172. package/scaffold/vanilla/variants/full/components/accordion.html +592 -0
  173. package/scaffold/vanilla/variants/full/components/alert.html +592 -0
  174. package/scaffold/vanilla/variants/full/components/avatar.html +592 -0
  175. package/scaffold/vanilla/variants/full/components/back-to-top.html +592 -0
  176. package/scaffold/vanilla/variants/full/components/badge.html +592 -0
  177. package/scaffold/vanilla/variants/full/components/breadcrumb.html +592 -0
  178. package/scaffold/vanilla/variants/full/components/button.html +592 -0
  179. package/scaffold/vanilla/variants/full/components/cards.html +592 -0
  180. package/scaffold/vanilla/variants/full/components/copy-to-clipboard.html +592 -0
  181. package/scaffold/vanilla/variants/full/components/dashboard.html +592 -0
  182. package/scaffold/vanilla/variants/full/components/divider.html +592 -0
  183. package/scaffold/vanilla/variants/full/components/docs-sidebar.html +592 -0
  184. package/scaffold/vanilla/variants/full/components/dropdown.html +592 -0
  185. package/scaffold/vanilla/variants/full/components/font-switcher.html +592 -0
  186. package/scaffold/vanilla/variants/full/components/footer.html +592 -0
  187. package/scaffold/vanilla/variants/full/components/forms.html +592 -0
  188. package/scaffold/vanilla/variants/full/components/icons.html +592 -0
  189. package/scaffold/vanilla/variants/full/components/index.html +625 -0
  190. package/scaffold/vanilla/variants/full/components/modal.html +592 -0
  191. package/scaffold/vanilla/variants/full/components/navbar.html +592 -0
  192. package/scaffold/vanilla/variants/full/components/pagination.html +592 -0
  193. package/scaffold/vanilla/variants/full/components/progress-bar.html +592 -0
  194. package/scaffold/vanilla/variants/full/components/search.html +592 -0
  195. package/scaffold/vanilla/variants/full/components/settings.html +592 -0
  196. package/scaffold/vanilla/variants/full/components/skeleton.html +592 -0
  197. package/scaffold/vanilla/variants/full/components/sound-effects.html +592 -0
  198. package/scaffold/vanilla/variants/full/components/spinner.html +592 -0
  199. package/scaffold/vanilla/variants/full/components/switch.html +592 -0
  200. package/scaffold/vanilla/variants/full/components/table.html +592 -0
  201. package/scaffold/vanilla/variants/full/components/tabs.html +592 -0
  202. package/scaffold/vanilla/variants/full/components/theme-switcher.html +592 -0
  203. package/scaffold/vanilla/variants/full/components/toast.html +592 -0
  204. package/scaffold/vanilla/variants/full/components/tooltip.html +592 -0
  205. package/scaffold/vanilla/variants/full/index.html +682 -0
  206. package/scaffold/vanilla/variants/full/js/main.js +989 -0
  207. package/scaffold/astro-core/.astro/content-assets.mjs +0 -1
  208. package/scaffold/astro-core/.astro/content-modules.mjs +0 -1
  209. package/scaffold/astro-core/.astro/content.d.ts +0 -199
  210. package/scaffold/astro-core/.astro/types.d.ts +0 -2
  211. package/scaffold/astro-core/.env.example +0 -3
  212. package/scaffold/svelte-core/.env.example +0 -3
  213. /package/scaffold/{astro-core → astro/base}/astro.config.mjs +0 -0
  214. /package/scaffold/{astro-core → astro/base}/dist/.gitkeep +0 -0
  215. /package/scaffold/{astro-core → astro/base}/dist/_noop-middleware.mjs +0 -0
  216. /package/scaffold/{astro-core → astro/base}/dist/chunks/astro/server_9Mzx7luy.mjs +0 -0
  217. /package/scaffold/{astro-core → astro/base}/dist/chunks/astro_BOYUKg7r.mjs +0 -0
  218. /package/scaffold/{astro-core → astro/base}/dist/favicon.svg +0 -0
  219. /package/scaffold/{astro-core → astro/base}/dist/manifest_DXpJmqSX.mjs +0 -0
  220. /package/scaffold/{astro-core → astro/base}/dist/noop-entrypoint.mjs +0 -0
  221. /package/scaffold/{astro-core → astro/base}/dist/pages/index.astro.mjs +0 -0
  222. /package/scaffold/{astro-core → astro/base}/dist/renderers.mjs +0 -0
  223. /package/scaffold/{astro-core → astro/base}/gitignore +0 -0
  224. /package/scaffold/{astro-core → astro/base}/node_modules/.astro/data-store.json +0 -0
  225. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/_metadata.json +0 -0
  226. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___aria-query.js +0 -0
  227. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___aria-query.js.map +0 -0
  228. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___axobject-query.js +0 -0
  229. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___axobject-query.js.map +0 -0
  230. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___cssesc.js +0 -0
  231. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/astro___cssesc.js.map +0 -0
  232. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/chunk-BUSYA2B4.js +0 -0
  233. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/chunk-BUSYA2B4.js.map +0 -0
  234. /package/scaffold/{astro-core → astro/base}/node_modules/.vite/deps/package.json +0 -0
  235. /package/scaffold/{astro-core → astro/base}/package.json +0 -0
  236. /package/scaffold/{astro-core → astro/base}/public/.gitkeep +0 -0
  237. /package/scaffold/{astro-core → astro/base}/public/favicon.svg +0 -0
  238. /package/scaffold/{astro-core → astro/base}/src/components/rizzo/CopyToClipboard.astro +0 -0
  239. /package/scaffold/{astro-core → astro/base}/src/components/rizzo/icons/Check.astro +0 -0
  240. /package/scaffold/{astro-core → astro/base}/src/components/rizzo/icons/Copy.astro +0 -0
  241. /package/scaffold/{astro-core → astro/base}/src/layouts/Layout.astro +0 -0
  242. /package/scaffold/{astro-core → astro/base}/tsconfig.json +0 -0
  243. /package/scaffold/{svelte-core/static → astro/variants/full/dist}/.gitkeep +0 -0
  244. /package/scaffold/{svelte-core → svelte/base}/gitignore +0 -0
  245. /package/scaffold/{svelte-core → svelte/base}/package.json +0 -0
  246. /package/scaffold/{svelte-core → svelte/base}/src/app.d.ts +0 -0
  247. /package/scaffold/{svelte-core → svelte/base}/src/app.html +0 -0
  248. /package/scaffold/{svelte-core → svelte/base}/src/routes/+layout.svelte +0 -0
  249. /package/scaffold/{svelte-core → svelte/base}/svelte.config.js +0 -0
  250. /package/scaffold/{svelte-core → svelte/base}/tsconfig.json +0 -0
@@ -0,0 +1,989 @@
1
+ /**
2
+ * Rizzo CSS — Vanilla JS component bundle
3
+ * Theme, toast, settings, tabs, modal, dropdown, accordion, search, navbar (mobile), copy-to-clipboard.
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 fontPairSelect = settings.querySelector('[data-font-pair]');
169
+ var reducedMotion = settings.querySelector('[data-reduced-motion]');
170
+ var highContrast = settings.querySelector('[data-high-contrast]');
171
+ var scrollbarStyleRadios = settings.querySelectorAll('[data-scrollbar-style]');
172
+ var html = document.documentElement;
173
+ if (!panel || !overlay || !closeBtn) return;
174
+ function updateSliderProgress(slider) {
175
+ var min = parseFloat(slider.min), max = parseFloat(slider.max), value = parseFloat(slider.value);
176
+ slider.style.setProperty('--slider-progress', ((value - min) / (max - min)) * 100 + '%');
177
+ }
178
+ function applyFontSize(scale) {
179
+ html.style.setProperty('--font-size-scale', scale);
180
+ if (fontSizeValue) fontSizeValue.textContent = Math.round(scale * 100) + '%';
181
+ }
182
+ function applyScrollbarStyle(style) {
183
+ html.classList.remove('scrollbar-thin', 'scrollbar-thick', 'scrollbar-hidden', 'hide-scrollbars');
184
+ if (style === 'thick') html.classList.add('scrollbar-thick');
185
+ else if (style === 'hidden') html.classList.add('scrollbar-hidden', 'hide-scrollbars');
186
+ }
187
+ function loadSettings() {
188
+ var saved = localStorage.getItem('fontSizeScale');
189
+ if (saved && fontSizeSlider) {
190
+ fontSizeSlider.value = saved;
191
+ applyFontSize(parseFloat(saved));
192
+ }
193
+ if (fontSizeSlider) updateSliderProgress(fontSizeSlider);
194
+ var savedFontPair = localStorage.getItem('fontPair') || 'geist';
195
+ if (fontPairSelect) {
196
+ fontPairSelect.value = savedFontPair;
197
+ var opt = fontPairSelect.options[fontPairSelect.selectedIndex];
198
+ if (opt && opt.dataset.sans && opt.dataset.mono) {
199
+ html.style.setProperty('--font-family', opt.dataset.sans);
200
+ html.style.setProperty('--font-family-mono', opt.dataset.mono);
201
+ }
202
+ }
203
+ if (reducedMotion) {
204
+ reducedMotion.checked = localStorage.getItem('reducedMotion') === 'true';
205
+ html.classList.toggle('reduced-motion', reducedMotion.checked);
206
+ }
207
+ if (highContrast) {
208
+ highContrast.checked = localStorage.getItem('highContrast') === 'true';
209
+ html.classList.toggle('high-contrast', highContrast.checked);
210
+ }
211
+ var scrollbar = localStorage.getItem('scrollbarStyle') || 'thin';
212
+ for (var i = 0; i < scrollbarStyleRadios.length; i++) {
213
+ if (scrollbarStyleRadios[i].value === scrollbar) scrollbarStyleRadios[i].checked = true;
214
+ }
215
+ applyScrollbarStyle(scrollbar);
216
+ }
217
+ function getFocusable(container) {
218
+ var sel = 'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
219
+ return Array.prototype.slice.call(container.querySelectorAll(sel));
220
+ }
221
+ var previousActive = null;
222
+ function openSettings() {
223
+ previousActive = document.activeElement;
224
+ settings.setAttribute('aria-hidden', 'false');
225
+ overlay.setAttribute('aria-hidden', 'false');
226
+ panel.setAttribute('aria-hidden', 'false');
227
+ panel.removeAttribute('data-open');
228
+ void panel.offsetHeight;
229
+ requestAnimationFrame(function () {
230
+ requestAnimationFrame(function () {
231
+ panel.setAttribute('data-open', 'true');
232
+ if (closeBtn) closeBtn.focus();
233
+ });
234
+ });
235
+ }
236
+ function closeSettings() {
237
+ panel.removeAttribute('data-open');
238
+ var duration = window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : 300;
239
+ setTimeout(function () {
240
+ settings.setAttribute('aria-hidden', 'true');
241
+ overlay.setAttribute('aria-hidden', 'true');
242
+ panel.setAttribute('aria-hidden', 'true');
243
+ if (previousActive) {
244
+ previousActive.focus();
245
+ previousActive = null;
246
+ }
247
+ }, duration);
248
+ }
249
+ closeBtn.addEventListener('click', closeSettings);
250
+ overlay.addEventListener('click', closeSettings);
251
+ document.addEventListener('keydown', function (e) {
252
+ if (panel.getAttribute('data-open') !== 'true') return;
253
+ if (e.key === 'Escape') { e.preventDefault(); closeSettings(); return; }
254
+ if (e.key === 'Tab') {
255
+ var els = getFocusable(panel);
256
+ if (els.length === 0) return;
257
+ var first = els[0], last = els[els.length - 1], active = document.activeElement;
258
+ if (e.shiftKey) {
259
+ if (active === first || !panel.contains(active)) { e.preventDefault(); last.focus(); }
260
+ } else {
261
+ if (active === last || !panel.contains(active)) { e.preventDefault(); first.focus(); }
262
+ }
263
+ }
264
+ });
265
+ if (fontSizeSlider) {
266
+ fontSizeSlider.addEventListener('input', function () {
267
+ var scale = parseFloat(this.value);
268
+ applyFontSize(scale);
269
+ updateSliderProgress(this);
270
+ localStorage.setItem('fontSizeScale', scale);
271
+ });
272
+ }
273
+ if (fontPairSelect) {
274
+ fontPairSelect.addEventListener('change', function () {
275
+ var opt = this.options[this.selectedIndex];
276
+ if (opt && opt.dataset.sans && opt.dataset.mono) {
277
+ html.style.setProperty('--font-family', opt.dataset.sans);
278
+ html.style.setProperty('--font-family-mono', opt.dataset.mono);
279
+ localStorage.setItem('fontPair', opt.value);
280
+ }
281
+ });
282
+ }
283
+ if (reducedMotion) {
284
+ reducedMotion.addEventListener('change', function () {
285
+ html.classList.toggle('reduced-motion', this.checked);
286
+ localStorage.setItem('reducedMotion', this.checked);
287
+ });
288
+ }
289
+ if (highContrast) {
290
+ highContrast.addEventListener('change', function () {
291
+ html.classList.toggle('high-contrast', this.checked);
292
+ localStorage.setItem('highContrast', this.checked);
293
+ });
294
+ }
295
+ for (var j = 0; j < scrollbarStyleRadios.length; j++) {
296
+ scrollbarStyleRadios[j].addEventListener('change', function () {
297
+ if (this.checked) {
298
+ applyScrollbarStyle(this.value);
299
+ localStorage.setItem('scrollbarStyle', this.value);
300
+ }
301
+ });
302
+ }
303
+ loadSettings();
304
+ window.openSettings = openSettings;
305
+ }
306
+
307
+ // --- Copy to clipboard: .copy-to-clipboard [data-copy-value] or [data-copy] with value ---
308
+ function initCopyToClipboard() {
309
+ function setupButton(btn) {
310
+ if (btn.getAttribute('data-copy-inited') === 'true') return;
311
+ btn.setAttribute('data-copy-inited', 'true');
312
+ var host = btn.closest('.tooltip-host');
313
+ var defaultTooltip = (host && host.getAttribute('data-tooltip')) || 'Copy to clipboard';
314
+ if (host) host.setAttribute('data-copy-default-tooltip', defaultTooltip);
315
+ var defaultAria = btn.getAttribute('aria-label') || 'Copy to clipboard';
316
+ var getValue = function () { return btn.getAttribute('data-copy-value') || btn.getAttribute('value') || ''; };
317
+ var getFormat = function () { return btn.getAttribute('data-copy-format') || ''; };
318
+ var copyIcon = btn.querySelector('.copy-to-clipboard__icon--copy');
319
+ var checkIcon = btn.querySelector('.copy-to-clipboard__icon--check');
320
+ var feedback = btn.querySelector('.copy-to-clipboard__feedback');
321
+ var textSpan = btn.querySelector('.copy-to-clipboard__text');
322
+ function doCopy() {
323
+ var value = getValue();
324
+ if (!value && textSpan) value = textSpan.textContent || '';
325
+ if (!value) return;
326
+ function showSuccess() {
327
+ if (copyIcon) copyIcon.classList.add('copy-to-clipboard__icon--hidden');
328
+ if (checkIcon) checkIcon.classList.remove('copy-to-clipboard__icon--hidden');
329
+ if (feedback) feedback.textContent = getFormat() ? 'Copied ' + getFormat() + '!' : 'Copied!';
330
+ if (host) host.setAttribute('data-tooltip', getFormat() ? 'Copied ' + getFormat() + '!' : 'Copied!');
331
+ btn.setAttribute('aria-label', getFormat() ? 'Copied ' + getFormat() + '!' : 'Copied!');
332
+ var labelEl = btn.querySelector('.copy-trigger__text');
333
+ var previousLabel = labelEl ? labelEl.textContent : '';
334
+ if (labelEl) labelEl.textContent = 'Copied!';
335
+ setTimeout(function () {
336
+ if (copyIcon) copyIcon.classList.remove('copy-to-clipboard__icon--hidden');
337
+ if (checkIcon) checkIcon.classList.add('copy-to-clipboard__icon--hidden');
338
+ if (feedback) feedback.textContent = '';
339
+ if (host) host.setAttribute('data-tooltip', host.getAttribute('data-copy-default-tooltip') || defaultTooltip);
340
+ btn.setAttribute('aria-label', defaultAria);
341
+ if (labelEl) labelEl.textContent = previousLabel || 'Copy';
342
+ }, 2000);
343
+ }
344
+ if (typeof navigator.clipboard !== 'undefined' && navigator.clipboard.writeText) {
345
+ navigator.clipboard.writeText(value).then(showSuccess).catch(function () {
346
+ try {
347
+ var ta = document.createElement('textarea');
348
+ ta.value = value;
349
+ ta.style.position = 'fixed';
350
+ ta.style.left = '-9999px';
351
+ document.body.appendChild(ta);
352
+ ta.focus();
353
+ ta.select();
354
+ document.execCommand('copy');
355
+ document.body.removeChild(ta);
356
+ showSuccess();
357
+ } catch (e) {
358
+ if (window.showToast) window.showToast('Failed to copy', { variant: 'warning' });
359
+ }
360
+ });
361
+ } else {
362
+ try {
363
+ var ta = document.createElement('textarea');
364
+ ta.value = value;
365
+ ta.style.position = 'fixed';
366
+ ta.style.left = '-9999px';
367
+ document.body.appendChild(ta);
368
+ ta.focus();
369
+ ta.select();
370
+ document.execCommand('copy');
371
+ document.body.removeChild(ta);
372
+ showSuccess();
373
+ } catch (e) {
374
+ if (window.showToast) window.showToast('Failed to copy', { variant: 'warning' });
375
+ }
376
+ }
377
+ }
378
+ btn.addEventListener('click', doCopy);
379
+ }
380
+ document.querySelectorAll('.copy-to-clipboard[data-copy-value], .copy-to-clipboard[data-copy], [data-copy]').forEach(setupButton);
381
+ }
382
+
383
+ // --- Tabs: init all [data-tabs] ---
384
+ function initTabs() {
385
+ document.querySelectorAll('[data-tabs]').forEach(function (tabsContainer) {
386
+ if (tabsContainer.getAttribute('data-rizzo-tabs-inited')) return;
387
+ tabsContainer.setAttribute('data-rizzo-tabs-inited', 'true');
388
+ var tabButtons = tabsContainer.querySelectorAll('[role="tab"]');
389
+ var tabPanels = tabsContainer.querySelectorAll('[role="tabpanel"]');
390
+ if (tabButtons.length === 0 || tabPanels.length === 0) return;
391
+ var activeIndex = -1;
392
+ for (var i = 0; i < tabButtons.length; i++) {
393
+ if (tabButtons[i].classList.contains('tabs__tab--active')) { activeIndex = i; break; }
394
+ }
395
+ if (activeIndex === -1) activeIndex = 0;
396
+ function activateTab(index) {
397
+ if (index < 0 || index >= tabButtons.length) return;
398
+ var targetButton = tabButtons[index];
399
+ var targetTabId = targetButton.getAttribute('data-tab-id');
400
+ if (!targetTabId) return;
401
+ for (var i = 0; i < tabButtons.length; i++) {
402
+ var isActive = i === index;
403
+ tabButtons[i].setAttribute('aria-selected', isActive ? 'true' : 'false');
404
+ tabButtons[i].setAttribute('tabindex', isActive ? '0' : '-1');
405
+ tabButtons[i].classList.toggle('tabs__tab--active', isActive);
406
+ }
407
+ for (var p = 0; p < tabPanels.length; p++) {
408
+ var panelId = tabPanels[p].getAttribute('data-panel-id');
409
+ var isActive = panelId === targetTabId;
410
+ tabPanels[p].setAttribute('aria-hidden', isActive ? 'false' : 'true');
411
+ tabPanels[p].classList.toggle('tabs__panel--active', isActive);
412
+ }
413
+ }
414
+ for (var i = 0; i < tabButtons.length; i++) {
415
+ (function (idx) {
416
+ tabButtons[idx].addEventListener('click', function () { activateTab(idx); });
417
+ tabButtons[idx].addEventListener('keydown', function (e) {
418
+ var targetIndex = idx;
419
+ switch (e.key) {
420
+ case 'ArrowRight':
421
+ case 'ArrowDown':
422
+ e.preventDefault();
423
+ targetIndex = (idx + 1) % tabButtons.length;
424
+ break;
425
+ case 'ArrowLeft':
426
+ case 'ArrowUp':
427
+ e.preventDefault();
428
+ targetIndex = idx === 0 ? tabButtons.length - 1 : idx - 1;
429
+ break;
430
+ case 'Home':
431
+ e.preventDefault();
432
+ targetIndex = 0;
433
+ break;
434
+ case 'End':
435
+ e.preventDefault();
436
+ targetIndex = tabButtons.length - 1;
437
+ break;
438
+ case 'Enter':
439
+ case ' ':
440
+ e.preventDefault();
441
+ activateTab(idx);
442
+ return;
443
+ default:
444
+ return;
445
+ }
446
+ activateTab(targetIndex);
447
+ tabButtons[targetIndex].focus();
448
+ });
449
+ })(i);
450
+ }
451
+ });
452
+ }
453
+
454
+ // --- Modal: [data-modal-open="modalId"] opens #modalId, #modalId-overlay, [data-modal-close] ---
455
+ function initModals() {
456
+ var inited = {};
457
+ function initModal(modalId) {
458
+ if (inited[modalId]) return;
459
+ var modal = document.getElementById(modalId);
460
+ var overlay = document.getElementById(modalId + '-overlay');
461
+ if (!modal || !overlay) return;
462
+ var closeBtn = modal.querySelector('[data-modal-close]');
463
+ if (!closeBtn) return;
464
+ inited[modalId] = true;
465
+ modal.setAttribute('data-rizzo-modal-inited', 'true');
466
+ var focusableSelectors = 'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
467
+ function getFocusable(container) {
468
+ return Array.prototype.slice.call(container.querySelectorAll(focusableSelectors));
469
+ }
470
+ var previousActive = null;
471
+ var focusTrapHandler = null;
472
+ function openModal() {
473
+ previousActive = document.activeElement;
474
+ modal.setAttribute('aria-hidden', 'false');
475
+ overlay.setAttribute('aria-hidden', 'false');
476
+ modal.setAttribute('data-open', 'true');
477
+ var focusable = getFocusable(modal);
478
+ var first = focusable.length ? focusable[0] : closeBtn;
479
+ if (first) setTimeout(function () { first.focus(); }, 0);
480
+ focusTrapHandler = function (e) {
481
+ if (modal.getAttribute('data-open') !== 'true') return;
482
+ if (e.key === 'Escape') { e.preventDefault(); closeModal(); return; }
483
+ if (e.key === 'Tab') {
484
+ var els = getFocusable(modal);
485
+ if (els.length === 0) return;
486
+ var firstEl = els[0], lastEl = els[els.length - 1], active = document.activeElement;
487
+ if (e.shiftKey) {
488
+ if (active === firstEl || !modal.contains(active)) { e.preventDefault(); lastEl.focus(); }
489
+ } else {
490
+ if (active === lastEl || !modal.contains(active)) { e.preventDefault(); firstEl.focus(); }
491
+ }
492
+ }
493
+ };
494
+ document.addEventListener('keydown', focusTrapHandler);
495
+ }
496
+ function closeModal() {
497
+ modal.setAttribute('aria-hidden', 'true');
498
+ overlay.setAttribute('aria-hidden', 'true');
499
+ modal.removeAttribute('data-open');
500
+ if (focusTrapHandler) {
501
+ document.removeEventListener('keydown', focusTrapHandler);
502
+ focusTrapHandler = null;
503
+ }
504
+ if (previousActive) { previousActive.focus(); previousActive = null; }
505
+ }
506
+ closeBtn.addEventListener('click', closeModal);
507
+ overlay.addEventListener('click', function (e) {
508
+ if (e.target === overlay) closeModal();
509
+ });
510
+ var idSafe = modalId.replace(/-/g, '_');
511
+ window['openModal_' + idSafe] = openModal;
512
+ window['closeModal_' + idSafe] = closeModal;
513
+ }
514
+ document.querySelectorAll('[data-modal-close]').forEach(function (closeBtn) {
515
+ var modal = closeBtn.closest ? closeBtn.closest('[role="dialog"]') : null;
516
+ if (modal && modal.id) initModal(modal.id);
517
+ });
518
+ document.querySelectorAll('[data-modal-open]').forEach(function (btn) {
519
+ var modalId = btn.getAttribute('data-modal-open');
520
+ if (!modalId) return;
521
+ initModal(modalId);
522
+ var openModalFn = window['openModal_' + modalId.replace(/-/g, '_')];
523
+ if (openModalFn) btn.addEventListener('click', function () { openModalFn(); });
524
+ });
525
+ }
526
+
527
+ // --- Dropdown: init all [data-dropdown] ---
528
+ function initDropdowns() {
529
+ var dropdowns = document.querySelectorAll('[data-dropdown]');
530
+ dropdowns.forEach(function (dropdown) {
531
+ var dropdownId = dropdown.getAttribute('data-dropdown');
532
+ if (!dropdownId) return;
533
+ if (dropdown.hasAttribute('data-dropdown-initialized')) return;
534
+ dropdown.setAttribute('data-dropdown-initialized', 'true');
535
+ var trigger = dropdown.querySelector('.dropdown__trigger');
536
+ var menu = dropdown.querySelector('.dropdown__menu');
537
+ var items = dropdown.querySelectorAll('.dropdown__item');
538
+ var itemWrappers = dropdown.querySelectorAll('.dropdown__item-wrapper');
539
+ if (!trigger || !menu) return;
540
+ var currentIndex = -1;
541
+ function getVisibleItems() {
542
+ return Array.prototype.filter.call(items, function (item) {
543
+ var disabled = item.getAttribute('aria-disabled') === 'true';
544
+ var wrapper = item.closest('.dropdown__item-wrapper');
545
+ var submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
546
+ if (submenu && item.closest('.dropdown__submenu')) return false;
547
+ return !disabled && (item.offsetParent !== null || menu.classList.contains('dropdown__menu--open'));
548
+ });
549
+ }
550
+ function closeAllSubmenus(exceptWrapper) {
551
+ for (var w = 0; w < itemWrappers.length; w++) {
552
+ if (itemWrappers[w] === exceptWrapper) continue;
553
+ var sub = itemWrappers[w].querySelector('.dropdown__submenu');
554
+ var it = itemWrappers[w].querySelector('.dropdown__item');
555
+ if (sub && it) {
556
+ sub.classList.remove('dropdown__submenu--open');
557
+ sub.setAttribute('aria-hidden', 'true');
558
+ it.setAttribute('aria-expanded', 'false');
559
+ }
560
+ }
561
+ }
562
+ function toggleSubmenu(wrapper, open) {
563
+ var submenu = wrapper.querySelector('.dropdown__submenu');
564
+ var item = wrapper.querySelector('.dropdown__item');
565
+ if (!submenu || !item) return;
566
+ var isOpen = open !== undefined ? open : submenu.classList.contains('dropdown__submenu--open');
567
+ var willBeOpen = !isOpen;
568
+ if (willBeOpen) {
569
+ var parentSub = wrapper.closest('.dropdown__submenu');
570
+ if (parentSub) {
571
+ var siblings = parentSub.querySelectorAll('.dropdown__item-wrapper');
572
+ for (var s = 0; s < siblings.length; s++) {
573
+ if (siblings[s] === wrapper) continue;
574
+ var sSub = siblings[s].querySelector('.dropdown__submenu');
575
+ var sItem = siblings[s].querySelector('.dropdown__item');
576
+ if (sSub && sItem) {
577
+ sSub.classList.remove('dropdown__submenu--open');
578
+ sSub.setAttribute('aria-hidden', 'true');
579
+ sItem.setAttribute('aria-expanded', 'false');
580
+ }
581
+ }
582
+ } else {
583
+ closeAllSubmenus(wrapper);
584
+ }
585
+ }
586
+ if (willBeOpen) {
587
+ submenu.classList.add('dropdown__submenu--open');
588
+ submenu.setAttribute('aria-hidden', 'false');
589
+ item.setAttribute('aria-expanded', 'true');
590
+ } else {
591
+ submenu.classList.remove('dropdown__submenu--open');
592
+ submenu.setAttribute('aria-hidden', 'true');
593
+ item.setAttribute('aria-expanded', 'false');
594
+ }
595
+ }
596
+ function toggleMenu(open) {
597
+ var isOpen = open !== undefined ? open : menu.classList.contains('dropdown__menu--open');
598
+ var willBeOpen = !isOpen;
599
+ menu.classList.toggle('dropdown__menu--open', willBeOpen);
600
+ trigger.setAttribute('aria-expanded', willBeOpen.toString());
601
+ menu.setAttribute('aria-hidden', (!willBeOpen).toString());
602
+ for (var i = 0; i < items.length; i++) items[i].setAttribute('tabindex', willBeOpen ? '0' : '-1');
603
+ if (!willBeOpen) {
604
+ trigger.focus();
605
+ currentIndex = -1;
606
+ closeAllSubmenus();
607
+ } else {
608
+ var vis = getVisibleItems();
609
+ if (vis.length > 0) {
610
+ currentIndex = 0;
611
+ setTimeout(function () { vis[0].focus(); }, 0);
612
+ }
613
+ }
614
+ }
615
+ function closeMenu() {
616
+ menu.classList.remove('dropdown__menu--open');
617
+ trigger.setAttribute('aria-expanded', 'false');
618
+ menu.setAttribute('aria-hidden', 'true');
619
+ for (var i = 0; i < items.length; i++) items[i].setAttribute('tabindex', '-1');
620
+ closeAllSubmenus();
621
+ currentIndex = -1;
622
+ }
623
+ function handleOutsideClick(e) {
624
+ if (e && e.target && !dropdown.contains(e.target)) {
625
+ closeMenu();
626
+ document.removeEventListener('click', handleOutsideClick);
627
+ }
628
+ }
629
+ function wrappedToggle(open) {
630
+ var was = menu.classList.contains('dropdown__menu--open');
631
+ toggleMenu(open);
632
+ var now = menu.classList.contains('dropdown__menu--open');
633
+ if (now && !was) setTimeout(function () { document.addEventListener('click', handleOutsideClick); }, 0);
634
+ else if (!now && was) document.removeEventListener('click', handleOutsideClick);
635
+ }
636
+ trigger.addEventListener('click', function () { wrappedToggle(undefined); });
637
+ menu.addEventListener('click', function (e) {
638
+ var target = e.target;
639
+ var item = target.closest ? target.closest('.dropdown__item') : null;
640
+ if (!item) return;
641
+ e.stopPropagation();
642
+ if (item.getAttribute('aria-disabled') === 'true') { e.preventDefault(); return; }
643
+ var wrapper = item.closest('.dropdown__item-wrapper');
644
+ if (wrapper) {
645
+ var sub = wrapper.querySelector('.dropdown__submenu');
646
+ if (sub) {
647
+ e.preventDefault();
648
+ e.stopImmediatePropagation();
649
+ toggleSubmenu(wrapper, undefined);
650
+ return;
651
+ }
652
+ }
653
+ var href = item.getAttribute('data-dropdown-href');
654
+ if (href) { window.location.href = href; }
655
+ var onClick = item.getAttribute('data-dropdown-onclick');
656
+ if (onClick && typeof window[onClick] === 'function') {
657
+ var val = item.getAttribute('data-dropdown-value') || item.textContent.trim() || '';
658
+ window[onClick](val);
659
+ }
660
+ closeMenu();
661
+ });
662
+ trigger.addEventListener('keydown', function (e) {
663
+ if (e.key === 'Enter' || e.key === ' ') {
664
+ e.preventDefault();
665
+ wrappedToggle(undefined);
666
+ } else if (e.key === 'ArrowDown') {
667
+ e.preventDefault();
668
+ var vis = getVisibleItems();
669
+ if (vis.length > 0) {
670
+ currentIndex = 0;
671
+ wrappedToggle(true);
672
+ setTimeout(function () { vis[0].focus(); }, 0);
673
+ }
674
+ } else if (e.key === 'ArrowUp') {
675
+ e.preventDefault();
676
+ var vis = getVisibleItems();
677
+ if (vis.length > 0) {
678
+ currentIndex = vis.length - 1;
679
+ wrappedToggle(true);
680
+ setTimeout(function () { vis[currentIndex].focus(); }, 0);
681
+ }
682
+ } else if (e.key === 'Escape') {
683
+ e.preventDefault();
684
+ closeMenu();
685
+ }
686
+ });
687
+ menu.addEventListener('keydown', function (e) {
688
+ var vis = getVisibleItems();
689
+ if (e.key === 'Escape') {
690
+ e.preventDefault();
691
+ closeMenu();
692
+ trigger.focus();
693
+ } else if (e.key === 'ArrowDown') {
694
+ e.preventDefault();
695
+ currentIndex = (currentIndex + 1) % vis.length;
696
+ vis[currentIndex].focus();
697
+ } else if (e.key === 'ArrowUp') {
698
+ e.preventDefault();
699
+ currentIndex = currentIndex <= 0 ? vis.length - 1 : currentIndex - 1;
700
+ vis[currentIndex].focus();
701
+ } else if (e.key === 'Home') {
702
+ e.preventDefault();
703
+ currentIndex = 0;
704
+ vis[0].focus();
705
+ } else if (e.key === 'End') {
706
+ e.preventDefault();
707
+ currentIndex = vis.length - 1;
708
+ vis[currentIndex].focus();
709
+ } else if (e.key === 'ArrowRight') {
710
+ var t = e.target;
711
+ if (t && t.closest) {
712
+ var w = t.closest('.dropdown__item-wrapper');
713
+ if (w) {
714
+ var sub = w.querySelector('.dropdown__submenu');
715
+ if (sub) {
716
+ e.preventDefault();
717
+ toggleSubmenu(w, true);
718
+ var first = sub.querySelector('.dropdown__item');
719
+ if (first) setTimeout(function () { first.focus(); }, 0);
720
+ }
721
+ }
722
+ }
723
+ } else if (e.key === 'ArrowLeft') {
724
+ var t = e.target;
725
+ if (t && t.closest) {
726
+ var sub = t.closest('.dropdown__submenu');
727
+ if (sub) {
728
+ e.preventDefault();
729
+ var w = sub.closest('.dropdown__item-wrapper');
730
+ if (w) {
731
+ toggleSubmenu(w, false);
732
+ var p = w.querySelector('.dropdown__item');
733
+ if (p) p.focus();
734
+ }
735
+ }
736
+ }
737
+ } else if (e.key === 'Enter' || e.key === ' ') {
738
+ e.preventDefault();
739
+ var t = e.target;
740
+ if (t && t.getAttribute && t.getAttribute('aria-disabled') !== 'true') {
741
+ var w = t.closest('.dropdown__item-wrapper');
742
+ var sub = w ? w.querySelector('.dropdown__submenu') : null;
743
+ if (sub) toggleSubmenu(w, undefined);
744
+ else {
745
+ if (t.tagName === 'A') t.click();
746
+ else if (t.tagName === 'BUTTON') t.click();
747
+ closeMenu();
748
+ }
749
+ }
750
+ } else if (e.key === 'Tab') {
751
+ closeMenu();
752
+ }
753
+ });
754
+ });
755
+ }
756
+
757
+ // --- Accordion: init all [data-accordion] ---
758
+ function initAccordions() {
759
+ function initOne(accordion) {
760
+ if (accordion.getAttribute('data-accordion-init') === 'true') return;
761
+ accordion.setAttribute('data-accordion-init', 'true');
762
+ var isMultiple = accordion.getAttribute('data-allow-multiple') === 'true';
763
+ var triggers = accordion.querySelectorAll('[data-accordion-trigger]');
764
+ function setExpanded(trigger, expanded) {
765
+ var panelId = trigger.getAttribute('aria-controls');
766
+ var panel = panelId ? accordion.querySelector('#' + CSS.escape(panelId)) : null;
767
+ trigger.setAttribute('aria-expanded', String(expanded));
768
+ trigger.classList.toggle('accordion__trigger--expanded', expanded);
769
+ if (panel) {
770
+ panel.classList.toggle('accordion__panel--expanded', expanded);
771
+ panel.hidden = !expanded;
772
+ }
773
+ }
774
+ function toggle(trigger) {
775
+ var expanded = trigger.getAttribute('aria-expanded') === 'true';
776
+ if (!isMultiple) {
777
+ for (var i = 0; i < triggers.length; i++) setExpanded(triggers[i], false);
778
+ }
779
+ setExpanded(trigger, !expanded);
780
+ }
781
+ for (var i = 0; i < triggers.length; i++) {
782
+ triggers[i].addEventListener('click', function () { toggle(this); });
783
+ }
784
+ for (var i = 0; i < triggers.length; i++) {
785
+ (function (idx) {
786
+ triggers[idx].addEventListener('keydown', function (e) {
787
+ var targetIndex = idx;
788
+ switch (e.key) {
789
+ case 'ArrowDown':
790
+ e.preventDefault();
791
+ targetIndex = Math.min(idx + 1, triggers.length - 1);
792
+ break;
793
+ case 'ArrowUp':
794
+ e.preventDefault();
795
+ targetIndex = Math.max(idx - 1, 0);
796
+ break;
797
+ case 'Home':
798
+ e.preventDefault();
799
+ targetIndex = 0;
800
+ break;
801
+ case 'End':
802
+ e.preventDefault();
803
+ targetIndex = triggers.length - 1;
804
+ break;
805
+ case 'Enter':
806
+ case ' ':
807
+ e.preventDefault();
808
+ toggle(triggers[idx]);
809
+ return;
810
+ default:
811
+ return;
812
+ }
813
+ if (targetIndex !== idx) triggers[targetIndex].focus();
814
+ });
815
+ })(i);
816
+ }
817
+ var slotContent = accordion.querySelector('.accordion__slot-content');
818
+ if (slotContent) {
819
+ var slotChildren = Array.prototype.slice.call(slotContent.children);
820
+ for (var i = 0; i < slotChildren.length; i++) {
821
+ var placeholder = accordion.querySelector('[data-accordion-slot-index="' + i + '"]');
822
+ if (placeholder) placeholder.appendChild(slotChildren[i]);
823
+ }
824
+ slotContent.remove();
825
+ }
826
+ }
827
+ document.querySelectorAll('[data-accordion]').forEach(initOne);
828
+ }
829
+
830
+ // --- Search: [data-search] — trigger opens overlay, panel has header (input + close), focus trap, overlay/close/Escape close
831
+ function initSearch() {
832
+ var focusableSel = 'button:not([disabled]),a[href],input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
833
+ function getFocusable(container) {
834
+ return Array.prototype.slice.call(container.querySelectorAll(focusableSel));
835
+ }
836
+ document.querySelectorAll('[data-search]').forEach(function (search) {
837
+ if (search.getAttribute('data-search-inited') === 'true') return;
838
+ search.setAttribute('data-search-inited', 'true');
839
+ var trigger = search.querySelector('.search__trigger');
840
+ var overlay = search.querySelector('[data-search-overlay]');
841
+ var panel = search.querySelector('.search__panel');
842
+ var input = search.querySelector('.search__input');
843
+ var closeBtn = search.querySelector('[data-search-close]');
844
+ var resultItems = search.querySelectorAll('.search__result-item');
845
+ if (!trigger || !overlay || !panel || !input) return;
846
+ var previousActive = null;
847
+ var focusTrapHandler = null;
848
+ function openSearch() {
849
+ previousActive = document.activeElement;
850
+ overlay.setAttribute('aria-hidden', 'false');
851
+ panel.setAttribute('aria-hidden', 'false');
852
+ panel.setAttribute('data-open', 'true');
853
+ trigger.setAttribute('aria-expanded', 'true');
854
+ for (var i = 0; i < resultItems.length; i++) resultItems[i].setAttribute('tabindex', '0');
855
+ input.focus();
856
+ focusTrapHandler = function (e) {
857
+ if (panel.getAttribute('data-open') !== 'true') return;
858
+ if (e.key === 'Escape') { e.preventDefault(); closeSearch(); return; }
859
+ if (e.key === 'Tab') {
860
+ var els = getFocusable(panel);
861
+ if (els.length === 0) return;
862
+ var first = els[0], last = els[els.length - 1], active = document.activeElement;
863
+ if (e.shiftKey) {
864
+ if (active === first || !panel.contains(active)) { e.preventDefault(); last.focus(); }
865
+ } else {
866
+ if (active === last || !panel.contains(active)) { e.preventDefault(); first.focus(); }
867
+ }
868
+ }
869
+ };
870
+ document.addEventListener('keydown', focusTrapHandler);
871
+ }
872
+ function closeSearch() {
873
+ document.removeEventListener('keydown', focusTrapHandler);
874
+ focusTrapHandler = null;
875
+ panel.removeAttribute('data-open');
876
+ panel.setAttribute('aria-hidden', 'true');
877
+ overlay.setAttribute('aria-hidden', 'true');
878
+ trigger.setAttribute('aria-expanded', 'false');
879
+ for (var i = 0; i < resultItems.length; i++) resultItems[i].setAttribute('tabindex', '-1');
880
+ if (previousActive && typeof previousActive.focus === 'function') previousActive.focus();
881
+ previousActive = null;
882
+ }
883
+ trigger.addEventListener('click', function () {
884
+ if (panel.getAttribute('data-open') === 'true') closeSearch(); else openSearch();
885
+ });
886
+ if (closeBtn) closeBtn.addEventListener('click', closeSearch);
887
+ overlay.addEventListener('click', function (e) {
888
+ if (e.target === overlay) closeSearch();
889
+ });
890
+ input.addEventListener('keydown', function (e) {
891
+ if (e.key === 'Escape') { e.preventDefault(); closeSearch(); }
892
+ });
893
+ search.__searchOpen = openSearch;
894
+ search.__searchClose = closeSearch;
895
+ });
896
+ if (!window.__rizzoSearchCmdK) {
897
+ window.__rizzoSearchCmdK = true;
898
+ document.addEventListener('keydown', function (e) {
899
+ var isMod = e.ctrlKey || e.metaKey;
900
+ var isK = e.key === 'k' || e.key === 'K';
901
+ if (!isMod || !isK) return;
902
+ var searchEl = document.querySelector('[data-search]');
903
+ if (!searchEl || !searchEl.__searchOpen) return;
904
+ var panelEl = searchEl.querySelector('.search__panel');
905
+ if (!panelEl) return;
906
+ var target = e.target;
907
+ var inOtherInput = target && !searchEl.contains(target) && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable === true || (target.closest && target.closest('input, textarea, [contenteditable="true"]')));
908
+ var isOpen = panelEl.getAttribute('data-open') === 'true';
909
+ if (isOpen || !inOtherInput) {
910
+ e.preventDefault();
911
+ e.stopPropagation();
912
+ if (isOpen) searchEl.__searchClose(); else searchEl.__searchOpen();
913
+ }
914
+ }, true);
915
+ }
916
+ }
917
+
918
+ function initNavbarMobile() {
919
+ document.querySelectorAll('.navbar').forEach(function (navbar) {
920
+ var toggle = navbar.querySelector('.navbar__toggle');
921
+ var menu = navbar.querySelector('.navbar__menu');
922
+ if (!toggle || !menu) return;
923
+ var outsideClickHandler = null;
924
+ function setMenuOpen(open) {
925
+ menu.classList.toggle('navbar__menu--open', open);
926
+ navbar.classList.toggle('navbar--menu-open', open);
927
+ toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
928
+ menu.setAttribute('aria-hidden', open ? 'false' : 'true');
929
+ if (outsideClickHandler) {
930
+ document.removeEventListener('click', outsideClickHandler);
931
+ outsideClickHandler = null;
932
+ }
933
+ if (open) {
934
+ outsideClickHandler = function (e) {
935
+ if (e.target && !navbar.contains(e.target)) setMenuOpen(false);
936
+ };
937
+ setTimeout(function () { document.addEventListener('click', outsideClickHandler); }, 0);
938
+ }
939
+ }
940
+ toggle.addEventListener('click', function () {
941
+ setMenuOpen(!menu.classList.contains('navbar__menu--open'));
942
+ });
943
+ menu.querySelectorAll('.navbar__link').forEach(function (link) {
944
+ link.addEventListener('click', function () { setMenuOpen(false); });
945
+ });
946
+ document.addEventListener('keydown', function (e) {
947
+ if (e.key === 'Escape' && menu.classList.contains('navbar__menu--open')) setMenuOpen(false);
948
+ });
949
+ });
950
+ }
951
+
952
+ function initBackToTop() {
953
+ var wrapper = document.querySelector('[data-back-to-top]');
954
+ var btn = wrapper && wrapper.querySelector('[data-back-to-top-btn]');
955
+ if (!wrapper || !btn) return;
956
+ var threshold = Number(wrapper.getAttribute('data-threshold')) || 400;
957
+ function updateVisibility() {
958
+ var visible = window.scrollY > threshold;
959
+ wrapper.setAttribute('data-visible', visible ? 'true' : 'false');
960
+ wrapper.setAttribute('aria-hidden', visible ? 'false' : 'true');
961
+ }
962
+ function scrollToTop() {
963
+ window.scrollTo({ top: 0, behavior: 'smooth' });
964
+ }
965
+ window.addEventListener('scroll', updateVisibility, { passive: true });
966
+ btn.addEventListener('click', scrollToTop);
967
+ updateVisibility();
968
+ }
969
+
970
+ function run() {
971
+ initTheme();
972
+ initSettings();
973
+ initCopyToClipboard();
974
+ initTabs();
975
+ initModals();
976
+ initDropdowns();
977
+ initAccordions();
978
+ initSearch();
979
+ initNavbarMobile();
980
+ initBackToTop();
981
+ }
982
+
983
+ if (document.readyState === 'loading') {
984
+ document.addEventListener('DOMContentLoaded', run);
985
+ } else {
986
+ run();
987
+ }
988
+ })();
989
+ {{RIZZO_SOUND_SCRIPT}}