@pyreon/kinetic 0.11.4 → 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.
- package/README.md +27 -24
- package/lib/index.d.ts +8 -8
- package/lib/index.js +46 -37
- package/package.json +22 -22
- package/src/Collapse.tsx +44 -44
- package/src/Stagger.tsx +7 -7
- package/src/Transition.tsx +21 -24
- package/src/TransitionGroup.tsx +85 -59
- package/src/__tests__/Collapse.test.tsx +125 -125
- package/src/__tests__/GroupRenderer.test.tsx +233 -190
- package/src/__tests__/StaggerRenderer.test.tsx +99 -99
- package/src/__tests__/Transition.test.tsx +89 -89
- package/src/__tests__/TransitionItem.test.tsx +120 -120
- package/src/__tests__/kinetic.test.tsx +135 -135
- package/src/__tests__/presets.test.ts +15 -15
- package/src/__tests__/useAnimationEnd.test.ts +33 -33
- package/src/__tests__/useReducedMotion.test.ts +22 -22
- package/src/__tests__/useTransitionState.test.ts +38 -38
- package/src/__tests__/utils.test.ts +63 -63
- package/src/index.ts +9 -17
- package/src/kinetic/CollapseRenderer.tsx +42 -42
- package/src/kinetic/GroupRenderer.tsx +88 -65
- package/src/kinetic/StaggerRenderer.tsx +9 -9
- package/src/kinetic/TransitionItem.tsx +18 -18
- package/src/kinetic/TransitionRenderer.tsx +19 -19
- package/src/kinetic/createKineticComponent.tsx +27 -27
- package/src/kinetic/types.ts +13 -13
- package/src/kinetic.ts +4 -4
- package/src/presets.ts +33 -33
- package/src/types.ts +3 -3
- package/src/useAnimationEnd.ts +8 -8
- package/src/useReducedMotion.ts +5 -5
- package/src/useTransitionState.ts +12 -12
- package/src/utils.ts +4 -4
package/src/TransitionGroup.tsx
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
|
-
import type { VNode } from
|
|
2
|
-
import { signal } from
|
|
3
|
-
import Transition from
|
|
4
|
-
import type { ClassTransitionProps, StyleTransitionProps, TransitionCallbacks } from
|
|
1
|
+
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { signal } from '@pyreon/reactivity'
|
|
3
|
+
import Transition from './Transition'
|
|
4
|
+
import type { ClassTransitionProps, StyleTransitionProps, TransitionCallbacks } from './types'
|
|
5
5
|
|
|
6
6
|
export type TransitionGroupProps = ClassTransitionProps &
|
|
7
7
|
StyleTransitionProps &
|
|
8
8
|
TransitionCallbacks & {
|
|
9
9
|
appear?: boolean | undefined
|
|
10
10
|
timeout?: number | undefined
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Children can be a static array OR a reactive accessor `() => VNode[]`.
|
|
13
|
+
* When passed as an accessor, TransitionGroup tracks changes and
|
|
14
|
+
* animates entering/leaving children automatically.
|
|
15
|
+
*/
|
|
16
|
+
children: VNode[] | (() => VNode[])
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
type KeyedChild = { key: string | number; element: VNode }
|
|
15
20
|
|
|
16
21
|
const isVNode = (child: unknown): child is VNode =>
|
|
17
|
-
child != null && typeof child ===
|
|
22
|
+
child != null && typeof child === 'object' && 'type' in (child as object)
|
|
18
23
|
|
|
19
24
|
const getKeyedChildren = (children: VNode[]): KeyedChild[] => {
|
|
20
25
|
const result: KeyedChild[] = []
|
|
@@ -29,6 +34,14 @@ const getKeyedChildren = (children: VNode[]): KeyedChild[] => {
|
|
|
29
34
|
return result
|
|
30
35
|
}
|
|
31
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Renders children with key-based enter/exit animations.
|
|
39
|
+
*
|
|
40
|
+
* In Pyreon, components run once. For TransitionGroup to detect children
|
|
41
|
+
* changes, pass children as a reactive accessor: `() => VNode[]`.
|
|
42
|
+
* The component uses a reactive accessor internally to diff previous vs
|
|
43
|
+
* current children and animate entries/exits.
|
|
44
|
+
*/
|
|
32
45
|
const TransitionGroup = ({
|
|
33
46
|
children,
|
|
34
47
|
appear = false,
|
|
@@ -38,71 +51,84 @@ const TransitionGroup = ({
|
|
|
38
51
|
}: TransitionGroupProps): VNode | null => {
|
|
39
52
|
const prevMap = new Map<string | number, VNode>()
|
|
40
53
|
const leavingMap = new Map<string | number, VNode>()
|
|
41
|
-
const
|
|
54
|
+
const forceUpdate = signal(0)
|
|
42
55
|
|
|
43
|
-
//
|
|
44
|
-
const
|
|
45
|
-
const currentMap = new Map<string | number, VNode>()
|
|
46
|
-
for (const { key, element } of currentKeyed) {
|
|
47
|
-
currentMap.set(key, element)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Track initial keys to know which children were present on first render
|
|
51
|
-
const initialKeys: Set<string | number> = new Set(currentMap.keys())
|
|
52
|
-
|
|
53
|
-
// Detect leaving children (were in prev but not in current)
|
|
54
|
-
for (const [key, child] of prevMap) {
|
|
55
|
-
if (!currentMap.has(key)) {
|
|
56
|
-
leavingMap.set(key, child)
|
|
57
|
-
}
|
|
58
|
-
}
|
|
56
|
+
// Normalize children to an accessor for uniform handling
|
|
57
|
+
const getChildren = typeof children === 'function' ? (children as () => VNode[]) : () => children
|
|
59
58
|
|
|
60
|
-
//
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Update prev
|
|
66
|
-
prevMap.clear()
|
|
67
|
-
for (const [key, element] of currentMap) {
|
|
59
|
+
// Track initial keys for appear animation logic
|
|
60
|
+
const initialKeyed = getKeyedChildren(getChildren())
|
|
61
|
+
const initialKeys = new Set(initialKeyed.map((c) => c.key))
|
|
62
|
+
for (const { key, element } of initialKeyed) {
|
|
68
63
|
prevMap.set(key, element)
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
const handleAfterLeave = (key: string | number) => {
|
|
72
67
|
leavingMap.delete(key)
|
|
73
68
|
onAfterLeave?.()
|
|
74
|
-
|
|
69
|
+
forceUpdate.update((c) => c + 1)
|
|
75
70
|
}
|
|
76
71
|
|
|
77
|
-
//
|
|
78
|
-
|
|
72
|
+
// Reactive accessor — re-evaluates when children() or forceUpdate changes.
|
|
73
|
+
// The runtime mounts this via mountReactive + effect, creating a
|
|
74
|
+
// reactive scope that tracks signal reads.
|
|
75
|
+
return (() => {
|
|
76
|
+
// Read forceUpdate to re-evaluate when leaving children finish
|
|
77
|
+
forceUpdate()
|
|
78
|
+
|
|
79
|
+
const currentChildren = getChildren()
|
|
80
|
+
const currentKeyed = getKeyedChildren(currentChildren)
|
|
81
|
+
const currentMap = new Map<string | number, VNode>()
|
|
82
|
+
for (const { key, element } of currentKeyed) {
|
|
83
|
+
currentMap.set(key, element)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Detect leaving children (were in prev but not in current)
|
|
87
|
+
for (const [key, child] of prevMap) {
|
|
88
|
+
if (!currentMap.has(key) && !leavingMap.has(key)) {
|
|
89
|
+
leavingMap.set(key, child)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
79
92
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
// If a leaving child reappears, cancel the leave
|
|
94
|
+
for (const key of currentMap.keys()) {
|
|
95
|
+
leavingMap.delete(key)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Update prev for next diff
|
|
99
|
+
prevMap.clear()
|
|
100
|
+
for (const [key, element] of currentMap) {
|
|
101
|
+
prevMap.set(key, element)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Merge current + leaving, preserving insertion order
|
|
105
|
+
const allEntries: KeyedChild[] = [...currentKeyed]
|
|
106
|
+
for (const [key, element] of leavingMap) {
|
|
107
|
+
allEntries.push({ key, element })
|
|
108
|
+
}
|
|
83
109
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
110
|
+
return (
|
|
111
|
+
<>
|
|
112
|
+
{allEntries.map(({ key, element }) => {
|
|
113
|
+
const isInitial = initialKeys.has(key)
|
|
114
|
+
const isShowing = currentMap.has(key)
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<Transition
|
|
118
|
+
key={key}
|
|
119
|
+
show={() => isShowing}
|
|
120
|
+
appear={isInitial ? appear : true}
|
|
121
|
+
timeout={timeout}
|
|
122
|
+
{...transitionProps}
|
|
123
|
+
onAfterLeave={() => handleAfterLeave(key)}
|
|
124
|
+
>
|
|
125
|
+
{element}
|
|
126
|
+
</Transition>
|
|
127
|
+
)
|
|
128
|
+
})}
|
|
129
|
+
</>
|
|
130
|
+
)
|
|
131
|
+
}) as unknown as VNode
|
|
106
132
|
}
|
|
107
133
|
|
|
108
134
|
export default TransitionGroup
|