@pyreon/kinetic 0.11.4 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,15 +10,16 @@ The result: GPU-composited 60/120 FPS animations with a 3.2KB footprint.
10
10
 
11
11
  ### How It Compares
12
12
 
13
- | Library | Gzipped | Engine | Enter/Exit | Stagger | List Recon. | Collapse | Reduced Motion |
14
- | ------- | ------- | ------ | ---------- | ------- | ----------- | -------- | -------------- |
15
- | **@pyreon/kinetic** | **3.2 KB** | CSS transitions | Yes | Yes | Yes | Yes | Yes |
16
- | Motion (framer-motion) | ~34 KB | JS (rAF + WAAPI) | Yes | Yes | Yes | Quirky | Yes |
17
- | @react-spring/web | ~16-24 KB | JS (spring physics) | Yes | Partial | Yes | Manual | Yes |
18
- | react-transition-group | ~5 KB | CSS classes | Yes | No | Yes | No | No |
19
- | AutoAnimate | ~2.5 KB | JS (FLIP) | Yes | No | Yes | No | Yes |
13
+ | Library | Gzipped | Engine | Enter/Exit | Stagger | List Recon. | Collapse | Reduced Motion |
14
+ | ---------------------- | ---------- | ------------------- | ---------- | ------- | ----------- | -------- | -------------- |
15
+ | **@pyreon/kinetic** | **3.2 KB** | CSS transitions | Yes | Yes | Yes | Yes | Yes |
16
+ | Motion (framer-motion) | ~34 KB | JS (rAF + WAAPI) | Yes | Yes | Yes | Quirky | Yes |
17
+ | @react-spring/web | ~16-24 KB | JS (spring physics) | Yes | Partial | Yes | Manual | Yes |
18
+ | react-transition-group | ~5 KB | CSS classes | Yes | No | Yes | No | No |
19
+ | AutoAnimate | ~2.5 KB | JS (FLIP) | Yes | No | Yes | No | Yes |
20
20
 
21
21
  **Key advantages:**
22
+
22
23
  - **10x smaller than Motion** for CSS-transition use cases
23
24
  - **CSS-first**: `transform`/`opacity` run on GPU compositor thread, not main thread
24
25
  - **Only library** combining CSS transitions + stagger + collapse + list reconciliation
@@ -53,9 +54,9 @@ FadeDiv({ show: show(), children: 'Hello, world!' })
53
54
  Creates an animated component. `tag` can be any HTML element string or Pyreon component.
54
55
 
55
56
  ```ts
56
- kinetic('div') // HTML element
57
- kinetic('section') // Any HTML tag
58
- kinetic(MyComponent) // Pyreon component
57
+ kinetic('div') // HTML element
58
+ kinetic('section') // Any HTML tag
59
+ kinetic(MyComponent) // Pyreon component
59
60
  ```
60
61
 
61
62
  Returns a renderable Pyreon component with chain methods attached. Default mode: **transition**.
@@ -109,7 +110,7 @@ Height animation with `overflow: hidden`. Measures `scrollHeight` automatically.
109
110
  ```ts
110
111
  const Accordion = kinetic('div').collapse()
111
112
  const FancyAccordion = kinetic('section').collapse({
112
- transition: 'height 400ms cubic-bezier(0.4, 0, 0.2, 1)'
113
+ transition: 'height 400ms cubic-bezier(0.4, 0, 0.2, 1)',
113
114
  })
114
115
 
115
116
  Accordion({ show: isExpanded, children: 'Expandable content' })
@@ -122,11 +123,14 @@ Staggered entrance/exit for child elements.
122
123
  ```ts
123
124
  const StaggerList = kinetic('ul').preset(slideUp).stagger({ interval: 75 })
124
125
 
