@pyreon/kinetic 0.24.5 → 0.24.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 (37) hide show
  1. package/package.json +10 -12
  2. package/src/Collapse.tsx +0 -166
  3. package/src/Stagger.tsx +0 -63
  4. package/src/Transition.tsx +0 -280
  5. package/src/TransitionGroup.tsx +0 -139
  6. package/src/__tests__/Collapse.test.tsx +0 -803
  7. package/src/__tests__/GroupRenderer.test.tsx +0 -434
  8. package/src/__tests__/StaggerRenderer.test.tsx +0 -523
  9. package/src/__tests__/Transition.ssr.test.tsx +0 -183
  10. package/src/__tests__/Transition.test.tsx +0 -403
  11. package/src/__tests__/TransitionItem.test.tsx +0 -514
  12. package/src/__tests__/kinetic-modes.ssr.test.tsx +0 -214
  13. package/src/__tests__/kinetic.browser.test.tsx +0 -327
  14. package/src/__tests__/kinetic.test.tsx +0 -565
  15. package/src/__tests__/presets.test.ts +0 -46
  16. package/src/__tests__/stagger-component-children-hydration.test.tsx +0 -191
  17. package/src/__tests__/top-level-transition-stagger-function-children.test.tsx +0 -141
  18. package/src/__tests__/useAnimationEnd.test.ts +0 -194
  19. package/src/__tests__/useReducedMotion.test.ts +0 -160
  20. package/src/__tests__/useTransitionState.test.ts +0 -132
  21. package/src/__tests__/utils.test.ts +0 -139
  22. package/src/index.ts +0 -15
  23. package/src/jsx-augment.d.ts +0 -12
  24. package/src/kinetic/CollapseRenderer.tsx +0 -216
  25. package/src/kinetic/GroupRenderer.tsx +0 -149
  26. package/src/kinetic/StaggerRenderer.tsx +0 -94
  27. package/src/kinetic/TransitionItem.tsx +0 -250
  28. package/src/kinetic/TransitionRenderer.tsx +0 -230
  29. package/src/kinetic/createKineticComponent.tsx +0 -224
  30. package/src/kinetic/types.ts +0 -149
  31. package/src/kinetic.ts +0 -25
  32. package/src/presets.ts +0 -66
  33. package/src/types.ts +0 -118
  34. package/src/useAnimationEnd.ts +0 -59
  35. package/src/useReducedMotion.ts +0 -28
  36. package/src/useTransitionState.ts +0 -62
  37. package/src/utils.ts +0 -113
