@spectral_labs/ui 1.7.0 → 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 (150) hide show
  1. package/LICENSE +21 -0
  2. package/THIRD_PARTY_NOTICES.md +201 -0
  3. package/package.json +8 -2
  4. package/dist/components/__tests__/overlay-scrim-source.test.js +0 -134
  5. package/dist/components/accordion/__tests__/AccordionTest.svelte +0 -31
  6. package/dist/components/accordion/__tests__/accordion.test.svelte.js +0 -139
  7. package/dist/components/alert-dialog/__tests__/AlertDialogTest.svelte +0 -28
  8. package/dist/components/alert-dialog/__tests__/alert-dialog.a11y.test.js +0 -42
  9. package/dist/components/alert-dialog/__tests__/alert-dialog.integration.test.svelte.js +0 -51
  10. package/dist/components/alert-dialog/__tests__/alert-dialog.test.svelte.js +0 -113
  11. package/dist/components/app-bar/__tests__/app-bar.test.svelte.js +0 -30
  12. package/dist/components/aspect-ratio/__tests__/aspect-ratio.test.svelte.js +0 -22
  13. package/dist/components/avatar/__tests__/avatar.test.svelte.js +0 -26
  14. package/dist/components/badge/__tests__/badge.test.svelte.js +0 -30
  15. package/dist/components/bottom-sheet/__tests__/BottomSheetTest.svelte +0 -22
  16. package/dist/components/bottom-sheet/__tests__/bottom-sheet.test.svelte.js +0 -83
  17. package/dist/components/button/__tests__/button.test.svelte.js +0 -63
  18. package/dist/components/calendar/__tests__/CalendarTest.svelte +0 -56
  19. package/dist/components/calendar/__tests__/calendar.test.svelte.js +0 -190
  20. package/dist/components/card/__tests__/card.test.svelte.js +0 -30
  21. package/dist/components/checkbox/__tests__/checkbox.test.svelte.js +0 -44
  22. package/dist/components/chips/__tests__/chips.test.svelte.js +0 -26
  23. package/dist/components/collapsible/__tests__/CollapsibleTest.svelte +0 -18
  24. package/dist/components/collapsible/__tests__/collapsible.test.svelte.js +0 -125
  25. package/dist/components/combobox/__tests__/ComboboxTest.svelte +0 -40
  26. package/dist/components/combobox/__tests__/combobox.test.svelte.js +0 -255
  27. package/dist/components/command/__tests__/CommandInlineDirectTest.svelte +0 -29
  28. package/dist/components/command/__tests__/CommandInlineTest.svelte +0 -89
  29. package/dist/components/command/__tests__/CommandTest.svelte +0 -77
  30. package/dist/components/command/__tests__/command-inline.test.svelte.js +0 -392
  31. package/dist/components/command/__tests__/command-item-passthrough.test.svelte.js +0 -284
  32. package/dist/components/command/__tests__/command.a11y.test.js +0 -30
  33. package/dist/components/command/__tests__/command.integration.test.svelte.js +0 -68
  34. package/dist/components/command/__tests__/command.test.svelte.js +0 -230
  35. package/dist/components/context-menu/__tests__/ContextMenuNonInteractiveTest.svelte +0 -32
  36. package/dist/components/context-menu/__tests__/ContextMenuTest.svelte +0 -25
  37. package/dist/components/context-menu/__tests__/context-menu.test.svelte.js +0 -141
  38. package/dist/components/date-field/__tests__/DateFieldTest.svelte +0 -20
  39. package/dist/components/date-field/__tests__/date-field.test.svelte.js +0 -139
  40. package/dist/components/date-picker/__tests__/DatePickerTest.svelte +0 -20
  41. package/dist/components/date-picker/__tests__/date-picker.test.svelte.js +0 -190
  42. package/dist/components/date-range-field/__tests__/DateRangeFieldTest.svelte +0 -20
  43. package/dist/components/date-range-field/__tests__/date-range-field.test.svelte.js +0 -130
  44. package/dist/components/date-range-picker/__tests__/DateRangePickerTest.svelte +0 -18
  45. package/dist/components/date-range-picker/__tests__/date-range-picker.test.svelte.js +0 -156
  46. package/dist/components/dialog/__tests__/DialogTest.svelte +0 -34
  47. package/dist/components/dialog/__tests__/dialog.test.svelte.js +0 -184
  48. package/dist/components/drop-zone/__tests__/drop-zone.test.svelte.js +0 -26
  49. package/dist/components/dropdown-menu/__tests__/DropdownMenuRadioTest.svelte +0 -90
  50. package/dist/components/dropdown-menu/__tests__/DropdownMenuTest.svelte +0 -71
  51. package/dist/components/dropdown-menu/__tests__/dropdown-menu-radio-group.test.svelte.js +0 -306
  52. package/dist/components/dropdown-menu/__tests__/dropdown-menu.test.svelte.js +0 -567
  53. package/dist/components/empty-state/__tests__/empty-state.test.svelte.js +0 -26
  54. package/dist/components/fab/__tests__/fab.test.svelte.js +0 -30
  55. package/dist/components/field/__tests__/FieldTest.svelte +0 -26
  56. package/dist/components/field/__tests__/field.test.svelte.js +0 -74
  57. package/dist/components/grid-list/__tests__/GridListTest.svelte +0 -46
  58. package/dist/components/grid-list/__tests__/grid-list.test.svelte.js +0 -231
  59. package/dist/components/hover-card/__tests__/HoverCardTest.svelte +0 -30
  60. package/dist/components/hover-card/__tests__/hover-card.test.svelte.js +0 -236
  61. package/dist/components/indicator/__tests__/indicator.test.svelte.js +0 -30
  62. package/dist/components/input/__tests__/input.test.svelte.js +0 -67
  63. package/dist/components/label/__tests__/label.test.svelte.js +0 -22
  64. package/dist/components/language-select/__tests__/language-select.test.svelte.js +0 -199
  65. package/dist/components/language-select/__tests__/languages.test.js +0 -87
  66. package/dist/components/link-preview/__tests__/LinkPreviewTest.svelte +0 -37
  67. package/dist/components/link-preview/__tests__/link-preview.a11y.test.js +0 -28
  68. package/dist/components/link-preview/__tests__/link-preview.integration.test.svelte.js +0 -54
  69. package/dist/components/link-preview/__tests__/link-preview.test.svelte.js +0 -215
  70. package/dist/components/list/__tests__/list.test.svelte.js +0 -22
  71. package/dist/components/menubar/__tests__/MenubarTest.svelte +0 -52
  72. package/dist/components/menubar/__tests__/menubar.a11y.test.js +0 -28
  73. package/dist/components/menubar/__tests__/menubar.integration.test.svelte.js +0 -57
  74. package/dist/components/menubar/__tests__/menubar.test.svelte.js +0 -328
  75. package/dist/components/meter/__tests__/meter.test.svelte.js +0 -26
  76. package/dist/components/nav-bar/__tests__/nav-bar.test.svelte.js +0 -23
  77. package/dist/components/nav-drawer/__tests__/nav-drawer.test.svelte.js +0 -28
  78. package/dist/components/nav-rail/__tests__/nav-rail.test.svelte.js +0 -28
  79. package/dist/components/pagination/__tests__/pagination.test.svelte.js +0 -26
  80. package/dist/components/pin-input/__tests__/pin-input.test.svelte.js +0 -71
  81. package/dist/components/popover/__tests__/PopoverTest.svelte +0 -27
  82. package/dist/components/popover/__tests__/popover.test.svelte.js +0 -196
  83. package/dist/components/progress/__tests__/progress.test.svelte.js +0 -32
  84. package/dist/components/radio-group/__tests__/radio-group.test.svelte.js +0 -22
  85. package/dist/components/range-calendar/__tests__/RangeCalendarTest.svelte +0 -23
  86. package/dist/components/range-calendar/__tests__/range-calendar.test.svelte.js +0 -105
  87. package/dist/components/rating-group/__tests__/rating-group.test.svelte.js +0 -26
  88. package/dist/components/scroll-area/__tests__/scroll-area.test.svelte.js +0 -34
  89. package/dist/components/search-field/__tests__/SearchFieldTest.svelte +0 -34
  90. package/dist/components/search-field/__tests__/search-field.test.svelte.js +0 -118
  91. package/dist/components/select/__tests__/SelectLabelPersistenceTest.svelte +0 -31
  92. package/dist/components/select/__tests__/SelectTest.svelte +0 -33
  93. package/dist/components/select/__tests__/select.test.svelte.js +0 -221
  94. package/dist/components/separator/__tests__/separator.test.svelte.js +0 -39
  95. package/dist/components/sheet/__tests__/SheetTest.svelte +0 -34
  96. package/dist/components/sheet/__tests__/sheet.test.svelte.js +0 -193
  97. package/dist/components/side-sheet/__tests__/side-sheet.test.svelte.js +0 -138
  98. package/dist/components/sidebar/__tests__/SidebarFullTest.svelte +0 -45
  99. package/dist/components/sidebar/__tests__/SidebarTest.svelte +0 -9
  100. package/dist/components/sidebar/__tests__/sidebar.test.svelte.js +0 -186
  101. package/dist/components/simple-dialog/__tests__/SimpleDialogTest.svelte +0 -40
  102. package/dist/components/simple-dialog/__tests__/simple-dialog.test.svelte.js +0 -50
  103. package/dist/components/simple-tooltip/__tests__/SimpleTooltipTest.svelte +0 -19
  104. package/dist/components/simple-tooltip/__tests__/simple-tooltip.test.svelte.js +0 -61
  105. package/dist/components/slider/__tests__/slider.test.svelte.js +0 -42
  106. package/dist/components/sortable-list/__tests__/NestedSortableListTest.svelte +0 -49
  107. package/dist/components/sortable-list/__tests__/SortableListTest.svelte +0 -42
  108. package/dist/components/sortable-list/__tests__/sortable-list.nested.test.svelte.js +0 -112
  109. package/dist/components/sortable-list/__tests__/sortable-list.test.svelte.js +0 -175
  110. package/dist/components/splitter/__tests__/splitter.test.svelte.js +0 -26
  111. package/dist/components/switch/__tests__/switch.test.svelte.js +0 -44
  112. package/dist/components/table/__tests__/table.test.svelte.js +0 -22
  113. package/dist/components/tabs/__tests__/TabsTest.svelte +0 -32
  114. package/dist/components/tabs/__tests__/tabs.test.svelte.js +0 -227
  115. package/dist/components/textarea/__tests__/textarea.test.svelte.js +0 -55
  116. package/dist/components/time-field/__tests__/TimeFieldTest.svelte +0 -20
  117. package/dist/components/time-field/__tests__/time-field.test.svelte.js +0 -100
  118. package/dist/components/time-range-field/__tests__/TimeRangeFieldTest.svelte +0 -20
  119. package/dist/components/time-range-field/__tests__/time-range-field.test.svelte.js +0 -124
  120. package/dist/components/toast/__tests__/toast.test.svelte.js +0 -46
  121. package/dist/components/toggle/__tests__/toggle.test.svelte.js +0 -38
  122. package/dist/components/toggle-group/__tests__/toggle-group.test.svelte.js +0 -22
  123. package/dist/components/toolbar/__tests__/ToolbarCompositionTest.svelte +0 -18
  124. package/dist/components/toolbar/__tests__/ToolbarTabstopTest.svelte +0 -10
  125. package/dist/components/toolbar/__tests__/toolbar.test.svelte.js +0 -63
  126. package/dist/components/tooltip/__tests__/TooltipTest.svelte +0 -22
  127. package/dist/components/tooltip/__tests__/tooltip.test.svelte.js +0 -225
  128. package/dist/components/tree/__tests__/TreeLabelContentTest.svelte +0 -21
  129. package/dist/components/tree/__tests__/TreeTest.svelte +0 -24
  130. package/dist/components/tree/__tests__/tree.test.svelte.js +0 -229
  131. package/dist/components/virtualizer/__tests__/waterfall-layout.test.js +0 -82
  132. package/dist/internal/announcer/__tests__/announcer.test.js +0 -42
  133. package/dist/internal/dismissible-layer/__tests__/dismissible-layer.test.js +0 -196
  134. package/dist/internal/drag-drop/__tests__/auto-scroll.test.js +0 -104
  135. package/dist/internal/drag-drop/__tests__/drag-session.test.svelte.js +0 -803
  136. package/dist/internal/drag-drop/__tests__/drag-source.test.svelte.js +0 -130
  137. package/dist/internal/drag-drop/__tests__/drop-delegate.test.js +0 -223
  138. package/dist/internal/drag-drop/__tests__/types.test.js +0 -20
  139. package/dist/internal/escape-layer/__tests__/escape-layer.test.js +0 -113
  140. package/dist/internal/focus-scope/__tests__/focus-scope.test.js +0 -225
  141. package/dist/internal/grace-area/__tests__/grace-area.test.js +0 -67
  142. package/dist/internal/helpers/__tests__/helpers.test.js +0 -123
  143. package/dist/internal/portal/__tests__/PortalTest.svelte +0 -21
  144. package/dist/internal/portal/__tests__/portal.test.js +0 -29
  145. package/dist/internal/portal/__tests__/portal.test.svelte.js +0 -57
  146. package/dist/internal/scroll-lock/__tests__/scroll-lock.test.js +0 -160
  147. package/dist/internal/typeahead/__tests__/typeahead.test.js +0 -61
  148. package/src/themes/__tests__/carbon-dark-contrast.test.ts +0 -170
  149. package/src/themes/__tests__/generated-css-drift.test.ts +0 -53
  150. 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>