@furystack/shades-common-components 12.0.0 → 12.1.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/CHANGELOG.md +56 -0
- package/README.md +26 -0
- package/esm/components/cache-view.d.ts +46 -0
- package/esm/components/cache-view.d.ts.map +1 -0
- package/esm/components/cache-view.js +65 -0
- package/esm/components/cache-view.js.map +1 -0
- package/esm/components/cache-view.spec.d.ts +2 -0
- package/esm/components/cache-view.spec.d.ts.map +1 -0
- package/esm/components/cache-view.spec.js +183 -0
- package/esm/components/cache-view.spec.js.map +1 -0
- package/esm/components/command-palette/command-palette-input.spec.js +148 -148
- package/esm/components/command-palette/command-palette-input.spec.js.map +1 -1
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js +258 -258
- package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -1
- package/esm/components/context-menu/context-menu-manager.spec.js +211 -217
- package/esm/components/context-menu/context-menu-manager.spec.js.map +1 -1
- package/esm/components/data-grid/body.spec.js +173 -173
- package/esm/components/data-grid/body.spec.js.map +1 -1
- package/esm/components/data-grid/data-grid.spec.js +39 -130
- package/esm/components/data-grid/data-grid.spec.js.map +1 -1
- package/esm/components/index.d.ts +1 -0
- package/esm/components/index.d.ts.map +1 -1
- package/esm/components/index.js +1 -0
- package/esm/components/index.js.map +1 -1
- package/esm/components/skeleton.d.ts.map +1 -1
- package/esm/components/skeleton.js +2 -11
- package/esm/components/skeleton.js.map +1 -1
- package/esm/components/skeleton.spec.js +6 -55
- package/esm/components/skeleton.spec.js.map +1 -1
- package/esm/services/click-away-service.spec.js +14 -12
- package/esm/services/click-away-service.spec.js.map +1 -1
- package/esm/services/list-service.spec.js +170 -141
- package/esm/services/list-service.spec.js.map +1 -1
- package/esm/services/tree-service.spec.js +190 -159
- package/esm/services/tree-service.spec.js.map +1 -1
- package/package.json +8 -8
- package/src/components/cache-view.spec.tsx +210 -0
- package/src/components/cache-view.tsx +103 -0
- package/src/components/command-palette/command-palette-input.spec.tsx +183 -194
- package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +303 -321
- package/src/components/context-menu/context-menu-manager.spec.ts +213 -258
- package/src/components/data-grid/body.spec.tsx +266 -276
- package/src/components/data-grid/data-grid.spec.tsx +137 -232
- package/src/components/index.ts +1 -0
- package/src/components/skeleton.spec.tsx +6 -73
- package/src/components/skeleton.tsx +2 -11
- package/src/services/click-away-service.spec.ts +14 -16
- package/src/services/list-service.spec.ts +170 -172
- package/src/services/tree-service.spec.ts +191 -207
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { using } from '@furystack/utils'
|
|
1
2
|
import { describe, expect, it, vi } from 'vitest'
|
|
2
3
|
import type { ContextMenuItem } from './context-menu-manager.js'
|
|
3
4
|
import { ContextMenuManager } from './context-menu-manager.js'
|
|
@@ -15,447 +16,401 @@ describe('ContextMenuManager', () => {
|
|
|
15
16
|
|
|
16
17
|
describe('getNavigableIndices', () => {
|
|
17
18
|
it('should return indices of non-separator, non-disabled items', () => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const indices = manager.getNavigableIndices()
|
|
19
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
20
|
+
manager.items.setValue(createTestItems())
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
const indices = manager.getNavigableIndices()
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
expect(indices).toEqual([0, 1, 3])
|
|
25
|
+
})
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
it('should return empty array when there are no navigable items', () => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const indices = manager.getNavigableIndices()
|
|
29
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
30
|
+
manager.items.setValue([
|
|
31
|
+
{ type: 'separator' },
|
|
32
|
+
{ type: 'item', data: { id: 1, name: 'Disabled' }, label: 'Disabled', disabled: true },
|
|
33
|
+
])
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
const indices = manager.getNavigableIndices()
|
|
38
36
|
|
|
39
|
-
|
|
37
|
+
expect(indices).toEqual([])
|
|
38
|
+
})
|
|
40
39
|
})
|
|
41
40
|
|
|
42
41
|
it('should return empty array for empty items', () => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const indices = manager.getNavigableIndices()
|
|
46
|
-
|
|
47
|
-
expect(indices).toEqual([])
|
|
42
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
43
|
+
const indices = manager.getNavigableIndices()
|
|
48
44
|
|
|
49
|
-
|
|
45
|
+
expect(indices).toEqual([])
|
|
46
|
+
})
|
|
50
47
|
})
|
|
51
48
|
})
|
|
52
49
|
|
|
53
50
|
describe('open', () => {
|
|
54
51
|
it('should set isOpened to true', () => {
|
|
55
|
-
|
|
52
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
53
|
+
manager.open({ items: createTestItems(), position: { x: 100, y: 200 } })
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
expect(manager.isOpened.getValue()).toBe(true)
|
|
60
|
-
|
|
61
|
-
manager[Symbol.dispose]()
|
|
55
|
+
expect(manager.isOpened.getValue()).toBe(true)
|
|
56
|
+
})
|
|
62
57
|
})
|
|
63
58
|
|
|
64
59
|
it('should set items when provided', () => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
manager.open({ items, position: { x: 0, y: 0 } })
|
|
60
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
61
|
+
const items = createTestItems()
|
|
69
62
|
|
|
70
|
-
|
|
63
|
+
manager.open({ items, position: { x: 0, y: 0 } })
|
|
71
64
|
|
|
72
|
-
|
|
65
|
+
expect(manager.items.getValue()).toEqual(items)
|
|
66
|
+
})
|
|
73
67
|
})
|
|
74
68
|
|
|
75
69
|
it('should set position when provided', () => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
manager.open({ items: createTestItems(), position: { x: 150, y: 250 } })
|
|
79
|
-
|
|
80
|
-
expect(manager.position.getValue()).toEqual({ x: 150, y: 250 })
|
|
70
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
71
|
+
manager.open({ items: createTestItems(), position: { x: 150, y: 250 } })
|
|
81
72
|
|
|
82
|
-
|
|
73
|
+
expect(manager.position.getValue()).toEqual({ x: 150, y: 250 })
|
|
74
|
+
})
|
|
83
75
|
})
|
|
84
76
|
|
|
85
77
|
it('should focus the first navigable item', () => {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
89
|
-
|
|
90
|
-
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
78
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
79
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
91
80
|
|
|
92
|
-
|
|
81
|
+
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
82
|
+
})
|
|
93
83
|
})
|
|
94
84
|
|
|
95
85
|
it('should focus the first navigable item when first items are separators', () => {
|
|
96
|
-
|
|
86
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
87
|
+
manager.open({
|
|
88
|
+
items: [{ type: 'separator' }, { type: 'item', data: { id: 1, name: 'First' }, label: 'First' }],
|
|
89
|
+
position: { x: 0, y: 0 },
|
|
90
|
+
})
|
|
97
91
|
|
|
98
|
-
|
|
99
|
-
items: [{ type: 'separator' }, { type: 'item', data: { id: 1, name: 'First' }, label: 'First' }],
|
|
100
|
-
position: { x: 0, y: 0 },
|
|
92
|
+
expect(manager.focusedIndex.getValue()).toBe(1)
|
|
101
93
|
})
|
|
102
|
-
|
|
103
|
-
expect(manager.focusedIndex.getValue()).toBe(1)
|
|
104
|
-
|
|
105
|
-
manager[Symbol.dispose]()
|
|
106
94
|
})
|
|
107
95
|
|
|
108
96
|
it('should set focusedIndex to -1 when no navigable items exist', () => {
|
|
109
|
-
|
|
97
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
98
|
+
manager.open({
|
|
99
|
+
items: [{ type: 'separator' }],
|
|
100
|
+
position: { x: 0, y: 0 },
|
|
101
|
+
})
|
|
110
102
|
|
|
111
|
-
|
|
112
|
-
items: [{ type: 'separator' }],
|
|
113
|
-
position: { x: 0, y: 0 },
|
|
103
|
+
expect(manager.focusedIndex.getValue()).toBe(-1)
|
|
114
104
|
})
|
|
115
|
-
|
|
116
|
-
expect(manager.focusedIndex.getValue()).toBe(-1)
|
|
117
|
-
|
|
118
|
-
manager[Symbol.dispose]()
|
|
119
105
|
})
|
|
120
106
|
|
|
121
107
|
it('should keep existing items when items option is not provided', () => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
108
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
109
|
+
const items = createTestItems()
|
|
110
|
+
manager.items.setValue(items)
|
|
125
111
|
|
|
126
|
-
|
|
112
|
+
manager.open({ position: { x: 50, y: 50 } })
|
|
127
113
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
manager[Symbol.dispose]()
|
|
114
|
+
expect(manager.items.getValue()).toEqual(items)
|
|
115
|
+
expect(manager.isOpened.getValue()).toBe(true)
|
|
116
|
+
})
|
|
132
117
|
})
|
|
133
118
|
|
|
134
119
|
it('should keep existing position when position option is not provided', () => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
120
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
121
|
+
manager.position.setValue({ x: 100, y: 200 })
|
|
122
|
+
manager.items.setValue(createTestItems())
|
|
138
123
|
|
|
139
|
-
|
|
124
|
+
manager.open()
|
|
140
125
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
manager[Symbol.dispose]()
|
|
126
|
+
expect(manager.position.getValue()).toEqual({ x: 100, y: 200 })
|
|
127
|
+
expect(manager.isOpened.getValue()).toBe(true)
|
|
128
|
+
})
|
|
145
129
|
})
|
|
146
130
|
})
|
|
147
131
|
|
|
148
132
|
describe('close', () => {
|
|
149
133
|
it('should set isOpened to false', () => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
manager.close()
|
|
134
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
135
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
154
136
|
|
|
155
|
-
|
|
137
|
+
manager.close()
|
|
156
138
|
|
|
157
|
-
|
|
139
|
+
expect(manager.isOpened.getValue()).toBe(false)
|
|
140
|
+
})
|
|
158
141
|
})
|
|
159
142
|
|
|
160
143
|
it('should reset focusedIndex to -1', () => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
manager.close()
|
|
144
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
145
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
165
146
|
|
|
166
|
-
|
|
147
|
+
manager.close()
|
|
167
148
|
|
|
168
|
-
|
|
149
|
+
expect(manager.focusedIndex.getValue()).toBe(-1)
|
|
150
|
+
})
|
|
169
151
|
})
|
|
170
152
|
})
|
|
171
153
|
|
|
172
154
|
describe('selectItem', () => {
|
|
173
155
|
it('should emit onSelectItem event with the item data', () => {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
156
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
157
|
+
const items = createTestItems()
|
|
158
|
+
manager.open({ items, position: { x: 0, y: 0 } })
|
|
177
159
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
manager.selectItem(1)
|
|
160
|
+
const onSelect = vi.fn()
|
|
161
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
182
162
|
|
|
183
|
-
|
|
163
|
+
manager.selectItem(1)
|
|
184
164
|
|
|
185
|
-
|
|
186
|
-
|
|
165
|
+
expect(onSelect).toHaveBeenCalledWith({ id: 2, name: 'Copy' })
|
|
166
|
+
})
|
|
187
167
|
})
|
|
188
168
|
|
|
189
169
|
it('should close the menu after selection', () => {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
manager.selectItem(0)
|
|
170
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
171
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
194
172
|
|
|
195
|
-
|
|
173
|
+
manager.selectItem(0)
|
|
196
174
|
|
|
197
|
-
|
|
175
|
+
expect(manager.isOpened.getValue()).toBe(false)
|
|
176
|
+
})
|
|
198
177
|
})
|
|
199
178
|
|
|
200
179
|
it('should use the focused index when no index is provided', () => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const onSelect = vi.fn()
|
|
207
|
-
const subscription = manager.subscribe('onSelectItem', onSelect)
|
|
180
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
181
|
+
const items = createTestItems()
|
|
182
|
+
manager.open({ items, position: { x: 0, y: 0 } })
|
|
183
|
+
manager.focusedIndex.setValue(3)
|
|
208
184
|
|
|
209
|
-
|
|
185
|
+
const onSelect = vi.fn()
|
|
186
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
210
187
|
|
|
211
|
-
|
|
188
|
+
manager.selectItem()
|
|
212
189
|
|
|
213
|
-
|
|
214
|
-
|
|
190
|
+
expect(onSelect).toHaveBeenCalledWith({ id: 3, name: 'Paste' })
|
|
191
|
+
})
|
|
215
192
|
})
|
|
216
193
|
|
|
217
194
|
it('should not emit when selecting a separator', () => {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const onSelect = vi.fn()
|
|
222
|
-
const subscription = manager.subscribe('onSelectItem', onSelect)
|
|
195
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
196
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
223
197
|
|
|
224
|
-
|
|
198
|
+
const onSelect = vi.fn()
|
|
199
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
225
200
|
|
|
226
|
-
|
|
201
|
+
manager.selectItem(2)
|
|
227
202
|
|
|
228
|
-
|
|
229
|
-
|
|
203
|
+
expect(onSelect).not.toHaveBeenCalled()
|
|
204
|
+
})
|
|
230
205
|
})
|
|
231
206
|
|
|
232
207
|
it('should not emit when selecting a disabled item', () => {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const onSelect = vi.fn()
|
|
237
|
-
const subscription = manager.subscribe('onSelectItem', onSelect)
|
|
208
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
209
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
238
210
|
|
|
239
|
-
|
|
211
|
+
const onSelect = vi.fn()
|
|
212
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
240
213
|
|
|
241
|
-
|
|
214
|
+
manager.selectItem(4)
|
|
242
215
|
|
|
243
|
-
|
|
244
|
-
|
|
216
|
+
expect(onSelect).not.toHaveBeenCalled()
|
|
217
|
+
})
|
|
245
218
|
})
|
|
246
219
|
|
|
247
220
|
it('should not emit when item has no data', () => {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const onSelect = vi.fn()
|
|
255
|
-
const subscription = manager.subscribe('onSelectItem', onSelect)
|
|
221
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
222
|
+
manager.open({
|
|
223
|
+
items: [{ type: 'item', label: 'No data' }],
|
|
224
|
+
position: { x: 0, y: 0 },
|
|
225
|
+
})
|
|
256
226
|
|
|
257
|
-
|
|
227
|
+
const onSelect = vi.fn()
|
|
228
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
258
229
|
|
|
259
|
-
|
|
230
|
+
manager.selectItem(0)
|
|
260
231
|
|
|
261
|
-
|
|
262
|
-
|
|
232
|
+
expect(onSelect).not.toHaveBeenCalled()
|
|
233
|
+
})
|
|
263
234
|
})
|
|
264
235
|
})
|
|
265
236
|
|
|
266
237
|
describe('handleKeyDown', () => {
|
|
267
238
|
it('should not handle keyboard events when menu is closed', () => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
239
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
240
|
+
manager.items.setValue(createTestItems())
|
|
241
|
+
manager.focusedIndex.setValue(0)
|
|
273
242
|
|
|
274
|
-
|
|
243
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
275
244
|
|
|
276
|
-
|
|
245
|
+
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
246
|
+
})
|
|
277
247
|
})
|
|
278
248
|
|
|
279
249
|
describe('ArrowDown', () => {
|
|
280
250
|
it('should move focus to the next navigable item', () => {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
251
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
252
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
253
|
+
manager.focusedIndex.setValue(0)
|
|
286
254
|
|
|
287
|
-
|
|
255
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
288
256
|
|
|
289
|
-
|
|
257
|
+
expect(manager.focusedIndex.getValue()).toBe(1)
|
|
258
|
+
})
|
|
290
259
|
})
|
|
291
260
|
|
|
292
261
|
it('should skip separators', () => {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
262
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
263
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
264
|
+
manager.focusedIndex.setValue(1)
|
|
296
265
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
expect(manager.focusedIndex.getValue()).toBe(3)
|
|
266
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
300
267
|
|
|
301
|
-
|
|
268
|
+
expect(manager.focusedIndex.getValue()).toBe(3)
|
|
269
|
+
})
|
|
302
270
|
})
|
|
303
271
|
|
|
304
272
|
it('should skip disabled items', () => {
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
273
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
274
|
+
manager.open({
|
|
275
|
+
items: [
|
|
276
|
+
{ type: 'item', data: { id: 1, name: 'A' }, label: 'A' },
|
|
277
|
+
{ type: 'item', data: { id: 2, name: 'B' }, label: 'B', disabled: true },
|
|
278
|
+
{ type: 'item', data: { id: 3, name: 'C' }, label: 'C' },
|
|
279
|
+
],
|
|
280
|
+
position: { x: 0, y: 0 },
|
|
281
|
+
})
|
|
282
|
+
manager.focusedIndex.setValue(0)
|
|
283
|
+
|
|
284
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
285
|
+
|
|
286
|
+
expect(manager.focusedIndex.getValue()).toBe(2)
|
|
313
287
|
})
|
|
314
|
-
manager.focusedIndex.setValue(0)
|
|
315
|
-
|
|
316
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
317
|
-
|
|
318
|
-
expect(manager.focusedIndex.getValue()).toBe(2)
|
|
319
|
-
|
|
320
|
-
manager[Symbol.dispose]()
|
|
321
288
|
})
|
|
322
289
|
|
|
323
290
|
it('should wrap to first item when at the end', () => {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
291
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
292
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
293
|
+
manager.focusedIndex.setValue(3)
|
|
327
294
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
295
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
|
331
296
|
|
|
332
|
-
|
|
297
|
+
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
298
|
+
})
|
|
333
299
|
})
|
|
334
300
|
})
|
|
335
301
|
|
|
336
302
|
describe('ArrowUp', () => {
|
|
337
303
|
it('should move focus to the previous navigable item', () => {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
304
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
305
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
306
|
+
manager.focusedIndex.setValue(1)
|
|
343
307
|
|
|
344
|
-
|
|
308
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
345
309
|
|
|
346
|
-
|
|
310
|
+
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
311
|
+
})
|
|
347
312
|
})
|
|
348
313
|
|
|
349
314
|
it('should skip separators', () => {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
315
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
316
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
317
|
+
manager.focusedIndex.setValue(3)
|
|
355
318
|
|
|
356
|
-
|
|
319
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
357
320
|
|
|
358
|
-
|
|
321
|
+
expect(manager.focusedIndex.getValue()).toBe(1)
|
|
322
|
+
})
|
|
359
323
|
})
|
|
360
324
|
|
|
361
325
|
it('should wrap to last navigable item when at the beginning', () => {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
326
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
327
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
328
|
+
manager.focusedIndex.setValue(0)
|
|
367
329
|
|
|
368
|
-
|
|
330
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
|
369
331
|
|
|
370
|
-
|
|
332
|
+
expect(manager.focusedIndex.getValue()).toBe(3)
|
|
333
|
+
})
|
|
371
334
|
})
|
|
372
335
|
})
|
|
373
336
|
|
|
374
337
|
describe('Home', () => {
|
|
375
338
|
it('should move focus to the first navigable item', () => {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
339
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
340
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
341
|
+
manager.focusedIndex.setValue(3)
|
|
379
342
|
|
|
380
|
-
|
|
343
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Home' }))
|
|
381
344
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
manager[Symbol.dispose]()
|
|
345
|
+
expect(manager.focusedIndex.getValue()).toBe(0)
|
|
346
|
+
})
|
|
385
347
|
})
|
|
386
348
|
})
|
|
387
349
|
|
|
388
350
|
describe('End', () => {
|
|
389
351
|
it('should move focus to the last navigable item', () => {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'End' }))
|
|
352
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
353
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
354
|
+
manager.focusedIndex.setValue(0)
|
|
395
355
|
|
|
396
|
-
|
|
356
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'End' }))
|
|
397
357
|
|
|
398
|
-
|
|
358
|
+
expect(manager.focusedIndex.getValue()).toBe(3)
|
|
359
|
+
})
|
|
399
360
|
})
|
|
400
361
|
})
|
|
401
362
|
|
|
402
363
|
describe('Enter', () => {
|
|
403
364
|
it('should select the focused item', () => {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const onSelect = vi.fn()
|
|
408
|
-
const subscription = manager.subscribe('onSelectItem', onSelect)
|
|
365
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
366
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
409
367
|
|
|
410
|
-
|
|
411
|
-
|
|
368
|
+
const onSelect = vi.fn()
|
|
369
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
412
370
|
|
|
413
|
-
|
|
371
|
+
manager.focusedIndex.setValue(1)
|
|
372
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
|
|
414
373
|
|
|
415
|
-
|
|
416
|
-
|
|
374
|
+
expect(onSelect).toHaveBeenCalledWith({ id: 2, name: 'Copy' })
|
|
375
|
+
})
|
|
417
376
|
})
|
|
418
377
|
|
|
419
378
|
it('should not select when no item is focused', () => {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
379
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
380
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
381
|
+
manager.focusedIndex.setValue(-1)
|
|
423
382
|
|
|
424
|
-
|
|
425
|
-
|
|
383
|
+
const onSelect = vi.fn()
|
|
384
|
+
manager.subscribe('onSelectItem', onSelect)
|
|
426
385
|
|
|
427
|
-
|
|
386
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
|
|
428
387
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
subscription[Symbol.dispose]()
|
|
432
|
-
manager[Symbol.dispose]()
|
|
388
|
+
expect(onSelect).not.toHaveBeenCalled()
|
|
389
|
+
})
|
|
433
390
|
})
|
|
434
391
|
|
|
435
392
|
it('should close the menu after selection', () => {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
393
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
394
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
395
|
+
manager.focusedIndex.setValue(0)
|
|
439
396
|
|
|
440
|
-
|
|
397
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
|
|
441
398
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
manager[Symbol.dispose]()
|
|
399
|
+
expect(manager.isOpened.getValue()).toBe(false)
|
|
400
|
+
})
|
|
445
401
|
})
|
|
446
402
|
})
|
|
447
403
|
|
|
448
404
|
describe('Escape', () => {
|
|
449
405
|
it('should close the menu', () => {
|
|
450
|
-
|
|
451
|
-
|
|
406
|
+
using(new ContextMenuManager<TestData>(), (manager) => {
|
|
407
|
+
manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
|
|
452
408
|
|
|
453
|
-
|
|
409
|
+
manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Escape' }))
|
|
454
410
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
manager[Symbol.dispose]()
|
|
411
|
+
expect(manager.isOpened.getValue()).toBe(false)
|
|
412
|
+
expect(manager.focusedIndex.getValue()).toBe(-1)
|
|
413
|
+
})
|
|
459
414
|
})
|
|
460
415
|
})
|
|
461
416
|
})
|