@ssgoi/react 3.3.0 → 4.0.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/README.md CHANGED
@@ -33,15 +33,13 @@ pnpm add @ssgoi/react
33
33
  ### 1. Wrap your app
34
34
 
35
35
  ```tsx
36
- import { Ssgoi } from '@ssgoi/react';
37
- import { fade } from '@ssgoi/react/view-transitions';
36
+ import { Ssgoi } from "@ssgoi/react";
37
+ import { fade } from "@ssgoi/react/view-transitions";
38
38
 
39
39
  export default function App() {
40
40
  return (
41
41
  <Ssgoi config={{ defaultTransition: fade() }}>
42
- <div style={{ position: 'relative' }}>
43
- {/* Your app */}
44
- </div>
42
+ <div style={{ position: "relative" }}>{/* Your app */}</div>
45
43
  </Ssgoi>
46
44
  );
47
45
  }
@@ -50,7 +48,7 @@ export default function App() {
50
48
  ### 2. Wrap your pages
51
49
 
52
50
  ```tsx
53
- import { SsgoiTransition } from '@ssgoi/react';
51
+ import { SsgoiTransition } from "@ssgoi/react";
54
52
 
55
53
  export default function HomePage() {
56
54
  return (
@@ -74,16 +72,20 @@ Define different transitions for different routes:
74
72
  const config = {
75
73
  transitions: [
76
74
  // Scroll between tabs
77
- { from: '/home', to: '/about', transition: scroll({ direction: 'up' }) },
78
- { from: '/about', to: '/home', transition: scroll({ direction: 'down' }) },
79
-
75
+ { from: "/home", to: "/about", transition: scroll({ direction: "up" }) },
76
+ { from: "/about", to: "/home", transition: scroll({ direction: "down" }) },
77
+
80
78
  // Drill in when entering details
81
- { from: '/products', to: '/products/*', transition: drill({ direction: 'enter' }) },
82
-
79
+ {
80
+ from: "/products",
81
+ to: "/products/*",
82
+ transition: drill({ direction: "enter" }),
83
+ },
84
+
83
85
  // Pinterest-style image transitions
84
- { from: '/gallery', to: '/photo/*', transition: pinterest() }
86
+ { from: "/gallery", to: "/photo/*", transition: pinterest() },
85
87
  ],
86
- defaultTransition: fade()
88
+ defaultTransition: fade(),
87
89
  };
88
90
  ```
89
91
 
@@ -94,7 +96,7 @@ Automatically create bidirectional transitions:
94
96
  ```tsx
95
97
  {
96
98
  from: '/home',
97
- to: '/about',
99
+ to: '/about',
98
100
  transition: scroll({ direction: 'up' }),
99
101
  symmetric: true // Automatically creates reverse transition
100
102
  }
@@ -105,16 +107,18 @@ Automatically create bidirectional transitions:
105
107
  Animate specific elements during mount/unmount:
106
108
 
107
109
  ```tsx
108
- import { transition } from '@ssgoi/react';
109
- import { fade, slide } from '@ssgoi/react/transitions';
110
+ import { transition } from "@ssgoi/react";
111
+ import { fade, slide } from "@ssgoi/react/transitions";
110
112
 
111
113
  function Card() {
112
114
  return (
113
- <div ref={transition({
114
- key: 'card',
115
- in: fade(),
116
- out: slide({ direction: 'up' })
117
- })}>
115
+ <div
116
+ ref={transition({
117
+ key: "card",
118
+ in: fade(),
119
+ out: slide({ direction: "up" }),
120
+ })}
121
+ >
118
122
  <h2>Animated Card</h2>
119
123
  </div>
120
124
  );
@@ -126,11 +130,12 @@ function Card() {
126
130
  The Auto Key Plugin automatically generates unique keys for your transitions based on the file location (`file:line:column`), eliminating the need to manually provide keys.
127
131
 
128
132
  **Benefits:**
133
+
129
134
  - **Automatic Key Generation**: No need to manually specify `key` in `transition()` calls
130
135
  - **Collision-Free**: Keys are based on exact code location
131
136
  - **Cleaner Code**: Less boilerplate in your components
132
137
 
133
- **⚠️ Important**: For list items rendered with `.map()`, always provide an explicit `key` for stability. The plugin cannot guarantee stable keys for dynamically generated elements.
138
+ **⚠️ Important**: For list items rendered with `.map()`, just use JSX key prop - the plugin automatically appends it to generate unique keys.
134
139
 
135
140
  #### Setup with Next.js
136
141
 
@@ -153,8 +158,8 @@ export default nextConfig;
153
158
 
154
159
  ```ts
155
160
  // vite.config.ts
156
- import { defineConfig } from 'vite';
157
- import react from '@vitejs/plugin-react';
161
+ import { defineConfig } from "vite";
162
+ import react from "@vitejs/plugin-react";
158
163
  import SsgoiAutoKey from "@ssgoi/react/unplugin/vite";
159
164
 
160
165
  export default defineConfig({
@@ -165,19 +170,11 @@ export default defineConfig({
165
170
  #### Usage Examples
166
171
 
167
172
  **WITH Auto Key Plugin (Recommended):**
168
- ```tsx
169
- import { transition } from '@ssgoi/react';
170
- import { fade, slide } from '@ssgoi/react/transitions';
171
173
 
172
- function Card() {
173
- return (
174
- <div ref={transition({ in: fade(), out: slide({ direction: 'up' }) })}>
175
- <h2>Animated Card</h2>
176
- </div>
177
- );
178
- }
174
+ ```tsx
175
+ import { transition } from "@ssgoi/react";
176
+ import { fade, slide } from "@ssgoi/react/transitions";
179
177
 
180
- // Even simpler with single transition
181
178
  function SimpleCard() {
182
179
  return (
183
180
  <div ref={transition(fade())}>
@@ -188,35 +185,34 @@ function SimpleCard() {
188
185
  ```
189
186
 
190
187
  **WITHOUT Auto Key Plugin:**
188
+
191
189
  ```tsx
192
190
  // Explicit key required for transition state tracking
193
191
  function Card() {
194
192
  return (
195
- <div ref={transition({
196
- key: 'my-card',
197
- in: fade(),
198
- out: slide({ direction: 'up' })
199
- })}>
193
+ <div
194
+ ref={transition({
195
+ key: "my-card",
196
+ ...fade(),
197
+ })}
198
+ >
200
199
  <h2>Animated Card</h2>
201
200
  </div>
202
201
  );
203
202
  }
204
203
  ```
205
204
 
206
- **List Items (Always Use Explicit Keys):**
205
+ **List Items:**
206
+
207
207
  ```tsx
208
- // For list items, always provide explicit keys for stability
208
+ // In .map() lists, just use JSX key - the plugin appends it automatically
209
209
  function List() {
210
210
  return (
211
211
  <ul>
212
212
  {items.map((item) => (
213
213
  <li
214
- key={item.id}
215
- ref={transition({
216
- key: `list-item-${item.id}`,
217
- in: fade(),
218
- out: slide({ direction: 'up' })
219
- })}
214
+ key={item.id} // JSX key is enough - plugin generates file:line:col:${key}
215
+ ref={transition(fade())}
220
216
  >
221
217
  {item.name}
222
218
  </li>
@@ -230,17 +226,19 @@ function List() {
230
226
 
231
227
  ```tsx
232
228
  // app/layout.tsx
233
- import { Ssgoi } from '@ssgoi/react';
234
- import { scroll } from '@ssgoi/react/view-transitions';
229
+ import { Ssgoi } from "@ssgoi/react";
230
+ import { scroll } from "@ssgoi/react/view-transitions";
235
231
 
236
232
  export default function RootLayout({ children }) {
237
233
  return (
238
234
  <html>
239
235
  <body>
240
- <Ssgoi config={{
241
- defaultTransition: scroll({ direction: 'up' })
242
- }}>
243
- <div style={{ position: 'relative', minHeight: '100vh' }}>
236
+ <Ssgoi
237
+ config={{
238
+ defaultTransition: scroll({ direction: "up" }),
239
+ }}
240
+ >
241
+ <div style={{ position: "relative", minHeight: "100vh" }}>
244
242
  {children}
245
243
  </div>
246
244
  </Ssgoi>
@@ -250,14 +248,10 @@ export default function RootLayout({ children }) {
250
248
  }
251
249
 
252
250
  // app/page.tsx
253
- import { SsgoiTransition } from '@ssgoi/react';
251
+ import { SsgoiTransition } from "@ssgoi/react";
254
252
 
255
253
  export default function Page() {
256
- return (
257
- <SsgoiTransition id="/">
258
- {/* Your page content */}
259
- </SsgoiTransition>
260
- );
254
+ return <SsgoiTransition id="/">{/* Your page content */}</SsgoiTransition>;
261
255
  }
262
256
  ```
263
257
 
@@ -266,26 +260,25 @@ export default function Page() {
266
260
  ### Components
267
261
 
268
262
  #### `<Ssgoi>`
263
+
269
264
  The provider component that manages transition context.
270
265
 
271
266
  ```tsx
272
- <Ssgoi config={ssgoiConfig}>
273
- {children}
274
- </Ssgoi>
267
+ <Ssgoi config={ssgoiConfig}>{children}</Ssgoi>
275
268
  ```
276
269
 
277
270
  #### `<SsgoiTransition>`
271
+
278
272
  Wrapper component for pages that should transition.
279
273
 
280
274
  ```tsx
281
- <SsgoiTransition id="/page-id">
282
- {children}
283
- </SsgoiTransition>
275
+ <SsgoiTransition id="/page-id">{children}</SsgoiTransition>
284
276
  ```
285
277
 
286
278
  ### Hooks
287
279
 
288
280
  #### `useTransition()`
281
+
289
282
  Access transition state and controls.
290
283
 
291
284
  ```tsx
@@ -295,14 +288,17 @@ const { isTransitioning, direction } = useTransition();
295
288
  ### Functions
296
289
 
297
290
  #### `transition()`
291
+
298
292
  Apply transitions to individual elements.
299
293
 
300
294
  ```tsx
301
- <div ref={transition({
302
- key: 'unique-key',
303
- in: fade(),
304
- out: fade()
305
- })}>
295
+ <div
296
+ ref={transition({
297
+ key: "unique-key",
298
+ in: fade(),
299
+ out: fade(),
300
+ })}
301
+ >
306
302
  Content
307
303
  </div>
308
304
  ```
@@ -310,6 +306,7 @@ Apply transitions to individual elements.
310
306
  ## Built-in Transitions
311
307
 
312
308
  ### Page Transitions (`@ssgoi/react/view-transitions`)
309
+
313
310
  - `fade()` - Smooth opacity transition
314
311
  - `scroll()` - Vertical scrolling (up/down)
315
312
  - `drill()` - Drill in/out effect (enter/exit)
@@ -317,6 +314,7 @@ Apply transitions to individual elements.
317
314
  - `pinterest()` - Pinterest-style expand effect
318
315
 
319
316
  ### Element Transitions (`@ssgoi/react/transitions`)
317
+
320
318
  - `fade()` - Fade in/out
321
319
  - `scale()` - Scale in/out
322
320
  - `slide()` - Slide (direction: up/down/left/right)
@@ -331,12 +329,12 @@ All transitions use spring physics for natural motion:
331
329
 
332
330
  ```tsx
333
331
  slide({
334
- direction: 'left',
332
+ direction: "left",
335
333
  spring: {
336
- stiffness: 300, // 1-1000, higher = faster
337
- damping: 30 // 0-100, higher = less oscillation
338
- }
339
- })
334
+ stiffness: 300, // 1-1000, higher = faster
335
+ damping: 30, // 0-100, higher = less oscillation
336
+ },
337
+ });
340
338
  ```
341
339
 
342
340
  ## TypeScript Support
@@ -344,7 +342,7 @@ slide({
344
342
  SSGOI is written in TypeScript and provides full type definitions:
345
343
 
346
344
  ```tsx
347
- import type { SsgoiConfig, TransitionConfig } from '@ssgoi/react';
345
+ import type { SsgoiConfig, TransitionConfig } from "@ssgoi/react";
348
346
 
349
347
  const config: SsgoiConfig = {
350
348
  // Full type safety
@@ -368,6 +366,7 @@ const config: SsgoiConfig = {
368
366
  ## Documentation
369
367
 
370
368
  Visit [https://ssgoi.dev](https://ssgoi.dev) for:
369
+
371
370
  - Complete API reference
372
371
  - Interactive examples
373
372
  - Advanced patterns
@@ -379,4 +378,4 @@ We welcome contributions! Please see our [contributing guide](https://github.com
379
378
 
380
379
  ## License
381
380
 
382
- MIT © [MeurSyphus](https://github.com/meursyphus)
381
+ MIT © [MeurSyphus](https://github.com/meursyphus)
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function h(e){return("tick"in e||"css"in e)&&!("springs"in e)}function s(e){return"springs"in e}function o(e){return"css"in e&&typeof e.css=="function"}function a(e){return"tick"in e&&typeof e.tick=="function"}function c(e){if(o(e)&&a(e))throw new Error("SingleSpringConfig cannot have both 'tick' and 'css' defined. Use one or the other.")}function l(e){if(e.tick&&e.css)throw new Error("SpringItem cannot have both 'tick' and 'css' defined. Use one or the other.")}async function m(e){const n=await e;return s(n)?(n.springs.forEach(l),n):(c(n),{prepare:n.prepare,wait:n.wait,onStart:n.onStart,onEnd:n.onEnd,springs:[{spring:n.spring,tick:n.tick,css:n.css}],schedule:"parallel"})}function S(e,n){const u=e.schedule??"parallel",f=e.springs.map(r=>{let t;switch(u){case"parallel":t=0;break;case"sequential":t=1;break;case"stagger":t=Math.max(0,Math.min(1,r.offset??0));break;default:t=0}const{css:i,offset:w,...g}=r,d=i?typeof i=="function"?n?{element:n,style:i}:void 0:{element:i.element,style:i.style}:void 0;return{...g,css:d,normalizedOffset:t}}),{schedule:k,...p}=e;return{...p,springs:f}}exports.isCssAnimation=o;exports.isMultiSpring=s;exports.isSingleSpring=h;exports.isTickAnimation=a;exports.normalizeMultiSpringSchedule=S;exports.normalizeToMultiSpring=m;exports.validateAnimationMode=c;exports.validateSpringItem=l;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function h(e){return("tick"in e||"css"in e)&&!("springs"in e)}function r(e){return"springs"in e}function o(e){return"css"in e&&typeof e.css=="function"}function c(e){return"tick"in e&&typeof e.tick=="function"}function a(e){if(o(e)&&c(e))throw new Error("SingleSpringConfig cannot have both 'tick' and 'css' defined. Use one or the other.")}function l(e){if(e.tick&&e.css)throw new Error("SpringItem cannot have both 'tick' and 'css' defined. Use one or the other.")}async function m(e){const t=await e;return r(t)?(t.springs.forEach(l),t):(a(t),{prepare:t.prepare,wait:t.wait,onStart:t.onStart,onEnd:t.onEnd,springs:[{physics:t.physics,tick:t.tick,css:t.css}],schedule:"parallel"})}function S(e,t){const u=e.schedule??"parallel",f=e.springs.map(s=>{let n;switch(u){case"parallel":n=0;break;case"sequential":n=1;break;case"stagger":n=Math.max(0,Math.min(1,s.offset??0));break;default:n=0}const{css:i,offset:y,...d}=s,g=i?typeof i=="function"?t?{element:t,style:i}:void 0:{element:i.element,style:i.style}:void 0;return{...d,css:g,normalizedOffset:n}}),{schedule:k,...p}=e;return{...p,springs:f}}exports.isCssAnimation=o;exports.isMultiSpring=r;exports.isSingleSpring=h;exports.isTickAnimation=c;exports.normalizeMultiSpringSchedule=S;exports.normalizeToMultiSpring=m;exports.validateAnimationMode=a;exports.validateSpringItem=l;
@@ -10,7 +10,7 @@ function p(n) {
10
10
  function u(n) {
11
11
  return "tick" in n && typeof n.tick == "function";
12
12
  }
13
- function g(n) {
13
+ function h(n) {
14
14
  if (p(n) && u(n))
15
15
  throw new Error(
16
16
  "SingleSpringConfig cannot have both 'tick' and 'css' defined. Use one or the other."
@@ -24,14 +24,14 @@ function d(n) {
24
24
  }
25
25
  async function S(n) {
26
26
  const e = await n;
27
- return f(e) ? (e.springs.forEach(d), e) : (g(e), {
27
+ return f(e) ? (e.springs.forEach(d), e) : (h(e), {
28
28
  prepare: e.prepare,
29
29
  wait: e.wait,
30
30
  onStart: e.onStart,
31
31
  onEnd: e.onEnd,
32
32
  springs: [
33
33
  {
34
- spring: e.spring,
34
+ physics: e.physics,
35
35
  tick: e.tick,
36
36
  css: e.css
37
37
  }
@@ -39,7 +39,7 @@ async function S(n) {
39
39
  schedule: "parallel"
40
40
  });
41
41
  }
42
- function w(n, e) {
42
+ function y(n, e) {
43
43
  const r = n.schedule ?? "parallel", a = n.springs.map(
44
44
  (s) => {
45
45
  let t;
@@ -59,7 +59,7 @@ function w(n, e) {
59
59
  const { css: i, offset: m, ...c } = s, l = i ? typeof i == "function" ? e ? { element: e, style: i } : void 0 : { element: i.element, style: i.style } : void 0;
60
60
  return { ...c, css: l, normalizedOffset: t };
61
61
  }
62
- ), { schedule: h, ...o } = n;
62
+ ), { schedule: g, ...o } = n;
63
63
  return {
64
64
  ...o,
65
65
  springs: a
@@ -70,8 +70,8 @@ export {
70
70
  f as isMultiSpring,
71
71
  k as isSingleSpring,
72
72
  u as isTickAnimation,
73
- w as normalizeMultiSpringSchedule,
73
+ y as normalizeMultiSpringSchedule,
74
74
  S as normalizeToMultiSpring,
75
- g as validateAnimationMode,
75
+ h as validateAnimationMode,
76
76
  d as validateSpringItem
77
77
  };
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@ssgoi/core"),i=r=>{if(!r.key)throw new Error("[ssgoi] transition() requires a 'key' property. Either provide it manually or use plugin for auto-injection. import plugin from @ssgoi/react/unplugin/webpack; ");return t.transition(r,"auto")};exports.transition=i;
2
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("@ssgoi/core"),t=e=>{if(!e.key)throw new Error("[ssgoi] transition() requires a 'key' property. Either provide it manually or use plugin for auto-injection. import plugin from @ssgoi/react/unplugin/webpack; see: https://ssgoi.dev/en/docs/core-concepts/react-plugin");return r.transition(e,"auto")};exports.transition=t;
@@ -1,11 +1,11 @@
1
1
  "use client";
2
- import { transition as i } from "@ssgoi/core";
2
+ import { transition as t } from "@ssgoi/core";
3
3
  const o = (r) => {
4
4
  if (!r.key)
5
5
  throw new Error(
6
- "[ssgoi] transition() requires a 'key' property. Either provide it manually or use plugin for auto-injection. import plugin from @ssgoi/react/unplugin/webpack; "
6
+ "[ssgoi] transition() requires a 'key' property. Either provide it manually or use plugin for auto-injection. import plugin from @ssgoi/react/unplugin/webpack; see: https://ssgoi.dev/en/docs/core-concepts/react-plugin"
7
7
  );
8
- return i(
8
+ return t(
9
9
  r,
10
10
  "auto"
11
11
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ssgoi/react",
3
- "version": "3.3.0",
3
+ "version": "4.0.0",
4
4
  "description": "React bindings for SSGOI - Native app-like page transitions for React applications",
5
5
  "private": false,
6
6
  "type": "module",
@@ -78,7 +78,7 @@
78
78
  "dependencies": {
79
79
  "unplugin": "^2.3.2",
80
80
  "@babel/core": "^7.26.10",
81
- "@ssgoi/core": "^3.3.0"
81
+ "@ssgoi/core": "^4.0.0"
82
82
  },
83
83
  "devDependencies": {
84
84
  "@types/babel__core": "^7.20.5",