@spectral_labs/ui 1.6.1 → 1.8.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES.md +201 -0
- package/dist/components/command/command.svelte.d.ts +30 -0
- package/dist/components/command/command.svelte.d.ts.map +1 -1
- package/dist/components/command/command.svelte.js +85 -4
- package/dist/components/command/components/command-group.svelte +25 -15
- package/dist/components/command/components/command-group.svelte.d.ts.map +1 -1
- package/dist/components/command/components/command-input.svelte +54 -5
- package/dist/components/command/components/command-input.svelte.d.ts +1 -1
- package/dist/components/command/components/command-input.svelte.d.ts.map +1 -1
- package/dist/components/command/components/command-list.svelte +22 -3
- package/dist/components/command/components/command-list.svelte.d.ts.map +1 -1
- package/dist/components/command/components/command-root.svelte +43 -4
- package/dist/components/command/components/command-root.svelte.d.ts.map +1 -1
- package/dist/components/command/index.d.ts +1 -0
- package/dist/components/command/index.d.ts.map +1 -1
- package/dist/components/command/types.d.ts +59 -4
- package/dist/components/command/types.d.ts.map +1 -1
- 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__/CommandTest.svelte +0 -77
- 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,196 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { DismissibleLayerState, resetDismissibleLayerStack } from '../dismissible-layer.svelte.js';
|
|
3
|
-
// jsdom does not define PointerEvent — polyfill it for tests
|
|
4
|
-
if (typeof globalThis.PointerEvent === 'undefined') {
|
|
5
|
-
// @ts-expect-error — minimal polyfill for testing
|
|
6
|
-
globalThis.PointerEvent = class PointerEvent extends MouseEvent {
|
|
7
|
-
constructor(type, init) {
|
|
8
|
-
super(type, init);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function createElement(rect) {
|
|
13
|
-
const el = document.createElement('div');
|
|
14
|
-
document.body.appendChild(el);
|
|
15
|
-
// Override getBoundingClientRect for rect-based inside checks
|
|
16
|
-
if (rect) {
|
|
17
|
-
el.getBoundingClientRect = () => ({
|
|
18
|
-
x: rect.x ?? 0,
|
|
19
|
-
y: rect.y ?? 0,
|
|
20
|
-
width: rect.width ?? 100,
|
|
21
|
-
height: rect.height ?? 100,
|
|
22
|
-
top: rect.top ?? 0,
|
|
23
|
-
right: rect.right ?? 100,
|
|
24
|
-
bottom: rect.bottom ?? 100,
|
|
25
|
-
left: rect.left ?? 0,
|
|
26
|
-
toJSON: () => ({}),
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return el;
|
|
30
|
-
}
|
|
31
|
-
function pointerDownOutside(x = 500, y = 500) {
|
|
32
|
-
const event = new PointerEvent('pointerdown', {
|
|
33
|
-
bubbles: true,
|
|
34
|
-
clientX: x,
|
|
35
|
-
clientY: y,
|
|
36
|
-
});
|
|
37
|
-
document.dispatchEvent(event);
|
|
38
|
-
}
|
|
39
|
-
function pointerDownOn(element) {
|
|
40
|
-
const event = new PointerEvent('pointerdown', {
|
|
41
|
-
bubbles: true,
|
|
42
|
-
clientX: 0,
|
|
43
|
-
clientY: 0,
|
|
44
|
-
});
|
|
45
|
-
element.dispatchEvent(event);
|
|
46
|
-
}
|
|
47
|
-
describe('dismissibleLayerState', () => {
|
|
48
|
-
beforeEach(() => {
|
|
49
|
-
resetDismissibleLayerStack();
|
|
50
|
-
});
|
|
51
|
-
afterEach(() => {
|
|
52
|
-
resetDismissibleLayerStack();
|
|
53
|
-
// Clean up any DOM elements
|
|
54
|
-
document.body.innerHTML = '';
|
|
55
|
-
});
|
|
56
|
-
it('calls onInteractOutside when clicking outside the element', () => {
|
|
57
|
-
const el = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
58
|
-
const onInteractOutside = vi.fn();
|
|
59
|
-
const props = {
|
|
60
|
-
enabled: true,
|
|
61
|
-
element: el,
|
|
62
|
-
onInteractOutside,
|
|
63
|
-
behavior: 'close',
|
|
64
|
-
};
|
|
65
|
-
const layer = new DismissibleLayerState(props);
|
|
66
|
-
layer.mount();
|
|
67
|
-
// Click outside the element's bounds
|
|
68
|
-
pointerDownOutside(500, 500);
|
|
69
|
-
expect(onInteractOutside).toHaveBeenCalledOnce();
|
|
70
|
-
expect(onInteractOutside).toHaveBeenCalledWith(expect.objectContaining({ type: 'pointerdown' }));
|
|
71
|
-
layer.unmount();
|
|
72
|
-
});
|
|
73
|
-
it('does NOT call onInteractOutside when clicking inside the element', () => {
|
|
74
|
-
const el = createElement();
|
|
75
|
-
const onInteractOutside = vi.fn();
|
|
76
|
-
const props = {
|
|
77
|
-
enabled: true,
|
|
78
|
-
element: el,
|
|
79
|
-
onInteractOutside,
|
|
80
|
-
behavior: 'close',
|
|
81
|
-
};
|
|
82
|
-
const layer = new DismissibleLayerState(props);
|
|
83
|
-
layer.mount();
|
|
84
|
-
// Click on the element itself (DOM containment check)
|
|
85
|
-
pointerDownOn(el);
|
|
86
|
-
expect(onInteractOutside).not.toHaveBeenCalled();
|
|
87
|
-
layer.unmount();
|
|
88
|
-
});
|
|
89
|
-
describe('stack behavior', () => {
|
|
90
|
-
it('only topmost layer handles the event', () => {
|
|
91
|
-
const el1 = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
92
|
-
const el2 = createElement({ top: 200, left: 200, right: 300, bottom: 300 });
|
|
93
|
-
const onInteractOutside1 = vi.fn();
|
|
94
|
-
const onInteractOutside2 = vi.fn();
|
|
95
|
-
const layer1 = new DismissibleLayerState({
|
|
96
|
-
enabled: true,
|
|
97
|
-
element: el1,
|
|
98
|
-
onInteractOutside: onInteractOutside1,
|
|
99
|
-
behavior: 'close',
|
|
100
|
-
});
|
|
101
|
-
const layer2 = new DismissibleLayerState({
|
|
102
|
-
enabled: true,
|
|
103
|
-
element: el2,
|
|
104
|
-
onInteractOutside: onInteractOutside2,
|
|
105
|
-
behavior: 'close',
|
|
106
|
-
});
|
|
107
|
-
layer1.mount();
|
|
108
|
-
layer2.mount();
|
|
109
|
-
// Click outside both elements
|
|
110
|
-
pointerDownOutside(500, 500);
|
|
111
|
-
// Only topmost (layer2) should have been called
|
|
112
|
-
expect(onInteractOutside2).toHaveBeenCalledOnce();
|
|
113
|
-
expect(onInteractOutside1).not.toHaveBeenCalled();
|
|
114
|
-
layer2.unmount();
|
|
115
|
-
layer1.unmount();
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
describe('ignore behavior', () => {
|
|
119
|
-
it('respects ignore behavior — does not fire callback', () => {
|
|
120
|
-
const el = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
121
|
-
const onInteractOutside = vi.fn();
|
|
122
|
-
const layer = new DismissibleLayerState({
|
|
123
|
-
enabled: true,
|
|
124
|
-
element: el,
|
|
125
|
-
onInteractOutside,
|
|
126
|
-
behavior: 'ignore',
|
|
127
|
-
});
|
|
128
|
-
layer.mount();
|
|
129
|
-
pointerDownOutside(500, 500);
|
|
130
|
-
expect(onInteractOutside).not.toHaveBeenCalled();
|
|
131
|
-
layer.unmount();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
describe('defer-otherwise-close behavior', () => {
|
|
135
|
-
it('falls through to bottom layer', () => {
|
|
136
|
-
const el1 = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
137
|
-
const el2 = createElement({ top: 200, left: 200, right: 300, bottom: 300 });
|
|
138
|
-
const onInteractOutside1 = vi.fn();
|
|
139
|
-
const onInteractOutside2 = vi.fn();
|
|
140
|
-
const layer1 = new DismissibleLayerState({
|
|
141
|
-
enabled: true,
|
|
142
|
-
element: el1,
|
|
143
|
-
onInteractOutside: onInteractOutside1,
|
|
144
|
-
behavior: 'defer-otherwise-close',
|
|
145
|
-
});
|
|
146
|
-
const layer2 = new DismissibleLayerState({
|
|
147
|
-
enabled: true,
|
|
148
|
-
element: el2,
|
|
149
|
-
onInteractOutside: onInteractOutside2,
|
|
150
|
-
behavior: 'defer-otherwise-close',
|
|
151
|
-
});
|
|
152
|
-
layer1.mount();
|
|
153
|
-
layer2.mount();
|
|
154
|
-
// Click outside both elements
|
|
155
|
-
pointerDownOutside(500, 500);
|
|
156
|
-
// Top layer defers, bottom layer handles it
|
|
157
|
-
expect(onInteractOutside2).not.toHaveBeenCalled();
|
|
158
|
-
expect(onInteractOutside1).toHaveBeenCalledOnce();
|
|
159
|
-
layer2.unmount();
|
|
160
|
-
layer1.unmount();
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
describe('cleanup', () => {
|
|
164
|
-
it('cleans up when all layers unmount', () => {
|
|
165
|
-
const el = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
166
|
-
const onInteractOutside = vi.fn();
|
|
167
|
-
const layer = new DismissibleLayerState({
|
|
168
|
-
enabled: true,
|
|
169
|
-
element: el,
|
|
170
|
-
onInteractOutside,
|
|
171
|
-
behavior: 'close',
|
|
172
|
-
});
|
|
173
|
-
layer.mount();
|
|
174
|
-
layer.unmount();
|
|
175
|
-
// After unmount, clicking should NOT trigger anything
|
|
176
|
-
pointerDownOutside(500, 500);
|
|
177
|
-
expect(onInteractOutside).not.toHaveBeenCalled();
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
describe('enabled prop', () => {
|
|
181
|
-
it('respects enabled=false — does not register in stack', () => {
|
|
182
|
-
const el = createElement({ top: 0, left: 0, right: 100, bottom: 100 });
|
|
183
|
-
const onInteractOutside = vi.fn();
|
|
184
|
-
const layer = new DismissibleLayerState({
|
|
185
|
-
enabled: false,
|
|
186
|
-
element: el,
|
|
187
|
-
onInteractOutside,
|
|
188
|
-
behavior: 'close',
|
|
189
|
-
});
|
|
190
|
-
layer.mount();
|
|
191
|
-
pointerDownOutside(500, 500);
|
|
192
|
-
expect(onInteractOutside).not.toHaveBeenCalled();
|
|
193
|
-
layer.unmount();
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
});
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { AutoScroll } from '../auto-scroll.svelte.js';
|
|
3
|
-
function createScrollableElement(opts = {}) {
|
|
4
|
-
const el = document.createElement('div');
|
|
5
|
-
Object.defineProperty(el, 'getBoundingClientRect', {
|
|
6
|
-
value: () => ({
|
|
7
|
-
top: 0,
|
|
8
|
-
left: 0,
|
|
9
|
-
bottom: opts.height ?? 400,
|
|
10
|
-
right: opts.width ?? 400,
|
|
11
|
-
width: opts.width ?? 400,
|
|
12
|
-
height: opts.height ?? 400,
|
|
13
|
-
x: 0,
|
|
14
|
-
y: 0,
|
|
15
|
-
toJSON() { },
|
|
16
|
-
}),
|
|
17
|
-
});
|
|
18
|
-
// Make it scrollable
|
|
19
|
-
let _scrollTop = opts.scrollTop ?? 0;
|
|
20
|
-
let _scrollLeft = opts.scrollLeft ?? 0;
|
|
21
|
-
Object.defineProperty(el, 'scrollHeight', { value: opts.scrollHeight ?? 800 });
|
|
22
|
-
Object.defineProperty(el, 'scrollWidth', { value: opts.scrollWidth ?? 800 });
|
|
23
|
-
Object.defineProperty(el, 'clientHeight', { value: opts.height ?? 400 });
|
|
24
|
-
Object.defineProperty(el, 'clientWidth', { value: opts.width ?? 400 });
|
|
25
|
-
Object.defineProperty(el, 'scrollTop', {
|
|
26
|
-
get: () => _scrollTop,
|
|
27
|
-
set: (v) => {
|
|
28
|
-
_scrollTop = v;
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
Object.defineProperty(el, 'scrollLeft', {
|
|
32
|
-
get: () => _scrollLeft,
|
|
33
|
-
set: (v) => {
|
|
34
|
-
_scrollLeft = v;
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
// Mock getComputedStyle
|
|
38
|
-
vi.spyOn(window, 'getComputedStyle').mockReturnValue({
|
|
39
|
-
overflowY: opts.overflowY ?? 'auto',
|
|
40
|
-
overflowX: opts.overflowX ?? 'auto',
|
|
41
|
-
});
|
|
42
|
-
return el;
|
|
43
|
-
}
|
|
44
|
-
describe('autoScroll', () => {
|
|
45
|
-
let autoScroll;
|
|
46
|
-
beforeEach(() => {
|
|
47
|
-
autoScroll = new AutoScroll();
|
|
48
|
-
vi.useFakeTimers();
|
|
49
|
-
});
|
|
50
|
-
afterEach(() => {
|
|
51
|
-
autoScroll.teardown();
|
|
52
|
-
vi.restoreAllMocks();
|
|
53
|
-
vi.useRealTimers();
|
|
54
|
-
});
|
|
55
|
-
it('creates without error', () => {
|
|
56
|
-
expect(autoScroll).toBeDefined();
|
|
57
|
-
});
|
|
58
|
-
it('does not throw when moving without setup', () => {
|
|
59
|
-
expect(() => autoScroll.move(100, 100)).not.toThrow();
|
|
60
|
-
});
|
|
61
|
-
it('does not throw when tearing down without setup', () => {
|
|
62
|
-
expect(() => autoScroll.teardown()).not.toThrow();
|
|
63
|
-
});
|
|
64
|
-
it('sets up with a scrollable element', () => {
|
|
65
|
-
const el = createScrollableElement();
|
|
66
|
-
expect(() => autoScroll.setup(el)).not.toThrow();
|
|
67
|
-
});
|
|
68
|
-
it('detects top edge and would scroll up', () => {
|
|
69
|
-
const el = createScrollableElement({ scrollTop: 100 });
|
|
70
|
-
autoScroll.setup(el);
|
|
71
|
-
// Point near top edge (within 30px)
|
|
72
|
-
autoScroll.move(200, 10);
|
|
73
|
-
// Run one animation frame
|
|
74
|
-
vi.advanceTimersByTime(16);
|
|
75
|
-
// scrollTop should have decreased
|
|
76
|
-
expect(el.scrollTop).toBeLessThan(100);
|
|
77
|
-
});
|
|
78
|
-
it('detects bottom edge and would scroll down', () => {
|
|
79
|
-
const el = createScrollableElement({ height: 400, scrollHeight: 800, scrollTop: 0 });
|
|
80
|
-
autoScroll.setup(el);
|
|
81
|
-
// Point near bottom edge
|
|
82
|
-
autoScroll.move(200, 390);
|
|
83
|
-
vi.advanceTimersByTime(16);
|
|
84
|
-
expect(el.scrollTop).toBeGreaterThan(0);
|
|
85
|
-
});
|
|
86
|
-
it('does not scroll when pointer is in center', () => {
|
|
87
|
-
const el = createScrollableElement({ scrollTop: 100 });
|
|
88
|
-
autoScroll.setup(el);
|
|
89
|
-
// Point in center
|
|
90
|
-
autoScroll.move(200, 200);
|
|
91
|
-
vi.advanceTimersByTime(16);
|
|
92
|
-
expect(el.scrollTop).toBe(100); // unchanged
|
|
93
|
-
});
|
|
94
|
-
it('stops scrolling on teardown', () => {
|
|
95
|
-
const el = createScrollableElement({ scrollTop: 100 });
|
|
96
|
-
autoScroll.setup(el);
|
|
97
|
-
autoScroll.move(200, 10); // trigger scroll
|
|
98
|
-
autoScroll.teardown();
|
|
99
|
-
const scrollBefore = el.scrollTop;
|
|
100
|
-
vi.advanceTimersByTime(100);
|
|
101
|
-
// Should not have changed after teardown (or only 1 frame)
|
|
102
|
-
expect(Math.abs(el.scrollTop - scrollBefore)).toBeLessThanOrEqual(8); // max 1 frame of scroll
|
|
103
|
-
});
|
|
104
|
-
});
|