@furystack/shades-common-components 11.0.0 → 12.0.1

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 (768) hide show
  1. package/CHANGELOG.md +443 -0
  2. package/esm/components/accordion/accordion-item.d.ts +31 -0
  3. package/esm/components/accordion/accordion-item.d.ts.map +1 -0
  4. package/esm/components/accordion/accordion-item.js +147 -0
  5. package/esm/components/accordion/accordion-item.js.map +1 -0
  6. package/esm/components/accordion/accordion.d.ts +27 -0
  7. package/esm/components/accordion/accordion.d.ts.map +1 -0
  8. package/esm/components/accordion/accordion.js +39 -0
  9. package/esm/components/accordion/accordion.js.map +1 -0
  10. package/esm/components/accordion/accordion.spec.d.ts +2 -0
  11. package/esm/components/accordion/accordion.spec.d.ts.map +1 -0
  12. package/esm/components/accordion/accordion.spec.js +284 -0
  13. package/esm/components/accordion/accordion.spec.js.map +1 -0
  14. package/esm/components/accordion/index.d.ts +3 -0
  15. package/esm/components/accordion/index.d.ts.map +1 -0
  16. package/esm/components/accordion/index.js +3 -0
  17. package/esm/components/accordion/index.js.map +1 -0
  18. package/esm/components/alert.d.ts +21 -0
  19. package/esm/components/alert.d.ts.map +1 -0
  20. package/esm/components/alert.js +131 -0
  21. package/esm/components/alert.js.map +1 -0
  22. package/esm/components/alert.spec.d.ts +2 -0
  23. package/esm/components/alert.spec.d.ts.map +1 -0
  24. package/esm/components/alert.spec.js +177 -0
  25. package/esm/components/alert.spec.js.map +1 -0
  26. package/esm/components/app-bar-link.d.ts +22 -2
  27. package/esm/components/app-bar-link.d.ts.map +1 -1
  28. package/esm/components/app-bar-link.js +20 -7
  29. package/esm/components/app-bar-link.js.map +1 -1
  30. package/esm/components/app-bar-link.spec.js +22 -19
  31. package/esm/components/app-bar-link.spec.js.map +1 -1
  32. package/esm/components/app-bar.d.ts +2 -0
  33. package/esm/components/app-bar.d.ts.map +1 -1
  34. package/esm/components/app-bar.js +16 -11
  35. package/esm/components/app-bar.js.map +1 -1
  36. package/esm/components/app-bar.spec.js +67 -52
  37. package/esm/components/app-bar.spec.js.map +1 -1
  38. package/esm/components/avatar.d.ts +2 -0
  39. package/esm/components/avatar.d.ts.map +1 -1
  40. package/esm/components/avatar.js +40 -37
  41. package/esm/components/avatar.js.map +1 -1
  42. package/esm/components/badge.d.ts +35 -0
  43. package/esm/components/badge.d.ts.map +1 -0
  44. package/esm/components/badge.js +68 -0
  45. package/esm/components/badge.js.map +1 -0
  46. package/esm/components/badge.spec.d.ts +2 -0
  47. package/esm/components/badge.spec.d.ts.map +1 -0
  48. package/esm/components/badge.spec.js +157 -0
  49. package/esm/components/badge.spec.js.map +1 -0
  50. package/esm/components/breadcrumb.d.ts +103 -0
  51. package/esm/components/breadcrumb.d.ts.map +1 -0
  52. package/esm/components/breadcrumb.js +121 -0
  53. package/esm/components/breadcrumb.js.map +1 -0
  54. package/esm/components/breadcrumb.spec.d.ts +2 -0
  55. package/esm/components/breadcrumb.spec.d.ts.map +1 -0
  56. package/esm/components/breadcrumb.spec.js +251 -0
  57. package/esm/components/breadcrumb.spec.js.map +1 -0
  58. package/esm/components/button-group.d.ts +85 -0
  59. package/esm/components/button-group.d.ts.map +1 -0
  60. package/esm/components/button-group.js +290 -0
  61. package/esm/components/button-group.js.map +1 -0
  62. package/esm/components/button-group.spec.d.ts +2 -0
  63. package/esm/components/button-group.spec.d.ts.map +1 -0
  64. package/esm/components/button-group.spec.js +502 -0
  65. package/esm/components/button-group.spec.js.map +1 -0
  66. package/esm/components/button.d.ts +44 -2
  67. package/esm/components/button.d.ts.map +1 -1
  68. package/esm/components/button.js +82 -73
  69. package/esm/components/button.js.map +1 -1
  70. package/esm/components/button.spec.js +205 -50
  71. package/esm/components/button.spec.js.map +1 -1
  72. package/esm/components/card.d.ts +117 -0
  73. package/esm/components/card.d.ts.map +1 -0
  74. package/esm/components/card.js +181 -0
  75. package/esm/components/card.js.map +1 -0
  76. package/esm/components/card.spec.d.ts +2 -0
  77. package/esm/components/card.spec.d.ts.map +1 -0
  78. package/esm/components/card.spec.js +278 -0
  79. package/esm/components/card.spec.js.map +1 -0
  80. package/esm/components/carousel.d.ts +50 -0
  81. package/esm/components/carousel.d.ts.map +1 -0
  82. package/esm/components/carousel.js +263 -0
  83. package/esm/components/carousel.js.map +1 -0
  84. package/esm/components/carousel.spec.d.ts +2 -0
  85. package/esm/components/carousel.spec.d.ts.map +1 -0
  86. package/esm/components/carousel.spec.js +677 -0
  87. package/esm/components/carousel.spec.js.map +1 -0
  88. package/esm/components/chip.d.ts +23 -0
  89. package/esm/components/chip.d.ts.map +1 -0
  90. package/esm/components/chip.js +139 -0
  91. package/esm/components/chip.js.map +1 -0
  92. package/esm/components/chip.spec.d.ts +2 -0
  93. package/esm/components/chip.spec.d.ts.map +1 -0
  94. package/esm/components/chip.spec.js +142 -0
  95. package/esm/components/chip.spec.js.map +1 -0
  96. package/esm/components/circular-progress.d.ts +37 -0
  97. package/esm/components/circular-progress.d.ts.map +1 -0
  98. package/esm/components/circular-progress.js +84 -0
  99. package/esm/components/circular-progress.js.map +1 -0
  100. package/esm/components/circular-progress.spec.d.ts +2 -0
  101. package/esm/components/circular-progress.spec.d.ts.map +1 -0
  102. package/esm/components/circular-progress.spec.js +228 -0
  103. package/esm/components/circular-progress.spec.js.map +1 -0
  104. package/esm/components/command-palette/command-palette-input.d.ts +3 -0
  105. package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
  106. package/esm/components/command-palette/command-palette-input.js +17 -9
  107. package/esm/components/command-palette/command-palette-input.js.map +1 -1
  108. package/esm/components/command-palette/command-palette-input.spec.js +172 -161
  109. package/esm/components/command-palette/command-palette-input.spec.js.map +1 -1
  110. package/esm/components/command-palette/command-palette-manager.spec.js +130 -114
  111. package/esm/components/command-palette/command-palette-manager.spec.js.map +1 -1
  112. package/esm/components/command-palette/command-palette-suggestion-list.d.ts +2 -0
  113. package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
  114. package/esm/components/command-palette/command-palette-suggestion-list.js +20 -20
  115. package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
  116. package/esm/components/command-palette/command-palette-suggestion-list.spec.js +296 -278
  117. package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -1
  118. package/esm/components/command-palette/index.d.ts +2 -0
  119. package/esm/components/command-palette/index.d.ts.map +1 -1
  120. package/esm/components/command-palette/index.js +25 -94
  121. package/esm/components/command-palette/index.js.map +1 -1
  122. package/esm/components/command-palette/index.spec.js +12 -12
  123. package/esm/components/command-palette/index.spec.js.map +1 -1
  124. package/esm/components/context-menu/context-menu-item.d.ts +9 -0
  125. package/esm/components/context-menu/context-menu-item.d.ts.map +1 -0
  126. package/esm/components/context-menu/context-menu-item.js +56 -0
  127. package/esm/components/context-menu/context-menu-item.js.map +1 -0
  128. package/esm/components/context-menu/context-menu-manager.d.ts +52 -0
  129. package/esm/components/context-menu/context-menu-manager.d.ts.map +1 -0
  130. package/esm/components/context-menu/context-menu-manager.js +128 -0
  131. package/esm/components/context-menu/context-menu-manager.js.map +1 -0
  132. package/esm/components/context-menu/context-menu-manager.spec.d.ts +2 -0
  133. package/esm/components/context-menu/context-menu-manager.spec.d.ts.map +1 -0
  134. package/esm/components/context-menu/context-menu-manager.spec.js +326 -0
  135. package/esm/components/context-menu/context-menu-manager.spec.js.map +1 -0
  136. package/esm/components/context-menu/context-menu.d.ts +8 -0
  137. package/esm/components/context-menu/context-menu.d.ts.map +1 -0
  138. package/esm/components/context-menu/context-menu.js +79 -0
  139. package/esm/components/context-menu/context-menu.js.map +1 -0
  140. package/esm/components/context-menu/context-menu.spec.d.ts +2 -0
  141. package/esm/components/context-menu/context-menu.spec.d.ts.map +1 -0
  142. package/esm/components/context-menu/context-menu.spec.js +282 -0
  143. package/esm/components/context-menu/context-menu.spec.js.map +1 -0
  144. package/esm/components/context-menu/index.d.ts +4 -0
  145. package/esm/components/context-menu/index.d.ts.map +1 -0
  146. package/esm/components/context-menu/index.js +4 -0
  147. package/esm/components/context-menu/index.js.map +1 -0
  148. package/esm/components/data-grid/body.spec.js +194 -184
  149. package/esm/components/data-grid/body.spec.js.map +1 -1
  150. package/esm/components/data-grid/data-grid-row.d.ts.map +1 -1
  151. package/esm/components/data-grid/data-grid-row.js +66 -54
  152. package/esm/components/data-grid/data-grid-row.js.map +1 -1
  153. package/esm/components/data-grid/data-grid-row.spec.js +127 -95
  154. package/esm/components/data-grid/data-grid-row.spec.js.map +1 -1
  155. package/esm/components/data-grid/data-grid.d.ts.map +1 -1
  156. package/esm/components/data-grid/data-grid.js +17 -16
  157. package/esm/components/data-grid/data-grid.js.map +1 -1
  158. package/esm/components/data-grid/data-grid.spec.js +364 -430
  159. package/esm/components/data-grid/data-grid.spec.js.map +1 -1
  160. package/esm/components/data-grid/footer.spec.js +215 -203
  161. package/esm/components/data-grid/footer.spec.js.map +1 -1
  162. package/esm/components/data-grid/header.d.ts +3 -1
  163. package/esm/components/data-grid/header.d.ts.map +1 -1
  164. package/esm/components/data-grid/header.js +42 -30
  165. package/esm/components/data-grid/header.js.map +1 -1
  166. package/esm/components/data-grid/header.spec.js +330 -307
  167. package/esm/components/data-grid/header.spec.js.map +1 -1
  168. package/esm/components/data-grid/selection-cell.d.ts +2 -0
  169. package/esm/components/data-grid/selection-cell.d.ts.map +1 -1
  170. package/esm/components/data-grid/selection-cell.js +2 -7
  171. package/esm/components/data-grid/selection-cell.js.map +1 -1
  172. package/esm/components/data-grid/selection-cell.spec.js +45 -36
  173. package/esm/components/data-grid/selection-cell.spec.js.map +1 -1
  174. package/esm/components/dialog.d.ts +46 -0
  175. package/esm/components/dialog.d.ts.map +1 -0
  176. package/esm/components/dialog.js +178 -0
  177. package/esm/components/dialog.js.map +1 -0
  178. package/esm/components/dialog.spec.d.ts +2 -0
  179. package/esm/components/dialog.spec.d.ts.map +1 -0
  180. package/esm/components/dialog.spec.js +113 -0
  181. package/esm/components/dialog.spec.js.map +1 -0
  182. package/esm/components/divider.d.ts +22 -0
  183. package/esm/components/divider.d.ts.map +1 -0
  184. package/esm/components/divider.js +113 -0
  185. package/esm/components/divider.js.map +1 -0
  186. package/esm/components/divider.spec.d.ts +2 -0
  187. package/esm/components/divider.spec.d.ts.map +1 -0
  188. package/esm/components/divider.spec.js +136 -0
  189. package/esm/components/divider.spec.js.map +1 -0
  190. package/esm/components/drawer/drawer-toggle-button.d.ts +36 -0
  191. package/esm/components/drawer/drawer-toggle-button.d.ts.map +1 -0
  192. package/esm/components/drawer/drawer-toggle-button.js +94 -0
  193. package/esm/components/drawer/drawer-toggle-button.js.map +1 -0
  194. package/esm/components/drawer/drawer-toggle-button.spec.d.ts +2 -0
  195. package/esm/components/drawer/drawer-toggle-button.spec.d.ts.map +1 -0
  196. package/esm/components/drawer/drawer-toggle-button.spec.js +306 -0
  197. package/esm/components/drawer/drawer-toggle-button.spec.js.map +1 -0
  198. package/esm/components/drawer/index.d.ts +56 -0
  199. package/esm/components/drawer/index.d.ts.map +1 -0
  200. package/esm/components/drawer/index.js +172 -0
  201. package/esm/components/drawer/index.js.map +1 -0
  202. package/esm/components/drawer/index.spec.d.ts +2 -0
  203. package/esm/components/drawer/index.spec.d.ts.map +1 -0
  204. package/esm/components/drawer/index.spec.js +538 -0
  205. package/esm/components/drawer/index.spec.js.map +1 -0
  206. package/esm/components/dropdown.d.ts +15 -0
  207. package/esm/components/dropdown.d.ts.map +1 -0
  208. package/esm/components/dropdown.js +262 -0
  209. package/esm/components/dropdown.js.map +1 -0
  210. package/esm/components/dropdown.spec.d.ts +2 -0
  211. package/esm/components/dropdown.spec.d.ts.map +1 -0
  212. package/esm/components/dropdown.spec.js +372 -0
  213. package/esm/components/dropdown.spec.js.map +1 -0
  214. package/esm/components/fab.d.ts +10 -1
  215. package/esm/components/fab.d.ts.map +1 -1
  216. package/esm/components/fab.js +24 -8
  217. package/esm/components/fab.js.map +1 -1
  218. package/esm/components/fab.spec.js +50 -39
  219. package/esm/components/fab.spec.js.map +1 -1
  220. package/esm/components/form.d.ts.map +1 -1
  221. package/esm/components/form.js +9 -7
  222. package/esm/components/form.js.map +1 -1
  223. package/esm/components/form.spec.js +209 -199
  224. package/esm/components/form.spec.js.map +1 -1
  225. package/esm/components/grid.js +10 -10
  226. package/esm/components/grid.js.map +1 -1
  227. package/esm/components/grid.spec.js +109 -85
  228. package/esm/components/grid.spec.js.map +1 -1
  229. package/esm/components/icons/icon-definitions.d.ts +140 -0
  230. package/esm/components/icons/icon-definitions.d.ts.map +1 -0
  231. package/esm/components/icons/icon-definitions.js +432 -0
  232. package/esm/components/icons/icon-definitions.js.map +1 -0
  233. package/esm/components/icons/icon-definitions.spec.d.ts +2 -0
  234. package/esm/components/icons/icon-definitions.spec.d.ts.map +1 -0
  235. package/esm/components/icons/icon-definitions.spec.js +59 -0
  236. package/esm/components/icons/icon-definitions.spec.js.map +1 -0
  237. package/esm/components/icons/icon-types.d.ts +48 -0
  238. package/esm/components/icons/icon-types.d.ts.map +1 -0
  239. package/esm/components/icons/icon-types.js +2 -0
  240. package/esm/components/icons/icon-types.js.map +1 -0
  241. package/esm/components/icons/icon.d.ts +56 -0
  242. package/esm/components/icons/icon.d.ts.map +1 -0
  243. package/esm/components/icons/icon.js +61 -0
  244. package/esm/components/icons/icon.js.map +1 -0
  245. package/esm/components/icons/icon.spec.d.ts +2 -0
  246. package/esm/components/icons/icon.spec.d.ts.map +1 -0
  247. package/esm/components/icons/icon.spec.js +224 -0
  248. package/esm/components/icons/icon.spec.js.map +1 -0
  249. package/esm/components/icons/index.d.ts +5 -0
  250. package/esm/components/icons/index.d.ts.map +1 -0
  251. package/esm/components/icons/index.js +3 -0
  252. package/esm/components/icons/index.js.map +1 -0
  253. package/esm/components/image.d.ts +62 -0
  254. package/esm/components/image.d.ts.map +1 -0
  255. package/esm/components/image.js +348 -0
  256. package/esm/components/image.js.map +1 -0
  257. package/esm/components/image.spec.d.ts +2 -0
  258. package/esm/components/image.spec.d.ts.map +1 -0
  259. package/esm/components/image.spec.js +542 -0
  260. package/esm/components/image.spec.js.map +1 -0
  261. package/esm/components/index.d.ts +32 -4
  262. package/esm/components/index.d.ts.map +1 -1
  263. package/esm/components/index.js +32 -4
  264. package/esm/components/index.js.map +1 -1
  265. package/esm/components/inputs/autocomplete.d.ts +2 -0
  266. package/esm/components/inputs/autocomplete.d.ts.map +1 -1
  267. package/esm/components/inputs/autocomplete.js +10 -6
  268. package/esm/components/inputs/autocomplete.js.map +1 -1
  269. package/esm/components/inputs/autocomplete.spec.js +10 -1
  270. package/esm/components/inputs/autocomplete.spec.js.map +1 -1
  271. package/esm/components/inputs/checkbox.d.ts +50 -0
  272. package/esm/components/inputs/checkbox.d.ts.map +1 -0
  273. package/esm/components/inputs/checkbox.js +126 -0
  274. package/esm/components/inputs/checkbox.js.map +1 -0
  275. package/esm/components/inputs/checkbox.spec.d.ts +2 -0
  276. package/esm/components/inputs/checkbox.spec.d.ts.map +1 -0
  277. package/esm/components/inputs/checkbox.spec.js +287 -0
  278. package/esm/components/inputs/checkbox.spec.js.map +1 -0
  279. package/esm/components/inputs/index.d.ts +7 -0
  280. package/esm/components/inputs/index.d.ts.map +1 -1
  281. package/esm/components/inputs/index.js +7 -0
  282. package/esm/components/inputs/index.js.map +1 -1
  283. package/esm/components/inputs/input-number.d.ts +79 -0
  284. package/esm/components/inputs/input-number.d.ts.map +1 -0
  285. package/esm/components/inputs/input-number.js +232 -0
  286. package/esm/components/inputs/input-number.js.map +1 -0
  287. package/esm/components/inputs/input-number.spec.d.ts +2 -0
  288. package/esm/components/inputs/input-number.spec.d.ts.map +1 -0
  289. package/esm/components/inputs/input-number.spec.js +516 -0
  290. package/esm/components/inputs/input-number.spec.js.map +1 -0
  291. package/esm/components/inputs/input.d.ts +2 -1
  292. package/esm/components/inputs/input.d.ts.map +1 -1
  293. package/esm/components/inputs/input.js +86 -116
  294. package/esm/components/inputs/input.js.map +1 -1
  295. package/esm/components/inputs/input.spec.js +461 -427
  296. package/esm/components/inputs/input.spec.js.map +1 -1
  297. package/esm/components/inputs/radio-group.d.ts +38 -0
  298. package/esm/components/inputs/radio-group.d.ts.map +1 -0
  299. package/esm/components/inputs/radio-group.js +58 -0
  300. package/esm/components/inputs/radio-group.js.map +1 -0
  301. package/esm/components/inputs/radio-group.spec.d.ts +2 -0
  302. package/esm/components/inputs/radio-group.spec.d.ts.map +1 -0
  303. package/esm/components/inputs/radio-group.spec.js +201 -0
  304. package/esm/components/inputs/radio-group.spec.js.map +1 -0
  305. package/esm/components/inputs/radio.d.ts +42 -0
  306. package/esm/components/inputs/radio.d.ts.map +1 -0
  307. package/esm/components/inputs/radio.js +134 -0
  308. package/esm/components/inputs/radio.js.map +1 -0
  309. package/esm/components/inputs/radio.spec.d.ts +2 -0
  310. package/esm/components/inputs/radio.spec.d.ts.map +1 -0
  311. package/esm/components/inputs/radio.spec.js +211 -0
  312. package/esm/components/inputs/radio.spec.js.map +1 -0
  313. package/esm/components/inputs/select.d.ts +67 -0
  314. package/esm/components/inputs/select.d.ts.map +1 -0
  315. package/esm/components/inputs/select.js +581 -0
  316. package/esm/components/inputs/select.js.map +1 -0
  317. package/esm/components/inputs/select.spec.d.ts +2 -0
  318. package/esm/components/inputs/select.spec.d.ts.map +1 -0
  319. package/esm/components/inputs/select.spec.js +1009 -0
  320. package/esm/components/inputs/select.spec.js.map +1 -0
  321. package/esm/components/inputs/slider.d.ts +66 -0
  322. package/esm/components/inputs/slider.d.ts.map +1 -0
  323. package/esm/components/inputs/slider.js +526 -0
  324. package/esm/components/inputs/slider.js.map +1 -0
  325. package/esm/components/inputs/slider.spec.d.ts +2 -0
  326. package/esm/components/inputs/slider.spec.d.ts.map +1 -0
  327. package/esm/components/inputs/slider.spec.js +812 -0
  328. package/esm/components/inputs/slider.spec.js.map +1 -0
  329. package/esm/components/inputs/switch.d.ts +50 -0
  330. package/esm/components/inputs/switch.d.ts.map +1 -0
  331. package/esm/components/inputs/switch.js +138 -0
  332. package/esm/components/inputs/switch.js.map +1 -0
  333. package/esm/components/inputs/switch.spec.d.ts +2 -0
  334. package/esm/components/inputs/switch.spec.d.ts.map +1 -0
  335. package/esm/components/inputs/switch.spec.js +313 -0
  336. package/esm/components/inputs/switch.spec.js.map +1 -0
  337. package/esm/components/inputs/text-area.d.ts +2 -0
  338. package/esm/components/inputs/text-area.d.ts.map +1 -1
  339. package/esm/components/inputs/text-area.js +13 -21
  340. package/esm/components/inputs/text-area.js.map +1 -1
  341. package/esm/components/inputs/text-area.spec.js +171 -156
  342. package/esm/components/inputs/text-area.spec.js.map +1 -1
  343. package/esm/components/linear-progress.d.ts +32 -0
  344. package/esm/components/linear-progress.d.ts.map +1 -0
  345. package/esm/components/linear-progress.js +79 -0
  346. package/esm/components/linear-progress.js.map +1 -0
  347. package/esm/components/linear-progress.spec.d.ts +2 -0
  348. package/esm/components/linear-progress.spec.d.ts.map +1 -0
  349. package/esm/components/linear-progress.spec.js +251 -0
  350. package/esm/components/linear-progress.spec.js.map +1 -0
  351. package/esm/components/list/index.d.ts +3 -0
  352. package/esm/components/list/index.d.ts.map +1 -0
  353. package/esm/components/list/index.js +3 -0
  354. package/esm/components/list/index.js.map +1 -0
  355. package/esm/components/list/list-item.d.ts +13 -0
  356. package/esm/components/list/list-item.d.ts.map +1 -0
  357. package/esm/components/list/list-item.js +81 -0
  358. package/esm/components/list/list-item.js.map +1 -0
  359. package/esm/components/list/list.d.ts +18 -0
  360. package/esm/components/list/list.d.ts.map +1 -0
  361. package/esm/components/list/list.js +42 -0
  362. package/esm/components/list/list.js.map +1 -0
  363. package/esm/components/list/list.spec.d.ts +2 -0
  364. package/esm/components/list/list.spec.d.ts.map +1 -0
  365. package/esm/components/list/list.spec.js +540 -0
  366. package/esm/components/list/list.spec.js.map +1 -0
  367. package/esm/components/loader.d.ts +2 -0
  368. package/esm/components/loader.d.ts.map +1 -1
  369. package/esm/components/loader.js +18 -10
  370. package/esm/components/loader.js.map +1 -1
  371. package/esm/components/loader.spec.js +191 -175
  372. package/esm/components/loader.spec.js.map +1 -1
  373. package/esm/components/menu/index.d.ts +3 -0
  374. package/esm/components/menu/index.d.ts.map +1 -0
  375. package/esm/components/menu/index.js +3 -0
  376. package/esm/components/menu/index.js.map +1 -0
  377. package/esm/components/menu/menu-types.d.ts +27 -0
  378. package/esm/components/menu/menu-types.d.ts.map +1 -0
  379. package/esm/components/menu/menu-types.js +22 -0
  380. package/esm/components/menu/menu-types.js.map +1 -0
  381. package/esm/components/menu/menu-types.spec.d.ts +2 -0
  382. package/esm/components/menu/menu-types.spec.d.ts.map +1 -0
  383. package/esm/components/menu/menu-types.spec.js +103 -0
  384. package/esm/components/menu/menu-types.spec.js.map +1 -0
  385. package/esm/components/menu/menu.d.ts +17 -0
  386. package/esm/components/menu/menu.d.ts.map +1 -0
  387. package/esm/components/menu/menu.js +240 -0
  388. package/esm/components/menu/menu.js.map +1 -0
  389. package/esm/components/menu/menu.spec.d.ts +2 -0
  390. package/esm/components/menu/menu.spec.d.ts.map +1 -0
  391. package/esm/components/menu/menu.spec.js +427 -0
  392. package/esm/components/menu/menu.spec.js.map +1 -0
  393. package/esm/components/modal.d.ts +3 -2
  394. package/esm/components/modal.d.ts.map +1 -1
  395. package/esm/components/modal.js +8 -5
  396. package/esm/components/modal.js.map +1 -1
  397. package/esm/components/modal.spec.js +50 -43
  398. package/esm/components/modal.spec.js.map +1 -1
  399. package/esm/components/noty-list.d.ts +4 -0
  400. package/esm/components/noty-list.d.ts.map +1 -1
  401. package/esm/components/noty-list.js +65 -53
  402. package/esm/components/noty-list.js.map +1 -1
  403. package/esm/components/noty-list.spec.js +71 -68
  404. package/esm/components/noty-list.spec.js.map +1 -1
  405. package/esm/components/page-container/index.d.ts +54 -0
  406. package/esm/components/page-container/index.d.ts.map +1 -0
  407. package/esm/components/page-container/index.js +63 -0
  408. package/esm/components/page-container/index.js.map +1 -0
  409. package/esm/components/page-container/index.spec.d.ts +2 -0
  410. package/esm/components/page-container/index.spec.d.ts.map +1 -0
  411. package/esm/components/page-container/index.spec.js +217 -0
  412. package/esm/components/page-container/index.spec.js.map +1 -0
  413. package/esm/components/page-container/page-header.d.ts +57 -0
  414. package/esm/components/page-container/page-header.d.ts.map +1 -0
  415. package/esm/components/page-container/page-header.js +93 -0
  416. package/esm/components/page-container/page-header.js.map +1 -0
  417. package/esm/components/page-container/page-header.spec.d.ts +2 -0
  418. package/esm/components/page-container/page-header.spec.d.ts.map +1 -0
  419. package/esm/components/page-container/page-header.spec.js +230 -0
  420. package/esm/components/page-container/page-header.spec.js.map +1 -0
  421. package/esm/components/page-layout/index.d.ts +83 -0
  422. package/esm/components/page-layout/index.d.ts.map +1 -0
  423. package/esm/components/page-layout/index.js +288 -0
  424. package/esm/components/page-layout/index.js.map +1 -0
  425. package/esm/components/page-layout/index.spec.d.ts +2 -0
  426. package/esm/components/page-layout/index.spec.d.ts.map +1 -0
  427. package/esm/components/page-layout/index.spec.js +637 -0
  428. package/esm/components/page-layout/index.spec.js.map +1 -0
  429. package/esm/components/pagination.d.ts +43 -0
  430. package/esm/components/pagination.d.ts.map +1 -0
  431. package/esm/components/pagination.js +165 -0
  432. package/esm/components/pagination.js.map +1 -0
  433. package/esm/components/pagination.spec.d.ts +2 -0
  434. package/esm/components/pagination.spec.d.ts.map +1 -0
  435. package/esm/components/pagination.spec.js +195 -0
  436. package/esm/components/pagination.spec.js.map +1 -0
  437. package/esm/components/paper.d.ts +3 -1
  438. package/esm/components/paper.d.ts.map +1 -1
  439. package/esm/components/paper.js +11 -9
  440. package/esm/components/paper.js.map +1 -1
  441. package/esm/components/paper.spec.js +26 -18
  442. package/esm/components/paper.spec.js.map +1 -1
  443. package/esm/components/rating.d.ts +62 -0
  444. package/esm/components/rating.d.ts.map +1 -0
  445. package/esm/components/rating.js +201 -0
  446. package/esm/components/rating.js.map +1 -0
  447. package/esm/components/rating.spec.d.ts +2 -0
  448. package/esm/components/rating.spec.d.ts.map +1 -0
  449. package/esm/components/rating.spec.js +663 -0
  450. package/esm/components/rating.spec.js.map +1 -0
  451. package/esm/components/result.d.ts +37 -0
  452. package/esm/components/result.d.ts.map +1 -0
  453. package/esm/components/result.js +109 -0
  454. package/esm/components/result.js.map +1 -0
  455. package/esm/components/result.spec.d.ts +2 -0
  456. package/esm/components/result.spec.d.ts.map +1 -0
  457. package/esm/components/result.spec.js +159 -0
  458. package/esm/components/result.spec.js.map +1 -0
  459. package/esm/components/searchable-input-styles.d.ts +8 -0
  460. package/esm/components/searchable-input-styles.d.ts.map +1 -0
  461. package/esm/components/searchable-input-styles.js +71 -0
  462. package/esm/components/searchable-input-styles.js.map +1 -0
  463. package/esm/components/skeleton.d.ts +2 -0
  464. package/esm/components/skeleton.d.ts.map +1 -1
  465. package/esm/components/skeleton.js +19 -6
  466. package/esm/components/skeleton.js.map +1 -1
  467. package/esm/components/skeleton.spec.js +103 -95
  468. package/esm/components/skeleton.spec.js.map +1 -1
  469. package/esm/components/styles.d.ts.map +1 -1
  470. package/esm/components/styles.js +14 -13
  471. package/esm/components/styles.js.map +1 -1
  472. package/esm/components/styles.spec.js +27 -26
  473. package/esm/components/styles.spec.js.map +1 -1
  474. package/esm/components/suggest/index.d.ts.map +1 -1
  475. package/esm/components/suggest/index.js +24 -85
  476. package/esm/components/suggest/index.js.map +1 -1
  477. package/esm/components/suggest/index.spec.js +402 -378
  478. package/esm/components/suggest/index.spec.js.map +1 -1
  479. package/esm/components/suggest/suggest-input.d.ts +2 -0
  480. package/esm/components/suggest/suggest-input.d.ts.map +1 -1
  481. package/esm/components/suggest/suggest-input.js +10 -8
  482. package/esm/components/suggest/suggest-input.js.map +1 -1
  483. package/esm/components/suggest/suggest-input.spec.js +83 -71
  484. package/esm/components/suggest/suggest-input.spec.js.map +1 -1
  485. package/esm/components/suggest/suggest-manager.spec.js +102 -92
  486. package/esm/components/suggest/suggest-manager.spec.js.map +1 -1
  487. package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
  488. package/esm/components/suggest/suggestion-list.js +21 -22
  489. package/esm/components/suggest/suggestion-list.js.map +1 -1
  490. package/esm/components/suggest/suggestion-list.spec.js +165 -146
  491. package/esm/components/suggest/suggestion-list.spec.js.map +1 -1
  492. package/esm/components/tabs.d.ts +18 -2
  493. package/esm/components/tabs.d.ts.map +1 -1
  494. package/esm/components/tabs.js +154 -14
  495. package/esm/components/tabs.js.map +1 -1
  496. package/esm/components/tabs.spec.js +295 -7
  497. package/esm/components/tabs.spec.js.map +1 -1
  498. package/esm/components/timeline.d.ts +53 -0
  499. package/esm/components/timeline.d.ts.map +1 -0
  500. package/esm/components/timeline.js +162 -0
  501. package/esm/components/timeline.js.map +1 -0
  502. package/esm/components/timeline.spec.d.ts +2 -0
  503. package/esm/components/timeline.spec.d.ts.map +1 -0
  504. package/esm/components/timeline.spec.js +209 -0
  505. package/esm/components/timeline.spec.js.map +1 -0
  506. package/esm/components/tooltip.d.ts +25 -0
  507. package/esm/components/tooltip.d.ts.map +1 -0
  508. package/esm/components/tooltip.js +113 -0
  509. package/esm/components/tooltip.js.map +1 -0
  510. package/esm/components/tooltip.spec.d.ts +2 -0
  511. package/esm/components/tooltip.spec.d.ts.map +1 -0
  512. package/esm/components/tooltip.spec.js +152 -0
  513. package/esm/components/tooltip.spec.js.map +1 -0
  514. package/esm/components/tree/index.d.ts +3 -0
  515. package/esm/components/tree/index.d.ts.map +1 -0
  516. package/esm/components/tree/index.js +3 -0
  517. package/esm/components/tree/index.js.map +1 -0
  518. package/esm/components/tree/tree-item.d.ts +14 -0
  519. package/esm/components/tree/tree-item.d.ts.map +1 -0
  520. package/esm/components/tree/tree-item.js +118 -0
  521. package/esm/components/tree/tree-item.js.map +1 -0
  522. package/esm/components/tree/tree.d.ts +20 -0
  523. package/esm/components/tree/tree.d.ts.map +1 -0
  524. package/esm/components/tree/tree.js +66 -0
  525. package/esm/components/tree/tree.js.map +1 -0
  526. package/esm/components/tree/tree.spec.d.ts +2 -0
  527. package/esm/components/tree/tree.spec.d.ts.map +1 -0
  528. package/esm/components/tree/tree.spec.js +427 -0
  529. package/esm/components/tree/tree.spec.js.map +1 -0
  530. package/esm/components/typography.d.ts +48 -0
  531. package/esm/components/typography.d.ts.map +1 -0
  532. package/esm/components/typography.js +223 -0
  533. package/esm/components/typography.js.map +1 -0
  534. package/esm/components/typography.spec.d.ts +2 -0
  535. package/esm/components/typography.spec.d.ts.map +1 -0
  536. package/esm/components/typography.spec.js +199 -0
  537. package/esm/components/typography.spec.js.map +1 -0
  538. package/esm/components/wizard/index.d.ts +2 -0
  539. package/esm/components/wizard/index.d.ts.map +1 -1
  540. package/esm/components/wizard/index.spec.js +70 -56
  541. package/esm/components/wizard/index.spec.js.map +1 -1
  542. package/esm/services/click-away-service.d.ts +5 -2
  543. package/esm/services/click-away-service.d.ts.map +1 -1
  544. package/esm/services/click-away-service.js +7 -1
  545. package/esm/services/click-away-service.js.map +1 -1
  546. package/esm/services/click-away-service.spec.js +14 -12
  547. package/esm/services/click-away-service.spec.js.map +1 -1
  548. package/esm/services/css-variable-theme.d.ts +167 -1
  549. package/esm/services/css-variable-theme.d.ts.map +1 -1
  550. package/esm/services/css-variable-theme.js +102 -0
  551. package/esm/services/css-variable-theme.js.map +1 -1
  552. package/esm/services/css-variable-theme.spec.js +131 -1
  553. package/esm/services/css-variable-theme.spec.js.map +1 -1
  554. package/esm/services/default-dark-theme.d.ts +107 -2
  555. package/esm/services/default-dark-theme.d.ts.map +1 -1
  556. package/esm/services/default-dark-theme.js +87 -1
  557. package/esm/services/default-dark-theme.js.map +1 -1
  558. package/esm/services/default-light-theme.d.ts +107 -2
  559. package/esm/services/default-light-theme.d.ts.map +1 -1
  560. package/esm/services/default-light-theme.js +86 -0
  561. package/esm/services/default-light-theme.js.map +1 -1
  562. package/esm/services/index.d.ts +6 -2
  563. package/esm/services/index.d.ts.map +1 -1
  564. package/esm/services/index.js +6 -2
  565. package/esm/services/index.js.map +1 -1
  566. package/esm/services/layout-service.d.ts +217 -0
  567. package/esm/services/layout-service.d.ts.map +1 -0
  568. package/esm/services/layout-service.js +331 -0
  569. package/esm/services/layout-service.js.map +1 -0
  570. package/esm/services/layout-service.spec.d.ts +2 -0
  571. package/esm/services/layout-service.spec.d.ts.map +1 -0
  572. package/esm/services/layout-service.spec.js +425 -0
  573. package/esm/services/layout-service.spec.js.map +1 -0
  574. package/esm/services/list-service.d.ts +31 -0
  575. package/esm/services/list-service.d.ts.map +1 -0
  576. package/esm/services/list-service.js +149 -0
  577. package/esm/services/list-service.js.map +1 -0
  578. package/esm/services/list-service.spec.d.ts +2 -0
  579. package/esm/services/list-service.spec.d.ts.map +1 -0
  580. package/esm/services/list-service.spec.js +283 -0
  581. package/esm/services/list-service.spec.js.map +1 -0
  582. package/esm/services/palette-css-vars.d.ts +12 -0
  583. package/esm/services/palette-css-vars.d.ts.map +1 -0
  584. package/esm/services/palette-css-vars.js +44 -0
  585. package/esm/services/palette-css-vars.js.map +1 -0
  586. package/esm/services/theme-provider-service.d.ts +387 -2
  587. package/esm/services/theme-provider-service.d.ts.map +1 -1
  588. package/esm/services/theme-provider-service.js.map +1 -1
  589. package/esm/services/tree-service.d.ts +61 -0
  590. package/esm/services/tree-service.d.ts.map +1 -0
  591. package/esm/services/tree-service.js +149 -0
  592. package/esm/services/tree-service.js.map +1 -0
  593. package/esm/services/tree-service.spec.d.ts +2 -0
  594. package/esm/services/tree-service.spec.d.ts.map +1 -0
  595. package/esm/services/tree-service.spec.js +338 -0
  596. package/esm/services/tree-service.spec.js.map +1 -0
  597. package/esm/utils/promisify-animation.d.ts.map +1 -1
  598. package/esm/utils/promisify-animation.js +6 -1
  599. package/esm/utils/promisify-animation.js.map +1 -1
  600. package/package.json +7 -8
  601. package/src/components/accordion/accordion-item.tsx +197 -0
  602. package/src/components/accordion/accordion.spec.tsx +418 -0
  603. package/src/components/accordion/accordion.tsx +50 -0
  604. package/src/components/accordion/index.ts +2 -0
  605. package/src/components/alert.spec.tsx +256 -0
  606. package/src/components/alert.tsx +186 -0
  607. package/src/components/app-bar-link.spec.tsx +22 -19
  608. package/src/components/app-bar-link.tsx +29 -10
  609. package/src/components/app-bar.spec.tsx +73 -58
  610. package/src/components/app-bar.tsx +19 -12
  611. package/src/components/avatar.tsx +46 -47
  612. package/src/components/badge.spec.tsx +228 -0
  613. package/src/components/badge.tsx +104 -0
  614. package/src/components/breadcrumb.spec.tsx +396 -0
  615. package/src/components/breadcrumb.tsx +188 -0
  616. package/src/components/button-group.spec.tsx +611 -0
  617. package/src/components/button-group.tsx +423 -0
  618. package/src/components/button.spec.tsx +257 -67
  619. package/src/components/button.tsx +130 -80
  620. package/src/components/card.spec.tsx +389 -0
  621. package/src/components/card.tsx +261 -0
  622. package/src/components/carousel.spec.tsx +894 -0
  623. package/src/components/carousel.tsx +376 -0
  624. package/src/components/chip.spec.tsx +200 -0
  625. package/src/components/chip.tsx +188 -0
  626. package/src/components/circular-progress.spec.tsx +289 -0
  627. package/src/components/circular-progress.tsx +145 -0
  628. package/src/components/command-palette/command-palette-input.spec.tsx +219 -219
  629. package/src/components/command-palette/command-palette-input.tsx +25 -9
  630. package/src/components/command-palette/command-palette-manager.spec.ts +132 -117
  631. package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +358 -358
  632. package/src/components/command-palette/command-palette-suggestion-list.tsx +22 -20
  633. package/src/components/command-palette/index.spec.tsx +12 -12
  634. package/src/components/command-palette/index.tsx +25 -102
  635. package/src/components/context-menu/context-menu-item.tsx +85 -0
  636. package/src/components/context-menu/context-menu-manager.spec.ts +433 -0
  637. package/src/components/context-menu/context-menu-manager.ts +148 -0
  638. package/src/components/context-menu/context-menu.spec.tsx +352 -0
  639. package/src/components/context-menu/context-menu.tsx +116 -0
  640. package/src/components/context-menu/index.ts +3 -0
  641. package/src/components/data-grid/body.spec.tsx +287 -283
  642. package/src/components/data-grid/data-grid-row.spec.tsx +165 -140
  643. package/src/components/data-grid/data-grid-row.tsx +72 -55
  644. package/src/components/data-grid/data-grid.spec.tsx +659 -729
  645. package/src/components/data-grid/data-grid.tsx +19 -15
  646. package/src/components/data-grid/footer.spec.tsx +249 -237
  647. package/src/components/data-grid/header.spec.tsx +374 -351
  648. package/src/components/data-grid/header.tsx +58 -39
  649. package/src/components/data-grid/selection-cell.spec.tsx +46 -45
  650. package/src/components/data-grid/selection-cell.tsx +2 -6
  651. package/src/components/dialog.spec.tsx +135 -0
  652. package/src/components/dialog.tsx +277 -0
  653. package/src/components/divider.spec.tsx +197 -0
  654. package/src/components/divider.tsx +147 -0
  655. package/src/components/drawer/drawer-toggle-button.spec.tsx +374 -0
  656. package/src/components/drawer/drawer-toggle-button.tsx +124 -0
  657. package/src/components/drawer/index.spec.tsx +748 -0
  658. package/src/components/drawer/index.tsx +227 -0
  659. package/src/components/dropdown.spec.tsx +445 -0
  660. package/src/components/dropdown.tsx +343 -0
  661. package/src/components/fab.spec.tsx +51 -40
  662. package/src/components/fab.tsx +32 -9
  663. package/src/components/form.spec.tsx +303 -293
  664. package/src/components/form.tsx +10 -7
  665. package/src/components/grid.spec.tsx +276 -183
  666. package/src/components/grid.tsx +10 -10
  667. package/src/components/icons/icon-definitions.spec.ts +68 -0
  668. package/src/components/icons/icon-definitions.ts +509 -0
  669. package/src/components/icons/icon-types.ts +48 -0
  670. package/src/components/icons/icon.spec.tsx +314 -0
  671. package/src/components/icons/icon.tsx +111 -0
  672. package/src/components/icons/index.ts +4 -0
  673. package/src/components/image.spec.tsx +748 -0
  674. package/src/components/image.tsx +520 -0
  675. package/src/components/index.ts +32 -4
  676. package/src/components/inputs/autocomplete.spec.tsx +10 -1
  677. package/src/components/inputs/autocomplete.tsx +13 -7
  678. package/src/components/inputs/checkbox.spec.tsx +377 -0
  679. package/src/components/inputs/checkbox.tsx +198 -0
  680. package/src/components/inputs/index.ts +7 -0
  681. package/src/components/inputs/input-number.spec.tsx +686 -0
  682. package/src/components/inputs/input-number.tsx +387 -0
  683. package/src/components/inputs/input.spec.tsx +544 -508
  684. package/src/components/inputs/input.tsx +91 -132
  685. package/src/components/inputs/radio-group.spec.tsx +281 -0
  686. package/src/components/inputs/radio-group.tsx +108 -0
  687. package/src/components/inputs/radio.spec.tsx +273 -0
  688. package/src/components/inputs/radio.tsx +199 -0
  689. package/src/components/inputs/select.spec.tsx +1237 -0
  690. package/src/components/inputs/select.tsx +775 -0
  691. package/src/components/inputs/slider.spec.tsx +1020 -0
  692. package/src/components/inputs/slider.tsx +696 -0
  693. package/src/components/inputs/switch.spec.tsx +410 -0
  694. package/src/components/inputs/switch.tsx +218 -0
  695. package/src/components/inputs/text-area.spec.tsx +186 -171
  696. package/src/components/inputs/text-area.tsx +13 -19
  697. package/src/components/linear-progress.spec.tsx +320 -0
  698. package/src/components/linear-progress.tsx +127 -0
  699. package/src/components/list/index.ts +2 -0
  700. package/src/components/list/list-item.tsx +106 -0
  701. package/src/components/list/list.spec.tsx +817 -0
  702. package/src/components/list/list.tsx +92 -0
  703. package/src/components/loader.spec.tsx +220 -204
  704. package/src/components/loader.tsx +17 -9
  705. package/src/components/menu/index.ts +2 -0
  706. package/src/components/menu/menu-types.spec.ts +122 -0
  707. package/src/components/menu/menu-types.ts +43 -0
  708. package/src/components/menu/menu.spec.tsx +483 -0
  709. package/src/components/menu/menu.tsx +326 -0
  710. package/src/components/modal.spec.tsx +65 -55
  711. package/src/components/modal.tsx +9 -6
  712. package/src/components/noty-list.spec.tsx +78 -75
  713. package/src/components/noty-list.tsx +76 -68
  714. package/src/components/page-container/index.spec.tsx +274 -0
  715. package/src/components/page-container/index.tsx +82 -0
  716. package/src/components/page-container/page-header.spec.tsx +308 -0
  717. package/src/components/page-container/page-header.tsx +127 -0
  718. package/src/components/page-layout/index.spec.tsx +882 -0
  719. package/src/components/page-layout/index.tsx +392 -0
  720. package/src/components/pagination.spec.tsx +275 -0
  721. package/src/components/pagination.tsx +249 -0
  722. package/src/components/paper.spec.tsx +26 -18
  723. package/src/components/paper.tsx +12 -10
  724. package/src/components/rating.spec.tsx +866 -0
  725. package/src/components/rating.tsx +286 -0
  726. package/src/components/result.spec.tsx +221 -0
  727. package/src/components/result.tsx +155 -0
  728. package/src/components/searchable-input-styles.ts +81 -0
  729. package/src/components/skeleton.spec.tsx +126 -118
  730. package/src/components/skeleton.tsx +23 -6
  731. package/src/components/styles.spec.ts +27 -28
  732. package/src/components/styles.tsx +15 -13
  733. package/src/components/suggest/index.spec.tsx +611 -587
  734. package/src/components/suggest/index.tsx +28 -95
  735. package/src/components/suggest/suggest-input.spec.tsx +95 -81
  736. package/src/components/suggest/suggest-input.tsx +9 -7
  737. package/src/components/suggest/suggest-manager.spec.ts +103 -93
  738. package/src/components/suggest/suggestion-list.spec.tsx +194 -173
  739. package/src/components/suggest/suggestion-list.tsx +23 -22
  740. package/src/components/tabs.spec.tsx +369 -7
  741. package/src/components/tabs.tsx +221 -18
  742. package/src/components/timeline.spec.tsx +294 -0
  743. package/src/components/timeline.tsx +221 -0
  744. package/src/components/tooltip.spec.tsx +223 -0
  745. package/src/components/tooltip.tsx +155 -0
  746. package/src/components/tree/index.ts +2 -0
  747. package/src/components/tree/tree-item.tsx +161 -0
  748. package/src/components/tree/tree.spec.tsx +677 -0
  749. package/src/components/tree/tree.tsx +111 -0
  750. package/src/components/typography.spec.tsx +235 -0
  751. package/src/components/typography.tsx +292 -0
  752. package/src/components/wizard/index.spec.tsx +77 -68
  753. package/src/services/click-away-service.spec.ts +14 -16
  754. package/src/services/click-away-service.ts +9 -3
  755. package/src/services/css-variable-theme.spec.ts +169 -1
  756. package/src/services/css-variable-theme.ts +107 -2
  757. package/src/services/default-dark-theme.ts +89 -3
  758. package/src/services/default-light-theme.ts +88 -2
  759. package/src/services/index.ts +6 -2
  760. package/src/services/layout-service.spec.ts +535 -0
  761. package/src/services/layout-service.ts +391 -0
  762. package/src/services/list-service.spec.ts +362 -0
  763. package/src/services/list-service.ts +169 -0
  764. package/src/services/palette-css-vars.ts +46 -0
  765. package/src/services/theme-provider-service.ts +246 -1
  766. package/src/services/tree-service.spec.ts +412 -0
  767. package/src/services/tree-service.ts +179 -0
  768. package/src/utils/promisify-animation.ts +7 -1
