@pyreon/hooks 0.11.5 → 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.
Files changed (65) hide show
  1. package/README.md +5 -5
  2. package/lib/index.d.ts +4 -4
  3. package/package.json +24 -24
  4. package/src/__tests__/useBreakpoint.test.ts +48 -48
  5. package/src/__tests__/useClickOutside.test.ts +31 -31
  6. package/src/__tests__/useColorScheme.test.ts +22 -22
  7. package/src/__tests__/useControllableState.test.ts +18 -18
  8. package/src/__tests__/useDebouncedCallback.test.ts +19 -19
  9. package/src/__tests__/useDebouncedValue.test.ts +28 -28
  10. package/src/__tests__/useElementSize.test.ts +21 -21
  11. package/src/__tests__/useFocus.test.ts +12 -12
  12. package/src/__tests__/useFocusTrap.test.ts +36 -36
  13. package/src/__tests__/useHover.test.ts +13 -13
  14. package/src/__tests__/useIntersection.test.ts +20 -20
  15. package/src/__tests__/useInterval.test.ts +7 -7
  16. package/src/__tests__/useIsomorphicLayoutEffect.test.ts +5 -5
  17. package/src/__tests__/useKeyboard.test.ts +38 -38
  18. package/src/__tests__/useLatest.test.ts +11 -11
  19. package/src/__tests__/useMediaQuery.test.ts +29 -29
  20. package/src/__tests__/useMergedRef.test.ts +10 -10
  21. package/src/__tests__/usePrevious.test.ts +20 -20
  22. package/src/__tests__/useReducedMotion.test.ts +15 -15
  23. package/src/__tests__/useRootSize.test.ts +9 -9
  24. package/src/__tests__/useScrollLock.test.ts +33 -33
  25. package/src/__tests__/useSpacing.test.ts +11 -11
  26. package/src/__tests__/useThemeValue.test.ts +5 -5
  27. package/src/__tests__/useThrottledCallback.test.ts +16 -16
  28. package/src/__tests__/useTimeout.test.ts +8 -8
  29. package/src/__tests__/useToggle.test.ts +14 -14
  30. package/src/__tests__/useUpdateEffect.test.ts +8 -8
  31. package/src/__tests__/useWindowResize.test.ts +34 -34
  32. package/src/index.ts +56 -56
  33. package/src/useBreakpoint.ts +6 -6
  34. package/src/useClickOutside.ts +5 -5
  35. package/src/useClipboard.ts +2 -2
  36. package/src/useColorScheme.ts +5 -5
  37. package/src/useControllableState.ts +2 -2
  38. package/src/useDebouncedCallback.ts +1 -1
  39. package/src/useDebouncedValue.ts +2 -2
  40. package/src/useDialog.ts +4 -4
  41. package/src/useElementSize.ts +2 -2
  42. package/src/useEventListener.ts +2 -2
  43. package/src/useFocus.ts +1 -1
  44. package/src/useFocusTrap.ts +4 -4
  45. package/src/useHover.ts +1 -1
  46. package/src/useInfiniteScroll.ts +10 -10
  47. package/src/useIntersection.ts +2 -2
  48. package/src/useInterval.ts +1 -1
  49. package/src/useIsomorphicLayoutEffect.ts +2 -2
  50. package/src/useKeyboard.ts +3 -3
  51. package/src/useMediaQuery.ts +4 -4
  52. package/src/useMergedRef.ts +1 -1
  53. package/src/useOnline.ts +6 -6
  54. package/src/usePrevious.ts +1 -1
  55. package/src/useReducedMotion.ts +2 -2
  56. package/src/useRootSize.ts +1 -1
  57. package/src/useScrollLock.ts +3 -3
  58. package/src/useSpacing.ts +1 -1
  59. package/src/useThemeValue.ts +2 -2
  60. package/src/useThrottledCallback.ts +2 -2
  61. package/src/useTimeAgo.ts +15 -15
  62. package/src/useTimeout.ts +1 -1
  63. package/src/useToggle.ts +1 -1
  64. package/src/useUpdateEffect.ts +2 -2
  65. package/src/useWindowResize.ts +6 -6
