@spectral_labs/ui 1.6.1 → 1.8.0-next.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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/THIRD_PARTY_NOTICES.md +201 -0
  3. package/dist/components/command/command.svelte.d.ts +30 -0
  4. package/dist/components/command/command.svelte.d.ts.map +1 -1
  5. package/dist/components/command/command.svelte.js +85 -4
  6. package/dist/components/command/components/command-group.svelte +25 -15
  7. package/dist/components/command/components/command-group.svelte.d.ts.map +1 -1
  8. package/dist/components/command/components/command-input.svelte +54 -5
  9. package/dist/components/command/components/command-input.svelte.d.ts +1 -1
  10. package/dist/components/command/components/command-input.svelte.d.ts.map +1 -1
  11. package/dist/components/command/components/command-list.svelte +22 -3
  12. package/dist/components/command/components/command-list.svelte.d.ts.map +1 -1
  13. package/dist/components/command/components/command-root.svelte +43 -4
  14. package/dist/components/command/components/command-root.svelte.d.ts.map +1 -1
  15. package/dist/components/command/index.d.ts +1 -0
  16. package/dist/components/command/index.d.ts.map +1 -1
  17. package/dist/components/command/types.d.ts +59 -4
  18. package/dist/components/command/types.d.ts.map +1 -1
  19. package/package.json +8 -2
  20. package/dist/components/__tests__/overlay-scrim-source.test.js +0 -134
  21. package/dist/components/accordion/__tests__/AccordionTest.svelte +0 -31
  22. package/dist/components/accordion/__tests__/accordion.test.svelte.js +0 -139
  23. package/dist/components/alert-dialog/__tests__/AlertDialogTest.svelte +0 -28
  24. package/dist/components/alert-dialog/__tests__/alert-dialog.a11y.test.js +0 -42
  25. package/dist/components/alert-dialog/__tests__/alert-dialog.integration.test.svelte.js +0 -51
  26. package/dist/components/alert-dialog/__tests__/alert-dialog.test.svelte.js +0 -113
  27. package/dist/components/app-bar/__tests__/app-bar.test.svelte.js +0 -30
  28. package/dist/components/aspect-ratio/__tests__/aspect-ratio.test.svelte.js +0 -22
  29. package/dist/components/avatar/__tests__/avatar.test.svelte.js +0 -26
  30. package/dist/components/badge/__tests__/badge.test.svelte.js +0 -30
  31. package/dist/components/bottom-sheet/__tests__/BottomSheetTest.svelte +0 -22
  32. package/dist/components/bottom-sheet/__tests__/bottom-sheet.test.svelte.js +0 -83
  33. package/dist/components/button/__tests__/button.test.svelte.js +0 -63
  34. package/dist/components/calendar/__tests__/CalendarTest.svelte +0 -56
  35. package/dist/components/calendar/__tests__/calendar.test.svelte.js +0 -190
  36. package/dist/components/card/__tests__/card.test.svelte.js +0 -30
  37. package/dist/components/checkbox/__tests__/checkbox.test.svelte.js +0 -44
  38. package/dist/components/chips/__tests__/chips.test.svelte.js +0 -26
  39. package/dist/components/collapsible/__tests__/CollapsibleTest.svelte +0 -18
  40. package/dist/components/collapsible/__tests__/collapsible.test.svelte.js +0 -125
  41. package/dist/components/combobox/__tests__/ComboboxTest.svelte +0 -40
  42. package/dist/components/combobox/__tests__/combobox.test.svelte.js +0 -255
  43. package/dist/components/command/__tests__/CommandTest.svelte +0 -77
  44. package/dist/components/command/__tests__/command-item-passthrough.test.svelte.js +0 -284
  45. package/dist/components/command/__tests__/command.a11y.test.js +0 -30
  46. package/dist/components/command/__tests__/command.integration.test.svelte.js +0 -68
  47. package/dist/components/command/__tests__/command.test.svelte.js +0 -230
  48. package/dist/components/context-menu/__tests__/ContextMenuNonInteractiveTest.svelte +0 -32
  49. package/dist/components/context-menu/__tests__/ContextMenuTest.svelte +0 -25
  50. package/dist/components/context-menu/__tests__/context-menu.test.svelte.js +0 -141
  51. package/dist/components/date-field/__tests__/DateFieldTest.svelte +0 -20
  52. package/dist/components/date-field/__tests__/date-field.test.svelte.js +0 -139
  53. package/dist/components/date-picker/__tests__/DatePickerTest.svelte +0 -20
  54. package/dist/components/date-picker/__tests__/date-picker.test.svelte.js +0 -190
  55. package/dist/components/date-range-field/__tests__/DateRangeFieldTest.svelte +0 -20
  56. package/dist/components/date-range-field/__tests__/date-range-field.test.svelte.js +0 -130
  57. package/dist/components/date-range-picker/__tests__/DateRangePickerTest.svelte +0 -18
  58. package/dist/components/date-range-picker/__tests__/date-range-picker.test.svelte.js +0 -156
  59. package/dist/components/dialog/__tests__/DialogTest.svelte +0 -34
  60. package/dist/components/dialog/__tests__/dialog.test.svelte.js +0 -184
  61. package/dist/components/drop-zone/__tests__/drop-zone.test.svelte.js +0 -26
  62. package/dist/components/dropdown-menu/__tests__/DropdownMenuRadioTest.svelte +0 -90
  63. package/dist/components/dropdown-menu/__tests__/DropdownMenuTest.svelte +0 -71
  64. package/dist/components/dropdown-menu/__tests__/dropdown-menu-radio-group.test.svelte.js +0 -306
  65. package/dist/components/dropdown-menu/__tests__/dropdown-menu.test.svelte.js +0 -567
  66. package/dist/components/empty-state/__tests__/empty-state.test.svelte.js +0 -26
  67. package/dist/components/fab/__tests__/fab.test.svelte.js +0 -30
  68. package/dist/components/field/__tests__/FieldTest.svelte +0 -26
  69. package/dist/components/field/__tests__/field.test.svelte.js +0 -74
  70. package/dist/components/grid-list/__tests__/GridListTest.svelte +0 -46
  71. package/dist/components/grid-list/__tests__/grid-list.test.svelte.js +0 -231
  72. package/dist/components/hover-card/__tests__/HoverCardTest.svelte +0 -30
  73. package/dist/components/hover-card/__tests__/hover-card.test.svelte.js +0 -236
  74. package/dist/components/indicator/__tests__/indicator.test.svelte.js +0 -30
  75. package/dist/components/input/__tests__/input.test.svelte.js +0 -67
  76. package/dist/components/label/__tests__/label.test.svelte.js +0 -22
  77. package/dist/components/language-select/__tests__/language-select.test.svelte.js +0 -199
  78. package/dist/components/language-select/__tests__/languages.test.js +0 -87
  79. package/dist/components/link-preview/__tests__/LinkPreviewTest.svelte +0 -37
  80. package/dist/components/link-preview/__tests__/link-preview.a11y.test.js +0 -28
  81. package/dist/components/link-preview/__tests__/link-preview.integration.test.svelte.js +0 -54
  82. package/dist/components/link-preview/__tests__/link-preview.test.svelte.js +0 -215
  83. package/dist/components/list/__tests__/list.test.svelte.js +0 -22
  84. package/dist/components/menubar/__tests__/MenubarTest.svelte +0 -52
  85. package/dist/components/menubar/__tests__/menubar.a11y.test.js +0 -28
  86. package/dist/components/menubar/__tests__/menubar.integration.test.svelte.js +0 -57
  87. package/dist/components/menubar/__tests__/menubar.test.svelte.js +0 -328
  88. package/dist/components/meter/__tests__/meter.test.svelte.js +0 -26
  89. package/dist/components/nav-bar/__tests__/nav-bar.test.svelte.js +0 -23
  90. package/dist/components/nav-drawer/__tests__/nav-drawer.test.svelte.js +0 -28
  91. package/dist/components/nav-rail/__tests__/nav-rail.test.svelte.js +0 -28
  92. package/dist/components/pagination/__tests__/pagination.test.svelte.js +0 -26
  93. package/dist/components/pin-input/__tests__/pin-input.test.svelte.js +0 -71
  94. package/dist/components/popover/__tests__/PopoverTest.svelte +0 -27
  95. package/dist/components/popover/__tests__/popover.test.svelte.js +0 -196
  96. package/dist/components/progress/__tests__/progress.test.svelte.js +0 -32
  97. package/dist/components/radio-group/__tests__/radio-group.test.svelte.js +0 -22
  98. package/dist/components/range-calendar/__tests__/RangeCalendarTest.svelte +0 -23
  99. package/dist/components/range-calendar/__tests__/range-calendar.test.svelte.js +0 -105
  100. package/dist/components/rating-group/__tests__/rating-group.test.svelte.js +0 -26
  101. package/dist/components/scroll-area/__tests__/scroll-area.test.svelte.js +0 -34
  102. package/dist/components/search-field/__tests__/SearchFieldTest.svelte +0 -34
  103. package/dist/components/search-field/__tests__/search-field.test.svelte.js +0 -118
  104. package/dist/components/select/__tests__/SelectLabelPersistenceTest.svelte +0 -31
  105. package/dist/components/select/__tests__/SelectTest.svelte +0 -33
  106. package/dist/components/select/__tests__/select.test.svelte.js +0 -221
  107. package/dist/components/separator/__tests__/separator.test.svelte.js +0 -39
  108. package/dist/components/sheet/__tests__/SheetTest.svelte +0 -34
  109. package/dist/components/sheet/__tests__/sheet.test.svelte.js +0 -193
  110. package/dist/components/side-sheet/__tests__/side-sheet.test.svelte.js +0 -138
  111. package/dist/components/sidebar/__tests__/SidebarFullTest.svelte +0 -45
  112. package/dist/components/sidebar/__tests__/SidebarTest.svelte +0 -9
  113. package/dist/components/sidebar/__tests__/sidebar.test.svelte.js +0 -186
  114. package/dist/components/simple-dialog/__tests__/SimpleDialogTest.svelte +0 -40
  115. package/dist/components/simple-dialog/__tests__/simple-dialog.test.svelte.js +0 -50
  116. package/dist/components/simple-tooltip/__tests__/SimpleTooltipTest.svelte +0 -19
  117. package/dist/components/simple-tooltip/__tests__/simple-tooltip.test.svelte.js +0 -61
  118. package/dist/components/slider/__tests__/slider.test.svelte.js +0 -42
  119. package/dist/components/sortable-list/__tests__/NestedSortableListTest.svelte +0 -49
  120. package/dist/components/sortable-list/__tests__/SortableListTest.svelte +0 -42
  121. package/dist/components/sortable-list/__tests__/sortable-list.nested.test.svelte.js +0 -112
  122. package/dist/components/sortable-list/__tests__/sortable-list.test.svelte.js +0 -175
  123. package/dist/components/splitter/__tests__/splitter.test.svelte.js +0 -26
  124. package/dist/components/switch/__tests__/switch.test.svelte.js +0 -44
  125. package/dist/components/table/__tests__/table.test.svelte.js +0 -22
  126. package/dist/components/tabs/__tests__/TabsTest.svelte +0 -32
  127. package/dist/components/tabs/__tests__/tabs.test.svelte.js +0 -227
  128. package/dist/components/textarea/__tests__/textarea.test.svelte.js +0 -55
  129. package/dist/components/time-field/__tests__/TimeFieldTest.svelte +0 -20
  130. package/dist/components/time-field/__tests__/time-field.test.svelte.js +0 -100
  131. package/dist/components/time-range-field/__tests__/TimeRangeFieldTest.svelte +0 -20
  132. package/dist/components/time-range-field/__tests__/time-range-field.test.svelte.js +0 -124
  133. package/dist/components/toast/__tests__/toast.test.svelte.js +0 -46
  134. package/dist/components/toggle/__tests__/toggle.test.svelte.js +0 -38
  135. package/dist/components/toggle-group/__tests__/toggle-group.test.svelte.js +0 -22
  136. package/dist/components/toolbar/__tests__/ToolbarCompositionTest.svelte +0 -18
  137. package/dist/components/toolbar/__tests__/ToolbarTabstopTest.svelte +0 -10
  138. package/dist/components/toolbar/__tests__/toolbar.test.svelte.js +0 -63
  139. package/dist/components/tooltip/__tests__/TooltipTest.svelte +0 -22
  140. package/dist/components/tooltip/__tests__/tooltip.test.svelte.js +0 -225
  141. package/dist/components/tree/__tests__/TreeLabelContentTest.svelte +0 -21
  142. package/dist/components/tree/__tests__/TreeTest.svelte +0 -24
  143. package/dist/components/tree/__tests__/tree.test.svelte.js +0 -229
  144. package/dist/components/virtualizer/__tests__/waterfall-layout.test.js +0 -82
  145. package/dist/internal/announcer/__tests__/announcer.test.js +0 -42
  146. package/dist/internal/dismissible-layer/__tests__/dismissible-layer.test.js +0 -196
  147. package/dist/internal/drag-drop/__tests__/auto-scroll.test.js +0 -104
  148. package/dist/internal/drag-drop/__tests__/drag-session.test.svelte.js +0 -803
  149. package/dist/internal/drag-drop/__tests__/drag-source.test.svelte.js +0 -130
  150. package/dist/internal/drag-drop/__tests__/drop-delegate.test.js +0 -223
  151. package/dist/internal/drag-drop/__tests__/types.test.js +0 -20
  152. package/dist/internal/escape-layer/__tests__/escape-layer.test.js +0 -113
  153. package/dist/internal/focus-scope/__tests__/focus-scope.test.js +0 -225
  154. package/dist/internal/grace-area/__tests__/grace-area.test.js +0 -67
  155. package/dist/internal/helpers/__tests__/helpers.test.js +0 -123
  156. package/dist/internal/portal/__tests__/PortalTest.svelte +0 -21
  157. package/dist/internal/portal/__tests__/portal.test.js +0 -29
  158. package/dist/internal/portal/__tests__/portal.test.svelte.js +0 -57
  159. package/dist/internal/scroll-lock/__tests__/scroll-lock.test.js +0 -160
  160. package/dist/internal/typeahead/__tests__/typeahead.test.js +0 -61
  161. package/src/themes/__tests__/carbon-dark-contrast.test.ts +0 -170
  162. package/src/themes/__tests__/generated-css-drift.test.ts +0 -53
  163. package/src/themes/__tests__/scrim-opaque.test.ts +0 -52
