@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,13 +1,13 @@
1
- import type { VNode } from "@pyreon/core"
2
- import { signal } from "@pyreon/reactivity"
1
+ import type { VNode } from '@pyreon/core'
2
+ import { signal } from '@pyreon/reactivity'
3
3
 
4
4
  let _reducedMotion = false
5
5
 
6
- vi.mock("../useReducedMotion", () => ({
6
+ vi.mock('../useReducedMotion', () => ({
7
7
  useReducedMotion: () => () => _reducedMotion,
8
8
  }))
9
9
 
10
- import Transition from "../Transition"
10
+ import Transition from '../Transition'
11
11
 
12
12
  // Mock rAF for deterministic double-rAF testing
13
13
  let rafCallbacks: (() => void)[] = []
@@ -19,20 +19,20 @@ beforeEach(() => {
19
19
  rafCallbacks = []
20
20
 
21
21
  vi.stubGlobal(
22
- "requestAnimationFrame",
22
+ 'requestAnimationFrame',
23
23
  vi.fn((cb: () => void) => {
24
24
  rafCallbacks.push(cb)
25
25
  return rafCallbacks.length
26
26
  }),
27
27
  )
28
28
 
29
- vi.stubGlobal("cancelAnimationFrame", vi.fn())
29
+ vi.stubGlobal('cancelAnimationFrame', vi.fn())
30
30
  })
31
31
 
32
32
  afterEach(() => {
33
33
  vi.useRealTimers()
34
- vi.stubGlobal("requestAnimationFrame", originalRaf)
35
- vi.stubGlobal("cancelAnimationFrame", originalCaf)
34
+ vi.stubGlobal('requestAnimationFrame', originalRaf)
35
+ vi.stubGlobal('cancelAnimationFrame', originalCaf)
36
36
  })
37
37
 
38
38
  const flushRaf = () => {
@@ -42,8 +42,8 @@ const flushRaf = () => {
42
42
  }
43
43
 
44
44
  const fireTransitionEnd = (el: HTMLElement) => {
45
- const event = new Event("transitionend", { bubbles: true })
46
- Object.defineProperty(event, "target", { value: el })
45
+ const event = new Event('transitionend', { bubbles: true })
46
+ Object.defineProperty(event, 'target', { value: el })
47
47
  el.dispatchEvent(event)
48
48
  }
49
49
 
@@ -56,27 +56,27 @@ const wireRef = (vnode: VNode | null, el: HTMLElement) => {
56
56
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: complex logic is inherent to this function
57
57
  const visitNode = (node: VNode) => {
58
58
  const nodeProps = node.props as Record<string, unknown>
59
- if (typeof nodeProps?.ref === "function") {
59
+ if (typeof nodeProps?.ref === 'function') {
60
60
  ;(nodeProps.ref as (element: HTMLElement | null) => void)(el)
61
- } else if (nodeProps?.ref && typeof nodeProps.ref === "object") {
61
+ } else if (nodeProps?.ref && typeof nodeProps.ref === 'object') {
62
62
  ;(nodeProps.ref as { current: HTMLElement | null }).current = el
63
63
  }
64
64
  if (node.children) {
65
65
  const ch = Array.isArray(node.children) ? node.children : [node.children]
66
66
  for (const c of ch) {
67
- if (c && typeof c === "object" && "type" in (c as object)) visitNode(c as VNode)
67
+ if (c && typeof c === 'object' && 'type' in (c as object)) visitNode(c as VNode)
68
68
  }
69
69
  }
70
70
  if (nodeProps?.children) {
71
71
  const pc = Array.isArray(nodeProps.children) ? nodeProps.children : [nodeProps.children]
72
72
  for (const c of pc) {
73
- if (c && typeof c === "object" && "type" in (c as object)) visitNode(c as VNode)
73
+ if (c && typeof c === 'object' && 'type' in (c as object)) visitNode(c as VNode)
74
74
  }
75
75
  }
76
76
  if (
77
77
  nodeProps?.fallback &&
78
- typeof nodeProps.fallback === "object" &&
79
- "type" in (nodeProps.fallback as object)
78
+ typeof nodeProps.fallback === 'object' &&
79
+ 'type' in (nodeProps.fallback as object)
80
80
  ) {
81
81
  visitNode(nodeProps.fallback as VNode)
82
82
  }
@@ -88,11 +88,11 @@ const wireRef = (vnode: VNode | null, el: HTMLElement) => {
88
88
  * Helper: call Transition and wire up a mock element to the merged ref.
89
89
  */
90
90
  const setupTransition = (props: Record<string, unknown>) => {
91
- const el = document.createElement("div")
91
+ const el = document.createElement('div')
92
92
  const child: VNode = {
93
- type: "div",
94
- props: { "data-testid": "child" },
95
- children: ["Hello"],
93
+ type: 'div',
94
+ props: { 'data-testid': 'child' },
95
+ children: ['Hello'],
96
96
  key: null,
97
97
  }
98
98
 
@@ -106,24 +106,24 @@ const setupTransition = (props: Record<string, unknown>) => {
106
106
  return { vnode, el }
107
107
  }
108
108
 
109
- describe("Transition", () => {
110
- it("returns a VNode when show=true", () => {
109
+ describe('Transition', () => {
110
+ it('returns a VNode when show=true', () => {
111
111
  const show = signal(true)
112
- const child: VNode = { type: "div", props: {}, children: ["Hello"], key: null }
112
+ const child: VNode = { type: 'div', props: {}, children: ['Hello'], key: null }
113
113
  const vnode = Transition({ show, children: child })
114
114
  expect(vnode).not.toBeNull()
115
115
  })
116
116
 
117
- it("returns a VNode with Show component", () => {
117
+ it('returns a VNode with Show component', () => {
118
118
  const show = signal(true)
119
- const child: VNode = { type: "div", props: {}, children: ["Hello"], key: null }
119
+ const child: VNode = { type: 'div', props: {}, children: ['Hello'], key: null }
120
120
  const vnode = Transition({ show, children: child })
121
121
  expect(vnode).not.toBeNull()
122
122
  // The outermost VNode should be a Show component
123
- expect(typeof vnode?.type).toBe("function")
123
+ expect(typeof vnode?.type).toBe('function')
124
124
  })
125
125
 
126
- it("fires onEnter callback when entering starts", () => {
126
+ it('fires onEnter callback when entering starts', () => {
127
127
  const show = signal(false)
128
128
  const onEnter = vi.fn()
129
129
 
@@ -135,7 +135,7 @@ describe("Transition", () => {
135
135
  expect(onEnter).toHaveBeenCalledTimes(1)
136
136
  })
137
137
 
138
- it("fires onLeave callback when leaving starts", () => {
138
+ it('fires onLeave callback when leaving starts', () => {
139
139
  const show = signal(true)
140
140
  const onLeave = vi.fn()
141
141
 
@@ -145,7 +145,7 @@ describe("Transition", () => {
145
145
  expect(onLeave).toHaveBeenCalledTimes(1)
146
146
  })
147
147
 
148
- it("fires onAfterEnter after transitionend", () => {
148
+ it('fires onAfterEnter after transitionend', () => {
149
149
  const show = signal(false)
150
150
  const onAfterEnter = vi.fn()
151
151
 
@@ -161,7 +161,7 @@ describe("Transition", () => {
161
161
  expect(onAfterEnter).toHaveBeenCalledTimes(1)
162
162
  })
163
163
 
164
- it("fires onAfterLeave after transitionend", () => {
164
+ it('fires onAfterLeave after transitionend', () => {
165
165
  const show = signal(true)
166
166
  const onAfterLeave = vi.fn()
167
167
 
@@ -177,29 +177,29 @@ describe("Transition", () => {
177
177
  expect(onAfterLeave).toHaveBeenCalledTimes(1)
178
178
  })
179
179
 
180
- it("applies enter classes on entering", () => {
180
+ it('applies enter classes on entering', () => {
181
181
  const show = signal(false)
182
182
  const { el } = setupTransition({
183
183
  show,
184
- enter: "t-enter",
185
- enterFrom: "t-enter-from",
186
- enterTo: "t-enter-to",
184
+ enter: 't-enter',
185
+ enterFrom: 't-enter-from',
186
+ enterTo: 't-enter-to',
187
187
  })
188
188
 
189
189
  show.set(true)
190
190
 
191
- expect(el.classList.contains("t-enter")).toBe(true)
192
- expect(el.classList.contains("t-enter-from")).toBe(true)
193
- expect(el.classList.contains("t-enter-to")).toBe(false)
191
+ expect(el.classList.contains('t-enter')).toBe(true)
192
+ expect(el.classList.contains('t-enter-from')).toBe(true)
193
+ expect(el.classList.contains('t-enter-to')).toBe(false)
194
194
  })
195
195
 
196
- it("swaps enterFrom to enterTo after double rAF", () => {
196
+ it('swaps enterFrom to enterTo after double rAF', () => {
197
197
  const show = signal(false)
198
198
  const { el } = setupTransition({
199
199
  show,
200
- enter: "t-enter",
201
- enterFrom: "t-enter-from",
202
- enterTo: "t-enter-to",
200
+ enter: 't-enter',
201
+ enterFrom: 't-enter-from',
202
+ enterTo: 't-enter-to',
203
203
  })
204
204
 
205
205
  show.set(true)
@@ -207,18 +207,18 @@ describe("Transition", () => {
207
207
  flushRaf()
208
208
  flushRaf()
209
209
 
210
- expect(el.classList.contains("t-enter")).toBe(true)
211
- expect(el.classList.contains("t-enter-from")).toBe(false)
212
- expect(el.classList.contains("t-enter-to")).toBe(true)
210
+ expect(el.classList.contains('t-enter')).toBe(true)
211
+ expect(el.classList.contains('t-enter-from')).toBe(false)
212
+ expect(el.classList.contains('t-enter-to')).toBe(true)
213
213
  })
214
214
 
215
- it("cleans up enter classes after transitionend", () => {
215
+ it('cleans up enter classes after transitionend', () => {
216
216
  const show = signal(false)
217
217
  const { el } = setupTransition({
218
218
  show,
219
- enter: "t-enter",
220
- enterFrom: "t-enter-from",
221
- enterTo: "t-enter-to",
219
+ enter: 't-enter',
220
+ enterFrom: 't-enter-from',
221
+ enterTo: 't-enter-to',
222
222
  })
223
223
 
224
224
  show.set(true)
@@ -227,71 +227,71 @@ describe("Transition", () => {
227
227
  fireTransitionEnd(el)
228
228
 
229
229
  // enter class should be removed on entered stage
230
- expect(el.classList.contains("t-enter")).toBe(false)
230
+ expect(el.classList.contains('t-enter')).toBe(false)
231
231
  })
232
232
 
233
- it("applies style-object transitions on entering", () => {
233
+ it('applies style-object transitions on entering', () => {
234
234
  const show = signal(false)
235
235
  const { el } = setupTransition({
236
236
  show,
237
237
  enterStyle: { opacity: 0 },
238
238
  enterToStyle: { opacity: 1 },
239
- enterTransition: "opacity 300ms ease",
239
+ enterTransition: 'opacity 300ms ease',
240
240
  })
241
241
 
242
242
  show.set(true)
243
243
 
244
- expect(el.style.opacity).toBe("0")
245
- expect(el.style.transition).toBe("opacity 300ms ease")
244
+ expect(el.style.opacity).toBe('0')
245
+ expect(el.style.transition).toBe('opacity 300ms ease')
246
246
 
247
247
  flushRaf()
248
248
  flushRaf()
249
249
 
250
- expect(el.style.opacity).toBe("1")
250
+ expect(el.style.opacity).toBe('1')
251
251
  })
252
252
 
253
- it("applies leave classes on leaving", () => {
253
+ it('applies leave classes on leaving', () => {
254
254
  const show = signal(true)
255
255
  const { el } = setupTransition({
256
256
  show,
257
- leave: "t-leave",
258
- leaveFrom: "t-leave-from",
259
- leaveTo: "t-leave-to",
257
+ leave: 't-leave',
258
+ leaveFrom: 't-leave-from',
259
+ leaveTo: 't-leave-to',
260
260
  })
261
261
 
262
262
  show.set(false)
263
263
 
264
- expect(el.classList.contains("t-leave")).toBe(true)
265
- expect(el.classList.contains("t-leave-from")).toBe(true)
264
+ expect(el.classList.contains('t-leave')).toBe(true)
265
+ expect(el.classList.contains('t-leave-from')).toBe(true)
266
266
 
267
267
  flushRaf()
268
268
  flushRaf()
269
269
 
270
- expect(el.classList.contains("t-leave-from")).toBe(false)
271
- expect(el.classList.contains("t-leave-to")).toBe(true)
270
+ expect(el.classList.contains('t-leave-from')).toBe(false)
271
+ expect(el.classList.contains('t-leave-to')).toBe(true)
272
272
  })
273
273
 
274
- it("applies leave style transitions", () => {
274
+ it('applies leave style transitions', () => {
275
275
  const show = signal(true)
276
276
  const { el } = setupTransition({
277
277
  show,
278
278
  leaveStyle: { opacity: 1 },
279
279
  leaveToStyle: { opacity: 0 },
280
- leaveTransition: "opacity 200ms ease-in",
280
+ leaveTransition: 'opacity 200ms ease-in',
281
281
  })
282
282
 
283
283
  show.set(false)
284
284
 
285
- expect(el.style.opacity).toBe("1")
286
- expect(el.style.transition).toBe("opacity 200ms ease-in")
285
+ expect(el.style.opacity).toBe('1')
286
+ expect(el.style.transition).toBe('opacity 200ms ease-in')
287
287
 
288
288
  flushRaf()
289
289
  flushRaf()
290
290
 
291
- expect(el.style.opacity).toBe("0")
291
+ expect(el.style.opacity).toBe('0')
292
292
  })
293
293
 
294
- it("appear=true fires onEnter on initial mount", () => {
294
+ it('appear=true fires onEnter on initial mount', () => {
295
295
  const show = signal(true)
296
296
  const onEnter = vi.fn()
297
297
 
@@ -300,7 +300,7 @@ describe("Transition", () => {
300
300
  expect(onEnter).toHaveBeenCalledTimes(1)
301
301
  })
302
302
 
303
- it("timeout fallback completes transition when transitionend never fires", () => {
303
+ it('timeout fallback completes transition when transitionend never fires', () => {
304
304
  const show = signal(false)
305
305
  const onAfterEnter = vi.fn()
306
306
 
@@ -315,54 +315,54 @@ describe("Transition", () => {
315
315
  expect(onAfterEnter).toHaveBeenCalledTimes(1)
316
316
  })
317
317
 
318
- it("cleans up transition style on entered stage", () => {
318
+ it('cleans up transition style on entered stage', () => {
319
319
  const show = signal(false)
320
320
  const { el } = setupTransition({
321
321
  show,
322
- enter: "t-enter",
323
- enterTransition: "opacity 300ms ease",
322
+ enter: 't-enter',
323
+ enterTransition: 'opacity 300ms ease',
324
324
  enterStyle: { opacity: 0 },
325
325
  enterToStyle: { opacity: 1 },
326
326
  })
327
327
 
328
328
  show.set(true)
329
- expect(el.style.transition).toBe("opacity 300ms ease")
330
- expect(el.classList.contains("t-enter")).toBe(true)
329
+ expect(el.style.transition).toBe('opacity 300ms ease')
330
+ expect(el.classList.contains('t-enter')).toBe(true)
331
331
 
332
332
  flushRaf()
333
333
  flushRaf()
334
334
  fireTransitionEnd(el)
335
335
 
336
336
  // After entering -> entered, transition reset and enter class removed
337
- expect(el.style.transition).toBe("")
338
- expect(el.classList.contains("t-enter")).toBe(false)
337
+ expect(el.style.transition).toBe('')
338
+ expect(el.classList.contains('t-enter')).toBe(false)
339
339
  })
340
340
  })
341
341
 
342
- describe("Transition — reduced motion", () => {
342
+ describe('Transition — reduced motion', () => {
343
343
  beforeEach(() => {
344
344
  vi.useFakeTimers()
345
345
  rafCallbacks = []
346
346
  _reducedMotion = true
347
347
 
348
348
  vi.stubGlobal(
349
- "requestAnimationFrame",
349
+ 'requestAnimationFrame',
350
350
  vi.fn((cb: () => void) => {
351
351
  rafCallbacks.push(cb)
352
352
  return rafCallbacks.length
353
353
  }),
354
354
  )
355
- vi.stubGlobal("cancelAnimationFrame", vi.fn())
355
+ vi.stubGlobal('cancelAnimationFrame', vi.fn())
356
356
  })
357
357
 
358
358
  afterEach(() => {
359
359
  vi.useRealTimers()
360
- vi.stubGlobal("requestAnimationFrame", originalRaf)
361
- vi.stubGlobal("cancelAnimationFrame", originalCaf)
360
+ vi.stubGlobal('requestAnimationFrame', originalRaf)
361
+ vi.stubGlobal('cancelAnimationFrame', originalCaf)
362
362
  _reducedMotion = false
363
363
  })
364
364
 
365
- it("reduced motion: entering fires onEnter and onAfterEnter immediately", () => {
365
+ it('reduced motion: entering fires onEnter and onAfterEnter immediately', () => {
366
366
  const show = signal(false)
367
367
  const onEnter = vi.fn()
368
368
  const onAfterEnter = vi.fn()
@@ -375,7 +375,7 @@ describe("Transition — reduced motion", () => {
375
375
  expect(onAfterEnter).toHaveBeenCalledTimes(1)
376
376
  })
377
377
 
378
- it("reduced motion: leaving fires onLeave and onAfterLeave immediately", () => {
378
+ it('reduced motion: leaving fires onLeave and onAfterLeave immediately', () => {
379
379
  const show = signal(true)
380
380
  const onLeave = vi.fn()
381
381
  const onAfterLeave = vi.fn()
@@ -388,19 +388,19 @@ describe("Transition — reduced motion", () => {
388
388
  expect(onAfterLeave).toHaveBeenCalledTimes(1)
389
389
  })
390
390
 
391
- it("reduced motion: does not use rAF or apply CSS classes", () => {
391
+ it('reduced motion: does not use rAF or apply CSS classes', () => {
392
392
  const show = signal(false)
393
393
  const { el } = setupTransition({
394
394
  show,
395
- enter: "t-enter",
396
- enterFrom: "t-enter-from",
397
- enterTo: "t-enter-to",
395
+ enter: 't-enter',
396
+ enterFrom: 't-enter-from',
397
+ enterTo: 't-enter-to',
398
398
  })
399
399
 
400
400
  show.set(true)
401
401
 
402
- expect(el.classList.contains("t-enter")).toBe(false)
403
- expect(el.classList.contains("t-enter-from")).toBe(false)
402
+ expect(el.classList.contains('t-enter')).toBe(false)
403
+ expect(el.classList.contains('t-enter-from')).toBe(false)
404
404
  expect(rafCallbacks.length).toBe(0)
405
405
  })
406
406
  })