@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.
Files changed (37) hide show
  1. package/package.json +10 -12
  2. package/src/Collapse.tsx +0 -166
  3. package/src/Stagger.tsx +0 -63
  4. package/src/Transition.tsx +0 -280
  5. package/src/TransitionGroup.tsx +0 -139
  6. package/src/__tests__/Collapse.test.tsx +0 -803
  7. package/src/__tests__/GroupRenderer.test.tsx +0 -434
  8. package/src/__tests__/StaggerRenderer.test.tsx +0 -523
  9. package/src/__tests__/Transition.ssr.test.tsx +0 -183
  10. package/src/__tests__/Transition.test.tsx +0 -403
  11. package/src/__tests__/TransitionItem.test.tsx +0 -514
  12. package/src/__tests__/kinetic-modes.ssr.test.tsx +0 -214
  13. package/src/__tests__/kinetic.browser.test.tsx +0 -327
  14. package/src/__tests__/kinetic.test.tsx +0 -565
  15. package/src/__tests__/presets.test.ts +0 -46
  16. package/src/__tests__/stagger-component-children-hydration.test.tsx +0 -191
  17. package/src/__tests__/top-level-transition-stagger-function-children.test.tsx +0 -141
  18. package/src/__tests__/useAnimationEnd.test.ts +0 -194
  19. package/src/__tests__/useReducedMotion.test.ts +0 -160
  20. package/src/__tests__/useTransitionState.test.ts +0 -132
  21. package/src/__tests__/utils.test.ts +0 -139
  22. package/src/index.ts +0 -15
  23. package/src/jsx-augment.d.ts +0 -12
  24. package/src/kinetic/CollapseRenderer.tsx +0 -216
  25. package/src/kinetic/GroupRenderer.tsx +0 -149
  26. package/src/kinetic/StaggerRenderer.tsx +0 -94
  27. package/src/kinetic/TransitionItem.tsx +0 -250
  28. package/src/kinetic/TransitionRenderer.tsx +0 -230
  29. package/src/kinetic/createKineticComponent.tsx +0 -224
  30. package/src/kinetic/types.ts +0 -149
  31. package/src/kinetic.ts +0 -25
  32. package/src/presets.ts +0 -66
  33. package/src/types.ts +0 -118
  34. package/src/useAnimationEnd.ts +0 -59
  35. package/src/useReducedMotion.ts +0 -28
  36. package/src/useTransitionState.ts +0 -62
  37. package/src/utils.ts +0 -113
