@furystack/shades-common-components 12.0.0 → 12.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/esm/components/command-palette/command-palette-input.spec.js +148 -148
  3. package/esm/components/command-palette/command-palette-input.spec.js.map +1 -1
  4. package/esm/components/command-palette/command-palette-suggestion-list.spec.js +258 -258
  5. package/esm/components/command-palette/command-palette-suggestion-list.spec.js.map +1 -1
  6. package/esm/components/context-menu/context-menu-manager.spec.js +211 -217
  7. package/esm/components/context-menu/context-menu-manager.spec.js.map +1 -1
  8. package/esm/components/data-grid/body.spec.js +173 -173
  9. package/esm/components/data-grid/body.spec.js.map +1 -1
  10. package/esm/components/data-grid/data-grid.spec.js +39 -130
  11. package/esm/components/data-grid/data-grid.spec.js.map +1 -1
  12. package/esm/services/click-away-service.spec.js +14 -12
  13. package/esm/services/click-away-service.spec.js.map +1 -1
  14. package/esm/services/list-service.spec.js +170 -141
  15. package/esm/services/list-service.spec.js.map +1 -1
  16. package/esm/services/tree-service.spec.js +190 -159
  17. package/esm/services/tree-service.spec.js.map +1 -1
  18. package/package.json +7 -8
  19. package/src/components/command-palette/command-palette-input.spec.tsx +183 -194
  20. package/src/components/command-palette/command-palette-suggestion-list.spec.tsx +303 -321
  21. package/src/components/context-menu/context-menu-manager.spec.ts +213 -258
  22. package/src/components/data-grid/body.spec.tsx +266 -276
  23. package/src/components/data-grid/data-grid.spec.tsx +137 -232
  24. package/src/services/click-away-service.spec.ts +14 -16
  25. package/src/services/list-service.spec.ts +170 -172
  26. 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
- const manager = new ContextMenuManager<TestData>()
19
- manager.items.setValue(createTestItems())
20
-
21
- const indices = manager.getNavigableIndices()
19
+ using(new ContextMenuManager<TestData>(), (manager) => {
20
+ manager.items.setValue(createTestItems())
22
21
 
23
- expect(indices).toEqual([0, 1, 3])
22
+ const indices = manager.getNavigableIndices()
24
23
 
25
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
30
- manager.items.setValue([
31
- { type: 'separator' },
32
- { type: 'item', data: { id: 1, name: 'Disabled' }, label: 'Disabled', disabled: true },
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
- expect(indices).toEqual([])
35
+ const indices = manager.getNavigableIndices()
38
36
 
39
- manager[Symbol.dispose]()
37
+ expect(indices).toEqual([])
38
+ })
40
39
  })
41
40
 
42
41
  it('should return empty array for empty items', () => {
43
- const manager = new ContextMenuManager<TestData>()
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
- manager[Symbol.dispose]()
45
+ expect(indices).toEqual([])
46
+ })
50
47
  })
51
48
  })
52
49
 
