@pyreon/kinetic 0.11.5 → 0.11.7

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,59 +1,59 @@
1
- import { signal } from "@pyreon/reactivity"
2
- import useAnimationEnd from "../useAnimationEnd"
1
+ import { signal } from '@pyreon/reactivity'
2
+ import useAnimationEnd from '../useAnimationEnd'
3
3
 
4
4
  const createMockRef = () => {
5
- const el = document.createElement("div")
5
+ const el = document.createElement('div')
6
6
  return { current: el }
7
7
  }
8
8
 
9
- describe("useAnimationEnd", () => {
9
+ describe('useAnimationEnd', () => {
10
10
  beforeEach(() => vi.useFakeTimers())
11
11
  afterEach(() => vi.useRealTimers())
12
12
 
13
- it("calls onEnd when transitionend fires on the element", () => {
13
+ it('calls onEnd when transitionend fires on the element', () => {
14
14
  const onEnd = vi.fn()
15
15
  const ref = createMockRef()
16
16
  const active = signal(true)
17
17
 
18
18
  useAnimationEnd({ ref, onEnd, active })
19
19
 
20
- const event = new Event("transitionend", { bubbles: true })
21
- Object.defineProperty(event, "target", { value: ref.current })
20
+ const event = new Event('transitionend', { bubbles: true })
21
+ Object.defineProperty(event, 'target', { value: ref.current })
22
22
  ref.current.dispatchEvent(event)
23
23
 
24
24
  expect(onEnd).toHaveBeenCalledTimes(1)
25
25
  })
26
26
 
27
- it("calls onEnd when animationend fires on the element", () => {
27
+ it('calls onEnd when animationend fires on the element', () => {
28
28
  const onEnd = vi.fn()
29
29
  const ref = createMockRef()
30
30
  const active = signal(true)
31
31
 
32
32
  useAnimationEnd({ ref, onEnd, active })
33
33
 
34
- const event = new Event("animationend", { bubbles: true })
35
- Object.defineProperty(event, "target", { value: ref.current })
34
+ const event = new Event('animationend', { bubbles: true })
35
+ Object.defineProperty(event, 'target', { value: ref.current })
36
36
  ref.current.dispatchEvent(event)
37
37
 
38
38
  expect(onEnd).toHaveBeenCalledTimes(1)
39
39
  })
40
40
 
41
- it("ignores bubbled events from children", () => {
41
+ it('ignores bubbled events from children', () => {
42
42
  const onEnd = vi.fn()
43
43
  const ref = createMockRef()
44
- const child = document.createElement("span")
44
+ const child = document.createElement('span')
45
45
  ref.current.appendChild(child)
46
46
  const active = signal(true)
47
47
 
48
48
  useAnimationEnd({ ref, onEnd, active })
49
49
 
50
- const event = new Event("transitionend", { bubbles: true })
50
+ const event = new Event('transitionend', { bubbles: true })
51
51
  child.dispatchEvent(event)
52
52
 
53
53
  expect(onEnd).not.toHaveBeenCalled()
54
54
  })
55
55
 
56
- it("fires timeout fallback when no event fires", () => {
56
+ it('fires timeout fallback when no event fires', () => {
57
57
  const onEnd = vi.fn()
58
58
  const ref = createMockRef()
59
59
  const active = signal(true)
@@ -67,7 +67,7 @@ describe("useAnimationEnd", () => {
67
67
  expect(onEnd).toHaveBeenCalledTimes(1)
68
68
  })
69
69
 
70
- it("uses default timeout of 5000ms", () => {
70
+ it('uses default timeout of 5000ms', () => {
71
71
  const onEnd = vi.fn()
72
72
  const ref = createMockRef()
73
73
  const active = signal(true)
@@ -81,25 +81,25 @@ describe("useAnimationEnd", () => {
81
81
  expect(onEnd).toHaveBeenCalledTimes(1)
82
82
  })
83
83
 
84
- it("only fires onEnd once even if multiple events fire", () => {
84
+ it('only fires onEnd once even if multiple events fire', () => {
85
85
  const onEnd = vi.fn()
86
86
  const ref = createMockRef()
87
87
  const active = signal(true)
88
88
 
89
89
  useAnimationEnd({ ref, onEnd, active })
90
90
 
91
- const event1 = new Event("transitionend", { bubbles: true })
92
- Object.defineProperty(event1, "target", { value: ref.current })
91
+ const event1 = new Event('transitionend', { bubbles: true })
92
+ Object.defineProperty(event1, 'target', { value: ref.current })
93
93
  ref.current.dispatchEvent(event1)
94
94
 
95
- const event2 = new Event("animationend", { bubbles: true })
96
- Object.defineProperty(event2, "target", { value: ref.current })
95
+ const event2 = new Event('animationend', { bubbles: true })
96
+ Object.defineProperty(event2, 'target', { value: ref.current })
97
97
  ref.current.dispatchEvent(event2)
98
98
 
99
99
  expect(onEnd).toHaveBeenCalledTimes(1)
100
100
  })
101
101
 
102
- it("does not fire when active is false", () => {
102
+ it('does not fire when active is false', () => {
103
103
  const onEnd = vi.fn()
104
104
  const ref = createMockRef()
105
105
  const active = signal(false)
@@ -111,7 +111,7 @@ describe("useAnimationEnd", () => {
111
111
  expect(onEnd).not.toHaveBeenCalled()
112
112
  })
113
113
 
114
- it("does not fire when active=true but ref.current is null", () => {
114
+ it('does not fire when active=true but ref.current is null', () => {
115
115
  const onEnd = vi.fn()
116
116
  const ref = { current: null } as { current: HTMLElement | null }
117
117
  const active = signal(true)
@@ -124,7 +124,7 @@ describe("useAnimationEnd", () => {
124
124
  expect(onEnd).not.toHaveBeenCalled()
125
125
  })
126
126
 
127
- it("does not call onEnd twice when transitionend fires and then timeout fires", () => {
127
+ it('does not call onEnd twice when transitionend fires and then timeout fires', () => {
128
128
  const onEnd = vi.fn()
129
129
  const ref = createMockRef()
130
130
  const active = signal(true)
@@ -132,8 +132,8 @@ describe("useAnimationEnd", () => {
132
132
  useAnimationEnd({ ref, onEnd, active, timeout: 1000 })
133
133
 
134
134
  // First: transitionend fires — calls done()
135
- const event = new Event("transitionend", { bubbles: true })
136
- Object.defineProperty(event, "target", { value: ref.current })
135
+ const event = new Event('transitionend', { bubbles: true })
136
+ Object.defineProperty(event, 'target', { value: ref.current })
137
137
  ref.current.dispatchEvent(event)
138
138
 
139
139
  expect(onEnd).toHaveBeenCalledTimes(1)
@@ -144,7 +144,7 @@ describe("useAnimationEnd", () => {
144
144
  expect(onEnd).toHaveBeenCalledTimes(1)
145
145
  })
146
146
 
147
- it("does not call onEnd twice when timeout fires and then transitionend fires", () => {
147
+ it('does not call onEnd twice when timeout fires and then transitionend fires', () => {
148
148
  const onEnd = vi.fn()
149
149
  const ref = createMockRef()
150
150
  const active = signal(true)
@@ -157,14 +157,14 @@ describe("useAnimationEnd", () => {
157
157
  expect(onEnd).toHaveBeenCalledTimes(1)
158
158
 
159
159
  // Second: transitionend fires — should be no-op via called guard
160
- const event = new Event("transitionend", { bubbles: true })
161
- Object.defineProperty(event, "target", { value: ref.current })
160
+ const event = new Event('transitionend', { bubbles: true })
161
+ Object.defineProperty(event, 'target', { value: ref.current })
162
162
  ref.current.dispatchEvent(event)
163
163
 
164
164
  expect(onEnd).toHaveBeenCalledTimes(1)
165
165
  })
166
166
 
167
- it("resets called when active transitions from true to false", () => {
167
+ it('resets called when active transitions from true to false', () => {
168
168
  const onEnd = vi.fn()
169
169
  const ref = createMockRef()
170
170
  const active = signal(true)
@@ -172,8 +172,8 @@ describe("useAnimationEnd", () => {
172
172
  useAnimationEnd({ ref, onEnd, active, timeout: 1000 })
173
173
 
174
174
  // Fire to set called = true
175
- const event = new Event("transitionend", { bubbles: true })
176
- Object.defineProperty(event, "target", { value: ref.current })
175
+ const event = new Event('transitionend', { bubbles: true })
176
+ Object.defineProperty(event, 'target', { value: ref.current })
177
177
  ref.current.dispatchEvent(event)
178
178
 
179
179
  expect(onEnd).toHaveBeenCalledTimes(1)
@@ -185,8 +185,8 @@ describe("useAnimationEnd", () => {
185
185
  active.set(true)
186
186
 
187
187
  // Should be able to fire again
188
- const event2 = new Event("transitionend", { bubbles: true })
189
- Object.defineProperty(event2, "target", { value: ref.current })
188
+ const event2 = new Event('transitionend', { bubbles: true })
189
+ Object.defineProperty(event2, 'target', { value: ref.current })
190
190
  ref.current.dispatchEvent(event2)
191
191
 
192
192
  expect(onEnd).toHaveBeenCalledTimes(2)
@@ -2,7 +2,7 @@
2
2
  let mountCallbacks: Array<() => undefined | (() => void)> = []
3
3
  let unmountCallbacks: Array<() => void> = []
4
4
 
5
- vi.mock("@pyreon/core", () => ({
5
+ vi.mock('@pyreon/core', () => ({
6
6
  onMount: vi.fn((cb: () => undefined | (() => void)) => {
7
7
  mountCallbacks.push(cb)
8
8
  }),
@@ -11,7 +11,7 @@ vi.mock("@pyreon/core", () => ({
11
11
  }),
12
12
  }))
13
13
 
14
- vi.mock("@pyreon/reactivity", () => {
14
+ vi.mock('@pyreon/reactivity', () => {
15
15
  const signal = <T>(initial: T) => {
16
16
  let value = initial
17
17
  const s = (() => value) as (() => T) & {
@@ -39,20 +39,20 @@ vi.mock("@pyreon/reactivity", () => {
39
39
  return { signal }
40
40
  })
41
41
 
42
- import { useReducedMotion } from "../useReducedMotion"
42
+ import { useReducedMotion } from '../useReducedMotion'
43
43
 
44
- describe("useReducedMotion", () => {
44
+ describe('useReducedMotion', () => {
45
45
  let changeHandlers: Array<(e: any) => void>
46
46
  let removedHandlers: Array<(e: any) => void>
47
47
 
48
48
  const createMockMQL = (matches: boolean) => ({
49
49
  matches,
50
- media: "(prefers-reduced-motion: reduce)",
50
+ media: '(prefers-reduced-motion: reduce)',
51
51
  addEventListener: vi.fn((event: string, handler: (e: any) => void) => {
52
- if (event === "change") changeHandlers.push(handler)
52
+ if (event === 'change') changeHandlers.push(handler)
53
53
  }),
54
54
  removeEventListener: vi.fn((event: string, handler: (e: any) => void) => {
55
- if (event === "change") removedHandlers.push(handler)
55
+ if (event === 'change') removedHandlers.push(handler)
56
56
  }),
57
57
  })
58
58
 
@@ -67,18 +67,18 @@ describe("useReducedMotion", () => {
67
67
  vi.restoreAllMocks()
68
68
  })
69
69
 
70
- it("returns false initially", () => {
70
+ it('returns false initially', () => {
71
71
  vi.stubGlobal(
72
- "matchMedia",
72
+ 'matchMedia',
73
73
  vi.fn(() => createMockMQL(false)),
74
74
  )
75
75
  const result = useReducedMotion()
76
76
  expect(result()).toBe(false)
77
77
  })
78
78
 
79
- it("reads matchMedia state on mount (true)", () => {
79
+ it('reads matchMedia state on mount (true)', () => {
80
80
  vi.stubGlobal(
81
- "matchMedia",
81
+ 'matchMedia',
82
82
  vi.fn(() => createMockMQL(true)),
83
83
  )
84
84
  const result = useReducedMotion()
@@ -89,9 +89,9 @@ describe("useReducedMotion", () => {
89
89
  expect(result()).toBe(true)
90
90
  })
91
91
 
92
- it("reads matchMedia state on mount (false)", () => {
92
+ it('reads matchMedia state on mount (false)', () => {
93
93
  vi.stubGlobal(
94
- "matchMedia",
94
+ 'matchMedia',
95
95
  vi.fn(() => createMockMQL(false)),
96
96
  )
97
97
  const result = useReducedMotion()
@@ -101,9 +101,9 @@ describe("useReducedMotion", () => {
101
101
  expect(result()).toBe(false)
102
102
  })
103
103
 
104
- it("reacts to change events", () => {
104
+ it('reacts to change events', () => {
105
105
  vi.stubGlobal(
106
- "matchMedia",
106
+ 'matchMedia',
107
107
  vi.fn(() => createMockMQL(false)),
108
108
  )
109
109
  const result = useReducedMotion()
@@ -119,19 +119,19 @@ describe("useReducedMotion", () => {
119
119
  expect(result()).toBe(true)
120
120
  })
121
121
 
122
- it("queries the correct media string", () => {
122
+ it('queries the correct media string', () => {
123
123
  const mockMatchMedia = vi.fn(() => createMockMQL(false))
124
- vi.stubGlobal("matchMedia", mockMatchMedia)
124
+ vi.stubGlobal('matchMedia', mockMatchMedia)
125
125
 
126
126
  useReducedMotion()
127
127
  for (const cb of mountCallbacks) cb()
128
128
 
129
- expect(mockMatchMedia).toHaveBeenCalledWith("(prefers-reduced-motion: reduce)")
129
+ expect(mockMatchMedia).toHaveBeenCalledWith('(prefers-reduced-motion: reduce)')
130
130
  })
131
131
 
132
- it("registers a change listener on mount", () => {
132
+ it('registers a change listener on mount', () => {
133
133
  vi.stubGlobal(
134
- "matchMedia",
134
+ 'matchMedia',
135
135
  vi.fn(() => createMockMQL(false)),
136
136
  )
137
137
  useReducedMotion()
@@ -141,9 +141,9 @@ describe("useReducedMotion", () => {
141
141
  expect(changeHandlers).toHaveLength(1)
142
142
  })
143
143
 
144
- it("removes the change listener on unmount", () => {
144
+ it('removes the change listener on unmount', () => {
145
145
  vi.stubGlobal(
146
- "matchMedia",
146
+ 'matchMedia',
147
147
  vi.fn(() => createMockMQL(false)),
148
148
  )
149
149
  useReducedMotion()
@@ -1,132 +1,132 @@
1
- import { signal } from "@pyreon/reactivity"
2
- import useTransitionState from "../useTransitionState"
1
+ import { signal } from '@pyreon/reactivity'
2
+ import useTransitionState from '../useTransitionState'
3
3
 
4
- describe("useTransitionState", () => {
5
- it("initial state is hidden when show=false", () => {
4
+ describe('useTransitionState', () => {
5
+ it('initial state is hidden when show=false', () => {
6
6
  const show = signal(false)
7
7
  const result = useTransitionState({ show })
8
- expect(result.stage()).toBe("hidden")
8
+ expect(result.stage()).toBe('hidden')
9
9
  expect(result.shouldMount()).toBe(false)
10
10
  })
11
11
 
12
- it("initial state is entered when show=true and appear=false", () => {
12
+ it('initial state is entered when show=true and appear=false', () => {
13
13
  const show = signal(true)
14
14
  const result = useTransitionState({ show })
15
- expect(result.stage()).toBe("entered")
15
+ expect(result.stage()).toBe('entered')
16
16
  expect(result.shouldMount()).toBe(true)
17
17
  })
18
18
 
19
- it("transitions to entering when show changes false->true", () => {
19
+ it('transitions to entering when show changes false->true', () => {
20
20
  const show = signal(false)
21
21
  const result = useTransitionState({ show })
22
22
 
23
- expect(result.stage()).toBe("hidden")
23
+ expect(result.stage()).toBe('hidden')
24
24
 
25
25
  show.set(true)
26
- expect(result.stage()).toBe("entering")
26
+ expect(result.stage()).toBe('entering')
27
27
  expect(result.shouldMount()).toBe(true)
28
28
  })
29
29
 
30
- it("complete() transitions entering->entered", () => {
30
+ it('complete() transitions entering->entered', () => {
31
31
  const show = signal(false)
32
32
  const result = useTransitionState({ show })
33
33
 
34
34
  show.set(true)
35
- expect(result.stage()).toBe("entering")
35
+ expect(result.stage()).toBe('entering')
36
36
 
37
37
  result.complete()
38
- expect(result.stage()).toBe("entered")
38
+ expect(result.stage()).toBe('entered')
39
39
  })
40
40
 
41
- it("transitions to leaving when show changes true->false", () => {
41
+ it('transitions to leaving when show changes true->false', () => {
42
42
  const show = signal(true)
43
43
  const result = useTransitionState({ show })
44
44
 
45
- expect(result.stage()).toBe("entered")
45
+ expect(result.stage()).toBe('entered')
46
46
 
47
47
  show.set(false)
48
- expect(result.stage()).toBe("leaving")
48
+ expect(result.stage()).toBe('leaving')
49
49
  expect(result.shouldMount()).toBe(true)
50
50
  })
51
51
 
52
- it("complete() transitions leaving->hidden", () => {
52
+ it('complete() transitions leaving->hidden', () => {
53
53
  const show = signal(true)
54
54
  const result = useTransitionState({ show })
55
55
 
56
56
  show.set(false)
57
- expect(result.stage()).toBe("leaving")
57
+ expect(result.stage()).toBe('leaving')
58
58
 
59
59
  result.complete()
60
- expect(result.stage()).toBe("hidden")
60
+ expect(result.stage()).toBe('hidden')
61
61
  expect(result.shouldMount()).toBe(false)
62
62
  })
63
63
 
64
- it("appear=true enters after ref is connected", () => {
64
+ it('appear=true enters after ref is connected', () => {
65
65
  const show = signal(true)
66
66
  const result = useTransitionState({ show, appear: true })
67
67
  // Before ref is wired, element should be mounted but stage is 'entered'
68
- expect(result.stage()).toBe("entered")
68
+ expect(result.stage()).toBe('entered')
69
69
  expect(result.shouldMount()).toBe(true)
70
70
 
71
71
  // Simulate ref connection (as the renderer would do)
72
- const el = document.createElement("div")
73
- if (typeof result.ref === "function") {
72
+ const el = document.createElement('div')
73
+ if (typeof result.ref === 'function') {
74
74
  result.ref(el)
75
75
  }
76
76
  // Now the appear animation should trigger
77
- expect(result.stage()).toBe("entering")
77
+ expect(result.stage()).toBe('entering')
78
78
  })
79
79
 
80
- it("complete() is a no-op in entered state", () => {
80
+ it('complete() is a no-op in entered state', () => {
81
81
  const show = signal(true)
82
82
  const result = useTransitionState({ show })
83
83
 
84
- expect(result.stage()).toBe("entered")
84
+ expect(result.stage()).toBe('entered')
85
85
 
86
86
  result.complete()
87
- expect(result.stage()).toBe("entered")
87
+ expect(result.stage()).toBe('entered')
88
88
  })
89
89
 
90
- it("complete() is a no-op in hidden state", () => {
90
+ it('complete() is a no-op in hidden state', () => {
91
91
  const show = signal(false)
92
92
  const result = useTransitionState({ show })
93
93
 
94
- expect(result.stage()).toBe("hidden")
94
+ expect(result.stage()).toBe('hidden')
95
95
 
96
96
  result.complete()
97
- expect(result.stage()).toBe("hidden")
97
+ expect(result.stage()).toBe('hidden')
98
98
  })
99
99
 
100
- it("handles rapid toggling true->false->true", () => {
100
+ it('handles rapid toggling true->false->true', () => {
101
101
  const show = signal(true)
102
102
  const result = useTransitionState({ show })
103
103
 
104
104
  // Start leave
105
105
  show.set(false)
106
- expect(result.stage()).toBe("leaving")
106
+ expect(result.stage()).toBe('leaving')
107
107
 
108
108
  // Interrupt with enter before leave completes
109
109
  show.set(true)
110
- expect(result.stage()).toBe("entering")
110
+ expect(result.stage()).toBe('entering')
111
111
  })
112
112
 
113
- it("handles rapid toggling false->true->false (entering to leaving)", () => {
113
+ it('handles rapid toggling false->true->false (entering to leaving)', () => {
114
114
  const show = signal(false)
115
115
  const result = useTransitionState({ show })
116
116
 
117
117
  // Start enter
118
118
  show.set(true)
119
- expect(result.stage()).toBe("entering")
119
+ expect(result.stage()).toBe('entering')
120
120
 
121
121
  // Interrupt with leave before enter completes
122
122
  show.set(false)
123
- expect(result.stage()).toBe("leaving")
123
+ expect(result.stage()).toBe('leaving')
124
124
  })
125
125
 
126
- it("provides a ref (callback or object)", () => {
126
+ it('provides a ref (callback or object)', () => {
127
127
  const show = signal(false)
128
128
  const result = useTransitionState({ show })
129
129
  expect(result.ref).toBeDefined()
130
- expect(typeof result.ref === "function" || "current" in result.ref).toBe(true)
130
+ expect(typeof result.ref === 'function' || 'current' in result.ref).toBe(true)
131
131
  })
132
132
  })