@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,215 +0,0 @@
|
|
|
1
|
-
import { flushSync, mount, unmount } from 'svelte';
|
|
2
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import LinkPreviewRoot from '../components/link-preview-root.svelte';
|
|
4
|
-
import LinkPreviewTest from './LinkPreviewTest.svelte';
|
|
5
|
-
describe('link-preview', () => {
|
|
6
|
-
let target;
|
|
7
|
-
let instance;
|
|
8
|
-
function setup(props = {}) {
|
|
9
|
-
target = document.createElement('div');
|
|
10
|
-
document.body.appendChild(target);
|
|
11
|
-
instance = mount(LinkPreviewTest, { target, props });
|
|
12
|
-
return target;
|
|
13
|
-
}
|
|
14
|
-
function setupRoot(props = {}) {
|
|
15
|
-
target = document.createElement('div');
|
|
16
|
-
document.body.appendChild(target);
|
|
17
|
-
instance = mount(LinkPreviewRoot, { target, props });
|
|
18
|
-
return target;
|
|
19
|
-
}
|
|
20
|
-
afterEach(() => {
|
|
21
|
-
vi.useRealTimers();
|
|
22
|
-
if (instance)
|
|
23
|
-
unmount(instance);
|
|
24
|
-
target?.remove();
|
|
25
|
-
});
|
|
26
|
-
// --- Basic rendering ---
|
|
27
|
-
it('renders root', () => {
|
|
28
|
-
setupRoot();
|
|
29
|
-
expect(target.querySelector('.sp-link-preview-root')).toBeTruthy();
|
|
30
|
-
});
|
|
31
|
-
it('root has data-state="closed" by default', () => {
|
|
32
|
-
setup();
|
|
33
|
-
const root = target.querySelector('.sp-link-preview-root');
|
|
34
|
-
expect(root?.getAttribute('data-state')).toBe('closed');
|
|
35
|
-
});
|
|
36
|
-
// --- Trigger ---
|
|
37
|
-
it('trigger renders as an anchor', () => {
|
|
38
|
-
setup();
|
|
39
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
40
|
-
expect(trigger?.tagName).toBe('A');
|
|
41
|
-
});
|
|
42
|
-
it('trigger has href attribute', () => {
|
|
43
|
-
setup();
|
|
44
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
45
|
-
expect(trigger?.getAttribute('href')).toBe('https://example.com');
|
|
46
|
-
});
|
|
47
|
-
it('trigger has aria-haspopup="dialog"', () => {
|
|
48
|
-
setup();
|
|
49
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
50
|
-
expect(trigger?.getAttribute('aria-haspopup')).toBe('dialog');
|
|
51
|
-
});
|
|
52
|
-
it('trigger has aria-expanded="false" when closed', () => {
|
|
53
|
-
setup();
|
|
54
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
55
|
-
expect(trigger?.getAttribute('aria-expanded')).toBe('false');
|
|
56
|
-
});
|
|
57
|
-
// --- Content ---
|
|
58
|
-
it('content not rendered when closed', () => {
|
|
59
|
-
setup();
|
|
60
|
-
expect(target.querySelector('[role="dialog"]')).toBeNull();
|
|
61
|
-
});
|
|
62
|
-
it('content appears on mouseenter with delay', () => {
|
|
63
|
-
vi.useFakeTimers();
|
|
64
|
-
setup({ openDelay: 0, closeDelay: 0 });
|
|
65
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
66
|
-
trigger.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
67
|
-
vi.advanceTimersByTime(10);
|
|
68
|
-
flushSync();
|
|
69
|
-
// Content is portalled to document.body, not inside target
|
|
70
|
-
const content = document.querySelector('[role="dialog"]');
|
|
71
|
-
expect(content).toBeTruthy();
|
|
72
|
-
});
|
|
73
|
-
it('content has data-state="open" when visible', () => {
|
|
74
|
-
vi.useFakeTimers();
|
|
75
|
-
setup({ openDelay: 0 });
|
|
76
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
77
|
-
trigger.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
78
|
-
vi.advanceTimersByTime(10);
|
|
79
|
-
flushSync();
|
|
80
|
-
// Content is portalled to document.body, not inside target
|
|
81
|
-
const content = document.querySelector('[role="dialog"]');
|
|
82
|
-
expect(content?.getAttribute('data-state')).toBe('open');
|
|
83
|
-
});
|
|
84
|
-
it('trigger has aria-expanded="true" when content is visible', () => {
|
|
85
|
-
vi.useFakeTimers();
|
|
86
|
-
setup({ openDelay: 0 });
|
|
87
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
88
|
-
trigger.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
89
|
-
vi.advanceTimersByTime(10);
|
|
90
|
-
flushSync();
|
|
91
|
-
expect(trigger.getAttribute('aria-expanded')).toBe('true');
|
|
92
|
-
});
|
|
93
|
-
it('trigger has aria-controls when open', () => {
|
|
94
|
-
vi.useFakeTimers();
|
|
95
|
-
setup({ openDelay: 0 });
|
|
96
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
97
|
-
trigger.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
98
|
-
vi.advanceTimersByTime(10);
|
|
99
|
-
flushSync();
|
|
100
|
-
// Content is portalled to document.body, not inside target
|
|
101
|
-
const content = document.querySelector('[role="dialog"]');
|
|
102
|
-
expect(trigger.getAttribute('aria-controls')).toBe(content?.id);
|
|
103
|
-
});
|
|
104
|
-
// --- Focus behavior ---
|
|
105
|
-
it('opens on focus', () => {
|
|
106
|
-
vi.useFakeTimers();
|
|
107
|
-
setup({ openDelay: 0 });
|
|
108
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
109
|
-
trigger.dispatchEvent(new FocusEvent('focus', { bubbles: true }));
|
|
110
|
-
vi.advanceTimersByTime(10);
|
|
111
|
-
flushSync();
|
|
112
|
-
// Content is portalled to document.body, not inside target
|
|
113
|
-
expect(document.querySelector('[role="dialog"]')).toBeTruthy();
|
|
114
|
-
});
|
|
115
|
-
it('closes on blur', () => {
|
|
116
|
-
vi.useFakeTimers();
|
|
117
|
-
setup({ openDelay: 0, closeDelay: 0 });
|
|
118
|
-
const trigger = target.querySelector('.sp-link-preview-trigger');
|
|
119
|
-
trigger.dispatchEvent(new FocusEvent('focus', { bubbles: true }));
|
|
120
|
-
vi.advanceTimersByTime(10);
|
|
121
|
-
flushSync();
|
|
122
|
-
// Content is portalled to document.body, not inside target
|
|
123
|
-
expect(document.querySelector('[role="dialog"]')).toBeTruthy();
|
|
124
|
-
trigger.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
|
|
125
|
-
vi.advanceTimersByTime(10);
|
|
126
|
-
flushSync();
|
|
127
|
-
expect(document.querySelector('[role="dialog"]')).toBeNull();
|
|
128
|
-
});
|
|
129
|
-
describe('portal opt-out (disablePortal)', () => {
|
|
130
|
-
beforeEach(() => {
|
|
131
|
-
vi.useFakeTimers();
|
|
132
|
-
});
|
|
133
|
-
it('portals to document.body by default', () => {
|
|
134
|
-
const localTarget = document.createElement('div');
|
|
135
|
-
document.body.appendChild(localTarget);
|
|
136
|
-
const localInstance = mount(LinkPreviewTest, {
|
|
137
|
-
target: localTarget,
|
|
138
|
-
props: { open: true },
|
|
139
|
-
});
|
|
140
|
-
flushSync(); // flush $effect (dispatches mouseenter → setTimeout(0))
|
|
141
|
-
vi.advanceTimersByTime(0); // fire the 0ms timer → open = true
|
|
142
|
-
flushSync(); // re-render content
|
|
143
|
-
try {
|
|
144
|
-
expect(localTarget.querySelector('.sp-link-preview-content')).toBeNull();
|
|
145
|
-
expect(document.body.querySelector('.sp-link-preview-content')).toBeTruthy();
|
|
146
|
-
}
|
|
147
|
-
finally {
|
|
148
|
-
unmount(localInstance);
|
|
149
|
-
localTarget.remove();
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
it('renders inline when disablePortal={true}', () => {
|
|
153
|
-
const localTarget = document.createElement('div');
|
|
154
|
-
document.body.appendChild(localTarget);
|
|
155
|
-
const localInstance = mount(LinkPreviewTest, {
|
|
156
|
-
target: localTarget,
|
|
157
|
-
props: { open: true, disablePortal: true },
|
|
158
|
-
});
|
|
159
|
-
flushSync();
|
|
160
|
-
vi.advanceTimersByTime(0);
|
|
161
|
-
flushSync();
|
|
162
|
-
try {
|
|
163
|
-
expect(localTarget.querySelector('.sp-link-preview-content')).toBeTruthy();
|
|
164
|
-
}
|
|
165
|
-
finally {
|
|
166
|
-
unmount(localInstance);
|
|
167
|
-
localTarget.remove();
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
it('preserves consumer class on the content element when inline', () => {
|
|
171
|
-
const localTarget = document.createElement('div');
|
|
172
|
-
document.body.appendChild(localTarget);
|
|
173
|
-
const localInstance = mount(LinkPreviewTest, {
|
|
174
|
-
target: localTarget,
|
|
175
|
-
props: { open: true, disablePortal: true, contentClass: 'my-consumer-class' },
|
|
176
|
-
});
|
|
177
|
-
flushSync();
|
|
178
|
-
vi.advanceTimersByTime(0);
|
|
179
|
-
flushSync();
|
|
180
|
-
try {
|
|
181
|
-
const el = localTarget.querySelector('.sp-link-preview-content.my-consumer-class');
|
|
182
|
-
expect(el).toBeTruthy();
|
|
183
|
-
}
|
|
184
|
-
finally {
|
|
185
|
-
unmount(localInstance);
|
|
186
|
-
localTarget.remove();
|
|
187
|
-
}
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
it('content is portalled to document.body when open', () => {
|
|
191
|
-
vi.useFakeTimers();
|
|
192
|
-
const localTarget = document.createElement('div');
|
|
193
|
-
document.body.appendChild(localTarget);
|
|
194
|
-
const localInstance = mount(LinkPreviewTest, {
|
|
195
|
-
target: localTarget,
|
|
196
|
-
props: { openDelay: 0, closeDelay: 0 },
|
|
197
|
-
});
|
|
198
|
-
flushSync();
|
|
199
|
-
try {
|
|
200
|
-
const trigger = localTarget.querySelector('.sp-link-preview-trigger');
|
|
201
|
-
trigger.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
202
|
-
vi.advanceTimersByTime(10);
|
|
203
|
-
flushSync();
|
|
204
|
-
// Content should NOT be rendered inside the local mount target
|
|
205
|
-
expect(localTarget.querySelector('.sp-link-preview-content')).toBeNull();
|
|
206
|
-
// Content SHOULD be rendered somewhere in the document (portalled)
|
|
207
|
-
expect(document.querySelector('.sp-link-preview-content')).toBeTruthy();
|
|
208
|
-
}
|
|
209
|
-
finally {
|
|
210
|
-
unmount(localInstance);
|
|
211
|
-
localTarget.remove();
|
|
212
|
-
vi.useRealTimers();
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { mount, unmount } from 'svelte';
|
|
2
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
-
import ListRoot from '../components/list-root.svelte';
|
|
4
|
-
describe('list', () => {
|
|
5
|
-
let target;
|
|
6
|
-
let instance;
|
|
7
|
-
function setup(props = {}) {
|
|
8
|
-
target = document.createElement('div');
|
|
9
|
-
document.body.appendChild(target);
|
|
10
|
-
instance = mount(ListRoot, { target, props });
|
|
11
|
-
return target;
|
|
12
|
-
}
|
|
13
|
-
afterEach(() => {
|
|
14
|
-
if (instance)
|
|
15
|
-
unmount(instance);
|
|
16
|
-
target?.remove();
|
|
17
|
-
});
|
|
18
|
-
it('renders with role=list', () => {
|
|
19
|
-
setup();
|
|
20
|
-
expect(target.querySelector('[role="list"]')).toBeTruthy();
|
|
21
|
-
});
|
|
22
|
-
});
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import DropdownMenuItem from '../../dropdown-menu/components/dropdown-menu-item.svelte'
|
|
3
|
-
import DropdownMenuSeparator from '../../dropdown-menu/components/dropdown-menu-separator.svelte'
|
|
4
|
-
import DropdownMenuSubContent from '../../dropdown-menu/components/dropdown-menu-sub-content.svelte'
|
|
5
|
-
import DropdownMenuSubTrigger from '../../dropdown-menu/components/dropdown-menu-sub-trigger.svelte'
|
|
6
|
-
import DropdownMenuSub from '../../dropdown-menu/components/dropdown-menu-sub.svelte'
|
|
7
|
-
import MenubarContent from '../components/menubar-content.svelte'
|
|
8
|
-
import MenubarMenu from '../components/menubar-menu.svelte'
|
|
9
|
-
import MenubarRoot from '../components/menubar-root.svelte'
|
|
10
|
-
import MenubarTrigger from '../components/menubar-trigger.svelte'
|
|
11
|
-
|
|
12
|
-
const {
|
|
13
|
-
loop = true,
|
|
14
|
-
portalTo,
|
|
15
|
-
withSub = false,
|
|
16
|
-
}: { loop?: boolean; portalTo?: HTMLElement | string; withSub?: boolean } = $props()
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
<MenubarRoot {loop}>
|
|
20
|
-
<MenubarMenu value="file">
|
|
21
|
-
<MenubarTrigger>File</MenubarTrigger>
|
|
22
|
-
<MenubarContent {portalTo}>
|
|
23
|
-
<DropdownMenuItem>New</DropdownMenuItem>
|
|
24
|
-
<DropdownMenuItem>Open</DropdownMenuItem>
|
|
25
|
-
<DropdownMenuSeparator />
|
|
26
|
-
<DropdownMenuItem>Save</DropdownMenuItem>
|
|
27
|
-
{#if withSub}
|
|
28
|
-
<DropdownMenuSub>
|
|
29
|
-
<DropdownMenuSubTrigger>Share</DropdownMenuSubTrigger>
|
|
30
|
-
<DropdownMenuSubContent>
|
|
31
|
-
<DropdownMenuItem>Email</DropdownMenuItem>
|
|
32
|
-
<DropdownMenuItem>Copy Link</DropdownMenuItem>
|
|
33
|
-
</DropdownMenuSubContent>
|
|
34
|
-
</DropdownMenuSub>
|
|
35
|
-
{/if}
|
|
36
|
-
</MenubarContent>
|
|
37
|
-
</MenubarMenu>
|
|
38
|
-
<MenubarMenu value="edit">
|
|
39
|
-
<MenubarTrigger>Edit</MenubarTrigger>
|
|
40
|
-
<MenubarContent {portalTo}>
|
|
41
|
-
<DropdownMenuItem>Undo</DropdownMenuItem>
|
|
42
|
-
<DropdownMenuItem>Redo</DropdownMenuItem>
|
|
43
|
-
</MenubarContent>
|
|
44
|
-
</MenubarMenu>
|
|
45
|
-
<MenubarMenu value="view">
|
|
46
|
-
<MenubarTrigger>View</MenubarTrigger>
|
|
47
|
-
<MenubarContent {portalTo}>
|
|
48
|
-
<DropdownMenuItem>Zoom In</DropdownMenuItem>
|
|
49
|
-
<DropdownMenuItem>Zoom Out</DropdownMenuItem>
|
|
50
|
-
</MenubarContent>
|
|
51
|
-
</MenubarMenu>
|
|
52
|
-
</MenubarRoot>
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { mount, unmount } from 'svelte';
|
|
2
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
-
import { configureAxe } from 'vitest-axe';
|
|
4
|
-
import * as matchers from 'vitest-axe/matchers';
|
|
5
|
-
import MenubarTest from './MenubarTest.svelte';
|
|
6
|
-
expect.extend(matchers);
|
|
7
|
-
const axe = configureAxe({
|
|
8
|
-
rules: {
|
|
9
|
-
region: { enabled: false },
|
|
10
|
-
'page-has-heading-one': { enabled: false },
|
|
11
|
-
'landmark-one-main': { enabled: false },
|
|
12
|
-
},
|
|
13
|
-
});
|
|
14
|
-
describe('menubar a11y', () => {
|
|
15
|
-
let cleanup;
|
|
16
|
-
afterEach(() => cleanup?.());
|
|
17
|
-
it('has no axe violations', async () => {
|
|
18
|
-
const container = document.createElement('div');
|
|
19
|
-
document.body.appendChild(container);
|
|
20
|
-
const instance = mount(MenubarTest, { target: container });
|
|
21
|
-
const results = await axe(container);
|
|
22
|
-
cleanup = () => {
|
|
23
|
-
unmount(instance);
|
|
24
|
-
container.remove();
|
|
25
|
-
};
|
|
26
|
-
expect(results).toHaveNoViolations();
|
|
27
|
-
});
|
|
28
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { flushSync, mount, unmount } from 'svelte';
|
|
2
|
-
import { afterEach, describe, expect, it } from 'vitest';
|
|
3
|
-
import MenubarTest from './MenubarTest.svelte';
|
|
4
|
-
describe('menubar integration', () => {
|
|
5
|
-
let target;
|
|
6
|
-
let instance;
|
|
7
|
-
function setup(props = {}) {
|
|
8
|
-
target = document.createElement('div');
|
|
9
|
-
document.body.appendChild(target);
|
|
10
|
-
instance = mount(MenubarTest, { target, props: { portalTo: target, ...props } });
|
|
11
|
-
flushSync();
|
|
12
|
-
return target;
|
|
13
|
-
}
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
if (instance)
|
|
16
|
-
unmount(instance);
|
|
17
|
-
target?.remove();
|
|
18
|
-
});
|
|
19
|
-
it('first trigger is Tab-reachable (tabindex=0)', () => {
|
|
20
|
-
setup();
|
|
21
|
-
const triggers = target.querySelectorAll('[data-menubar-trigger]');
|
|
22
|
-
expect(triggers[0]?.getAttribute('tabindex')).toBe('0');
|
|
23
|
-
expect(triggers[1]?.getAttribute('tabindex')).toBe('-1');
|
|
24
|
-
expect(triggers[2]?.getAttribute('tabindex')).toBe('-1');
|
|
25
|
-
});
|
|
26
|
-
it('full flow: click → select item → menu closes', () => {
|
|
27
|
-
setup();
|
|
28
|
-
const triggers = target.querySelectorAll('[data-menubar-trigger]');
|
|
29
|
-
triggers[0].click();
|
|
30
|
-
flushSync();
|
|
31
|
-
const menu = target.querySelector('[role="menu"]');
|
|
32
|
-
expect(menu).toBeTruthy();
|
|
33
|
-
const items = menu.querySelectorAll('[role="menuitem"]');
|
|
34
|
-
items[0].click();
|
|
35
|
-
flushSync();
|
|
36
|
-
expect(target.querySelector('[role="menu"]')).toBeNull();
|
|
37
|
-
});
|
|
38
|
-
it('full flow: click File → hover Edit → Edit opens', () => {
|
|
39
|
-
setup();
|
|
40
|
-
const triggers = target.querySelectorAll('[data-menubar-trigger]');
|
|
41
|
-
triggers[0].click();
|
|
42
|
-
flushSync();
|
|
43
|
-
triggers[1].dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
|
|
44
|
-
flushSync();
|
|
45
|
-
expect(triggers[0].getAttribute('data-state')).toBe('closed');
|
|
46
|
-
expect(triggers[1].getAttribute('data-state')).toBe('open');
|
|
47
|
-
});
|
|
48
|
-
it('roving tabindex updates after ArrowRight', () => {
|
|
49
|
-
setup();
|
|
50
|
-
const triggers = target.querySelectorAll('[data-menubar-trigger]');
|
|
51
|
-
triggers[0].focus();
|
|
52
|
-
triggers[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
|
|
53
|
-
flushSync();
|
|
54
|
-
expect(triggers[1]?.getAttribute('tabindex')).toBe('0');
|
|
55
|
-
expect(triggers[0]?.getAttribute('tabindex')).toBe('-1');
|
|
56
|
-
});
|
|
57
|
-
});
|