@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,224 +0,0 @@
|
|
|
1
|
-
import type { VNode } from '@pyreon/core'
|
|
2
|
-
import { splitProps } from '@pyreon/core'
|
|
3
|
-
import type { CSSProperties, TransitionCallbacks } from '../types'
|
|
4
|
-
import CollapseRenderer from './CollapseRenderer'
|
|
5
|
-
import GroupRenderer from './GroupRenderer'
|
|
6
|
-
import StaggerRenderer from './StaggerRenderer'
|
|
7
|
-
import TransitionRenderer from './TransitionRenderer'
|
|
8
|
-
import type { ClassConfig, KineticComponent, KineticConfig, KineticMode } from './types'
|
|
9
|
-
|
|
10
|
-
/** Keys that are kinetic-specific and should not be forwarded as HTML attrs. */
|
|
11
|
-
const KINETIC_KEYS = new Set([
|
|
12
|
-
'show',
|
|
13
|
-
'appear',
|
|
14
|
-
'unmount',
|
|
15
|
-
'timeout',
|
|
16
|
-
'transition',
|
|
17
|
-
'interval',
|
|
18
|
-
'reverseLeave',
|
|
19
|
-
'onEnter',
|
|
20
|
-
'onAfterEnter',
|
|
21
|
-
'onLeave',
|
|
22
|
-
'onAfterLeave',
|
|
23
|
-
])
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Core factory. Creates a component that delegates to the appropriate
|
|
27
|
-
* renderer based on config.mode, then attaches immutable chain methods
|
|
28
|
-
* via Object.assign.
|
|
29
|
-
*/
|
|
30
|
-
const createKineticComponent = <Tag extends string, Mode extends KineticMode = 'transition'>(
|
|
31
|
-
config: KineticConfig,
|
|
32
|
-
): KineticComponent<Tag, Mode> => {
|
|
33
|
-
const Component = (props: Record<string, unknown>): VNode | null => {
|
|
34
|
-
// Separate kinetic-specific props from HTML pass-through props.
|
|
35
|
-
// MUST use splitProps (descriptor-preserving) — a plain
|
|
36
|
-
// `htmlProps[key] = props[key]` value-copy fires every getter at
|
|
37
|
-
// component-setup time. The compiler emits `<KineticDiv class={sig()}>`
|
|
38
|
-
// as `_rp(() => sig())`, which `makeReactiveProps` turns into a getter
|
|
39
|
-
// on `props`; reading it here (outside any tracking scope) would
|
|
40
|
-
// collapse it to a static snapshot and freeze the HTML attr forever.
|
|
41
|
-
// splitProps copies DESCRIPTORS via Object.getOwnPropertyDescriptor +
|
|
42
|
-
// Object.defineProperty, so the getter survives to the renderer's
|
|
43
|
-
// `h(config.tag, htmlProps)` where runtime-dom's applyProps detects
|
|
44
|
-
// the descriptor and wraps the read in renderEffect.
|
|
45
|
-
// `props` is `Record<string, unknown>`, so `Omit<…, string>` collapses
|
|
46
|
-
// to `{}` at the type level — the runtime split is correct (splitProps
|
|
47
|
-
// copies descriptors for every own key not in the pick set), only the
|
|
48
|
-
// inferred result types degrade. Cast back to the real shape.
|
|
49
|
-
const [kineticProps, htmlPropsWithChildren] = splitProps(props, [...KINETIC_KEYS]) as [
|
|
50
|
-
Record<string, unknown>,
|
|
51
|
-
Record<string, unknown>,
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
const {
|
|
55
|
-
show,
|
|
56
|
-
appear,
|
|
57
|
-
unmount,
|
|
58
|
-
timeout,
|
|
59
|
-
transition,
|
|
60
|
-
interval,
|
|
61
|
-
reverseLeave,
|
|
62
|
-
onEnter,
|
|
63
|
-
onAfterEnter,
|
|
64
|
-
onLeave,
|
|
65
|
-
onAfterLeave,
|
|
66
|
-
} = kineticProps as {
|
|
67
|
-
show?: () => boolean
|
|
68
|
-
appear?: boolean
|
|
69
|
-
unmount?: boolean
|
|
70
|
-
timeout?: number
|
|
71
|
-
transition?: string
|
|
72
|
-
interval?: number
|
|
73
|
-
reverseLeave?: boolean
|
|
74
|
-
} & Partial<TransitionCallbacks>
|
|
75
|
-
|
|
76
|
-
const callbacks: Partial<TransitionCallbacks> = {
|
|
77
|
-
onEnter: onEnter ?? config.onEnter,
|
|
78
|
-
onAfterEnter: onAfterEnter ?? config.onAfterEnter,
|
|
79
|
-
onLeave: onLeave ?? config.onLeave,
|
|
80
|
-
onAfterLeave: onAfterLeave ?? config.onAfterLeave,
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Carve `children` out of the HTML pass-through set — also via
|
|
84
|
-
// splitProps so the remaining HTML attrs keep their getter
|
|
85
|
-
// descriptors (`const { children, ...restHtml } = …` is the same
|
|
86
|
-
// value-copy footgun as the split above).
|
|
87
|
-
const [childHolder, restHtml] = splitProps(htmlPropsWithChildren, ['children'])
|
|
88
|
-
const children = childHolder.children
|
|
89
|
-
|
|
90
|
-
if (config.mode === 'collapse') {
|
|
91
|
-
return (
|
|
92
|
-
<CollapseRenderer
|
|
93
|
-
config={config}
|
|
94
|
-
htmlProps={restHtml}
|
|
95
|
-
show={show as () => boolean}
|
|
96
|
-
appear={appear}
|
|
97
|
-
timeout={timeout}
|
|
98
|
-
transition={transition}
|
|
99
|
-
callbacks={callbacks}
|
|
100
|
-
>
|
|
101
|
-
{children as VNode | VNode[]}
|
|
102
|
-
</CollapseRenderer>
|
|
103
|
-
)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (config.mode === 'stagger') {
|
|
107
|
-
return (
|
|
108
|
-
<StaggerRenderer
|
|
109
|
-
config={config}
|
|
110
|
-
htmlProps={restHtml}
|
|
111
|
-
show={show as () => boolean}
|
|
112
|
-
appear={appear}
|
|
113
|
-
timeout={timeout}
|
|
114
|
-
interval={interval}
|
|
115
|
-
reverseLeave={reverseLeave}
|
|
116
|
-
callbacks={callbacks}
|
|
117
|
-
>
|
|
118
|
-
{children as VNode[]}
|
|
119
|
-
</StaggerRenderer>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (config.mode === 'group') {
|
|
124
|
-
return (
|
|
125
|
-
<GroupRenderer
|
|
126
|
-
config={config}
|
|
127
|
-
htmlProps={restHtml}
|
|
128
|
-
appear={appear}
|
|
129
|
-
timeout={timeout}
|
|
130
|
-
callbacks={callbacks}
|
|
131
|
-
>
|
|
132
|
-
{children as VNode[]}
|
|
133
|
-
</GroupRenderer>
|
|
134
|
-
)
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Default: transition mode
|
|
138
|
-
return (
|
|
139
|
-
<TransitionRenderer
|
|
140
|
-
config={config}
|
|
141
|
-
htmlProps={restHtml}
|
|
142
|
-
show={show as () => boolean}
|
|
143
|
-
appear={appear}
|
|
144
|
-
unmount={unmount}
|
|
145
|
-
timeout={timeout}
|
|
146
|
-
callbacks={callbacks}
|
|
147
|
-
>
|
|
148
|
-
{children as VNode | VNode[]}
|
|
149
|
-
</TransitionRenderer>
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
Component.displayName = `kinetic(${config.tag})`
|
|
154
|
-
|
|
155
|
-
// Immutable chain methods — each returns a new component with merged config.
|
|
156
|
-
return Object.assign(Component, {
|
|
157
|
-
preset: (preset: Record<string, unknown>) =>
|
|
158
|
-
createKineticComponent<Tag, Mode>({
|
|
159
|
-
...config,
|
|
160
|
-
...preset,
|
|
161
|
-
} as KineticConfig),
|
|
162
|
-
|
|
163
|
-
enter: (styles: CSSProperties) =>
|
|
164
|
-
createKineticComponent<Tag, Mode>({ ...config, enterStyle: styles }),
|
|
165
|
-
|
|
166
|
-
enterTo: (styles: CSSProperties) =>
|
|
167
|
-
createKineticComponent<Tag, Mode>({ ...config, enterToStyle: styles }),
|
|
168
|
-
|
|
169
|
-
enterTransition: (value: string) =>
|
|
170
|
-
createKineticComponent<Tag, Mode>({ ...config, enterTransition: value }),
|
|
171
|
-
|
|
172
|
-
leave: (styles: CSSProperties) =>
|
|
173
|
-
createKineticComponent<Tag, Mode>({ ...config, leaveStyle: styles }),
|
|
174
|
-
|
|
175
|
-
leaveTo: (styles: CSSProperties) =>
|
|
176
|
-
createKineticComponent<Tag, Mode>({ ...config, leaveToStyle: styles }),
|
|
177
|
-
|
|
178
|
-
leaveTransition: (value: string) =>
|
|
179
|
-
createKineticComponent<Tag, Mode>({ ...config, leaveTransition: value }),
|
|
180
|
-
|
|
181
|
-
enterClass: ({ active, from, to }: ClassConfig) =>
|
|
182
|
-
createKineticComponent<Tag, Mode>({
|
|
183
|
-
...config,
|
|
184
|
-
enter: active,
|
|
185
|
-
enterFrom: from,
|
|
186
|
-
enterTo: to,
|
|
187
|
-
}),
|
|
188
|
-
|
|
189
|
-
leaveClass: ({ active, from, to }: ClassConfig) =>
|
|
190
|
-
createKineticComponent<Tag, Mode>({
|
|
191
|
-
...config,
|
|
192
|
-
leave: active,
|
|
193
|
-
leaveFrom: from,
|
|
194
|
-
leaveTo: to,
|
|
195
|
-
}),
|
|
196
|
-
|
|
197
|
-
config: (opts: Record<string, unknown>) =>
|
|
198
|
-
createKineticComponent<Tag, Mode>({
|
|
199
|
-
...config,
|
|
200
|
-
...opts,
|
|
201
|
-
} as KineticConfig),
|
|
202
|
-
|
|
203
|
-
on: (cbs: Partial<TransitionCallbacks>) =>
|
|
204
|
-
createKineticComponent<Tag, Mode>({ ...config, ...cbs }),
|
|
205
|
-
|
|
206
|
-
collapse: (opts?: { transition?: string }) =>
|
|
207
|
-
createKineticComponent<Tag, 'collapse'>({
|
|
208
|
-
...config,
|
|
209
|
-
mode: 'collapse',
|
|
210
|
-
...opts,
|
|
211
|
-
}),
|
|
212
|
-
|
|
213
|
-
stagger: (opts?: { interval?: number; reverseLeave?: boolean }) =>
|
|
214
|
-
createKineticComponent<Tag, 'stagger'>({
|
|
215
|
-
...config,
|
|
216
|
-
mode: 'stagger',
|
|
217
|
-
...opts,
|
|
218
|
-
}),
|
|
219
|
-
|
|
220
|
-
group: () => createKineticComponent<Tag, 'group'>({ ...config, mode: 'group' }),
|
|
221
|
-
}) as unknown as KineticComponent<Tag, Mode>
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
export default createKineticComponent
|
package/src/kinetic/types.ts
DELETED
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import type { ComponentFn, VNodeChild } from '@pyreon/core'
|
|
2
|
-
import type {
|
|
3
|
-
ClassTransitionProps,
|
|
4
|
-
CSSProperties,
|
|
5
|
-
StyleTransitionProps,
|
|
6
|
-
TransitionCallbacks,
|
|
7
|
-
} from '../types'
|
|
8
|
-
|
|
9
|
-
// ─── Kinetic Modes ────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
export type KineticMode = 'transition' | 'collapse' | 'stagger' | 'group'
|
|
12
|
-
|
|
13
|
-
// ─── Internal Config (accumulated through chaining) ──────
|
|
14
|
-
|
|
15
|
-
export type KineticConfig = StyleTransitionProps &
|
|
16
|
-
ClassTransitionProps &
|
|
17
|
-
TransitionCallbacks & {
|
|
18
|
-
tag: string
|
|
19
|
-
mode: KineticMode
|
|
20
|
-
appear?: boolean | undefined
|
|
21
|
-
unmount?: boolean | undefined
|
|
22
|
-
timeout?: number | undefined
|
|
23
|
-
/** Collapse: CSS transition for height. */
|
|
24
|
-
transition?: string | undefined
|
|
25
|
-
/** Stagger: delay between each child in ms. */
|
|
26
|
-
interval?: number | undefined
|
|
27
|
-
/** Stagger: reverse order on leave. */
|
|
28
|
-
reverseLeave?: boolean | undefined
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// ─── Class Config (for .enterClass / .leaveClass) ────────
|
|
32
|
-
|
|
33
|
-
export type ClassConfig = {
|
|
34
|
-
active?: string | undefined
|
|
35
|
-
from?: string | undefined
|
|
36
|
-
to?: string | undefined
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// ─── Mode-specific config options for .config() ──────────
|
|
40
|
-
|
|
41
|
-
export type TransitionConfigOpts = {
|
|
42
|
-
appear?: boolean | undefined
|
|
43
|
-
unmount?: boolean | undefined
|
|
44
|
-
timeout?: number | undefined
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type CollapseConfigOpts = {
|
|
48
|
-
appear?: boolean | undefined
|
|
49
|
-
timeout?: number | undefined
|
|
50
|
-
transition?: string | undefined
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export type StaggerConfigOpts = {
|
|
54
|
-
appear?: boolean | undefined
|
|
55
|
-
timeout?: number | undefined
|
|
56
|
-
interval?: number | undefined
|
|
57
|
-
reverseLeave?: boolean | undefined
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export type GroupConfigOpts = {
|
|
61
|
-
appear?: boolean | undefined
|
|
62
|
-
timeout?: number | undefined
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ─── Mode-specific component props ───────────────────────
|
|
66
|
-
|
|
67
|
-
export type KineticTransitionProps<_Tag extends string> = Record<string, unknown> & {
|
|
68
|
-
show: () => boolean
|
|
69
|
-
appear?: boolean | undefined
|
|
70
|
-
unmount?: boolean | undefined
|
|
71
|
-
timeout?: number | undefined
|
|
72
|
-
children?: VNodeChild | undefined
|
|
73
|
-
} & Partial<TransitionCallbacks>
|
|
74
|
-
|
|
75
|
-
export type KineticCollapseProps<_Tag extends string> = Record<string, unknown> & {
|
|
76
|
-
show: () => boolean
|
|
77
|
-
appear?: boolean | undefined
|
|
78
|
-
timeout?: number | undefined
|
|
79
|
-
transition?: string | undefined
|
|
80
|
-
children?: VNodeChild | undefined
|
|
81
|
-
} & Partial<TransitionCallbacks>
|
|
82
|
-
|
|
83
|
-
export type KineticStaggerProps<_Tag extends string> = Record<string, unknown> & {
|
|
84
|
-
show: () => boolean
|
|
85
|
-
appear?: boolean | undefined
|
|
86
|
-
timeout?: number | undefined
|
|
87
|
-
interval?: number | undefined
|
|
88
|
-
reverseLeave?: boolean | undefined
|
|
89
|
-
children: VNodeChild
|
|
90
|
-
} & Partial<TransitionCallbacks>
|
|
91
|
-
|
|
92
|
-
export type KineticGroupProps<_Tag extends string> = Record<string, unknown> & {
|
|
93
|
-
appear?: boolean | undefined
|
|
94
|
-
timeout?: number | undefined
|
|
95
|
-
children: VNodeChild
|
|
96
|
-
} & Partial<TransitionCallbacks>
|
|
97
|
-
|
|
98
|
-
// ─── Conditional props based on mode ─────────────────────
|
|
99
|
-
|
|
100
|
-
export type KineticComponentProps<
|
|
101
|
-
Tag extends string,
|
|
102
|
-
Mode extends KineticMode,
|
|
103
|
-
> = Mode extends 'collapse'
|
|
104
|
-
? KineticCollapseProps<Tag>
|
|
105
|
-
: Mode extends 'stagger'
|
|
106
|
-
? KineticStaggerProps<Tag>
|
|
107
|
-
: Mode extends 'group'
|
|
108
|
-
? KineticGroupProps<Tag>
|
|
109
|
-
: KineticTransitionProps<Tag>
|
|
110
|
-
|
|
111
|
-
// ─── Conditional config opts based on mode ───────────────
|
|
112
|
-
|
|
113
|
-
type ConfigOpts<Mode extends KineticMode> = Mode extends 'collapse'
|
|
114
|
-
? CollapseConfigOpts
|
|
115
|
-
: Mode extends 'stagger'
|
|
116
|
-
? StaggerConfigOpts
|
|
117
|
-
: Mode extends 'group'
|
|
118
|
-
? GroupConfigOpts
|
|
119
|
-
: TransitionConfigOpts
|
|
120
|
-
|
|
121
|
-
// ─── Chain methods ───────────────────────────────────────
|
|
122
|
-
|
|
123
|
-
export type KineticChain<Tag extends string, Mode extends KineticMode> = {
|
|
124
|
-
displayName: string
|
|
125
|
-
preset: (preset: StyleTransitionProps & ClassTransitionProps) => KineticComponent<Tag, Mode>
|
|
126
|
-
enter: (styles: CSSProperties) => KineticComponent<Tag, Mode>
|
|
127
|
-
enterTo: (styles: CSSProperties) => KineticComponent<Tag, Mode>
|
|
128
|
-
enterTransition: (value: string) => KineticComponent<Tag, Mode>
|
|
129
|
-
leave: (styles: CSSProperties) => KineticComponent<Tag, Mode>
|
|
130
|
-
leaveTo: (styles: CSSProperties) => KineticComponent<Tag, Mode>
|
|
131
|
-
leaveTransition: (value: string) => KineticComponent<Tag, Mode>
|
|
132
|
-
enterClass: (opts: ClassConfig) => KineticComponent<Tag, Mode>
|
|
133
|
-
leaveClass: (opts: ClassConfig) => KineticComponent<Tag, Mode>
|
|
134
|
-
config: (opts: ConfigOpts<Mode>) => KineticComponent<Tag, Mode>
|
|
135
|
-
on: (callbacks: Partial<TransitionCallbacks>) => KineticComponent<Tag, Mode>
|
|
136
|
-
collapse: (opts?: CollapseConfigOpts) => KineticComponent<Tag, 'collapse'>
|
|
137
|
-
stagger: (opts?: {
|
|
138
|
-
interval?: number | undefined
|
|
139
|
-
reverseLeave?: boolean | undefined
|
|
140
|
-
}) => KineticComponent<Tag, 'stagger'>
|
|
141
|
-
group: () => KineticComponent<Tag, 'group'>
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// ─── The full kinetic component: renderable + chainable ───
|
|
145
|
-
|
|
146
|
-
export type KineticComponent<
|
|
147
|
-
Tag extends string,
|
|
148
|
-
Mode extends KineticMode = 'transition',
|
|
149
|
-
> = ComponentFn<KineticComponentProps<Tag, Mode>> & KineticChain<Tag, Mode>
|
package/src/kinetic.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import createKineticComponent from './kinetic/createKineticComponent'
|
|
2
|
-
import type { KineticComponent } from './kinetic/types'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a reusable animated component via immutable chaining.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```tsx
|
|
9
|
-
* // Transition (default)
|
|
10
|
-
* const FadeDiv = kinetic('div').preset(fade)
|
|
11
|
-
*
|
|
12
|
-
* // Collapse
|
|
13
|
-
* const Accordion = kinetic('div').collapse()
|
|
14
|
-
*
|
|
15
|
-
* // Stagger
|
|
16
|
-
* const StaggerList = kinetic('ul').preset(slideUp).stagger({ interval: 50 })
|
|
17
|
-
*
|
|
18
|
-
* // Group (key-based enter/exit)
|
|
19
|
-
* const AnimatedList = kinetic('ul').preset(fade).group()
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
const kinetic = <Tag extends string>(tag: Tag): KineticComponent<Tag, 'transition'> =>
|
|
23
|
-
createKineticComponent<Tag, 'transition'>({ tag, mode: 'transition' })
|
|
24
|
-
|
|
25
|
-
export default kinetic
|
package/src/presets.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import type { ClassTransitionProps, StyleTransitionProps } from './types'
|
|
2
|
-
|
|
3
|
-
export type Preset = StyleTransitionProps & ClassTransitionProps
|
|
4
|
-
|
|
5
|
-
export const fade: Preset = {
|
|
6
|
-
enterStyle: { opacity: 0 },
|
|
7
|
-
enterToStyle: { opacity: 1 },
|
|
8
|
-
enterTransition: 'opacity 300ms ease-out',
|
|
9
|
-
leaveStyle: { opacity: 1 },
|
|
10
|
-
leaveToStyle: { opacity: 0 },
|
|
11
|
-
leaveTransition: 'opacity 200ms ease-in',
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const scaleIn: Preset = {
|
|
15
|
-
enterStyle: { opacity: 0, transform: 'scale(0.95)' },
|
|
16
|
-
enterToStyle: { opacity: 1, transform: 'scale(1)' },
|
|
17
|
-
enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',
|
|
18
|
-
leaveStyle: { opacity: 1, transform: 'scale(1)' },
|
|
19
|
-
leaveToStyle: { opacity: 0, transform: 'scale(0.95)' },
|
|
20
|
-
leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export const slideUp: Preset = {
|
|
24
|
-
enterStyle: { opacity: 0, transform: 'translateY(16px)' },
|
|
25
|
-
enterToStyle: { opacity: 1, transform: 'translateY(0)' },
|
|
26
|
-
enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',
|
|
27
|
-
leaveStyle: { opacity: 1, transform: 'translateY(0)' },
|
|
28
|
-
leaveToStyle: { opacity: 0, transform: 'translateY(16px)' },
|
|
29
|
-
leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export const slideDown: Preset = {
|
|
33
|
-
enterStyle: { opacity: 0, transform: 'translateY(-16px)' },
|
|
34
|
-
enterToStyle: { opacity: 1, transform: 'translateY(0)' },
|
|
35
|
-
enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',
|
|
36
|
-
leaveStyle: { opacity: 1, transform: 'translateY(0)' },
|
|
37
|
-
leaveToStyle: { opacity: 0, transform: 'translateY(-16px)' },
|
|
38
|
-
leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export const slideLeft: Preset = {
|
|
42
|
-
enterStyle: { opacity: 0, transform: 'translateX(16px)' },
|
|
43
|
-
enterToStyle: { opacity: 1, transform: 'translateX(0)' },
|
|
44
|
-
enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',
|
|
45
|
-
leaveStyle: { opacity: 1, transform: 'translateX(0)' },
|
|
46
|
-
leaveToStyle: { opacity: 0, transform: 'translateX(16px)' },
|
|
47
|
-
leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export const slideRight: Preset = {
|
|
51
|
-
enterStyle: { opacity: 0, transform: 'translateX(-16px)' },
|
|
52
|
-
enterToStyle: { opacity: 1, transform: 'translateX(0)' },
|
|
53
|
-
enterTransition: 'opacity 300ms ease-out, transform 300ms ease-out',
|
|
54
|
-
leaveStyle: { opacity: 1, transform: 'translateX(0)' },
|
|
55
|
-
leaveToStyle: { opacity: 0, transform: 'translateX(-16px)' },
|
|
56
|
-
leaveTransition: 'opacity 200ms ease-in, transform 200ms ease-in',
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export const presets = {
|
|
60
|
-
fade,
|
|
61
|
-
scaleIn,
|
|
62
|
-
slideUp,
|
|
63
|
-
slideDown,
|
|
64
|
-
slideLeft,
|
|
65
|
-
slideRight,
|
|
66
|
-
} as const
|
package/src/types.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import type { Ref, VNode } from '@pyreon/core'
|
|
2
|
-
import type { Signal } from '@pyreon/reactivity'
|
|
3
|
-
|
|
4
|
-
export type CSSProperties = Record<string, string | number | undefined>
|
|
5
|
-
|
|
6
|
-
/** Internal lifecycle stages of a transition. */
|
|
7
|
-
export type TransitionStage = 'hidden' | 'entering' | 'entered' | 'leaving'
|
|
8
|
-
|
|
9
|
-
/** Class-based transition definition. */
|
|
10
|
-
export type ClassTransitionProps = {
|
|
11
|
-
/** Classes applied during the entire enter phase */
|
|
12
|
-
enter?: string | undefined
|
|
13
|
-
/** Classes applied on first frame of enter, removed on next frame */
|
|
14
|
-
enterFrom?: string | undefined
|
|
15
|
-
/** Classes applied on second frame of enter, kept until complete */
|
|
16
|
-
enterTo?: string | undefined
|
|
17
|
-
/** Classes applied during the entire leave phase */
|
|
18
|
-
leave?: string | undefined
|
|
19
|
-
/** Classes applied on first frame of leave */
|
|
20
|
-
leaveFrom?: string | undefined
|
|
21
|
-
/** Classes applied on second frame of leave, kept until complete */
|
|
22
|
-
leaveTo?: string | undefined
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Style-object transition definition (zero-CSS option). */
|
|
26
|
-
export type StyleTransitionProps = {
|
|
27
|
-
/** Inline styles for the start of enter */
|
|
28
|
-
enterStyle?: CSSProperties | undefined
|
|
29
|
-
/** Inline styles for the end of enter */
|
|
30
|
-
enterToStyle?: CSSProperties | undefined
|
|
31
|
-
/** CSS transition shorthand applied during enter */
|
|
32
|
-
enterTransition?: string | undefined
|
|
33
|
-
/** Inline styles for the start of leave */
|
|
34
|
-
leaveStyle?: CSSProperties | undefined
|
|
35
|
-
/** Inline styles for the end of leave */
|
|
36
|
-
leaveToStyle?: CSSProperties | undefined
|
|
37
|
-
/** CSS transition shorthand applied during leave */
|
|
38
|
-
leaveTransition?: string | undefined
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** Lifecycle callbacks. */
|
|
42
|
-
export type TransitionCallbacks = {
|
|
43
|
-
/** Called immediately when entering begins */
|
|
44
|
-
onEnter?: (() => void) | undefined
|
|
45
|
-
/** Called when enter animation completes */
|
|
46
|
-
onAfterEnter?: (() => void) | undefined
|
|
47
|
-
/** Called immediately when leaving begins */
|
|
48
|
-
onLeave?: (() => void) | undefined
|
|
49
|
-
/** Called when leave animation completes */
|
|
50
|
-
onAfterLeave?: (() => void) | undefined
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export type TransitionProps = ClassTransitionProps &
|
|
54
|
-
StyleTransitionProps &
|
|
55
|
-
TransitionCallbacks & {
|
|
56
|
-
/** Reactive accessor controlling visibility. true = enter, false = leave + unmount. */
|
|
57
|
-
show: () => boolean
|
|
58
|
-
/** If true, runs enter animation on initial mount. Default: false. */
|
|
59
|
-
appear?: boolean | undefined
|
|
60
|
-
/** If true (default), unmounts when hidden. If false, keeps with display:none. */
|
|
61
|
-
unmount?: boolean | undefined
|
|
62
|
-
/** Safety timeout in ms. Default: 5000. */
|
|
63
|
-
timeout?: number | undefined
|
|
64
|
-
/** Single child element. Must accept ref. */
|
|
65
|
-
children: VNode
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export type TransitionGroupProps = ClassTransitionProps &
|
|
69
|
-
StyleTransitionProps &
|
|
70
|
-
TransitionCallbacks & {
|
|
71
|
-
/** If true, animates initial children on mount. Default: false. */
|
|
72
|
-
appear?: boolean | undefined
|
|
73
|
-
/** Safety timeout in ms. Default: 5000. */
|
|
74
|
-
timeout?: number | undefined
|
|
75
|
-
/** Children with unique keys. */
|
|
76
|
-
children: VNode[]
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type StaggerProps = ClassTransitionProps &
|
|
80
|
-
StyleTransitionProps &
|
|
81
|
-
TransitionCallbacks & {
|
|
82
|
-
/** Reactive accessor controlling visibility of all children. */
|
|
83
|
-
show: () => boolean
|
|
84
|
-
/** Delay between each child's animation start in ms. Default: 50. */
|
|
85
|
-
interval?: number | undefined
|
|
86
|
-
/** If true, reverses stagger order on leave. Default: false. */
|
|
87
|
-
reverseLeave?: boolean | undefined
|
|
88
|
-
/** If true, animates on initial mount. Default: false. */
|
|
89
|
-
appear?: boolean | undefined
|
|
90
|
-
/** Safety timeout in ms. Default: 5000. */
|
|
91
|
-
timeout?: number | undefined
|
|
92
|
-
/** Children to stagger. */
|
|
93
|
-
children: VNode[]
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export type CollapseProps = TransitionCallbacks & {
|
|
97
|
-
/** Reactive accessor controlling expanded/collapsed state. */
|
|
98
|
-
show: () => boolean
|
|
99
|
-
/** CSS transition for height. Default: "height 300ms ease". */
|
|
100
|
-
transition?: string | undefined
|
|
101
|
-
/** If true, animates on initial mount. Default: false. */
|
|
102
|
-
appear?: boolean | undefined
|
|
103
|
-
/** Safety timeout in ms. Default: 5000. */
|
|
104
|
-
timeout?: number | undefined
|
|
105
|
-
/** The content to collapse. */
|
|
106
|
-
children: VNode
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export type TransitionStateResult = {
|
|
110
|
-
/** Current lifecycle stage (signal) */
|
|
111
|
-
stage: Signal<TransitionStage>
|
|
112
|
-
/** Ref callback to attach to the transitioning element */
|
|
113
|
-
ref: Ref<HTMLElement> | ((node: HTMLElement | null) => void)
|
|
114
|
-
/** Reactive accessor: whether the element should be rendered */
|
|
115
|
-
shouldMount: () => boolean
|
|
116
|
-
/** Call when the current animation finishes */
|
|
117
|
-
complete: () => void
|
|
118
|
-
}
|
package/src/useAnimationEnd.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type { Ref } from '@pyreon/core'
|
|
2
|
-
import { watch } from '@pyreon/reactivity'
|
|
3
|
-
|
|
4
|
-
const DEFAULT_TIMEOUT = 5000
|
|
5
|
-
|
|
6
|
-
export type UseAnimationEnd = (options: {
|
|
7
|
-
ref: Ref<HTMLElement>
|
|
8
|
-
onEnd: () => void
|
|
9
|
-
active: () => boolean
|
|
10
|
-
timeout?: number | undefined
|
|
11
|
-
}) => void
|
|
12
|
-
|
|
13
|
-
const useAnimationEnd: UseAnimationEnd = ({ ref, onEnd, active, timeout = DEFAULT_TIMEOUT }) => {
|
|
14
|
-
let called = false
|
|
15
|
-
|
|
16
|
-
watch(
|
|
17
|
-
active,
|
|
18
|
-
(isActive) => {
|
|
19
|
-
if (!isActive) {
|
|
20
|
-
called = false
|
|
21
|
-
return
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const el = ref.current
|
|
25
|
-
if (!el) return
|
|
26
|
-
|
|
27
|
-
called = false
|
|
28
|
-
|
|
29
|
-
const done = () => {
|
|
30
|
-
if (called) return
|
|
31
|
-
called = true
|
|
32
|
-
el.removeEventListener('transitionend', handleEnd)
|
|
33
|
-
el.removeEventListener('animationend', handleEnd)
|
|
34
|
-
clearTimeout(timer)
|
|
35
|
-
onEnd()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const handleEnd = (e: Event) => {
|
|
39
|
-
// Ignore bubbled events from children
|
|
40
|
-
if (e.target !== el) return
|
|
41
|
-
done()
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
el.addEventListener('transitionend', handleEnd)
|
|
45
|
-
el.addEventListener('animationend', handleEnd)
|
|
46
|
-
|
|
47
|
-
const timer = setTimeout(done, timeout)
|
|
48
|
-
|
|
49
|
-
return () => {
|
|
50
|
-
el.removeEventListener('transitionend', handleEnd)
|
|
51
|
-
el.removeEventListener('animationend', handleEnd)
|
|
52
|
-
clearTimeout(timer)
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
{ immediate: true },
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default useAnimationEnd
|
package/src/useReducedMotion.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { onMount, onUnmount } from '@pyreon/core'
|
|
2
|
-
import { signal } from '@pyreon/reactivity'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Inline reduced-motion check for kinetic package.
|
|
6
|
-
* Avoids depending on @pyreon/hooks for a single media query.
|
|
7
|
-
*/
|
|
8
|
-
export function useReducedMotion(): () => boolean {
|
|
9
|
-
const matches = signal(false)
|
|
10
|
-
let mql: MediaQueryList | undefined
|
|
11
|
-
|
|
12
|
-
const onChange = (e: MediaQueryListEvent) => {
|
|
13
|
-
matches.set(e.matches)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
onMount(() => {
|
|
17
|
-
mql = window.matchMedia('(prefers-reduced-motion: reduce)')
|
|
18
|
-
matches.set(mql.matches)
|
|
19
|
-
mql.addEventListener('change', onChange)
|
|
20
|
-
return undefined
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
onUnmount(() => {
|
|
24
|
-
mql?.removeEventListener('change', onChange)
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
return matches
|
|
28
|
-
}
|