@pyreon/dnd 0.11.4 → 0.11.6

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.
@@ -1,24 +1,24 @@
1
- import { signal } from "@pyreon/reactivity"
2
- import { describe, expect, it } from "vitest"
1
+ import { signal } from '@pyreon/reactivity'
2
+ import { describe, expect, it } from 'vitest'
3
3
 
4
4
  // ─── useDraggable ───────────────────────────────────────────────────────────
5
5
 
6
- describe("useDraggable", () => {
7
- it("exports useDraggable", async () => {
8
- const { useDraggable } = await import("../index")
9
- expect(typeof useDraggable).toBe("function")
6
+ describe('useDraggable', () => {
7
+ it('exports useDraggable', async () => {
8
+ const { useDraggable } = await import('../index')
9
+ expect(typeof useDraggable).toBe('function')
10
10
  })
11
11
 
12
- it("returns isDragging signal initialized to false", async () => {
13
- const { useDraggable } = await import("../use-draggable")
14
- const el = document.createElement("div")
15
- const { isDragging } = useDraggable({ element: () => el, data: { id: "1" } })
12
+ it('returns isDragging signal initialized to false', async () => {
13
+ const { useDraggable } = await import('../use-draggable')
14
+ const el = document.createElement('div')
15
+ const { isDragging } = useDraggable({ element: () => el, data: { id: '1' } })
16
16
  expect(isDragging()).toBe(false)
17
17
  })
18
18
 
19
- it("accepts function data for dynamic values", async () => {
20
- const { useDraggable } = await import("../use-draggable")
21
- const el = document.createElement("div")
19
+ it('accepts function data for dynamic values', async () => {
20
+ const { useDraggable } = await import('../use-draggable')
21
+ const el = document.createElement('div')
22
22
  const counter = signal(0)
23
23
  const { isDragging } = useDraggable({
24
24
  element: () => el,
@@ -27,34 +27,34 @@ describe("useDraggable", () => {
27
27
  expect(isDragging()).toBe(false)
28
28
  })
29
29
 
30
- it("accepts disabled as boolean", async () => {
31
- const { useDraggable } = await import("../use-draggable")
32
- const el = document.createElement("div")
30
+ it('accepts disabled as boolean', async () => {
31
+ const { useDraggable } = await import('../use-draggable')
32
+ const el = document.createElement('div')
33
33
  const { isDragging } = useDraggable({
34
34
  element: () => el,
35
- data: { id: "1" },
35
+ data: { id: '1' },
36
36
  disabled: true,
37
37
  })
38
38
  expect(isDragging()).toBe(false)
39
39
  })
40
40
 
41
- it("accepts disabled as reactive getter", async () => {
42
- const { useDraggable } = await import("../use-draggable")
43
- const el = document.createElement("div")
41
+ it('accepts disabled as reactive getter', async () => {
42
+ const { useDraggable } = await import('../use-draggable')
43
+ const el = document.createElement('div')
44
44
  const disabled = signal(false)
45
45
  const { isDragging } = useDraggable({
46
46
  element: () => el,
47
- data: { id: "1" },
47
+ data: { id: '1' },
48
48
  disabled,
49
49
  })
50
50
  expect(isDragging()).toBe(false)
51
51
  })
52
52
 
53
- it("handles null element gracefully", async () => {
54
- const { useDraggable } = await import("../use-draggable")
53
+ it('handles null element gracefully', async () => {
54
+ const { useDraggable } = await import('../use-draggable')
55
55
  const { isDragging } = useDraggable({
56
56
  element: () => null,
57
- data: { id: "1" },
57
+ data: { id: '1' },
58
58
  })
59
59
  expect(isDragging()).toBe(false)
60
60
  })
@@ -62,32 +62,32 @@ describe("useDraggable", () => {
62
62
 
63
63
  // ─── useDroppable ───────────────────────────────────────────────────────────
64
64
 
65
- describe("useDroppable", () => {
66
- it("exports useDroppable", async () => {
67
- const { useDroppable } = await import("../index")
68
- expect(typeof useDroppable).toBe("function")
65
+ describe('useDroppable', () => {
66
+ it('exports useDroppable', async () => {
67
+ const { useDroppable } = await import('../index')
68
+ expect(typeof useDroppable).toBe('function')
69
69
  })
70
70
 
71
- it("returns isOver signal initialized to false", async () => {
72
- const { useDroppable } = await import("../use-droppable")
73
- const el = document.createElement("div")
71
+ it('returns isOver signal initialized to false', async () => {
72
+ const { useDroppable } = await import('../use-droppable')
73
+ const el = document.createElement('div')
74
74
  const { isOver } = useDroppable({ element: () => el, onDrop: () => {} })
75
75
  expect(isOver()).toBe(false)
76
76
  })
77
77
 
78
- it("accepts canDrop filter", async () => {
79
- const { useDroppable } = await import("../use-droppable")
80
- const el = document.createElement("div")
78
+ it('accepts canDrop filter', async () => {
79
+ const { useDroppable } = await import('../use-droppable')
80
+ const el = document.createElement('div')
81
81
  const { isOver } = useDroppable({
82
82
  element: () => el,
83
- canDrop: (data) => data.type === "card",
83
+ canDrop: (data) => data.type === 'card',
84
84
  onDrop: () => {},
85
85
  })
86
86
  expect(isOver()).toBe(false)
87
87
  })
88
88
 
89
- it("handles null element gracefully", async () => {
90
- const { useDroppable } = await import("../use-droppable")
89
+ it('handles null element gracefully', async () => {
90
+ const { useDroppable } = await import('../use-droppable')
91
91
  const { isOver } = useDroppable({ element: () => null, onDrop: () => {} })
92
92
  expect(isOver()).toBe(false)
93
93
  })
@@ -95,18 +95,18 @@ describe("useDroppable", () => {
95
95
 
96
96
  // ─── useSortable ────────────────────────────────────────────────────────────
97
97
 
98
- describe("useSortable", () => {
99
- it("exports useSortable", async () => {
100
- const { useSortable } = await import("../index")
101
- expect(typeof useSortable).toBe("function")
98
+ describe('useSortable', () => {
99
+ it('exports useSortable', async () => {
100
+ const { useSortable } = await import('../index')
101
+ expect(typeof useSortable).toBe('function')
102
102
  })
103
103
 
104
- it("returns full sortable API with overEdge", async () => {
105
- const { useSortable } = await import("../use-sortable")
104
+ it('returns full sortable API with overEdge', async () => {
105
+ const { useSortable } = await import('../use-sortable')
106
106
  const items = signal([
107
- { id: "1", name: "A" },
108
- { id: "2", name: "B" },
109
- { id: "3", name: "C" },
107
+ { id: '1', name: 'A' },
108
+ { id: '2', name: 'B' },
109
+ { id: '3', name: 'C' },
110
110
  ])
111
111
 
112
112
  const result = useSortable({
@@ -115,16 +115,16 @@ describe("useSortable", () => {
115
115
  onReorder: (newItems) => items.set(newItems),
116
116
  })
117
117
 
118
- expect(typeof result.containerRef).toBe("function")
119
- expect(typeof result.itemRef).toBe("function")
118
+ expect(typeof result.containerRef).toBe('function')
119
+ expect(typeof result.itemRef).toBe('function')
120
120
  expect(result.activeId()).toBeNull()
121
121
  expect(result.overId()).toBeNull()
122
122
  expect(result.overEdge()).toBeNull()
123
123
  })
124
124
 
125
- it("itemRef returns a ref callback per key", async () => {
126
- const { useSortable } = await import("../use-sortable")
127
- const items = signal([{ id: "1" }, { id: "2" }])
125
+ it('itemRef returns a ref callback per key', async () => {
126
+ const { useSortable } = await import('../use-sortable')
127
+ const items = signal([{ id: '1' }, { id: '2' }])
128
128
 
129
129
  const { itemRef } = useSortable({
130
130
  items,
@@ -132,16 +132,16 @@ describe("useSortable", () => {
132
132
  onReorder: () => {},
133
133
  })
134
134
 
135
- const ref1 = itemRef("1")
136
- const ref2 = itemRef("2")
137
- expect(typeof ref1).toBe("function")
138
- expect(typeof ref2).toBe("function")
135
+ const ref1 = itemRef('1')
136
+ const ref2 = itemRef('2')
137
+ expect(typeof ref1).toBe('function')
138
+ expect(typeof ref2).toBe('function')
139
139
  expect(ref1).not.toBe(ref2)
140
140
  })
141
141
 
142
- it("itemRef sets accessibility attributes on elements", async () => {
143
- const { useSortable } = await import("../use-sortable")
144
- const items = signal([{ id: "1" }])
142
+ it('itemRef sets accessibility attributes on elements', async () => {
143
+ const { useSortable } = await import('../use-sortable')
144
+ const items = signal([{ id: '1' }])
145
145
 
146
146
  const { itemRef } = useSortable({
147
147
  items,
@@ -149,18 +149,18 @@ describe("useSortable", () => {
149
149
  onReorder: () => {},
150
150
  })
151
151
 
152
- const el = document.createElement("div")
153
- itemRef("1")(el)
152
+ const el = document.createElement('div')
153
+ itemRef('1')(el)
154
154
 
155
- expect(el.getAttribute("role")).toBe("listitem")
156
- expect(el.getAttribute("aria-roledescription")).toBe("sortable item")
157
- expect(el.getAttribute("tabindex")).toBe("0")
158
- expect(el.dataset.pyreonSortKey).toBe("1")
155
+ expect(el.getAttribute('role')).toBe('listitem')
156
+ expect(el.getAttribute('aria-roledescription')).toBe('sortable item')
157
+ expect(el.getAttribute('tabindex')).toBe('0')
158
+ expect(el.dataset.pyreonSortKey).toBe('1')
159
159
  })
160
160
 
161
- it("does not override existing tabindex", async () => {
162
- const { useSortable } = await import("../use-sortable")
163
- const items = signal([{ id: "1" }])
161
+ it('does not override existing tabindex', async () => {
162
+ const { useSortable } = await import('../use-sortable')
163
+ const items = signal([{ id: '1' }])
164
164
 
165
165
  const { itemRef } = useSortable({
166
166
  items,
@@ -168,22 +168,22 @@ describe("useSortable", () => {
168
168
  onReorder: () => {},
169
169
  })
170
170
 
171
- const el = document.createElement("div")
172
- el.setAttribute("tabindex", "-1")
173
- itemRef("1")(el)
171
+ const el = document.createElement('div')
172
+ el.setAttribute('tabindex', '-1')
173
+ itemRef('1')(el)
174
174
 
175
- expect(el.getAttribute("tabindex")).toBe("-1")
175
+ expect(el.getAttribute('tabindex')).toBe('-1')
176
176
  })
177
177
 
178
- it("supports horizontal axis", async () => {
179
- const { useSortable } = await import("../use-sortable")
180
- const items = signal([{ id: "1" }, { id: "2" }])
178
+ it('supports horizontal axis', async () => {
179
+ const { useSortable } = await import('../use-sortable')
180
+ const items = signal([{ id: '1' }, { id: '2' }])
181
181
 
182
182
  const result = useSortable({
183
183
  items,
184
184
  by: (item) => item.id,
185
185
  onReorder: () => {},
186
- axis: "horizontal",
186
+ axis: 'horizontal',
187
187
  })
188
188
 
189
189
  expect(result.activeId()).toBeNull()
@@ -192,15 +192,15 @@ describe("useSortable", () => {
192
192
 
193
193
  // ─── useFileDrop ────────────────────────────────────────────────────────────
194
194
 
195
- describe("useFileDrop", () => {
196
- it("exports useFileDrop", async () => {
197
- const { useFileDrop } = await import("../index")
198
- expect(typeof useFileDrop).toBe("function")
195
+ describe('useFileDrop', () => {
196
+ it('exports useFileDrop', async () => {
197
+ const { useFileDrop } = await import('../index')
198
+ expect(typeof useFileDrop).toBe('function')
199
199
  })
200
200
 
201
- it("returns isOver and isDraggingFiles signals", async () => {
202
- const { useFileDrop } = await import("../use-file-drop")
203
- const el = document.createElement("div")
201
+ it('returns isOver and isDraggingFiles signals', async () => {
202
+ const { useFileDrop } = await import('../use-file-drop')
203
+ const el = document.createElement('div')
204
204
  const { isOver, isDraggingFiles } = useFileDrop({
205
205
  element: () => el,
206
206
  onDrop: () => {},
@@ -209,21 +209,21 @@ describe("useFileDrop", () => {
209
209
  expect(isDraggingFiles()).toBe(false)
210
210
  })
211
211
 
212
- it("accepts accept filter and maxFiles", async () => {
213
- const { useFileDrop } = await import("../use-file-drop")
214
- const el = document.createElement("div")
212
+ it('accepts accept filter and maxFiles', async () => {
213
+ const { useFileDrop } = await import('../use-file-drop')
214
+ const el = document.createElement('div')
215
215
  const { isOver } = useFileDrop({
216
216
  element: () => el,
217
- accept: ["image/*", ".pdf"],
217
+ accept: ['image/*', '.pdf'],
218
218
  maxFiles: 5,
219
219
  onDrop: () => {},
220
220
  })
221
221
  expect(isOver()).toBe(false)
222
222
  })
223
223
 
224
- it("accepts disabled option", async () => {
225
- const { useFileDrop } = await import("../use-file-drop")
226
- const el = document.createElement("div")
224
+ it('accepts disabled option', async () => {
225
+ const { useFileDrop } = await import('../use-file-drop')
226
+ const el = document.createElement('div')
227
227
  const disabled = signal(true)
228
228
  const { isOver } = useFileDrop({
229
229
  element: () => el,
@@ -236,29 +236,29 @@ describe("useFileDrop", () => {
236
236
 
237
237
  // ─── useDragMonitor ─────────────────────────────────────────────────────────
238
238
 
239
- describe("useDragMonitor", () => {
240
- it("exports useDragMonitor", async () => {
241
- const { useDragMonitor } = await import("../index")
242
- expect(typeof useDragMonitor).toBe("function")
239
+ describe('useDragMonitor', () => {
240
+ it('exports useDragMonitor', async () => {
241
+ const { useDragMonitor } = await import('../index')
242
+ expect(typeof useDragMonitor).toBe('function')
243
243
  })
244
244
 
245
- it("returns isDragging and dragData signals", async () => {
246
- const { useDragMonitor } = await import("../use-drag-monitor")
245
+ it('returns isDragging and dragData signals', async () => {
246
+ const { useDragMonitor } = await import('../use-drag-monitor')
247
247
  const { isDragging, dragData } = useDragMonitor()
248
248
  expect(isDragging()).toBe(false)
249
249
  expect(dragData()).toBeNull()
250
250
  })
251
251
 
252
- it("accepts canMonitor filter", async () => {
253
- const { useDragMonitor } = await import("../use-drag-monitor")
252
+ it('accepts canMonitor filter', async () => {
253
+ const { useDragMonitor } = await import('../use-drag-monitor')
254
254
  const { isDragging } = useDragMonitor({
255
- canMonitor: (data) => data.type === "card",
255
+ canMonitor: (data) => data.type === 'card',
256
256
  })
257
257
  expect(isDragging()).toBe(false)
258
258
  })
259
259
 
260
- it("accepts onDragStart and onDrop callbacks", async () => {
261
- const { useDragMonitor } = await import("../use-drag-monitor")
260
+ it('accepts onDragStart and onDrop callbacks', async () => {
261
+ const { useDragMonitor } = await import('../use-drag-monitor')
262
262
  const { isDragging } = useDragMonitor({
263
263
  onDragStart: () => {},
264
264
  onDrop: () => {},
@@ -269,10 +269,10 @@ describe("useDragMonitor", () => {
269
269
 
270
270
  // ─── useSortable: containerRef and auto-scroll ────────────────────────────
271
271
 
272
- describe("useSortable containerRef", () => {
273
- it("containerRef registers auto-scroll and drop target on element", async () => {
274
- const { useSortable } = await import("../use-sortable")
275
- const items = signal([{ id: "1" }, { id: "2" }, { id: "3" }])
272
+ describe('useSortable containerRef', () => {
273
+ it('containerRef registers auto-scroll and drop target on element', async () => {
274
+ const { useSortable } = await import('../use-sortable')
275
+ const items = signal([{ id: '1' }, { id: '2' }, { id: '3' }])
276
276
 
277
277
  const { containerRef } = useSortable({
278
278
  items,
@@ -280,14 +280,14 @@ describe("useSortable containerRef", () => {
280
280
  onReorder: () => {},
281
281
  })
282
282
 
283
- const container = document.createElement("ul")
283
+ const container = document.createElement('ul')
284
284
  // Should not throw — sets up autoScrollForElements + dropTargetForElements
285
285
  expect(() => containerRef(container)).not.toThrow()
286
286
  })
287
287
 
288
- it("containerRef adds keydown event listener to element", async () => {
289
- const { useSortable } = await import("../use-sortable")
290
- const items = signal([{ id: "1" }, { id: "2" }])
288
+ it('containerRef adds keydown event listener to element', async () => {
289
+ const { useSortable } = await import('../use-sortable')
290
+ const items = signal([{ id: '1' }, { id: '2' }])
291
291
 
292
292
  const { containerRef } = useSortable({
293
293
  items,
@@ -295,21 +295,21 @@ describe("useSortable containerRef", () => {
295
295
  onReorder: () => {},
296
296
  })
297
297
 
298
- const container = document.createElement("ul")
299
- const spy = vi.spyOn(container, "addEventListener")
298
+ const container = document.createElement('ul')
299
+ const spy = vi.spyOn(container, 'addEventListener')
300
300
  containerRef(container)
301
301
 
302
- expect(spy).toHaveBeenCalledWith("keydown", expect.any(Function))
302
+ expect(spy).toHaveBeenCalledWith('keydown', expect.any(Function))
303
303
  spy.mockRestore()
304
304
  })
305
305
  })
306
306
 
307
307
  // ─── useSortable: overEdge signal ─────────────────────────────────────────
308
308
 
309
- describe("useSortable overEdge", () => {
310
- it("overEdge signal is initially null", async () => {
311
- const { useSortable } = await import("../use-sortable")
312
- const items = signal([{ id: "1" }, { id: "2" }])
309
+ describe('useSortable overEdge', () => {
310
+ it('overEdge signal is initially null', async () => {
311
+ const { useSortable } = await import('../use-sortable')
312
+ const items = signal([{ id: '1' }, { id: '2' }])
313
313
 
314
314
  const { overEdge } = useSortable({
315
315
  items,
@@ -320,9 +320,9 @@ describe("useSortable overEdge", () => {
320
320
  expect(overEdge()).toBeNull()
321
321
  })
322
322
 
323
- it("overEdge is part of the returned API alongside activeId and overId", async () => {
324
- const { useSortable } = await import("../use-sortable")
325
- const items = signal([{ id: "a" }, { id: "b" }])
323
+ it('overEdge is part of the returned API alongside activeId and overId', async () => {
324
+ const { useSortable } = await import('../use-sortable')
325
+ const items = signal([{ id: 'a' }, { id: 'b' }])
326
326
 
327
327
  const result = useSortable({
328
328
  items,
@@ -330,21 +330,21 @@ describe("useSortable overEdge", () => {
330
330
  onReorder: () => {},
331
331
  })
332
332
 
333
- expect(result).toHaveProperty("overEdge")
334
- expect(result).toHaveProperty("activeId")
335
- expect(result).toHaveProperty("overId")
336
- expect(result).toHaveProperty("containerRef")
337
- expect(result).toHaveProperty("itemRef")
333
+ expect(result).toHaveProperty('overEdge')
334
+ expect(result).toHaveProperty('activeId')
335
+ expect(result).toHaveProperty('overId')
336
+ expect(result).toHaveProperty('containerRef')
337
+ expect(result).toHaveProperty('itemRef')
338
338
  })
339
339
  })
340
340
 
341
341
  // ─── useSortable: keyboard handler ─────────────────────────────────────────
342
342
 
343
- describe("useSortable keyboard reordering", () => {
344
- it("Alt+ArrowDown swaps focused item with next (vertical axis)", async () => {
345
- const { useSortable } = await import("../use-sortable")
343
+ describe('useSortable keyboard reordering', () => {
344
+ it('Alt+ArrowDown swaps focused item with next (vertical axis)', async () => {
345
+ const { useSortable } = await import('../use-sortable')
346
346
  const reordered: { id: string }[][] = []
347
- const items = signal([{ id: "1" }, { id: "2" }, { id: "3" }])
347
+ const items = signal([{ id: '1' }, { id: '2' }, { id: '3' }])
348
348
 
349
349
  const { containerRef, itemRef } = useSortable({
350
350
  items,
@@ -353,16 +353,16 @@ describe("useSortable keyboard reordering", () => {
353
353
  })
354
354
 
355
355
  // Build a container with items
356
- const container = document.createElement("ul")
356
+ const container = document.createElement('ul')
357
357
  document.body.appendChild(container)
358
358
  containerRef(container)
359
359
 
360
- const li1 = document.createElement("li")
361
- const li2 = document.createElement("li")
362
- const li3 = document.createElement("li")
363
- itemRef("1")(li1)
364
- itemRef("2")(li2)
365
- itemRef("3")(li3)
360
+ const li1 = document.createElement('li')
361
+ const li2 = document.createElement('li')
362
+ const li3 = document.createElement('li')
363
+ itemRef('1')(li1)
364
+ itemRef('2')(li2)
365
+ itemRef('3')(li3)
366
366
  container.appendChild(li1)
367
367
  container.appendChild(li2)
368
368
  container.appendChild(li3)
@@ -371,23 +371,23 @@ describe("useSortable keyboard reordering", () => {
371
371
  li1.focus()
372
372
 
373
373
  // Dispatch Alt+ArrowDown
374
- const event = new KeyboardEvent("keydown", {
375
- key: "ArrowDown",
374
+ const event = new KeyboardEvent('keydown', {
375
+ key: 'ArrowDown',
376
376
  altKey: true,
377
377
  bubbles: true,
378
378
  })
379
379
  container.dispatchEvent(event)
380
380
 
381
381
  expect(reordered.length).toBe(1)
382
- expect(reordered[0]!.map((i) => i.id)).toEqual(["2", "1", "3"])
382
+ expect(reordered[0]!.map((i) => i.id)).toEqual(['2', '1', '3'])
383
383
 
384
384
  document.body.removeChild(container)
385
385
  })
386
386
 
387
- it("Alt+ArrowUp swaps focused item with previous (vertical axis)", async () => {
388
- const { useSortable } = await import("../use-sortable")
387
+ it('Alt+ArrowUp swaps focused item with previous (vertical axis)', async () => {
388
+ const { useSortable } = await import('../use-sortable')
389
389
  const reordered: { id: string }[][] = []
390
- const items = signal([{ id: "1" }, { id: "2" }, { id: "3" }])
390
+ const items = signal([{ id: '1' }, { id: '2' }, { id: '3' }])
391
391
 
392
392
  const { containerRef, itemRef } = useSortable({
393
393
  items,
@@ -395,16 +395,16 @@ describe("useSortable keyboard reordering", () => {
395
395
  onReorder: (newItems) => reordered.push(newItems),
396
396
  })
397
397
 
398
- const container = document.createElement("ul")
398
+ const container = document.createElement('ul')
399
399
  document.body.appendChild(container)
400
400
  containerRef(container)
401
401
 
402
- const li1 = document.createElement("li")
403
- const li2 = document.createElement("li")
404
- const li3 = document.createElement("li")
405
- itemRef("1")(li1)
406
- itemRef("2")(li2)
407
- itemRef("3")(li3)
402
+ const li1 = document.createElement('li')
403
+ const li2 = document.createElement('li')
404
+ const li3 = document.createElement('li')
405
+ itemRef('1')(li1)
406
+ itemRef('2')(li2)
407
+ itemRef('3')(li3)
408
408
  container.appendChild(li1)
409
409
  container.appendChild(li2)
410
410
  container.appendChild(li3)
@@ -412,23 +412,23 @@ describe("useSortable keyboard reordering", () => {
412
412
  // Focus the second item
413
413
  li2.focus()
414
414
 
415
- const event = new KeyboardEvent("keydown", {
416
- key: "ArrowUp",
415
+ const event = new KeyboardEvent('keydown', {
416
+ key: 'ArrowUp',
417
417
  altKey: true,
418
418
  bubbles: true,
419
419
  })
420
420
  container.dispatchEvent(event)
421
421
 
422
422
  expect(reordered.length).toBe(1)
423
- expect(reordered[0]!.map((i) => i.id)).toEqual(["2", "1", "3"])
423
+ expect(reordered[0]!.map((i) => i.id)).toEqual(['2', '1', '3'])
424
424
 
425
425
  document.body.removeChild(container)
426
426
  })
427
427
 
428
- it("ignores keyboard events without Alt key", async () => {
429
- const { useSortable } = await import("../use-sortable")
428
+ it('ignores keyboard events without Alt key', async () => {
429
+ const { useSortable } = await import('../use-sortable')
430
430
  const reordered: { id: string }[][] = []
431
- const items = signal([{ id: "1" }, { id: "2" }])
431
+ const items = signal([{ id: '1' }, { id: '2' }])
432
432
 
433
433
  const { containerRef, itemRef } = useSortable({
434
434
  items,
@@ -436,21 +436,21 @@ describe("useSortable keyboard reordering", () => {
436
436
  onReorder: (newItems) => reordered.push(newItems),
437
437
  })
438
438
 
439
- const container = document.createElement("ul")
439
+ const container = document.createElement('ul')
440
440
  document.body.appendChild(container)
441
441
  containerRef(container)
442
442
 
443
- const li1 = document.createElement("li")
444
- const li2 = document.createElement("li")
445
- itemRef("1")(li1)
446
- itemRef("2")(li2)
443
+ const li1 = document.createElement('li')
444
+ const li2 = document.createElement('li')
445
+ itemRef('1')(li1)
446
+ itemRef('2')(li2)
447
447
  container.appendChild(li1)
448
448
  container.appendChild(li2)
449
449
 
450
450
  li1.focus()
451
451
 
452
- const event = new KeyboardEvent("keydown", {
453
- key: "ArrowDown",
452
+ const event = new KeyboardEvent('keydown', {
453
+ key: 'ArrowDown',
454
454
  altKey: false,
455
455
  bubbles: true,
456
456
  })
@@ -461,10 +461,10 @@ describe("useSortable keyboard reordering", () => {
461
461
  document.body.removeChild(container)
462
462
  })
463
463
 
464
- it("ignores Alt+ArrowDown at the last item (boundary)", async () => {
465
- const { useSortable } = await import("../use-sortable")
464
+ it('ignores Alt+ArrowDown at the last item (boundary)', async () => {
465
+ const { useSortable } = await import('../use-sortable')
466
466
  const reordered: { id: string }[][] = []
467
- const items = signal([{ id: "1" }, { id: "2" }])
467
+ const items = signal([{ id: '1' }, { id: '2' }])
468
468
 
469
469
  const { containerRef, itemRef } = useSortable({
470
470
  items,
@@ -472,22 +472,22 @@ describe("useSortable keyboard reordering", () => {
472
472
  onReorder: (newItems) => reordered.push(newItems),
473
473
  })
474
474
 
475
- const container = document.createElement("ul")
475
+ const container = document.createElement('ul')
476
476
  document.body.appendChild(container)
477
477
  containerRef(container)
478
478
 
479
- const li1 = document.createElement("li")
480
- const li2 = document.createElement("li")
481
- itemRef("1")(li1)
482
- itemRef("2")(li2)
479
+ const li1 = document.createElement('li')
480
+ const li2 = document.createElement('li')
481
+ itemRef('1')(li1)
482
+ itemRef('2')(li2)
483
483
  container.appendChild(li1)
484
484
  container.appendChild(li2)
485
485
 
486
486
  // Focus last item
487
487
  li2.focus()
488
488
 
489
- const event = new KeyboardEvent("keydown", {
490
- key: "ArrowDown",
489
+ const event = new KeyboardEvent('keydown', {
490
+ key: 'ArrowDown',
491
491
  altKey: true,
492
492
  bubbles: true,
493
493
  })
@@ -498,28 +498,28 @@ describe("useSortable keyboard reordering", () => {
498
498
  document.body.removeChild(container)
499
499
  })
500
500
 
501
- it("horizontal axis uses ArrowLeft/ArrowRight", async () => {
502
- const { useSortable } = await import("../use-sortable")
501
+ it('horizontal axis uses ArrowLeft/ArrowRight', async () => {
502
+ const { useSortable } = await import('../use-sortable')
503
503
  const reordered: { id: string }[][] = []
504
- const items = signal([{ id: "1" }, { id: "2" }, { id: "3" }])
504
+ const items = signal([{ id: '1' }, { id: '2' }, { id: '3' }])
505
505
 
506
506
  const { containerRef, itemRef } = useSortable({
507
507
  items,
508
508
  by: (item) => item.id,
509
509
  onReorder: (newItems) => reordered.push(newItems),
510
- axis: "horizontal",
510
+ axis: 'horizontal',
511
511
  })
512
512
 
513
- const container = document.createElement("div")
513
+ const container = document.createElement('div')
514
514
  document.body.appendChild(container)
515
515
  containerRef(container)
516
516
 
517
- const el1 = document.createElement("div")
518
- const el2 = document.createElement("div")
519
- const el3 = document.createElement("div")
520
- itemRef("1")(el1)
521
- itemRef("2")(el2)
522
- itemRef("3")(el3)
517
+ const el1 = document.createElement('div')
518
+ const el2 = document.createElement('div')
519
+ const el3 = document.createElement('div')
520
+ itemRef('1')(el1)
521
+ itemRef('2')(el2)
522
+ itemRef('3')(el3)
523
523
  container.appendChild(el1)
524
524
  container.appendChild(el2)
525
525
  container.appendChild(el3)
@@ -528,16 +528,16 @@ describe("useSortable keyboard reordering", () => {
528
528
 
529
529
  // ArrowDown should be ignored in horizontal mode
530
530
  container.dispatchEvent(
531
- new KeyboardEvent("keydown", { key: "ArrowDown", altKey: true, bubbles: true }),
531
+ new KeyboardEvent('keydown', { key: 'ArrowDown', altKey: true, bubbles: true }),
532
532
  )
533
533
  expect(reordered.length).toBe(0)
534
534
 
535
535
  // ArrowRight should work
536
536
  container.dispatchEvent(
537
- new KeyboardEvent("keydown", { key: "ArrowRight", altKey: true, bubbles: true }),
537
+ new KeyboardEvent('keydown', { key: 'ArrowRight', altKey: true, bubbles: true }),
538
538
  )
539
539
  expect(reordered.length).toBe(1)
540
- expect(reordered[0]!.map((i) => i.id)).toEqual(["2", "1", "3"])
540
+ expect(reordered[0]!.map((i) => i.id)).toEqual(['2', '1', '3'])
541
541
 
542
542
  document.body.removeChild(container)
543
543
  })
@@ -545,56 +545,56 @@ describe("useSortable keyboard reordering", () => {
545
545
 
546
546
  // ─── useFileDrop: MIME type filtering ──────────────────────────────────────
547
547
 
548
- describe("useFileDrop MIME filtering logic", () => {
549
- it("matchesAccept handles extension patterns (.pdf)", async () => {
548
+ describe('useFileDrop MIME filtering logic', () => {
549
+ it('matchesAccept handles extension patterns (.pdf)', async () => {
550
550
  // We can't test matchesAccept directly since it's private,
551
551
  // but we can verify the useFileDrop options are accepted
552
- const { useFileDrop } = await import("../use-file-drop")
553
- const el = document.createElement("div")
552
+ const { useFileDrop } = await import('../use-file-drop')
553
+ const el = document.createElement('div')
554
554
  const { isOver } = useFileDrop({
555
555
  element: () => el,
556
- accept: [".pdf", ".doc", ".docx"],
556
+ accept: ['.pdf', '.doc', '.docx'],
557
557
  onDrop: () => {},
558
558
  })
559
559
  expect(isOver()).toBe(false)
560
560
  })
561
561
 
562
- it("matchesAccept handles wildcard MIME types (image/*)", async () => {
563
- const { useFileDrop } = await import("../use-file-drop")
564
- const el = document.createElement("div")
562
+ it('matchesAccept handles wildcard MIME types (image/*)', async () => {
563
+ const { useFileDrop } = await import('../use-file-drop')
564
+ const el = document.createElement('div')
565
565
  const { isOver } = useFileDrop({
566
566
  element: () => el,
567
- accept: ["image/*"],
567
+ accept: ['image/*'],
568
568
  onDrop: () => {},
569
569
  })
570
570
  expect(isOver()).toBe(false)
571
571
  })
572
572
 
573
- it("matchesAccept handles exact MIME types (application/json)", async () => {
574
- const { useFileDrop } = await import("../use-file-drop")
575
- const el = document.createElement("div")
573
+ it('matchesAccept handles exact MIME types (application/json)', async () => {
574
+ const { useFileDrop } = await import('../use-file-drop')
575
+ const el = document.createElement('div')
576
576
  const { isOver } = useFileDrop({
577
577
  element: () => el,
578
- accept: ["application/json", "text/plain"],
578
+ accept: ['application/json', 'text/plain'],
579
579
  onDrop: () => {},
580
580
  })
581
581
  expect(isOver()).toBe(false)
582
582
  })
583
583
 
584
- it("handles maxFiles option", async () => {
585
- const { useFileDrop } = await import("../use-file-drop")
586
- const el = document.createElement("div")
584
+ it('handles maxFiles option', async () => {
585
+ const { useFileDrop } = await import('../use-file-drop')
586
+ const el = document.createElement('div')
587
587
  const { isOver } = useFileDrop({
588
588
  element: () => el,
589
- accept: ["image/*"],
589
+ accept: ['image/*'],
590
590
  maxFiles: 1,
591
591
  onDrop: () => {},
592
592
  })
593
593
  expect(isOver()).toBe(false)
594
594
  })
595
595
 
596
- it("handles null element gracefully", async () => {
597
- const { useFileDrop } = await import("../use-file-drop")
596
+ it('handles null element gracefully', async () => {
597
+ const { useFileDrop } = await import('../use-file-drop')
598
598
  const { isOver, isDraggingFiles } = useFileDrop({
599
599
  element: () => null,
600
600
  onDrop: () => {},
@@ -603,9 +603,9 @@ describe("useFileDrop MIME filtering logic", () => {
603
603
  expect(isDraggingFiles()).toBe(false)
604
604
  })
605
605
 
606
- it("accepts disabled as reactive getter", async () => {
607
- const { useFileDrop } = await import("../use-file-drop")
608
- const el = document.createElement("div")
606
+ it('accepts disabled as reactive getter', async () => {
607
+ const { useFileDrop } = await import('../use-file-drop')
608
+ const el = document.createElement('div')
609
609
  const isDisabled = signal(false)
610
610
  const { isOver } = useFileDrop({
611
611
  element: () => el,
@@ -618,15 +618,15 @@ describe("useFileDrop MIME filtering logic", () => {
618
618
 
619
619
  // ─── useDragMonitor: canMonitor filter ─────────────────────────────────────
620
620
 
621
- describe("useDragMonitor canMonitor filter", () => {
622
- it("canMonitor option is a function that receives drag data", async () => {
623
- const { useDragMonitor } = await import("../use-drag-monitor")
621
+ describe('useDragMonitor canMonitor filter', () => {
622
+ it('canMonitor option is a function that receives drag data', async () => {
623
+ const { useDragMonitor } = await import('../use-drag-monitor')
624
624
  const canMonitorCalls: unknown[] = []
625
625
 
626
626
  const { isDragging } = useDragMonitor({
627
627
  canMonitor: (data) => {
628
628
  canMonitorCalls.push(data)
629
- return data.type === "card"
629
+ return data.type === 'card'
630
630
  },
631
631
  })
632
632
 
@@ -635,21 +635,21 @@ describe("useDragMonitor canMonitor filter", () => {
635
635
  // We can't trigger real drag events, but verify setup doesn't throw
636
636
  })
637
637
 
638
- it("creates monitor without canMonitor (monitors all drags)", async () => {
639
- const { useDragMonitor } = await import("../use-drag-monitor")
638
+ it('creates monitor without canMonitor (monitors all drags)', async () => {
639
+ const { useDragMonitor } = await import('../use-drag-monitor')
640
640
  const { isDragging, dragData } = useDragMonitor()
641
641
 
642
642
  expect(isDragging()).toBe(false)
643
643
  expect(dragData()).toBeNull()
644
644
  })
645
645
 
646
- it("creates monitor with all options", async () => {
647
- const { useDragMonitor } = await import("../use-drag-monitor")
646
+ it('creates monitor with all options', async () => {
647
+ const { useDragMonitor } = await import('../use-drag-monitor')
648
648
  const starts: unknown[] = []
649
649
  const drops: unknown[] = []
650
650
 
651
651
  const { isDragging } = useDragMonitor({
652
- canMonitor: (data) => data.type === "task",
652
+ canMonitor: (data) => data.type === 'task',
653
653
  onDragStart: (data) => starts.push(data),
654
654
  onDrop: (source, target) => drops.push({ source, target }),
655
655
  })
@@ -661,9 +661,9 @@ describe("useDragMonitor canMonitor filter", () => {
661
661
 
662
662
  // ─── Module exports ─────────────────────────────────────────────────────────
663
663
 
664
- describe("module exports", () => {
665
- it("exports all 5 hooks", async () => {
666
- const mod = await import("../index")
664
+ describe('module exports', () => {
665
+ it('exports all 5 hooks', async () => {
666
+ const mod = await import('../index')
667
667
  expect(mod.useDraggable).toBeDefined()
668
668
  expect(mod.useDroppable).toBeDefined()
669
669
  expect(mod.useSortable).toBeDefined()