@pyreon/kinetic 0.13.1 → 0.15.0
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/lib/index.js +1 -49
- package/package.json +11 -10
- package/src/__tests__/Collapse.test.tsx +22 -21
- package/src/__tests__/GroupRenderer.test.tsx +10 -7
- package/src/__tests__/StaggerRenderer.test.tsx +9 -12
- package/src/__tests__/Transition.test.tsx +6 -8
- package/src/__tests__/TransitionItem.test.tsx +9 -17
- package/src/__tests__/kinetic.browser.test.tsx +6 -3
- package/src/__tests__/kinetic.test.tsx +6 -1
- package/src/__tests__/useReducedMotion.test.ts +4 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Show, createRef, h, onMount, onUnmount } from "@pyreon/core";
|
|
2
2
|
import { runUntracked, signal, watch } from "@pyreon/reactivity";
|
|
3
|
+
import { jsx } from "@pyreon/core/jsx-runtime";
|
|
3
4
|
|
|
4
5
|
//#region src/useAnimationEnd.ts
|
|
5
6
|
const DEFAULT_TIMEOUT = 5e3;
|
|
@@ -59,55 +60,6 @@ function useReducedMotion() {
|
|
|
59
60
|
return matches;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region ../../core/core/lib/jsx-runtime.js
|
|
64
|
-
/**
|
|
65
|
-
* Hyperscript function — the compiled output of JSX.
|
|
66
|
-
* `<div class="x">hello</div>` → `h("div", { class: "x" }, "hello")`
|
|
67
|
-
*
|
|
68
|
-
* Generic on P so TypeScript validates props match the component's signature
|
|
69
|
-
* at the call site, then stores the result in the loosely-typed VNode.
|
|
70
|
-
*/
|
|
71
|
-
/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */
|
|
72
|
-
const EMPTY_PROPS = {};
|
|
73
|
-
function h$1(type, props, ...children) {
|
|
74
|
-
return {
|
|
75
|
-
type,
|
|
76
|
-
props: props ?? EMPTY_PROPS,
|
|
77
|
-
children: normalizeChildren(children),
|
|
78
|
-
key: props?.key ?? null
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
function normalizeChildren(children) {
|
|
82
|
-
for (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);
|
|
83
|
-
return children;
|
|
84
|
-
}
|
|
85
|
-
function flattenChildren(children) {
|
|
86
|
-
const result = [];
|
|
87
|
-
for (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));
|
|
88
|
-
else result.push(child);
|
|
89
|
-
return result;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* JSX automatic runtime.
|
|
93
|
-
*
|
|
94
|
-
* When tsconfig has `"jsxImportSource": "@pyreon/core"`, the TS/bundler compiler
|
|
95
|
-
* rewrites JSX to imports from this file automatically:
|
|
96
|
-
* <div class="x" /> → jsx("div", { class: "x" })
|
|
97
|
-
*/
|
|
98
|
-
function jsx(type, props, key) {
|
|
99
|
-
const { children, ...rest } = props;
|
|
100
|
-
const propsWithKey = key != null ? {
|
|
101
|
-
...rest,
|
|
102
|
-
key
|
|
103
|
-
} : rest;
|
|
104
|
-
if (typeof type === "function") return h$1(type, children !== void 0 ? {
|
|
105
|
-
...propsWithKey,
|
|
106
|
-
children
|
|
107
|
-
} : propsWithKey);
|
|
108
|
-
return h$1(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
63
|
//#endregion
|
|
112
64
|
//#region src/kinetic/CollapseRenderer.tsx
|
|
113
65
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/kinetic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "CSS-transition-based animation components for Pyreon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"lib",
|
|
13
|
+
"!lib/**/*.map",
|
|
13
14
|
"!lib/analysis",
|
|
14
15
|
"README.md",
|
|
15
16
|
"LICENSE",
|
|
@@ -41,18 +42,18 @@
|
|
|
41
42
|
"typecheck": "tsc --noEmit"
|
|
42
43
|
},
|
|
43
44
|
"devDependencies": {
|
|
44
|
-
"@pyreon/core": "^0.
|
|
45
|
-
"@pyreon/reactivity": "^0.
|
|
46
|
-
"@pyreon/runtime-dom": "^0.
|
|
47
|
-
"@pyreon/test-utils": "^0.13.
|
|
48
|
-
"@pyreon/typescript": "^0.
|
|
45
|
+
"@pyreon/core": "^0.15.0",
|
|
46
|
+
"@pyreon/reactivity": "^0.15.0",
|
|
47
|
+
"@pyreon/runtime-dom": "^0.15.0",
|
|
48
|
+
"@pyreon/test-utils": "^0.13.2",
|
|
49
|
+
"@pyreon/typescript": "^0.15.0",
|
|
49
50
|
"@vitest/browser-playwright": "^4.1.4",
|
|
50
|
-
"@vitus-labs/tools-rolldown": "^
|
|
51
|
+
"@vitus-labs/tools-rolldown": "^2.3.0"
|
|
51
52
|
},
|
|
52
53
|
"peerDependencies": {
|
|
53
|
-
"@pyreon/core": "^0.
|
|
54
|
-
"@pyreon/reactivity": "^0.
|
|
55
|
-
"@pyreon/runtime-dom": "^0.
|
|
54
|
+
"@pyreon/core": "^0.15.0",
|
|
55
|
+
"@pyreon/reactivity": "^0.15.0",
|
|
56
|
+
"@pyreon/runtime-dom": "^0.15.0"
|
|
56
57
|
},
|
|
57
58
|
"engines": {
|
|
58
59
|
"node": ">= 22"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import { signal } from '@pyreon/reactivity'
|
|
3
4
|
import Collapse from '../Collapse'
|
|
4
5
|
import CollapseRenderer from '../kinetic/CollapseRenderer'
|
|
@@ -95,7 +96,7 @@ describe('Collapse', () => {
|
|
|
95
96
|
|
|
96
97
|
it('returns a VNode', () => {
|
|
97
98
|
const show = signal(true)
|
|
98
|
-
const child =
|
|
99
|
+
const child = h('div', null, 'Hello') as VNode
|
|
99
100
|
const vnode = Collapse({ show, children: child } as any)
|
|
100
101
|
expect(vnode).not.toBeNull()
|
|
101
102
|
})
|
|
@@ -107,7 +108,7 @@ describe('Collapse', () => {
|
|
|
107
108
|
setupCollapse({
|
|
108
109
|
show,
|
|
109
110
|
onEnter,
|
|
110
|
-
children:
|
|
111
|
+
children: h('div', null, 'Hello') as VNode,
|
|
111
112
|
})
|
|
112
113
|
|
|
113
114
|
show.set(true)
|
|
@@ -121,7 +122,7 @@ describe('Collapse', () => {
|
|
|
121
122
|
const { wrapperEl } = setupCollapse({
|
|
122
123
|
show,
|
|
123
124
|
onAfterEnter,
|
|
124
|
-
children:
|
|
125
|
+
children: h('div', null, 'Hello') as VNode,
|
|
125
126
|
})
|
|
126
127
|
|
|
127
128
|
show.set(true)
|
|
@@ -138,7 +139,7 @@ describe('Collapse', () => {
|
|
|
138
139
|
setupCollapse({
|
|
139
140
|
show,
|
|
140
141
|
onLeave,
|
|
141
|
-
children:
|
|
142
|
+
children: h('div', null, 'Hello') as VNode,
|
|
142
143
|
})
|
|
143
144
|
|
|
144
145
|
show.set(false)
|
|
@@ -152,7 +153,7 @@ describe('Collapse', () => {
|
|
|
152
153
|
const { wrapperEl } = setupCollapse({
|
|
153
154
|
show,
|
|
154
155
|
onAfterLeave,
|
|
155
|
-
children:
|
|
156
|
+
children: h('div', null, 'Hello') as VNode,
|
|
156
157
|
})
|
|
157
158
|
|
|
158
159
|
show.set(false)
|
|
@@ -167,7 +168,7 @@ describe('Collapse', () => {
|
|
|
167
168
|
|
|
168
169
|
const { wrapperEl } = setupCollapse({
|
|
169
170
|
show,
|
|
170
|
-
children:
|
|
171
|
+
children: h('div', null, 'Hello') as VNode,
|
|
171
172
|
})
|
|
172
173
|
|
|
173
174
|
show.set(true)
|
|
@@ -181,7 +182,7 @@ describe('Collapse', () => {
|
|
|
181
182
|
|
|
182
183
|
const { wrapperEl } = setupCollapse({
|
|
183
184
|
show,
|
|
184
|
-
children:
|
|
185
|
+
children: h('div', null, 'Hello') as VNode,
|
|
185
186
|
})
|
|
186
187
|
|
|
187
188
|
show.set(true)
|
|
@@ -197,7 +198,7 @@ describe('Collapse', () => {
|
|
|
197
198
|
|
|
198
199
|
const { wrapperEl } = setupCollapse({
|
|
199
200
|
show,
|
|
200
|
-
children:
|
|
201
|
+
children: h('div', null, 'Hello') as VNode,
|
|
201
202
|
})
|
|
202
203
|
|
|
203
204
|
show.set(false)
|
|
@@ -212,7 +213,7 @@ describe('Collapse', () => {
|
|
|
212
213
|
const { wrapperEl } = setupCollapse({
|
|
213
214
|
show,
|
|
214
215
|
transition: 'height 500ms ease-in-out',
|
|
215
|
-
children:
|
|
216
|
+
children: h('div', null, 'Hello') as VNode,
|
|
216
217
|
})
|
|
217
218
|
|
|
218
219
|
show.set(true)
|
|
@@ -228,7 +229,7 @@ describe('Collapse', () => {
|
|
|
228
229
|
show,
|
|
229
230
|
appear: true,
|
|
230
231
|
onEnter,
|
|
231
|
-
children:
|
|
232
|
+
children: h('div', null, 'Hello') as VNode,
|
|
232
233
|
})
|
|
233
234
|
|
|
234
235
|
// appear defers via queueMicrotask so all refs are wired first
|
|
@@ -246,7 +247,7 @@ describe('Collapse', () => {
|
|
|
246
247
|
show,
|
|
247
248
|
timeout: 800,
|
|
248
249
|
onAfterLeave,
|
|
249
|
-
children:
|
|
250
|
+
children: h('div', null, 'Hello') as VNode,
|
|
250
251
|
})
|
|
251
252
|
|
|
252
253
|
show.set(false)
|
|
@@ -266,7 +267,7 @@ describe('Collapse', () => {
|
|
|
266
267
|
show,
|
|
267
268
|
onEnter,
|
|
268
269
|
onLeave,
|
|
269
|
-
children:
|
|
270
|
+
children: h('div', null, 'Hello') as VNode,
|
|
270
271
|
})
|
|
271
272
|
|
|
272
273
|
// Start leaving
|
|
@@ -288,7 +289,7 @@ describe('Collapse', () => {
|
|
|
288
289
|
show,
|
|
289
290
|
onEnter,
|
|
290
291
|
onLeave,
|
|
291
|
-
children:
|
|
292
|
+
children: h('div', null, 'Hello') as VNode,
|
|
292
293
|
})
|
|
293
294
|
|
|
294
295
|
// Start entering
|
|
@@ -307,7 +308,7 @@ describe('Collapse', () => {
|
|
|
307
308
|
const { wrapperEl } = setupCollapse({
|
|
308
309
|
show,
|
|
309
310
|
onEnter,
|
|
310
|
-
children:
|
|
311
|
+
children: h('div', null, 'Hello') as VNode,
|
|
311
312
|
})
|
|
312
313
|
|
|
313
314
|
show.set(true)
|
|
@@ -329,7 +330,7 @@ describe('Collapse', () => {
|
|
|
329
330
|
const { wrapperEl } = setupCollapse({
|
|
330
331
|
show,
|
|
331
332
|
onLeave,
|
|
332
|
-
children:
|
|
333
|
+
children: h('div', null, 'Hello') as VNode,
|
|
333
334
|
})
|
|
334
335
|
|
|
335
336
|
show.set(false)
|
|
@@ -350,7 +351,7 @@ describe('Collapse', () => {
|
|
|
350
351
|
show,
|
|
351
352
|
appear: true,
|
|
352
353
|
onAfterEnter,
|
|
353
|
-
children:
|
|
354
|
+
children: h('div', null, 'Hello') as VNode,
|
|
354
355
|
})
|
|
355
356
|
|
|
356
357
|
await Promise.resolve()
|
|
@@ -365,7 +366,7 @@ describe('Collapse', () => {
|
|
|
365
366
|
|
|
366
367
|
const { wrapperEl } = setupCollapse({
|
|
367
368
|
show,
|
|
368
|
-
children:
|
|
369
|
+
children: h('div', null, 'Hello') as VNode,
|
|
369
370
|
})
|
|
370
371
|
|
|
371
372
|
show.set(false)
|
|
@@ -443,7 +444,7 @@ const setupCollapseRenderer = (props: {
|
|
|
443
444
|
})
|
|
444
445
|
|
|
445
446
|
const config = props.config ?? makeCollapseConfig()
|
|
446
|
-
const child
|
|
447
|
+
const child = h('p', null, 'Content') as VNode
|
|
447
448
|
|
|
448
449
|
const vnode = CollapseRenderer({
|
|
449
450
|
config,
|
|
@@ -473,7 +474,7 @@ describe('CollapseRenderer', () => {
|
|
|
473
474
|
it('returns a VNode with the config.tag', () => {
|
|
474
475
|
const show = signal(true)
|
|
475
476
|
const config = makeCollapseConfig({ tag: 'section' })
|
|
476
|
-
const child
|
|
477
|
+
const child = h('p', null, 'Content') as VNode
|
|
477
478
|
|
|
478
479
|
const vnode = CollapseRenderer({
|
|
479
480
|
config,
|
|
@@ -748,7 +749,7 @@ describe('Collapse — reduced motion', () => {
|
|
|
748
749
|
show,
|
|
749
750
|
onEnter,
|
|
750
751
|
onAfterEnter,
|
|
751
|
-
children:
|
|
752
|
+
children: h('div', null, 'Hello') as VNode,
|
|
752
753
|
})
|
|
753
754
|
|
|
754
755
|
show.set(true)
|
|
@@ -768,7 +769,7 @@ describe('Collapse — reduced motion', () => {
|
|
|
768
769
|
show,
|
|
769
770
|
onLeave,
|
|
770
771
|
onAfterLeave,
|
|
771
|
-
children:
|
|
772
|
+
children: h('div', null, 'Hello') as VNode,
|
|
772
773
|
})
|
|
773
774
|
|
|
774
775
|
show.set(false)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import GroupRenderer from '../kinetic/GroupRenderer'
|
|
3
4
|
import type { KineticConfig } from '../kinetic/types'
|
|
4
5
|
|
|
@@ -47,12 +48,13 @@ const unwrap = (val: any): any => {
|
|
|
47
48
|
return result
|
|
48
49
|
}
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
key,
|
|
55
|
-
}
|
|
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
|
+
}
|
|
56
58
|
|
|
57
59
|
describe('GroupRenderer', () => {
|
|
58
60
|
it('returns a VNode wrapping children in config.tag', () => {
|
|
@@ -285,7 +287,8 @@ describe('GroupRenderer', () => {
|
|
|
285
287
|
it('ignores children without keys', () => {
|
|
286
288
|
const config = makeConfig()
|
|
287
289
|
const keyedChild = makeKeyedChild('a', 'Alpha')
|
|
288
|
-
|
|
290
|
+
// Real h() output instead of a mock literal — same shape, real path.
|
|
291
|
+
const unkeyedChild: VNode = h('span', null, 'No key') as VNode
|
|
289
292
|
|
|
290
293
|
const vnode = unwrap(
|
|
291
294
|
GroupRenderer({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import StaggerRenderer from '../kinetic/StaggerRenderer'
|
|
3
4
|
import type { KineticConfig } from '../kinetic/types'
|
|
4
5
|
|
|
@@ -40,12 +41,12 @@ const makeConfig = (overrides: Partial<KineticConfig> = {}): KineticConfig => ({
|
|
|
40
41
|
...overrides,
|
|
41
42
|
})
|
|
42
43
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
key
|
|
48
|
-
}
|
|
44
|
+
// Real h() instead of a hand-built `{ type, props, children, key }`
|
|
45
|
+
// literal — same VNode shape as production.
|
|
46
|
+
const makeChild = (key: string | number, text: string): VNode => {
|
|
47
|
+
const vnode = h('span', { 'data-testid': `child-${key}` }, text) as VNode
|
|
48
|
+
return { ...vnode, key }
|
|
49
|
+
}
|
|
49
50
|
|
|
50
51
|
/**
|
|
51
52
|
* Extract the cloned child VNode from a TransitionItem VNode.
|
|
@@ -476,12 +477,8 @@ describe('StaggerRenderer', () => {
|
|
|
476
477
|
|
|
477
478
|
it('preserves existing style on child when injecting stagger styles', () => {
|
|
478
479
|
const config = makeConfig()
|
|
479
|
-
const
|
|
480
|
-
|
|
481
|
-
props: { style: { color: 'red', fontWeight: 'bold' } },
|
|
482
|
-
children: ['Styled'],
|
|
483
|
-
key: 'styled',
|
|
484
|
-
}
|
|
480
|
+
const realVnode = h('span', { style: { color: 'red', fontWeight: 'bold' } }, 'Styled') as VNode
|
|
481
|
+
const childWithStyle: VNode = { ...realVnode, key: 'styled' }
|
|
485
482
|
|
|
486
483
|
const vnode = StaggerRenderer({
|
|
487
484
|
config,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import { signal } from '@pyreon/reactivity'
|
|
3
4
|
|
|
4
5
|
let _reducedMotion = false
|
|
@@ -88,12 +89,9 @@ const wireRef = (vnode: VNode | null, el: HTMLElement) => {
|
|
|
88
89
|
*/
|
|
89
90
|
const setupTransition = (props: Record<string, unknown>) => {
|
|
90
91
|
const el = document.createElement('div')
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
children: ['Hello'],
|
|
95
|
-
key: null,
|
|
96
|
-
}
|
|
92
|
+
// Real h() instead of a mock literal — same VNode shape as
|
|
93
|
+
// production, so the runtime sees real h()-normalised output.
|
|
94
|
+
const child = h('div', { 'data-testid': 'child' }, 'Hello') as VNode
|
|
97
95
|
|
|
98
96
|
const vnode = Transition({
|
|
99
97
|
...props,
|
|
@@ -108,14 +106,14 @@ const setupTransition = (props: Record<string, unknown>) => {
|
|
|
108
106
|
describe('Transition', () => {
|
|
109
107
|
it('returns a VNode when show=true', () => {
|
|
110
108
|
const show = signal(true)
|
|
111
|
-
const child
|
|
109
|
+
const child = h('div', null, 'Hello') as VNode
|
|
112
110
|
const vnode = Transition({ show, children: child })
|
|
113
111
|
expect(vnode).not.toBeNull()
|
|
114
112
|
})
|
|
115
113
|
|
|
116
114
|
it('returns a VNode with Show component', () => {
|
|
117
115
|
const show = signal(true)
|
|
118
|
-
const child
|
|
116
|
+
const child = h('div', null, 'Hello') as VNode
|
|
119
117
|
const vnode = Transition({ show, children: child })
|
|
120
118
|
expect(vnode).not.toBeNull()
|
|
121
119
|
// The outermost VNode should be a Show component
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import { signal } from '@pyreon/reactivity'
|
|
3
4
|
|
|
4
5
|
let _reducedMotion = false
|
|
@@ -88,12 +89,8 @@ const wireRef = (vnode: VNode | null, el: HTMLElement) => {
|
|
|
88
89
|
*/
|
|
89
90
|
const setupTransitionItem = (props: Record<string, unknown>) => {
|
|
90
91
|
const el = document.createElement('div')
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
props: { 'data-testid': 'child' },
|
|
94
|
-
children: ['Hello'],
|
|
95
|
-
key: null,
|
|
96
|
-
}
|
|
92
|
+
// Real h() instead of a mock literal — same VNode shape as production.
|
|
93
|
+
const child = h('div', { 'data-testid': 'child' }, 'Hello') as VNode
|
|
97
94
|
|
|
98
95
|
const vnode = TransitionItem({
|
|
99
96
|
...props,
|
|
@@ -108,14 +105,14 @@ const setupTransitionItem = (props: Record<string, unknown>) => {
|
|
|
108
105
|
describe('TransitionItem', () => {
|
|
109
106
|
it('returns a VNode when show returns true', () => {
|
|
110
107
|
const show = () => true
|
|
111
|
-
const child
|
|
108
|
+
const child = h('div', null, 'Hello') as VNode
|
|
112
109
|
const vnode = TransitionItem({ show, children: child })
|
|
113
110
|
expect(vnode).not.toBeNull()
|
|
114
111
|
})
|
|
115
112
|
|
|
116
113
|
it('wraps child in a Show component', () => {
|
|
117
114
|
const show = () => true
|
|
118
|
-
const child
|
|
115
|
+
const child = h('div', null, 'Hello') as VNode
|
|
119
116
|
const vnode = TransitionItem({ show, children: child })
|
|
120
117
|
expect(vnode).not.toBeNull()
|
|
121
118
|
expect(typeof vnode?.type).toBe('function')
|
|
@@ -123,7 +120,7 @@ describe('TransitionItem', () => {
|
|
|
123
120
|
|
|
124
121
|
it('clones child VNode with merged ref', () => {
|
|
125
122
|
const show = () => true
|
|
126
|
-
const child
|
|
123
|
+
const child = h('div', null, 'Hello') as VNode
|
|
127
124
|
const vnode = TransitionItem({ show, children: child })
|
|
128
125
|
|
|
129
126
|
// The Show component's children (or fallback) should have a ref prop
|
|
@@ -358,7 +355,7 @@ describe('TransitionItem', () => {
|
|
|
358
355
|
|
|
359
356
|
it('unmount=false keeps element with display:none when hidden', () => {
|
|
360
357
|
const show = () => false
|
|
361
|
-
const child
|
|
358
|
+
const child = h('div', null, 'Hello') as VNode
|
|
362
359
|
const vnode = TransitionItem({ show, unmount: false, children: child })
|
|
363
360
|
|
|
364
361
|
expect(vnode).not.toBeNull()
|
|
@@ -374,7 +371,7 @@ describe('TransitionItem', () => {
|
|
|
374
371
|
|
|
375
372
|
it('unmount=false fallback has a merged ref', () => {
|
|
376
373
|
const show = () => false
|
|
377
|
-
const child
|
|
374
|
+
const child = h('div', null, 'Hello') as VNode
|
|
378
375
|
const vnode = TransitionItem({ show, unmount: false, children: child })
|
|
379
376
|
|
|
380
377
|
const showProps = vnode?.props as Record<string, unknown>
|
|
@@ -388,12 +385,7 @@ describe('TransitionItem', () => {
|
|
|
388
385
|
|
|
389
386
|
it('unmount=false merges existing child style with display:none', () => {
|
|
390
387
|
const show = () => false
|
|
391
|
-
const child:
|
|
392
|
-
type: 'div',
|
|
393
|
-
props: { style: { color: 'red', opacity: 1 } },
|
|
394
|
-
children: ['Hello'],
|
|
395
|
-
key: null,
|
|
396
|
-
}
|
|
388
|
+
const child = h('div', { style: { color: 'red', opacity: 1 } }, 'Hello') as VNode
|
|
397
389
|
const vnode = TransitionItem({ show, unmount: false, children: child })
|
|
398
390
|
|
|
399
391
|
const showProps = vnode?.props as Record<string, unknown>
|
|
@@ -51,8 +51,11 @@ describe('@pyreon/kinetic browser smoke', () => {
|
|
|
51
51
|
expect(mergeClassNames(undefined, undefined)).toBe(undefined)
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
it('runs in a real browser —
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
it('runs in a real browser — Vitest defines `process.env.NODE_ENV !== "production"`', () => {
|
|
55
|
+
// Sanity check the test env: dev gates use bundler-agnostic
|
|
56
|
+
// `process.env.NODE_ENV !== 'production'`. Vitest's Vite pipeline
|
|
57
|
+
// replaces this at build time so the literal lands as
|
|
58
|
+
// `"development" !== "production"` → `true` in dev runs.
|
|
59
|
+
expect(process.env.NODE_ENV).not.toBe('production')
|
|
57
60
|
})
|
|
58
61
|
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { VNode, VNodeChild } from '@pyreon/core'
|
|
2
|
+
import { h } from '@pyreon/core'
|
|
2
3
|
import { signal } from '@pyreon/reactivity'
|
|
3
4
|
|
|
4
5
|
let _reducedMotion = false
|
|
@@ -353,7 +354,11 @@ describe('kinetic() — collapse mode', () => {
|
|
|
353
354
|
show,
|
|
354
355
|
onEnter,
|
|
355
356
|
onAfterEnter,
|
|
356
|
-
|
|
357
|
+
// Real h() instead of a mock literal — same VNode shape as
|
|
358
|
+
// production, so the test exercises whatever flattening /
|
|
359
|
+
// normalisation h() applies (instead of asserting the
|
|
360
|
+
// hand-built shape always matches).
|
|
361
|
+
children: h('p', null, 'Content'),
|
|
357
362
|
}),
|
|
358
363
|
)
|
|
359
364
|
|
|
@@ -36,7 +36,10 @@ vi.mock('@pyreon/reactivity', () => {
|
|
|
36
36
|
s.debug = () => ({ name: undefined, value, subscriberCount: 0 })
|
|
37
37
|
return s
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
// No-op stub for the DI hook `@pyreon/core/context.ts` calls at module
|
|
40
|
+
// load. See sibling test mocks for the full rationale.
|
|
41
|
+
const setSnapshotCapture = () => {}
|
|
42
|
+
return { signal, setSnapshotCapture }
|
|
40
43
|
})
|
|
41
44
|
|
|
42
45
|
import { useReducedMotion } from '../useReducedMotion'
|
package/lib/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index2.d.ts","names":[],"sources":["../../src/types.ts","../../src/kinetic/types.ts","../../src/kinetic.ts","../../src/presets.ts","../../src/useAnimationEnd.ts","../../src/useTransitionState.ts"],"mappings":"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"}
|
package/lib/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["h","applyEnter","applyLeave","applyReducedMotion","isVNode"],"sources":["../src/useAnimationEnd.ts","../src/useReducedMotion.ts","../../../core/core/lib/jsx-runtime.js","../src/kinetic/CollapseRenderer.tsx","../src/useTransitionState.ts","../src/utils.ts","../src/kinetic/TransitionItem.tsx","../src/kinetic/GroupRenderer.tsx","../src/kinetic/StaggerRenderer.tsx","../src/kinetic/TransitionRenderer.tsx","../src/kinetic/createKineticComponent.tsx","../src/kinetic.ts","../src/presets.ts"],"sourcesContent":["import type { Ref } from '@pyreon/core'\nimport { watch } from '@pyreon/reactivity'\n\nconst DEFAULT_TIMEOUT = 5000\n\nexport type UseAnimationEnd = (options: {\n ref: Ref<HTMLElement>\n onEnd: () => void\n active: () => boolean\n timeout?: number | undefined\n}) => void\n\nconst useAnimationEnd: UseAnimationEnd = ({ ref, onEnd, active, timeout = DEFAULT_TIMEOUT }) => {\n let called = false\n\n watch(\n active,\n (isActive) => {\n if (!isActive) {\n called = false\n return\n }\n\n const el = ref.current\n if (!el) return\n\n called = false\n\n const done = () => {\n if (called) return\n called = true\n el.removeEventListener('transitionend', handleEnd)\n el.removeEventListener('animationend', handleEnd)\n clearTimeout(timer)\n onEnd()\n }\n\n const handleEnd = (e: Event) => {\n // Ignore bubbled events from children\n if (e.target !== el) return\n done()\n }\n\n el.addEventListener('transitionend', handleEnd)\n el.addEventListener('animationend', handleEnd)\n\n const timer = setTimeout(done, timeout)\n\n return () => {\n el.removeEventListener('transitionend', handleEnd)\n el.removeEventListener('animationend', handleEnd)\n clearTimeout(timer)\n }\n },\n { immediate: true },\n )\n}\n\nexport default useAnimationEnd\n","import { onMount, onUnmount } from '@pyreon/core'\nimport { signal } from '@pyreon/reactivity'\n\n/**\n * Inline reduced-motion check for kinetic package.\n * Avoids depending on @pyreon/hooks for a single media query.\n */\nexport function useReducedMotion(): () => boolean {\n const matches = signal(false)\n let mql: MediaQueryList | undefined\n\n const onChange = (e: MediaQueryListEvent) => {\n matches.set(e.matches)\n }\n\n onMount(() => {\n mql = window.matchMedia('(prefers-reduced-motion: reduce)')\n matches.set(mql.matches)\n mql.addEventListener('change', onChange)\n return undefined\n })\n\n onUnmount(() => {\n mql?.removeEventListener('change', onChange)\n })\n\n return matches\n}\n","//#region src/h.ts\n/** Marker for fragment nodes — renders children without a wrapper element */\nconst Fragment = Symbol(\"Pyreon.Fragment\");\n/**\n* Hyperscript function — the compiled output of JSX.\n* `<div class=\"x\">hello</div>` → `h(\"div\", { class: \"x\" }, \"hello\")`\n*\n* Generic on P so TypeScript validates props match the component's signature\n* at the call site, then stores the result in the loosely-typed VNode.\n*/\n/** Shared empty props sentinel — identity-checked in mountElement to skip applyProps. */\nconst EMPTY_PROPS = {};\nfunction h(type, props, ...children) {\n\treturn {\n\t\ttype,\n\t\tprops: props ?? EMPTY_PROPS,\n\t\tchildren: normalizeChildren(children),\n\t\tkey: props?.key ?? null\n\t};\n}\nfunction normalizeChildren(children) {\n\tfor (let i = 0; i < children.length; i++) if (Array.isArray(children[i])) return flattenChildren(children);\n\treturn children;\n}\nfunction flattenChildren(children) {\n\tconst result = [];\n\tfor (const child of children) if (Array.isArray(child)) result.push(...flattenChildren(child));\n\telse result.push(child);\n\treturn result;\n}\n\n//#endregion\n//#region src/jsx-runtime.ts\n/**\n* JSX automatic runtime.\n*\n* When tsconfig has `\"jsxImportSource\": \"@pyreon/core\"`, the TS/bundler compiler\n* rewrites JSX to imports from this file automatically:\n* <div class=\"x\" /> → jsx(\"div\", { class: \"x\" })\n*/\nfunction jsx(type, props, key) {\n\tconst { children, ...rest } = props;\n\tconst propsWithKey = key != null ? {\n\t\t...rest,\n\t\tkey\n\t} : rest;\n\tif (typeof type === \"function\") return h(type, children !== void 0 ? {\n\t\t...propsWithKey,\n\t\tchildren\n\t} : propsWithKey);\n\treturn h(type, propsWithKey, ...children === void 0 ? [] : Array.isArray(children) ? children : [children]);\n}\nconst jsxs = jsx;\n\n//#endregion\nexport { Fragment, jsx, jsxs };\n//# sourceMappingURL=jsx-runtime.js.map","import type { VNode } from '@pyreon/core'\nimport { createRef, h, Show } from '@pyreon/core'\nimport { runUntracked, signal, watch } from '@pyreon/reactivity'\nimport type { CSSProperties, TransitionCallbacks, TransitionStage } from '../types'\nimport useAnimationEnd from '../useAnimationEnd'\nimport { useReducedMotion } from '../useReducedMotion'\nimport type { KineticConfig } from './types'\n\ntype CollapseRendererProps = {\n config: KineticConfig\n htmlProps: Record<string, unknown>\n show: () => boolean\n appear?: boolean | undefined\n timeout?: number | undefined\n transition?: string | undefined\n callbacks: Partial<TransitionCallbacks>\n children: VNode | VNode[]\n}\n\n/**\n * Renders a height-animated collapse. The config.tag becomes the outer\n * wrapper (overflow:hidden + animated height). An inner div measures\n * scrollHeight for the target value.\n */\nconst CollapseRenderer = ({\n config,\n htmlProps,\n show,\n appear,\n timeout,\n transition,\n callbacks,\n children,\n}: CollapseRendererProps): VNode | null => {\n const reducedMotion = useReducedMotion()\n let wrapperRef: { current: HTMLElement | null } = createRef<HTMLElement>()\n const contentRef = createRef<HTMLDivElement>()\n\n const effectiveAppear = appear ?? config.appear ?? false\n const effectiveTimeout = timeout ?? config.timeout ?? 5000\n const effectiveTransition = transition ?? config.transition ?? 'height 300ms ease'\n\n const initialShow = show()\n const needsAppear = effectiveAppear && initialShow\n const stage = signal<TransitionStage>(initialShow ? 'entered' : 'hidden')\n let isInitialMount = true\n let appearTriggered = false\n\n // Intercept ref assignment to trigger appear after all refs are wired\n if (needsAppear) {\n const orig = wrapperRef\n const proxy = { current: null as HTMLElement | null }\n Object.defineProperty(proxy, 'current', {\n get() {\n return orig.current\n },\n set(node: HTMLElement | null) {\n orig.current = node\n if (node && !appearTriggered) {\n appearTriggered = true\n queueMicrotask(() => stage.set('entering'))\n }\n },\n })\n wrapperRef = proxy\n }\n\n // State machine transitions\n watch(\n show,\n (showVal) => {\n if (isInitialMount) {\n isInitialMount = false\n // appear case is handled by ref proxy above\n return\n }\n\n const currentStage = runUntracked(() => stage())\n if (showVal && (currentStage === 'hidden' || currentStage === 'leaving')) {\n stage.set('entering')\n } else if (!showVal && (currentStage === 'entered' || currentStage === 'entering')) {\n stage.set('leaving')\n }\n },\n { immediate: true },\n )\n\n // Animate height\n watch(\n () => stage(),\n (currentStage) => {\n const wrapper = wrapperRef.current\n const content = contentRef.current\n if (!wrapper || !content) return\n\n if (reducedMotion()) {\n if (currentStage === 'entering') {\n callbacks.onEnter?.()\n wrapper.style.height = 'auto'\n wrapper.style.overflow = ''\n callbacks.onAfterEnter?.()\n stage.set('entered')\n } else if (currentStage === 'leaving') {\n callbacks.onLeave?.()\n wrapper.style.height = '0px'\n wrapper.style.overflow = 'hidden'\n callbacks.onAfterLeave?.()\n stage.set('hidden')\n }\n return\n }\n\n if (currentStage === 'entering') {\n callbacks.onEnter?.()\n const height = content.scrollHeight\n wrapper.style.transition = 'none'\n wrapper.style.height = '0px'\n wrapper.style.overflow = 'hidden'\n // Force reflow\n void wrapper.offsetHeight\n wrapper.style.transition = effectiveTransition\n wrapper.style.height = `${height}px`\n }\n\n if (currentStage === 'leaving') {\n callbacks.onLeave?.()\n const height = content.scrollHeight\n wrapper.style.transition = 'none'\n wrapper.style.height = `${height}px`\n wrapper.style.overflow = 'hidden'\n // Force reflow\n void wrapper.offsetHeight\n wrapper.style.transition = effectiveTransition\n wrapper.style.height = '0px'\n }\n },\n { immediate: true },\n )\n\n useAnimationEnd({\n ref: wrapperRef,\n active: () => (stage() === 'entering' || stage() === 'leaving') && !reducedMotion(),\n timeout: effectiveTimeout,\n onEnd: () => {\n const wrapper = wrapperRef.current\n if (stage() === 'entering') {\n if (wrapper) {\n wrapper.style.height = 'auto'\n wrapper.style.overflow = ''\n wrapper.style.transition = ''\n }\n callbacks.onAfterEnter?.()\n stage.set('entered')\n } else if (stage() === 'leaving') {\n callbacks.onAfterLeave?.()\n stage.set('hidden')\n }\n },\n })\n\n const shouldRender = () => stage() !== 'hidden'\n\n const wrapperStyle: CSSProperties = {\n ...((htmlProps.style as CSSProperties) ?? {}),\n ...(stage() !== 'entered' ? { overflow: 'hidden' } : {}),\n ...(stage() === 'hidden' ? { height: '0px' } : stage() === 'entered' ? { height: 'auto' } : {}),\n }\n\n return h(\n config.tag,\n { ref: wrapperRef, ...htmlProps, style: wrapperStyle },\n <Show when={shouldRender}>\n <div ref={contentRef}>{children}</div>\n </Show>,\n )\n}\n\nexport default CollapseRenderer\n","import { createRef } from '@pyreon/core'\nimport { runUntracked, signal, watch } from '@pyreon/reactivity'\nimport type { TransitionStage, TransitionStateResult } from './types'\n\nexport type UseTransitionState = (options: {\n show: () => boolean\n appear?: boolean | undefined\n}) => TransitionStateResult\n\nconst useTransitionState: UseTransitionState = ({ show, appear = false }) => {\n const initialShow = show()\n // When appear=true and show starts true, mount the element (stage='entered')\n // but defer the enter animation until the ref is connected.\n const needsAppear = appear && initialShow\n const stage = signal<TransitionStage>(initialShow ? 'entered' : 'hidden')\n const elementRef = createRef<HTMLElement>()\n let isInitialMount = true\n let appearTriggered = false\n\n // Ref callback that triggers the appear animation once the element is wired\n const refCallback = (node: HTMLElement | null) => {\n elementRef.current = node\n if (node && needsAppear && !appearTriggered) {\n appearTriggered = true\n stage.set('entering')\n }\n }\n\n watch(\n show,\n (showVal) => {\n if (isInitialMount) {\n isInitialMount = false\n // appear case is handled by refCallback above\n return\n }\n\n const currentStage = runUntracked(() => stage())\n if (showVal && (currentStage === 'hidden' || currentStage === 'leaving')) {\n stage.set('entering')\n } else if (!showVal && (currentStage === 'entered' || currentStage === 'entering')) {\n stage.set('leaving')\n }\n },\n { immediate: true },\n )\n\n const complete = () => {\n const current = stage()\n if (current === 'entering') stage.set('entered')\n if (current === 'leaving') stage.set('hidden')\n }\n\n return {\n stage,\n ref: refCallback,\n shouldMount: () => stage() !== 'hidden',\n complete,\n }\n}\n\nexport default useTransitionState\n","import type { Ref, VNode } from '@pyreon/core'\nimport type { CSSProperties } from './types'\n\nconst splitCache = new Map<string, string[]>()\nconst splitClasses = (classes: string): string[] => {\n let cached = splitCache.get(classes)\n if (!cached) {\n cached = classes.split(/\\s+/).filter(Boolean)\n splitCache.set(classes, cached)\n }\n return cached\n}\n\n/** Adds space-separated CSS classes to an element. */\nexport const addClasses = (el: HTMLElement, classes: string | undefined) => {\n if (!classes) return\n const list = splitClasses(classes)\n if (list.length > 0) el.classList.add(...list)\n}\n\n/** Removes space-separated CSS classes from an element. */\nexport const removeClasses = (el: HTMLElement, classes: string | undefined) => {\n if (!classes) return\n const list = splitClasses(classes)\n if (list.length > 0) el.classList.remove(...list)\n}\n\n/**\n * Executes callback after two animation frames (double-rAF).\n * Ensures the browser paints the current state before applying changes,\n * which is required for CSS transitions to trigger. Returns 0 on SSR —\n * the typeof-window guard makes the SSR-safety contract explicit (callers\n * are always browser-only via `onMount`, but the rule can't AST-trace it).\n */\nexport const nextFrame = (callback: () => void): number => {\n if (typeof requestAnimationFrame === 'undefined') return 0\n return requestAnimationFrame(() => {\n requestAnimationFrame(callback)\n })\n}\n\n/** Merges two className strings, filtering undefined/empty. */\nexport const mergeClassNames = (\n existing: string | undefined,\n additional: string | undefined,\n): string | undefined => {\n const parts = [existing, additional].filter(Boolean)\n return parts.length > 0 ? parts.join(' ') : undefined\n}\n\n/** Merges two CSSProperties objects, with `b` taking precedence. */\nexport const mergeStyles = (\n a: CSSProperties | undefined,\n b: CSSProperties | undefined,\n): CSSProperties | undefined => {\n if (!a && !b) return undefined\n if (!a) return b\n if (!b) return a\n return { ...a, ...b }\n}\n\n// ─── Ref & Motion Utilities ─────────────────────────────────\n\ntype RefCallback<T> = (node: T | null) => void\ntype RefLike<T> = RefCallback<T> | Ref<T>\n\n/** Merges multiple refs (callback or object) into a single callback ref. */\nexport const mergeRefs = <T>(...refs: (RefLike<T> | undefined)[]): ((node: T | null) => void) => {\n return (node: T | null) => {\n for (const ref of refs) {\n if (!ref) continue\n if (typeof ref === 'function') {\n ref(node)\n } else {\n ;(ref as { current: unknown }).current = node\n }\n }\n }\n}\n\n/** Clones a VNode with merged props. */\nexport const cloneVNode = (vnode: VNode, extraProps: Record<string, unknown>): VNode => ({\n ...vnode,\n props: { ...vnode.props, ...extraProps },\n})\n","import type { VNode } from '@pyreon/core'\nimport { createRef, Show } from '@pyreon/core'\nimport { watch } from '@pyreon/reactivity'\nimport type { ClassTransitionProps, StyleTransitionProps, TransitionCallbacks } from '../types'\nimport useAnimationEnd from '../useAnimationEnd'\nimport { useReducedMotion } from '../useReducedMotion'\nimport useTransitionState from '../useTransitionState'\nimport { addClasses, cloneVNode, mergeRefs, mergeStyles, nextFrame, removeClasses } from '../utils'\n\ntype TransitionItemProps = ClassTransitionProps &\n StyleTransitionProps &\n TransitionCallbacks & {\n show: () => boolean\n appear?: boolean | undefined\n unmount?: boolean | undefined\n timeout?: number | undefined\n delay?: number | undefined\n children: VNode\n }\n\nconst applyEnter = (el: HTMLElement, config: ClassTransitionProps & StyleTransitionProps) => {\n addClasses(el, config.enter)\n addClasses(el, config.enterFrom)\n if (config.enterStyle) Object.assign(el.style, config.enterStyle)\n if (config.enterTransition) el.style.transition = config.enterTransition\n\n return nextFrame(() => {\n removeClasses(el, config.enterFrom)\n addClasses(el, config.enterTo)\n if (config.enterToStyle) Object.assign(el.style, config.enterToStyle)\n })\n}\n\nconst applyLeave = (el: HTMLElement, config: ClassTransitionProps & StyleTransitionProps) => {\n removeClasses(el, config.enter)\n removeClasses(el, config.enterTo)\n\n addClasses(el, config.leave)\n addClasses(el, config.leaveFrom)\n if (config.leaveStyle) Object.assign(el.style, config.leaveStyle)\n if (config.leaveTransition) el.style.transition = config.leaveTransition\n\n return nextFrame(() => {\n removeClasses(el, config.leaveFrom)\n addClasses(el, config.leaveTo)\n if (config.leaveToStyle) Object.assign(el.style, config.leaveToStyle)\n })\n}\n\nconst applyReducedMotion = (\n stage: string,\n callbacks: Partial<TransitionCallbacks>,\n complete: () => void,\n) => {\n if (stage === 'entering') {\n callbacks.onEnter?.()\n callbacks.onAfterEnter?.()\n complete()\n } else if (stage === 'leaving') {\n callbacks.onLeave?.()\n callbacks.onAfterLeave?.()\n complete()\n }\n}\n\n/**\n * Internal per-child transition component. Used by StaggerRenderer and\n * GroupRenderer to give each child its own animation state.\n *\n * Uses cloneVNode to inject ref onto the child — the child must accept ref.\n */\nconst TransitionItem = (props: TransitionItemProps): VNode | null => {\n const appear = props.appear ?? false\n const unmount = props.unmount ?? true\n const timeout = props.timeout ?? 5000\n const reducedMotion = useReducedMotion()\n const { stage, ref: stateRef, shouldMount, complete } = useTransitionState({\n show: props.show,\n appear,\n })\n\n const elementRef = createRef<HTMLElement>()\n const mergedRef = mergeRefs(\n elementRef,\n stateRef,\n (props.children.props as Record<string, unknown>)?.ref as\n | ((el: HTMLElement | null) => void)\n | undefined,\n )\n\n const callbacks = {\n onEnter: props.onEnter,\n onAfterEnter: props.onAfterEnter,\n onLeave: props.onLeave,\n onAfterLeave: props.onAfterLeave,\n }\n\n const transitionConfig = {\n enter: props.enter,\n enterFrom: props.enterFrom,\n enterTo: props.enterTo,\n leave: props.leave,\n leaveFrom: props.leaveFrom,\n leaveTo: props.leaveTo,\n enterStyle: props.enterStyle,\n enterToStyle: props.enterToStyle,\n enterTransition: props.enterTransition,\n leaveStyle: props.leaveStyle,\n leaveToStyle: props.leaveToStyle,\n leaveTransition: props.leaveTransition,\n }\n\n useAnimationEnd({\n ref: elementRef,\n active: () => (stage() === 'entering' || stage() === 'leaving') && !reducedMotion(),\n timeout,\n onEnd: () => {\n if (stage() === 'entering') {\n callbacks.onAfterEnter?.()\n } else if (stage() === 'leaving') {\n callbacks.onAfterLeave?.()\n }\n complete()\n },\n })\n\n watch(\n () => stage(),\n (currentStage) => {\n const el = elementRef.current\n if (!el) return\n\n if (reducedMotion()) {\n applyReducedMotion(currentStage, callbacks, complete)\n return\n }\n\n if (currentStage === 'entering') {\n callbacks.onEnter?.()\n const frameId = applyEnter(el, transitionConfig)\n return () => cancelAnimationFrame(frameId)\n }\n\n if (currentStage === 'leaving') {\n callbacks.onLeave?.()\n const frameId = applyLeave(el, transitionConfig)\n return () => cancelAnimationFrame(frameId)\n }\n\n if (currentStage === 'entered') {\n removeClasses(el, props.enter)\n el.style.transition = ''\n }\n },\n { immediate: true },\n )\n\n return (\n <Show\n when={shouldMount}\n fallback={\n unmount\n ? null\n : cloneVNode(props.children, {\n ref: mergedRef,\n style: mergeStyles(\n (props.children.props as Record<string, unknown>)?.style as\n | Record<string, string | number | undefined>\n | undefined,\n { display: 'none' },\n ),\n })\n }\n >\n {cloneVNode(props.children, { ref: mergedRef })}\n </Show>\n )\n}\n\nexport default TransitionItem\n","import type { VNode } from '@pyreon/core'\nimport { h } from '@pyreon/core'\nimport { signal } from '@pyreon/reactivity'\nimport type { TransitionCallbacks } from '../types'\nimport TransitionItem from './TransitionItem'\nimport type { KineticConfig } from './types'\n\ntype GroupRendererProps = {\n config: KineticConfig\n htmlProps: Record<string, unknown>\n appear?: boolean | undefined\n timeout?: number | undefined\n callbacks: Partial<TransitionCallbacks>\n /**\n * Children can be a static array OR a reactive accessor `() => VNode[]`.\n * When passed as an accessor, GroupRenderer tracks changes and\n * animates entering/leaving children automatically.\n */\n children: VNode[] | (() => VNode[])\n}\n\ntype KeyedChild = { key: string | number; element: VNode }\n\nconst isVNode = (child: unknown): child is VNode =>\n child != null && typeof child === 'object' && 'type' in (child as object)\n\nconst getKeyedChildren = (children: VNode[]): KeyedChild[] => {\n const result: KeyedChild[] = []\n for (const child of children) {\n if (isVNode(child)) {\n const key = (child as VNode & { key?: string | number }).key\n if (key != null) {\n result.push({ key, element: child })\n }\n }\n }\n return result\n}\n\n/**\n * Renders children with key-based enter/exit animation (no `show` prop).\n * Children that appear (new key) animate in. Children that disappear\n * (removed key) stay in DOM during leave animation, then unmount.\n * config.tag wraps all children as a container element.\n *\n * In Pyreon, components run once. Pass children as a reactive accessor\n * `() => VNode[]` for the group to detect changes and animate entries/exits.\n */\nconst GroupRenderer = ({\n config,\n htmlProps,\n appear,\n timeout,\n callbacks,\n children,\n}: GroupRendererProps): VNode | null => {\n const effectiveAppear = appear ?? config.appear ?? false\n const effectiveTimeout = timeout ?? config.timeout ?? 5000\n\n const prevMap = new Map<string | number, VNode>()\n const leavingMap = new Map<string | number, VNode>()\n const forceUpdate = signal(0)\n\n // Normalize children to an accessor\n const getChildren = typeof children === 'function' ? (children as () => VNode[]) : () => children\n\n // Track initial keys for appear animation logic\n const initialKeyed = getKeyedChildren(getChildren())\n const initialKeys = new Set(initialKeyed.map((c) => c.key))\n for (const { key, element } of initialKeyed) {\n prevMap.set(key, element)\n }\n\n const handleAfterLeave = (key: string | number) => {\n leavingMap.delete(key)\n callbacks.onAfterLeave?.()\n forceUpdate.update((c) => c + 1)\n }\n\n // Reactive accessor — re-evaluates when children() or forceUpdate changes\n return (() => {\n forceUpdate()\n\n const currentChildren = getChildren()\n const currentKeyed = getKeyedChildren(currentChildren)\n const currentMap = new Map<string | number, VNode>()\n for (const { key, element } of currentKeyed) {\n currentMap.set(key, element)\n }\n\n // Detect leaving children\n for (const [key, child] of prevMap) {\n if (!currentMap.has(key) && !leavingMap.has(key)) {\n leavingMap.set(key, child)\n }\n }\n\n // Cancel leave if child reappears\n for (const key of currentMap.keys()) {\n leavingMap.delete(key)\n }\n\n // Update prev for next diff\n prevMap.clear()\n for (const [key, element] of currentMap) {\n prevMap.set(key, element)\n }\n\n // Merge current + leaving\n const allEntries: KeyedChild[] = [...currentKeyed]\n for (const [key, element] of leavingMap) {\n allEntries.push({ key, element })\n }\n\n const groupedChildren = allEntries.map(({ key, element }) => {\n const isInitial = initialKeys.has(key)\n const isShowing = currentMap.has(key)\n\n return (\n <TransitionItem\n show={() => isShowing}\n appear={isInitial ? effectiveAppear : true}\n timeout={effectiveTimeout}\n enterStyle={config.enterStyle}\n enterToStyle={config.enterToStyle}\n enterTransition={config.enterTransition}\n leaveStyle={config.leaveStyle}\n leaveToStyle={config.leaveToStyle}\n leaveTransition={config.leaveTransition}\n enter={config.enter}\n enterFrom={config.enterFrom}\n enterTo={config.enterTo}\n leave={config.leave}\n leaveFrom={config.leaveFrom}\n leaveTo={config.leaveTo}\n onAfterLeave={() => handleAfterLeave(key)}\n >\n {element}\n </TransitionItem>\n )\n })\n\n return h(config.tag, { ...htmlProps }, ...groupedChildren)\n }) as unknown as VNode\n}\n\nexport default GroupRenderer\n","import type { VNode } from '@pyreon/core'\nimport { h } from '@pyreon/core'\nimport type { CSSProperties, TransitionCallbacks } from '../types'\nimport { cloneVNode } from '../utils'\nimport TransitionItem from './TransitionItem'\nimport type { KineticConfig } from './types'\n\ntype StaggerRendererProps = {\n config: KineticConfig\n htmlProps: Record<string, unknown>\n show: () => boolean\n appear?: boolean | undefined\n timeout?: number | undefined\n interval?: number | undefined\n reverseLeave?: boolean | undefined\n callbacks: Partial<TransitionCallbacks>\n children: VNode[]\n}\n\nconst isVNode = (child: unknown): child is VNode =>\n child != null && typeof child === 'object' && 'type' in (child as object)\n\n/**\n * Renders children with staggered enter/exit animation.\n * config.tag wraps the staggered children as a container element.\n * Each child is individually animated via TransitionItem.\n */\nconst StaggerRenderer = ({\n config,\n htmlProps,\n show,\n appear,\n timeout,\n interval,\n reverseLeave,\n callbacks,\n children,\n}: StaggerRendererProps): VNode | null => {\n const effectiveAppear = appear ?? config.appear ?? false\n const effectiveTimeout = timeout ?? config.timeout ?? 5000\n const effectiveInterval = interval ?? config.interval ?? 50\n const effectiveReverseLeave = reverseLeave ?? config.reverseLeave ?? false\n\n const childArray = (Array.isArray(children) ? children : [children]).filter(isVNode)\n const count = childArray.length\n\n const staggeredChildren = childArray.map((child, index) => {\n const staggerIndex = !show() && effectiveReverseLeave ? count - 1 - index : index\n const delay = staggerIndex * effectiveInterval\n\n return (\n <TransitionItem\n key={(child as VNode & { key?: string | number }).key ?? index}\n show={show}\n appear={effectiveAppear}\n timeout={effectiveTimeout + delay}\n enterStyle={config.enterStyle}\n enterToStyle={config.enterToStyle}\n enterTransition={config.enterTransition}\n leaveStyle={config.leaveStyle}\n leaveToStyle={config.leaveToStyle}\n leaveTransition={config.leaveTransition}\n enter={config.enter}\n enterFrom={config.enterFrom}\n enterTo={config.enterTo}\n leave={config.leave}\n leaveFrom={config.leaveFrom}\n leaveTo={config.leaveTo}\n onAfterLeave={\n index === (effectiveReverseLeave ? 0 : count - 1) ? callbacks.onAfterLeave : undefined\n }\n >\n {cloneVNode(child, {\n style: {\n ...((child.props as Record<string, unknown>)?.style as CSSProperties | undefined),\n '--stagger-index': staggerIndex,\n '--stagger-interval': `${effectiveInterval}ms`,\n transitionDelay: `${delay}ms`,\n } as CSSProperties,\n })}\n </TransitionItem>\n )\n })\n\n return h(config.tag, { ...htmlProps }, ...staggeredChildren)\n}\n\nexport default StaggerRenderer\n","import type { VNode } from '@pyreon/core'\nimport { createRef, h, Show } from '@pyreon/core'\nimport { watch } from '@pyreon/reactivity'\nimport type { CSSProperties, TransitionCallbacks } from '../types'\nimport useAnimationEnd from '../useAnimationEnd'\nimport { useReducedMotion } from '../useReducedMotion'\nimport useTransitionState from '../useTransitionState'\nimport { addClasses, mergeRefs, nextFrame, removeClasses } from '../utils'\nimport type { KineticConfig } from './types'\n\ntype TransitionRendererProps = {\n config: KineticConfig\n htmlProps: Record<string, unknown>\n show: () => boolean\n appear?: boolean | undefined\n unmount?: boolean | undefined\n timeout?: number | undefined\n callbacks: Partial<TransitionCallbacks>\n children: VNode | VNode[]\n}\n\nconst applyEnter = (el: HTMLElement, config: KineticConfig) => {\n addClasses(el, config.enter)\n addClasses(el, config.enterFrom)\n if (config.enterStyle) Object.assign(el.style, config.enterStyle)\n if (config.enterTransition) el.style.transition = config.enterTransition\n\n return nextFrame(() => {\n removeClasses(el, config.enterFrom)\n addClasses(el, config.enterTo)\n if (config.enterToStyle) Object.assign(el.style, config.enterToStyle)\n })\n}\n\nconst applyLeave = (el: HTMLElement, config: KineticConfig) => {\n removeClasses(el, config.enter)\n removeClasses(el, config.enterTo)\n\n addClasses(el, config.leave)\n addClasses(el, config.leaveFrom)\n if (config.leaveStyle) Object.assign(el.style, config.leaveStyle)\n if (config.leaveTransition) el.style.transition = config.leaveTransition\n\n return nextFrame(() => {\n removeClasses(el, config.leaveFrom)\n addClasses(el, config.leaveTo)\n if (config.leaveToStyle) Object.assign(el.style, config.leaveToStyle)\n })\n}\n\nconst applyReducedMotion = (\n stage: string,\n cbs: Partial<TransitionCallbacks>,\n complete: () => void,\n) => {\n if (stage === 'entering') {\n cbs.onEnter?.()\n cbs.onAfterEnter?.()\n complete()\n } else if (stage === 'leaving') {\n cbs.onLeave?.()\n cbs.onAfterLeave?.()\n complete()\n }\n}\n\n/**\n * Renders a single element with CSS transition enter/exit animation.\n * Uses h(config.tag) — no cloneElement needed.\n */\nconst TransitionRenderer = (props: TransitionRendererProps): VNode | null => {\n const reducedMotion = useReducedMotion()\n const {\n stage,\n ref: stateRef,\n shouldMount,\n complete,\n } = useTransitionState({\n show: props.show,\n appear: props.appear ?? props.config.appear ?? false,\n })\n\n const elementRef = createRef<HTMLElement>()\n const mergedRef = mergeRefs(elementRef, stateRef)\n\n const effectiveUnmount = props.unmount ?? props.config.unmount ?? true\n const effectiveTimeout = props.timeout ?? props.config.timeout ?? 5000\n\n useAnimationEnd({\n ref: elementRef,\n active: () => (stage() === 'entering' || stage() === 'leaving') && !reducedMotion(),\n timeout: effectiveTimeout,\n onEnd: () => {\n if (stage() === 'entering') {\n props.callbacks.onAfterEnter?.()\n } else if (stage() === 'leaving') {\n props.callbacks.onAfterLeave?.()\n }\n complete()\n },\n })\n\n watch(\n () => stage(),\n (currentStage) => {\n const el = elementRef.current\n if (!el) return\n\n if (reducedMotion()) {\n applyReducedMotion(currentStage, props.callbacks, complete)\n return\n }\n\n if (currentStage === 'entering') {\n props.callbacks.onEnter?.()\n const frameId = applyEnter(el, props.config)\n return () => cancelAnimationFrame(frameId)\n }\n\n if (currentStage === 'leaving') {\n props.callbacks.onLeave?.()\n const frameId = applyLeave(el, props.config)\n return () => cancelAnimationFrame(frameId)\n }\n\n if (currentStage === 'entered') {\n removeClasses(el, props.config.enter)\n el.style.transition = ''\n }\n },\n { immediate: true },\n )\n\n return (\n <Show\n when={shouldMount}\n fallback={\n effectiveUnmount\n ? null\n : h(\n props.config.tag,\n {\n ref: mergedRef,\n ...props.htmlProps,\n style: {\n ...((props.htmlProps.style as CSSProperties) ?? {}),\n display: 'none',\n },\n },\n props.children,\n )\n }\n >\n {h(props.config.tag, { ref: mergedRef, ...props.htmlProps }, props.children)}\n </Show>\n )\n}\n\nexport default TransitionRenderer\n","import type { VNode } from '@pyreon/core'\nimport type { CSSProperties, TransitionCallbacks } from '../types'\nimport CollapseRenderer from './CollapseRenderer'\nimport GroupRenderer from './GroupRenderer'\nimport StaggerRenderer from './StaggerRenderer'\nimport TransitionRenderer from './TransitionRenderer'\nimport type { ClassConfig, KineticComponent, KineticConfig, KineticMode } from './types'\n\n/** Keys that are kinetic-specific and should not be forwarded as HTML attrs. */\nconst KINETIC_KEYS = new Set([\n 'show',\n 'appear',\n 'unmount',\n 'timeout',\n 'transition',\n 'interval',\n 'reverseLeave',\n 'onEnter',\n 'onAfterEnter',\n 'onLeave',\n 'onAfterLeave',\n])\n\n/**\n * Core factory. Creates a component that delegates to the appropriate\n * renderer based on config.mode, then attaches immutable chain methods\n * via Object.assign.\n */\nconst createKineticComponent = <Tag extends string, Mode extends KineticMode = 'transition'>(\n config: KineticConfig,\n): KineticComponent<Tag, Mode> => {\n const Component = (props: Record<string, unknown>): VNode | null => {\n // Separate kinetic-specific props from HTML pass-through props\n const htmlProps: Record<string, unknown> = {}\n const kineticProps: Record<string, unknown> = {}\n\n for (const key in props) {\n if (KINETIC_KEYS.has(key)) {\n kineticProps[key] = props[key]\n } else {\n htmlProps[key] = props[key]\n }\n }\n\n const {\n show,\n appear,\n unmount,\n timeout,\n transition,\n interval,\n reverseLeave,\n onEnter,\n onAfterEnter,\n onLeave,\n onAfterLeave,\n } = kineticProps as {\n show?: () => boolean\n appear?: boolean\n unmount?: boolean\n timeout?: number\n transition?: string\n interval?: number\n reverseLeave?: boolean\n } & Partial<TransitionCallbacks>\n\n const callbacks: Partial<TransitionCallbacks> = {\n onEnter: onEnter ?? config.onEnter,\n onAfterEnter: onAfterEnter ?? config.onAfterEnter,\n onLeave: onLeave ?? config.onLeave,\n onAfterLeave: onAfterLeave ?? config.onAfterLeave,\n }\n\n // Extract children from htmlProps (it's not an HTML attribute)\n const { children, ...restHtml } = htmlProps\n\n if (config.mode === 'collapse') {\n return (\n <CollapseRenderer\n config={config}\n htmlProps={restHtml}\n show={show as () => boolean}\n appear={appear}\n timeout={timeout}\n transition={transition}\n callbacks={callbacks}\n >\n {children as VNode | VNode[]}\n </CollapseRenderer>\n )\n }\n\n if (config.mode === 'stagger') {\n return (\n <StaggerRenderer\n config={config}\n htmlProps={restHtml}\n show={show as () => boolean}\n appear={appear}\n timeout={timeout}\n interval={interval}\n reverseLeave={reverseLeave}\n callbacks={callbacks}\n >\n {children as VNode[]}\n </StaggerRenderer>\n )\n }\n\n if (config.mode === 'group') {\n return (\n <GroupRenderer\n config={config}\n htmlProps={restHtml}\n appear={appear}\n timeout={timeout}\n callbacks={callbacks}\n >\n {children as VNode[]}\n </GroupRenderer>\n )\n }\n\n // Default: transition mode\n return (\n <TransitionRenderer\n config={config}\n htmlProps={restHtml}\n show={show as () => boolean}\n appear={appear}\n unmount={unmount}\n timeout={timeout}\n callbacks={callbacks}\n >\n {children as VNode | VNode[]}\n </TransitionRenderer>\n )\n }\n\n Component.displayName = `kinetic(${config.tag})`\n\n // Immutable chain methods — each returns a new component with merged config.\n return Object.assign(Component, {\n preset: (preset: Record<string, unknown>) =>\n createKineticComponent<Tag, Mode>({\n ...config,\n ...preset,\n } as KineticConfig),\n\n enter: (styles: CSSProperties) =>\n createKineticComponent<Tag, Mode>({ ...config, enterStyle: styles }),\n\n enterTo: (styles: CSSProperties) =>\n createKineticComponent<Tag, Mode>({ ...config, enterToStyle: styles }),\n\n enterTransition: (value: string) =>\n createKineticComponent<Tag, Mode>({ ...config, enterTransition: value }),\n\n leave: (styles: CSSProperties) =>\n createKineticComponent<Tag, Mode>({ ...config, leaveStyle: styles }),\n\n leaveTo: (styles: CSSProperties) =>\n createKineticComponent<Tag, Mode>({ ...config, leaveToStyle: styles }),\n\n leaveTransition: (value: string) =>\n createKineticComponent<Tag, Mode>({ ...config, leaveTransition: value }),\n\n enterClass: ({ active, from, to }: ClassConfig) =>\n createKineticComponent<Tag, Mode>({\n ...config,\n enter: active,\n enterFrom: from,\n enterTo: to,\n }),\n\n leaveClass: ({ active, from, to }: ClassConfig) =>\n createKineticComponent<Tag, Mode>({\n ...config,\n leave: active,\n leaveFrom: from,\n leaveTo: to,\n }),\n\n config: (opts: Record<string, unknown>) =>\n createKineticComponent<Tag, Mode>({\n ...config,\n ...opts,\n } as KineticConfig),\n\n on: (cbs: Partial<TransitionCallbacks>) =>\n createKineticComponent<Tag, Mode>({ ...config, ...cbs }),\n\n collapse: (opts?: { transition?: string }) =>\n createKineticComponent<Tag, 'collapse'>({\n ...config,\n mode: 'collapse',\n ...opts,\n }),\n\n stagger: (opts?: { interval?: number; reverseLeave?: boolean }) =>\n createKineticComponent<Tag, 'stagger'>({\n ...config,\n mode: 'stagger',\n ...opts,\n }),\n\n group: () => createKineticComponent<Tag, 'group'>({ ...config, mode: 'group' }),\n }) as unknown as KineticComponent<Tag, Mode>\n}\n\nexport default createKineticComponent\n","import createKineticComponent from './kinetic/createKineticComponent'\nimport type { KineticComponent } from './kinetic/types'\n\n/**\n * Creates a reusable animated component via immutable chaining.\n *\n * @example\n * ```tsx\n * // Transition (default)\n * const FadeDiv = kinetic('div').preset(fade)\n *\n * // Collapse\n * const Accordion = kinetic('div').collapse()\n *\n * // Stagger\n * const StaggerList = kinetic('ul').preset(slideUp).stagger({ interval: 50 })\n *\n * // Group (key-based enter/exit)\n * const AnimatedList = kinetic('ul').preset(fade).group()\n * ```\n */\nconst kinetic = <Tag extends string>(tag: Tag): KineticComponent<Tag, 'transition'> =>\n createKineticComponent<Tag, 'transition'>({ tag, mode: 'transition' })\n\nexport default kinetic\n","import type { ClassTransitionProps, StyleTransitionProps } from './types'\n\nexport type Preset = StyleTransitionProps & ClassTransitionProps\n\nexport const fade: Preset = {\n enterStyle: { opacity: 0 },\n enterToStyle: { opacity: 1 },\n enterTransition: 'opacity 300ms ease-out',\n leaveStyle: { opacity: 1 },\n leaveToStyle: { opacity: 0 },\n leaveTransition: 'opacity 200ms ease-in',\n}\n\nexport const scaleIn: Preset = {\n enterStyle: { opacity: 0, transform: 'scale(0.95)' },\n enterToStyle: { opacity: 1, transform: 'scale(1)' },\n enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',\n leaveStyle: { opacity: 1, transform: 'scale(1)' },\n leaveToStyle: { opacity: 0, transform: 'scale(0.95)' },\n leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',\n}\n\nexport const slideUp: Preset = {\n enterStyle: { opacity: 0, transform: 'translateY(16px)' },\n enterToStyle: { opacity: 1, transform: 'translateY(0)' },\n enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',\n leaveStyle: { opacity: 1, transform: 'translateY(0)' },\n leaveToStyle: { opacity: 0, transform: 'translateY(16px)' },\n leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',\n}\n\nexport const slideDown: Preset = {\n enterStyle: { opacity: 0, transform: 'translateY(-16px)' },\n enterToStyle: { opacity: 1, transform: 'translateY(0)' },\n enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',\n leaveStyle: { opacity: 1, transform: 'translateY(0)' },\n leaveToStyle: { opacity: 0, transform: 'translateY(-16px)' },\n leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',\n}\n\nexport const slideLeft: Preset = {\n enterStyle: { opacity: 0, transform: 'translateX(16px)' },\n enterToStyle: { opacity: 1, transform: 'translateX(0)' },\n enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',\n leaveStyle: { opacity: 1, transform: 'translateX(0)' },\n leaveToStyle: { opacity: 0, transform: 'translateX(16px)' },\n leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',\n}\n\nexport const slideRight: Preset = {\n enterStyle: { opacity: 0, transform: 'translateX(-16px)' },\n enterToStyle: { opacity: 1, transform: 'translateX(0)' },\n enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',\n leaveStyle: { opacity: 1, transform: 'translateX(0)' },\n leaveToStyle: { opacity: 0, transform: 'translateX(-16px)' },\n leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',\n}\n\nexport const presets = {\n fade,\n scaleIn,\n slideUp,\n slideDown,\n slideLeft,\n slideRight,\n} as const\n"],"mappings":"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"}
|