125
- StaggerList({ show: isVisible, children: [
126
- h('li', { key: '1' }, 'Item 1'),
127
- h('li', { key: '2' }, 'Item 2'),
128
- h('li', { key: '3' }, 'Item 3'),
129
- ]})
126
+ StaggerList({
127
+ show: isVisible,
128
+ children: [
129
+ h('li', { key: '1' }, 'Item 1'),
130
+ h('li', { key: '2' }, 'Item 2'),
131
+ h('li', { key: '3' }, 'Item 3'),
132
+ ],
133
+ })
130
134
  ```
131
135
 
132
136
  #### Group
@@ -136,9 +140,7 @@ Key-based enter/exit — adding a child triggers enter animation, removing trigg
136
140
  ```ts
137
141
  const AnimatedList = kinetic('ul').preset(fade).group()
138
142
 
139
- AnimatedList({ children: items.map(item =>
140
- h('li', { key: item.id }, item.text)
141
- )})
143
+ AnimatedList({ children: items.map((item) => h('li', { key: item.id }, item.text)) })
142
144
  ```
143
145
 
144
146
  ### Inline Configuration
@@ -199,8 +201,9 @@ Kinetic and rocketstyle compose naturally:
199
201
  ```ts
200
202
  import rocketstyle from '@pyreon/rocketstyle'
201
203
 
202
- const Button = rocketstyle()({ component: 'button', name: 'Button' })
203
- .theme({ primaryColor: 'blue' })
204
+ const Button = rocketstyle()({ component: 'button', name: 'Button' }).theme({
205
+ primaryColor: 'blue',
206
+ })
204
207
 
205
208
  const AnimatedButton = kinetic(Button).preset(fade)
206
209
 
