@getmicdrop/svelte-components 5.10.3 → 5.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/dist/calendar/AboutShow/AboutShow.svelte +172 -172
  2. package/dist/calendar/Calendar/MiniMonthCalendar.svelte +782 -782
  3. package/dist/calendar/FAQs/FAQs.svelte +75 -75
  4. package/dist/calendar/MonthSwitcher/MonthSwitcher.svelte +126 -126
  5. package/dist/calendar/OrderSummary/OrderSummary.svelte +367 -367
  6. package/dist/calendar/PublicCard/PublicCard.svelte +146 -146
  7. package/dist/calendar/ShowCard/ShowCard.svelte +157 -157
  8. package/dist/calendar/ShowTimeCard/ShowTimeCard.svelte +61 -61
  9. package/dist/components/Heading.svelte +60 -60
  10. package/dist/components/Layout/AppShell.svelte +104 -104
  11. package/dist/components/Layout/ContentSection.svelte +80 -80
  12. package/dist/components/Layout/Grid.svelte +4 -4
  13. package/dist/components/Layout/Heading.svelte +81 -81
  14. package/dist/components/Layout/PageContainer.svelte +69 -69
  15. package/dist/components/Layout/Responsive.svelte +75 -75
  16. package/dist/components/Layout/Section.svelte +80 -80
  17. package/dist/components/Layout/ShowOnDesktop.svelte +37 -37
  18. package/dist/components/Layout/ShowOnMobile.svelte +37 -37
  19. package/dist/components/Layout/Sidebar.svelte +108 -108
  20. package/dist/components/Layout/Stack.spec.js +1 -1
  21. package/dist/components/Layout/Stack.svelte +6 -6
  22. package/dist/components/Layout/Text.svelte +87 -87
  23. package/dist/components/Layout/TwoColumn.svelte +108 -108
  24. package/dist/components/Text.svelte +53 -53
  25. package/dist/constants/validation.js +91 -91
  26. package/dist/constants/validation.spec.js +64 -64
  27. package/dist/datetime/__tests__/format.test.js +1 -1
  28. package/dist/datetime/__tests__/parse.test.js +1 -1
  29. package/dist/datetime/__tests__/timezone.test.js +1 -1
  30. package/dist/datetime/parse.js +1 -1
  31. package/dist/forms/createFormStore.svelte.js +0 -1
  32. package/dist/index.d.ts +2 -0
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +57 -51
  35. package/dist/index.spec.js +0 -1
  36. package/dist/patterns/data/DataGrid.svelte +45 -45
  37. package/dist/patterns/data/DataList.svelte +24 -24
  38. package/dist/patterns/data/DataTable.svelte +36 -36
  39. package/dist/patterns/forms/FormActions.spec.js +95 -95
  40. package/dist/patterns/forms/FormActions.stories.svelte +97 -97
  41. package/dist/patterns/forms/FormActions.svelte +46 -46
  42. package/dist/patterns/forms/FormGrid.svelte +33 -33
  43. package/dist/patterns/forms/FormSection.svelte +32 -32
  44. package/dist/patterns/forms/FormValidationSummary.stories.svelte +83 -83
  45. package/dist/patterns/forms/FormValidationSummary.svelte +74 -74
  46. package/dist/patterns/layout/Sidebar.svelte +39 -39
  47. package/dist/patterns/layout/index.js +29 -29
  48. package/dist/patterns/navigation/BottomNav.stories.svelte +117 -117
  49. package/dist/patterns/navigation/BottomNav.svelte +74 -74
  50. package/dist/patterns/navigation/Header.stories.svelte +77 -77
  51. package/dist/patterns/navigation/Header.svelte +251 -255
  52. package/dist/patterns/navigation/Header.svelte.d.ts.map +1 -1
  53. package/dist/patterns/page/PageHeader.svelte +18 -18
  54. package/dist/patterns/page/PageLayout.svelte +40 -40
  55. package/dist/patterns/page/PageLoader.spec.js +57 -57
  56. package/dist/patterns/page/PageLoader.stories.svelte +137 -137
  57. package/dist/patterns/page/PageLoader.svelte +24 -24
  58. package/dist/patterns/page/SectionHeader.svelte +29 -29
  59. package/dist/presets/badges.js +112 -112
  60. package/dist/presets/buttons.js +76 -76
  61. package/dist/presets/index.js +9 -9
  62. package/dist/primitives/Accordion/Accordion.stories.svelte +75 -75
  63. package/dist/primitives/Accordion/Accordion.svelte +42 -42
  64. package/dist/primitives/Accordion/AccordionItem.svelte +95 -95
  65. package/dist/primitives/Alert/Alert.spec.js +173 -173
  66. package/dist/primitives/Alert/Alert.stories.svelte +88 -88
  67. package/dist/primitives/Alert/Alert.svelte +27 -27
  68. package/dist/primitives/Avatar/Avatar.stories.svelte +94 -94
  69. package/dist/primitives/Avatar/Avatar.svelte +66 -66
  70. package/dist/primitives/AvatarButton/AvatarButton.svelte +57 -0
  71. package/dist/primitives/AvatarButton/AvatarButton.svelte.d.ts +18 -0
  72. package/dist/primitives/AvatarButton/AvatarButton.svelte.d.ts.map +1 -0
  73. package/dist/primitives/Badges/Badge.spec.js +144 -144
  74. package/dist/primitives/Badges/Badge.stories.svelte +86 -86
  75. package/dist/primitives/Badges/Badge.svelte +99 -99
  76. package/dist/primitives/BottomSheet/BottomSheet.spec.js +136 -136
  77. package/dist/primitives/BottomSheet/BottomSheet.stories.svelte +83 -83
  78. package/dist/primitives/BottomSheet/BottomSheet.svelte +100 -100
  79. package/dist/primitives/BottomSheet/BottomSheet.svelte.d.ts +2 -2
  80. package/dist/primitives/BottomSheet/BottomSheet.svelte.d.ts.map +1 -1
  81. package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte +3 -3
  82. package/dist/primitives/BottomSheet/BottomSheetWrapper.test.svelte.d.ts +1 -1
  83. package/dist/primitives/Breadcrumb/Breadcrumb.spec.js +123 -122
  84. package/dist/primitives/Breadcrumb/Breadcrumb.stories.svelte +23 -23
  85. package/dist/primitives/Breadcrumb/Breadcrumb.svelte +99 -98
  86. package/dist/primitives/Button/Button.spec.js +223 -223
  87. package/dist/primitives/Button/Button.stories.svelte +76 -76
  88. package/dist/primitives/Button/Button.svelte +278 -283
  89. package/dist/primitives/Button/Button.svelte.d.ts +2 -0
  90. package/dist/primitives/Button/Button.svelte.d.ts.map +1 -1
  91. package/dist/primitives/Button/ButtonGroup.svelte +50 -50
  92. package/dist/primitives/Button/ButtonSaveDemo.spec.js +146 -146
  93. package/dist/primitives/Button/ButtonSaveDemo.svelte +25 -25
  94. package/dist/primitives/Button/ButtonVariantShowcase.svelte +129 -129
  95. package/dist/primitives/Card.spec.js +49 -49
  96. package/dist/primitives/Card.stories.svelte +22 -22
  97. package/dist/primitives/Card.svelte +28 -28
  98. package/dist/primitives/CardAction/CardAction.svelte +68 -0
  99. package/dist/primitives/CardAction/CardAction.svelte.d.ts +20 -0
  100. package/dist/primitives/CardAction/CardAction.svelte.d.ts.map +1 -0
  101. package/dist/primitives/Checkbox/Checkbox.stories.svelte +84 -84
  102. package/dist/primitives/Checkbox/Checkbox.svelte +88 -88
  103. package/dist/primitives/DarkModeToggle.spec.js +390 -390
  104. package/dist/primitives/DarkModeToggle.stories.svelte +57 -57
  105. package/dist/primitives/DarkModeToggle.svelte +136 -136
  106. package/dist/primitives/Drawer/Drawer.spec.js +33 -33
  107. package/dist/primitives/Drawer/Drawer.stories.svelte +80 -80
  108. package/dist/primitives/Drawer/Drawer.svelte +123 -127
  109. package/dist/primitives/Drawer/Drawer.svelte.d.ts +2 -3
  110. package/dist/primitives/Drawer/Drawer.svelte.d.ts.map +1 -1
  111. package/dist/primitives/Dropdown/Dropdown.stories.svelte +137 -137
  112. package/dist/primitives/Dropdown/Dropdown.svelte +170 -170
  113. package/dist/primitives/Dropdown/DropdownDivider.svelte +9 -9
  114. package/dist/primitives/Dropdown/DropdownItem.svelte +80 -80
  115. package/dist/primitives/Helper/Helper.svelte +33 -33
  116. package/dist/primitives/Icons/ArrowLeft.svelte +8 -8
  117. package/dist/primitives/Icons/ArrowRight.svelte +8 -8
  118. package/dist/primitives/Icons/Availability.svelte +14 -14
  119. package/dist/primitives/Icons/Back.svelte +14 -14
  120. package/dist/primitives/Icons/CheckCircle.svelte +6 -6
  121. package/dist/primitives/Icons/CheckCircleOutline.svelte +15 -15
  122. package/dist/primitives/Icons/ChevronLeft.svelte +4 -4
  123. package/dist/primitives/Icons/ChevronRight.svelte +4 -4
  124. package/dist/primitives/Icons/Copy.svelte +15 -15
  125. package/dist/primitives/Icons/Cross.svelte +5 -5
  126. package/dist/primitives/Icons/DownArrow.svelte +8 -8
  127. package/dist/primitives/Icons/ErrorCircle.svelte +6 -6
  128. package/dist/primitives/Icons/FacebookIcon.svelte +2 -2
  129. package/dist/primitives/Icons/Home.svelte +15 -15
  130. package/dist/primitives/Icons/Icon.spec.js +169 -169
  131. package/dist/primitives/Icons/Icon.stories.svelte +100 -100
  132. package/dist/primitives/Icons/Icon.svelte +52 -52
  133. package/dist/primitives/Icons/IconGallery.stories.svelte +235 -235
  134. package/dist/primitives/Icons/Info.svelte +7 -7
  135. package/dist/primitives/Icons/InstagramIcon.svelte +4 -4
  136. package/dist/primitives/Icons/LogoInstagram.svelte +2 -2
  137. package/dist/primitives/Icons/Message.svelte +15 -15
  138. package/dist/primitives/Icons/MoonIcon.svelte +5 -5
  139. package/dist/primitives/Icons/More.svelte +21 -21
  140. package/dist/primitives/Icons/MoreHori.spec.js +61 -61
  141. package/dist/primitives/Icons/MoreHori.svelte +22 -22
  142. package/dist/primitives/Icons/Notification.svelte +14 -14
  143. package/dist/primitives/Icons/Payment.svelte +14 -14
  144. package/dist/primitives/Icons/Profile.svelte +21 -21
  145. package/dist/primitives/Icons/Reload.svelte +29 -29
  146. package/dist/primitives/Icons/Shows.svelte +21 -21
  147. package/dist/primitives/Icons/Signout.svelte +21 -21
  148. package/dist/primitives/Icons/SunIcon.svelte +8 -8
  149. package/dist/primitives/Icons/TiktokIcon.svelte +2 -2
  150. package/dist/primitives/Icons/TwitterIcon.svelte +2 -2
  151. package/dist/primitives/Icons/WarningIcon.spec.js +18 -18
  152. package/dist/primitives/Icons/WarningIcon.svelte +5 -5
  153. package/dist/primitives/Input/Input.spec.js +573 -573
  154. package/dist/primitives/Input/Input.stories.svelte +139 -139
  155. package/dist/primitives/Input/Input.svelte +423 -423
  156. package/dist/primitives/Input/Select.spec.js +218 -218
  157. package/dist/primitives/Input/Select.stories.svelte +112 -112
  158. package/dist/primitives/Input/Select.svelte +252 -252
  159. package/dist/primitives/Input/Textarea.stories.svelte +137 -137
  160. package/dist/primitives/Input/Textarea.svelte +105 -105
  161. package/dist/primitives/Label/Label.svelte +37 -37
  162. package/dist/primitives/LandingButton/LandingButton.svelte +92 -0
  163. package/dist/primitives/LandingButton/LandingButton.svelte.d.ts +22 -0
  164. package/dist/primitives/LandingButton/LandingButton.svelte.d.ts.map +1 -0
  165. package/dist/primitives/MenuItem/MenuItem.svelte +85 -0
  166. package/dist/primitives/MenuItem/MenuItem.svelte.d.ts +24 -0
  167. package/dist/primitives/MenuItem/MenuItem.svelte.d.ts.map +1 -0
  168. package/dist/primitives/Modal/Modal.spec.js +99 -99
  169. package/dist/primitives/Modal/Modal.stories.svelte +86 -86
  170. package/dist/primitives/Modal/Modal.svelte +181 -157
  171. package/dist/primitives/Modal/Modal.svelte.d.ts +7 -5
  172. package/dist/primitives/Modal/Modal.svelte.d.ts.map +1 -1
  173. package/dist/primitives/Modal/ModalTestWrapper.svelte +3 -3
  174. package/dist/primitives/Modal/ModalTestWrapper.svelte.d.ts +2 -2
  175. package/dist/primitives/NavItem/NavItem.svelte +75 -0
  176. package/dist/primitives/NavItem/NavItem.svelte.d.ts +20 -0
  177. package/dist/primitives/NavItem/NavItem.svelte.d.ts.map +1 -0
  178. package/dist/primitives/Pagination/Pagination.stories.svelte +76 -76
  179. package/dist/primitives/Pagination/Pagination.svelte +261 -261
  180. package/dist/primitives/Radio/Radio.stories.svelte +80 -80
  181. package/dist/primitives/Radio/Radio.svelte +67 -67
  182. package/dist/primitives/SearchResultItem/SearchResultItem.svelte +109 -0
  183. package/dist/primitives/SearchResultItem/SearchResultItem.svelte.d.ts +26 -0
  184. package/dist/primitives/SearchResultItem/SearchResultItem.svelte.d.ts.map +1 -0
  185. package/dist/primitives/SidebarToggle/SidebarToggle.svelte +55 -0
  186. package/dist/primitives/SidebarToggle/SidebarToggle.svelte.d.ts +18 -0
  187. package/dist/primitives/SidebarToggle/SidebarToggle.svelte.d.ts.map +1 -0
  188. package/dist/primitives/Skeleton/CardPlaceholder.svelte +87 -87
  189. package/dist/primitives/Skeleton/ImagePlaceholder.svelte +59 -59
  190. package/dist/primitives/Skeleton/ListPlaceholder.svelte +76 -76
  191. package/dist/primitives/Skeleton/Skeleton.stories.svelte +151 -151
  192. package/dist/primitives/Skeleton/Skeleton.svelte +26 -26
  193. package/dist/primitives/Spinner/Spinner.spec.js +71 -71
  194. package/dist/primitives/Spinner/Spinner.stories.svelte +29 -29
  195. package/dist/primitives/Spinner/Spinner.svelte +20 -20
  196. package/dist/primitives/Tabs/TabItem.svelte +49 -49
  197. package/dist/primitives/Tabs/Tabs.stories.svelte +112 -112
  198. package/dist/primitives/Tabs/Tabs.svelte +137 -137
  199. package/dist/primitives/Toggle.spec.js +146 -146
  200. package/dist/primitives/Toggle.stories.svelte +92 -92
  201. package/dist/primitives/Toggle.svelte +141 -131
  202. package/dist/primitives/Toggle.svelte.d.ts +2 -0
  203. package/dist/primitives/Toggle.svelte.d.ts.map +1 -1
  204. package/dist/primitives/Tooltip/Tooltip.svelte +83 -83
  205. package/dist/primitives/Typography/Typography.svelte +53 -53
  206. package/dist/primitives/ValidationError.spec.js +103 -103
  207. package/dist/primitives/ValidationError.stories.svelte +69 -69
  208. package/dist/primitives/ValidationError.svelte +29 -29
  209. package/dist/primitives/index.d.ts +7 -0
  210. package/dist/primitives/index.js +113 -92
  211. package/dist/recipes/CropImage/CropImage.spec.js +208 -208
  212. package/dist/recipes/CropImage/CropImage.stories.svelte +104 -104
  213. package/dist/recipes/CropImage/CropImage.svelte +219 -219
  214. package/dist/recipes/ImageUploader/ImageUploader.stories.svelte +125 -125
  215. package/dist/recipes/ImageUploader/ImageUploader.svelte +970 -970
  216. package/dist/recipes/SuperLogin/SuperLogin.svelte +3 -3
  217. package/dist/recipes/SuperLogin/SuperLogin.svelte.d.ts.map +1 -1
  218. package/dist/recipes/Toaster/Toaster.stories.svelte +62 -62
  219. package/dist/recipes/feedback/EmptyState/EmptyState.svelte +1 -1
  220. package/dist/recipes/feedback/ErrorDisplay.spec.js +69 -69
  221. package/dist/recipes/feedback/ErrorDisplay.stories.svelte +101 -101
  222. package/dist/recipes/feedback/ErrorDisplay.svelte +1 -1
  223. package/dist/recipes/feedback/StatusIndicator/StatusIndicator.spec.js +133 -133
  224. package/dist/recipes/feedback/StatusIndicator/StatusIndicator.svelte +157 -157
  225. package/dist/recipes/fields/CheckboxField.svelte +85 -85
  226. package/dist/recipes/fields/FormField.svelte +58 -58
  227. package/dist/recipes/fields/RadioGroup.svelte +95 -95
  228. package/dist/recipes/fields/SelectField.svelte +80 -80
  229. package/dist/recipes/fields/TextareaField.svelte +97 -97
  230. package/dist/recipes/fields/ToggleField.svelte +60 -60
  231. package/dist/recipes/fields/index.js +7 -7
  232. package/dist/recipes/inputs/MultiSelect.spec.js +260 -260
  233. package/dist/recipes/inputs/MultiSelect.stories.svelte +133 -133
  234. package/dist/recipes/inputs/MultiSelect.svelte +283 -283
  235. package/dist/recipes/inputs/OTPInput.spec.js +251 -251
  236. package/dist/recipes/inputs/OTPInput.stories.svelte +162 -162
  237. package/dist/recipes/inputs/OTPInput.svelte +117 -117
  238. package/dist/recipes/inputs/PasswordInput.svelte +22 -22
  239. package/dist/recipes/inputs/PasswordStrengthIndicator/PasswordStrengthIndicator.svelte +131 -131
  240. package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.stories.svelte +123 -123
  241. package/dist/recipes/inputs/PlaceAutocomplete/PlaceAutocomplete.svelte +344 -344
  242. package/dist/recipes/inputs/Search.svelte +102 -102
  243. package/dist/recipes/inputs/index.d.ts +0 -1
  244. package/dist/recipes/inputs/index.js +0 -1
  245. package/dist/recipes/modals/AlertModal.spec.js +2 -2
  246. package/dist/recipes/modals/AlertModal.svelte +130 -130
  247. package/dist/recipes/modals/AlertModal.svelte.d.ts +3 -3
  248. package/dist/recipes/modals/ConfirmationModal.spec.js +206 -206
  249. package/dist/recipes/modals/ConfirmationModal.stories.svelte +119 -119
  250. package/dist/recipes/modals/ConfirmationModal.svelte +162 -152
  251. package/dist/recipes/modals/ConfirmationModal.svelte.d.ts +5 -3
  252. package/dist/recipes/modals/ConfirmationModal.svelte.d.ts.map +1 -1
  253. package/dist/recipes/modals/InputModal.spec.js +2 -2
  254. package/dist/recipes/modals/InputModal.svelte +182 -182
  255. package/dist/recipes/modals/InputModal.svelte.d.ts +3 -3
  256. package/dist/recipes/modals/ModalStateManager.spec.js +100 -100
  257. package/dist/recipes/modals/ModalStateManager.svelte +77 -77
  258. package/dist/recipes/modals/ModalTestWrapper.spec.js +49 -49
  259. package/dist/recipes/modals/ModalTestWrapper.svelte +65 -65
  260. package/dist/recipes/modals/ModalTestWrapper.svelte.d.ts +2 -2
  261. package/dist/recipes/modals/StatusModal.spec.js +2 -2
  262. package/dist/recipes/modals/StatusModal.svelte +206 -206
  263. package/dist/recipes/modals/StatusModal.svelte.d.ts +3 -3
  264. package/dist/services/EventService.js +75 -75
  265. package/dist/services/EventService.spec.js +217 -217
  266. package/dist/services/ShowService.spec.js +345 -345
  267. package/dist/stores/toaster.js +13 -13
  268. package/dist/stories/ButtonAuditReview.stories.svelte +14 -14
  269. package/dist/stories/ButtonAuditReview.svelte +427 -427
  270. package/dist/stories/ComponentConsolidation.stories.svelte +10 -10
  271. package/dist/stories/PatternsGallery.stories.svelte +19 -19
  272. package/dist/stories/PatternsGallery.svelte +206 -206
  273. package/dist/stories/PrimitivesGallery.stories.svelte +19 -19
  274. package/dist/stories/PrimitivesGallery.svelte +756 -752
  275. package/dist/stories/PrimitivesGallery.svelte.d.ts.map +1 -1
  276. package/dist/stories/RecipesGallery.spec.js +9 -18
  277. package/dist/stories/RecipesGallery.stories.svelte +19 -19
  278. package/dist/stories/RecipesGallery.svelte +454 -471
  279. package/dist/stories/RecipesGallery.svelte.d.ts.map +1 -1
  280. package/dist/stories/button-audit-manifest.json +11186 -11186
  281. package/dist/tailwind/preset.cjs +82 -82
  282. package/dist/telemetry.js +405 -405
  283. package/dist/telemetry.spec.js +1169 -1169
  284. package/dist/tokens/tokens.css +87 -87
  285. package/dist/tokens/typography-base.css +163 -163
  286. package/dist/tokens/utilities.css +353 -353
  287. package/dist/utils/apiConfig.spec.js +219 -219
  288. package/dist/utils/haptic.d.ts +41 -0
  289. package/dist/utils/haptic.d.ts.map +1 -0
  290. package/dist/utils/haptic.js +115 -0
  291. package/dist/utils/transitions.js +4 -4
  292. package/dist/utils/utils.js +693 -693
  293. package/package.json +297 -297
  294. package/dist/recipes/inputs/SelectDropdown.spec.d.ts +0 -2
  295. package/dist/recipes/inputs/SelectDropdown.spec.d.ts.map +0 -1
  296. package/dist/recipes/inputs/SelectDropdown.spec.js +0 -518
  297. package/dist/recipes/inputs/SelectDropdown.svelte +0 -171
  298. package/dist/recipes/inputs/SelectDropdown.svelte.d.ts +0 -16
  299. package/dist/recipes/inputs/SelectDropdown.svelte.d.ts.map +0 -1