@@ -0,0 +1,227 @@
1
+ import { ScreenService, Shade, createComponent, type ScreenSize } from '@furystack/shades'
2
+ import type { ValueObserver } from '@furystack/utils'
3
+ import { cssVariableTheme } from '../../services/css-variable-theme.js'
4
+ import { LayoutService } from '../../services/layout-service.js'
5
+
6
+ export { DrawerToggleButton, type DrawerToggleButtonProps } from './drawer-toggle-button.js'
7
+
8
+ /**
9
+ * Props for the Drawer component.
10
+ */
11
+ export type DrawerProps = {
12
+ /** Position of the drawer */
13
+ position: 'left' | 'right'
14
+ /** Drawer behavior variant */
15
+ variant: 'permanent' | 'collapsible' | 'temporary'
16
+ /** Width of the drawer (CSS value). Default: '240px' */
17
+ width?: string
18
+ /** Initial open state for collapsible/temporary drawers. Default: true for collapsible, false for temporary */
19
+ defaultOpen?: boolean
20
+ /** Auto-collapse the drawer below this breakpoint (uses ScreenService) */
21
+ collapseOnBreakpoint?: ScreenSize
22
+ }
23
+
24
+ const DEFAULT_DRAWER_WIDTH = '240px'
25
+
26
+ /**
27
+ * Standalone Drawer component for sidebars and navigation panels.
28
+ *
29
+ * Works with LayoutService for state management and supports three variants:
30
+ * - **permanent**: Always visible, cannot be closed
31
+ * - **collapsible**: Can be toggled open/closed, pushes content
32
+ * - **temporary**: Overlays content with backdrop, closes on backdrop click
33
+ *
34
+ * Supports responsive behavior via `collapseOnBreakpoint` prop which
35
+ * auto-collapses the drawer below a specified screen size.
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * // Simple collapsible drawer
40
+ * <Drawer position="left" variant="collapsible">
41
+ * <nav>Navigation items...</nav>
42
+ * </Drawer>
43
+ *
44
+ * // Responsive drawer that collapses on mobile
45
+ * <Drawer
46
+ * position="left"
47
+ * variant="collapsible"
48
+ * collapseOnBreakpoint="md"
49
+ * >
50
+ * <nav>Navigation items...</nav>
51
+ * </Drawer>
52
+ *
53
+ * // Temporary drawer (mobile navigation)
54
+ * <Drawer position="left" variant="temporary">
55
+ * <nav>Mobile navigation...</nav>
56
+ * </Drawer>
57
+ * ```
58
+ */
59
+ export const Drawer = Shade<DrawerProps>({
60
+ shadowDomName: 'shade-drawer',
61
+ css: {
62
+ display: 'block',
63
+
64
+ // Drawer container
65
+ '& .drawer-container': {
66
+ position: 'fixed',
67
+ top: 'var(--layout-content-margin-top, 0px)',
68
+ bottom: '0',
69
+ zIndex: '1000',
70
+ overflow: 'hidden',
71
+ transition: `width ${cssVariableTheme.transitions.duration.slow} ${cssVariableTheme.transitions.easing.easeInOut}, transform ${cssVariableTheme.transitions.duration.slow} ${cssVariableTheme.transitions.easing.easeInOut}`,
72
+ background: cssVariableTheme.background.paper,
73
+ },
74
+
75
+ // Left drawer positioning
76
+ '& .drawer-container.drawer-left': {
77
+ left: '0',
78
+ borderRight: `1px solid ${cssVariableTheme.divider}`,
79
+ },
80
+
81
+ // Right drawer positioning
82
+ '& .drawer-container.drawer-right': {
83
+ right: '0',
84
+ borderLeft: `1px solid ${cssVariableTheme.divider}`,
85
+ },
86
+
87
+ // Closed state for permanent/collapsible
88
+ '& .drawer-container.closed': {
89
+ width: '0 !important',
90
+ overflow: 'hidden',
91
+ },
92
+
93
+ // Content wrapper for proper overflow
94
+ '& .drawer-content': {
95
+ height: '100%',
96
+ overflow: 'auto',
97
+ },
98
+
99
+ // Backdrop for temporary drawer
100
+ '& .drawer-backdrop': {
101
+ position: 'fixed',
102
+ top: '0',
103
+ left: '0',
104
+ right: '0',
105
+ bottom: '0',
106
+ backgroundColor: cssVariableTheme.action.backdrop,
107
+ zIndex: '999',
108
+ opacity: '0',
109
+ pointerEvents: 'none',
110
+ transition: `opacity ${cssVariableTheme.transitions.duration.slow} ${cssVariableTheme.transitions.easing.easeInOut}`,
111
+ },
112
+ '& .drawer-backdrop.visible': {
113
+ opacity: '1',
114
+ pointerEvents: 'auto',
115
+ },
116
+ },
117
+
118
+ render: ({ props, children, injector, useObservable, useDisposable }) => {
119
+ const layoutService = injector.getInstance(LayoutService)
120
+ const screenService = injector.getInstance(ScreenService)
121
+
122
+ const { position, variant, width = DEFAULT_DRAWER_WIDTH, defaultOpen, collapseOnBreakpoint } = props
123
+
124
+ // Determine initial open state based on variant
125
+ const getInitialOpenState = (): boolean => {
126
+ if (variant === 'permanent') return true
127
+ if (variant === 'temporary') return defaultOpen ?? false
128
+ // collapsible defaults to true
129
+ return defaultOpen ?? true
130
+ }
131
+
132
+ // Initialize drawer state if not already set
133
+ const currentState = layoutService.drawerState.getValue()[position]
134
+ if (!currentState) {
135
+ layoutService.initDrawer(position, {
136
+ open: getInitialOpenState(),
137
+ width,
138
+ variant,
139
+ })
140
+ } else if (currentState.width !== width) {
141
+ // Update width if it changed
142
+ layoutService.setDrawerWidth(position, width)
143
+ }
144
+
145
+ // Subscribe to drawer state
146
+ const [drawerState] = useObservable('drawerState', layoutService.drawerState)
147
+ const isOpen = drawerState[position]?.open ?? false
148
+
149
+ // Set up responsive breakpoint listener
150
+ useDisposable(`breakpoint-listener-${collapseOnBreakpoint}`, () => {
151
+ if (!collapseOnBreakpoint || variant === 'permanent') {
152
+ return { [Symbol.dispose]: () => {} }
153
+ }
154
+
155
+ const breakpointObservable = screenService.screenSize.atLeast[collapseOnBreakpoint]
156
+
157
+ const subscription: ValueObserver<boolean> = breakpointObservable.subscribe((isAtLeast) => {
158
+ // When screen becomes smaller than breakpoint, close the drawer
159
+ // When screen becomes larger than breakpoint, open the drawer (for collapsible)
160
+ if (variant === 'collapsible') {
161
+ layoutService.setDrawerOpen(position, isAtLeast)
162
+ } else if (variant === 'temporary' && isAtLeast) {
163
+ // For temporary drawers, close when screen is large enough
164
+ layoutService.setDrawerOpen(position, false)
165
+ }
166
+ })
167
+
168
+ return subscription
169
+ })
170
+
171
+ // Handle backdrop click for temporary drawer
172
+ const handleBackdropClick = () => {
173
+ if (variant === 'temporary') {
174
+ layoutService.setDrawerOpen(position, false)
175
+ }
176
+ }
177
+
178
+ // Calculate drawer style
179
+ const getDrawerStyle = (): Partial<CSSStyleDeclaration> => {
180
+ if (variant === 'temporary') {
181
+ // Temporary drawers use transform for slide animation
182
+ return {
183
+ width,
184
+ transform: isOpen ? 'translateX(0)' : position === 'left' ? 'translateX(-100%)' : 'translateX(100%)',
185
+ }
186
+ }
187
+
188
+ // Permanent and collapsible drawers animate width
189
+ return {
190
+ width: isOpen ? width : '0',
191
+ }
192
+ }
193
+
194
+ // Build container class list
195
+ const containerClasses = ['drawer-container', `drawer-${position}`]
196
+ if (!isOpen && variant !== 'temporary') {
197
+ containerClasses.push('closed')
198
+ }
199
+
200
+ // Show backdrop only for open temporary drawers
201
+ const showBackdrop = variant === 'temporary' && isOpen
202
+
203
+ return (
204
+ <>
205
+ {/* Backdrop for temporary drawer */}
206
+ {variant === 'temporary' && (
207
+ <div
208
+ className={`drawer-backdrop ${showBackdrop ? 'visible' : ''}`}
209
+ onclick={handleBackdropClick}
210
+ data-testid={`drawer-backdrop-${position}`}
211
+ />
212
+ )}
213
+
214
+ {/* Drawer container */}
215
+ <div
216
+ className={containerClasses.join(' ')}
217
+ style={getDrawerStyle()}
218
+ data-testid={`drawer-${position}`}
219
+ data-variant={variant}
220
+ data-open={isOpen ? 'true' : 'false'}
221
+ >
222
+ <div className="drawer-content">{children}</div>
223
+ </div>
224
+ </>
225
+ )
226
+ },
227
+ })
@@ -0,0 +1,445 @@
1
+ import { Injector } from '@furystack/inject'
2
+ import { createComponent, initializeShadeRoot } from '@furystack/shades'
3
+ import { sleepAsync, usingAsync } from '@furystack/utils'
4
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
5
+ import { Dropdown } from './dropdown.js'
6
+ import type { MenuEntry } from './menu/menu-types.js'
7
+
8
+ describe('Dropdown', () => {
9
+ beforeEach(() => {
10
+ document.body.innerHTML = '<div id="root"></div>'
11
+ })
12
+
13
+ afterEach(() => {
14
+ document.body.innerHTML = ''
15
+ })
16
+
17
+ const createTestItems = (): MenuEntry[] => [
18
+ { key: 'cut', label: 'Cut' },
19
+ { key: 'copy', label: 'Copy' },
20
+ { type: 'divider' },
21
+ { key: 'paste', label: 'Paste' },
22
+ ]
23
+
24
+ const renderDropdown = async (
25
+ props: Omit<Parameters<typeof Dropdown>[0], 'items'> & { items?: MenuEntry[] },
26
+ triggerText = 'Open',
27
+ ) => {
28
+ const items = props.items ?? createTestItems()
29
+ const injector = new Injector()
30
+ const root = document.getElementById('root')!
31
+ initializeShadeRoot({
32
+ injector,
33
+ rootElement: root,
34
+ jsxElement: (
35
+ <Dropdown {...props} items={items}>
36
+ <button>{triggerText}</button>
37
+ </Dropdown>
38
+ ),
39
+ })
40
+ await sleepAsync(50)
41
+ return {
42
+ injector,
43
+ dropdown: root.querySelector('shade-dropdown') as HTMLElement,
44
+ [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
45
+ }
46
+ }
47
+
48
+ describe('rendering', () => {
49
+ it('should render the dropdown element', async () => {
50
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
51
+ expect(dropdown).toBeTruthy()
52
+ expect(dropdown.tagName.toLowerCase()).toBe('shade-dropdown')
53
+ })
54
+ })
55
+
56
+ it('should render the trigger content', async () => {
57
+ await usingAsync(await renderDropdown({}, 'Click me'), async ({ dropdown }) => {
58
+ const trigger = dropdown.querySelector('.dropdown-trigger')
59
+ expect(trigger).toBeTruthy()
60
+ expect(trigger?.textContent).toContain('Click me')
61
+ })
62
+ })
63
+
64
+ it('should not show the dropdown panel initially', async () => {
65
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
66
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
67
+ const panel = dropdown.querySelector('.dropdown-panel')
68
+ expect(panel).toBeTruthy()
69
+ expect(panel?.classList.contains('visible')).toBe(false)
70
+ })
71
+ })
72
+ })
73
+
74
+ describe('opening and closing', () => {
75
+ it('should open when trigger is clicked', async () => {
76
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
77
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
78
+ trigger.click()
79
+ await sleepAsync(50)
80
+
81
+ const panel = dropdown.querySelector('.dropdown-panel')
82
+ expect(panel).toBeTruthy()
83
+ })
84
+ })
85
+
86
+ it('should show menu items when open', async () => {
87
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
88
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
89
+ trigger.click()
90
+ await sleepAsync(50)
91
+
92
+ const items = dropdown.querySelectorAll('[role="menuitem"]')
93
+ expect(items.length).toBe(3)
94
+ expect(dropdown.textContent).toContain('Cut')
95
+ expect(dropdown.textContent).toContain('Copy')
96
+ expect(dropdown.textContent).toContain('Paste')
97
+ })
98
+ })
99
+
100
+ it('should show dividers when open', async () => {
101
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
102
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
103
+ trigger.click()
104
+ await sleepAsync(50)
105
+
106
+ const dividers = dropdown.querySelectorAll('[role="separator"]')
107
+ expect(dividers.length).toBe(1)
108
+ })
109
+ })
110
+
111
+ it('should close when backdrop is clicked', async () => {
112
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
113
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
114
+ trigger.click()
115
+ await sleepAsync(50)
116
+
117
+ const backdrop = dropdown.querySelector('.dropdown-backdrop') as HTMLElement
118
+ backdrop.click()
119
+ await sleepAsync(50)
120
+
121
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
122
+ const panel = dropdown.querySelector('.dropdown-panel')
123
+ expect(panel?.classList.contains('visible')).toBe(false)
124
+ })
125
+ })
126
+
127
+ it('should toggle when trigger is clicked twice', async () => {
128
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
129
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
130
+ trigger.click()
131
+ await sleepAsync(50)
132
+ expect(dropdown.hasAttribute('data-open')).toBe(true)
133
+
134
+ trigger.click()
135
+ await sleepAsync(50)
136
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
137
+ })
138
+ })
139
+ })
140
+
141
+ describe('item selection', () => {
142
+ it('should call onSelect when an item is clicked', async () => {
143
+ const handleSelect = vi.fn()
144
+ await usingAsync(await renderDropdown({ onSelect: handleSelect }), async ({ dropdown }) => {
145
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
146
+ trigger.click()
147
+ await sleepAsync(50)
148
+
149
+ const item = dropdown.querySelector('[data-key="copy"]') as HTMLElement
150
+ item.click()
151
+ await sleepAsync(50)
152
+
153
+ expect(handleSelect).toHaveBeenCalledWith('copy')
154
+ })
155
+ })
156
+
157
+ it('should close after selection', async () => {
158
+ await usingAsync(await renderDropdown({ onSelect: vi.fn() }), async ({ dropdown }) => {
159
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
160
+ trigger.click()
161
+ await sleepAsync(50)
162
+
163
+ const item = dropdown.querySelector('[data-key="cut"]') as HTMLElement
164
+ item.click()
165
+ await sleepAsync(50)
166
+
167
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
168
+ const panel = dropdown.querySelector('.dropdown-panel')
169
+ expect(panel?.classList.contains('visible')).toBe(false)
170
+ })
171
+ })
172
+
173
+ it('should not call onSelect for disabled items', async () => {
174
+ const handleSelect = vi.fn()
175
+ const items: MenuEntry[] = [{ key: 'disabled', label: 'Disabled', disabled: true }]
176
+ await usingAsync(await renderDropdown({ items, onSelect: handleSelect }), async ({ dropdown }) => {
177
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
178
+ trigger.click()
179
+ await sleepAsync(50)
180
+
181
+ const item = dropdown.querySelector('[data-key="disabled"]') as HTMLElement
182
+ item.click()
183
+ await sleepAsync(50)
184
+
185
+ expect(handleSelect).not.toHaveBeenCalled()
186
+ })
187
+ })
188
+ })
189
+
190
+ describe('disabled state', () => {
191
+ it('should not open when disabled', async () => {
192
+ await usingAsync(await renderDropdown({ disabled: true }), async ({ dropdown }) => {
193
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
194
+ trigger.click()
195
+ await sleepAsync(50)
196
+
197
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
198
+ const panel = dropdown.querySelector('.dropdown-panel')
199
+ expect(panel?.classList.contains('visible')).toBe(false)
200
+ })
201
+ })
202
+
203
+ it('should mark trigger as disabled', async () => {
204
+ await usingAsync(await renderDropdown({ disabled: true }), async ({ dropdown }) => {
205
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
206
+ expect(trigger.classList.contains('disabled')).toBe(true)
207
+ })
208
+ })
209
+
210
+ it('should not mark trigger as disabled when not disabled', async () => {
211
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
212
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
213
+ expect(trigger.classList.contains('disabled')).toBe(false)
214
+ })
215
+ })
216
+ })
217
+
218
+ describe('groups', () => {
219
+ it('should render groups in dropdown', async () => {
220
+ const items: MenuEntry[] = [
221
+ {
222
+ type: 'group',
223
+ key: 'actions',
224
+ label: 'Actions',
225
+ children: [
226
+ { key: 'save', label: 'Save' },
227
+ { key: 'delete', label: 'Delete' },
228
+ ],
229
+ },
230
+ ]
231
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
232
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
233
+ trigger.click()
234
+ await sleepAsync(50)
235
+
236
+ const group = dropdown.querySelector('[role="group"]')
237
+ expect(group).toBeTruthy()
238
+
239
+ const menuItems = dropdown.querySelectorAll('[role="menuitem"]')
240
+ expect(menuItems.length).toBe(2)
241
+ })
242
+ })
243
+ })
244
+
245
+ describe('item icons', () => {
246
+ it('should render item icons', async () => {
247
+ const items: MenuEntry[] = [{ key: 'cut', label: 'Cut', icon: <span className="icon">✂️</span> }]
248
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
249
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
250
+ trigger.click()
251
+ await sleepAsync(50)
252
+
253
+ const icon = dropdown.querySelector('.dropdown-item-icon')
254
+ expect(icon).toBeTruthy()
255
+ expect(icon?.textContent).toContain('✂️')
256
+ })
257
+ })
258
+
259
+ it('should render JSX element icons', async () => {
260
+ const items: MenuEntry[] = [{ key: 'cut', label: 'Cut', icon: <span>X</span> }]
261
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
262
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
263
+ trigger.click()
264
+ await sleepAsync(50)
265
+
266
+ const icon = dropdown.querySelector('.dropdown-item-icon')
267
+ expect(icon).toBeTruthy()
268
+ expect(icon?.textContent).toContain('X')
269
+ })
270
+ })
271
+ })
272
+
273
+ describe('keyboard navigation', () => {
274
+ it('should close on Escape key', async () => {
275
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
276
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
277
+ trigger.click()
278
+ await sleepAsync(50)
279
+ expect(dropdown.hasAttribute('data-open')).toBe(true)
280
+
281
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
282
+ await sleepAsync(50)
283
+
284
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
285
+ })
286
+ })
287
+
288
+ it('should navigate to next item on ArrowDown', async () => {
289
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
290
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
291
+ trigger.click()
292
+ await sleepAsync(50)
293
+
294
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
295
+ await sleepAsync(50)
296
+
297
+ const focusedItems = dropdown.querySelectorAll('.dropdown-item.focused')
298
+ expect(focusedItems.length).toBe(1)
299
+ })
300
+ })
301
+
302
+ it('should navigate to previous item on ArrowUp', async () => {
303
+ await usingAsync(await renderDropdown({}), async ({ dropdown }) => {
304
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
305
+ trigger.click()
306
+ await sleepAsync(50)
307
+
308
+ // Move down twice then up once
309
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
310
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
311
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }))
312
+ await sleepAsync(50)
313
+
314
+ const focusedItems = dropdown.querySelectorAll('.dropdown-item.focused')
315
+ expect(focusedItems.length).toBe(1)
316
+ })
317
+ })
318
+
319
+ it('should select focused item on Enter', async () => {
320
+ const handleSelect = vi.fn()
321
+ await usingAsync(await renderDropdown({ onSelect: handleSelect }), async ({ dropdown }) => {
322
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
323
+ trigger.click()
324
+ await sleepAsync(50)
325
+
326
+ // Navigate down then press Enter
327
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
328
+ await sleepAsync(50)
329
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
330
+ await sleepAsync(50)
331
+
332
+ expect(handleSelect).toHaveBeenCalled()
333
+ })
334
+ })
335
+
336
+ it('should wrap around when navigating past the last item', async () => {
337
+ const items: MenuEntry[] = [
338
+ { key: 'a', label: 'A' },
339
+ { key: 'b', label: 'B' },
340
+ ]
341
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
342
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
343
+ trigger.click()
344
+ await sleepAsync(50)
345
+
346
+ // Navigate down past the end (2 items + 1 wrap)
347
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
348
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
349
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
350
+ await sleepAsync(50)
351
+
352
+ const focusedItems = dropdown.querySelectorAll('.dropdown-item.focused')
353
+ expect(focusedItems.length).toBe(1)
354
+ })
355
+ })
356
+
357
+ it('should wrap around when navigating before the first item', async () => {
358
+ const items: MenuEntry[] = [
359
+ { key: 'a', label: 'A' },
360
+ { key: 'b', label: 'B' },
361
+ ]
362
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
363
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
364
+ trigger.click()
365
+ await sleepAsync(50)
366
+
367
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', bubbles: true }))
368
+ await sleepAsync(50)
369
+
370
+ const focusedItems = dropdown.querySelectorAll('.dropdown-item.focused')
371
+ expect(focusedItems.length).toBe(1)
372
+ })
373
+ })
374
+
375
+ it('should not respond to keyboard when closed', async () => {
376
+ const handleSelect = vi.fn()
377
+ await usingAsync(await renderDropdown({ onSelect: handleSelect }), async ({ dropdown }) => {
378
+ // Don't open the dropdown
379
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
380
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }))
381
+ await sleepAsync(50)
382
+
383
+ expect(handleSelect).not.toHaveBeenCalled()
384
+ expect(dropdown.hasAttribute('data-open')).toBe(false)
385
+ })
386
+ })
387
+
388
+ it('should skip disabled items during navigation', async () => {
389
+ const items: MenuEntry[] = [
390
+ { key: 'a', label: 'A' },
391
+ { key: 'b', label: 'B', disabled: true },
392
+ { key: 'c', label: 'C' },
393
+ ]
394
+ await usingAsync(await renderDropdown({ items }), async ({ dropdown }) => {
395
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
396
+ trigger.click()
397
+ await sleepAsync(50)
398
+
399
+ // Navigate to first enabled item
400
+ window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }))
401
+ await sleepAsync(50)
402
+
403
+ const focusedItems = dropdown.querySelectorAll('.dropdown-item.focused')
404
+ expect(focusedItems.length).toBe(1)
405
+ // Focused item should not be the disabled one
406
+ expect(focusedItems[0].classList.contains('disabled')).toBe(false)
407
+ })
408
+ })
409
+ })
410
+
411
+ describe('placement', () => {
412
+ it('should accept bottomRight placement', async () => {
413
+ await usingAsync(await renderDropdown({ placement: 'bottomRight' }), async ({ dropdown }) => {
414
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
415
+ trigger.click()
416
+ await sleepAsync(50)
417
+
418
+ const panel = dropdown.querySelector('.dropdown-panel')
419
+ expect(panel).toBeTruthy()
420
+ })
421
+ })
422
+
423
+ it('should accept topLeft placement', async () => {
424
+ await usingAsync(await renderDropdown({ placement: 'topLeft' }), async ({ dropdown }) => {
425
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
426
+ trigger.click()
427
+ await sleepAsync(50)
428
+
429
+ const panel = dropdown.querySelector('.dropdown-panel')
430
+ expect(panel).toBeTruthy()
431
+ })
432
+ })
433
+
434
+ it('should accept topRight placement', async () => {
435
+ await usingAsync(await renderDropdown({ placement: 'topRight' }), async ({ dropdown }) => {
436
+ const trigger = dropdown.querySelector('.dropdown-trigger') as HTMLElement
437
+ trigger.click()
438
+ await sleepAsync(50)
439
+
440
+ const panel = dropdown.querySelector('.dropdown-panel')
441
+ expect(panel).toBeTruthy()
442
+ })
443
+ })
444
+ })
445
+ })