@@ -1,434 +0,0 @@
1
- import type { VNode } from '@pyreon/core'
2
- import { h } from '@pyreon/core'
3
- import GroupRenderer from '../kinetic/GroupRenderer'
4
- import type { KineticConfig } from '../kinetic/types'
5
-
6
- // Mock rAF for deterministic testing
7
- let rafCallbacks: (() => void)[] = []
8
- const originalRaf = globalThis.requestAnimationFrame
9
- const originalCaf = globalThis.cancelAnimationFrame
10
-
11
- beforeEach(() => {
12
- vi.useFakeTimers()
13
- rafCallbacks = []
14
-
15
- vi.stubGlobal(
16
- 'requestAnimationFrame',
17
- vi.fn((cb: () => void) => {
18
- rafCallbacks.push(cb)
19
- return rafCallbacks.length
20
- }),
21
- )
22
-
23
- vi.stubGlobal('cancelAnimationFrame', vi.fn())
24
- })
25
-
26
- afterEach(() => {
27
- vi.useRealTimers()
28
- vi.stubGlobal('requestAnimationFrame', originalRaf)
29
- vi.stubGlobal('cancelAnimationFrame', originalCaf)
30
- })
31
-
32
- const makeConfig = (overrides: Partial<KineticConfig> = {}): KineticConfig => ({
33
- tag: 'div',
34
- mode: 'group',
35
- enter: 'g-enter',
36
- enterFrom: 'g-enter-from',
37
- enterTo: 'g-enter-to',
38
- leave: 'g-leave',
39
- leaveFrom: 'g-leave-from',
40
- leaveTo: 'g-leave-to',
41
- ...overrides,
42
- })
43
-
44
- /** Unwrap reactive accessors returned by GroupRenderer. */
45
- const unwrap = (val: any): any => {
46
- let result = val
47
- while (typeof result === 'function') result = result()
48
- return result
49
- }
50
-
51
- // Real h() instead of a hand-built `{ type, props, children, key }`
52
- // literal — same VNode shape as production, so any test running the
53
- // returned node through the runtime sees real h()-normalised output.
54
- const makeKeyedChild = (key: string | number, text: string): VNode => {
55
- const vnode = h('span', { 'data-testid': `child-${key}` }, text) as VNode
56
- return { ...vnode, key }
57
- }
58
-
59
- describe('GroupRenderer', () => {
60
- it('returns a VNode wrapping children in config.tag', () => {
61
- const config = makeConfig()
62
- const children = [makeKeyedChild('a', 'Alpha'), makeKeyedChild('b', 'Beta')]
63
-
64
- const vnode = unwrap(
65
- GroupRenderer({
66
- config,
67
- htmlProps: {},
68
- callbacks: {},
69
- children,
70
- }),
71
- )
72
-
73
- expect(vnode).not.toBeNull()
74
- expect(vnode?.type).toBe('div')
75
- })
76
-
77
- it('uses custom tag from config', () => {
78
- const config = makeConfig({ tag: 'ul' })
79
- const children = [makeKeyedChild('a', 'Alpha')]
80
-
81
- const vnode = unwrap(
82
- GroupRenderer({
83
- config,
84
- htmlProps: {},
85
- callbacks: {},
86
- children,
87
- }),
88
- )
89
-
90
- expect(vnode?.type).toBe('ul')
91
- })
92
-
93
- it('passes htmlProps to the wrapper element', () => {
94
- const config = makeConfig()
95
- const children = [makeKeyedChild('a', 'Alpha')]
96
-
97
- const vnode = unwrap(
98
- GroupRenderer({
99
- config,
100
- htmlProps: { 'data-testid': 'group-wrapper', class: 'my-group' },
101
- callbacks: {},
102
- children,
103
- }),
104
- )
105
-
106
- const props = vnode?.props as Record<string, unknown>
107
- expect(props?.['data-testid']).toBe('group-wrapper')
108
- expect(props?.class).toBe('my-group')
109
- })
110
-
111
- it('wraps each keyed child in a TransitionItem', () => {
112
- const config = makeConfig()
113
- const children = [makeKeyedChild('a', 'Alpha'), makeKeyedChild('b', 'Beta')]
114
-
115
- const vnode = unwrap(
116
- GroupRenderer({
117
- config,
118
- htmlProps: {},
119
- callbacks: {},
120
- children,
121
- }),
122
- )
123
-
124
- // The wrapper div should have children that are TransitionItem VNodes
125
- const wrapperChildren = vnode?.children
126
- expect(wrapperChildren).toBeDefined()
127
- const childArray = Array.isArray(wrapperChildren) ? wrapperChildren : [wrapperChildren]
128
- expect(childArray.length).toBe(2)
129
-
130
- // Each child should be a TransitionItem (function component)
131
- for (const child of childArray) {
132
- const childVNode = child as VNode
133
- expect(typeof childVNode.type).toBe('function')
134
- }
135
- })
136
-
137
- it('sets appear=true for newly added children (non-initial)', () => {
138
- const config = makeConfig()
139
-
140
- // First render with initial children
141
- const initialChildren = [makeKeyedChild('a', 'Alpha')]
142
- unwrap(
143
- GroupRenderer({
144
- config,
145
- htmlProps: {},
146
- callbacks: {},
147
- children: initialChildren,
148
- }),
149
- )
150
-
151
- // Second render with a new child added
152
- const updatedChildren = [makeKeyedChild('a', 'Alpha'), makeKeyedChild('b', 'Beta')]
153
- const vnode = unwrap(
154
- GroupRenderer({
155
- config,
156
- htmlProps: {},
157
- callbacks: {},
158
- children: updatedChildren,
159
- }),
160
- )
161
-
162
- const wrapperChildren = vnode?.children as VNode[]
163
- expect(wrapperChildren.length).toBe(2)
164
- })
165
-
166
- it('passes transition class config to TransitionItem children', () => {
167
- const config = makeConfig({
168
- enter: 'custom-enter',
169
- enterFrom: 'custom-from',
170
- enterTo: 'custom-to',
171
- leave: 'custom-leave',
172
- leaveFrom: 'custom-lfrom',
173
- leaveTo: 'custom-lto',
174
- })
175
- const children = [makeKeyedChild('a', 'Alpha')]
176
-
177
- const vnode = unwrap(
178
- GroupRenderer({
179
- config,
180
- htmlProps: {},
181
- callbacks: {},
182
- children,
183
- }),
184
- )
185
-
186
- const wrapperChildren = vnode?.children as VNode[]
187
- const transitionItemVNode = wrapperChildren[0] as VNode
188
- const tiProps = transitionItemVNode.props as Record<string, unknown>
189
-
190
- expect(tiProps.enter).toBe('custom-enter')
191
- expect(tiProps.enterFrom).toBe('custom-from')
192
- expect(tiProps.enterTo).toBe('custom-to')
193
- expect(tiProps.leave).toBe('custom-leave')
194
- expect(tiProps.leaveFrom).toBe('custom-lfrom')
195
- expect(tiProps.leaveTo).toBe('custom-lto')
196
- })
197
-
198
- it('passes style transition config to TransitionItem children', () => {
199
- const config = makeConfig({
200
- enterStyle: { opacity: 0 },
201
- enterToStyle: { opacity: 1 },
202
- enterTransition: 'opacity 300ms ease',
203
- leaveStyle: { opacity: 1 },
204
- leaveToStyle: { opacity: 0 },
205
- leaveTransition: 'opacity 200ms ease-in',
206
- })
207
- const children = [makeKeyedChild('a', 'Alpha')]
208
-
209
- const vnode = unwrap(
210
- GroupRenderer({
211
- config,
212
- htmlProps: {},
213
- callbacks: {},
214
- children,
215
- }),
216
- )
217
-
218
- const wrapperChildren = vnode?.children as VNode[]
219
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
220
-
221
- expect(tiProps.enterStyle).toEqual({ opacity: 0 })
222
- expect(tiProps.enterToStyle).toEqual({ opacity: 1 })
223
- expect(tiProps.enterTransition).toBe('opacity 300ms ease')
224
- expect(tiProps.leaveStyle).toEqual({ opacity: 1 })
225
- expect(tiProps.leaveToStyle).toEqual({ opacity: 0 })
226
- expect(tiProps.leaveTransition).toBe('opacity 200ms ease-in')
227
- })
228
-
229
- it('uses effectiveAppear from config when appear prop is not provided', () => {
230
- const config = makeConfig({ appear: true })
231
- const children = [makeKeyedChild('a', 'Alpha')]
232
-
233
- const vnode = unwrap(
234
- GroupRenderer({
235
- config,
236
- htmlProps: {},
237
- callbacks: {},
238
- children,
239
- }),
240
- )
241
-
242
- const wrapperChildren = vnode?.children as VNode[]
243
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
244
-
245
- // Initial children should use effectiveAppear (true)
246
- expect(tiProps.appear).toBe(true)
247
- })
248
-
249
- it('uses effectiveTimeout from config when timeout prop is not provided', () => {
250
- const config = makeConfig({ timeout: 2000 })
251
- const children = [makeKeyedChild('a', 'Alpha')]
252
-
253
- const vnode = unwrap(
254
- GroupRenderer({
255
- config,
256
- htmlProps: {},
257
- callbacks: {},
258
- children,
259
- }),
260
- )
261
-
262
- const wrapperChildren = vnode?.children as VNode[]
263
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
264
-
265
- expect(tiProps.timeout).toBe(2000)
266
- })
267
-
268
- it('defaults timeout to 5000 when not provided', () => {
269
- const config = makeConfig()
270
- const children = [makeKeyedChild('a', 'Alpha')]
271
-
272
- const vnode = unwrap(
273
- GroupRenderer({
274
- config,
275
- htmlProps: {},
276
- callbacks: {},
277
- children,
278
- }),
279
- )
280
-
281
- const wrapperChildren = vnode?.children as VNode[]
282
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
283
-
284
- expect(tiProps.timeout).toBe(5000)
285
- })
286
-
287
- it('ignores children without keys', () => {
288
- const config = makeConfig()
289
- const keyedChild = makeKeyedChild('a', 'Alpha')
290
- // Real h() output instead of a mock literal — same shape, real path.
291
- const unkeyedChild: VNode = h('span', null, 'No key') as VNode
292
-
293
- const vnode = unwrap(
294
- GroupRenderer({
295
- config,
296
- htmlProps: {},
297
- callbacks: {},
298
- children: [keyedChild, unkeyedChild],
299
- }),
300
- )
301
-
302
- // Only keyed child should be wrapped in TransitionItem
303
- const wrapperChildren = vnode?.children as VNode[]
304
- expect(wrapperChildren.length).toBe(1)
305
- })
306
-
307
- it('appear prop overrides config.appear', () => {
308
- const config = makeConfig({ appear: false })
309
- const children = [makeKeyedChild('a', 'Alpha')]
310
-
311
- const vnode = unwrap(
312
- GroupRenderer({
313
- config,
314
- htmlProps: {},
315
- appear: true,
316
- callbacks: {},
317
- children,
318
- }),
319
- )
320
-
321
- const wrapperChildren = vnode?.children as VNode[]
322
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
323
-
324
- expect(tiProps.appear).toBe(true)
325
- })
326
-
327
- it('timeout prop overrides config.timeout', () => {
328
- const config = makeConfig({ timeout: 2000 })
329
- const children = [makeKeyedChild('a', 'Alpha')]
330
-
331
- const vnode = unwrap(
332
- GroupRenderer({
333
- config,
334
- htmlProps: {},
335
- timeout: 3000,
336
- callbacks: {},
337
- children,
338
- }),
339
- )
340
-
341
- const wrapperChildren = vnode?.children as VNode[]
342
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
343
-
344
- expect(tiProps.timeout).toBe(3000)
345
- })
346
-
347
- it('handleAfterLeave fires the callbacks.onAfterLeave and updates forceUpdateSignal', () => {
348
- const onAfterLeave = vi.fn()
349
- const config = makeConfig()
350
- const children = [makeKeyedChild('a', 'Alpha')]
351
-
352
- const vnode = unwrap(
353
- GroupRenderer({
354
- config,
355
- htmlProps: {},
356
- callbacks: { onAfterLeave },
357
- children,
358
- }),
359
- )
360
-
361
- // Each TransitionItem child gets an onAfterLeave that calls handleAfterLeave(key)
362
- const wrapperChildren = vnode?.children as VNode[]
363
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
364
- const tiAfterLeave = tiProps.onAfterLeave as () => void
365
-
366
- expect(tiAfterLeave).toBeDefined()
367
- tiAfterLeave()
368
-
369
- expect(onAfterLeave).toHaveBeenCalledTimes(1)
370
- })
371
-
372
- it('TransitionItem children have show returning true for current children', () => {
373
- const config = makeConfig()
374
- const children = [makeKeyedChild('a', 'Alpha'), makeKeyedChild('b', 'Beta')]
375
-
376
- const vnode = unwrap(
377
- GroupRenderer({
378
- config,
379
- htmlProps: {},
380
- callbacks: {},
381
- children,
382
- }),
383
- )
384
-
385
- const wrapperChildren = vnode?.children as VNode[]
386
-
387
- for (const child of wrapperChildren) {
388
- const tiProps = (child as VNode).props as Record<string, unknown>
389
- const showFn = tiProps.show as () => boolean
390
- expect(showFn()).toBe(true)
391
- }
392
- })
393
-
394
- it('initial children use effectiveAppear for appear prop', () => {
395
- const config = makeConfig({ appear: false })
396
- const children = [makeKeyedChild('a', 'Alpha')]
397
-
398
- const vnode = unwrap(
399
- GroupRenderer({
400
- config,
401
- htmlProps: {},
402
- callbacks: {},
403
- children,
404
- }),
405
- )
406
-
407
- const wrapperChildren = vnode?.children as VNode[]
408
- const tiProps = wrapperChildren[0]?.props as Record<string, unknown>
409
-
410
- // Initial keys use effectiveAppear (false in this case)
411
- expect(tiProps.appear).toBe(false)
412
- })
413
-
414
- it('each TransitionItem child gets the element as its children', () => {
415
- const config = makeConfig()
416
- const children = [makeKeyedChild('a', 'Alpha')]
417
-
418
- const vnode = unwrap(
419
- GroupRenderer({
420
- config,
421
- htmlProps: {},
422
- callbacks: {},
423
- children,
424
- }),
425
- )
426
-
427
- const wrapperChildren = vnode?.children as VNode[]
428
- const tiVNode = wrapperChildren[0] as VNode
429
-
430
- // The TransitionItem should have the original element as children
431
- const tiChildren = (tiVNode.props as Record<string, unknown>)?.children ?? tiVNode.children
432
- expect(tiChildren).toBeDefined()
433
- })
434
- })