@@ -1,260 +1,260 @@
1
- import { render, screen, fireEvent } from "@testing-library/svelte";
2
- import userEvent from "@testing-library/user-event";
3
- import { expect, describe, test, vi } from "vitest";
4
- import MultiSelect from "./MultiSelect.svelte";
5
-
6
- // Mock transitions to be instant for testing
7
- vi.mock('../../utils/transitions.js', () => ({
8
- bloom: () => ({ duration: 0, delay: 0, css: () => '' }),
9
- safeSlide: () => ({ duration: 0, delay: 0, css: () => '' }),
10
- }));
11
-
12
- const sampleItems = [
13
- { name: "Option 1", value: "opt1" },
14
- { name: "Option 2", value: "opt2" },
15
- { name: "Option 3", value: "opt3" },
16
- { name: "Option 4", value: "opt4" },
17
- ];
18
-
19
- function setupTest(args = {}) {
20
- const user = userEvent.setup();
21
- const { component } = render(MultiSelect, {
22
- props: {
23
- items: sampleItems,
24
- ...args,
25
- },
26
- });
27
- return { user, component };
28
- }
29
-
30
- describe("MultiSelect Component Tests", () => {
31
- test("Renders multiselect with label", () => {
32
- setupTest({
33
- label: "Test Label",
34
- id: "test-multiselect",
35
- });
36
- expect(screen.getByText("Test Label")).toBeInTheDocument();
37
- });
38
-
39
- test("Shows placeholder when no value selected", () => {
40
- setupTest({
41
- placeholder: "Select options",
42
- });
43
- expect(screen.getByText("Select options")).toBeInTheDocument();
44
- });
45
-
46
- test("Opens dropdown on click", async () => {
47
- const { user } = setupTest();
48
- const trigger = screen.getByRole("combobox");
49
-
50
- await user.click(trigger);
51
-
52
- expect(screen.getByRole("listbox")).toBeInTheDocument();
53
- expect(screen.getByText("Option 1")).toBeInTheDocument();
54
- expect(screen.getByText("Option 2")).toBeInTheDocument();
55
- });
56
-
57
- test("Selects multiple items", async () => {
58
- const { user } = setupTest();
59
- const trigger = screen.getByRole("combobox");
60
-
61
- await user.click(trigger);
62
- // Click on options in dropdown
63
- const options = screen.getAllByRole("option");
64
- await user.click(options[0]); // Option 1
65
- await user.click(options[2]); // Option 3
66
-
67
- // Both tags should be visible (may have duplicates due to dropdown still open)
68
- expect(screen.getAllByText("Option 1").length).toBeGreaterThanOrEqual(1);
69
- expect(screen.getAllByText("Option 3").length).toBeGreaterThanOrEqual(1);
70
- });
71
-
72
- test("Dropdown stays open after selection", async () => {
73
- const { user } = setupTest();
74
- const trigger = screen.getByRole("combobox");
75
-
76
- await user.click(trigger);
77
- await user.click(screen.getByText("Option 1"));
78
-
79
- // Dropdown should still be open for multi-select
80
- expect(screen.getByRole("listbox")).toBeInTheDocument();
81
- });
82
-
83
- test("Shows selected values as tags", () => {
84
- setupTest({
85
- value: ["opt1", "opt2"],
86
- });
87
- expect(screen.getByText("Option 1")).toBeInTheDocument();
88
- expect(screen.getByText("Option 2")).toBeInTheDocument();
89
- });
90
-
91
- test("Removes item when clicking tag remove button", async () => {
92
- const { user } = setupTest({
93
- value: ["opt1", "opt2"],
94
- });
95
-
96
- // Find the remove button for Option 1
97
- const removeButtons = screen.getAllByRole("button", { name: /remove/i });
98
- await user.click(removeButtons[0]);
99
-
100
- // Option 1 should be removed, Option 2 should remain
101
- expect(screen.queryByText("Option 1")).not.toBeInTheDocument();
102
- expect(screen.getByText("Option 2")).toBeInTheDocument();
103
- });
104
-
105
- test("Clears all selections when clicking clear button", async () => {
106
- const { user } = setupTest({
107
- value: ["opt1", "opt2", "opt3"],
108
- });
109
-
110
- const clearButton = screen.getByRole("button", { name: /clear all/i });
111
- await user.click(clearButton);
112
-
113
- expect(screen.getByText("Select options")).toBeInTheDocument();
114
- expect(screen.queryByText("Option 1")).not.toBeInTheDocument();
115
- });
116
-
117
- test("Hides clear button when hideClear is true", () => {
118
- setupTest({
119
- value: ["opt1"],
120
- hideClear: true,
121
- });
122
- expect(screen.queryByRole("button", { name: /clear all/i })).not.toBeInTheDocument();
123
- });
124
-
125
- test("Dispatches change event on selection", async () => {
126
- const changeSpy = vi.fn();
127
- const { user } = setupTest({
128
- onchange: changeSpy,
129
- });
130
-
131
- const trigger = screen.getByRole("combobox");
132
- await user.click(trigger);
133
- await user.click(screen.getByText("Option 2"));
134
-
135
- expect(changeSpy).toHaveBeenCalled();
136
- expect(changeSpy.mock.calls[0][0].value).toContain("opt2");
137
- });
138
-
139
- test("Shows required indicator when required", () => {
140
- setupTest({
141
- label: "Required Field",
142
- required: true,
143
- });
144
- expect(screen.getByText("*")).toBeInTheDocument();
145
- });
146
-
147
- test("Displays error state", () => {
148
- setupTest({
149
- error: "Please select at least one option",
150
- });
151
- expect(screen.getByText("Please select at least one option")).toBeInTheDocument();
152
- });
153
-
154
- test("Disables multiselect when disabled prop is true", async () => {
155
- const { user } = setupTest({
156
- disabled: true,
157
- });
158
- const trigger = screen.getByRole("combobox");
159
-
160
- expect(trigger).toHaveAttribute("aria-disabled", "true");
161
- await user.click(trigger);
162
- expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
163
- });
164
-
165
- test("Navigates options with keyboard", async () => {
166
- const { user } = setupTest();
167
- const trigger = screen.getByRole("combobox");
168
-
169
- await user.click(trigger);
170
- await user.keyboard("{ArrowDown}");
171
- await user.keyboard("{Enter}");
172
-
173
- // First option should be selected
174
- expect(screen.getByText("Option 1")).toBeInTheDocument();
175
- });
176
-
177
- test("Closes dropdown on Escape key", async () => {
178
- const { user } = setupTest();
179
- const trigger = screen.getByRole("combobox");
180
-
181
- await user.click(trigger);
182
- expect(screen.getByRole("listbox")).toBeInTheDocument();
183
-
184
- await user.keyboard("{Escape}");
185
- expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
186
- });
187
-
188
- test("Toggles item off when clicking selected item", async () => {
189
- const { user } = setupTest({
190
- value: ["opt1"],
191
- });
192
- const trigger = screen.getByRole("combobox");
193
-
194
- await user.click(trigger);
195
-
196
- // Click Option 1 to deselect it
197
- const option1 = screen.getByRole("option", { name: /option 1/i });
198
- await user.click(option1);
199
-
200
- // Should show placeholder now
201
- expect(screen.getByText("Select options")).toBeInTheDocument();
202
- });
203
-
204
- test("Applies animate focus class by default", () => {
205
- setupTest();
206
- const trigger = screen.getByRole("combobox");
207
- expect(trigger).toHaveClass("multiselect-animate-focus");
208
- });
209
-
210
- test("Does not apply animate focus when disabled", () => {
211
- setupTest({
212
- animateFocus: false,
213
- });
214
- const trigger = screen.getByRole("combobox");
215
- expect(trigger).not.toHaveClass("multiselect-animate-focus");
216
- });
217
-
218
- test("Shows checkbox for each option", async () => {
219
- const { user } = setupTest();
220
- const trigger = screen.getByRole("combobox");
221
-
222
- await user.click(trigger);
223
-
224
- // Each option should have a checkbox element
225
- const options = screen.getAllByRole("option");
226
- options.forEach(option => {
227
- expect(option.querySelector(".multiselect-checkbox")).toBeInTheDocument();
228
- });
229
- });
230
-
231
- test("Shows checked checkbox for selected items", async () => {
232
- const { user } = setupTest({
233
- value: ["opt1"],
234
- });
235
- const trigger = screen.getByRole("combobox");
236
-
237
- await user.click(trigger);
238
-
239
- const selectedOption = screen.getByRole("option", { name: /option 1/i });
240
- expect(selectedOption.querySelector(".multiselect-checkbox-checked")).toBeInTheDocument();
241
- });
242
-
243
- test("Sets aria-multiselectable on listbox", async () => {
244
- const { user } = setupTest();
245
- const trigger = screen.getByRole("combobox");
246
-
247
- await user.click(trigger);
248
-
249
- const listbox = screen.getByRole("listbox");
250
- expect(listbox).toHaveAttribute("aria-multiselectable", "true");
251
- });
252
-
253
- test("Initializes empty value as array", () => {
254
- setupTest({
255
- value: null,
256
- });
257
- // Should not crash and show placeholder
258
- expect(screen.getByText("Select options")).toBeInTheDocument();
259
- });
260
- });
1
+ import { render, screen, fireEvent } from "@testing-library/svelte";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { expect, describe, test, vi } from "vitest";
4
+ import MultiSelect from "./MultiSelect.svelte";
5
+
6
+ // Mock transitions to be instant for testing
7
+ vi.mock('../../utils/transitions.js', () => ({
8
+ bloom: () => ({ duration: 0, delay: 0, css: () => '' }),
9
+ safeSlide: () => ({ duration: 0, delay: 0, css: () => '' }),
10
+ }));
11
+
12
+ const sampleItems = [
13
+ { name: "Option 1", value: "opt1" },
14
+ { name: "Option 2", value: "opt2" },
15
+ { name: "Option 3", value: "opt3" },
16
+ { name: "Option 4", value: "opt4" },
17
+ ];
18
+
19
+ function setupTest(args = {}) {
20
+ const user = userEvent.setup();
21
+ const { component } = render(MultiSelect, {
22
+ props: {
23
+ items: sampleItems,
24
+ ...args,
25
+ },
26
+ });
27
+ return { user, component };
28
+ }
29
+
30
+ describe("MultiSelect Component Tests", () => {
31
+ test("Renders multiselect with label", () => {
32
+ setupTest({
33
+ label: "Test Label",
34
+ id: "test-multiselect",
35
+ });
36
+ expect(screen.getByText("Test Label")).toBeInTheDocument();
37
+ });
38
+
39
+ test("Shows placeholder when no value selected", () => {
40
+ setupTest({
41
+ placeholder: "Select options",
42
+ });
43
+ expect(screen.getByText("Select options")).toBeInTheDocument();
44
+ });
45
+
46
+ test("Opens dropdown on click", async () => {
47
+ const { user } = setupTest();
48
+ const trigger = screen.getByRole("combobox");
49
+
50
+ await user.click(trigger);
51
+
52
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
53
+ expect(screen.getByText("Option 1")).toBeInTheDocument();
54
+ expect(screen.getByText("Option 2")).toBeInTheDocument();
55
+ });
56
+
57
+ test("Selects multiple items", async () => {
58
+ const { user } = setupTest();
59
+ const trigger = screen.getByRole("combobox");
60
+
61
+ await user.click(trigger);
62
+ // Click on options in dropdown
63
+ const options = screen.getAllByRole("option");
64
+ await user.click(options[0]); // Option 1
65
+ await user.click(options[2]); // Option 3
66
+
67
+ // Both tags should be visible (may have duplicates due to dropdown still open)
68
+ expect(screen.getAllByText("Option 1").length).toBeGreaterThanOrEqual(1);
69
+ expect(screen.getAllByText("Option 3").length).toBeGreaterThanOrEqual(1);
70
+ });
71
+
72
+ test("Dropdown stays open after selection", async () => {
73
+ const { user } = setupTest();
74
+ const trigger = screen.getByRole("combobox");
75
+
76
+ await user.click(trigger);
77
+ await user.click(screen.getByText("Option 1"));
78
+
79
+ // Dropdown should still be open for multi-select
80
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
81
+ });
82
+
83
+ test("Shows selected values as tags", () => {
84
+ setupTest({
85
+ value: ["opt1", "opt2"],
86
+ });
87
+ expect(screen.getByText("Option 1")).toBeInTheDocument();
88
+ expect(screen.getByText("Option 2")).toBeInTheDocument();
89
+ });
90
+
91
+ test("Removes item when clicking tag remove button", async () => {
92
+ const { user } = setupTest({
93
+ value: ["opt1", "opt2"],
94
+ });
95
+
96
+ // Find the remove button for Option 1
97
+ const removeButtons = screen.getAllByRole("button", { name: /remove/i });
98
+ await user.click(removeButtons[0]);
99
+
100
+ // Option 1 should be removed, Option 2 should remain
101
+ expect(screen.queryByText("Option 1")).not.toBeInTheDocument();
102
+ expect(screen.getByText("Option 2")).toBeInTheDocument();
103
+ });
104
+
105
+ test("Clears all selections when clicking clear button", async () => {
106
+ const { user } = setupTest({
107
+ value: ["opt1", "opt2", "opt3"],
108
+ });
109
+
110
+ const clearButton = screen.getByRole("button", { name: /clear all/i });
111
+ await user.click(clearButton);
112
+
113
+ expect(screen.getByText("Select options")).toBeInTheDocument();
114
+ expect(screen.queryByText("Option 1")).not.toBeInTheDocument();
115
+ });
116
+
117
+ test("Hides clear button when hideClear is true", () => {
118
+ setupTest({
119
+ value: ["opt1"],
120
+ hideClear: true,
121
+ });
122
+ expect(screen.queryByRole("button", { name: /clear all/i })).not.toBeInTheDocument();
123
+ });
124
+
125
+ test("Dispatches change event on selection", async () => {
126
+ const changeSpy = vi.fn();
127
+ const { user } = setupTest({
128
+ onchange: changeSpy,
129
+ });
130
+
131
+ const trigger = screen.getByRole("combobox");
132
+ await user.click(trigger);
133
+ await user.click(screen.getByText("Option 2"));
134
+
135
+ expect(changeSpy).toHaveBeenCalled();
136
+ expect(changeSpy.mock.calls[0][0].value).toContain("opt2");
137
+ });
138
+
139
+ test("Shows required indicator when required", () => {
140
+ setupTest({
141
+ label: "Required Field",
142
+ required: true,
143
+ });
144
+ expect(screen.getByText("*")).toBeInTheDocument();
145
+ });
146
+
147
+ test("Displays error state", () => {
148
+ setupTest({
149
+ error: "Please select at least one option",
150
+ });
151
+ expect(screen.getByText("Please select at least one option")).toBeInTheDocument();
152
+ });
153
+
154
+ test("Disables multiselect when disabled prop is true", async () => {
155
+ const { user } = setupTest({
156
+ disabled: true,
157
+ });
158
+ const trigger = screen.getByRole("combobox");
159
+
160
+ expect(trigger).toHaveAttribute("aria-disabled", "true");
161
+ await user.click(trigger);
162
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
163
+ });
164
+
165
+ test("Navigates options with keyboard", async () => {
166
+ const { user } = setupTest();
167
+ const trigger = screen.getByRole("combobox");
168
+
169
+ await user.click(trigger);
170
+ await user.keyboard("{ArrowDown}");
171
+ await user.keyboard("{Enter}");
172
+
173
+ // First option should be selected
174
+ expect(screen.getByText("Option 1")).toBeInTheDocument();
175
+ });
176
+
177
+ test("Closes dropdown on Escape key", async () => {
178
+ const { user } = setupTest();
179
+ const trigger = screen.getByRole("combobox");
180
+
181
+ await user.click(trigger);
182
+ expect(screen.getByRole("listbox")).toBeInTheDocument();
183
+
184
+ await user.keyboard("{Escape}");
185
+ expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
186
+ });
187
+
188
+ test("Toggles item off when clicking selected item", async () => {
189
+ const { user } = setupTest({
190
+ value: ["opt1"],
191
+ });
192
+ const trigger = screen.getByRole("combobox");
193
+
194
+ await user.click(trigger);
195
+
196
+ // Click Option 1 to deselect it
197
+ const option1 = screen.getByRole("option", { name: /option 1/i });
198
+ await user.click(option1);
199
+
200
+ // Should show placeholder now
201
+ expect(screen.getByText("Select options")).toBeInTheDocument();
202
+ });
203
+
204
+ test("Applies animate focus class by default", () => {
205
+ setupTest();
206
+ const trigger = screen.getByRole("combobox");
207
+ expect(trigger).toHaveClass("multiselect-animate-focus");
208
+ });
209
+
210
+ test("Does not apply animate focus when disabled", () => {
211
+ setupTest({
212
+ animateFocus: false,
213
+ });
214
+ const trigger = screen.getByRole("combobox");
215
+ expect(trigger).not.toHaveClass("multiselect-animate-focus");
216
+ });
217
+
218
+ test("Shows checkbox for each option", async () => {
219
+ const { user } = setupTest();
220
+ const trigger = screen.getByRole("combobox");
221
+
222
+ await user.click(trigger);
223
+
224
+ // Each option should have a checkbox element
225
+ const options = screen.getAllByRole("option");
226
+ options.forEach(option => {
227
+ expect(option.querySelector(".multiselect-checkbox")).toBeInTheDocument();
228
+ });
229
+ });
230
+
231
+ test("Shows checked checkbox for selected items", async () => {
232
+ const { user } = setupTest({
233
+ value: ["opt1"],
234
+ });
235
+ const trigger = screen.getByRole("combobox");
236
+
237
+ await user.click(trigger);
238
+
239
+ const selectedOption = screen.getByRole("option", { name: /option 1/i });
240
+ expect(selectedOption.querySelector(".multiselect-checkbox-checked")).toBeInTheDocument();
241
+ });
242
+
243
+ test("Sets aria-multiselectable on listbox", async () => {
244
+ const { user } = setupTest();
245
+ const trigger = screen.getByRole("combobox");
246
+
247
+ await user.click(trigger);
248
+
249
+ const listbox = screen.getByRole("listbox");
250
+ expect(listbox).toHaveAttribute("aria-multiselectable", "true");
251
+ });
252
+
253
+ test("Initializes empty value as array", () => {
254
+ setupTest({
255
+ value: null,
256
+ });
257
+ // Should not crash and show placeholder
258
+ expect(screen.getByText("Select options")).toBeInTheDocument();
259
+ });
260
+ });