@@ -210,9 +213,9 @@ AnimatedButton({ show: isVisible, primary: true, size: 'large', children: 'Click
210
213
 
211
214
  ## Peer Dependencies
212
215
 
213
- | Package | Version |
214
- | ------- | ------- |
215
- | @pyreon/core | >= 0.0.1 |
216
+ | Package | Version |
217
+ | ------------------ | -------- |
218
+ | @pyreon/core | >= 0.0.1 |
216
219
  | @pyreon/reactivity | >= 0.0.1 |
217
220
 
218
221
  ## License
package/lib/index.d.ts CHANGED
@@ -4,7 +4,7 @@ import { Signal } from "@pyreon/reactivity";
4
4
  //#region src/types.d.ts
5
5
  type CSSProperties = Record<string, string | number | undefined>;
6
6
  /** Internal lifecycle stages of a transition. */
7
- type TransitionStage = "hidden" | "entering" | "entered" | "leaving";
7
+ type TransitionStage = 'hidden' | 'entering' | 'entered' | 'leaving';
8
8
  /** Class-based transition definition. */
9
9
  type ClassTransitionProps = {
10
10
  /** Classes applied during the entire enter phase */enter?: string | undefined; /** Classes applied on first frame of enter, removed on next frame */
@@ -38,7 +38,7 @@ type TransitionStateResult = {
38
38
  };
39
39
  //#endregion
40
40
  //#region src/kinetic/types.d.ts
41
- type KineticMode = "transition" | "collapse" | "stagger" | "group";
41
+ type KineticMode = 'transition' | 'collapse' | 'stagger' | 'group';
42
42
  type ClassConfig = {
43
43
  active?: string | undefined;
44
44
  from?: string | undefined;
@@ -91,8 +91,8 @@ type KineticGroupProps<_Tag extends string> = Record<string, unknown> & {
91
91
  timeout?: number | undefined;
92
92
  children: VNodeChild;
93
93
  } & Partial<TransitionCallbacks>;
94
- type KineticComponentProps<Tag extends string, Mode extends KineticMode> = Mode extends "collapse" ? KineticCollapseProps<Tag> : Mode extends "stagger" ? KineticStaggerProps<Tag> : Mode extends "group" ? KineticGroupProps<Tag> : KineticTransitionProps<Tag>;
95
- type ConfigOpts<Mode extends KineticMode> = Mode extends "collapse" ? CollapseConfigOpts : Mode extends "stagger" ? StaggerConfigOpts : Mode extends "group" ? GroupConfigOpts : TransitionConfigOpts;
94
+ type KineticComponentProps<Tag extends string, Mode extends KineticMode> = Mode extends 'collapse' ? KineticCollapseProps<Tag> : Mode extends 'stagger' ? KineticStaggerProps<Tag> : Mode extends 'group' ? KineticGroupProps<Tag> : KineticTransitionProps<Tag>;
95
+ type ConfigOpts<Mode extends KineticMode> = Mode extends 'collapse' ? CollapseConfigOpts : Mode extends 'stagger' ? StaggerConfigOpts : Mode extends 'group' ? GroupConfigOpts : TransitionConfigOpts;
96
96
  type KineticChain<Tag extends string, Mode extends KineticMode> = {
97
97
  displayName: string;
98
98
  preset: (preset: StyleTransitionProps & ClassTransitionProps) => KineticComponent<Tag, Mode>;
@@ -106,14 +106,14 @@ type KineticChain<Tag extends string, Mode extends KineticMode> = {
106
106
  leaveClass: (opts: ClassConfig) => KineticComponent<Tag, Mode>;
107
107
  config: (opts: ConfigOpts<Mode>) => KineticComponent<Tag, Mode>;
108
108
  on: (callbacks: Partial<TransitionCallbacks>) => KineticComponent<Tag, Mode>;
109
- collapse: (opts?: CollapseConfigOpts) => KineticComponent<Tag, "collapse">;
109
+ collapse: (opts?: CollapseConfigOpts) => KineticComponent<Tag, 'collapse'>;
110
110
  stagger: (opts?: {
111
111
  interval?: number | undefined;
112
112
  reverseLeave?: boolean | undefined;
113
- }) => KineticComponent<Tag, "stagger">;
114
- group: () => KineticComponent<Tag, "group">;
113
+ }) => KineticComponent<Tag, 'stagger'>;
114
+ group: () => KineticComponent<Tag, 'group'>;
115
115
  };
116
- type KineticComponent<Tag extends string, Mode extends KineticMode = "transition"> = ComponentFn<KineticComponentProps<Tag, Mode>> & KineticChain<Tag, Mode>;
116
+ type KineticComponent<Tag extends string, Mode extends KineticMode = 'transition'> = ComponentFn<KineticComponentProps<Tag, Mode>> & KineticChain<Tag, Mode>;
117
117
  //#endregion
118
118
  //#region src/kinetic.d.ts
119
119
  /**
package/lib/index.js CHANGED
@@ -415,55 +415,64 @@ const getKeyedChildren = (children) => {
415
415
  * Children that appear (new key) animate in. Children that disappear
416
416
  * (removed key) stay in DOM during leave animation, then unmount.
417
417
  * config.tag wraps all children as a container element.
418
+ *
419
+ * In Pyreon, components run once. Pass children as a reactive accessor
420
+ * `() => VNode[]` for the group to detect changes and animate entries/exits.
418
421
  */
419
422
  const GroupRenderer = ({ config, htmlProps, appear, timeout, callbacks, children }) => {
420
423
  const effectiveAppear = appear ?? config.appear ?? false;
421
424
  const effectiveTimeout = timeout ?? config.timeout ?? 5e3;
422
425
  const prevMap = /* @__PURE__ */ new Map();
423
426
  const leavingMap = /* @__PURE__ */ new Map();
424
- const forceUpdateSignal = signal(0);
425
- const currentKeyed = getKeyedChildren(children);
426
- const currentMap = /* @__PURE__ */ new Map();
427
- for (const { key, element } of currentKeyed) currentMap.set(key, element);
428
- const initialKeys = new Set(currentMap.keys());
429
- for (const [key, child] of prevMap) if (!currentMap.has(key)) leavingMap.set(key, child);
430
- for (const key of currentMap.keys()) leavingMap.delete(key);
431
- prevMap.clear();
432
- for (const [key, element] of currentMap) prevMap.set(key, element);
427
+ const forceUpdate = signal(0);
428
+ const getChildren = typeof children === "function" ? children : () => children;
429
+ const initialKeyed = getKeyedChildren(getChildren());
430
+ const initialKeys = new Set(initialKeyed.map((c) => c.key));
431
+ for (const { key, element } of initialKeyed) prevMap.set(key, element);
433
432
  const handleAfterLeave = (key) => {
434
433
  leavingMap.delete(key);
435
434
  callbacks.onAfterLeave?.();
436
- forceUpdateSignal.update((c) => c + 1);
435
+ forceUpdate.update((c) => c + 1);
437
436
  };
438
- const allEntries = [...currentKeyed];
439
- for (const [key, element] of leavingMap) allEntries.push({
440
- key,
441
- element
442
- });
443
- const groupedChildren = allEntries.map(({ key, element }) => {
444
- const isInitial = initialKeys.has(key);
445
- const isShowing = currentMap.has(key);
446
- return /* @__PURE__ */ jsx(TransitionItem, {
447
- show: () => isShowing,
448
- appear: isInitial ? effectiveAppear : true,
449
- timeout: effectiveTimeout,
450
- enterStyle: config.enterStyle,
451
- enterToStyle: config.enterToStyle,
452
- enterTransition: config.enterTransition,
453
- leaveStyle: config.leaveStyle,
454
- leaveToStyle: config.leaveToStyle,
455
- leaveTransition: config.leaveTransition,
456
- enter: config.enter,
457
- enterFrom: config.enterFrom,
458
- enterTo: config.enterTo,
459
- leave: config.leave,
460
- leaveFrom: config.leaveFrom,
461
- leaveTo: config.leaveTo,
462
- onAfterLeave: () => handleAfterLeave(key),
463
- children: element
437
+ return (() => {
438
+ forceUpdate();
439
+ const currentKeyed = getKeyedChildren(getChildren());
440
+ const currentMap = /* @__PURE__ */ new Map();
441
+ for (const { key, element } of currentKeyed) currentMap.set(key, element);
442
+ for (const [key, child] of prevMap) if (!currentMap.has(key) && !leavingMap.has(key)) leavingMap.set(key, child);
443
+ for (const key of currentMap.keys()) leavingMap.delete(key);
444
+ prevMap.clear();
445
+ for (const [key, element] of currentMap) prevMap.set(key, element);
446
+ const allEntries = [...currentKeyed];
447
+ for (const [key, element] of leavingMap) allEntries.push({
448
+ key,
449
+ element
450
+ });
451
+ const groupedChildren = allEntries.map(({ key, element }) => {
452
+ const isInitial = initialKeys.has(key);
453
+ const isShowing = currentMap.has(key);
454
+ return /* @__PURE__ */ jsx(TransitionItem, {
455
+ show: () => isShowing,
456
+ appear: isInitial ? effectiveAppear : true,
457
+ timeout: effectiveTimeout,
458
+ enterStyle: config.enterStyle,
459
+ enterToStyle: config.enterToStyle,
460
+ enterTransition: config.enterTransition,
461
+ leaveStyle: config.leaveStyle,
462
+ leaveToStyle: config.leaveToStyle,
463
+ leaveTransition: config.leaveTransition,
464
+ enter: config.enter,
465
+ enterFrom: config.enterFrom,
466
+ enterTo: config.enterTo,
467
+ leave: config.leave,
468
+ leaveFrom: config.leaveFrom,
469
+ leaveTo: config.leaveTo,
470
+ onAfterLeave: () => handleAfterLeave(key),
471
+ children: element
472
+ });
464
473
  });
474
+ return h(config.tag, { ...htmlProps }, ...groupedChildren);
465
475
  });
466
- return h(config.tag, { ...htmlProps }, ...groupedChildren);
467
476
  };
468
477
 
469
478
  //#endregion
package/package.json CHANGED
@@ -1,24 +1,13 @@
1
1
  {
2
2
  "name": "@pyreon/kinetic",
3
- "version": "0.11.4",
3
+ "version": "0.11.6",
4
+ "description": "CSS-transition-based animation components for Pyreon",
5
+ "license": "MIT",
4
6
  "repository": {
5
7
  "type": "git",
6
8
  "url": "https://github.com/pyreon/pyreon",
7
9
  "directory": "packages/ui-system/kinetic"
8
10
  },
9
- "description": "CSS-transition-based animation components for Pyreon",
10
- "license": "MIT",
11
- "type": "module",
12
- "sideEffects": false,
13
- "exports": {
14
- ".": {
15
- "bun": "./src/index.ts",
16
- "import": "./lib/index.js",
17
- "types": "./lib/index.d.ts"
18
- }
19
- },
20
- "types": "./lib/index.d.ts",
21
- "main": "./lib/index.js",
22
11
  "files": [
23
12
  "lib",
24
13
  "!lib/**/*.map",
@@ -27,8 +16,16 @@
27
16
  "LICENSE",
28
17
  "src"
29
18
  ],
30
- "engines": {
31
- "node": ">= 22"
19
+ "type": "module",
20
+ "sideEffects": false,
21
+ "main": "./lib/index.js",
22
+ "types": "./lib/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "bun": "./src/index.ts",
26
+ "import": "./lib/index.js",
27
+ "types": "./lib/index.d.ts"
28
+ }
32
29
  },
33
30
  "publishConfig": {
34
31
  "access": "public"
@@ -37,18 +34,21 @@
37
34
  "prepublish": "bun run build",
38
35
  "build": "bun run vl_rolldown_build",
39
36
  "build:watch": "bun run vl_rolldown_build-watch",
40
- "lint": "biome check src/",
37
+ "lint": "oxlint .",
41
38
  "test": "vitest run",
42
39
  "test:coverage": "vitest run --coverage",
43
40
  "test:watch": "vitest",
44
41
  "typecheck": "tsc --noEmit"
45
42
  },
43
+ "devDependencies": {
44
+ "@pyreon/typescript": "^0.11.6",
45
+ "@vitus-labs/tools-rolldown": "^1.15.3"
46
+ },
46
47
  "peerDependencies": {
47
- "@pyreon/core": "^0.11.4",
48
- "@pyreon/reactivity": "^0.11.4"
48
+ "@pyreon/core": "^0.11.6",
49
+ "@pyreon/reactivity": "^0.11.6"
49
50
  },
50
- "devDependencies": {
51
- "@vitus-labs/tools-rolldown": "^1.15.3",
52
- "@pyreon/typescript": "^0.11.4"
51
+ "engines": {
52
+ "node": ">= 22"
53
53
  }
54
54
  }
package/src/Collapse.tsx CHANGED
@@ -1,13 +1,13 @@
1
- import type { VNode } from "@pyreon/core"
2
- import { createRef, Show } from "@pyreon/core"
3
- import { runUntracked, signal, watch } from "@pyreon/reactivity"
4
- import type { CollapseProps, TransitionStage } from "./types"
5
- import useAnimationEnd from "./useAnimationEnd"
6
- import { useReducedMotion } from "./useReducedMotion"
1
+ import type { VNode } from '@pyreon/core'
2
+ import { createRef, Show } from '@pyreon/core'
3
+ import { runUntracked, signal, watch } from '@pyreon/reactivity'
4
+ import type { CollapseProps, TransitionStage } from './types'
5
+ import useAnimationEnd from './useAnimationEnd'
6
+ import { useReducedMotion } from './useReducedMotion'
7
7
 
8
8
  const Collapse = ({
9
9
  show,
10
- transition = "height 300ms ease",
10
+ transition = 'height 300ms ease',
11
11
  appear = false,
12
12
  timeout = 5000,
13
13
  onEnter,
@@ -30,7 +30,7 @@ const Collapse = ({
30
30
  const initialShow = show()
31
31
  // When appear=true and show starts true, mount but defer animation until ref is wired
32
32
  const needsAppear = appear && initialShow
33
- const stage = signal<TransitionStage>(initialShow ? "entered" : "hidden")
33
+ const stage = signal<TransitionStage>(initialShow ? 'entered' : 'hidden')
34
34
  let isInitialMount = true
35
35
  let appearTriggered = false
36
36
 
@@ -39,7 +39,7 @@ const Collapse = ({
39
39
  if (needsAppear) {
40
40
  const orig = wrapperRef
41
41
  const proxy = { current: null as HTMLDivElement | null }
42
- Object.defineProperty(proxy, "current", {
42
+ Object.defineProperty(proxy, 'current', {
43
43
  get() {
44
44
  return orig.current
45
45
  },
@@ -47,7 +47,7 @@ const Collapse = ({
47
47
  orig.current = node
48
48
  if (node && !appearTriggered) {
49
49
  appearTriggered = true
50
- queueMicrotask(() => stage.set("entering"))
50
+ queueMicrotask(() => stage.set('entering'))
51
51
  }
52
52
  },
53
53
  })
@@ -65,10 +65,10 @@ const Collapse = ({
65
65
  }
66
66
 
67
67
  const currentStage = runUntracked(() => stage())
68
- if (showVal && (currentStage === "hidden" || currentStage === "leaving")) {
69
- stage.set("entering")
70
- } else if (!showVal && (currentStage === "entered" || currentStage === "entering")) {
71
- stage.set("leaving")
68
+ if (showVal && (currentStage === 'hidden' || currentStage === 'leaving')) {
69
+ stage.set('entering')
70
+ } else if (!showVal && (currentStage === 'entered' || currentStage === 'entering')) {
71
+ stage.set('leaving')
72
72
  }
73
73
  },
74
74
  { immediate: true },
@@ -83,44 +83,44 @@ const Collapse = ({
83
83
  if (!wrapper || !content) return
84
84
 
85
85
  if (reducedMotion()) {
86
- if (currentStage === "entering") {
86
+ if (currentStage === 'entering') {
87
87
  callbacks.onEnter?.()
88
- wrapper.style.height = "auto"
89
- wrapper.style.overflow = ""
88
+ wrapper.style.height = 'auto'
89
+ wrapper.style.overflow = ''
90
90
  callbacks.onAfterEnter?.()
91
- stage.set("entered")
92
- } else if (currentStage === "leaving") {
91
+ stage.set('entered')
92
+ } else if (currentStage === 'leaving') {
93
93
  callbacks.onLeave?.()
94
- wrapper.style.height = "0px"
95
- wrapper.style.overflow = "hidden"
94
+ wrapper.style.height = '0px'
95
+ wrapper.style.overflow = 'hidden'
96
96
  callbacks.onAfterLeave?.()
97
- stage.set("hidden")
97
+ stage.set('hidden')
98
98
  }
99
99
  return
100
100
  }
101
101
 
102
- if (currentStage === "entering") {
102
+ if (currentStage === 'entering') {
103
103
  callbacks.onEnter?.()
104
104
  const height = content.scrollHeight
105
- wrapper.style.transition = "none"
106
- wrapper.style.height = "0px"
107
- wrapper.style.overflow = "hidden"
105
+ wrapper.style.transition = 'none'
106
+ wrapper.style.height = '0px'
107
+ wrapper.style.overflow = 'hidden'
108
108
  // Force reflow so the browser registers height: 0
109
109
  void wrapper.offsetHeight
110
110
  wrapper.style.transition = transition
111
111
  wrapper.style.height = `${height}px`
112
112
  }
113
113
 
114
- if (currentStage === "leaving") {
114
+ if (currentStage === 'leaving') {
115
115
  callbacks.onLeave?.()
116
116
  const height = content.scrollHeight
117
- wrapper.style.transition = "none"
117
+ wrapper.style.transition = 'none'
118
118
  wrapper.style.height = `${height}px`
119
- wrapper.style.overflow = "hidden"
119
+ wrapper.style.overflow = 'hidden'
120
120
  // Force reflow
121
121
  void wrapper.offsetHeight
122
122
  wrapper.style.transition = transition
123
- wrapper.style.height = "0px"
123
+ wrapper.style.height = '0px'
124
124
  }
125
125
  },
126
126
  { immediate: true },
@@ -129,36 +129,36 @@ const Collapse = ({
129
129
  // Listen for animation end
130
130
  useAnimationEnd({
131
131
  ref: wrapperRef,
132
- active: () => (stage() === "entering" || stage() === "leaving") && !reducedMotion(),
132
+ active: () => (stage() === 'entering' || stage() === 'leaving') && !reducedMotion(),
133
133
  timeout,
134
134
  onEnd: () => {
135
135
  const wrapper = wrapperRef.current
136
- if (stage() === "entering") {
136
+ if (stage() === 'entering') {
137
137
  if (wrapper) {
138
- wrapper.style.height = "auto"
139
- wrapper.style.overflow = ""
140
- wrapper.style.transition = ""
138
+ wrapper.style.height = 'auto'
139
+ wrapper.style.overflow = ''
140
+ wrapper.style.transition = ''
141
141
  }
142
142
  callbacks.onAfterEnter?.()
143
- stage.set("entered")
144
- } else if (stage() === "leaving") {
143
+ stage.set('entered')
144
+ } else if (stage() === 'leaving') {
145
145
  callbacks.onAfterLeave?.()
146
- stage.set("hidden")
146
+ stage.set('hidden')
147
147
  }
148
148
  },
149
149
  })
150
150
 
151
- const shouldRender = () => stage() !== "hidden"
151
+ const shouldRender = () => stage() !== 'hidden'
152
152
 
153
153
  return (
154
154
  <div
155
155
  ref={wrapperRef}
156
156
  style={{
157
- ...(stage() !== "entered" ? { overflow: "hidden" } : {}),
158
- ...(stage() === "hidden"
159
- ? { height: "0px" }
160
- : stage() === "entered"
161
- ? { height: "auto" }
157
+ ...(stage() !== 'entered' ? { overflow: 'hidden' } : {}),
158
+ ...(stage() === 'hidden'
159
+ ? { height: '0px' }
160
+ : stage() === 'entered'
161
+ ? { height: 'auto' }
162
162
  : {}),
163
163
  }}
164
164
  >
package/src/Stagger.tsx CHANGED
@@ -1,10 +1,10 @@
1
- import type { VNode } from "@pyreon/core"
2
- import Transition from "./Transition"
3
- import type { CSSProperties, StaggerProps } from "./types"
4
- import { cloneVNode } from "./utils"
1
+ import type { VNode } from '@pyreon/core'
2
+ import Transition from './Transition'
3
+ import type { CSSProperties, StaggerProps } from './types'
4
+ import { cloneVNode } from './utils'
5
5
 
6
6
  const isVNode = (child: unknown): child is VNode =>
7
- child != null && typeof child === "object" && "type" in (child as object)
7
+ child != null && typeof child === 'object' && 'type' in (child as object)
8
8
 
9
9
  const Stagger = ({
10
10
  show,
@@ -37,8 +37,8 @@ const Stagger = ({
37
37
  {cloneVNode(child, {
38
38
  style: {
39
39
  ...((child.props as Record<string, unknown>)?.style as CSSProperties | undefined),
40
- "--stagger-index": staggerIndex,
41
- "--stagger-interval": `${interval}ms`,
40
+ '--stagger-index': staggerIndex,
41
+ '--stagger-interval': `${interval}ms`,
42
42
  transitionDelay: `${delay}ms`,
43
43
  } as CSSProperties,
44
44
  })}
@@ -1,11 +1,11 @@
1
- import type { VNode } from "@pyreon/core"
2
- import { createRef, Show } from "@pyreon/core"
3
- import { watch } from "@pyreon/reactivity"
4
- import type { ClassTransitionProps, StyleTransitionProps, TransitionProps } from "./types"
5
- import useAnimationEnd from "./useAnimationEnd"
6
- import { useReducedMotion } from "./useReducedMotion"
7
- import useTransitionState from "./useTransitionState"
8
- import { addClasses, cloneVNode, mergeRefs, mergeStyles, nextFrame, removeClasses } from "./utils"
1
+ import type { VNode } from '@pyreon/core'
2
+ import { createRef, Show } from '@pyreon/core'
3
+ import { watch } from '@pyreon/reactivity'
4
+ import type { ClassTransitionProps, StyleTransitionProps, TransitionProps } from './types'
5
+ import useAnimationEnd from './useAnimationEnd'
6
+ import { useReducedMotion } from './useReducedMotion'
7
+ import useTransitionState from './useTransitionState'
8
+ import { addClasses, cloneVNode, mergeRefs, mergeStyles, nextFrame, removeClasses } from './utils'
9
9
 
10
10
  const applyEnter = (
11
11
  el: HTMLElement,
@@ -68,11 +68,11 @@ const applyReducedMotion = (
68
68
  },
69
69
  complete: () => void,
70
70
  ) => {
71
- if (stage === "entering") {
71
+ if (stage === 'entering') {
72
72
  callbacks.onEnter?.()
73
73
  callbacks.onAfterEnter?.()
74
74
  complete()
75
- } else if (stage === "leaving") {
75
+ } else if (stage === 'leaving') {
76
76
  callbacks.onLeave?.()
77
77
  callbacks.onAfterLeave?.()
78
78
  complete()
@@ -114,12 +114,11 @@ const Transition = ({
114
114
  })
115
115
 
116
116
  const elementRef = createRef<HTMLElement>()
117
+ const childProps = (children.props ?? {}) as Record<string, unknown>
117
118
  const mergedRef = mergeRefs(
118
119
  elementRef,
119
120
  stateRef,
120
- (children.props as Record<string, unknown>)?.ref as
121
- | ((el: HTMLElement | null) => void)
122
- | undefined,
121
+ childProps.ref as ((el: HTMLElement | null) => void) | undefined,
123
122
  )
124
123
 
125
124
  const callbacks = {
@@ -146,12 +145,12 @@ const Transition = ({
146
145
 
147
146
  useAnimationEnd({
148
147
  ref: elementRef,
149
- active: () => (stage() === "entering" || stage() === "leaving") && !reducedMotion(),
148
+ active: () => (stage() === 'entering' || stage() === 'leaving') && !reducedMotion(),
150
149
  timeout,
151
150
  onEnd: () => {
152
- if (stage() === "entering") {
151
+ if (stage() === 'entering') {
153
152
  callbacks.onAfterEnter?.()
154
- } else if (stage() === "leaving") {
153
+ } else if (stage() === 'leaving') {
155
154
  callbacks.onAfterLeave?.()
156
155
  }
157
156
  complete()
@@ -169,21 +168,21 @@ const Transition = ({
169
168
  return
170
169
  }
171
170
 
172
- if (currentStage === "entering") {
171
+ if (currentStage === 'entering') {
173
172
  callbacks.onEnter?.()
174
173
  const frameId = applyEnter(el, transitionConfig)
175
174
  return () => cancelAnimationFrame(frameId)
176
175
  }
177
176
 
178
- if (currentStage === "leaving") {
177
+ if (currentStage === 'leaving') {
179
178
  callbacks.onLeave?.()
180
179
  const frameId = applyLeave(el, transitionConfig)
181
180
  return () => cancelAnimationFrame(frameId)
182
181
  }
183
182
 
184
- if (currentStage === "entered") {
183
+ if (currentStage === 'entered') {
185
184
  removeClasses(el, enter)
186
- el.style.transition = ""
185
+ el.style.transition = ''
187
186
  }
188
187
  },
189
188
  { immediate: true },
@@ -198,10 +197,8 @@ const Transition = ({
198
197
  : cloneVNode(children, {
199
198
  ref: mergedRef,
200
199
  style: mergeStyles(
201
- (children.props as Record<string, unknown>)?.style as
202
- | Record<string, string | number | undefined>
203
- | undefined,
204
- { display: "none" },
200
+ childProps.style as Record<string, string | number | undefined> | undefined,
201
+ { display: 'none' },
205
202
  ),
206
203
  })
207
204
  }