@ssgoi/react 6.3.0 → 6.5.0-beta.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 +77 -54
- package/dist/lib/ssgoi-transition.cjs +1 -1
- package/dist/lib/ssgoi-transition.d.ts +2 -5
- package/dist/lib/ssgoi-transition.js +8 -21
- package/dist/lib/ssgoi.cjs +1 -1
- package/dist/lib/ssgoi.js +14 -11
- package/package.json +2 -2
- package/dist/lib/context.cjs +0 -2
- package/dist/lib/context.d.ts +0 -3
- package/dist/lib/context.js +0 -11
package/README.md
CHANGED
|
@@ -6,6 +6,16 @@ try this: [ssgoi.dev](https://ssgoi.dev)
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
+
## AI-Assisted Setup
|
|
10
|
+
|
|
11
|
+
Using Claude, Cursor, ChatGPT, or another AI assistant? Point it at:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
https://ssgoi.dev/llms.txt
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
It has the full setup guide, every transition, the API, and troubleshooting — everything an agent needs to wire SSGOI into your app.
|
|
18
|
+
|
|
9
19
|
## What is SSGOI?
|
|
10
20
|
|
|
11
21
|
SSGOI brings native app-like page transitions to the web. Transform your static page navigations into smooth, delightful experiences that users love.
|
|
@@ -36,74 +46,73 @@ pnpm add @ssgoi/react
|
|
|
36
46
|
import { Ssgoi } from "@ssgoi/react";
|
|
37
47
|
import { fade } from "@ssgoi/react/view-transitions";
|
|
38
48
|
|
|
49
|
+
const config = {
|
|
50
|
+
transitions: [fade({ paths: ["/", "/about"] })],
|
|
51
|
+
};
|
|
52
|
+
|
|
39
53
|
export default function App() {
|
|
40
54
|
return (
|
|
41
|
-
<Ssgoi config={
|
|
42
|
-
|
|
55
|
+
<Ssgoi config={config}>
|
|
56
|
+
{/* relative + z-0 are required (see "Layout Requirements" below) */}
|
|
57
|
+
<div className="relative z-0">{/* Your app */}</div>
|
|
43
58
|
</Ssgoi>
|
|
44
59
|
);
|
|
45
60
|
}
|
|
46
61
|
```
|
|
47
62
|
|
|
48
|
-
### 2.
|
|
63
|
+
### 2. Mark your pages
|
|
49
64
|
|
|
50
65
|
```tsx
|
|
51
|
-
import { SsgoiTransition } from "@ssgoi/react";
|
|
52
|
-
|
|
53
66
|
export default function HomePage() {
|
|
54
67
|
return (
|
|
55
|
-
<
|
|
68
|
+
<main data-ssgoi-transition="/">
|
|
56
69
|
<h1>Welcome</h1>
|
|
57
70
|
{/* Page content */}
|
|
58
|
-
</
|
|
71
|
+
</main>
|
|
59
72
|
);
|
|
60
73
|
}
|
|
61
74
|
```
|
|
62
75
|
|
|
63
76
|
**That's it!** Your configured pages now transition smoothly with a fade effect.
|
|
64
77
|
|
|
78
|
+
## Layout Requirements
|
|
79
|
+
|
|
80
|
+
The element wrapping `<Ssgoi>` needs `position: relative` and `z-index: 0` (`relative z-0` in Tailwind).
|
|
81
|
+
|
|
82
|
+
When a page leaves, SSGOI clones it back into the DOM with `position: absolute` so it can animate out while the new page animates in. Without a positioned, stacking-context ancestor the clone jumps to the wrong place or falls behind the background. Add `overflow-x-clip` too if you use horizontal transitions (`slide`, `drill`).
|
|
83
|
+
|
|
65
84
|
## Advanced Transitions
|
|
66
85
|
|
|
67
86
|
### Route-based Transitions
|
|
68
87
|
|
|
69
|
-
|
|
88
|
+
Each transition factory returns a path-transition group. Drop the results straight into `config.transitions` — nested arrays are flattened automatically:
|
|
70
89
|
|
|
71
90
|
```tsx
|
|
91
|
+
import { fade, drill, zoom } from "@ssgoi/react/view-transitions";
|
|
92
|
+
|
|
72
93
|
const config = {
|
|
73
94
|
transitions: [
|
|
74
|
-
//
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
transition: drill({ direction: "enter" }),
|
|
83
|
-
},
|
|
84
|
-
|
|
85
|
-
// Pinterest-style image transitions
|
|
86
|
-
{ from: "/gallery", to: "/photo/*", transition: pinterest() },
|
|
95
|
+
// Calm cross-fade between tabs
|
|
96
|
+
fade({ paths: ["/home", "/about"] }),
|
|
97
|
+
|
|
98
|
+
// iOS-style drill-in when entering details
|
|
99
|
+
drill({ enter: "/products/*", exit: "/products" }),
|
|
100
|
+
|
|
101
|
+
// Card-to-detail zoom (needs matching data-zoom-*-key)
|
|
102
|
+
zoom({ paths: ["/gallery", "/photo/*"], type: "expand" }),
|
|
87
103
|
],
|
|
88
104
|
};
|
|
89
105
|
```
|
|
90
106
|
|
|
91
|
-
|
|
107
|
+
Transitions come in three shapes:
|
|
92
108
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
{
|
|
97
|
-
from: '/home',
|
|
98
|
-
to: '/about',
|
|
99
|
-
transition: scroll({ direction: 'up' }),
|
|
100
|
-
symmetric: true // Automatically creates reverse transition
|
|
101
|
-
}
|
|
102
|
-
```
|
|
109
|
+
- **`{ paths }`** — symmetric: every pair animates with the same physics (`fade`, `hero`, `zoom`, `blind`, `film`, `rotate`, `strip`, `jaemin`)
|
|
110
|
+
- **`{ enter, exit, type? }`** — directional: enter and exit get different physics (`drill`, `sheet`)
|
|
111
|
+
- **`{ paths }`** — ordered: path order decides forward / back direction (`slide`, `scroll`, `axis`)
|
|
103
112
|
|
|
104
113
|
### Individual Element Animations
|
|
105
114
|
|
|
106
|
-
Animate specific elements during mount/unmount
|
|
115
|
+
Animate specific elements during mount/unmount with `transition()`:
|
|
107
116
|
|
|
108
117
|
```tsx
|
|
109
118
|
import { transition } from "@ssgoi/react";
|
|
@@ -226,31 +235,36 @@ function List() {
|
|
|
226
235
|
```tsx
|
|
227
236
|
// app/layout.tsx
|
|
228
237
|
import { Ssgoi } from "@ssgoi/react";
|
|
229
|
-
import {
|
|
238
|
+
import { drill, fade } from "@ssgoi/react/view-transitions";
|
|
239
|
+
|
|
240
|
+
const config = {
|
|
241
|
+
transitions: [
|
|
242
|
+
drill({ enter: "/post/*", exit: "*" }),
|
|
243
|
+
fade({ paths: ["/", "/about"] }),
|
|
244
|
+
],
|
|
245
|
+
};
|
|
230
246
|
|
|
231
|
-
export default function RootLayout({
|
|
247
|
+
export default function RootLayout({
|
|
248
|
+
children,
|
|
249
|
+
}: {
|
|
250
|
+
children: React.ReactNode;
|
|
251
|
+
}) {
|
|
232
252
|
return (
|
|
233
253
|
<html>
|
|
234
254
|
<body>
|
|
235
|
-
<Ssgoi
|
|
236
|
-
|
|
237
|
-
transitions: scroll({ paths: ["/", "/about"] }),
|
|
238
|
-
}}
|
|
239
|
-
>
|
|
240
|
-
<div style={{ position: "relative", minHeight: "100vh" }}>
|
|
241
|
-
{children}
|
|
242
|
-
</div>
|
|
255
|
+
<Ssgoi config={config}>
|
|
256
|
+
<div className="relative z-0 min-h-screen">{children}</div>
|
|
243
257
|
</Ssgoi>
|
|
244
258
|
</body>
|
|
245
259
|
</html>
|
|
246
260
|
);
|
|
247
261
|
}
|
|
262
|
+
```
|
|
248
263
|
|
|
264
|
+
```tsx
|
|
249
265
|
// app/page.tsx
|
|
250
|
-
import { SsgoiTransition } from "@ssgoi/react";
|
|
251
|
-
|
|
252
266
|
export default function Page() {
|
|
253
|
-
return <
|
|
267
|
+
return <main data-ssgoi-transition="/">{/* Your page content */}</main>;
|
|
254
268
|
}
|
|
255
269
|
```
|
|
256
270
|
|
|
@@ -266,12 +280,13 @@ The provider component that manages transition context.
|
|
|
266
280
|
<Ssgoi config={ssgoiConfig}>{children}</Ssgoi>
|
|
267
281
|
```
|
|
268
282
|
|
|
269
|
-
####
|
|
283
|
+
#### `data-ssgoi-transition`
|
|
270
284
|
|
|
271
|
-
|
|
285
|
+
Attribute for pages that should transition. Set it on the page boundary element
|
|
286
|
+
inside `<Ssgoi>`.
|
|
272
287
|
|
|
273
288
|
```tsx
|
|
274
|
-
<
|
|
289
|
+
<main data-ssgoi-transition="/page-id">{children}</main>
|
|
275
290
|
```
|
|
276
291
|
|
|
277
292
|
### Hooks
|
|
@@ -306,11 +321,19 @@ Apply transitions to individual elements.
|
|
|
306
321
|
|
|
307
322
|
### Page Transitions (`@ssgoi/react/view-transitions`)
|
|
308
323
|
|
|
309
|
-
- `fade()` -
|
|
310
|
-
- `
|
|
311
|
-
- `
|
|
312
|
-
- `
|
|
313
|
-
- `
|
|
324
|
+
- `fade()` - Calm cross-fade. Safe default for unrelated pages
|
|
325
|
+
- `drill()` - iOS-style hierarchical navigation (list → detail)
|
|
326
|
+
- `slide()` - Horizontal push for tabs / sequential flows
|
|
327
|
+
- `scroll()` - Vertical page scroll for onboarding / paginated views
|
|
328
|
+
- `axis()` - Material/Flutter shared-axis swap for sibling/tab routes
|
|
329
|
+
- `sheet()` - Bottom sheet that slides up (modal-like flows)
|
|
330
|
+
- `hero()` - Shared element transition (matching `data-hero-enter-key` / `data-hero-exit-key`)
|
|
331
|
+
- `zoom()` - Card-to-detail expansion (matching `data-zoom-enter-key` / `data-zoom-exit-key`)
|
|
332
|
+
- `strip()` - 3D Y-axis perspective flip
|
|
333
|
+
- `blind()` - Window-blinds wipe reveal
|
|
334
|
+
- `film()` - Cinematic shrink + tile (gallery / lightbox)
|
|
335
|
+
- `rotate()` - Card flip between siblings
|
|
336
|
+
- `jaemin()` - Playful rotated zoom for special moments
|
|
314
337
|
|
|
315
338
|
### Element Transitions (`@ssgoi/react/transitions`)
|
|
316
339
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),a=({children:t,id:i,as:n,className:o,...s})=>{const e=n||"div";return r.jsx(e,{"data-ssgoi-transition":i,className:o,...s,children:t})};exports.SsgoiTransition=a;
|
|
@@ -8,11 +8,8 @@ type SsgoiTransitionProps<T extends ElementType = "div"> = {
|
|
|
8
8
|
/**
|
|
9
9
|
* Marks a subtree as a Ssgoi page boundary.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* id, so React doesn't see a fresh ref each commit and won't churn the
|
|
14
|
-
* attach/detach cycle. Unmount is detected internally via the shared
|
|
15
|
-
* MutationObserver in the dispatcher; nothing extra to wire up here.
|
|
11
|
+
* @deprecated Set `data-ssgoi-transition` directly on the page boundary
|
|
12
|
+
* element inside `<Ssgoi>` instead.
|
|
16
13
|
*/
|
|
17
14
|
export declare const SsgoiTransition: <T extends ElementType = "div">({ children, id, as, className, ...rest }: SsgoiTransitionProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
18
15
|
export {};
|
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
className: r,
|
|
2
|
+
import { jsx as r } from "react/jsx-runtime";
|
|
3
|
+
const m = ({
|
|
4
|
+
children: o,
|
|
5
|
+
id: n,
|
|
6
|
+
as: t,
|
|
7
|
+
className: i,
|
|
9
8
|
...s
|
|
10
|
-
}) => {
|
|
11
|
-
const { refFor: i } = m();
|
|
12
|
-
return /* @__PURE__ */ e(
|
|
13
|
-
n || "div",
|
|
14
|
-
{
|
|
15
|
-
ref: i(o),
|
|
16
|
-
"data-ssgoi-transition": o,
|
|
17
|
-
className: r,
|
|
18
|
-
...s,
|
|
19
|
-
children: t
|
|
20
|
-
}
|
|
21
|
-
);
|
|
22
|
-
};
|
|
9
|
+
}) => /* @__PURE__ */ r(t || "div", { "data-ssgoi-transition": n, className: i, ...s, children: o });
|
|
23
10
|
export {
|
|
24
|
-
|
|
11
|
+
m as SsgoiTransition
|
|
25
12
|
};
|
package/dist/lib/ssgoi.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
2
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react/jsx-runtime"),e=require("react"),i=require("@ssgoi/core/internal"),a={display:"contents"},l=e.memo(({config:t,host:o,children:u})=>{const r=e.useRef(null),s=e.useMemo(()=>i.createSggoiTransitionContext(t,{host:o}),[t,o]);return e.useEffect(()=>{const n=r.current;if(n)return i.observeSsgoiTransitions(n,s)},[s]),c.jsx("div",{ref:r,"data-ssgoi-root":"",style:a,children:u})});exports.Ssgoi=l;
|
package/dist/lib/ssgoi.js
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
[o, r]
|
|
2
|
+
import { jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import c, { useRef as m, useMemo as f, useEffect as u } from "react";
|
|
4
|
+
import { createSggoiTransitionContext as a, observeSsgoiTransitions as g } from "@ssgoi/core/internal";
|
|
5
|
+
const l = { display: "contents" }, x = c.memo(
|
|
6
|
+
({ config: o, host: t, children: n }) => {
|
|
7
|
+
const r = m(null), e = f(
|
|
8
|
+
() => a(o, { host: t }),
|
|
9
|
+
[o, t]
|
|
11
10
|
);
|
|
12
|
-
return
|
|
11
|
+
return u(() => {
|
|
12
|
+
const s = r.current;
|
|
13
|
+
if (s)
|
|
14
|
+
return g(s, e);
|
|
15
|
+
}, [e]), /* @__PURE__ */ i("div", { ref: r, "data-ssgoi-root": "", style: l, children: n });
|
|
13
16
|
}
|
|
14
17
|
);
|
|
15
18
|
export {
|
|
16
|
-
|
|
19
|
+
x as Ssgoi
|
|
17
20
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssgoi/react",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0-beta.0",
|
|
4
4
|
"description": "React bindings for SSGOI - Native app-like page transitions for React applications",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"unplugin": "^2.3.2",
|
|
68
68
|
"@babel/core": "^7.26.10",
|
|
69
|
-
"@ssgoi/core": "^6.
|
|
69
|
+
"@ssgoi/core": "^6.5.0-beta.0"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
72
|
"@types/babel__core": "^7.20.5",
|
package/dist/lib/context.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("react"),t=o.createContext(null),r=t.Provider,s=()=>{const e=o.useContext(t);if(!e)throw new Error("useSsgoi must be used within Ssgoi provider");return e};exports.SsgoiProvider=r;exports.useSsgoi=s;
|
package/dist/lib/context.d.ts
DELETED
package/dist/lib/context.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { createContext as e, useContext as r } from "react";
|
|
3
|
-
const t = e(null), n = t.Provider, i = () => {
|
|
4
|
-
const o = r(t);
|
|
5
|
-
if (!o) throw new Error("useSsgoi must be used within Ssgoi provider");
|
|
6
|
-
return o;
|
|
7
|
-
};
|
|
8
|
-
export {
|
|
9
|
-
n as SsgoiProvider,
|
|
10
|
-
i as useSsgoi
|
|
11
|
-
};
|