@@ -1,43 +1,43 @@
1
- import { describe, expect, it, vi } from "vitest"
2
- import { useControllableState } from "../useControllableState"
1
+ import { describe, expect, it, vi } from 'vitest'
2
+ import { useControllableState } from '../useControllableState'
3
3
 
4
- describe("useControllableState", () => {
5
- it("uses defaultValue when uncontrolled", () => {
6
- const [value] = useControllableState({ defaultValue: "hello" })
7
- expect(value()).toBe("hello")
4
+ describe('useControllableState', () => {
5
+ it('uses defaultValue when uncontrolled', () => {
6
+ const [value] = useControllableState({ defaultValue: 'hello' })
7
+ expect(value()).toBe('hello')
8
8
  })
9
9
 
10
- it("updates internal state when uncontrolled", () => {
10
+ it('updates internal state when uncontrolled', () => {
11
11
  const [value, setValue] = useControllableState({ defaultValue: 0 })
12
12
  setValue(5)
13
13
  expect(value()).toBe(5)
14
14
  })
15
15
 
16
- it("uses value when controlled", () => {
17
- const [value] = useControllableState({ value: "controlled", defaultValue: "default" })
18
- expect(value()).toBe("controlled")
16
+ it('uses value when controlled', () => {
17
+ const [value] = useControllableState({ value: 'controlled', defaultValue: 'default' })
18
+ expect(value()).toBe('controlled')
19
19
  })
20
20
 
21
- it("does not update internal state when controlled", () => {
21
+ it('does not update internal state when controlled', () => {
22
22
  const onChange = vi.fn()
23
23
  const [value, setValue] = useControllableState({
24
- value: "controlled",
25
- defaultValue: "default",
24
+ value: 'controlled',
25
+ defaultValue: 'default',
26
26
  onChange,
27
27
  })
28
- setValue("new")
29
- expect(value()).toBe("controlled")
30
- expect(onChange).toHaveBeenCalledWith("new")
28
+ setValue('new')
29
+ expect(value()).toBe('controlled')
30
+ expect(onChange).toHaveBeenCalledWith('new')
31
31
  })
32
32
 
33
- it("calls onChange in uncontrolled mode", () => {
33
+ it('calls onChange in uncontrolled mode', () => {
34
34
  const onChange = vi.fn()
35
35
  const [, setValue] = useControllableState({ defaultValue: 0, onChange })
36
36
  setValue(10)
37
37
  expect(onChange).toHaveBeenCalledWith(10)
38
38
  })
39
39
 
40
- it("supports updater function", () => {
40
+ it('supports updater function', () => {
41
41
  const [value, setValue] = useControllableState({ defaultValue: 1 })
42
42
  setValue((prev: number) => prev + 1)
43
43
  expect(value()).toBe(2)
@@ -1,54 +1,54 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
2
- import { useDebouncedCallback } from "../useDebouncedCallback"
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
+ import { useDebouncedCallback } from '../useDebouncedCallback'
3
3
 
4
4
  // Mock onUnmount since it requires component lifecycle context
5
- vi.mock("@pyreon/core", () => ({
5
+ vi.mock('@pyreon/core', () => ({
6
6
  onMount: (fn: () => void) => fn(),
7
7
  onUnmount: (_fn: () => void) => {
8
8
  /* no-op */
9
9
  },
10
10
  }))
11
11
 
12
- describe("useDebouncedCallback", () => {
12
+ describe('useDebouncedCallback', () => {
13
13
  beforeEach(() => vi.useFakeTimers())
14
14
  afterEach(() => vi.useRealTimers())
15
15
 
16
- it("debounces the callback", () => {
16
+ it('debounces the callback', () => {
17
17
  const fn = vi.fn()
18
18
  const debounced = useDebouncedCallback(fn, 100)
19
19
 
20
- debounced("a")
21
- debounced("b")
22
- debounced("c")
20
+ debounced('a')
21
+ debounced('b')
22
+ debounced('c')
23
23
 
24
24
  expect(fn).not.toHaveBeenCalled()
25
25
  vi.advanceTimersByTime(100)
26
26
  expect(fn).toHaveBeenCalledTimes(1)
27
- expect(fn).toHaveBeenCalledWith("c")
27
+ expect(fn).toHaveBeenCalledWith('c')
28
28
  })
29
29
 
30
- it("cancel prevents the callback", () => {
30
+ it('cancel prevents the callback', () => {
31
31
  const fn = vi.fn()
32
32
  const debounced = useDebouncedCallback(fn, 100)
33
33
 
34
- debounced("a")
34
+ debounced('a')
35
35
  debounced.cancel()
36
36
  vi.advanceTimersByTime(200)
37
37
 
38
38
  expect(fn).not.toHaveBeenCalled()
39
39
  })
40
40
 
41
- it("flush invokes immediately", () => {
41
+ it('flush invokes immediately', () => {
42
42
  const fn = vi.fn()
43
43
  const debounced = useDebouncedCallback(fn, 100)
44
44
 
45
- debounced("x")
45
+ debounced('x')
46
46
  debounced.flush()
47
47
 
48
- expect(fn).toHaveBeenCalledWith("x")
48
+ expect(fn).toHaveBeenCalledWith('x')
49
49
  })
50
50
 
51
- it("flush is a no-op when no pending timer", () => {
51
+ it('flush is a no-op when no pending timer', () => {
52
52
  const fn = vi.fn()
53
53
  const debounced = useDebouncedCallback(fn, 100)
54
54
 
@@ -56,11 +56,11 @@ describe("useDebouncedCallback", () => {
56
56
  expect(fn).not.toHaveBeenCalled()
57
57
  })
58
58
 
59
- it("flush is a no-op after timer already fired", () => {
59
+ it('flush is a no-op after timer already fired', () => {
60
60
  const fn = vi.fn()
61
61
  const debounced = useDebouncedCallback(fn, 100)
62
62
 
63
- debounced("a")
63
+ debounced('a')
64
64
  vi.advanceTimersByTime(100)
65
65
  expect(fn).toHaveBeenCalledTimes(1)
66
66
 
@@ -68,11 +68,11 @@ describe("useDebouncedCallback", () => {
68
68
  expect(fn).toHaveBeenCalledTimes(1)
69
69
  })
70
70
 
71
- it("flush is a no-op after cancel", () => {
71
+ it('flush is a no-op after cancel', () => {
72
72
  const fn = vi.fn()
73
73
  const debounced = useDebouncedCallback(fn, 100)
74
74
 
75
- debounced("a")
75
+ debounced('a')
76
76
  debounced.cancel()
77
77
  debounced.flush()
78
78
  expect(fn).not.toHaveBeenCalled()
@@ -1,16 +1,16 @@
1
- import { signal } from "@pyreon/reactivity"
2
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
3
- import { useDebouncedValue } from "../useDebouncedValue"
1
+ import { signal } from '@pyreon/reactivity'
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
3
+ import { useDebouncedValue } from '../useDebouncedValue'
4
4
 
5
5
  // Mock onUnmount since it requires component lifecycle context
6
- vi.mock("@pyreon/core", () => ({
6
+ vi.mock('@pyreon/core', () => ({
7
7
  onMount: (fn: () => void) => fn(),
8
8
  onUnmount: (_fn: () => void) => {
9
9
  /* no-op */
10
10
  },
11
11
  }))
12
12
 
13
- describe("useDebouncedValue", () => {
13
+ describe('useDebouncedValue', () => {
14
14
  beforeEach(() => {
15
15
  vi.useFakeTimers()
16
16
  })
@@ -19,33 +19,33 @@ describe("useDebouncedValue", () => {
19
19
  vi.useRealTimers()
20
20
  })
21
21
 
22
- it("returns the initial value immediately", () => {
22
+ it('returns the initial value immediately', () => {
23
23
  const source = signal(42)
24
24
  const debounced = useDebouncedValue(source, 300)
25
25
  expect(debounced()).toBe(42)
26
26
  })
27
27
 
28
- it("does not update immediately when source changes", () => {
29
- const source = signal("hello")
28
+ it('does not update immediately when source changes', () => {
29
+ const source = signal('hello')
30
30
  const debounced = useDebouncedValue(source, 300)
31
- expect(debounced()).toBe("hello")
31
+ expect(debounced()).toBe('hello')
32
32
 
33
- source.set("world")
34
- expect(debounced()).toBe("hello")
33
+ source.set('world')
34
+ expect(debounced()).toBe('hello')
35
35
  })
36
36
 
37
- it("updates after the delay elapses", () => {
38
- const source = signal("hello")
37
+ it('updates after the delay elapses', () => {
38
+ const source = signal('hello')
39
39
  const debounced = useDebouncedValue(source, 300)
40
40
 
41
- source.set("world")
42
- expect(debounced()).toBe("hello")
41
+ source.set('world')
42
+ expect(debounced()).toBe('hello')
43
43
 
44
44
  vi.advanceTimersByTime(300)
45
- expect(debounced()).toBe("world")
45
+ expect(debounced()).toBe('world')
46
46
  })
47
47
 
48
- it("resets the timer on rapid changes", () => {
48
+ it('resets the timer on rapid changes', () => {
49
49
  const source = signal(1)
50
50
  const debounced = useDebouncedValue(source, 300)
51
51
 
@@ -62,7 +62,7 @@ describe("useDebouncedValue", () => {
62
62
  expect(debounced()).toBe(4)
63
63
  })
64
64
 
65
- it("only applies the last value after debounce", () => {
65
+ it('only applies the last value after debounce', () => {
66
66
  const source = signal(0)
67
67
  const debounced = useDebouncedValue(source, 200)
68
68
 
@@ -76,20 +76,20 @@ describe("useDebouncedValue", () => {
76
76
  expect(debounced()).toBe(5)
77
77
  })
78
78
 
79
- it("handles multiple debounce cycles", () => {
80
- const source = signal("a")
79
+ it('handles multiple debounce cycles', () => {
80
+ const source = signal('a')
81
81
  const debounced = useDebouncedValue(source, 100)
82
82
 
83
- source.set("b")
83
+ source.set('b')
84
84
  vi.advanceTimersByTime(100)
85
- expect(debounced()).toBe("b")
85
+ expect(debounced()).toBe('b')
86
86
 
87
- source.set("c")
87
+ source.set('c')
88
88
  vi.advanceTimersByTime(100)
89
- expect(debounced()).toBe("c")
89
+ expect(debounced()).toBe('c')
90
90
  })
91
91
 
92
- it("works with zero delay", () => {
92
+ it('works with zero delay', () => {
93
93
  const source = signal(1)
94
94
  const debounced = useDebouncedValue(source, 0)
95
95
 
@@ -98,9 +98,9 @@ describe("useDebouncedValue", () => {
98
98
  expect(debounced()).toBe(2)
99
99
  })
100
100
 
101
- it("works with object values", () => {
102
- const obj1 = { name: "Alice" }
103
- const obj2 = { name: "Bob" }
101
+ it('works with object values', () => {
102
+ const obj1 = { name: 'Alice' }
103
+ const obj2 = { name: 'Bob' }
104
104
  const source = signal(obj1)
105
105
  const debounced = useDebouncedValue(source, 100)
106
106
  expect(debounced()).toBe(obj1)
@@ -1,9 +1,9 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest"
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
3
  let mountCallbacks: Array<() => unknown> = []
4
4
  let unmountCallbacks: Array<() => void> = []
5
5
 
6
- vi.mock("@pyreon/core", () => ({
6
+ vi.mock('@pyreon/core', () => ({
7
7
  onMount: (fn: () => unknown) => {
8
8
  mountCallbacks.push(fn)
9
9
  },
@@ -12,9 +12,9 @@ vi.mock("@pyreon/core", () => ({
12
12
  },
13
13
  }))
14
14
 
15
- import { useElementSize } from "../useElementSize"
15
+ import { useElementSize } from '../useElementSize'
16
16
 
17
- describe("useElementSize", () => {
17
+ describe('useElementSize', () => {
18
18
  let resizeCallback: ((entries: ResizeObserverEntry[]) => void) | undefined
19
19
  let observeSpy: ReturnType<typeof vi.fn>
20
20
  let disconnectSpy: ReturnType<typeof vi.fn>
@@ -36,15 +36,15 @@ describe("useElementSize", () => {
36
36
  }) as unknown as typeof ResizeObserver
37
37
  })
38
38
 
39
- it("returns initial size of 0x0", () => {
39
+ it('returns initial size of 0x0', () => {
40
40
  const size = useElementSize(() => null)
41
41
  expect(size().width).toBe(0)
42
42
  expect(size().height).toBe(0)
43
43
  })
44
44
 
45
- it("measures initial element size on mount", () => {
46
- const el = document.createElement("div")
47
- vi.spyOn(el, "getBoundingClientRect").mockReturnValue({
45
+ it('measures initial element size on mount', () => {
46
+ const el = document.createElement('div')
47
+ vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({
48
48
  width: 200,
49
49
  height: 100,
50
50
  x: 0,
@@ -67,9 +67,9 @@ describe("useElementSize", () => {
67
67
  expect(size().height).toBe(100)
68
68
  })
69
69
 
70
- it("observes the element with ResizeObserver", () => {
71
- const el = document.createElement("div")
72
- vi.spyOn(el, "getBoundingClientRect").mockReturnValue({
70
+ it('observes the element with ResizeObserver', () => {
71
+ const el = document.createElement('div')
72
+ vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({
73
73
  width: 0,
74
74
  height: 0,
75
75
  x: 0,
@@ -91,9 +91,9 @@ describe("useElementSize", () => {
91
91
  expect(observeSpy).toHaveBeenCalledWith(el)
92
92
  })
93
93
 
94
- it("updates size when ResizeObserver fires", () => {
95
- const el = document.createElement("div")
96
- vi.spyOn(el, "getBoundingClientRect").mockReturnValue({
94
+ it('updates size when ResizeObserver fires', () => {
95
+ const el = document.createElement('div')
96
+ vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({
97
97
  width: 100,
98
98
  height: 50,
99
99
  x: 0,
@@ -124,7 +124,7 @@ describe("useElementSize", () => {
124
124
  expect(size().height).toBe(150)
125
125
  })
126
126
 
127
- it("does nothing on mount when element is null", () => {
127
+ it('does nothing on mount when element is null', () => {
128
128
  useElementSize(() => null)
129
129
  mountCallbacks.forEach((cb) => {
130
130
  cb()
@@ -133,9 +133,9 @@ describe("useElementSize", () => {
133
133
  expect(observeSpy).not.toHaveBeenCalled()
134
134
  })
135
135
 
136
- it("disconnects ResizeObserver on unmount", () => {
137
- const el = document.createElement("div")
138
- vi.spyOn(el, "getBoundingClientRect").mockReturnValue({
136
+ it('disconnects ResizeObserver on unmount', () => {
137
+ const el = document.createElement('div')
138
+ vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({
139
139
  width: 0,
140
140
  height: 0,
141
141
  x: 0,
@@ -160,9 +160,9 @@ describe("useElementSize", () => {
160
160
  expect(disconnectSpy).toHaveBeenCalled()
161
161
  })
162
162
 
163
- it("handles ResizeObserver callback with no entry", () => {
164
- const el = document.createElement("div")
165
- vi.spyOn(el, "getBoundingClientRect").mockReturnValue({
163
+ it('handles ResizeObserver callback with no entry', () => {
164
+ const el = document.createElement('div')
165
+ vi.spyOn(el, 'getBoundingClientRect').mockReturnValue({
166
166
  width: 50,
167
167
  height: 25,
168
168
  x: 0,
@@ -1,19 +1,19 @@
1
- import { describe, expect, it } from "vitest"
2
- import { useFocus } from "../useFocus"
1
+ import { describe, expect, it } from 'vitest'
2
+ import { useFocus } from '../useFocus'
3
3
 
4
- describe("useFocus", () => {
5
- it("initializes with focused=false", () => {
4
+ describe('useFocus', () => {
5
+ it('initializes with focused=false', () => {
6
6
  const { focused } = useFocus()
7
7
  expect(focused()).toBe(false)
8
8
  })
9
9
 
10
- it("sets focused to true on focus", () => {
10
+ it('sets focused to true on focus', () => {
11
11
  const { focused, props } = useFocus()
12
12
  props.onFocus()
13
13
  expect(focused()).toBe(true)
14
14
  })
15
15
 
16
- it("sets focused to false on blur", () => {
16
+ it('sets focused to false on blur', () => {
17
17
  const { focused, props } = useFocus()
18
18
  props.onFocus()
19
19
  expect(focused()).toBe(true)
@@ -21,7 +21,7 @@ describe("useFocus", () => {
21
21
  expect(focused()).toBe(false)
22
22
  })
23
23
 
24
- it("toggles focus state through multiple cycles", () => {
24
+ it('toggles focus state through multiple cycles', () => {
25
25
  const { focused, props } = useFocus()
26
26
  props.onFocus()
27
27
  expect(focused()).toBe(true)
@@ -31,22 +31,22 @@ describe("useFocus", () => {
31
31
  expect(focused()).toBe(true)
32
32
  })
33
33
 
34
- it("calling blur when not focused is safe", () => {
34
+ it('calling blur when not focused is safe', () => {
35
35
  const { focused, props } = useFocus()
36
36
  props.onBlur()
37
37
  expect(focused()).toBe(false)
38
38
  })
39
39
 
40
- it("calling focus multiple times stays true", () => {
40
+ it('calling focus multiple times stays true', () => {
41
41
  const { focused, props } = useFocus()
42
42
  props.onFocus()
43
43
  props.onFocus()
44
44
  expect(focused()).toBe(true)
45
45
  })
46
46
 
47
- it("returns props object with onFocus and onBlur", () => {
47
+ it('returns props object with onFocus and onBlur', () => {
48
48
  const { props } = useFocus()
49
- expect(typeof props.onFocus).toBe("function")
50
- expect(typeof props.onBlur).toBe("function")
49
+ expect(typeof props.onFocus).toBe('function')
50
+ expect(typeof props.onBlur).toBe('function')
51
51
  })
52
52
  })
@@ -1,9 +1,9 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
3
  let mountCallbacks: Array<() => void> = []
4
4
  let unmountCallbacks: Array<() => void> = []
5
5
 
6
- vi.mock("@pyreon/core", () => ({
6
+ vi.mock('@pyreon/core', () => ({
7
7
  onMount: (fn: () => unknown) => {
8
8
  mountCallbacks.push(fn as () => void)
9
9
  },
@@ -12,9 +12,9 @@ vi.mock("@pyreon/core", () => ({
12
12
  },
13
13
  }))
14
14
 
15
- import { useFocusTrap } from "../useFocusTrap"
15
+ import { useFocusTrap } from '../useFocusTrap'
16
16
 
17
- describe("useFocusTrap", () => {
17
+ describe('useFocusTrap', () => {
18
18
  let container: HTMLDivElement
19
19
  let btn1: HTMLButtonElement
20
20
  let btn2: HTMLButtonElement
@@ -23,10 +23,10 @@ describe("useFocusTrap", () => {
23
23
  beforeEach(() => {
24
24
  mountCallbacks = []
25
25
  unmountCallbacks = []
26
- container = document.createElement("div")
27
- btn1 = document.createElement("button")
28
- btn2 = document.createElement("button")
29
- btn3 = document.createElement("button")
26
+ container = document.createElement('div')
27
+ btn1 = document.createElement('button')
28
+ btn2 = document.createElement('button')
29
+ btn3 = document.createElement('button')
30
30
  container.append(btn1, btn2, btn3)
31
31
  document.body.appendChild(container)
32
32
  })
@@ -35,84 +35,84 @@ describe("useFocusTrap", () => {
35
35
  document.body.removeChild(container)
36
36
  })
37
37
 
38
- it("wraps focus from last to first on Tab", () => {
38
+ it('wraps focus from last to first on Tab', () => {
39
39
  useFocusTrap(() => container)
40
40
  mountCallbacks.forEach((cb) => {
41
41
  cb()
42
42
  })
43
43
 
44
44
  btn3.focus()
45
- const event = new KeyboardEvent("keydown", { key: "Tab", bubbles: true })
46
- const prevented = vi.spyOn(event, "preventDefault")
45
+ const event = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true })
46
+ const prevented = vi.spyOn(event, 'preventDefault')
47
47
  document.dispatchEvent(event)
48
48
 
49
49
  expect(prevented).toHaveBeenCalled()
50
50
  expect(document.activeElement).toBe(btn1)
51
51
  })
52
52
 
53
- it("wraps focus from first to last on Shift+Tab", () => {
53
+ it('wraps focus from first to last on Shift+Tab', () => {
54
54
  useFocusTrap(() => container)
55
55
  mountCallbacks.forEach((cb) => {
56
56
  cb()
57
57
  })
58
58
 
59
59
  btn1.focus()
60
- const event = new KeyboardEvent("keydown", {
61
- key: "Tab",
60
+ const event = new KeyboardEvent('keydown', {
61
+ key: 'Tab',
62
62
  shiftKey: true,
63
63
  bubbles: true,
64
64
  })
65
- const prevented = vi.spyOn(event, "preventDefault")
65
+ const prevented = vi.spyOn(event, 'preventDefault')
66
66
  document.dispatchEvent(event)
67
67
 
68
68
  expect(prevented).toHaveBeenCalled()
69
69
  expect(document.activeElement).toBe(btn3)
70
70
  })
71
71
 
72
- it("does not wrap when Tab on middle element", () => {
72
+ it('does not wrap when Tab on middle element', () => {
73
73
  useFocusTrap(() => container)
74
74
  mountCallbacks.forEach((cb) => {
75
75
  cb()
76
76
  })
77
77
 
78
78
  btn2.focus()
79
- const event = new KeyboardEvent("keydown", { key: "Tab", bubbles: true })
80
- const prevented = vi.spyOn(event, "preventDefault")
79
+ const event = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true })
80
+ const prevented = vi.spyOn(event, 'preventDefault')
81
81
  document.dispatchEvent(event)
82
82
 
83
83
  expect(prevented).not.toHaveBeenCalled()
84
84
  })
85
85
 
86
- it("ignores non-Tab keys", () => {
86
+ it('ignores non-Tab keys', () => {
87
87
  useFocusTrap(() => container)
88
88
  mountCallbacks.forEach((cb) => {
89
89
  cb()
90
90
  })
91
91
 
92
92
  btn3.focus()
93
- const event = new KeyboardEvent("keydown", { key: "Enter", bubbles: true })
94
- const prevented = vi.spyOn(event, "preventDefault")
93
+ const event = new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })
94
+ const prevented = vi.spyOn(event, 'preventDefault')
95
95
  document.dispatchEvent(event)
96
96
 
97
97
  expect(prevented).not.toHaveBeenCalled()
98
98
  })
99
99
 
100
- it("does nothing when element is null", () => {
100
+ it('does nothing when element is null', () => {
101
101
  useFocusTrap(() => null)
102
102
  mountCallbacks.forEach((cb) => {
103
103
  cb()
104
104
  })
105
105
 
106
- const event = new KeyboardEvent("keydown", { key: "Tab", bubbles: true })
107
- const prevented = vi.spyOn(event, "preventDefault")
106
+ const event = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true })
107
+ const prevented = vi.spyOn(event, 'preventDefault')
108
108
  document.dispatchEvent(event)
109
109
 
110
110
  expect(prevented).not.toHaveBeenCalled()
111
111
  })
112
112
 
113
- it("does nothing when container has no focusable children", () => {
114
- const emptyContainer = document.createElement("div")
115
- emptyContainer.appendChild(document.createElement("div"))
113
+ it('does nothing when container has no focusable children', () => {
114
+ const emptyContainer = document.createElement('div')
115
+ emptyContainer.appendChild(document.createElement('div'))
116
116
  document.body.appendChild(emptyContainer)
117
117
 
118
118
  useFocusTrap(() => emptyContainer)
@@ -120,16 +120,16 @@ describe("useFocusTrap", () => {
120
120
  cb()
121
121
  })
122
122
 
123
- const event = new KeyboardEvent("keydown", { key: "Tab", bubbles: true })
124
- const prevented = vi.spyOn(event, "preventDefault")
123
+ const event = new KeyboardEvent('keydown', { key: 'Tab', bubbles: true })
124
+ const prevented = vi.spyOn(event, 'preventDefault')
125
125
  document.dispatchEvent(event)
126
126
 
127
127
  expect(prevented).not.toHaveBeenCalled()
128
128
  document.body.removeChild(emptyContainer)
129
129
  })
130
130
 
131
- it("cleans up event listener on unmount", () => {
132
- const removeSpy = vi.spyOn(document, "removeEventListener")
131
+ it('cleans up event listener on unmount', () => {
132
+ const removeSpy = vi.spyOn(document, 'removeEventListener')
133
133
  useFocusTrap(() => container)
134
134
  mountCallbacks.forEach((cb) => {
135
135
  cb()
@@ -138,23 +138,23 @@ describe("useFocusTrap", () => {
138
138
  cb()
139
139
  })
140
140
 
141
- expect(removeSpy).toHaveBeenCalledWith("keydown", expect.any(Function))
141
+ expect(removeSpy).toHaveBeenCalledWith('keydown', expect.any(Function))
142
142
  removeSpy.mockRestore()
143
143
  })
144
144
 
145
- it("does not prevent default when Shift+Tab on non-first element", () => {
145
+ it('does not prevent default when Shift+Tab on non-first element', () => {
146
146
  useFocusTrap(() => container)
147
147
  mountCallbacks.forEach((cb) => {
148
148
  cb()
149
149
  })
150
150
 
151
151
  btn2.focus()
152
- const event = new KeyboardEvent("keydown", {
153
- key: "Tab",
152
+ const event = new KeyboardEvent('keydown', {
153
+ key: 'Tab',
154
154
  shiftKey: true,
155
155
  bubbles: true,
156
156
  })
157
- const prevented = vi.spyOn(event, "preventDefault")
157
+ const prevented = vi.spyOn(event, 'preventDefault')
158
158
  document.dispatchEvent(event)
159
159
 
160
160
  expect(prevented).not.toHaveBeenCalled()