@pyreon/kinetic 0.24.4 → 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.
- package/package.json +10 -12
- package/src/Collapse.tsx +0 -166
- package/src/Stagger.tsx +0 -63
- package/src/Transition.tsx +0 -280
- package/src/TransitionGroup.tsx +0 -139
- package/src/__tests__/Collapse.test.tsx +0 -803
- package/src/__tests__/GroupRenderer.test.tsx +0 -434
- package/src/__tests__/StaggerRenderer.test.tsx +0 -523
- package/src/__tests__/Transition.ssr.test.tsx +0 -183
- package/src/__tests__/Transition.test.tsx +0 -403
- package/src/__tests__/TransitionItem.test.tsx +0 -514
- package/src/__tests__/kinetic-modes.ssr.test.tsx +0 -214
- package/src/__tests__/kinetic.browser.test.tsx +0 -327
- package/src/__tests__/kinetic.test.tsx +0 -565
- package/src/__tests__/presets.test.ts +0 -46
- package/src/__tests__/stagger-component-children-hydration.test.tsx +0 -191
- package/src/__tests__/top-level-transition-stagger-function-children.test.tsx +0 -141
- package/src/__tests__/useAnimationEnd.test.ts +0 -194
- package/src/__tests__/useReducedMotion.test.ts +0 -160
- package/src/__tests__/useTransitionState.test.ts +0 -132
- package/src/__tests__/utils.test.ts +0 -139
- package/src/index.ts +0 -15
- package/src/jsx-augment.d.ts +0 -12
- package/src/kinetic/CollapseRenderer.tsx +0 -216
- package/src/kinetic/GroupRenderer.tsx +0 -149
- package/src/kinetic/StaggerRenderer.tsx +0 -94
- package/src/kinetic/TransitionItem.tsx +0 -250
- package/src/kinetic/TransitionRenderer.tsx +0 -230
- package/src/kinetic/createKineticComponent.tsx +0 -224
- package/src/kinetic/types.ts +0 -149
- package/src/kinetic.ts +0 -25
- package/src/presets.ts +0 -66
- package/src/types.ts +0 -118
- package/src/useAnimationEnd.ts +0 -59
- package/src/useReducedMotion.ts +0 -28
- package/src/useTransitionState.ts +0 -62
- 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
|
-
})
|