@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 CHANGED
@@ -6,6 +6,16 @@ try this: [ssgoi.dev](https://ssgoi.dev)
6
6
 
7
7
  ![https://ssgoi.dev](https://ssgoi.dev/ssgoi.gif)
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={{ transitions: fade({ paths: ["/", "/about"] }) }}>
42
- <div style={{ position: "relative" }}>{/* Your app */}</div>
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. Wrap your pages
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
- <SsgoiTransition id="/">
68
+ <main data-ssgoi-transition="/">
56
69
  <h1>Welcome</h1>
57
70
  {/* Page content */}
58
- </SsgoiTransition>
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
- Define different transitions for different routes:
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
- // Scroll between tabs
75
- { from: "/home", to: "/about", transition: scroll({ direction: "up" }) },
76
- { from: "/about", to: "/home", transition: scroll({ direction: "down" }) },
77
-
78
- // Drill in when entering details
79
- {
80
- from: "/products",
81
- to: "/products/*",
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
- ### Symmetric Transitions
107
+ Transitions come in three shapes:
92
108
 
93
- Automatically create bidirectional transitions:
94
-
95
- ```tsx
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 { scroll } from "@ssgoi/react/view-transitions";
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({ children }) {
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
- config={{
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 <SsgoiTransition id="/">{/* Your page content */}</SsgoiTransition>;
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
- #### `<SsgoiTransition>`
283
+ #### `data-ssgoi-transition`
270
284
 
271
- Wrapper component for pages that should transition.
285
+ Attribute for pages that should transition. Set it on the page boundary element
286
+ inside `<Ssgoi>`.
272
287
 
273
288
  ```tsx
274
- <SsgoiTransition id="/page-id">{children}</SsgoiTransition>
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()` - Smooth opacity transition
310
- - `scroll()` - Vertical scrolling (up/down)
311
- - `drill()` - Drill in/out effect (enter/exit)
312
- - `hero()` - Shared element transitions
313
- - `pinterest()` - Pinterest-style expand effect
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 c=require("react/jsx-runtime"),u=require("./context.cjs"),a=({children:o,id:t,as:e,className:n,...s})=>{const{refFor:i}=u.useSsgoi(),r=e||"div";return c.jsx(r,{ref:i(t),"data-ssgoi-transition":t,className:n,...s,children:o})};exports.SsgoiTransition=a;
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
- * The ssgoi context hands out a stable, path-bound ref callback via
12
- * `refFor(id)` — the same function reference across renders for the same
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 e } from "react/jsx-runtime";
3
- import { useSsgoi as m } from "./context.js";
4
- const c = ({
5
- children: t,
6
- id: o,
7
- as: n,
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
- c as SsgoiTransition
11
+ m as SsgoiTransition
25
12
  };
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),o=require("react"),n=require("./context.cjs"),u=require("@ssgoi/core/internal"),c=o.memo(({config:e,host:t,children:r})=>{const i=o.useMemo(()=>u.createSggoiTransitionContext(e,{host:t}),[e,t]);return s.jsx(n.SsgoiProvider,{value:i,children:r})});exports.Ssgoi=c;
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 m } from "react/jsx-runtime";
3
- import i, { useMemo as s } from "react";
4
- import { SsgoiProvider as n } from "./context.js";
5
- import { createSggoiTransitionContext as p } from "@ssgoi/core/internal";
6
- const u = i.memo(
7
- ({ config: o, host: r, children: t }) => {
8
- const e = s(
9
- () => p(o, { host: r }),
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 /* @__PURE__ */ m(n, { value: e, children: t });
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
- u as Ssgoi
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.0",
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.3.0"
69
+ "@ssgoi/core": "^6.5.0-beta.0"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/babel__core": "^7.20.5",
@@ -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;
@@ -1,3 +0,0 @@
1
- import { SsgoiContext } from '@ssgoi/core/types';
2
- export declare const SsgoiProvider: import('react').Provider<SsgoiContext | null>;
3
- export declare const useSsgoi: () => SsgoiContext;
@@ -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
- };