@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
package/README.md CHANGED
@@ -184,12 +184,12 @@ const debouncedSearch = useDebouncedValue(searchTerm, 300)
184
184
 
185
185
  ## Peer Dependencies
186
186
 
187
- | Package | Version |
188
- | ------- | ------- |
189
- | @pyreon/core | >= 0.0.1 |
187
+ | Package | Version |
188
+ | ------------------ | -------- |
189
+ | @pyreon/core | >= 0.0.1 |
190
190
  | @pyreon/reactivity | >= 0.0.1 |
191
- | @pyreon/styler | >= 0.0.1 |
192
- | @pyreon/ui-core | >= 0.0.1 |
191
+ | @pyreon/styler | >= 0.0.1 |
192
+ | @pyreon/ui-core | >= 0.0.1 |
193
193
 
194
194
  ## License
195
195
 
package/lib/index.d.ts CHANGED
@@ -44,7 +44,7 @@ declare function useClipboard(options?: {
44
44
  /**
45
45
  * Returns the OS color scheme preference as 'light' or 'dark'.
46
46
  */
47
- declare function useColorScheme(): () => "light" | "dark";
47
+ declare function useColorScheme(): () => 'light' | 'dark';
48
48
  //#endregion
49
49
  //#region src/useControllableState.d.ts
50
50
  type UseControllableStateOptions<T> = {
@@ -193,7 +193,7 @@ interface UseInfiniteScrollOptions {
193
193
  /** Whether there's more data to load. Default: true */
194
194
  hasMore?: () => boolean;
195
195
  /** Scroll direction. Default: "down" */
196
- direction?: "up" | "down";
196
+ direction?: 'up' | 'down';
197
197
  }
198
198
  interface UseInfiniteScrollResult {
199
199
  /** Attach to the scroll container element. */
@@ -263,7 +263,7 @@ declare const useIsomorphicLayoutEffect: UseIsomorphicLayoutEffect;
263
263
  * Listen for a specific key press.
264
264
  */
265
265
  declare function useKeyboard(key: string, handler: (event: KeyboardEvent) => void, options?: {
266
- event?: "keydown" | "keyup";
266
+ event?: 'keydown' | 'keyup';
267
267
  target?: EventTarget;
268
268
  }): void;
269
269
  //#endregion
@@ -400,7 +400,7 @@ type UseThrottledCallback = <T extends (...args: any[]) => any>(callback: T, del
400
400
  declare const useThrottledCallback: UseThrottledCallback;
401
401
  //#endregion
402
402
  //#region src/useTimeAgo.d.ts
403
- type TimeUnit = "second" | "minute" | "hour" | "day" | "week" | "month" | "year";
403
+ type TimeUnit = 'second' | 'minute' | 'hour' | 'day' | 'week' | 'month' | 'year';
404
404
  interface UseTimeAgoOptions {
405
405
  /** Custom formatter. Receives the value, unit, and whether it's in the past. */
406
406
  formatter?: (value: number, unit: TimeUnit, isPast: boolean) => string;
package/package.json CHANGED
@@ -1,24 +1,13 @@
1
1
  {
2
2
  "name": "@pyreon/hooks",
3
- "version": "0.11.5",
3
+ "version": "0.11.6",
4
+ "description": "Signal-based reactive utilities for Pyreon",
5
+ "license": "MIT",
4
6
  "repository": {
5
7
  "type": "git",
6
8
  "url": "https://github.com/pyreon/pyreon",
7
9
  "directory": "packages/fundamentals/hooks"
8
10
  },
9
- "description": "Signal-based reactive utilities for Pyreon",
10
- "license": "MIT",
11
- "type": "module",
12
- "sideEffects": false,
13
- "exports": {
14
- ".": {
15
- "bun": "./src/index.ts",
16
- "import": "./lib/index.js",
17
- "types": "./lib/index.d.ts"
18
- }
19
- },
20
- "types": "./lib/index.d.ts",
21
- "main": "./lib/index.js",
22
11
  "files": [
23
12
  "lib",
24
13
  "!lib/**/*.map",
@@ -27,8 +16,16 @@
27
16
  "LICENSE",
28
17
  "src"
29
18
  ],
30
- "engines": {
31
- "node": ">= 22"
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "main": "./lib/index.js",
22
+ "types": "./lib/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "bun": "./src/index.ts",
26
+ "import": "./lib/index.js",
27
+ "types": "./lib/index.d.ts"
28
+ }
32
29
  },
33
30
  "publishConfig": {
34
31
  "access": "public"
@@ -37,20 +34,23 @@
37
34
  "prepublish": "bun run build",
38
35
  "build": "bun run vl_rolldown_build",
39
36
  "build:watch": "bun run vl_rolldown_build-watch",
40
- "lint": "biome check src/",
37
+ "lint": "oxlint .",
41
38
  "test": "vitest run",
42
39
  "test:coverage": "vitest run --coverage",
43
40
  "test:watch": "vitest",
44
41
  "typecheck": "tsc --noEmit"
45
42
  },
43
+ "devDependencies": {
44
+ "@pyreon/typescript": "^0.11.6",
45
+ "@vitus-labs/tools-rolldown": "^1.15.3"
46
+ },
46
47
  "peerDependencies": {
47
- "@pyreon/core": "^0.11.5",
48
- "@pyreon/reactivity": "^0.11.5",
49
- "@pyreon/styler": "^0.11.5",
50
- "@pyreon/ui-core": "^0.11.5"
48
+ "@pyreon/core": "^0.11.6",
49
+ "@pyreon/reactivity": "^0.11.6",
50
+ "@pyreon/styler": "^0.11.6",
51
+ "@pyreon/ui-core": "^0.11.6"
51
52
  },
52
- "devDependencies": {
53
- "@vitus-labs/tools-rolldown": "^1.15.3",
54
- "@pyreon/typescript": "^0.11.5"
53
+ "engines": {
54
+ "node": ">= 22"
55
55
  }
56
56
  }
@@ -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<() => 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 { useBreakpoint } from "../useBreakpoint"
15
+ import { useBreakpoint } from '../useBreakpoint'
16
16
 
17
- describe("useBreakpoint", () => {
17
+ describe('useBreakpoint', () => {
18
18
  const originalInnerWidth = window.innerWidth
19
19
  let rafCallback: FrameRequestCallback | undefined
20
20
 
@@ -23,103 +23,103 @@ describe("useBreakpoint", () => {
23
23
  unmountCallbacks = []
24
24
  rafCallback = undefined
25
25
 
26
- vi.spyOn(window, "requestAnimationFrame").mockImplementation((cb) => {
26
+ vi.spyOn(window, 'requestAnimationFrame').mockImplementation((cb) => {
27
27
  rafCallback = cb
28
28
  return 1
29
29
  })
30
- vi.spyOn(window, "cancelAnimationFrame").mockImplementation(() => {
30
+ vi.spyOn(window, 'cancelAnimationFrame').mockImplementation(() => {
31
31
  /* no-op */
32
32
  })
33
33
  })
34
34
 
35
35
  afterEach(() => {
36
- Object.defineProperty(window, "innerWidth", { writable: true, value: originalInnerWidth })
36
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: originalInnerWidth })
37
37
  vi.restoreAllMocks()
38
38
  })
39
39
 
40
- it("returns the active breakpoint based on window width", () => {
41
- Object.defineProperty(window, "innerWidth", { writable: true, value: 800 })
40
+ it('returns the active breakpoint based on window width', () => {
41
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 800 })
42
42
  const bp = useBreakpoint()
43
- expect(bp()).toBe("md") // 768 <= 800 < 992
43
+ expect(bp()).toBe('md') // 768 <= 800 < 992
44
44
  })
45
45
 
46
- it("uses default breakpoints", () => {
47
- Object.defineProperty(window, "innerWidth", { writable: true, value: 400 })
46
+ it('uses default breakpoints', () => {
47
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 400 })
48
48
  const bp = useBreakpoint()
49
- expect(bp()).toBe("xs") // 0 <= 400 < 576
49
+ expect(bp()).toBe('xs') // 0 <= 400 < 576
50
50
 
51
- Object.defineProperty(window, "innerWidth", { writable: true, value: 600 })
51
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 600 })
52
52
  const bp2 = useBreakpoint()
53
- expect(bp2()).toBe("sm") // 576 <= 600 < 768
53
+ expect(bp2()).toBe('sm') // 576 <= 600 < 768
54
54
  })
55
55
 
56
- it("supports custom breakpoints", () => {
57
- Object.defineProperty(window, "innerWidth", { writable: true, value: 500 })
56
+ it('supports custom breakpoints', () => {
57
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 500 })
58
58
  const bp = useBreakpoint({ mobile: 0, tablet: 600, desktop: 1024 })
59
- expect(bp()).toBe("mobile")
59
+ expect(bp()).toBe('mobile')
60
60
  })
61
61
 
62
- it("returns largest matching breakpoint", () => {
63
- Object.defineProperty(window, "innerWidth", { writable: true, value: 1200 })
62
+ it('returns largest matching breakpoint', () => {
63
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 1200 })
64
64
  const bp = useBreakpoint()
65
- expect(bp()).toBe("xl")
65
+ expect(bp()).toBe('xl')
66
66
  })
67
67
 
68
- it("returns first breakpoint for very small widths", () => {
69
- Object.defineProperty(window, "innerWidth", { writable: true, value: 0 })
68
+ it('returns first breakpoint for very small widths', () => {
69
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 0 })
70
70
  const bp = useBreakpoint()
71
- expect(bp()).toBe("xs")
71
+ expect(bp()).toBe('xs')
72
72
  })
73
73
 
74
- it("updates breakpoint on resize", () => {
75
- Object.defineProperty(window, "innerWidth", { writable: true, value: 800 })
74
+ it('updates breakpoint on resize', () => {
75
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 800 })
76
76
  const bp = useBreakpoint()
77
77
  mountCallbacks.forEach((cb) => {
78
78
  cb()
79
79
  })
80
- expect(bp()).toBe("md")
80
+ expect(bp()).toBe('md')
81
81
 
82
82
  // Simulate resize
83
- Object.defineProperty(window, "innerWidth", { writable: true, value: 1200 })
84
- window.dispatchEvent(new Event("resize"))
83
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 1200 })
84
+ window.dispatchEvent(new Event('resize'))
85
85
 
86
86
  // Execute rAF callback
87
87
  rafCallback?.(0)
88
- expect(bp()).toBe("xl")
88
+ expect(bp()).toBe('xl')
89
89
  })
90
90
 
91
- it("debounces resize with requestAnimationFrame", () => {
92
- Object.defineProperty(window, "innerWidth", { writable: true, value: 800 })
91
+ it('debounces resize with requestAnimationFrame', () => {
92
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 800 })
93
93
  const bp = useBreakpoint()
94
94
  mountCallbacks.forEach((cb) => {
95
95
  cb()
96
96
  })
97
97
 
98
- Object.defineProperty(window, "innerWidth", { writable: true, value: 1200 })
99
- window.dispatchEvent(new Event("resize"))
98
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 1200 })
99
+ window.dispatchEvent(new Event('resize'))
100
100
 
101
101
  // Before rAF fires, value should still be old
102
- expect(bp()).toBe("md")
102
+ expect(bp()).toBe('md')
103
103
 
104
104
  rafCallback?.(0)
105
- expect(bp()).toBe("xl")
105
+ expect(bp()).toBe('xl')
106
106
  })
107
107
 
108
- it("cancels pending rAF on new resize", () => {
109
- Object.defineProperty(window, "innerWidth", { writable: true, value: 800 })
108
+ it('cancels pending rAF on new resize', () => {
109
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 800 })
110
110
  useBreakpoint()
111
111
  mountCallbacks.forEach((cb) => {
112
112
  cb()
113
113
  })
114
114
 
115
- window.dispatchEvent(new Event("resize"))
116
- window.dispatchEvent(new Event("resize"))
115
+ window.dispatchEvent(new Event('resize'))
116
+ window.dispatchEvent(new Event('resize'))
117
117
 
118
118
  expect(window.cancelAnimationFrame).toHaveBeenCalled()
119
119
  })
120
120
 
121
- it("cleans up on unmount", () => {
122
- const removeSpy = vi.spyOn(window, "removeEventListener")
121
+ it('cleans up on unmount', () => {
122
+ const removeSpy = vi.spyOn(window, 'removeEventListener')
123
123
  useBreakpoint()
124
124
  mountCallbacks.forEach((cb) => {
125
125
  cb()
@@ -128,21 +128,21 @@ describe("useBreakpoint", () => {
128
128
  cb()
129
129
  })
130
130
 
131
- expect(removeSpy).toHaveBeenCalledWith("resize", expect.any(Function))
131
+ expect(removeSpy).toHaveBeenCalledWith('resize', expect.any(Function))
132
132
  })
133
133
 
134
- it("does not update when breakpoint has not changed", () => {
135
- Object.defineProperty(window, "innerWidth", { writable: true, value: 800 })
134
+ it('does not update when breakpoint has not changed', () => {
135
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 800 })
136
136
  const bp = useBreakpoint()
137
137
  mountCallbacks.forEach((cb) => {
138
138
  cb()
139
139
  })
140
140
 
141
141
  // Resize but stay within same breakpoint
142
- Object.defineProperty(window, "innerWidth", { writable: true, value: 850 })
143
- window.dispatchEvent(new Event("resize"))
142
+ Object.defineProperty(window, 'innerWidth', { writable: true, value: 850 })
143
+ window.dispatchEvent(new Event('resize'))
144
144
  rafCallback?.(0)
145
145
 
146
- expect(bp()).toBe("md") // Still md (768-991)
146
+ expect(bp()).toBe('md') // Still md (768-991)
147
147
  })
148
148
  })
@@ -1,10 +1,10 @@
1
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
3
  // Capture registered callbacks so we can invoke lifecycle manually
4
4
  let mountCallbacks: Array<() => void> = []
5
5
  let unmountCallbacks: Array<() => void> = []
6
6
 
7
- vi.mock("@pyreon/core", () => ({
7
+ vi.mock('@pyreon/core', () => ({
8
8
  onMount: (fn: () => unknown) => {
9
9
  mountCallbacks.push(fn as () => void)
10
10
  },
@@ -13,15 +13,15 @@ vi.mock("@pyreon/core", () => ({
13
13
  },
14
14
  }))
15
15
 
16
- import { useClickOutside } from "../useClickOutside"
16
+ import { useClickOutside } from '../useClickOutside'
17
17
 
18
- describe("useClickOutside", () => {
18
+ describe('useClickOutside', () => {
19
19
  let container: HTMLDivElement
20
20
 
21
21
  beforeEach(() => {
22
22
  mountCallbacks = []
23
23
  unmountCallbacks = []
24
- container = document.createElement("div")
24
+ container = document.createElement('div')
25
25
  document.body.appendChild(container)
26
26
  })
27
27
 
@@ -29,7 +29,7 @@ describe("useClickOutside", () => {
29
29
  document.body.removeChild(container)
30
30
  })
31
31
 
32
- it("calls handler when clicking outside the element", () => {
32
+ it('calls handler when clicking outside the element', () => {
33
33
  const handler = vi.fn()
34
34
  useClickOutside(() => container, handler)
35
35
 
@@ -38,20 +38,20 @@ describe("useClickOutside", () => {
38
38
  cb()
39
39
  })
40
40
 
41
- const outside = document.createElement("div")
41
+ const outside = document.createElement('div')
42
42
  document.body.appendChild(outside)
43
43
 
44
- const event = new MouseEvent("mousedown", { bubbles: true })
45
- Object.defineProperty(event, "target", { value: outside })
44
+ const event = new MouseEvent('mousedown', { bubbles: true })
45
+ Object.defineProperty(event, 'target', { value: outside })
46
46
  document.dispatchEvent(event)
47
47
 
48
48
  expect(handler).toHaveBeenCalledTimes(1)
49
49
  document.body.removeChild(outside)
50
50
  })
51
51
 
52
- it("does not call handler when clicking inside the element", () => {
52
+ it('does not call handler when clicking inside the element', () => {
53
53
  const handler = vi.fn()
54
- const child = document.createElement("span")
54
+ const child = document.createElement('span')
55
55
  container.appendChild(child)
56
56
 
57
57
  useClickOutside(() => container, handler)
@@ -59,86 +59,86 @@ describe("useClickOutside", () => {
59
59
  cb()
60
60
  })
61
61
 
62
- const event = new MouseEvent("mousedown", { bubbles: true })
63
- Object.defineProperty(event, "target", { value: child })
62
+ const event = new MouseEvent('mousedown', { bubbles: true })
63
+ Object.defineProperty(event, 'target', { value: child })
64
64
  document.dispatchEvent(event)
65
65
 
66
66
  expect(handler).not.toHaveBeenCalled()
67
67
  })
68
68
 
69
- it("does not call handler when clicking the element itself", () => {
69
+ it('does not call handler when clicking the element itself', () => {
70
70
  const handler = vi.fn()
71
71
  useClickOutside(() => container, handler)
72
72
  mountCallbacks.forEach((cb) => {
73
73
  cb()
74
74
  })
75
75
 
76
- const event = new MouseEvent("mousedown", { bubbles: true })
77
- Object.defineProperty(event, "target", { value: container })
76
+ const event = new MouseEvent('mousedown', { bubbles: true })
77
+ Object.defineProperty(event, 'target', { value: container })
78
78
  document.dispatchEvent(event)
79
79
 
80
80
  expect(handler).not.toHaveBeenCalled()
81
81
  })
82
82
 
83
- it("does not call handler when element is null", () => {
83
+ it('does not call handler when element is null', () => {
84
84
  const handler = vi.fn()
85
85
  useClickOutside(() => null, handler)
86
86
  mountCallbacks.forEach((cb) => {
87
87
  cb()
88
88
  })
89
89
 
90
- const event = new MouseEvent("mousedown", { bubbles: true })
91
- Object.defineProperty(event, "target", { value: document.body })
90
+ const event = new MouseEvent('mousedown', { bubbles: true })
91
+ Object.defineProperty(event, 'target', { value: document.body })
92
92
  document.dispatchEvent(event)
93
93
 
94
94
  expect(handler).not.toHaveBeenCalled()
95
95
  })
96
96
 
97
- it("handles touchstart events", () => {
97
+ it('handles touchstart events', () => {
98
98
  const handler = vi.fn()
99
99
  useClickOutside(() => container, handler)
100
100
  mountCallbacks.forEach((cb) => {
101
101
  cb()
102
102
  })
103
103
 
104
- const outside = document.createElement("div")
104
+ const outside = document.createElement('div')
105
105
  document.body.appendChild(outside)
106
106
 
107
- const event = new Event("touchstart", { bubbles: true })
108
- Object.defineProperty(event, "target", { value: outside })
107
+ const event = new Event('touchstart', { bubbles: true })
108
+ Object.defineProperty(event, 'target', { value: outside })
109
109
  document.dispatchEvent(event)
110
110
 
111
111
  expect(handler).toHaveBeenCalledTimes(1)
112
112
  document.body.removeChild(outside)
113
113
  })
114
114
 
115
- it("removes listeners on unmount", () => {
115
+ it('removes listeners on unmount', () => {
116
116
  const handler = vi.fn()
117
117
  useClickOutside(() => container, handler)
118
118
  mountCallbacks.forEach((cb) => {
119
119
  cb()
120
120
  })
121
121
 
122
- const removeSpy = vi.spyOn(document, "removeEventListener")
122
+ const removeSpy = vi.spyOn(document, 'removeEventListener')
123
123
  unmountCallbacks.forEach((cb) => {
124
124
  cb()
125
125
  })
126
126
 
127
- expect(removeSpy).toHaveBeenCalledWith("mousedown", expect.any(Function), true)
128
- expect(removeSpy).toHaveBeenCalledWith("touchstart", expect.any(Function), true)
127
+ expect(removeSpy).toHaveBeenCalledWith('mousedown', expect.any(Function), true)
128
+ expect(removeSpy).toHaveBeenCalledWith('touchstart', expect.any(Function), true)
129
129
  removeSpy.mockRestore()
130
130
  })
131
131
 
132
- it("adds listeners with capture phase", () => {
132
+ it('adds listeners with capture phase', () => {
133
133
  const handler = vi.fn()
134
- const addSpy = vi.spyOn(document, "addEventListener")
134
+ const addSpy = vi.spyOn(document, 'addEventListener')
135
135
  useClickOutside(() => container, handler)
136
136
  mountCallbacks.forEach((cb) => {
137
137
  cb()
138
138
  })
139
139
 
140
- expect(addSpy).toHaveBeenCalledWith("mousedown", expect.any(Function), true)
141
- expect(addSpy).toHaveBeenCalledWith("touchstart", expect.any(Function), true)
140
+ expect(addSpy).toHaveBeenCalledWith('mousedown', expect.any(Function), true)
141
+ expect(addSpy).toHaveBeenCalledWith('touchstart', expect.any(Function), true)
142
142
  addSpy.mockRestore()
143
143
  })
144
144
  })
@@ -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 { useColorScheme } from "../useColorScheme"
15
+ import { useColorScheme } from '../useColorScheme'
16
16
 
17
- describe("useColorScheme", () => {
17
+ describe('useColorScheme', () => {
18
18
  let changeListeners: Map<string, (e: MediaQueryListEvent) => void>
19
19
 
20
20
  beforeEach(() => {
@@ -22,35 +22,35 @@ describe("useColorScheme", () => {
22
22
  unmountCallbacks = []
23
23
  changeListeners = new Map()
24
24
 
25
- Object.defineProperty(window, "matchMedia", {
25
+ Object.defineProperty(window, 'matchMedia', {
26
26
  writable: true,
27
27
  value: vi.fn((query: string) => ({
28
28
  matches: false,
29
29
  media: query,
30
30
  addEventListener: vi.fn((event: string, cb: (e: MediaQueryListEvent) => void) => {
31
- if (event === "change") changeListeners.set(query, cb)
31
+ if (event === 'change') changeListeners.set(query, cb)
32
32
  }),
33
33
  removeEventListener: vi.fn(),
34
34
  })),
35
35
  })
36
36
  })
37
37
 
38
- it("returns light by default", () => {
38
+ it('returns light by default', () => {
39
39
  const scheme = useColorScheme()
40
40
  mountCallbacks.forEach((cb) => {
41
41
  cb()
42
42
  })
43
- expect(scheme()).toBe("light")
43
+ expect(scheme()).toBe('light')
44
44
  })
45
45
 
46
- it("returns dark when prefers-color-scheme is dark", () => {
47
- Object.defineProperty(window, "matchMedia", {
46
+ it('returns dark when prefers-color-scheme is dark', () => {
47
+ Object.defineProperty(window, 'matchMedia', {
48
48
  writable: true,
49
49
  value: vi.fn((query: string) => ({
50
50
  matches: true,
51
51
  media: query,
52
52
  addEventListener: vi.fn((event: string, cb: (e: MediaQueryListEvent) => void) => {
53
- if (event === "change") changeListeners.set(query, cb)
53
+ if (event === 'change') changeListeners.set(query, cb)
54
54
  }),
55
55
  removeEventListener: vi.fn(),
56
56
  })),
@@ -60,29 +60,29 @@ describe("useColorScheme", () => {
60
60
  mountCallbacks.forEach((cb) => {
61
61
  cb()
62
62
  })
63
- expect(scheme()).toBe("dark")
63
+ expect(scheme()).toBe('dark')
64
64
  })
65
65
 
66
- it("updates when color scheme changes from light to dark", () => {
66
+ it('updates when color scheme changes from light to dark', () => {
67
67
  const scheme = useColorScheme()
68
68
  mountCallbacks.forEach((cb) => {
69
69
  cb()
70
70
  })
71
- expect(scheme()).toBe("light")
71
+ expect(scheme()).toBe('light')
72
72
 
73
- const listener = changeListeners.get("(prefers-color-scheme: dark)")
73
+ const listener = changeListeners.get('(prefers-color-scheme: dark)')
74
74
  listener?.({ matches: true } as MediaQueryListEvent)
75
- expect(scheme()).toBe("dark")
75
+ expect(scheme()).toBe('dark')
76
76
  })
77
77
 
78
- it("updates when color scheme changes from dark to light", () => {
79
- Object.defineProperty(window, "matchMedia", {
78
+ it('updates when color scheme changes from dark to light', () => {
79
+ Object.defineProperty(window, 'matchMedia', {
80
80
  writable: true,
81
81
  value: vi.fn((query: string) => ({
82
82
  matches: true,
83
83
  media: query,
84
84
  addEventListener: vi.fn((event: string, cb: (e: MediaQueryListEvent) => void) => {
85
- if (event === "change") changeListeners.set(query, cb)
85
+ if (event === 'change') changeListeners.set(query, cb)
86
86
  }),
87
87
  removeEventListener: vi.fn(),
88
88
  })),
@@ -92,10 +92,10 @@ describe("useColorScheme", () => {
92
92
  mountCallbacks.forEach((cb) => {
93
93
  cb()
94
94
  })
95
- expect(scheme()).toBe("dark")
95
+ expect(scheme()).toBe('dark')
96
96
 
97
- const listener = changeListeners.get("(prefers-color-scheme: dark)")
97
+ const listener = changeListeners.get('(prefers-color-scheme: dark)')
98
98
  listener?.({ matches: false } as MediaQueryListEvent)
99
- expect(scheme()).toBe("light")
99
+ expect(scheme()).toBe('light')
100
100
  })
101
101
  })