@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.
- package/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES.md +201 -0
- package/package.json +8 -2
- package/dist/components/__tests__/overlay-scrim-source.test.js +0 -134
- package/dist/components/accordion/__tests__/AccordionTest.svelte +0 -31
- package/dist/components/accordion/__tests__/accordion.test.svelte.js +0 -139
- package/dist/components/alert-dialog/__tests__/AlertDialogTest.svelte +0 -28
- package/dist/components/alert-dialog/__tests__/alert-dialog.a11y.test.js +0 -42
- package/dist/components/alert-dialog/__tests__/alert-dialog.integration.test.svelte.js +0 -51
- package/dist/components/alert-dialog/__tests__/alert-dialog.test.svelte.js +0 -113
- package/dist/components/app-bar/__tests__/app-bar.test.svelte.js +0 -30
- package/dist/components/aspect-ratio/__tests__/aspect-ratio.test.svelte.js +0 -22
- package/dist/components/avatar/__tests__/avatar.test.svelte.js +0 -26
- package/dist/components/badge/__tests__/badge.test.svelte.js +0 -30
- package/dist/components/bottom-sheet/__tests__/BottomSheetTest.svelte +0 -22
- package/dist/components/bottom-sheet/__tests__/bottom-sheet.test.svelte.js +0 -83
- package/dist/components/button/__tests__/button.test.svelte.js +0 -63
- package/dist/components/calendar/__tests__/CalendarTest.svelte +0 -56
- package/dist/components/calendar/__tests__/calendar.test.svelte.js +0 -190
- package/dist/components/card/__tests__/card.test.svelte.js +0 -30
- package/dist/components/checkbox/__tests__/checkbox.test.svelte.js +0 -44
- package/dist/components/chips/__tests__/chips.test.svelte.js +0 -26
- package/dist/components/collapsible/__tests__/CollapsibleTest.svelte +0 -18
- package/dist/components/collapsible/__tests__/collapsible.test.svelte.js +0 -125
- package/dist/components/combobox/__tests__/ComboboxTest.svelte +0 -40
- package/dist/components/combobox/__tests__/combobox.test.svelte.js +0 -255
- package/dist/components/command/__tests__/CommandInlineDirectTest.svelte +0 -29
- package/dist/components/command/__tests__/CommandInlineTest.svelte +0 -89
- package/dist/components/command/__tests__/CommandTest.svelte +0 -77
- package/dist/components/command/__tests__/command-inline.test.svelte.js +0 -392
- package/dist/components/command/__tests__/command-item-passthrough.test.svelte.js +0 -284
- package/dist/components/command/__tests__/command.a11y.test.js +0 -30
- package/dist/components/command/__tests__/command.integration.test.svelte.js +0 -68
- package/dist/components/command/__tests__/command.test.svelte.js +0 -230
- package/dist/components/context-menu/__tests__/ContextMenuNonInteractiveTest.svelte +0 -32
- package/dist/components/context-menu/__tests__/ContextMenuTest.svelte +0 -25
- package/dist/components/context-menu/__tests__/context-menu.test.svelte.js +0 -141
- package/dist/components/date-field/__tests__/DateFieldTest.svelte +0 -20
- package/dist/components/date-field/__tests__/date-field.test.svelte.js +0 -139
- package/dist/components/date-picker/__tests__/DatePickerTest.svelte +0 -20
- package/dist/components/date-picker/__tests__/date-picker.test.svelte.js +0 -190
- package/dist/components/date-range-field/__tests__/DateRangeFieldTest.svelte +0 -20
- package/dist/components/date-range-field/__tests__/date-range-field.test.svelte.js +0 -130
- package/dist/components/date-range-picker/__tests__/DateRangePickerTest.svelte +0 -18
- package/dist/components/date-range-picker/__tests__/date-range-picker.test.svelte.js +0 -156
- package/dist/components/dialog/__tests__/DialogTest.svelte +0 -34
- package/dist/components/dialog/__tests__/dialog.test.svelte.js +0 -184
- package/dist/components/drop-zone/__tests__/drop-zone.test.svelte.js +0 -26
- package/dist/components/dropdown-menu/__tests__/DropdownMenuRadioTest.svelte +0 -90
- package/dist/components/dropdown-menu/__tests__/DropdownMenuTest.svelte +0 -71
- package/dist/components/dropdown-menu/__tests__/dropdown-menu-radio-group.test.svelte.js +0 -306
- package/dist/components/dropdown-menu/__tests__/dropdown-menu.test.svelte.js +0 -567
- package/dist/components/empty-state/__tests__/empty-state.test.svelte.js +0 -26
- package/dist/components/fab/__tests__/fab.test.svelte.js +0 -30
- package/dist/components/field/__tests__/FieldTest.svelte +0 -26
- package/dist/components/field/__tests__/field.test.svelte.js +0 -74
- package/dist/components/grid-list/__tests__/GridListTest.svelte +0 -46
- package/dist/components/grid-list/__tests__/grid-list.test.svelte.js +0 -231
- package/dist/components/hover-card/__tests__/HoverCardTest.svelte +0 -30
- package/dist/components/hover-card/__tests__/hover-card.test.svelte.js +0 -236
- package/dist/components/indicator/__tests__/indicator.test.svelte.js +0 -30
- package/dist/components/input/__tests__/input.test.svelte.js +0 -67
- package/dist/components/label/__tests__/label.test.svelte.js +0 -22
- package/dist/components/language-select/__tests__/language-select.test.svelte.js +0 -199
- package/dist/components/language-select/__tests__/languages.test.js +0 -87
- package/dist/components/link-preview/__tests__/LinkPreviewTest.svelte +0 -37
- package/dist/components/link-preview/__tests__/link-preview.a11y.test.js +0 -28
- package/dist/components/link-preview/__tests__/link-preview.integration.test.svelte.js +0 -54
- package/dist/components/link-preview/__tests__/link-preview.test.svelte.js +0 -215
- package/dist/components/list/__tests__/list.test.svelte.js +0 -22
- package/dist/components/menubar/__tests__/MenubarTest.svelte +0 -52
- package/dist/components/menubar/__tests__/menubar.a11y.test.js +0 -28
- package/dist/components/menubar/__tests__/menubar.integration.test.svelte.js +0 -57
- package/dist/components/menubar/__tests__/menubar.test.svelte.js +0 -328
- package/dist/components/meter/__tests__/meter.test.svelte.js +0 -26
- package/dist/components/nav-bar/__tests__/nav-bar.test.svelte.js +0 -23
- package/dist/components/nav-drawer/__tests__/nav-drawer.test.svelte.js +0 -28
- package/dist/components/nav-rail/__tests__/nav-rail.test.svelte.js +0 -28
- package/dist/components/pagination/__tests__/pagination.test.svelte.js +0 -26
- package/dist/components/pin-input/__tests__/pin-input.test.svelte.js +0 -71
- package/dist/components/popover/__tests__/PopoverTest.svelte +0 -27
- package/dist/components/popover/__tests__/popover.test.svelte.js +0 -196
- package/dist/components/progress/__tests__/progress.test.svelte.js +0 -32
- package/dist/components/radio-group/__tests__/radio-group.test.svelte.js +0 -22
- package/dist/components/range-calendar/__tests__/RangeCalendarTest.svelte +0 -23
- package/dist/components/range-calendar/__tests__/range-calendar.test.svelte.js +0 -105
- package/dist/components/rating-group/__tests__/rating-group.test.svelte.js +0 -26
- package/dist/components/scroll-area/__tests__/scroll-area.test.svelte.js +0 -34
- package/dist/components/search-field/__tests__/SearchFieldTest.svelte +0 -34
- package/dist/components/search-field/__tests__/search-field.test.svelte.js +0 -118
- package/dist/components/select/__tests__/SelectLabelPersistenceTest.svelte +0 -31
- package/dist/components/select/__tests__/SelectTest.svelte +0 -33
- package/dist/components/select/__tests__/select.test.svelte.js +0 -221
- package/dist/components/separator/__tests__/separator.test.svelte.js +0 -39
- package/dist/components/sheet/__tests__/SheetTest.svelte +0 -34
- package/dist/components/sheet/__tests__/sheet.test.svelte.js +0 -193
- package/dist/components/side-sheet/__tests__/side-sheet.test.svelte.js +0 -138
- package/dist/components/sidebar/__tests__/SidebarFullTest.svelte +0 -45
- package/dist/components/sidebar/__tests__/SidebarTest.svelte +0 -9
- package/dist/components/sidebar/__tests__/sidebar.test.svelte.js +0 -186
- package/dist/components/simple-dialog/__tests__/SimpleDialogTest.svelte +0 -40
- package/dist/components/simple-dialog/__tests__/simple-dialog.test.svelte.js +0 -50
- package/dist/components/simple-tooltip/__tests__/SimpleTooltipTest.svelte +0 -19
- package/dist/components/simple-tooltip/__tests__/simple-tooltip.test.svelte.js +0 -61
- package/dist/components/slider/__tests__/slider.test.svelte.js +0 -42
- package/dist/components/sortable-list/__tests__/NestedSortableListTest.svelte +0 -49
- package/dist/components/sortable-list/__tests__/SortableListTest.svelte +0 -42
- package/dist/components/sortable-list/__tests__/sortable-list.nested.test.svelte.js +0 -112
- package/dist/components/sortable-list/__tests__/sortable-list.test.svelte.js +0 -175
- package/dist/components/splitter/__tests__/splitter.test.svelte.js +0 -26
- package/dist/components/switch/__tests__/switch.test.svelte.js +0 -44
- package/dist/components/table/__tests__/table.test.svelte.js +0 -22
- package/dist/components/tabs/__tests__/TabsTest.svelte +0 -32
- package/dist/components/tabs/__tests__/tabs.test.svelte.js +0 -227
- package/dist/components/textarea/__tests__/textarea.test.svelte.js +0 -55
- package/dist/components/time-field/__tests__/TimeFieldTest.svelte +0 -20
- package/dist/components/time-field/__tests__/time-field.test.svelte.js +0 -100
- package/dist/components/time-range-field/__tests__/TimeRangeFieldTest.svelte +0 -20
- package/dist/components/time-range-field/__tests__/time-range-field.test.svelte.js +0 -124
- package/dist/components/toast/__tests__/toast.test.svelte.js +0 -46
- package/dist/components/toggle/__tests__/toggle.test.svelte.js +0 -38
- package/dist/components/toggle-group/__tests__/toggle-group.test.svelte.js +0 -22
- package/dist/components/toolbar/__tests__/ToolbarCompositionTest.svelte +0 -18
- package/dist/components/toolbar/__tests__/ToolbarTabstopTest.svelte +0 -10
- package/dist/components/toolbar/__tests__/toolbar.test.svelte.js +0 -63
- package/dist/components/tooltip/__tests__/TooltipTest.svelte +0 -22
- package/dist/components/tooltip/__tests__/tooltip.test.svelte.js +0 -225
- package/dist/components/tree/__tests__/TreeLabelContentTest.svelte +0 -21
- package/dist/components/tree/__tests__/TreeTest.svelte +0 -24
- package/dist/components/tree/__tests__/tree.test.svelte.js +0 -229
- package/dist/components/virtualizer/__tests__/waterfall-layout.test.js +0 -82
- package/dist/internal/announcer/__tests__/announcer.test.js +0 -42
- package/dist/internal/dismissible-layer/__tests__/dismissible-layer.test.js +0 -196
- package/dist/internal/drag-drop/__tests__/auto-scroll.test.js +0 -104
- package/dist/internal/drag-drop/__tests__/drag-session.test.svelte.js +0 -803
- package/dist/internal/drag-drop/__tests__/drag-source.test.svelte.js +0 -130
- package/dist/internal/drag-drop/__tests__/drop-delegate.test.js +0 -223
- package/dist/internal/drag-drop/__tests__/types.test.js +0 -20
- package/dist/internal/escape-layer/__tests__/escape-layer.test.js +0 -113
- package/dist/internal/focus-scope/__tests__/focus-scope.test.js +0 -225
- package/dist/internal/grace-area/__tests__/grace-area.test.js +0 -67
- package/dist/internal/helpers/__tests__/helpers.test.js +0 -123
- package/dist/internal/portal/__tests__/PortalTest.svelte +0 -21
- package/dist/internal/portal/__tests__/portal.test.js +0 -29
- package/dist/internal/portal/__tests__/portal.test.svelte.js +0 -57
- package/dist/internal/scroll-lock/__tests__/scroll-lock.test.js +0 -160
- package/dist/internal/typeahead/__tests__/typeahead.test.js +0 -61
- package/src/themes/__tests__/carbon-dark-contrast.test.ts +0 -170
- package/src/themes/__tests__/generated-css-drift.test.ts +0 -53
- 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>
|