@ssgoi/core 0.0.3 → 2.1.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 +252 -23
- package/dist/animator.d.ts +28 -17
- package/dist/animator.d.ts.map +1 -1
- package/dist/create-ssgoi-transition-context.d.ts.map +1 -1
- package/dist/create-transition-callback.d.ts +3 -32
- package/dist/create-transition-callback.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +374 -213
- package/dist/presets/index.cjs +1 -0
- package/dist/presets/index.d.ts +16 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +35 -0
- package/dist/transition-strategy.d.ts +60 -0
- package/dist/transition-strategy.d.ts.map +1 -0
- package/dist/transition.d.ts +55 -11
- package/dist/transition.d.ts.map +1 -1
- package/dist/transitions/blur.d.ts +5 -1
- package/dist/transitions/blur.d.ts.map +1 -1
- package/dist/transitions/bounce.d.ts +5 -0
- package/dist/transitions/bounce.d.ts.map +1 -1
- package/dist/transitions/fade.d.ts +3 -0
- package/dist/transitions/fade.d.ts.map +1 -1
- package/dist/transitions/fly.d.ts +30 -0
- package/dist/transitions/fly.d.ts.map +1 -0
- package/dist/transitions/index.cjs +1 -1
- package/dist/transitions/index.d.ts +1 -0
- package/dist/transitions/index.d.ts.map +1 -1
- package/dist/transitions/index.js +200 -120
- package/dist/transitions/none.d.ts +3 -0
- package/dist/transitions/none.d.ts.map +1 -1
- package/dist/transitions/rotate.d.ts +6 -0
- package/dist/transitions/rotate.d.ts.map +1 -1
- package/dist/transitions/scale.d.ts +6 -3
- package/dist/transitions/scale.d.ts.map +1 -1
- package/dist/transitions/slide.d.ts +6 -1
- package/dist/transitions/slide.d.ts.map +1 -1
- package/dist/types.d.ts +19 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils-8Eptbv7c.cjs +2 -0
- package/dist/utils-DTRMUQW4.js +31 -0
- package/dist/utils.d.ts +11 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/view-transitions/drill.d.ts +9 -0
- package/dist/view-transitions/drill.d.ts.map +1 -0
- package/dist/view-transitions/fade.d.ts +3 -1
- package/dist/view-transitions/fade.d.ts.map +1 -1
- package/dist/view-transitions/hero.d.ts.map +1 -1
- package/dist/view-transitions/index.cjs +1 -1
- package/dist/view-transitions/index.d.ts +2 -1
- package/dist/view-transitions/index.d.ts.map +1 -1
- package/dist/view-transitions/index.js +233 -177
- package/dist/view-transitions/scroll.d.ts +8 -0
- package/dist/view-transitions/scroll.d.ts.map +1 -0
- package/package.json +28 -10
- package/dist/utils-BSgyev81.cjs +0 -1
- package/dist/utils-DR41YsAh.js +0 -16
package/README.md
CHANGED
|
@@ -1,34 +1,263 @@
|
|
|
1
|
-
#
|
|
1
|
+
# SSGOI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## What is SSGOI?
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
SSGOI brings native app-like page transitions to the web. Transform your static page navigations into smooth, delightful experiences that users love.
|
|
6
|
+
|
|
7
|
+
try this: [ssgoi.dev](https://ssgoi.dev)
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
### ✨ Key Features
|
|
12
|
+
|
|
13
|
+
- **🌍 Works Everywhere** - Unlike the browser's View Transition API, SSGOI works in all modern browsers (Chrome, Firefox, Safari)
|
|
14
|
+
- **🚀 SSR Ready** - Perfect compatibility with Next.js, Nuxt, SvelteKit. No hydration issues, SEO-friendly
|
|
15
|
+
- **🎯 Use Your Router** - Keep your existing routing. React Router, Next.js App Router, SvelteKit - all work seamlessly
|
|
16
|
+
- **💾 State Persistence** - Remembers animation state during navigation, even with browser back/forward
|
|
17
|
+
- **🎨 Framework Agnostic** - One consistent API for React, Svelte, Vue, SolidJS, and more
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
### Installation
|
|
6
22
|
|
|
7
23
|
```bash
|
|
8
|
-
#
|
|
9
|
-
|
|
24
|
+
# React
|
|
25
|
+
npm install @ssgoi/react
|
|
26
|
+
|
|
27
|
+
# Svelte
|
|
28
|
+
npm install @ssgoi/svelte
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Add Transitions in 30 Seconds
|
|
32
|
+
|
|
33
|
+
#### 1. Wrap your app
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { Ssgoi } from '@ssgoi/react';
|
|
37
|
+
import { fade } from '@ssgoi/react/view-transitions';
|
|
38
|
+
|
|
39
|
+
export default function App() {
|
|
40
|
+
return (
|
|
41
|
+
<Ssgoi config={{ defaultTransition: fade() }}>
|
|
42
|
+
<div style={{ position: 'relative' }}>
|
|
43
|
+
{/* Your app */}
|
|
44
|
+
</div>
|
|
45
|
+
</Ssgoi>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### 2. Wrap your pages
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import { SsgoiTransition } from '@ssgoi/react';
|
|
54
|
+
|
|
55
|
+
export default function HomePage() {
|
|
56
|
+
return (
|
|
57
|
+
<SsgoiTransition id="/">
|
|
58
|
+
<h1>Welcome</h1>
|
|
59
|
+
{/* Page content */}
|
|
60
|
+
</SsgoiTransition>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**That's it!** Your pages now transition smoothly with a fade effect.
|
|
66
|
+
|
|
67
|
+
## Advanced Transitions
|
|
68
|
+
|
|
69
|
+
### Route-based Transitions
|
|
70
|
+
|
|
71
|
+
Define different transitions for different routes:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
const config = {
|
|
75
|
+
transitions: [
|
|
76
|
+
// Slide between tabs
|
|
77
|
+
{ from: '/home', to: '/about', transition: slide({ direction: 'left' }) },
|
|
78
|
+
{ from: '/about', to: '/home', transition: slide({ direction: 'right' }) },
|
|
79
|
+
|
|
80
|
+
// Scale up when entering details
|
|
81
|
+
{ from: '/products', to: '/products/*', transition: scale() },
|
|
82
|
+
|
|
83
|
+
// Pinterest-style image transitions
|
|
84
|
+
{ from: '/gallery', to: '/photo/*', transition: pinterest() }
|
|
85
|
+
],
|
|
86
|
+
defaultTransition: fade()
|
|
87
|
+
};
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Symmetric Transitions
|
|
10
91
|
|
|
11
|
-
|
|
12
|
-
pnpm dev
|
|
92
|
+
Automatically create bidirectional transitions:
|
|
13
93
|
|
|
14
|
-
|
|
15
|
-
|
|
94
|
+
```tsx
|
|
95
|
+
{
|
|
96
|
+
from: '/home',
|
|
97
|
+
to: '/about',
|
|
98
|
+
transition: slide({ direction: 'left' }),
|
|
99
|
+
symmetric: true // Automatically creates reverse transition
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Individual Element Animations
|
|
104
|
+
|
|
105
|
+
Animate specific elements during mount/unmount:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { transition } from '@ssgoi/react';
|
|
109
|
+
import { fadeIn, slideUp } from '@ssgoi/react/transitions';
|
|
16
110
|
|
|
17
|
-
|
|
18
|
-
|
|
111
|
+
function Card() {
|
|
112
|
+
return (
|
|
113
|
+
<div ref={transition({
|
|
114
|
+
key: 'card',
|
|
115
|
+
in: fadeIn(),
|
|
116
|
+
out: slideUp()
|
|
117
|
+
})}>
|
|
118
|
+
<h2>Animated Card</h2>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
19
122
|
```
|
|
20
123
|
|
|
21
|
-
##
|
|
124
|
+
## Built-in Transitions
|
|
125
|
+
|
|
126
|
+
### Page Transitions
|
|
127
|
+
- `fade` - Smooth opacity transition
|
|
128
|
+
- `slide` - Directional sliding (left/right/up/down)
|
|
129
|
+
- `scale` - Zoom in/out effect
|
|
130
|
+
- `hero` - Shared element transitions
|
|
131
|
+
- `pinterest` - Pinterest-style expand effect
|
|
132
|
+
- `ripple` - Material Design ripple effect
|
|
133
|
+
|
|
134
|
+
### Element Transitions
|
|
135
|
+
- `fadeIn` / `fadeOut`
|
|
136
|
+
- `slideUp` / `slideDown` / `slideLeft` / `slideRight`
|
|
137
|
+
- `scaleIn` / `scaleOut`
|
|
138
|
+
- `bounce`
|
|
139
|
+
- `blur`
|
|
140
|
+
- `rotate`
|
|
141
|
+
|
|
142
|
+
## Framework Examples
|
|
143
|
+
|
|
144
|
+
### Next.js App Router
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
// app/layout.tsx
|
|
148
|
+
import { Ssgoi } from '@ssgoi/react';
|
|
149
|
+
import { slide } from '@ssgoi/react/view-transitions';
|
|
150
|
+
|
|
151
|
+
export default function RootLayout({ children }) {
|
|
152
|
+
return (
|
|
153
|
+
<html>
|
|
154
|
+
<body>
|
|
155
|
+
<Ssgoi config={{
|
|
156
|
+
defaultTransition: slide({ direction: 'left' })
|
|
157
|
+
}}>
|
|
158
|
+
<div style={{ position: 'relative', minHeight: '100vh' }}>
|
|
159
|
+
{children}
|
|
160
|
+
</div>
|
|
161
|
+
</Ssgoi>
|
|
162
|
+
</body>
|
|
163
|
+
</html>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// app/page.tsx
|
|
168
|
+
import { SsgoiTransition } from '@ssgoi/react';
|
|
169
|
+
|
|
170
|
+
export default function Page() {
|
|
171
|
+
return (
|
|
172
|
+
<SsgoiTransition id="/">
|
|
173
|
+
{/* Your page content */}
|
|
174
|
+
</SsgoiTransition>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### SvelteKit
|
|
180
|
+
|
|
181
|
+
```svelte
|
|
182
|
+
<!-- +layout.svelte -->
|
|
183
|
+
<script>
|
|
184
|
+
import { Ssgoi } from '@ssgoi/svelte';
|
|
185
|
+
import { fade } from '@ssgoi/svelte/view-transitions';
|
|
186
|
+
</script>
|
|
187
|
+
|
|
188
|
+
<Ssgoi config={{ defaultTransition: fade() }}>
|
|
189
|
+
<div style="position: relative; min-height: 100vh;">
|
|
190
|
+
<slot />
|
|
191
|
+
</div>
|
|
192
|
+
</Ssgoi>
|
|
193
|
+
|
|
194
|
+
<!-- +page.svelte -->
|
|
195
|
+
<script>
|
|
196
|
+
import { SsgoiTransition } from '@ssgoi/svelte';
|
|
197
|
+
import { page } from '$app/stores';
|
|
198
|
+
</script>
|
|
199
|
+
|
|
200
|
+
<SsgoiTransition id={$page.url.pathname}>
|
|
201
|
+
<!-- Your page content -->
|
|
202
|
+
</SsgoiTransition>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Why SSGOI?
|
|
206
|
+
|
|
207
|
+
### vs View Transition API
|
|
208
|
+
- ✅ Works in all browsers, not just Chrome
|
|
209
|
+
- ✅ More animation options with spring physics
|
|
210
|
+
- ✅ Better developer experience
|
|
211
|
+
|
|
212
|
+
### vs Other Animation Libraries
|
|
213
|
+
- ✅ Built specifically for page transitions
|
|
214
|
+
- ✅ SSR-first design
|
|
215
|
+
- ✅ No router lock-in
|
|
216
|
+
- ✅ Minimal bundle size
|
|
217
|
+
|
|
218
|
+
## How It Works
|
|
219
|
+
|
|
220
|
+
SSGOI intercepts DOM lifecycle events to create smooth transitions:
|
|
221
|
+
|
|
222
|
+
1. **Route Change**: Your router changes the URL
|
|
223
|
+
2. **Exit Animation**: Current page animates out
|
|
224
|
+
3. **Enter Animation**: New page animates in
|
|
225
|
+
4. **State Sync**: Animation state persists across navigation
|
|
226
|
+
|
|
227
|
+
All powered by a spring physics engine for natural, smooth motion.
|
|
228
|
+
|
|
229
|
+
## Live Demos
|
|
230
|
+
|
|
231
|
+
Try out SSGOI with our framework-specific demo applications:
|
|
232
|
+
|
|
233
|
+
### React Demo
|
|
234
|
+
```bash
|
|
235
|
+
pnpm react-demo:dev
|
|
236
|
+
# Opens at http://localhost:3001
|
|
237
|
+
```
|
|
238
|
+
Explore Next.js App Router integration with various transition effects.
|
|
239
|
+
|
|
240
|
+
### Svelte Demo
|
|
241
|
+
```bash
|
|
242
|
+
pnpm svelte-demo:dev
|
|
243
|
+
# Opens at http://localhost:5174
|
|
244
|
+
```
|
|
245
|
+
See SvelteKit integration with smooth page transitions.
|
|
246
|
+
|
|
247
|
+
Visit the `/apps` directory to explore the demo source code and learn how to implement SSGOI in your own projects.
|
|
248
|
+
|
|
249
|
+
## Documentation
|
|
250
|
+
|
|
251
|
+
Visit [https://ssgoi.dev](https://ssgoi.dev) for:
|
|
252
|
+
- Detailed API reference
|
|
253
|
+
- Interactive examples
|
|
254
|
+
- Framework integration guides
|
|
255
|
+
- Custom transition recipes
|
|
256
|
+
|
|
257
|
+
## Contributing
|
|
258
|
+
|
|
259
|
+
We welcome contributions! Please see our [contributing guide](CONTRIBUTING.md) for details.
|
|
22
260
|
|
|
23
|
-
|
|
24
|
-
import { createTransition } from '@ssgoi/core'
|
|
261
|
+
## License
|
|
25
262
|
|
|
26
|
-
|
|
27
|
-
from: element1,
|
|
28
|
-
to: element2,
|
|
29
|
-
options: {
|
|
30
|
-
duration: 1000,
|
|
31
|
-
easing: 'ease-in-out'
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
```
|
|
263
|
+
MIT © [MeurSyphus](https://github.com/meursyphus)
|
package/dist/animator.d.ts
CHANGED
|
@@ -1,41 +1,52 @@
|
|
|
1
1
|
import { SpringConfig } from './types';
|
|
2
|
-
export interface AnimationOptions {
|
|
3
|
-
from:
|
|
4
|
-
to:
|
|
2
|
+
export interface AnimationOptions<TAnimationValue = number> {
|
|
3
|
+
from: TAnimationValue;
|
|
4
|
+
to: TAnimationValue;
|
|
5
5
|
spring: SpringConfig;
|
|
6
|
-
onUpdate: (value:
|
|
6
|
+
onUpdate: (value: TAnimationValue) => void;
|
|
7
7
|
onComplete: () => void;
|
|
8
8
|
onStart?: () => void;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
11
|
* New Animator implementation using Popmotion
|
|
12
12
|
* Provides spring-based animations with fine control
|
|
13
|
+
* Supports both number and object animations
|
|
14
|
+
*
|
|
15
|
+
* @template TAnimationValue - The type of value being animated (number | object)
|
|
13
16
|
*/
|
|
14
|
-
export declare class Animator {
|
|
17
|
+
export declare class Animator<TAnimationValue = number> {
|
|
15
18
|
private options;
|
|
16
19
|
private currentValue;
|
|
17
20
|
private velocity;
|
|
18
21
|
private isAnimating;
|
|
19
22
|
private controls;
|
|
20
|
-
|
|
23
|
+
private animationMap;
|
|
24
|
+
private activeAnimations;
|
|
25
|
+
private completedAnimations;
|
|
26
|
+
private updatedProperties;
|
|
27
|
+
constructor(options: Partial<AnimationOptions<TAnimationValue>>);
|
|
21
28
|
private animate;
|
|
29
|
+
private animateObject;
|
|
22
30
|
forward(): void;
|
|
23
31
|
backward(): void;
|
|
24
32
|
reverse(): void;
|
|
33
|
+
private shouldReverse;
|
|
25
34
|
stop(): void;
|
|
26
|
-
getVelocity(): number
|
|
27
|
-
getCurrentValue():
|
|
35
|
+
getVelocity(): TAnimationValue extends number ? number : Record<string, number>;
|
|
36
|
+
getCurrentValue(): TAnimationValue;
|
|
28
37
|
getIsAnimating(): boolean;
|
|
29
38
|
getCurrentState(): {
|
|
30
|
-
position:
|
|
31
|
-
velocity: number
|
|
39
|
+
position: TAnimationValue;
|
|
40
|
+
velocity: TAnimationValue extends number ? number : Record<string, number>;
|
|
41
|
+
from: TAnimationValue;
|
|
42
|
+
to: TAnimationValue;
|
|
32
43
|
};
|
|
33
|
-
setVelocity(velocity: number): void;
|
|
34
|
-
setValue(value:
|
|
35
|
-
updateOptions(newOptions: Partial<AnimationOptions
|
|
36
|
-
static fromState(state: {
|
|
37
|
-
position:
|
|
38
|
-
velocity: number
|
|
39
|
-
}, newOptions: Partial<AnimationOptions
|
|
44
|
+
setVelocity(velocity: TAnimationValue extends number ? number : Record<string, number>): void;
|
|
45
|
+
setValue(value: TAnimationValue): void;
|
|
46
|
+
updateOptions(newOptions: Partial<AnimationOptions<TAnimationValue>>): void;
|
|
47
|
+
static fromState<TAnimationValue = number>(state: {
|
|
48
|
+
position: TAnimationValue;
|
|
49
|
+
velocity: TAnimationValue extends number ? number : Record<string, number>;
|
|
50
|
+
}, newOptions: Partial<AnimationOptions<TAnimationValue>>): Animator<TAnimationValue>;
|
|
40
51
|
}
|
|
41
52
|
//# sourceMappingURL=animator.d.ts.map
|
package/dist/animator.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animator.d.ts","sourceRoot":"","sources":["../src/lib/animator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,WAAW,gBAAgB;
|
|
1
|
+
{"version":3,"file":"animator.d.ts","sourceRoot":"","sources":["../src/lib/animator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,WAAW,gBAAgB,CAAC,eAAe,GAAG,MAAM;IACxD,IAAI,EAAE,eAAe,CAAC;IACtB,EAAE,EAAE,eAAe,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED;;;;;;GAMG;AACH,qBAAa,QAAQ,CAAC,eAAe,GAAG,MAAM;IAC5C,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,YAAY,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAmE;IACnF,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAqC;IAGrD,OAAO,CAAC,YAAY,CAAkD;IACtE,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,mBAAmB,CAAqB;IAChD,OAAO,CAAC,iBAAiB,CAAqB;gBAElC,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAyB/D,OAAO,CAAC,OAAO,CA8Fb;IAEF,OAAO,CAAC,aAAa,CAyGnB;IAGF,OAAO,IAAI,IAAI;IAKf,QAAQ,IAAI,IAAI;IAKhB,OAAO,IAAI,IAAI;IAcf,OAAO,CAAC,aAAa;IAYrB,IAAI,IAAI,IAAI;IAyBZ,WAAW,IAAI,eAAe,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAI/E,eAAe,IAAI,eAAe;IAIlC,cAAc,IAAI,OAAO;IAIzB,eAAe,IAAI;QACjB,QAAQ,EAAE,eAAe,CAAC;QAC1B,QAAQ,EAAE,eAAe,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3E,IAAI,EAAE,eAAe,CAAC;QACtB,EAAE,EAAE,eAAe,CAAC;KACrB;IAUD,WAAW,CACT,QAAQ,EAAE,eAAe,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACzE,IAAI;IAIP,QAAQ,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAKtC,aAAa,CAAC,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,GAAG,IAAI;IAY3E,MAAM,CAAC,SAAS,CAAC,eAAe,GAAG,MAAM,EACvC,KAAK,EAAE;QACL,QAAQ,EAAE,eAAe,CAAC;QAC1B,QAAQ,EAAE,eAAe,SAAS,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC5E,EACD,UAAU,EAAE,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,GACrD,QAAQ,CAAC,eAAe,CAAC;CAM7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-ssgoi-transition-context.d.ts","sourceRoot":"","sources":["../src/lib/create-ssgoi-transition-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAGb,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"create-ssgoi-transition-context.d.ts","sourceRoot":"","sources":["../src/lib/create-ssgoi-transition-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,YAAY,EAGb,MAAM,SAAS,CAAC;AAwHjB;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,WAAW,GACnB,YAAY,CA6Fd"}
|
|
@@ -1,36 +1,7 @@
|
|
|
1
1
|
import { Transition, TransitionCallback } from './types';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* This is the core logic that frameworks can wrap with their own APIs
|
|
5
|
-
*
|
|
6
|
-
* UX Animation Behavior - 4 Main Scenarios:
|
|
7
|
-
*
|
|
8
|
-
* 1. No animation running + IN trigger:
|
|
9
|
-
* - Start entrance animation (0 → 1)
|
|
10
|
-
* - Return cleanup function for exit
|
|
11
|
-
*
|
|
12
|
-
* 2. No animation running + OUT trigger:
|
|
13
|
-
* - Clone element, start exit animation (1 → 0)
|
|
14
|
-
* - Remove clone when complete
|
|
15
|
-
*
|
|
16
|
-
* 3. IN animation running + OUT trigger:
|
|
17
|
-
* - Stop current IN animation (DOM is disappearing)
|
|
18
|
-
* - Clone element for exit animation
|
|
19
|
-
* - Create REVERSED IN animation (not OUT animation) with current state
|
|
20
|
-
* - This gives natural backward motion instead of jumping to OUT definition
|
|
21
|
-
*
|
|
22
|
-
* 4. OUT animation running + IN trigger:
|
|
23
|
-
* - Stop current OUT animation (cleanup any cloned elements)
|
|
24
|
-
* - Create REVERSED OUT animation (not IN animation) with current state
|
|
25
|
-
* - This gives natural backward motion instead of jumping to IN definition
|
|
26
|
-
* - Switch to entrance mode
|
|
27
|
-
*
|
|
28
|
-
* Closure Structure:
|
|
29
|
-
* - Outer function: Returns entrance callback
|
|
30
|
-
* - Inner function (entrance callback): Returns cleanup callback (exit)
|
|
31
|
-
* - Cleanup callback: Handles exit transitions
|
|
32
|
-
*/
|
|
33
|
-
export declare function createTransitionCallback(getTransition: () => Transition, options?: {
|
|
2
|
+
import { StrategyContext, TransitionStrategy } from './transition-strategy';
|
|
3
|
+
export declare function createTransitionCallback<TAnimationValue = number>(getTransition: () => Transition<undefined, TAnimationValue>, options?: {
|
|
34
4
|
onCleanupEnd?: () => void;
|
|
5
|
+
strategy?: (context: StrategyContext<TAnimationValue>) => TransitionStrategy<TAnimationValue>;
|
|
35
6
|
}): TransitionCallback;
|
|
36
7
|
//# sourceMappingURL=create-transition-callback.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-transition-callback.d.ts","sourceRoot":"","sources":["../src/lib/create-transition-callback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE9D
|
|
1
|
+
{"version":3,"file":"create-transition-callback.d.ts","sourceRoot":"","sources":["../src/lib/create-transition-callback.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE9D,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EAExB,MAAM,uBAAuB,CAAC;AAE/B,wBAAgB,wBAAwB,CAAC,eAAe,GAAG,MAAM,EAC/D,aAAa,EAAE,MAAM,UAAU,CAAC,SAAS,EAAE,eAAe,CAAC,EAC3D,OAAO,CAAC,EAAE;IACR,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC,eAAe,CAAC,KAAK,kBAAkB,CAAC,eAAe,CAAC,CAAC;CAC/F,GACA,kBAAkB,CAuIpB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var I=Object.defineProperty;var k=(i,t,o)=>t in i?I(i,t,{enumerable:!0,configurable:!0,writable:!0,value:o}):i[t]=o;var g=(i,t,o)=>k(i,typeof t!="symbol"?t+"":t,o);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("popmotion"),P=require("./utils-8Eptbv7c.cjs");class A{constructor(t){g(this,"options");g(this,"currentValue");g(this,"velocity");g(this,"isAnimating",!1);g(this,"controls",null);g(this,"animationMap",null);g(this,"activeAnimations",new Set);g(this,"completedAnimations",new Set);g(this,"updatedProperties",new Set);g(this,"animate",(t=!1)=>{!this.isAnimating&&this.options.onStart&&this.options.onStart(),this.isAnimating=!0;const o=t?this.options.from:this.options.to;if(typeof this.currentValue=="object"&&this.currentValue!==null){this.animateObject(o,t);return}let n=this.currentValue,e=performance.now();const m={from:this.currentValue,to:o,stiffness:this.options.spring.stiffness,damping:this.options.spring.damping,mass:1};typeof this.velocity=="number"&&(m.velocity=this.velocity*1e3),this.controls=R.animate({...m,onUpdate:a=>{const f=performance.now(),h=(f-e)/1e3;if(h>0){if(typeof a=="number"&&typeof n=="number"){const c=(a-n)/h;this.velocity=c/1e3}else if(typeof a=="object"&&a!==null){const c={};Object.keys(a).forEach(u=>{const r=a[u],s=n[u];if(typeof r=="number"&&typeof s=="number"){const p=(r-s)/h;c[u]=p/1e3}}),this.velocity=c}n=a,e=f}this.currentValue=a,this.options.onUpdate(a)},onComplete:()=>{this.currentValue=o,this.isAnimating=!1,this.controls=null,typeof this.velocity=="object"&&this.velocity!==null?Object.keys(this.velocity).forEach(a=>{this.velocity[a]=0}):this.velocity=0,this.options.onComplete()}})});g(this,"animateObject",(t,o)=>{const n=this.currentValue,e=Object.keys(n);this.animationMap=new Map,this.activeAnimations.clear(),this.completedAnimations.clear(),this.updatedProperties.clear();const m={...n},a={};let f=!1;const h=()=>{const c=e.filter(r=>!this.completedAnimations.has(r));if(c.every(r=>this.updatedProperties.has(r))&&c.length>0){if(typeof this.velocity=="object"&&this.velocity){const r=performance.now();Object.keys(m).forEach(s=>{if(a[s]){const p=(r-a[s])/1e3,l=this.currentValue[s],d=m[s];typeof l=="number"&&typeof d=="number"&&p>0&&(this.velocity[s]=(d-l)/p/1e3)}a[s]=r})}this.currentValue={...m},this.options.onUpdate(this.currentValue),this.updatedProperties.clear(),!f&&this.options.onStart&&(f=!0,this.options.onStart())}};e.forEach(c=>{this.activeAnimations.add(c);const u={from:n[c],to:t[c],stiffness:this.options.spring.stiffness,damping:this.options.spring.damping,mass:1};typeof this.velocity=="object"&&this.velocity&&c in this.velocity&&(u.velocity=this.velocity[c]*1e3);const r=R.animate({...u,onUpdate:s=>{m[c]=s,this.updatedProperties.add(c),h()},onComplete:()=>{this.completedAnimations.add(c),this.updatedProperties.delete(c),this.completedAnimations.size===e.length&&(this.currentValue=t,this.isAnimating=!1,this.animationMap=null,typeof this.velocity=="object"&&this.velocity&&Object.keys(this.velocity).forEach(s=>{this.velocity[s]=0}),this.options.onComplete())}});this.animationMap.set(c,r)})});if(this.options={from:t.from??0,to:t.to??1,spring:t.spring??{stiffness:100,damping:10},onUpdate:t.onUpdate??(()=>{}),onComplete:t.onComplete??(()=>{}),onStart:t.onStart},this.currentValue=this.options.from,typeof this.options.from=="object"&&this.options.from!==null){const o={};Object.keys(this.options.from).forEach(n=>{o[n]=0}),this.velocity=o}else this.velocity=0}forward(){this.stop(),this.animate(!1)}backward(){this.stop(),this.animate(!0)}reverse(){const t=this.options.from;if(this.options.from=this.options.to,this.options.to=t,this.isAnimating){const o=this.shouldReverse();this.stop(),this.animate(!o)}}shouldReverse(){return typeof this.currentValue=="number"&&typeof this.options.from=="number"&&typeof this.options.to=="number"?this.currentValue>(this.options.from+this.options.to)/2:!1}stop(){this.isAnimating=!1,this.controls&&(this.controls.stop(),this.controls=null),this.animationMap&&(this.animationMap.forEach(t=>{t.stop()}),this.animationMap.clear(),this.animationMap=null),this.updatedProperties.clear()}getVelocity(){return this.velocity}getCurrentValue(){return this.currentValue}getIsAnimating(){return this.isAnimating}getCurrentState(){return{position:this.currentValue,velocity:this.velocity,from:this.options.from,to:this.options.to}}setVelocity(t){this.velocity=t}setValue(t){this.currentValue=t}updateOptions(t){if(this.options={...this.options,...t},this.isAnimating&&this.controls){const o=this.shouldReverse();this.stop(),this.animate(!o)}}static fromState(t,o){const n=new A(o);return n.setValue(t.position),n.setVelocity(t.velocity),n}}const M=Symbol.for("TRANSITION_STRATEGY"),x=i=>({runIn:async t=>{const{currentAnimation:o}=i;if(o&&o.direction==="out"){const a=o.animator.getCurrentState();if(o.animator.stop(),t.out){const f=await t.out,{from:h=1,to:c=0}=f;return{config:f,state:a,from:h,to:c,direction:"backward"}}}const n=await t.in;if(!n)return{state:{position:0,velocity:0},from:0,to:1,direction:"forward"};const{from:e=0,to:m=1}=n;return{config:n,state:{position:e,velocity:0},from:e,to:m,direction:"forward"}},runOut:async t=>{const{currentAnimation:o}=i;if(o&&o.direction==="in"){const a=o.animator.getCurrentState();if(o.animator.stop(),t.in){const f=await t.in,{from:h=0,to:c=1}=f;return{config:f,state:{position:a.position,velocity:a.velocity},from:h,to:c,direction:"backward"}}}const n=await t.out;if(!n)return{state:{position:1,velocity:0},from:1,to:0,direction:"forward"};const{from:e=1,to:m=0}=n;return{config:n,state:{position:e,velocity:0},from:e,to:m,direction:"forward"}}});function D(i,t){var u;let o=null,n=null,e=null,m=null;const a={get currentAnimation(){return o}},f=((u=t==null?void 0:t.strategy)==null?void 0:u.call(t,a))||x(a),h=async r=>{var y,S;n&&(n.remove(),n=null);const s=i(),p={in:s.in&&Promise.resolve(s.in(r)),out:s.out&&Promise.resolve(s.out(r))},l=await f.runIn(p);if(!l.config)return;(S=(y=l.config).prepare)==null||S.call(y,r),l.config.wait&&await l.config.wait();const d=A.fromState(l.state,{from:l.from,to:l.to,spring:l.config.spring,onStart:l.config.onStart,onUpdate:l.config.tick,onComplete:()=>{var v,w;o=null,(w=(v=l.config)==null?void 0:v.onEnd)==null||w.call(v)}});o={animator:d,direction:"in"},l.direction==="forward"?d.forward():d.backward()},c=async r=>{var S,v;n=r;const s=i(),p={in:s.in&&Promise.resolve(s.in(r)),out:s.out&&Promise.resolve(s.out(r))},l=await f.runOut(p);if(!l.config)return;(v=(S=l.config).prepare)==null||v.call(S,r),y(),l.config.wait&&await l.config.wait();const d=A.fromState(l.state,{from:l.from,to:l.to,spring:l.config.spring,onStart:l.config.onStart,onUpdate:l.config.tick,onComplete:()=>{var w,C,O;(C=(w=l.config)==null?void 0:w.onEnd)==null||C.call(w),n&&(n.remove(),n=null),o=null,(O=t==null?void 0:t.onCleanupEnd)==null||O.call(t)}});o={animator:d,direction:"out"},l.direction==="forward"?d.forward():d.backward();function y(){!e||!n||(m&&e.contains(m)?e.insertBefore(n,m):e.appendChild(n))}};return r=>{if(r)return e=r.parentElement,m=r.nextElementSibling,h(r),()=>{const s=r.cloneNode(!0);c(s)}}}const T=new Map,V=new Map;function N(i,t,o){T.set(i,t);let n=V.get(i);return n||(n=D(()=>{const e=T.get(i);return e||(console.warn(`Transition "${String(i)}" not found`),{})},{strategy:o,onCleanupEnd:()=>U(i)}),V.set(i,n),n)}function U(i){T.delete(i),V.delete(i)}function _(){const i=P.parseCallerLocation(new Error().stack);return i?`auto_${i.file}_${i.line}_${i.column}`:Symbol(`ssgoi_auto_${Date.now()}`)}const E=globalThis.FinalizationRegistry,j=E?new E(i=>{try{U(i)}catch{}}):void 0;function $(i){const t=i.key??_();if(i.ref&&j)try{j.register(i.ref,t)}catch{}return N(t,{in:i.in,out:i.out},i[M])}function F(i){const t=i.filter(o=>o.symmetric).map(o=>({from:o.to,to:o.from,transition:o.transition}));return[...i,...t]}function K(){let i=null;const t=new Map;let o=null;const n=()=>{i&&o&&t.set(o,{x:i.scrollLeft,y:i.scrollTop})};return{startScrollTracking:(a,f)=>{i||(i=P.getScrollingElement(a),(i===document.documentElement?window:i).addEventListener("scroll",n,{passive:!0})),o=f},calculateScrollOffset:(a,f)=>{const h=a&&t.has(a)?t.get(a):{x:0,y:0},c=f&&t.has(f)?t.get(f):{x:0,y:0};return{x:-c.x+h.x,y:-c.y+h.y}}}}function L(i){const{transitions:t=[],defaultTransition:o,middleware:n=(u,r)=>({from:u,to:r})}=i;let e=null;const m=F(t),{startScrollTracking:a,calculateScrollOffset:f}=K();function h(){if(e!=null&&e.from&&(e!=null&&e.to)){const{from:u,to:r}=n(e.from,e.to),p=z(u,r,m)||o,d={scrollOffset:f(e.from,e.to)};p&&(p.out&&e.outResolve&&e.outResolve(y=>p.out(y,d)),p.in&&e.inResolve&&e.inResolve(y=>p.in(y,d))),e=null}}const c=async(u,r)=>r==="in"&&(!e||!e.from)?()=>({}):(e||(e={}),r==="out"?(e.from=u,new Promise(s=>{e.outResolve=s,h()})):(e.to=u,new Promise(s=>{e.inResolve=s,h()})));return u=>({key:u,in:async r=>(a(r,u),(await c(u,"in"))(r)),out:async r=>(await c(u,"out"))(r)})}function z(i,t,o){for(const n of o)if(b(i,n.from)&&b(t,n.to))return n.transition;for(const n of o)if((n.from==="*"||b(i,n.from))&&(n.to==="*"||b(t,n.to)))return n.transition;return null}function b(i,t){if(t==="*")return!0;if(t.endsWith("/*")){const o=t.slice(0,-2);return i===o||i.startsWith(o+"/")}return i===t}exports.TRANSITION_STRATEGY=M;exports.createDefaultStrategy=x;exports.createSggoiTransitionContext=L;exports.generateAutoKey=_;exports.transition=$;
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/lib/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,mCAAmC,CAAC;AAClD,cAAc,uBAAuB,CAAC"}
|