rizzo-css 0.0.17 → 0.0.18

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 (260) hide show
  1. package/README.md +4 -4
  2. package/bin/rizzo-css.js +151 -103
  3. package/package.json +7 -3
  4. package/scaffold/astro-minimal/.env.example +3 -0
  5. package/scaffold/astro-minimal/README.md +36 -0
  6. package/scaffold/astro-minimal/package.json +13 -0
  7. package/scaffold/astro-minimal/src/layouts/Layout.astro +28 -0
  8. package/scaffold/astro-minimal/src/pages/index.astro +10 -0
  9. package/scaffold/svelte-minimal/.env.example +3 -0
  10. package/scaffold/svelte-minimal/README.md +37 -0
  11. package/scaffold/svelte-minimal/package.json +20 -0
  12. package/scaffold/svelte-minimal/src/app.d.ts +11 -0
  13. package/scaffold/svelte-minimal/src/app.html +15 -0
  14. package/scaffold/svelte-minimal/src/routes/+layout.svelte +1 -0
  15. package/scaffold/svelte-minimal/src/routes/+page.svelte +5 -0
  16. package/scaffold/svelte-minimal/svelte.config.js +10 -0
  17. package/scaffold/svelte-minimal/tsconfig.json +11 -0
  18. package/scaffold/vanilla/README.md +4 -4
  19. package/scaffold/vanilla/components/accordion.html +8 -0
  20. package/scaffold/vanilla/components/alert.html +8 -0
  21. package/scaffold/vanilla/components/avatar.html +8 -0
  22. package/scaffold/vanilla/components/badge.html +8 -0
  23. package/scaffold/vanilla/components/breadcrumb.html +8 -0
  24. package/scaffold/vanilla/components/button.html +8 -0
  25. package/scaffold/vanilla/components/cards.html +8 -0
  26. package/scaffold/vanilla/components/copy-to-clipboard.html +8 -0
  27. package/scaffold/vanilla/components/divider.html +8 -0
  28. package/scaffold/vanilla/components/dropdown.html +8 -0
  29. package/scaffold/vanilla/components/forms.html +8 -0
  30. package/scaffold/vanilla/components/icons.html +8 -0
  31. package/scaffold/vanilla/components/index.html +8 -0
  32. package/scaffold/vanilla/components/modal.html +8 -0
  33. package/scaffold/vanilla/components/navbar.html +8 -0
  34. package/scaffold/vanilla/components/pagination.html +8 -0
  35. package/scaffold/vanilla/components/progress-bar.html +8 -0
  36. package/scaffold/vanilla/components/search.html +8 -0
  37. package/scaffold/vanilla/components/settings.html +8 -0
  38. package/scaffold/vanilla/components/spinner.html +8 -0
  39. package/scaffold/vanilla/components/table.html +8 -0
  40. package/scaffold/vanilla/components/tabs.html +8 -0
  41. package/scaffold/vanilla/components/theme-switcher.html +8 -0
  42. package/scaffold/vanilla/components/toast.html +8 -0
  43. package/scaffold/vanilla/components/tooltip.html +8 -0
  44. package/scaffold/vanilla/index.html +8 -0
  45. package/scaffold/astro-app/README.md +0 -43
  46. package/scaffold/astro-app/package.json +0 -1
  47. package/scaffold/astro-app/src/components/Accordion.astro +0 -178
  48. package/scaffold/astro-app/src/components/Alert.astro +0 -131
  49. package/scaffold/astro-app/src/components/Avatar.astro +0 -59
  50. package/scaffold/astro-app/src/components/Badge.astro +0 -24
  51. package/scaffold/astro-app/src/components/Breadcrumb.astro +0 -61
  52. package/scaffold/astro-app/src/components/Button.astro +0 -3
  53. package/scaffold/astro-app/src/components/Card.astro +0 -18
  54. package/scaffold/astro-app/src/components/Checkbox.astro +0 -38
  55. package/scaffold/astro-app/src/components/CliCommandTabs.astro +0 -90
  56. package/scaffold/astro-app/src/components/CodeBlock.astro +0 -393
  57. package/scaffold/astro-app/src/components/CopyToClipboard.astro +0 -219
  58. package/scaffold/astro-app/src/components/Divider.astro +0 -37
  59. package/scaffold/astro-app/src/components/DocsSidebar.astro +0 -51
  60. package/scaffold/astro-app/src/components/Dropdown.astro +0 -807
  61. package/scaffold/astro-app/src/components/FormGroup.astro +0 -59
  62. package/scaffold/astro-app/src/components/FrameworkSwitcher.astro +0 -72
  63. package/scaffold/astro-app/src/components/Input.astro +0 -59
  64. package/scaffold/astro-app/src/components/Modal.astro +0 -212
  65. package/scaffold/astro-app/src/components/Navbar.astro +0 -623
  66. package/scaffold/astro-app/src/components/PackageInstallTabs.astro +0 -87
  67. package/scaffold/astro-app/src/components/Pagination.astro +0 -240
  68. package/scaffold/astro-app/src/components/ProgressBar.astro +0 -65
  69. package/scaffold/astro-app/src/components/Radio.astro +0 -38
  70. package/scaffold/astro-app/src/components/Search.astro +0 -1259
  71. package/scaffold/astro-app/src/components/Select.astro +0 -49
  72. package/scaffold/astro-app/src/components/Settings.astro +0 -382
  73. package/scaffold/astro-app/src/components/Spinner.astro +0 -30
  74. package/scaffold/astro-app/src/components/Table.astro +0 -181
  75. package/scaffold/astro-app/src/components/Tabs.astro +0 -223
  76. package/scaffold/astro-app/src/components/Textarea.astro +0 -58
  77. package/scaffold/astro-app/src/components/ThemeIcon.astro +0 -50
  78. package/scaffold/astro-app/src/components/ThemeSwitcher.astro +0 -504
  79. package/scaffold/astro-app/src/components/Toast.astro +0 -30
  80. package/scaffold/astro-app/src/components/Tooltip.astro +0 -32
  81. package/scaffold/astro-app/src/components/icons/Brush.astro +0 -10
  82. package/scaffold/astro-app/src/components/icons/Cake.astro +0 -11
  83. package/scaffold/astro-app/src/components/icons/Check.astro +0 -29
  84. package/scaffold/astro-app/src/components/icons/Cherry.astro +0 -11
  85. package/scaffold/astro-app/src/components/icons/ChevronDown.astro +0 -29
  86. package/scaffold/astro-app/src/components/icons/Circle.astro +0 -29
  87. package/scaffold/astro-app/src/components/icons/Close.astro +0 -30
  88. package/scaffold/astro-app/src/components/icons/Cmd.astro +0 -26
  89. package/scaffold/astro-app/src/components/icons/Copy.astro +0 -30
  90. package/scaffold/astro-app/src/components/icons/Eye.astro +0 -30
  91. package/scaffold/astro-app/src/components/icons/Filter.astro +0 -29
  92. package/scaffold/astro-app/src/components/icons/Flame.astro +0 -28
  93. package/scaffold/astro-app/src/components/icons/Flower.astro +0 -11
  94. package/scaffold/astro-app/src/components/icons/Gear.astro +0 -30
  95. package/scaffold/astro-app/src/components/icons/Heart.astro +0 -28
  96. package/scaffold/astro-app/src/components/icons/IceCream.astro +0 -31
  97. package/scaffold/astro-app/src/components/icons/Leaf.astro +0 -29
  98. package/scaffold/astro-app/src/components/icons/Lemon.astro +0 -11
  99. package/scaffold/astro-app/src/components/icons/Moon.astro +0 -29
  100. package/scaffold/astro-app/src/components/icons/Owl.astro +0 -34
  101. package/scaffold/astro-app/src/components/icons/Palette.astro +0 -33
  102. package/scaffold/astro-app/src/components/icons/Rainbow.astro +0 -31
  103. package/scaffold/astro-app/src/components/icons/Search.astro +0 -30
  104. package/scaffold/astro-app/src/components/icons/Shield.astro +0 -28
  105. package/scaffold/astro-app/src/components/icons/Snowflake.astro +0 -34
  106. package/scaffold/astro-app/src/components/icons/Sort.astro +0 -30
  107. package/scaffold/astro-app/src/components/icons/Sun.astro +0 -29
  108. package/scaffold/astro-app/src/components/icons/Sunset.astro +0 -10
  109. package/scaffold/astro-app/src/components/icons/Zap.astro +0 -9
  110. package/scaffold/astro-app/src/components/icons/devicons/Astro.astro +0 -53
  111. package/scaffold/astro-app/src/components/icons/devicons/Bash.astro +0 -34
  112. package/scaffold/astro-app/src/components/icons/devicons/Css3.astro +0 -29
  113. package/scaffold/astro-app/src/components/icons/devicons/Git.astro +0 -24
  114. package/scaffold/astro-app/src/components/icons/devicons/Html5.astro +0 -27
  115. package/scaffold/astro-app/src/components/icons/devicons/Javascript.astro +0 -25
  116. package/scaffold/astro-app/src/components/icons/devicons/Nodejs.astro +0 -47
  117. package/scaffold/astro-app/src/components/icons/devicons/Plaintext.astro +0 -33
  118. package/scaffold/astro-app/src/components/icons/devicons/React.astro +0 -27
  119. package/scaffold/astro-app/src/components/icons/devicons/Svelte.astro +0 -25
  120. package/scaffold/astro-app/src/components/icons/devicons/Vue.astro +0 -26
  121. package/scaffold/astro-app/src/config/frameworks.ts +0 -26
  122. package/scaffold/astro-app/src/config/themes.ts +0 -54
  123. package/scaffold/astro-app/src/layouts/DocsLayout.astro +0 -263
  124. package/scaffold/astro-app/src/layouts/Layout.astro +0 -41
  125. package/scaffold/astro-app/src/pages/components/accordion.astro +0 -172
  126. package/scaffold/astro-app/src/pages/components/alert.astro +0 -250
  127. package/scaffold/astro-app/src/pages/components/avatar.astro +0 -102
  128. package/scaffold/astro-app/src/pages/components/badge.astro +0 -119
  129. package/scaffold/astro-app/src/pages/components/breadcrumb.astro +0 -124
  130. package/scaffold/astro-app/src/pages/components/button.astro +0 -74
  131. package/scaffold/astro-app/src/pages/components/cards.astro +0 -247
  132. package/scaffold/astro-app/src/pages/components/copy-to-clipboard.astro +0 -49
  133. package/scaffold/astro-app/src/pages/components/divider.astro +0 -74
  134. package/scaffold/astro-app/src/pages/components/dropdown.astro +0 -394
  135. package/scaffold/astro-app/src/pages/components/forms.astro +0 -367
  136. package/scaffold/astro-app/src/pages/components/icons.astro +0 -246
  137. package/scaffold/astro-app/src/pages/components/modal.astro +0 -152
  138. package/scaffold/astro-app/src/pages/components/navbar.astro +0 -80
  139. package/scaffold/astro-app/src/pages/components/pagination.astro +0 -126
  140. package/scaffold/astro-app/src/pages/components/progress-bar.astro +0 -94
  141. package/scaffold/astro-app/src/pages/components/search.astro +0 -155
  142. package/scaffold/astro-app/src/pages/components/settings.astro +0 -78
  143. package/scaffold/astro-app/src/pages/components/spinner.astro +0 -81
  144. package/scaffold/astro-app/src/pages/components/table.astro +0 -144
  145. package/scaffold/astro-app/src/pages/components/tabs.astro +0 -220
  146. package/scaffold/astro-app/src/pages/components/theme-switcher.astro +0 -69
  147. package/scaffold/astro-app/src/pages/components/toast.astro +0 -157
  148. package/scaffold/astro-app/src/pages/components/tooltip.astro +0 -209
  149. package/scaffold/astro-app/src/pages/components.astro +0 -290
  150. package/scaffold/astro-app/src/pages/docs/accessibility.astro +0 -9
  151. package/scaffold/astro-app/src/pages/docs/colors.astro +0 -9
  152. package/scaffold/astro-app/src/pages/docs/design-system.astro +0 -9
  153. package/scaffold/astro-app/src/pages/docs/getting-started.astro +0 -9
  154. package/scaffold/astro-app/src/pages/docs/index.astro +0 -15
  155. package/scaffold/astro-app/src/pages/docs/themes/[theme].astro +0 -14
  156. package/scaffold/astro-app/src/pages/docs/theming.astro +0 -10
  157. package/scaffold/astro-app/src/pages/index.astro +0 -24
  158. package/scaffold/svelte-app/README.md +0 -39
  159. package/scaffold/svelte-app/package.json +0 -22
  160. package/scaffold/svelte-app/src/app.d.ts +0 -28
  161. package/scaffold/svelte-app/src/app.html +0 -21
  162. package/scaffold/svelte-app/src/lib/assets/favicon.svg +0 -1
  163. package/scaffold/svelte-app/src/lib/rizzo/Accordion.svelte +0 -128
  164. package/scaffold/svelte-app/src/lib/rizzo/Alert.svelte +0 -85
  165. package/scaffold/svelte-app/src/lib/rizzo/Avatar.svelte +0 -39
  166. package/scaffold/svelte-app/src/lib/rizzo/Badge.svelte +0 -31
  167. package/scaffold/svelte-app/src/lib/rizzo/Breadcrumb.svelte +0 -49
  168. package/scaffold/svelte-app/src/lib/rizzo/Button.svelte +0 -27
  169. package/scaffold/svelte-app/src/lib/rizzo/Card.svelte +0 -17
  170. package/scaffold/svelte-app/src/lib/rizzo/Checkbox.svelte +0 -37
  171. package/scaffold/svelte-app/src/lib/rizzo/CopyToClipboard.svelte +0 -79
  172. package/scaffold/svelte-app/src/lib/rizzo/Divider.svelte +0 -28
  173. package/scaffold/svelte-app/src/lib/rizzo/Dropdown.svelte +0 -254
  174. package/scaffold/svelte-app/src/lib/rizzo/FormGroup.svelte +0 -51
  175. package/scaffold/svelte-app/src/lib/rizzo/Input.svelte +0 -59
  176. package/scaffold/svelte-app/src/lib/rizzo/Modal.svelte +0 -157
  177. package/scaffold/svelte-app/src/lib/rizzo/Pagination.svelte +0 -93
  178. package/scaffold/svelte-app/src/lib/rizzo/ProgressBar.svelte +0 -58
  179. package/scaffold/svelte-app/src/lib/rizzo/Radio.svelte +0 -38
  180. package/scaffold/svelte-app/src/lib/rizzo/Select.svelte +0 -51
  181. package/scaffold/svelte-app/src/lib/rizzo/Spinner.svelte +0 -14
  182. package/scaffold/svelte-app/src/lib/rizzo/Table.svelte +0 -158
  183. package/scaffold/svelte-app/src/lib/rizzo/Tabs.svelte +0 -117
  184. package/scaffold/svelte-app/src/lib/rizzo/Textarea.svelte +0 -59
  185. package/scaffold/svelte-app/src/lib/rizzo/ThemeIcon.svelte +0 -54
  186. package/scaffold/svelte-app/src/lib/rizzo/ThemeSwitcher.svelte +0 -315
  187. package/scaffold/svelte-app/src/lib/rizzo/Toast.svelte +0 -33
  188. package/scaffold/svelte-app/src/lib/rizzo/Tooltip.svelte +0 -19
  189. package/scaffold/svelte-app/src/lib/rizzo/icons/Check.svelte +0 -29
  190. package/scaffold/svelte-app/src/lib/rizzo/icons/ChevronDown.svelte +0 -29
  191. package/scaffold/svelte-app/src/lib/rizzo/icons/Circle.svelte +0 -29
  192. package/scaffold/svelte-app/src/lib/rizzo/icons/Close.svelte +0 -30
  193. package/scaffold/svelte-app/src/lib/rizzo/icons/Cmd.svelte +0 -27
  194. package/scaffold/svelte-app/src/lib/rizzo/icons/Copy.svelte +0 -30
  195. package/scaffold/svelte-app/src/lib/rizzo/icons/Eye.svelte +0 -30
  196. package/scaffold/svelte-app/src/lib/rizzo/icons/Filter.svelte +0 -29
  197. package/scaffold/svelte-app/src/lib/rizzo/icons/Gear.svelte +0 -30
  198. package/scaffold/svelte-app/src/lib/rizzo/icons/IceCream.svelte +0 -31
  199. package/scaffold/svelte-app/src/lib/rizzo/icons/Moon.svelte +0 -29
  200. package/scaffold/svelte-app/src/lib/rizzo/icons/Owl.svelte +0 -34
  201. package/scaffold/svelte-app/src/lib/rizzo/icons/Palette.svelte +0 -33
  202. package/scaffold/svelte-app/src/lib/rizzo/icons/Rainbow.svelte +0 -31
  203. package/scaffold/svelte-app/src/lib/rizzo/icons/Search.svelte +0 -30
  204. package/scaffold/svelte-app/src/lib/rizzo/icons/Snowflake.svelte +0 -34
  205. package/scaffold/svelte-app/src/lib/rizzo/icons/Sort.svelte +0 -30
  206. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Astro.svelte +0 -45
  207. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Bash.svelte +0 -28
  208. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Css3.svelte +0 -23
  209. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Git.svelte +0 -18
  210. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Html5.svelte +0 -21
  211. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Javascript.svelte +0 -19
  212. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Nodejs.svelte +0 -44
  213. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Plaintext.svelte +0 -24
  214. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/React.svelte +0 -21
  215. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/SvelteIcon.svelte +0 -19
  216. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Vue.svelte +0 -20
  217. package/scaffold/svelte-app/src/lib/rizzo/index.ts +0 -35
  218. package/scaffold/svelte-app/src/lib/rizzo-docs/CodeBlock.svelte +0 -239
  219. package/scaffold/svelte-app/src/lib/rizzo-docs/SvelteDocPage.svelte +0 -99
  220. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AccordionDoc.svelte +0 -53
  221. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AlertDoc.svelte +0 -114
  222. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AvatarDoc.svelte +0 -92
  223. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BadgeDoc.svelte +0 -60
  224. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BreadcrumbDoc.svelte +0 -55
  225. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ButtonDoc.svelte +0 -55
  226. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CardsDoc.svelte +0 -173
  227. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComingSoon.svelte +0 -12
  228. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComponentsOverview.svelte +0 -92
  229. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CopyToClipboardDoc.svelte +0 -26
  230. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DividerDoc.svelte +0 -105
  231. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DropdownDoc.svelte +0 -161
  232. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/FormsDoc.svelte +0 -375
  233. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/IconsDoc.svelte +0 -246
  234. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Index.svelte +0 -8
  235. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ModalDoc.svelte +0 -50
  236. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/NavbarDoc.svelte +0 -79
  237. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/PaginationDoc.svelte +0 -44
  238. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ProgressBarDoc.svelte +0 -95
  239. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SearchDoc.svelte +0 -147
  240. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SettingsDoc.svelte +0 -158
  241. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SpinnerDoc.svelte +0 -41
  242. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TableDoc.svelte +0 -116
  243. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TabsDoc.svelte +0 -152
  244. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ThemeSwitcherDoc.svelte +0 -189
  245. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Theming.svelte +0 -6
  246. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ToastDoc.svelte +0 -136
  247. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TooltipDoc.svelte +0 -57
  248. package/scaffold/svelte-app/src/routes/+layout.svelte +0 -10
  249. package/scaffold/svelte-app/src/routes/+page.svelte +0 -31
  250. package/scaffold/svelte-app/src/routes/components/+page.svelte +0 -4
  251. package/scaffold/svelte-app/src/routes/components/[slug]/+page.svelte +0 -7
  252. package/scaffold/svelte-app/static/robots.txt +0 -3
  253. package/scaffold/svelte-app/svelte.config.js +0 -13
  254. package/scaffold/svelte-app/tsconfig.json +0 -21
  255. package/scaffold/svelte-app/vite.config.ts +0 -6
  256. /package/scaffold/{astro-app → astro-minimal}/astro.config.mjs +0 -0
  257. /package/scaffold/{astro-app → astro-minimal}/public/.gitkeep +0 -0
  258. /package/scaffold/{astro-app → astro-minimal}/public/favicon.svg +0 -0
  259. /package/scaffold/{astro-app → astro-minimal}/tsconfig.json +0 -0
  260. /package/scaffold/{svelte-app → svelte-minimal}/static/.gitkeep +0 -0