53
50
  describe('open', () => {
54
51
  it('should set isOpened to true', () => {
55
- const manager = new ContextMenuManager<TestData>()
52
+ using(new ContextMenuManager<TestData>(), (manager) => {
53
+ manager.open({ items: createTestItems(), position: { x: 100, y: 200 } })
56
54
 
57
- manager.open({ items: createTestItems(), position: { x: 100, y: 200 } })
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
- const manager = new ContextMenuManager<TestData>()
66
- const items = createTestItems()
67
-
68
- manager.open({ items, position: { x: 0, y: 0 } })
60
+ using(new ContextMenuManager<TestData>(), (manager) => {
61
+ const items = createTestItems()
69
62
 
70
- expect(manager.items.getValue()).toEqual(items)
63
+ manager.open({ items, position: { x: 0, y: 0 } })
71
64
 
72
- manager[Symbol.dispose]()
65
+ expect(manager.items.getValue()).toEqual(items)
66
+ })
73
67
  })
74
68
 
75
69
  it('should set position when provided', () => {
76
- const manager = new ContextMenuManager<TestData>()
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
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
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
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
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
- manager.open({
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
- const manager = new ContextMenuManager<TestData>()
97
+ using(new ContextMenuManager<TestData>(), (manager) => {
98
+ manager.open({
99
+ items: [{ type: 'separator' }],
100
+ position: { x: 0, y: 0 },
101
+ })
110
102
 
111
- manager.open({
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
- const manager = new ContextMenuManager<TestData>()
123
- const items = createTestItems()
124
- manager.items.setValue(items)
108
+ using(new ContextMenuManager<TestData>(), (manager) => {
109
+ const items = createTestItems()
110
+ manager.items.setValue(items)
125
111
 
126
- manager.open({ position: { x: 50, y: 50 } })
112
+ manager.open({ position: { x: 50, y: 50 } })
127
113
 
128
- expect(manager.items.getValue()).toEqual(items)
129
- expect(manager.isOpened.getValue()).toBe(true)
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
- const manager = new ContextMenuManager<TestData>()
136
- manager.position.setValue({ x: 100, y: 200 })
137
- manager.items.setValue(createTestItems())
120
+ using(new ContextMenuManager<TestData>(), (manager) => {
121
+ manager.position.setValue({ x: 100, y: 200 })
122
+ manager.items.setValue(createTestItems())
138
123
 
139
- manager.open()
124
+ manager.open()
140
125
 
141
- expect(manager.position.getValue()).toEqual({ x: 100, y: 200 })
142
- expect(manager.isOpened.getValue()).toBe(true)
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
- const manager = new ContextMenuManager<TestData>()
151
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
152
-
153
- manager.close()
134
+ using(new ContextMenuManager<TestData>(), (manager) => {
135
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
154
136
 
155
- expect(manager.isOpened.getValue()).toBe(false)
137
+ manager.close()
156
138
 
157
- manager[Symbol.dispose]()
139
+ expect(manager.isOpened.getValue()).toBe(false)
140
+ })
158
141
  })
159
142
 
160
143
  it('should reset focusedIndex to -1', () => {
161
- const manager = new ContextMenuManager<TestData>()
162
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
163
-
164
- manager.close()
144
+ using(new ContextMenuManager<TestData>(), (manager) => {
145
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
165
146
 
166
- expect(manager.focusedIndex.getValue()).toBe(-1)
147
+ manager.close()
167
148
 
168
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
175
- const items = createTestItems()
176
- manager.open({ items, position: { x: 0, y: 0 } })
156
+ using(new ContextMenuManager<TestData>(), (manager) => {
157
+ const items = createTestItems()
158
+ manager.open({ items, position: { x: 0, y: 0 } })
177
159
 
178
- const onSelect = vi.fn()
179
- const subscription = manager.subscribe('onSelectItem', onSelect)
180
-
181
- manager.selectItem(1)
160
+ const onSelect = vi.fn()
161
+ manager.subscribe('onSelectItem', onSelect)
182
162
 
183
- expect(onSelect).toHaveBeenCalledWith({ id: 2, name: 'Copy' })
163
+ manager.selectItem(1)
184
164
 
185
- subscription[Symbol.dispose]()
186
- manager[Symbol.dispose]()
165
+ expect(onSelect).toHaveBeenCalledWith({ id: 2, name: 'Copy' })
166
+ })
187
167
  })
188
168
 
189
169
  it('should close the menu after selection', () => {
190
- const manager = new ContextMenuManager<TestData>()
191
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
192
-
193
- manager.selectItem(0)
170
+ using(new ContextMenuManager<TestData>(), (manager) => {
171
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
194
172
 
195
- expect(manager.isOpened.getValue()).toBe(false)
173
+ manager.selectItem(0)
196
174
 
197
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
202
- const items = createTestItems()
203
- manager.open({ items, position: { x: 0, y: 0 } })
204
- manager.focusedIndex.setValue(3)
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
- manager.selectItem()
185
+ const onSelect = vi.fn()
186
+ manager.subscribe('onSelectItem', onSelect)
210
187
 
211
- expect(onSelect).toHaveBeenCalledWith({ id: 3, name: 'Paste' })
188
+ manager.selectItem()
212
189
 
213
- subscription[Symbol.dispose]()
214
- manager[Symbol.dispose]()
190
+ expect(onSelect).toHaveBeenCalledWith({ id: 3, name: 'Paste' })
191
+ })
215
192
  })
216
193
 
217
194
  it('should not emit when selecting a separator', () => {
218
- const manager = new ContextMenuManager<TestData>()
219
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
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
- manager.selectItem(2)
198
+ const onSelect = vi.fn()
199
+ manager.subscribe('onSelectItem', onSelect)
225
200
 
226
- expect(onSelect).not.toHaveBeenCalled()
201
+ manager.selectItem(2)
227
202
 
228
- subscription[Symbol.dispose]()
229
- manager[Symbol.dispose]()
203
+ expect(onSelect).not.toHaveBeenCalled()
204
+ })
230
205
  })
231
206
 
232
207
  it('should not emit when selecting a disabled item', () => {
233
- const manager = new ContextMenuManager<TestData>()
234
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
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
- manager.selectItem(4)
211
+ const onSelect = vi.fn()
212
+ manager.subscribe('onSelectItem', onSelect)
240
213
 
241
- expect(onSelect).not.toHaveBeenCalled()
214
+ manager.selectItem(4)
242
215
 
243
- subscription[Symbol.dispose]()
244
- manager[Symbol.dispose]()
216
+ expect(onSelect).not.toHaveBeenCalled()
217
+ })
245
218
  })
246
219
 
247
220
  it('should not emit when item has no data', () => {
248
- const manager = new ContextMenuManager<TestData>()
249
- manager.open({
250
- items: [{ type: 'item', label: 'No data' }],
251
- position: { x: 0, y: 0 },
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
- manager.selectItem(0)
227
+ const onSelect = vi.fn()
228
+ manager.subscribe('onSelectItem', onSelect)
258
229
 
259
- expect(onSelect).not.toHaveBeenCalled()
230
+ manager.selectItem(0)
260
231
 
261
- subscription[Symbol.dispose]()
262
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
269
- manager.items.setValue(createTestItems())
270
- manager.focusedIndex.setValue(0)
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
- expect(manager.focusedIndex.getValue()).toBe(0)
243
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
275
244
 
276
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
282
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
283
- manager.focusedIndex.setValue(0)
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
- expect(manager.focusedIndex.getValue()).toBe(1)
255
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
288
256
 
289
- manager[Symbol.dispose]()
257
+ expect(manager.focusedIndex.getValue()).toBe(1)
258
+ })
290
259
  })
291
260
 
292
261
  it('should skip separators', () => {
293
- const manager = new ContextMenuManager<TestData>()
294
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
295
- manager.focusedIndex.setValue(1)
262
+ using(new ContextMenuManager<TestData>(), (manager) => {
263
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
264
+ manager.focusedIndex.setValue(1)
296
265
 
297
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
298
-
299
- expect(manager.focusedIndex.getValue()).toBe(3)
266
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
300
267
 
301
- manager[Symbol.dispose]()
268
+ expect(manager.focusedIndex.getValue()).toBe(3)
269
+ })
302
270
  })
303
271
 
304
272
  it('should skip disabled items', () => {
305
- const manager = new ContextMenuManager<TestData>()
306
- manager.open({
307
- items: [
308
- { type: 'item', data: { id: 1, name: 'A' }, label: 'A' },
309
- { type: 'item', data: { id: 2, name: 'B' }, label: 'B', disabled: true },
310
- { type: 'item', data: { id: 3, name: 'C' }, label: 'C' },
311
- ],
312
- position: { x: 0, y: 0 },
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
- const manager = new ContextMenuManager<TestData>()
325
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
326
- manager.focusedIndex.setValue(3)
291
+ using(new ContextMenuManager<TestData>(), (manager) => {
292
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
293
+ manager.focusedIndex.setValue(3)
327
294
 
328
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
329
-
330
- expect(manager.focusedIndex.getValue()).toBe(0)
295
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
331
296
 
332
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
339
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
340
- manager.focusedIndex.setValue(1)
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
- expect(manager.focusedIndex.getValue()).toBe(0)
308
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
345
309
 
346
- manager[Symbol.dispose]()
310
+ expect(manager.focusedIndex.getValue()).toBe(0)
311
+ })
347
312
  })
348
313
 
349
314
  it('should skip separators', () => {
350
- const manager = new ContextMenuManager<TestData>()
351
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
352
- manager.focusedIndex.setValue(3)
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
- expect(manager.focusedIndex.getValue()).toBe(1)
319
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
357
320
 
358
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
363
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
364
- manager.focusedIndex.setValue(0)
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
- expect(manager.focusedIndex.getValue()).toBe(3)
330
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
369
331
 
370
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
377
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
378
- manager.focusedIndex.setValue(3)
339
+ using(new ContextMenuManager<TestData>(), (manager) => {
340
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
341
+ manager.focusedIndex.setValue(3)
379
342
 
380
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Home' }))
343
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Home' }))
381
344
 
382
- expect(manager.focusedIndex.getValue()).toBe(0)
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
- const manager = new ContextMenuManager<TestData>()
391
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
392
- manager.focusedIndex.setValue(0)
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
- expect(manager.focusedIndex.getValue()).toBe(3)
356
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'End' }))
397
357
 
398
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
405
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
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
- manager.focusedIndex.setValue(1)
411
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
368
+ const onSelect = vi.fn()
369
+ manager.subscribe('onSelectItem', onSelect)
412
370
 
413
- expect(onSelect).toHaveBeenCalledWith({ id: 2, name: 'Copy' })
371
+ manager.focusedIndex.setValue(1)
372
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
414
373
 
415
- subscription[Symbol.dispose]()
416
- manager[Symbol.dispose]()
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
- const manager = new ContextMenuManager<TestData>()
421
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
422
- manager.focusedIndex.setValue(-1)
379
+ using(new ContextMenuManager<TestData>(), (manager) => {
380
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
381
+ manager.focusedIndex.setValue(-1)
423
382
 
424
- const onSelect = vi.fn()
425
- const subscription = manager.subscribe('onSelectItem', onSelect)
383
+ const onSelect = vi.fn()
384
+ manager.subscribe('onSelectItem', onSelect)
426
385
 
427
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
386
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
428
387
 
429
- expect(onSelect).not.toHaveBeenCalled()
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
- const manager = new ContextMenuManager<TestData>()
437
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
438
- manager.focusedIndex.setValue(0)
393
+ using(new ContextMenuManager<TestData>(), (manager) => {
394
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
395
+ manager.focusedIndex.setValue(0)
439
396
 
440
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
397
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Enter' }))
441
398
 
442
- expect(manager.isOpened.getValue()).toBe(false)
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
- const manager = new ContextMenuManager<TestData>()
451
- manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
406
+ using(new ContextMenuManager<TestData>(), (manager) => {
407
+ manager.open({ items: createTestItems(), position: { x: 0, y: 0 } })
452
408
 
453
- manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Escape' }))
409
+ manager.handleKeyDown(new KeyboardEvent('keydown', { key: 'Escape' }))
454
410
 
455
- expect(manager.isOpened.getValue()).toBe(false)
456
- expect(manager.focusedIndex.getValue()).toBe(-1)
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
  })