@@ -1,190 +0,0 @@
1
- import { CalendarDate } from '@internationalized/date';
2
- import { flushSync, mount, unmount } from 'svelte';
3
- import { afterEach, describe, expect, it } from 'vitest';
4
- import CalendarTest from './CalendarTest.svelte';
5
- // Polyfill PointerEvent for jsdom
6
- if (typeof globalThis.PointerEvent === 'undefined') {
7
- // @ts-expect-error — minimal polyfill for testing
8
- globalThis.PointerEvent = class PointerEvent extends MouseEvent {
9
- constructor(type, init) {
10
- super(type, init);
11
- }
12
- };
13
- }
14
- // April 2026 fixture: Mon 13 Apr 2026
15
- const APRIL_13 = new CalendarDate(2026, 4, 13);
16
- describe('calendar', () => {
17
- let target;
18
- let instance;
19
- function setup(props = {}) {
20
- target = document.createElement('div');
21
- document.body.appendChild(target);
22
- instance = mount(CalendarTest, { target, props });
23
- flushSync();
24
- }
25
- afterEach(() => {
26
- if (instance)
27
- unmount(instance);
28
- instance = undefined;
29
- target?.remove();
30
- });
31
- // ── Smoke (3) ──────────────────────────────────────────────────────────────
32
- it('renders root group element', () => {
33
- setup({ placeholder: APRIL_13 });
34
- // Root renders as role="group"
35
- expect(target.querySelector('[role="group"].sp-calendar')).toBeTruthy();
36
- });
37
- it('heading shows current month and year', () => {
38
- setup({ placeholder: APRIL_13 });
39
- const text = target.textContent ?? '';
40
- // Should contain April and 2026
41
- expect(text).toMatch(/April|Apr/i);
42
- expect(text).toMatch(/2026/);
43
- });
44
- it('renders day cells inside role="grid"', () => {
45
- setup({ placeholder: APRIL_13 });
46
- const grid = target.querySelector('[role="grid"]');
47
- expect(grid).toBeTruthy();
48
- // April 2026 has 30 days; with weekStartsOn=1 we get ~5 rows of 7
49
- const cells = target.querySelectorAll('[role="gridcell"]');
50
- expect(cells.length).toBeGreaterThan(20);
51
- });
52
- // ── Value binding (2) ──────────────────────────────────────────────────────
53
- it('marks selected cell when value is pre-set', () => {
54
- setup({ value: APRIL_13 });
55
- // data-selected is set on both <td> and <button> when selected
56
- const selectedCell = target.querySelector('[role="gridcell"][data-selected]');
57
- expect(selectedCell).toBeTruthy();
58
- });
59
- it('clicking an unselected day cell selects it', () => {
60
- setup({ placeholder: APRIL_13 });
61
- // No selection yet
62
- expect(target.querySelector('[data-selected]')).toBeNull();
63
- // Click first enabled button
64
- const btn = target.querySelector('[role="gridcell"]:not([data-disabled]) button:not([disabled])');
65
- btn?.click();
66
- flushSync();
67
- expect(target.querySelector('[data-selected]')).toBeTruthy();
68
- });
69
- // ── Navigation (2) ────────────────────────────────────────────────────────
70
- it('next button advances to following month', () => {
71
- setup({ placeholder: APRIL_13 });
72
- const textBefore = target.textContent ?? '';
73
- const nextBtn = target.querySelector('button[aria-label="Next"]');
74
- expect(nextBtn).toBeTruthy();
75
- nextBtn?.click();
76
- flushSync();
77
- const textAfter = target.textContent ?? '';
78
- expect(textAfter).not.toBe(textBefore);
79
- // Should now show May 2026
80
- expect(textAfter).toMatch(/May|2026/);
81
- });
82
- it('prev button goes back to previous month', () => {
83
- setup({ placeholder: APRIL_13 });
84
- const prevBtn = target.querySelector('button[aria-label="Previous"]');
85
- expect(prevBtn).toBeTruthy();
86
- prevBtn?.click();
87
- flushSync();
88
- const textAfter = target.textContent ?? '';
89
- // Should now show March 2026
90
- expect(textAfter).toMatch(/March|Mar/);
91
- expect(textAfter).toMatch(/2026/);
92
- });
93
- // ── Disabled (2) ──────────────────────────────────────────────────────────
94
- it('disabled calendar does not allow value change on click', () => {
95
- setup({ disabled: true, placeholder: APRIL_13 });
96
- const root = target.querySelector('[role="group"]');
97
- expect(root?.getAttribute('data-disabled')).toBe('true');
98
- // Click a cell button — should not change selection
99
- const btn = target.querySelector('button.sp-calendar-day');
100
- btn?.click();
101
- flushSync();
102
- expect(target.querySelector('[data-selected]')).toBeNull();
103
- });
104
- it('readonly calendar does not allow value change on click', () => {
105
- setup({ readonly: true, placeholder: APRIL_13 });
106
- const root = target.querySelector('[role="group"]');
107
- expect(root?.getAttribute('data-readonly')).toBe('true');
108
- const btn = target.querySelector('[role="gridcell"]:not([data-disabled]) button:not([disabled])');
109
- btn?.click();
110
- flushSync();
111
- expect(target.querySelector('[data-selected]')).toBeNull();
112
- });
113
- // ── Date constraints (2) ──────────────────────────────────────────────────
114
- it('disables cells outside [minValue, maxValue] range', () => {
115
- setup({
116
- placeholder: APRIL_13,
117
- minValue: new CalendarDate(2026, 4, 10),
118
- maxValue: new CalendarDate(2026, 4, 20),
119
- });
120
- // Cells before Apr 10 and after Apr 20 should be disabled
121
- const disabledCells = target.querySelectorAll('[role="gridcell"][data-disabled]');
122
- expect(disabledCells.length).toBeGreaterThan(0);
123
- });
124
- it('prev button is disabled when already at minValue month', () => {
125
- setup({
126
- placeholder: APRIL_13,
127
- minValue: new CalendarDate(2026, 4, 1),
128
- maxValue: new CalendarDate(2026, 6, 30),
129
- });
130
- const prevBtn = target.querySelector('button[aria-label="Previous"]');
131
- // March is before the April minValue month, so prev is disabled
132
- expect(prevBtn?.disabled).toBe(true);
133
- });
134
- // ── Locale + multi-month (2) ───────────────────────────────────────────────
135
- it('renders calendar with weekStartsOn=0 (Sunday-first)', () => {
136
- setup({ placeholder: APRIL_13, weekStartsOn: 0 });
137
- // Should still render a grid
138
- expect(target.querySelector('[role="grid"]')).toBeTruthy();
139
- // 7 weekday header cells
140
- const headCells = target.querySelectorAll('th.sp-calendar-head-cell');
141
- expect(headCells.length).toBe(7);
142
- });
143
- it('renders two grids when numberOfMonths=2', () => {
144
- setup({ placeholder: APRIL_13, numberOfMonths: 2 });
145
- // CalendarTest renders one Grid per month index
146
- const grids = target.querySelectorAll('[role="grid"]');
147
- expect(grids.length).toBeGreaterThanOrEqual(2);
148
- // Heading should span April – May 2026
149
- const text = target.textContent ?? '';
150
- expect(text).toMatch(/April|Apr/);
151
- expect(text).toMatch(/May/);
152
- });
153
- // ── Deselect (2) ──────────────────────────────────────────────────────────
154
- it('clicking selected cell deselects it by default', () => {
155
- setup({ value: APRIL_13 });
156
- // Confirm selection
157
- expect(target.querySelector('[data-selected]')).toBeTruthy();
158
- // Click the selected day button
159
- const selectedBtn = target.querySelector('button[data-selected]');
160
- selectedBtn?.click();
161
- flushSync();
162
- // Should be deselected
163
- expect(target.querySelector('[data-selected]')).toBeNull();
164
- });
165
- it('preventDeselect=true keeps selection when re-clicking selected cell', () => {
166
- setup({ value: APRIL_13, preventDeselect: true });
167
- expect(target.querySelector('[data-selected]')).toBeTruthy();
168
- const selectedBtn = target.querySelector('button[data-selected]');
169
- selectedBtn?.click();
170
- flushSync();
171
- // Still selected
172
- expect(target.querySelector('[data-selected]')).toBeTruthy();
173
- });
174
- // ── ARIA (2) ──────────────────────────────────────────────────────────────
175
- it('grid table has role="grid"', () => {
176
- setup({ placeholder: APRIL_13 });
177
- const grid = target.querySelector('[role="grid"]');
178
- expect(grid).toBeTruthy();
179
- expect(grid?.tagName.toLowerCase()).toBe('table');
180
- });
181
- it('root group has descriptive aria-label including calendar label and heading', () => {
182
- setup({ placeholder: APRIL_13 });
183
- const root = target.querySelector('[role="group"]');
184
- expect(root).toBeTruthy();
185
- const label = root?.getAttribute('aria-label') ?? '';
186
- // Default calendarLabel="Calendar", heading includes "April 2026"
187
- expect(label).toMatch(/Calendar/i);
188
- expect(label).toMatch(/April|2026/);
189
- });
190
- });
@@ -1,30 +0,0 @@
1
- import { mount, unmount } from 'svelte';
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import Card from '../card.svelte';
4
- describe('card', () => {
5
- let target;
6
- let instance;
7
- function setup(props = {}) {
8
- target = document.createElement('div');
9
- document.body.appendChild(target);
10
- instance = mount(Card, { target, props });
11
- return target;
12
- }
13
- afterEach(() => {
14
- if (instance)
15
- unmount(instance);
16
- target?.remove();
17
- });
18
- it('renders div', () => {
19
- setup();
20
- expect(target.querySelector('.sp-card')).toBeTruthy();
21
- });
22
- it('applies variant', () => {
23
- setup({ variant: 'outlined' });
24
- expect(target.querySelector('.sp-card')?.className.includes('outlined')).toBeTruthy();
25
- });
26
- it('applies padding', () => {
27
- setup({ padding: 'lg' });
28
- expect(target.querySelector('.sp-card')?.className.includes('pad-lg')).toBeTruthy();
29
- });
30
- });
@@ -1,44 +0,0 @@
1
- import { mount, unmount } from 'svelte';
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import Checkbox from '../checkbox.svelte';
4
- describe('checkbox', () => {
5
- let target;
6
- let instance;
7
- function setup(props = {}) {
8
- target = document.createElement('div');
9
- document.body.appendChild(target);
10
- instance = mount(Checkbox, { target, props });
11
- return target;
12
- }
13
- afterEach(() => {
14
- if (instance)
15
- unmount(instance);
16
- target?.remove();
17
- });
18
- it('renders with role="checkbox"', () => {
19
- setup();
20
- expect(target.querySelector('[role="checkbox"]')).toBeTruthy();
21
- });
22
- it('has aria-checked="false" by default', () => {
23
- setup();
24
- expect(target.querySelector('[role="checkbox"]')?.getAttribute('aria-checked')).toBe('false');
25
- });
26
- it('has aria-checked="true" when checked', () => {
27
- setup({ checked: true });
28
- expect(target.querySelector('[role="checkbox"]')?.getAttribute('aria-checked')).toBe('true');
29
- });
30
- it('has aria-checked="mixed" when indeterminate', () => {
31
- setup({ checked: 'indeterminate' });
32
- expect(target.querySelector('[role="checkbox"]')?.getAttribute('aria-checked')).toBe('mixed');
33
- });
34
- it('renders disabled', () => {
35
- setup({ disabled: true });
36
- expect(target.querySelector('[role="checkbox"]')?.hasAttribute('disabled')).toBe(true);
37
- });
38
- it('generates hidden input when name is provided', () => {
39
- setup({ name: 'agree', checked: true, value: 'yes' });
40
- const hidden = target.querySelector('input[type="hidden"]');
41
- expect(hidden).toBeTruthy();
42
- expect(hidden.name).toBe('agree');
43
- });
44
- });
@@ -1,26 +0,0 @@
1
- import { mount, unmount } from 'svelte';
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import Chip from '../chips.svelte';
4
- describe('chips', () => {
5
- let target;
6
- let instance;
7
- function setup(props = {}) {
8
- target = document.createElement('div');
9
- document.body.appendChild(target);
10
- instance = mount(Chip, { target, props });
11
- return target;
12
- }
13
- afterEach(() => {
14
- if (instance)
15
- unmount(instance);
16
- target?.remove();
17
- });
18
- it('renders button', () => {
19
- setup();
20
- expect(target.querySelector('button')).toBeTruthy();
21
- });
22
- it('applies variant', () => {
23
- setup({ variant: 'filter' });
24
- expect(target.querySelector('[data-variant="filter"]')).toBeTruthy();
25
- });
26
- });
@@ -1,18 +0,0 @@
1
- <script lang="ts">
2
- import CollapsibleContent from '../components/collapsible-content.svelte'
3
- import CollapsibleRoot from '../components/collapsible-root.svelte'
4
- import CollapsibleTrigger from '../components/collapsible-trigger.svelte'
5
-
6
- let {
7
- open = $bindable(false),
8
- disabled = false,
9
- }: {
10
- open?: boolean
11
- disabled?: boolean
12
- } = $props()
13
- </script>
14
-
15
- <CollapsibleRoot bind:open {disabled}>
16
- <CollapsibleTrigger>Toggle</CollapsibleTrigger>
17
- <CollapsibleContent>Collapsible content here</CollapsibleContent>
18
- </CollapsibleRoot>
@@ -1,125 +0,0 @@
1
- import { flushSync, mount, unmount } from 'svelte';
2
- import { afterEach, describe, expect, it } from 'vitest';
3
- import CollapsibleRoot from '../components/collapsible-root.svelte';
4
- import CollapsibleTest from './CollapsibleTest.svelte';
5
- describe('collapsible', () => {
6
- let target;
7
- let instance;
8
- function setup(props = {}) {
9
- target = document.createElement('div');
10
- document.body.appendChild(target);
11
- instance = mount(CollapsibleTest, { target, props });
12
- return target;
13
- }
14
- function setupRoot(props = {}) {
15
- target = document.createElement('div');
16
- document.body.appendChild(target);
17
- instance = mount(CollapsibleRoot, { target, props });
18
- return target;
19
- }
20
- afterEach(() => {
21
- if (instance)
22
- unmount(instance);
23
- target?.remove();
24
- });
25
- // --- Basic rendering ---
26
- it('renders container', () => {
27
- setupRoot();
28
- expect(target.querySelector('.sp-collapsible')).toBeTruthy();
29
- });
30
- it('renders trigger button', () => {
31
- setup();
32
- const trigger = target.querySelector('.sp-collapsible-trigger');
33
- expect(trigger).toBeTruthy();
34
- expect(trigger?.tagName).toBe('BUTTON');
35
- });
36
- // --- ARIA attributes ---
37
- it('trigger has aria-expanded="false" when closed', () => {
38
- setup({ open: false });
39
- const trigger = target.querySelector('.sp-collapsible-trigger');
40
- expect(trigger?.getAttribute('aria-expanded')).toBe('false');
41
- });
42
- it('trigger has aria-expanded="true" when open', () => {
43
- setup({ open: true });
44
- const trigger = target.querySelector('.sp-collapsible-trigger');
45
- expect(trigger?.getAttribute('aria-expanded')).toBe('true');
46
- });
47
- it('content has role="region"', () => {
48
- setup({ open: true });
49
- const content = target.querySelector('.sp-collapsible-content');
50
- expect(content?.getAttribute('role')).toBe('region');
51
- });
52
- // --- Data-state attributes ---
53
- it('root has data-state="closed" when closed', () => {
54
- setup({ open: false });
55
- const root = target.querySelector('.sp-collapsible');
56
- expect(root?.getAttribute('data-state')).toBe('closed');
57
- });
58
- it('root has data-state="open" when open', () => {
59
- setup({ open: true });
60
- const root = target.querySelector('.sp-collapsible');
61
- expect(root?.getAttribute('data-state')).toBe('open');
62
- });
63
- it('trigger has data-state matching open/closed', () => {
64
- setup({ open: true });
65
- const trigger = target.querySelector('.sp-collapsible-trigger');
66
- expect(trigger?.getAttribute('data-state')).toBe('open');
67
- });
68
- // --- Toggle behavior ---
69
- it('clicking trigger opens content', () => {
70
- setup({ open: false });
71
- const trigger = target.querySelector('.sp-collapsible-trigger');
72
- expect(target.querySelector('.sp-collapsible-content')).toBeNull();
73
- trigger.click();
74
- flushSync();
75
- expect(target.querySelector('.sp-collapsible-content')).toBeTruthy();
76
- });
77
- it('clicking trigger again closes content', () => {
78
- setup({ open: true });
79
- const trigger = target.querySelector('.sp-collapsible-trigger');
80
- expect(target.querySelector('.sp-collapsible-content')).toBeTruthy();
81
- trigger.click();
82
- flushSync();
83
- expect(target.querySelector('.sp-collapsible-content')).toBeNull();
84
- });
85
- it('toggle updates aria-expanded', () => {
86
- setup({ open: false });
87
- const trigger = target.querySelector('.sp-collapsible-trigger');
88
- expect(trigger.getAttribute('aria-expanded')).toBe('false');
89
- trigger.click();
90
- flushSync();
91
- expect(trigger.getAttribute('aria-expanded')).toBe('true');
92
- trigger.click();
93
- flushSync();
94
- expect(trigger.getAttribute('aria-expanded')).toBe('false');
95
- });
96
- // --- Content rendering ---
97
- it('content is not rendered when closed', () => {
98
- setup({ open: false });
99
- expect(target.querySelector('.sp-collapsible-content')).toBeNull();
100
- });
101
- it('content is rendered when open', () => {
102
- setup({ open: true });
103
- const content = target.querySelector('.sp-collapsible-content');
104
- expect(content).toBeTruthy();
105
- expect(content?.textContent).toContain('Collapsible content here');
106
- });
107
- // --- Disabled state ---
108
- it('disabled root has data-disabled', () => {
109
- setup({ disabled: true });
110
- const root = target.querySelector('.sp-collapsible');
111
- expect(root?.hasAttribute('data-disabled')).toBe(true);
112
- });
113
- it('disabled trigger has disabled attribute', () => {
114
- setup({ disabled: true });
115
- const trigger = target.querySelector('.sp-collapsible-trigger');
116
- expect(trigger?.disabled).toBe(true);
117
- });
118
- it('clicking disabled trigger does not toggle', () => {
119
- setup({ disabled: true, open: false });
120
- const trigger = target.querySelector('.sp-collapsible-trigger');
121
- trigger.click();
122
- flushSync();
123
- expect(target.querySelector('.sp-collapsible-content')).toBeNull();
124
- });
125
- });
@@ -1,40 +0,0 @@
1
- <script lang="ts">
2
- import type { Align, Side } from '../../../internal/floating-layer/types.js'
3
- import ComboboxContent from '../components/combobox-content.svelte'
4
- import ComboboxInput from '../components/combobox-input.svelte'
5
- import ComboboxItem from '../components/combobox-item.svelte'
6
- import ComboboxRoot from '../components/combobox-root.svelte'
7
-
8
- let {
9
- value = $bindable(''),
10
- open = $bindable(false),
11
- name = '',
12
- portalTo,
13
- disablePortal,
14
- contentClass,
15
- side,
16
- sideOffset,
17
- align,
18
- onOpenChange,
19
- }: {
20
- value?: string
21
- open?: boolean
22
- name?: string
23
- portalTo?: HTMLElement | string
24
- disablePortal?: boolean
25
- contentClass?: string
26
- side?: Side
27
- sideOffset?: number
28
- align?: Align
29
- onOpenChange?: (open: boolean) => void
30
- } = $props()
31
- </script>
32
-
33
- <ComboboxRoot bind:value bind:open {name} {onOpenChange}>
34
- <ComboboxInput placeholder="Search..." />
35
- <ComboboxContent {portalTo} {disablePortal} class={contentClass} {side} {sideOffset} {align}>
36
- <ComboboxItem value="apple">Apple</ComboboxItem>
37
- <ComboboxItem value="banana">Banana</ComboboxItem>
38
- <ComboboxItem value="cherry">Cherry</ComboboxItem>
39
- </ComboboxContent>
40
- </ComboboxRoot>