@ssgoi/solid 6.4.0 → 6.6.4
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 +219 -0
- package/package.json +8 -2
- package/src/lib/context.tsx +14 -0
- package/src/lib/index.ts +5 -0
- package/src/lib/ssgoi-transition.tsx +34 -0
- package/src/lib/ssgoi.tsx +35 -0
- package/src/lib/types.ts +1 -0
- package/src/lib/view-transitions.ts +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# @ssgoi/solid
|
|
2
|
+
|
|
3
|
+
Solid bindings for SSGOI - Native app-like page transitions for Solid and SolidStart.
|
|
4
|
+
|
|
5
|
+
try this: [ssgoi.dev](https://ssgoi.dev)
|
|
6
|
+
|
|
7
|
+

|
|
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
|
+
|
|
19
|
+
## What is SSGOI?
|
|
20
|
+
|
|
21
|
+
SSGOI brings native app-like page transitions to the web. Transform your static page navigations into smooth, delightful experiences that users love.
|
|
22
|
+
|
|
23
|
+
### ✨ Key Features
|
|
24
|
+
|
|
25
|
+
- **🌍 Works Everywhere** - Unlike the browser's View Transition API, SSGOI works in all modern browsers (Chrome, Firefox, Safari)
|
|
26
|
+
- **🚀 SSR Ready** - Perfect compatibility with SolidStart. No hydration issues, SEO-friendly
|
|
27
|
+
- **🎯 Use Your Router** - Keep your existing routing. `@solidjs/router` and SolidStart work seamlessly
|
|
28
|
+
- **💾 State Persistence** - Remembers animation state during navigation, even with browser back/forward
|
|
29
|
+
- **⚡ Solid Native** - Built on Solid's fine-grained reactivity, so change detection stays minimal
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install @ssgoi/solid
|
|
35
|
+
# or
|
|
36
|
+
yarn add @ssgoi/solid
|
|
37
|
+
# or
|
|
38
|
+
pnpm add @ssgoi/solid
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Quick Start
|
|
42
|
+
|
|
43
|
+
### 1. Wrap your app
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { Ssgoi } from "@ssgoi/solid";
|
|
47
|
+
import { fade } from "@ssgoi/solid/view-transitions";
|
|
48
|
+
|
|
49
|
+
const config = {
|
|
50
|
+
transitions: [fade({ paths: ["/", "/about"] })],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default function App(props) {
|
|
54
|
+
return (
|
|
55
|
+
<Ssgoi config={config}>
|
|
56
|
+
{/* position: relative + z-index: 0 are required (see below) */}
|
|
57
|
+
<div style="position: relative; z-index: 0; min-height: 100vh">
|
|
58
|
+
{props.children}
|
|
59
|
+
</div>
|
|
60
|
+
</Ssgoi>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Mark your pages
|
|
66
|
+
|
|
67
|
+
Set `data-ssgoi-transition` on each page boundary element inside `<Ssgoi>`:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
export default function Home() {
|
|
71
|
+
return (
|
|
72
|
+
<main data-ssgoi-transition="/">
|
|
73
|
+
<h1>Welcome</h1>
|
|
74
|
+
{/* Page content */}
|
|
75
|
+
</main>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**That's it!** Your pages now transition smoothly with the configured effect.
|
|
81
|
+
|
|
82
|
+
> **Why `position: relative; z-index: 0`?** 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. The clone needs a positioned, stacking-context ancestor or it jumps / falls behind the background. Add `overflow-x-clip` too if you use horizontal transitions (`slide`, `drill`).
|
|
83
|
+
|
|
84
|
+
## Advanced Transitions
|
|
85
|
+
|
|
86
|
+
Each transition factory returns a path-transition group. Drop the results straight into `config.transitions` — nested arrays are flattened automatically:
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
import { Ssgoi } from "@ssgoi/solid";
|
|
90
|
+
import { fade, drill, zoom } from "@ssgoi/solid/view-transitions";
|
|
91
|
+
|
|
92
|
+
const config = {
|
|
93
|
+
transitions: [
|
|
94
|
+
// Calm cross-fade between tabs
|
|
95
|
+
fade({ paths: ["/", "/about"] }),
|
|
96
|
+
|
|
97
|
+
// iOS-style drill-in when entering a detail page
|
|
98
|
+
drill({ enter: "/products/*", exit: "/products" }),
|
|
99
|
+
|
|
100
|
+
// Card-to-detail zoom (needs matching data-zoom-*-key)
|
|
101
|
+
zoom({ paths: ["/gallery", "/photo/*"], type: "expand" }),
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Transitions come in three shapes:
|
|
107
|
+
|
|
108
|
+
- **`{ paths }`** — symmetric: every pair animates with the same physics (`fade`, `hero`, `zoom`, `blind`, `film`, `rotate`, `strip`, `jaemin`)
|
|
109
|
+
- **`{ enter, exit, type? }`** — directional: enter and exit get different physics (`drill`, `sheet`)
|
|
110
|
+
- **`{ paths }`** — ordered: path order decides forward / back direction (`slide`, `scroll`, `axis`)
|
|
111
|
+
|
|
112
|
+
## SolidStart Example
|
|
113
|
+
|
|
114
|
+
Wrap your root component once, then mark each route:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
// src/app.tsx
|
|
118
|
+
import { Router } from "@solidjs/router";
|
|
119
|
+
import { FileRoutes } from "@solidjs/start/router";
|
|
120
|
+
import { Ssgoi } from "@ssgoi/solid";
|
|
121
|
+
import { scroll } from "@ssgoi/solid/view-transitions";
|
|
122
|
+
|
|
123
|
+
const config = {
|
|
124
|
+
transitions: [scroll({ paths: ["/", "/about", "/products"] })],
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default function App() {
|
|
128
|
+
return (
|
|
129
|
+
<Router
|
|
130
|
+
root={(props) => (
|
|
131
|
+
<Ssgoi config={config}>
|
|
132
|
+
<div style="position: relative; z-index: 0; min-height: 100vh">
|
|
133
|
+
{props.children}
|
|
134
|
+
</div>
|
|
135
|
+
</Ssgoi>
|
|
136
|
+
)}
|
|
137
|
+
>
|
|
138
|
+
<FileRoutes />
|
|
139
|
+
</Router>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
// src/routes/index.tsx
|
|
146
|
+
export default function Index() {
|
|
147
|
+
return <main data-ssgoi-transition="/">{/* Your page content */}</main>;
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## API Reference
|
|
152
|
+
|
|
153
|
+
### `<Ssgoi>`
|
|
154
|
+
|
|
155
|
+
The provider component that manages transition context.
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
<Ssgoi config={ssgoiConfig}>{/* children */}</Ssgoi>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Props:
|
|
162
|
+
|
|
163
|
+
- `config: SsgoiConfig` - transition configuration object
|
|
164
|
+
- `host?: HostAnimation` - optional external playback host for debug tooling
|
|
165
|
+
|
|
166
|
+
### `data-ssgoi-transition`
|
|
167
|
+
|
|
168
|
+
Attribute for pages that should transition. Set it on the page boundary element inside `<Ssgoi>` — the value (commonly the route path) uniquely identifies the view.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<main data-ssgoi-transition="/page-id">{/* children */}</main>
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Built-in Transitions
|
|
175
|
+
|
|
176
|
+
Import from `@ssgoi/solid/view-transitions`:
|
|
177
|
+
|
|
178
|
+
- `fade()` - Calm cross-fade. Safe default for unrelated pages
|
|
179
|
+
- `drill()` - iOS-style hierarchical navigation (list → detail)
|
|
180
|
+
- `slide()` - Horizontal push for tabs / sequential flows
|
|
181
|
+
- `scroll()` - Vertical page scroll for onboarding / paginated views
|
|
182
|
+
- `axis()` - Material/Flutter shared-axis swap for sibling/tab routes
|
|
183
|
+
- `sheet()` - Bottom sheet that slides up (modal-like flows)
|
|
184
|
+
- `hero()` - Shared element transition (matching `data-hero-enter-key` / `data-hero-exit-key`)
|
|
185
|
+
- `zoom()` - Card-to-detail expansion (matching `data-zoom-enter-key` / `data-zoom-exit-key`)
|
|
186
|
+
- `strip()` - 3D Y-axis perspective flip
|
|
187
|
+
- `blind()` - Window-blinds wipe reveal
|
|
188
|
+
- `film()` - Cinematic shrink + tile (gallery / lightbox)
|
|
189
|
+
- `rotate()` - Card flip between siblings
|
|
190
|
+
- `jaemin()` - Playful rotated zoom for special moments
|
|
191
|
+
|
|
192
|
+
## TypeScript Support
|
|
193
|
+
|
|
194
|
+
SSGOI is written in TypeScript and provides full type definitions:
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
import type { SsgoiConfig } from "@ssgoi/solid";
|
|
198
|
+
|
|
199
|
+
const config: SsgoiConfig = {
|
|
200
|
+
// Full type safety
|
|
201
|
+
};
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Browser Support
|
|
205
|
+
|
|
206
|
+
- Chrome/Edge 88+
|
|
207
|
+
- Firefox 78+
|
|
208
|
+
- Safari 14+
|
|
209
|
+
- All modern mobile browsers
|
|
210
|
+
|
|
211
|
+
## License
|
|
212
|
+
|
|
213
|
+
MIT © [MeurSyphus](https://github.com/meursyphus)
|
|
214
|
+
|
|
215
|
+
## Links
|
|
216
|
+
|
|
217
|
+
- [Documentation](https://ssgoi.dev)
|
|
218
|
+
- [GitHub](https://github.com/meursyphus/ssgoi)
|
|
219
|
+
- [Issues](https://github.com/meursyphus/ssgoi/issues)
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssgoi/solid",
|
|
3
|
-
"version": "6.4
|
|
3
|
+
"version": "6.6.4",
|
|
4
4
|
"description": "Solid.js bindings for SSGOI - Native app-like page transitions for Solid applications",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
+
"src/lib",
|
|
8
9
|
"dist",
|
|
10
|
+
"!src/**/*.test.*",
|
|
11
|
+
"!src/**/*.spec.*",
|
|
9
12
|
"!dist/**/*.test.*",
|
|
10
13
|
"!dist/**/*.spec.*"
|
|
11
14
|
],
|
|
@@ -14,18 +17,21 @@
|
|
|
14
17
|
"types": "./dist/index.d.ts",
|
|
15
18
|
"exports": {
|
|
16
19
|
".": {
|
|
20
|
+
"solid": "./src/lib/index.ts",
|
|
17
21
|
"types": "./dist/index.d.ts",
|
|
18
22
|
"import": "./dist/index.js",
|
|
19
23
|
"require": "./dist/index.cjs",
|
|
20
24
|
"default": "./dist/index.js"
|
|
21
25
|
},
|
|
22
26
|
"./types": {
|
|
27
|
+
"solid": "./src/lib/types.ts",
|
|
23
28
|
"types": "./dist/types.d.ts",
|
|
24
29
|
"import": "./dist/types.js",
|
|
25
30
|
"require": "./dist/types.cjs",
|
|
26
31
|
"default": "./dist/types.js"
|
|
27
32
|
},
|
|
28
33
|
"./view-transitions": {
|
|
34
|
+
"solid": "./src/lib/view-transitions.ts",
|
|
29
35
|
"types": "./dist/view-transitions.d.ts",
|
|
30
36
|
"import": "./dist/view-transitions.js",
|
|
31
37
|
"require": "./dist/view-transitions.cjs",
|
|
@@ -33,7 +39,7 @@
|
|
|
33
39
|
}
|
|
34
40
|
},
|
|
35
41
|
"dependencies": {
|
|
36
|
-
"@ssgoi/core": "^6.4
|
|
42
|
+
"@ssgoi/core": "^6.6.4"
|
|
37
43
|
},
|
|
38
44
|
"devDependencies": {
|
|
39
45
|
"@eslint/js": "^9.30.1",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext, useContext } from "solid-js";
|
|
2
|
+
import type { SsgoiContext } from "./types";
|
|
3
|
+
|
|
4
|
+
const SsgoiContextInstance = createContext<SsgoiContext | null>(null);
|
|
5
|
+
|
|
6
|
+
export const SsgoiProvider = SsgoiContextInstance.Provider;
|
|
7
|
+
|
|
8
|
+
export const useSsgoi = () => {
|
|
9
|
+
const context = useContext(SsgoiContextInstance);
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error("useSsgoi must be used within SsgoiProvider");
|
|
12
|
+
}
|
|
13
|
+
return context;
|
|
14
|
+
};
|
package/src/lib/index.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { splitProps, type JSX, type ValidComponent } from "solid-js";
|
|
2
|
+
import { Dynamic } from "solid-js/web";
|
|
3
|
+
import { useSsgoi } from "./context";
|
|
4
|
+
|
|
5
|
+
type SsgoiTransitionProps<T extends ValidComponent = "div"> = {
|
|
6
|
+
children: JSX.Element;
|
|
7
|
+
id: string;
|
|
8
|
+
as?: T;
|
|
9
|
+
class?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @deprecated Set `data-ssgoi-transition` directly on the page boundary
|
|
14
|
+
* element inside `<Ssgoi>` instead.
|
|
15
|
+
*/
|
|
16
|
+
export const SsgoiTransition = <T extends ValidComponent = "div">(
|
|
17
|
+
props: SsgoiTransitionProps<T>,
|
|
18
|
+
) => {
|
|
19
|
+
const [local, rest] = splitProps(props, ["children", "id", "as", "class"]);
|
|
20
|
+
const ssgoi = useSsgoi();
|
|
21
|
+
const component = (local.as || "div") as ValidComponent;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Dynamic
|
|
25
|
+
component={component}
|
|
26
|
+
ref={ssgoi.refFor(local.id)}
|
|
27
|
+
data-ssgoi-transition={local.id}
|
|
28
|
+
class={local.class}
|
|
29
|
+
{...(rest as object)}
|
|
30
|
+
>
|
|
31
|
+
{local.children}
|
|
32
|
+
</Dynamic>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createEffect, createMemo, onCleanup, type JSX } from "solid-js";
|
|
2
|
+
import type { SsgoiConfig, SsgoiContext } from "./types";
|
|
3
|
+
import { SsgoiProvider } from "./context";
|
|
4
|
+
import {
|
|
5
|
+
createSggoiTransitionContext,
|
|
6
|
+
observeSsgoiTransitions,
|
|
7
|
+
} from "@ssgoi/core/internal";
|
|
8
|
+
import type { HostAnimation } from "@ssgoi/core/internal";
|
|
9
|
+
|
|
10
|
+
interface SsgoiProps {
|
|
11
|
+
config: SsgoiConfig;
|
|
12
|
+
host?: HostAnimation;
|
|
13
|
+
children: JSX.Element;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Ssgoi = (props: SsgoiProps) => {
|
|
17
|
+
let root!: HTMLDivElement;
|
|
18
|
+
const contextValue = createMemo<SsgoiContext>(() =>
|
|
19
|
+
createSggoiTransitionContext(props.config, { host: props.host }),
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
createEffect(() => {
|
|
23
|
+
if (!root) return;
|
|
24
|
+
const cleanup = observeSsgoiTransitions(root, contextValue());
|
|
25
|
+
onCleanup(cleanup);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<SsgoiProvider value={contextValue()}>
|
|
30
|
+
<div ref={root} data-ssgoi-root="" style={{ display: "contents" }}>
|
|
31
|
+
{props.children}
|
|
32
|
+
</div>
|
|
33
|
+
</SsgoiProvider>
|
|
34
|
+
);
|
|
35
|
+
};
|
package/src/lib/types.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@ssgoi/core/types";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@ssgoi/core";
|