@@ -1,62 +0,0 @@
1
- import { createRef } from '@pyreon/core'
2
- import { runUntracked, signal, watch } from '@pyreon/reactivity'
3
- import type { TransitionStage, TransitionStateResult } from './types'
4
-
5
- export type UseTransitionState = (options: {
6
- show: () => boolean
7
- appear?: boolean | undefined
8
- }) => TransitionStateResult
9
-
10
- const useTransitionState: UseTransitionState = ({ show, appear = false }) => {
11
- const initialShow = show()
12
- // When appear=true and show starts true, mount the element (stage='entered')
13
- // but defer the enter animation until the ref is connected.
14
- const needsAppear = appear && initialShow
15
- const stage = signal<TransitionStage>(initialShow ? 'entered' : 'hidden')
16
- const elementRef = createRef<HTMLElement>()
17
- let isInitialMount = true
18
- let appearTriggered = false
19
-
20
- // Ref callback that triggers the appear animation once the element is wired
21
- const refCallback = (node: HTMLElement | null) => {
22
- elementRef.current = node
23
- if (node && needsAppear && !appearTriggered) {
24
- appearTriggered = true
25
- stage.set('entering')
26
- }
27
- }
28
-
29
- watch(
30
- show,
31
- (showVal) => {
32
- if (isInitialMount) {
33
- isInitialMount = false
34
- // appear case is handled by refCallback above
35
- return
36
- }
37
-
38
- const currentStage = runUntracked(() => stage())
39
- if (showVal && (currentStage === 'hidden' || currentStage === 'leaving')) {
40
- stage.set('entering')
41
- } else if (!showVal && (currentStage === 'entered' || currentStage === 'entering')) {
42
- stage.set('leaving')
43
- }
44
- },
45
- { immediate: true },
46
- )
47
-
48
- const complete = () => {
49
- const current = stage()
50
- if (current === 'entering') stage.set('entered')
51
- if (current === 'leaving') stage.set('hidden')
52
- }
53
-
54
- return {
55
- stage,
56
- ref: refCallback,
57
- shouldMount: () => stage() !== 'hidden',
58
- complete,
59
- }
60
- }
61
-
62
- export default useTransitionState
package/src/utils.ts DELETED
@@ -1,113 +0,0 @@
1
- import type { Ref, VNode } from '@pyreon/core'
2
- import type { CSSProperties } from './types'
3
-
4
- const splitCache = new Map<string, string[]>()
5
- const splitClasses = (classes: string): string[] => {
6
- let cached = splitCache.get(classes)
7
- if (!cached) {
8
- cached = classes.split(/\s+/).filter(Boolean)
9
- splitCache.set(classes, cached)
10
- }
11
- return cached
12
- }
13
-
14
- /** Adds space-separated CSS classes to an element. */
15
- export const addClasses = (el: HTMLElement, classes: string | undefined) => {
16
- if (!classes) return
17
- const list = splitClasses(classes)
18
- if (list.length > 0) el.classList.add(...list)
19
- }
20
-
21
- /** Removes space-separated CSS classes from an element. */
22
- export const removeClasses = (el: HTMLElement, classes: string | undefined) => {
23
- if (!classes) return
24
- const list = splitClasses(classes)
25
- if (list.length > 0) el.classList.remove(...list)
26
- }
27
-
28
- /**
29
- * Executes callback after two animation frames (double-rAF).
30
- * Ensures the browser paints the current state before applying changes,
31
- * which is required for CSS transitions to trigger. Returns 0 on SSR —
32
- * the typeof-window guard makes the SSR-safety contract explicit (callers
33
- * are always browser-only via `onMount`, but the rule can't AST-trace it).
34
- */
35
- export const nextFrame = (callback: () => void): number => {
36
- if (typeof requestAnimationFrame === 'undefined') return 0
37
- return requestAnimationFrame(() => {
38
- requestAnimationFrame(callback)
39
- })
40
- }
41
-
42
- /** Merges two className strings, filtering undefined/empty. */
43
- export const mergeClassNames = (
44
- existing: string | undefined,
45
- additional: string | undefined,
46
- ): string | undefined => {
47
- const parts = [existing, additional].filter(Boolean)
48
- return parts.length > 0 ? parts.join(' ') : undefined
49
- }
50
-
51
- /** Merges two CSSProperties objects, with `b` taking precedence. */
52
- export const mergeStyles = (
53
- a: CSSProperties | undefined,
54
- b: CSSProperties | undefined,
55
- ): CSSProperties | undefined => {
56
- if (!a && !b) return undefined
57
- if (!a) return b
58
- if (!b) return a
59
- return { ...a, ...b }
60
- }
61
-
62
- // ─── Ref & Motion Utilities ─────────────────────────────────
63
-
64
- type RefCallback<T> = (node: T | null) => void
65
- type RefLike<T> = RefCallback<T> | Ref<T>
66
-
67
- /** Merges multiple refs (callback or object) into a single callback ref. */
68
- export const mergeRefs = <T>(...refs: (RefLike<T> | undefined)[]): ((node: T | null) => void) => {
69
- return (node: T | null) => {
70
- for (const ref of refs) {
71
- if (!ref) continue
72
- if (typeof ref === 'function') {
73
- ref(node)
74
- } else {
75
- ;(ref as { current: unknown }).current = node
76
- }
77
- }
78
- }
79
- }
80
-
81
- /** Clones a VNode with merged props. */
82
- export const cloneVNode = (vnode: VNode, extraProps: Record<string, unknown>): VNode => ({
83
- ...vnode,
84
- props: { ...vnode.props, ...extraProps },
85
- })
86
-
87
- /**
88
- * Resolves a `children` value the Pyreon compiler may have wrapped in a
89
- * deferred accessor.
90
- *
91
- * **Why:** the compiler's prop-inlining pass rewrites `<Comp>{children}</Comp>`
92
- * to `Comp({ ..., children: () => <inlined-expression> })` whenever
93
- * `children` is a local `const` derived from a getter-shaped binding
94
- * (`const children = childHolder.children` after `splitProps`). DOM-side
95
- * consumers route through `mountChild` which already treats function
96
- * children as reactive accessors, so the wrap is invisible there. Kinetic's
97
- * Stagger/Group/Transition/Collapse renderers iterate `children` directly
98
- * at the VNode level (to build per-child `TransitionItem`s), so a wrapped
99
- * function landed in `Array.isArray(children) ? children : [children]` as
100
- * `[function]` → `.filter(isVNode)` → `[]` → the rendered `<div>` had zero
101
- * children → SSR content vanished post-hydration. Reproducer:
102
- * `examples/bokisch.com`'s Intro section with `kinetic('div').stagger()`
103
- * + `appear` + `show={() => true}` + component children → SSG HTML had
104
- * `<h1>Hello</h1>`, post-hydrate the entire subtree was replaced by
105
- * `<!--pyreon-->` markers.
106
- *
107
- * Kinetic deliberately snapshots children at render time (animation state
108
- * is per-item, built once) — it does NOT observe children changes after
109
- * the initial render. Eagerly unwrapping the function matches that
110
- * contract; no reactivity is lost.
111
- */
112
- export const resolveChildren = <T>(children: T | (() => T)): T =>
113
- (typeof children === 'function' ? (children as () => T)() : children) as T