@@ -1,807 +0,0 @@
1
- ---
2
- import ChevronDown from './icons/ChevronDown.astro';
3
-
4
- interface MenuItem {
5
- label: string;
6
- value?: string;
7
- href?: string;
8
- onClick?: string;
9
- disabled?: boolean;
10
- separator?: boolean;
11
- submenu?: MenuItem[];
12
- }
13
-
14
- interface Props {
15
- trigger: string;
16
- items: MenuItem[];
17
- id?: string;
18
- class?: string;
19
- position?: 'left' | 'right';
20
- align?: 'start' | 'end';
21
- }
22
-
23
- const {
24
- trigger,
25
- items,
26
- id,
27
- class: className = '',
28
- position = 'left',
29
- align = 'start',
30
- } = Astro.props;
31
-
32
- const dropdownId = id || `dropdown-${Math.random().toString(36).substr(2, 9)}`;
33
- const triggerId = `${dropdownId}-trigger`;
34
- const menuId = `${dropdownId}-menu`;
35
- ---
36
-
37
- <div class={`dropdown ${className}`.trim()} data-dropdown={dropdownId}>
38
- <button
39
- type="button"
40
- class="dropdown__trigger"
41
- id={triggerId}
42
- aria-expanded="false"
43
- aria-haspopup="true"
44
- aria-controls={menuId}
45
- aria-label={trigger}
46
- >
47
- <span class="dropdown__trigger-text">{trigger}</span>
48
- <ChevronDown class="dropdown__icon" width={16} height={16} />
49
- </button>
50
-
51
- <div
52
- class={`dropdown__menu dropdown__menu--${position} dropdown__menu--${align}`}
53
- id={menuId}
54
- role="menu"
55
- aria-labelledby={triggerId}
56
- aria-label={`${trigger} menu`}
57
- aria-orientation="vertical"
58
- aria-hidden="true"
59
- tabindex="-1"
60
- >
61
- {items.map((item, index) => {
62
- if (item.separator) {
63
- return <div class="dropdown__separator" role="separator" />;
64
- }
65
-
66
- const itemId = `${dropdownId}-item-${index}`;
67
- const hasSubmenu = item.submenu && item.submenu.length > 0;
68
- const submenuId = hasSubmenu ? `${dropdownId}-submenu-${index}` : undefined;
69
-
70
- if (item.href) {
71
- return (
72
- <div class={`dropdown__item-wrapper ${hasSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
73
- {hasSubmenu ? (
74
- <div
75
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
76
- role="menuitem"
77
- id={itemId}
78
- tabindex="-1"
79
- aria-label={item.label}
80
- aria-disabled={item.disabled ? 'true' : 'false'}
81
- aria-expanded="false"
82
- aria-haspopup="true"
83
- aria-controls={submenuId}
84
- data-dropdown-has-submenu="true"
85
- >
86
- <span>{item.label}</span>
87
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
88
- </div>
89
- ) : (
90
- <div
91
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''}`}
92
- role="menuitem"
93
- id={itemId}
94
- tabindex="-1"
95
- aria-label={item.label}
96
- aria-disabled={item.disabled ? 'true' : 'false'}
97
- data-dropdown-href={item.href}
98
- >
99
- <span>{item.label}</span>
100
- </div>
101
- )}
102
- {hasSubmenu && item.submenu && (
103
- <div
104
- class="dropdown__submenu"
105
- id={submenuId}
106
- role="menu"
107
- aria-label={`${item.label} submenu`}
108
- aria-hidden="true"
109
- >
110
- {item.submenu.map((subItem, subIndex) => {
111
- if (subItem.separator) {
112
- return <div class="dropdown__separator" role="separator" />;
113
- }
114
-
115
- const subItemId = `${submenuId}-item-${subIndex}`;
116
- const hasNestedSubmenu = subItem.submenu && subItem.submenu.length > 0;
117
- const nestedSubmenuId = hasNestedSubmenu ? `${subItemId}-submenu` : undefined;
118
-
119
- if (subItem.href) {
120
- return (
121
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
122
- {hasNestedSubmenu ? (
123
- <div
124
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
125
- role="menuitem"
126
- id={subItemId}
127
- tabindex="-1"
128
- aria-label={subItem.label}
129
- aria-disabled={subItem.disabled ? 'true' : 'false'}
130
- aria-expanded="false"
131
- aria-haspopup="true"
132
- aria-controls={nestedSubmenuId}
133
- data-dropdown-has-submenu="true"
134
- >
135
- <span>{subItem.label}</span>
136
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
137
- </div>
138
- ) : (
139
- <div
140
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''}`}
141
- role="menuitem"
142
- id={subItemId}
143
- tabindex="-1"
144
- aria-label={subItem.label}
145
- aria-disabled={subItem.disabled ? 'true' : 'false'}
146
- data-dropdown-href={subItem.href}
147
- >
148
- <span>{subItem.label}</span>
149
- </div>
150
- )}
151
- {hasNestedSubmenu && subItem.submenu && (
152
- <div
153
- class="dropdown__submenu"
154
- id={nestedSubmenuId}
155
- role="menu"
156
- aria-label={`${subItem.label} submenu`}
157
- aria-hidden="true"
158
- >
159
- {subItem.submenu.map((nestedItem, nestedIndex) => {
160
- if (nestedItem.separator) {
161
- return <div class="dropdown__separator" role="separator" />;
162
- }
163
-
164
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
165
-
166
- if (nestedItem.href) {
167
- return (
168
- <div
169
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
170
- role="menuitem"
171
- id={nestedItemId}
172
- tabindex="-1"
173
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
174
- data-dropdown-href={nestedItem.href}
175
- >
176
- <span>{nestedItem.label}</span>
177
- </div>
178
- );
179
- }
180
-
181
- return (
182
- <div
183
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
184
- role="menuitem"
185
- id={nestedItemId}
186
- tabindex="-1"
187
- aria-label={nestedItem.label}
188
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
189
- data-dropdown-value={nestedItem.value || nestedItem.label}
190
- data-dropdown-onclick={nestedItem.onClick || ''}
191
- >
192
- <span>{nestedItem.label}</span>
193
- </div>
194
- );
195
- })}
196
- </div>
197
- )}
198
- </div>
199
- );
200
- }
201
-
202
- return (
203
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
204
- <div
205
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} ${hasNestedSubmenu ? 'dropdown__item--has-submenu' : ''}`}
206
- role="menuitem"
207
- id={subItemId}
208
- tabindex="-1"
209
- aria-label={subItem.label}
210
- aria-disabled={subItem.disabled ? 'true' : 'false'}
211
- aria-expanded={hasNestedSubmenu ? 'false' : undefined}
212
- aria-haspopup={hasNestedSubmenu ? 'true' : undefined}
213
- aria-controls={nestedSubmenuId}
214
- data-dropdown-value={subItem.value || subItem.label}
215
- data-dropdown-onclick={subItem.onClick || ''}
216
- data-dropdown-has-submenu={hasNestedSubmenu ? 'true' : undefined}
217
- >
218
- <span>{subItem.label}</span>
219
- {hasNestedSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
220
- </div>
221
- {hasNestedSubmenu && subItem.submenu && (
222
- <div
223
- class="dropdown__submenu"
224
- id={nestedSubmenuId}
225
- role="menu"
226
- aria-label={`${subItem.label} submenu`}
227
- aria-hidden="true"
228
- >
229
- {subItem.submenu.map((nestedItem, nestedIndex) => {
230
- if (nestedItem.separator) {
231
- return <div class="dropdown__separator" role="separator" />;
232
- }
233
-
234
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
235
-
236
- if (nestedItem.href) {
237
- return (
238
- <div
239
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
240
- role="menuitem"
241
- id={nestedItemId}
242
- tabindex="-1"
243
- aria-label={nestedItem.label}
244
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
245
- data-dropdown-href={nestedItem.href}
246
- >
247
- <span>{nestedItem.label}</span>
248
- </div>
249
- );
250
- }
251
-
252
- return (
253
- <div
254
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
255
- role="menuitem"
256
- id={nestedItemId}
257
- tabindex="-1"
258
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
259
- data-dropdown-value={nestedItem.value || nestedItem.label}
260
- data-dropdown-onclick={nestedItem.onClick || ''}
261
- >
262
- <span>{nestedItem.label}</span>
263
- </div>
264
- );
265
- })}
266
- </div>
267
- )}
268
- </div>
269
- );
270
- })}
271
- </div>
272
- )}
273
- </div>
274
- );
275
- }
276
-
277
- return (
278
- <div class={`dropdown__item-wrapper ${hasSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
279
- <div
280
- class={`dropdown__item ${item.disabled ? 'dropdown__item--disabled' : ''} ${hasSubmenu ? 'dropdown__item--has-submenu' : ''}`}
281
- role="menuitem"
282
- id={itemId}
283
- tabindex="-1"
284
- aria-disabled={item.disabled ? 'true' : 'false'}
285
- aria-expanded={hasSubmenu ? 'false' : undefined}
286
- aria-haspopup={hasSubmenu ? 'true' : undefined}
287
- aria-controls={submenuId}
288
- data-dropdown-value={item.value || item.label}
289
- data-dropdown-onclick={item.onClick || ''}
290
- data-dropdown-has-submenu={hasSubmenu ? 'true' : undefined}
291
- >
292
- <span>{item.label}</span>
293
- {hasSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
294
- </div>
295
- {hasSubmenu && item.submenu && (
296
- <div
297
- class="dropdown__submenu"
298
- id={submenuId}
299
- role="menu"
300
- aria-label={`${item.label} submenu`}
301
- aria-hidden="true"
302
- >
303
- {item.submenu.map((subItem, subIndex) => {
304
- if (subItem.separator) {
305
- return <div class="dropdown__separator" role="separator" />;
306
- }
307
-
308
- const subItemId = `${submenuId}-item-${subIndex}`;
309
- const hasNestedSubmenu = subItem.submenu && subItem.submenu.length > 0;
310
- const nestedSubmenuId = hasNestedSubmenu ? `${subItemId}-submenu` : undefined;
311
-
312
- if (subItem.href) {
313
- return (
314
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
315
- {hasNestedSubmenu ? (
316
- <div
317
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} dropdown__item--has-submenu`}
318
- role="menuitem"
319
- id={subItemId}
320
- tabindex="-1"
321
- aria-disabled={subItem.disabled ? 'true' : 'false'}
322
- aria-expanded="false"
323
- aria-haspopup="true"
324
- aria-controls={nestedSubmenuId}
325
- data-dropdown-has-submenu="true"
326
- >
327
- <span>{subItem.label}</span>
328
- <ChevronDown class="dropdown__item-arrow" width={12} height={12} />
329
- </div>
330
- ) : (
331
- <div
332
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''}`}
333
- role="menuitem"
334
- id={subItemId}
335
- tabindex="-1"
336
- aria-disabled={subItem.disabled ? 'true' : 'false'}
337
- data-dropdown-href={subItem.href}
338
- >
339
- <span>{subItem.label}</span>
340
- </div>
341
- )}
342
- {hasNestedSubmenu && subItem.submenu && (
343
- <div
344
- class="dropdown__submenu"
345
- id={nestedSubmenuId}
346
- role="menu"
347
- aria-label={`${subItem.label} submenu`}
348
- aria-hidden="true"
349
- >
350
- {subItem.submenu.map((nestedItem, nestedIndex) => {
351
- if (nestedItem.separator) {
352
- return <div class="dropdown__separator" role="separator" />;
353
- }
354
-
355
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
356
-
357
- if (nestedItem.href) {
358
- return (
359
- <div
360
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
361
- role="menuitem"
362
- id={nestedItemId}
363
- tabindex="-1"
364
- aria-label={nestedItem.label}
365
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
366
- data-dropdown-href={nestedItem.href}
367
- >
368
- <span>{nestedItem.label}</span>
369
- </div>
370
- );
371
- }
372
-
373
- return (
374
- <div
375
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
376
- role="menuitem"
377
- id={nestedItemId}
378
- tabindex="-1"
379
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
380
- data-dropdown-value={nestedItem.value || nestedItem.label}
381
- data-dropdown-onclick={nestedItem.onClick || ''}
382
- >
383
- <span>{nestedItem.label}</span>
384
- </div>
385
- );
386
- })}
387
- </div>
388
- )}
389
- </div>
390
- );
391
- }
392
-
393
- return (
394
- <div class={`dropdown__item-wrapper ${hasNestedSubmenu ? 'dropdown__item-wrapper--has-submenu' : ''}`}>
395
- <div
396
- class={`dropdown__item dropdown__submenu-item ${subItem.disabled ? 'dropdown__item--disabled' : ''} ${hasNestedSubmenu ? 'dropdown__item--has-submenu' : ''}`}
397
- role="menuitem"
398
- id={subItemId}
399
- tabindex="-1"
400
- aria-label={subItem.label}
401
- aria-disabled={subItem.disabled ? 'true' : 'false'}
402
- aria-expanded={hasNestedSubmenu ? 'false' : undefined}
403
- aria-haspopup={hasNestedSubmenu ? 'true' : undefined}
404
- aria-controls={nestedSubmenuId}
405
- data-dropdown-value={subItem.value || subItem.label}
406
- data-dropdown-onclick={subItem.onClick || ''}
407
- data-dropdown-has-submenu={hasNestedSubmenu ? 'true' : undefined}
408
- >
409
- <span>{subItem.label}</span>
410
- {hasNestedSubmenu && <ChevronDown class="dropdown__item-arrow" width={12} height={12} />}
411
- </div>
412
- {hasNestedSubmenu && subItem.submenu && (
413
- <div
414
- class="dropdown__submenu"
415
- id={nestedSubmenuId}
416
- role="menu"
417
- aria-label={`${subItem.label} submenu`}
418
- aria-hidden="true"
419
- >
420
- {subItem.submenu.map((nestedItem, nestedIndex) => {
421
- if (nestedItem.separator) {
422
- return <div class="dropdown__separator" role="separator" />;
423
- }
424
-
425
- const nestedItemId = `${nestedSubmenuId}-item-${nestedIndex}`;
426
-
427
- if (nestedItem.href) {
428
- return (
429
- <div
430
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
431
- role="menuitem"
432
- id={nestedItemId}
433
- tabindex="-1"
434
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
435
- data-dropdown-href={nestedItem.href}
436
- >
437
- <span>{nestedItem.label}</span>
438
- </div>
439
- );
440
- }
441
-
442
- return (
443
- <div
444
- class={`dropdown__item dropdown__submenu-item ${nestedItem.disabled ? 'dropdown__item--disabled' : ''}`}
445
- role="menuitem"
446
- id={nestedItemId}
447
- tabindex="-1"
448
- aria-disabled={nestedItem.disabled ? 'true' : 'false'}
449
- data-dropdown-value={nestedItem.value || nestedItem.label}
450
- data-dropdown-onclick={nestedItem.onClick || ''}
451
- >
452
- <span>{nestedItem.label}</span>
453
- </div>
454
- );
455
- })}
456
- </div>
457
- )}
458
- </div>
459
- );
460
- })}
461
- </div>
462
- )}
463
- </div>
464
- );
465
- })}
466
- </div>
467
- </div>
468
-
469
- <script is:inline>
470
- (function initDropdown() {
471
- const init = () => {
472
- const dropdowns = document.querySelectorAll('[data-dropdown]');
473
-
474
- dropdowns.forEach((dropdown) => {
475
- const dropdownId = dropdown.getAttribute('data-dropdown');
476
- if (!dropdownId) return;
477
-
478
- if (dropdown.hasAttribute('data-dropdown-initialized')) return;
479
- dropdown.setAttribute('data-dropdown-initialized', 'true');
480
-
481
- const trigger = dropdown.querySelector('.dropdown__trigger');
482
- const menu = dropdown.querySelector('.dropdown__menu');
483
- const items = dropdown.querySelectorAll('.dropdown__item');
484
- const itemWrappers = dropdown.querySelectorAll('.dropdown__item-wrapper');
485
-
486
- if (!trigger || !menu) return;
487
-
488
- let currentIndex = -1;
489
-
490
- const getVisibleItems = () => {
491
- return Array.from(items).filter(item => {
492
- const isDisabled = item.getAttribute('aria-disabled') === 'true';
493
- const wrapper = item.closest('.dropdown__item-wrapper');
494
- const submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
495
- // Don't include submenu items in main navigation
496
- if (submenu && item.closest('.dropdown__submenu')) {
497
- return false;
498
- }
499
- return !isDisabled && (item.offsetParent !== null || menu.classList.contains('dropdown__menu--open'));
500
- });
501
- };
502
-
503
- // Close all submenus except the one being opened
504
- const closeAllSubmenus = (exceptWrapper = null) => {
505
- itemWrappers.forEach((wrapper) => {
506
- if (wrapper === exceptWrapper) return; // Don't close the one we're opening
507
- const submenu = wrapper.querySelector('.dropdown__submenu');
508
- const item = wrapper.querySelector('.dropdown__item');
509
- if (submenu && item) {
510
- submenu.classList.remove('dropdown__submenu--open');
511
- submenu.setAttribute('aria-hidden', 'true');
512
- item.setAttribute('aria-expanded', 'false');
513
- }
514
- });
515
- };
516
-
517
- // Toggle submenu
518
- const toggleSubmenu = (wrapper, open) => {
519
- const submenu = wrapper.querySelector('.dropdown__submenu');
520
- const item = wrapper.querySelector('.dropdown__item');
521
- if (!submenu || !item) return;
522
-
523
- const isOpen = open !== undefined ? open : submenu.classList.contains('dropdown__submenu--open');
524
- const willBeOpen = !isOpen;
525
-
526
- // Close other submenus at the same level, but keep parent submenus open
527
- if (willBeOpen) {
528
- // Find all submenus at the same level (siblings of the current wrapper's parent)
529
- const parentSubmenu = wrapper.closest('.dropdown__submenu');
530
- if (parentSubmenu) {
531
- // Close siblings within the same parent submenu
532
- const siblingWrappers = parentSubmenu.querySelectorAll('.dropdown__item-wrapper');
533
- siblingWrappers.forEach((siblingWrapper) => {
534
- if (siblingWrapper === wrapper) return; // Don't close the one we're opening
535
- const siblingSubmenu = siblingWrapper.querySelector('.dropdown__submenu');
536
- const siblingItem = siblingWrapper.querySelector('.dropdown__item');
537
- if (siblingSubmenu && siblingItem) {
538
- siblingSubmenu.classList.remove('dropdown__submenu--open');
539
- siblingSubmenu.setAttribute('aria-hidden', 'true');
540
- siblingItem.setAttribute('aria-expanded', 'false');
541
- }
542
- });
543
- } else {
544
- // Main menu level - close all other main menu submenus
545
- closeAllSubmenus(wrapper);
546
- }
547
- }
548
-
549
- // Toggle the open class
550
- if (willBeOpen) {
551
- submenu.classList.add('dropdown__submenu--open');
552
- submenu.setAttribute('aria-hidden', 'false');
553
- item.setAttribute('aria-expanded', 'true');
554
- } else {
555
- submenu.classList.remove('dropdown__submenu--open');
556
- submenu.setAttribute('aria-hidden', 'true');
557
- item.setAttribute('aria-expanded', 'false');
558
- }
559
-
560
- // Position submenu - now positioned directly under the item
561
- if (willBeOpen) {
562
- // Submenu is positioned directly under via CSS (top: 100%, left: 0, right: 0)
563
- // No JavaScript positioning needed
564
- } else {
565
- // Reset any inline styles when closing
566
- submenu.style.left = '';
567
- submenu.style.right = '';
568
- submenu.style.top = '';
569
- submenu.style.marginLeft = '';
570
- submenu.style.marginRight = '';
571
- submenu.style.marginTop = '';
572
- submenu.style.maxWidth = '';
573
- submenu.style.width = '';
574
- }
575
- };
576
-
577
- const toggleMenu = (open) => {
578
- const isOpen = open !== undefined ? open : menu.classList.contains('dropdown__menu--open');
579
- const willBeOpen = !isOpen;
580
-
581
- menu.classList.toggle('dropdown__menu--open', willBeOpen);
582
- trigger.setAttribute('aria-expanded', willBeOpen.toString());
583
- menu.setAttribute('aria-hidden', (!willBeOpen).toString());
584
-
585
- items.forEach((item) => {
586
- item.setAttribute('tabindex', willBeOpen ? '0' : '-1');
587
- });
588
-
589
- if (!willBeOpen) {
590
- trigger.focus();
591
- currentIndex = -1;
592
- closeAllSubmenus();
593
- } else {
594
- const visibleItems = getVisibleItems();
595
- if (visibleItems.length > 0) {
596
- currentIndex = 0;
597
- setTimeout(() => visibleItems[0].focus(), 0);
598
- }
599
- }
600
- };
601
-
602
- const closeMenu = () => {
603
- menu.classList.remove('dropdown__menu--open');
604
- trigger.setAttribute('aria-expanded', 'false');
605
- menu.setAttribute('aria-hidden', 'true');
606
- items.forEach((item) => {
607
- item.setAttribute('tabindex', '-1');
608
- });
609
- closeAllSubmenus();
610
- currentIndex = -1;
611
- };
612
-
613
- // Handle outside click
614
- const handleOutsideClick = (e) => {
615
- if (e && e.target && !dropdown.contains(e.target)) {
616
- closeMenu();
617
- document.removeEventListener('click', handleOutsideClick);
618
- }
619
- };
620
-
621
- const wrappedToggleMenu = (open) => {
622
- const wasOpen = menu.classList.contains('dropdown__menu--open');
623
- toggleMenu(open);
624
- const isNowOpen = menu.classList.contains('dropdown__menu--open');
625
-
626
- if (isNowOpen && !wasOpen) {
627
- setTimeout(() => document.addEventListener('click', handleOutsideClick), 0);
628
- } else if (!isNowOpen && wasOpen) {
629
- document.removeEventListener('click', handleOutsideClick);
630
- }
631
- };
632
-
633
- // Trigger click
634
- trigger.addEventListener('click', () => wrappedToggleMenu(undefined));
635
-
636
- // Menu item click handler - handles all clicks including nested submenus
637
- menu.addEventListener('click', (e) => {
638
- const target = e.target;
639
- // Find the item - could be the button/a itself, or a child element (span, arrow icon, etc.)
640
- const item = target.closest('.dropdown__item');
641
- if (!item) return;
642
-
643
- // Stop propagation to prevent outside click handler from firing
644
- e.stopPropagation();
645
-
646
- const isDisabled = item.getAttribute('aria-disabled') === 'true';
647
- if (isDisabled) {
648
- e.preventDefault();
649
- return;
650
- }
651
-
652
- // FIRST: Check if item has submenu by finding wrapper and checking for submenu
653
- // This must be checked FIRST, regardless of whether item is in a submenu or not
654
- const wrapper = item.closest('.dropdown__item-wrapper');
655
-
656
- if (wrapper) {
657
- const submenu = wrapper.querySelector('.dropdown__submenu');
658
- if (submenu) {
659
- // Item has submenu - toggle it (works for main menu items AND nested submenu items)
660
- e.preventDefault();
661
- e.stopImmediatePropagation();
662
- toggleSubmenu(wrapper, undefined);
663
- return;
664
- }
665
- }
666
-
667
- // Item does NOT have a submenu - handle as regular item
668
- const href = item.getAttribute('data-dropdown-href');
669
- if (href) {
670
- window.location.href = href;
671
- }
672
- const onClick = item.getAttribute('data-dropdown-onclick');
673
- if (onClick && typeof window[onClick] === 'function') {
674
- const value = item.getAttribute('data-dropdown-value') || item.textContent?.trim() || '';
675
- window[onClick](value);
676
- }
677
-
678
- // Close menu for final items (items without submenus)
679
- closeMenu();
680
- });
681
-
682
- // Keyboard navigation on trigger
683
- trigger.addEventListener('keydown', (e) => {
684
- if (e && 'key' in e) {
685
- const keyEvent = e;
686
- if (keyEvent.key === 'Enter' || keyEvent.key === ' ') {
687
- keyEvent.preventDefault();
688
- wrappedToggleMenu(undefined);
689
- } else if (keyEvent.key === 'ArrowDown') {
690
- keyEvent.preventDefault();
691
- const visibleItems = getVisibleItems();
692
- if (visibleItems.length > 0) {
693
- currentIndex = 0;
694
- wrappedToggleMenu(true);
695
- setTimeout(() => visibleItems[0].focus(), 0);
696
- }
697
- } else if (keyEvent.key === 'ArrowUp') {
698
- keyEvent.preventDefault();
699
- const visibleItems = getVisibleItems();
700
- if (visibleItems.length > 0) {
701
- currentIndex = visibleItems.length - 1;
702
- wrappedToggleMenu(true);
703
- setTimeout(() => visibleItems[currentIndex].focus(), 0);
704
- }
705
- } else if (keyEvent.key === 'Escape') {
706
- keyEvent.preventDefault();
707
- closeMenu();
708
- }
709
- }
710
- });
711
-
712
- // Keyboard navigation in menu
713
- menu.addEventListener('keydown', (e) => {
714
- if (e && 'key' in e) {
715
- const keyEvent = e;
716
- const visibleItems = getVisibleItems();
717
-
718
- if (keyEvent.key === 'Escape') {
719
- keyEvent.preventDefault();
720
- closeMenu();
721
- trigger.focus();
722
- } else if (keyEvent.key === 'ArrowDown') {
723
- keyEvent.preventDefault();
724
- currentIndex = (currentIndex + 1) % visibleItems.length;
725
- visibleItems[currentIndex].focus();
726
- } else if (keyEvent.key === 'ArrowUp') {
727
- keyEvent.preventDefault();
728
- currentIndex = currentIndex <= 0 ? visibleItems.length - 1 : currentIndex - 1;
729
- visibleItems[currentIndex].focus();
730
- } else if (keyEvent.key === 'Home') {
731
- keyEvent.preventDefault();
732
- currentIndex = 0;
733
- visibleItems[0].focus();
734
- } else if (keyEvent.key === 'End') {
735
- keyEvent.preventDefault();
736
- currentIndex = visibleItems.length - 1;
737
- visibleItems[currentIndex].focus();
738
- } else if (keyEvent.key === 'ArrowRight') {
739
- // Open submenu if available
740
- const target = keyEvent.target;
741
- if (target && target instanceof HTMLElement) {
742
- const wrapper = target.closest('.dropdown__item-wrapper');
743
- if (wrapper) {
744
- const submenu = wrapper.querySelector('.dropdown__submenu');
745
- if (submenu) {
746
- keyEvent.preventDefault();
747
- toggleSubmenu(wrapper, true);
748
- const firstSubItem = submenu.querySelector('.dropdown__item');
749
- if (firstSubItem) {
750
- setTimeout(() => firstSubItem.focus(), 0);
751
- }
752
- }
753
- }
754
- }
755
- } else if (keyEvent.key === 'ArrowLeft') {
756
- // Close submenu if in one
757
- const target = keyEvent.target;
758
- if (target && target instanceof HTMLElement) {
759
- const submenu = target.closest('.dropdown__submenu');
760
- if (submenu) {
761
- keyEvent.preventDefault();
762
- const wrapper = submenu.closest('.dropdown__item-wrapper');
763
- if (wrapper) {
764
- toggleSubmenu(wrapper, false);
765
- const parentItem = wrapper.querySelector('.dropdown__item');
766
- if (parentItem) {
767
- parentItem.focus();
768
- }
769
- }
770
- }
771
- }
772
- } else if (keyEvent.key === 'Enter' || keyEvent.key === ' ') {
773
- keyEvent.preventDefault();
774
- const target = keyEvent.target;
775
- if (target && target instanceof HTMLElement) {
776
- const isDisabled = target.getAttribute('aria-disabled') === 'true';
777
- if (!isDisabled) {
778
- // Check if item has submenu
779
- const wrapper = target.closest('.dropdown__item-wrapper');
780
- const submenu = wrapper ? wrapper.querySelector('.dropdown__submenu') : null;
781
- if (submenu) {
782
- toggleSubmenu(wrapper, undefined);
783
- } else {
784
- if (target.tagName === 'A') {
785
- target.click();
786
- } else if (target.tagName === 'BUTTON') {
787
- target.click();
788
- }
789
- closeMenu();
790
- }
791
- }
792
- }
793
- } else if (keyEvent.key === 'Tab') {
794
- closeMenu();
795
- }
796
- }
797
- });
798
- });
799
- };
800
-
801
- if (document.readyState === 'loading') {
802
- document.addEventListener('DOMContentLoaded', init);
803
- } else {
804
- init();
805
- }
806
- })();
807
- </script>