@ssgoi/react 0.0.1
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 +265 -0
- package/dist/context.d.ts +3 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +770 -0
- package/dist/ssgoi-transition.d.ts +5 -0
- package/dist/ssgoi.d.ts +8 -0
- package/dist/transition.d.ts +2 -0
- package/dist/transitions/index.cjs +1 -0
- package/dist/transitions/index.d.ts +1 -0
- package/dist/transitions/index.js +173 -0
- package/dist/types.cjs +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.js +1 -0
- package/dist/utils-BSgyev81.cjs +1 -0
- package/dist/utils-DR41YsAh.js +16 -0
- package/dist/view-transitions/index.cjs +1 -0
- package/dist/view-transitions/index.d.ts +1 -0
- package/dist/view-transitions/index.js +301 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# @ssgoi/react
|
|
2
|
+
|
|
3
|
+
React bindings for SSGOI - Native app-like page transitions for React applications.
|
|
4
|
+
|
|
5
|
+
## What is SSGOI?
|
|
6
|
+
|
|
7
|
+
SSGOI brings native app-like page transitions to the web. Transform your static page navigations into smooth, delightful experiences that users love.
|
|
8
|
+
|
|
9
|
+
### ✨ Key Features
|
|
10
|
+
|
|
11
|
+
- **🌍 Works Everywhere** - Unlike the browser's View Transition API, SSGOI works in all modern browsers (Chrome, Firefox, Safari)
|
|
12
|
+
- **🚀 SSR Ready** - Perfect compatibility with Next.js. No hydration issues, SEO-friendly
|
|
13
|
+
- **🎯 Use Your Router** - Keep your existing routing. React Router, Next.js App Router - all work seamlessly
|
|
14
|
+
- **💾 State Persistence** - Remembers animation state during navigation, even with browser back/forward
|
|
15
|
+
- **⚛️ React Optimized** - Built specifically for React with hooks and modern patterns
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @ssgoi/react
|
|
21
|
+
# or
|
|
22
|
+
yarn add @ssgoi/react
|
|
23
|
+
# or
|
|
24
|
+
pnpm add @ssgoi/react
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### 1. Wrap your app
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { Ssgoi } from '@ssgoi/react';
|
|
33
|
+
import { fade } from '@ssgoi/react/view-transitions';
|
|
34
|
+
|
|
35
|
+
export default function App() {
|
|
36
|
+
return (
|
|
37
|
+
<Ssgoi config={{ defaultTransition: fade() }}>
|
|
38
|
+
<div style={{ position: 'relative' }}>
|
|
39
|
+
{/* Your app */}
|
|
40
|
+
</div>
|
|
41
|
+
</Ssgoi>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 2. Wrap your pages
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { SsgoiTransition } from '@ssgoi/react';
|
|
50
|
+
|
|
51
|
+
export default function HomePage() {
|
|
52
|
+
return (
|
|
53
|
+
<SsgoiTransition id="/">
|
|
54
|
+
<h1>Welcome</h1>
|
|
55
|
+
{/* Page content */}
|
|
56
|
+
</SsgoiTransition>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**That's it!** Your pages now transition smoothly with a fade effect.
|
|
62
|
+
|
|
63
|
+
## Advanced Transitions
|
|
64
|
+
|
|
65
|
+
### Route-based Transitions
|
|
66
|
+
|
|
67
|
+
Define different transitions for different routes:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
const config = {
|
|
71
|
+
transitions: [
|
|
72
|
+
// Slide between tabs
|
|
73
|
+
{ from: '/home', to: '/about', transition: slide({ direction: 'left' }) },
|
|
74
|
+
{ from: '/about', to: '/home', transition: slide({ direction: 'right' }) },
|
|
75
|
+
|
|
76
|
+
// Scale up when entering details
|
|
77
|
+
{ from: '/products', to: '/products/*', transition: scale() },
|
|
78
|
+
|
|
79
|
+
// Pinterest-style image transitions
|
|
80
|
+
{ from: '/gallery', to: '/photo/*', transition: pinterest() }
|
|
81
|
+
],
|
|
82
|
+
defaultTransition: fade()
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Symmetric Transitions
|
|
87
|
+
|
|
88
|
+
Automatically create bidirectional transitions:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
{
|
|
92
|
+
from: '/home',
|
|
93
|
+
to: '/about',
|
|
94
|
+
transition: slide({ direction: 'left' }),
|
|
95
|
+
symmetric: true // Automatically creates reverse transition
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Individual Element Animations
|
|
100
|
+
|
|
101
|
+
Animate specific elements during mount/unmount:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { transition } from '@ssgoi/react';
|
|
105
|
+
import { fadeIn, slideUp } from '@ssgoi/react/transitions';
|
|
106
|
+
|
|
107
|
+
function Card() {
|
|
108
|
+
return (
|
|
109
|
+
<div ref={transition({
|
|
110
|
+
key: 'card',
|
|
111
|
+
in: fadeIn(),
|
|
112
|
+
out: slideUp()
|
|
113
|
+
})}>
|
|
114
|
+
<h2>Animated Card</h2>
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Next.js App Router Example
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
// app/layout.tsx
|
|
124
|
+
import { Ssgoi } from '@ssgoi/react';
|
|
125
|
+
import { slide } from '@ssgoi/react/view-transitions';
|
|
126
|
+
|
|
127
|
+
export default function RootLayout({ children }) {
|
|
128
|
+
return (
|
|
129
|
+
<html>
|
|
130
|
+
<body>
|
|
131
|
+
<Ssgoi config={{
|
|
132
|
+
defaultTransition: slide({ direction: 'left' })
|
|
133
|
+
}}>
|
|
134
|
+
<div style={{ position: 'relative', minHeight: '100vh' }}>
|
|
135
|
+
{children}
|
|
136
|
+
</div>
|
|
137
|
+
</Ssgoi>
|
|
138
|
+
</body>
|
|
139
|
+
</html>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// app/page.tsx
|
|
144
|
+
import { SsgoiTransition } from '@ssgoi/react';
|
|
145
|
+
|
|
146
|
+
export default function Page() {
|
|
147
|
+
return (
|
|
148
|
+
<SsgoiTransition id="/">
|
|
149
|
+
{/* Your page content */}
|
|
150
|
+
</SsgoiTransition>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## API Reference
|
|
156
|
+
|
|
157
|
+
### Components
|
|
158
|
+
|
|
159
|
+
#### `<Ssgoi>`
|
|
160
|
+
The provider component that manages transition context.
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
<Ssgoi config={ssgoiConfig}>
|
|
164
|
+
{children}
|
|
165
|
+
</Ssgoi>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### `<SsgoiTransition>`
|
|
169
|
+
Wrapper component for pages that should transition.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
<SsgoiTransition id="/page-id">
|
|
173
|
+
{children}
|
|
174
|
+
</SsgoiTransition>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Hooks
|
|
178
|
+
|
|
179
|
+
#### `useTransition()`
|
|
180
|
+
Access transition state and controls.
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
const { isTransitioning, direction } = useTransition();
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Functions
|
|
187
|
+
|
|
188
|
+
#### `transition()`
|
|
189
|
+
Apply transitions to individual elements.
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
<div ref={transition({
|
|
193
|
+
key: 'unique-key',
|
|
194
|
+
in: fadeIn(),
|
|
195
|
+
out: fadeOut()
|
|
196
|
+
})}>
|
|
197
|
+
Content
|
|
198
|
+
</div>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Built-in Transitions
|
|
202
|
+
|
|
203
|
+
### Page Transitions (`@ssgoi/react/view-transitions`)
|
|
204
|
+
- `fade()` - Smooth opacity transition
|
|
205
|
+
- `slide()` - Directional sliding (left/right/up/down)
|
|
206
|
+
- `scale()` - Zoom in/out effect
|
|
207
|
+
- `hero()` - Shared element transitions
|
|
208
|
+
- `pinterest()` - Pinterest-style expand effect
|
|
209
|
+
- `ripple()` - Material Design ripple effect
|
|
210
|
+
|
|
211
|
+
### Element Transitions (`@ssgoi/react/transitions`)
|
|
212
|
+
- `fadeIn()` / `fadeOut()`
|
|
213
|
+
- `slideUp()` / `slideDown()` / `slideLeft()` / `slideRight()`
|
|
214
|
+
- `scaleIn()` / `scaleOut()`
|
|
215
|
+
- `bounce()`
|
|
216
|
+
- `blur()`
|
|
217
|
+
- `rotate()`
|
|
218
|
+
|
|
219
|
+
## Spring Physics Configuration
|
|
220
|
+
|
|
221
|
+
All transitions use spring physics for natural motion:
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
slide({
|
|
225
|
+
direction: 'left',
|
|
226
|
+
spring: {
|
|
227
|
+
stiffness: 300, // 1-1000, higher = faster
|
|
228
|
+
damping: 30 // 0-100, higher = less oscillation
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## TypeScript Support
|
|
234
|
+
|
|
235
|
+
SSGOI is written in TypeScript and provides full type definitions:
|
|
236
|
+
|
|
237
|
+
```tsx
|
|
238
|
+
import type { SsgoiConfig, TransitionConfig } from '@ssgoi/react';
|
|
239
|
+
|
|
240
|
+
const config: SsgoiConfig = {
|
|
241
|
+
// Full type safety
|
|
242
|
+
};
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Browser Support
|
|
246
|
+
|
|
247
|
+
- Chrome/Edge 88+
|
|
248
|
+
- Firefox 78+
|
|
249
|
+
- Safari 14+
|
|
250
|
+
- All modern mobile browsers
|
|
251
|
+
|
|
252
|
+
## Performance
|
|
253
|
+
|
|
254
|
+
- Minimal bundle size (~8kb gzipped)
|
|
255
|
+
- Hardware-accelerated animations
|
|
256
|
+
- Automatic cleanup and memory management
|
|
257
|
+
- Smart preloading for instant transitions
|
|
258
|
+
|
|
259
|
+
## Contributing
|
|
260
|
+
|
|
261
|
+
We welcome contributions! Please see our [contributing guide](https://github.com/meursyphus/ssgoi/blob/main/CONTRIBUTING.md) for details.
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT © [MeurSyphus](https://github.com/meursyphus)
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ht=require("react/jsx-runtime"),X=require("react"),Bt=require("./utils-BSgyev81.cjs");function dt(t,e){var n={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var s=0,r=Object.getOwnPropertySymbols(t);s<r.length;s++)e.indexOf(r[s])<0&&Object.prototype.propertyIsEnumerable.call(t,r[s])&&(n[r[s]]=t[r[s]]);return n}var Y=function(){},V=function(){};process.env.NODE_ENV!=="production"&&(Y=function(t,e){!t&&typeof console<"u"&&console.warn(e)},V=function(t,e){if(!t)throw new Error(e)});const W=(t,e,n)=>Math.min(Math.max(n,t),e),L=.001,_t=.01,it=10,Wt=.05,Gt=1;function Ht({duration:t=800,bounce:e=.25,velocity:n=0,mass:r=1}){let s,i;Y(t<=it*1e3,"Spring duration must be 10 seconds or less");let o=1-e;o=W(Wt,Gt,o),t=W(_t,it,t/1e3),o<1?(s=a=>{const p=a*o,m=p*t,u=p-n,f=G(a,o),h=Math.exp(-m);return L-u/f*h},i=a=>{const m=a*o*t,u=m*n+n,f=Math.pow(o,2)*Math.pow(a,2)*t,h=Math.exp(-m),x=G(Math.pow(a,2),o);return(-s(a)+L>0?-1:1)*((u-f)*h)/x}):(s=a=>{const p=Math.exp(-a*t),m=(a-n)*t+1;return-L+p*m},i=a=>{const p=Math.exp(-a*t),m=(n-a)*(t*t);return p*m});const l=5/t,c=zt(s,i,l);if(t=t*1e3,isNaN(c))return{stiffness:100,damping:10,duration:t};{const a=Math.pow(c,2)*r;return{stiffness:a,damping:o*2*Math.sqrt(r*a),duration:t}}}const Kt=12;function zt(t,e,n){let r=n;for(let s=1;s<Kt;s++)r=r-t(r)/e(r);return r}function G(t,e){return t*Math.sqrt(1-e*e)}const Zt=["duration","bounce"],Jt=["stiffness","damping","mass"];function at(t,e){return e.some(n=>t[n]!==void 0)}function Qt(t){let e=Object.assign({velocity:0,stiffness:100,damping:10,mass:1,isResolvedFromDuration:!1},t);if(!at(t,Jt)&&at(t,Zt)){const n=Ht(t);e=Object.assign(Object.assign(Object.assign({},e),n),{velocity:0,mass:1}),e.isResolvedFromDuration=!0}return e}function tt(t){var{from:e=0,to:n=1,restSpeed:r=2,restDelta:s}=t,i=dt(t,["from","to","restSpeed","restDelta"]);const o={done:!1,value:e};let{stiffness:l,damping:c,mass:a,velocity:p,duration:m,isResolvedFromDuration:u}=Qt(i),f=lt,h=lt;function x(){const y=p?-(p/1e3):0,S=n-e,b=c/(2*Math.sqrt(l*a)),g=Math.sqrt(l/a)/1e3;if(s===void 0&&(s=Math.min(Math.abs(n-e)/100,.4)),b<1){const d=G(g,b);f=M=>{const w=Math.exp(-b*g*M);return n-w*((y+b*g*S)/d*Math.sin(d*M)+S*Math.cos(d*M))},h=M=>{const w=Math.exp(-b*g*M);return b*g*w*(Math.sin(d*M)*(y+b*g*S)/d+S*Math.cos(d*M))-w*(Math.cos(d*M)*(y+b*g*S)-d*S*Math.sin(d*M))}}else if(b===1)f=d=>n-Math.exp(-g*d)*(S+(y+g*S)*d);else{const d=g*Math.sqrt(b*b-1);f=M=>{const w=Math.exp(-b*g*M),T=Math.min(d*M,300);return n-w*((y+b*g*S)*Math.sinh(T)+d*S*Math.cosh(T))/d}}}return x(),{next:y=>{const S=f(y);if(u)o.done=y>=m;else{const b=h(y)*1e3,g=Math.abs(b)<=r,d=Math.abs(n-S)<=s;o.done=g&&d}return o.value=o.done?n:S,o},flipTarget:()=>{p=-p,[e,n]=[n,e],x()}}}tt.needsInterpolation=(t,e)=>typeof t=="string"||typeof e=="string";const lt=t=>0,gt=(t,e,n)=>{const r=e-t;return r===0?1:(n-t)/r},et=(t,e,n)=>-n*t+n*e+t,yt=(t,e)=>n=>Math.max(Math.min(n,e),t),A=t=>t%1?Number(t.toFixed(5)):t,N=/(-)?([\d]*\.?[\d])+/g,H=/(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))/gi,Xt=/^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;function I(t){return typeof t=="string"}const k={test:t=>typeof t=="number",parse:parseFloat,transform:t=>t},bt=Object.assign(Object.assign({},k),{transform:yt(0,1)});Object.assign(Object.assign({},k),{default:1});const Yt=t=>({test:e=>I(e)&&e.endsWith(t)&&e.split(" ").length===1,parse:parseFloat,transform:e=>`${e}${t}`}),R=Yt("%");Object.assign(Object.assign({},R),{parse:t=>R.parse(t)/100,transform:t=>R.transform(t*100)});const nt=(t,e)=>n=>!!(I(n)&&Xt.test(n)&&n.startsWith(t)||e&&Object.prototype.hasOwnProperty.call(n,e)),xt=(t,e,n)=>r=>{if(!I(r))return r;const[s,i,o,l]=r.match(N);return{[t]:parseFloat(s),[e]:parseFloat(i),[n]:parseFloat(o),alpha:l!==void 0?parseFloat(l):1}},O={test:nt("hsl","hue"),parse:xt("hue","saturation","lightness"),transform:({hue:t,saturation:e,lightness:n,alpha:r=1})=>"hsla("+Math.round(t)+", "+R.transform(A(e))+", "+R.transform(A(n))+", "+A(bt.transform(r))+")"},te=yt(0,255),B=Object.assign(Object.assign({},k),{transform:t=>Math.round(te(t))}),v={test:nt("rgb","red"),parse:xt("red","green","blue"),transform:({red:t,green:e,blue:n,alpha:r=1})=>"rgba("+B.transform(t)+", "+B.transform(e)+", "+B.transform(n)+", "+A(bt.transform(r))+")"};function ee(t){let e="",n="",r="",s="";return t.length>5?(e=t.substr(1,2),n=t.substr(3,2),r=t.substr(5,2),s=t.substr(7,2)):(e=t.substr(1,1),n=t.substr(2,1),r=t.substr(3,1),s=t.substr(4,1),e+=e,n+=n,r+=r,s+=s),{red:parseInt(e,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:s?parseInt(s,16)/255:1}}const K={test:nt("#"),parse:ee,transform:v.transform},U={test:t=>v.test(t)||K.test(t)||O.test(t),parse:t=>v.test(t)?v.parse(t):O.test(t)?O.parse(t):K.parse(t),transform:t=>I(t)?t:t.hasOwnProperty("red")?v.transform(t):O.transform(t)},St="${c}",Mt="${n}";function ne(t){var e,n,r,s;return isNaN(t)&&I(t)&&((n=(e=t.match(N))===null||e===void 0?void 0:e.length)!==null&&n!==void 0?n:0)+((s=(r=t.match(H))===null||r===void 0?void 0:r.length)!==null&&s!==void 0?s:0)>0}function wt(t){typeof t=="number"&&(t=`${t}`);const e=[];let n=0;const r=t.match(H);r&&(n=r.length,t=t.replace(H,St),e.push(...r.map(U.parse)));const s=t.match(N);return s&&(t=t.replace(N,Mt),e.push(...s.map(k.parse))),{values:e,numColors:n,tokenised:t}}function vt(t){return wt(t).values}function Ot(t){const{values:e,numColors:n,tokenised:r}=wt(t),s=e.length;return i=>{let o=r;for(let l=0;l<s;l++)o=o.replace(l<n?St:Mt,l<n?U.transform(i[l]):A(i[l]));return o}}const re=t=>typeof t=="number"?0:t;function se(t){const e=vt(t);return Ot(t)(e.map(re))}const Tt={test:ne,parse:vt,createTransformer:Ot,getAnimatableNone:se};function _(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+(e-t)*6*n:n<1/2?e:n<2/3?t+(e-t)*(2/3-n)*6:t}function ct({hue:t,saturation:e,lightness:n,alpha:r}){t/=360,e/=100,n/=100;let s=0,i=0,o=0;if(!e)s=i=o=n;else{const l=n<.5?n*(1+e):n+e-n*e,c=2*n-l;s=_(c,l,t+1/3),i=_(c,l,t),o=_(c,l,t-1/3)}return{red:Math.round(s*255),green:Math.round(i*255),blue:Math.round(o*255),alpha:r}}const oe=(t,e,n)=>{const r=t*t,s=e*e;return Math.sqrt(Math.max(0,n*(s-r)+r))},ie=[K,v,O],ut=t=>ie.find(e=>e.test(t)),ft=t=>`'${t}' is not an animatable color. Use the equivalent color code instead.`,Ct=(t,e)=>{let n=ut(t),r=ut(e);V(!!n,ft(t)),V(!!r,ft(e));let s=n.parse(t),i=r.parse(e);n===O&&(s=ct(s),n=v),r===O&&(i=ct(i),r=v);const o=Object.assign({},s);return l=>{for(const c in o)c!=="alpha"&&(o[c]=oe(s[c],i[c],l));return o.alpha=et(s.alpha,i.alpha,l),n.transform(o)}},ae=t=>typeof t=="number",le=(t,e)=>n=>e(t(n)),At=(...t)=>t.reduce(le);function Rt(t,e){return ae(t)?n=>et(t,e,n):U.test(t)?Ct(t,e):Vt(t,e)}const Et=(t,e)=>{const n=[...t],r=n.length,s=t.map((i,o)=>Rt(i,e[o]));return i=>{for(let o=0;o<r;o++)n[o]=s[o](i);return n}},ce=(t,e)=>{const n=Object.assign(Object.assign({},t),e),r={};for(const s in n)t[s]!==void 0&&e[s]!==void 0&&(r[s]=Rt(t[s],e[s]));return s=>{for(const i in r)n[i]=r[i](s);return n}};function pt(t){const e=Tt.parse(t),n=e.length;let r=0,s=0,i=0;for(let o=0;o<n;o++)r||typeof e[o]=="number"?r++:e[o].hue!==void 0?i++:s++;return{parsed:e,numNumbers:r,numRGB:s,numHSL:i}}const Vt=(t,e)=>{const n=Tt.createTransformer(e),r=pt(t),s=pt(e);return r.numHSL===s.numHSL&&r.numRGB===s.numRGB&&r.numNumbers>=s.numNumbers?At(Et(r.parsed,s.parsed),n):(Y(!0,`Complex values '${t}' and '${e}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`),o=>`${o>0?e:t}`)},ue=(t,e)=>n=>et(t,e,n);function fe(t){if(typeof t=="number")return ue;if(typeof t=="string")return U.test(t)?Ct:Vt;if(Array.isArray(t))return Et;if(typeof t=="object")return ce}function pe(t,e,n){const r=[],s=n||fe(t[0]),i=t.length-1;for(let o=0;o<i;o++){let l=s(t[o],t[o+1]);if(e){const c=Array.isArray(e)?e[o]:e;l=At(c,l)}r.push(l)}return r}function me([t,e],[n]){return r=>n(gt(t,e,r))}function he(t,e){const n=t.length,r=n-1;return s=>{let i=0,o=!1;if(s<=t[0]?o=!0:s>=t[r]&&(i=r-1,o=!0),!o){let c=1;for(;c<n&&!(t[c]>s||c===r);c++);i=c-1}const l=gt(t[i],t[i+1],s);return e[i](l)}}function jt(t,e,{clamp:n=!0,ease:r,mixer:s}={}){const i=t.length;V(i===e.length,"Both input and output ranges must be the same length"),V(!r||!Array.isArray(r)||r.length===i-1,"Array of easing functions must be of length `input.length - 1`, as it applies to the transitions **between** the defined values."),t[0]>t[i-1]&&(t=[].concat(t),e=[].concat(e),t.reverse(),e.reverse());const o=pe(e,r,s),l=i===2?me(t,o):he(t,o);return n?c=>l(W(t[0],t[i-1],c)):l}const de=t=>e=>e<=.5?t(2*e)/2:(2-t(2*(1-e)))/2,ge=t=>e=>Math.pow(e,t),ye=ge(2),be=de(ye);function xe(t,e){return t.map(()=>e||be).splice(0,t.length-1)}function Se(t){const e=t.length;return t.map((n,r)=>r!==0?r/(e-1):0)}function Me(t,e){return t.map(n=>n*e)}function P({from:t=0,to:e=1,ease:n,offset:r,duration:s=300}){const i={done:!1,value:t},o=Array.isArray(e)?e:[t,e],l=Me(r&&r.length===o.length?r:Se(o),s);function c(){return jt(l,o,{ease:Array.isArray(n)?n:xe(o,n)})}let a=c();return{next:p=>(i.value=a(p),i.done=p>=s,i),flipTarget:()=>{o.reverse(),a=c()}}}function we({velocity:t=0,from:e=0,power:n=.8,timeConstant:r=350,restDelta:s=.5,modifyTarget:i}){const o={done:!1,value:e};let l=n*t;const c=e+l,a=i===void 0?c:i(c);return a!==c&&(l=a-e),{next:p=>{const m=-l*Math.exp(-p/r);return o.done=!(m>s||m<-s),o.value=o.done?a:a+m,o},flipTarget:()=>{}}}const mt={keyframes:P,spring:tt,decay:we};function ve(t){if(Array.isArray(t.to))return P;if(mt[t.type])return mt[t.type];const e=new Set(Object.keys(t));return e.has("ease")||e.has("duration")&&!e.has("dampingRatio")?P:e.has("dampingRatio")||e.has("stiffness")||e.has("mass")||e.has("damping")||e.has("restSpeed")||e.has("restDelta")?tt:P}const It=1/60*1e3,Oe=typeof performance<"u"?()=>performance.now():()=>Date.now(),Ft=typeof window<"u"?t=>window.requestAnimationFrame(t):t=>setTimeout(()=>t(Oe()),It);function Te(t){let e=[],n=[],r=0,s=!1,i=!1;const o=new WeakSet,l={schedule:(c,a=!1,p=!1)=>{const m=p&&s,u=m?e:n;return a&&o.add(c),u.indexOf(c)===-1&&(u.push(c),m&&s&&(r=e.length)),c},cancel:c=>{const a=n.indexOf(c);a!==-1&&n.splice(a,1),o.delete(c)},process:c=>{if(s){i=!0;return}if(s=!0,[e,n]=[n,e],n.length=0,r=e.length,r)for(let a=0;a<r;a++){const p=e[a];p(c),o.has(p)&&(l.schedule(p),t())}s=!1,i&&(i=!1,l.process(c))}};return l}const Ce=40;let z=!0,j=!1,Z=!1;const E={delta:0,timestamp:0},F=["read","update","preRender","render","postRender"],$=F.reduce((t,e)=>(t[e]=Te(()=>j=!0),t),{}),Ae=F.reduce((t,e)=>{const n=$[e];return t[e]=(r,s=!1,i=!1)=>(j||Ve(),n.schedule(r,s,i)),t},{}),Re=F.reduce((t,e)=>(t[e]=$[e].cancel,t),{});F.reduce((t,e)=>(t[e]=()=>$[e].process(E),t),{});const Ee=t=>$[t].process(E),Dt=t=>{j=!1,E.delta=z?It:Math.max(Math.min(t-E.timestamp,Ce),1),E.timestamp=t,Z=!0,F.forEach(Ee),Z=!1,j&&(z=!1,Ft(Dt))},Ve=()=>{j=!0,z=!0,Z||Ft(Dt)};function Pt(t,e,n=0){return t-e-n}function je(t,e,n=0,r=!0){return r?Pt(e+-t,e,n):e-(t-e)+n}function Ie(t,e,n,r){return r?t>=e+n:t<=-n}const Fe=t=>{const e=({delta:n})=>t(n);return{start:()=>Ae.update(e,!0),stop:()=>Re.update(e)}};function De(t){var e,n,{from:r,autoplay:s=!0,driver:i=Fe,elapsed:o=0,repeat:l=0,repeatType:c="loop",repeatDelay:a=0,onPlay:p,onStop:m,onComplete:u,onRepeat:f,onUpdate:h}=t,x=dt(t,["from","autoplay","driver","elapsed","repeat","repeatType","repeatDelay","onPlay","onStop","onComplete","onRepeat","onUpdate"]);let{to:y}=x,S,b=0,g=x.duration,d,M=!1,w=!0,T;const rt=ve(x);!((n=(e=rt).needsInterpolation)===null||n===void 0)&&n.call(e,r,y)&&(T=jt([0,100],[r,y],{clamp:!1}),r=0,y=100);const st=rt(Object.assign(Object.assign({},x),{from:r,to:y}));function Ut(){b++,c==="reverse"?(w=b%2===0,o=je(o,g,a,w)):(o=Pt(o,g,a),c==="mirror"&&st.flipTarget()),M=!1,f&&f()}function $t(){S.stop(),u&&u()}function qt(q){if(w||(q=-q),o+=q,!M){const ot=st.next(Math.max(0,o));d=ot.value,T&&(d=T(d)),M=w?ot.done:o<=0}h?.(d),M&&(b===0&&(g??(g=o)),b<l?Ie(o,g,a,w)&&Ut():$t())}function Lt(){p?.(),S=i(qt),S.start()}return s&&Lt(),{stop:()=>{m?.(),S.stop()}}}class C{options;currentValue;velocity=0;isAnimating=!1;controls=null;constructor(e){this.options={from:e.from??0,to:e.to??1,spring:e.spring??{stiffness:100,damping:10},onUpdate:e.onUpdate??(()=>{}),onComplete:e.onComplete??(()=>{}),onStart:e.onStart},this.currentValue=this.options.from}animate=(e=!1)=>{!this.isAnimating&&this.options.onStart&&this.options.onStart(),this.isAnimating=!0;const n=e?this.options.from:this.options.to;let r=this.currentValue,s=performance.now();this.controls=De({from:this.currentValue,to:n,velocity:this.velocity*1e3,stiffness:this.options.spring.stiffness,damping:this.options.spring.damping,mass:1,onUpdate:i=>{const o=performance.now(),l=(o-s)/1e3;if(l>0){const c=(i-r)/l;this.velocity=c/1e3,r=i,s=o}this.currentValue=i,this.options.onUpdate(i)},onComplete:()=>{this.currentValue=n,this.isAnimating=!1,this.controls=null,this.velocity=0,this.options.onComplete()}})};forward(){this.stop(),this.animate(!1)}backward(){this.stop(),this.animate(!0)}reverse(){const e=this.options.from;if(this.options.from=this.options.to,this.options.to=e,this.isAnimating){const n=this.currentValue>(this.options.from+this.options.to)/2;this.stop(),this.animate(!n)}}stop(){this.isAnimating=!1,this.controls&&(this.controls.stop(),this.controls=null)}getVelocity(){return this.velocity}getCurrentValue(){return this.currentValue}getIsAnimating(){return this.isAnimating}getCurrentState(){return{position:this.currentValue,velocity:this.velocity}}setVelocity(e){this.velocity=e}setValue(e){this.currentValue=e}updateOptions(e){if(this.options={...this.options,...e},this.isAnimating&&this.controls){const n=this.currentValue<this.options.to;this.stop(),this.animate(!n)}}static fromState(e,n){const r=new C(n);return r.setValue(e.position),r.setVelocity(e.velocity),r}}function Pe(t,e){let n=null,r=null,s=null,i=null,o=!1;const l=async a=>{if(n&&n.getIsAnimating()&&!o){const p=n.getCurrentState();n.stop(),r&&(r.remove(),r=null),o=!0;const m=t();if(!m.out)return;const u=await Promise.resolve(m.out(a));n=C.fromState(p,{from:1,to:0,spring:u.spring,onStart:u.onStart,onUpdate:f=>{u.tick?.(f)},onComplete:()=>{n=null,o=!1,u.onEnd?.()}}),n.backward();return}if(!n||!n.getIsAnimating()){o=!0;const p=t();if(!p.in)return;const m=await Promise.resolve(p.in(a));m.prepare?.(a),n=new C({from:0,to:1,spring:m.spring,onStart:m.onStart,onUpdate:u=>{m.tick?.(u)},onComplete:()=>{n=null,o=!1,m.onEnd?.()}}),n.forward()}};function c(a){const p=()=>{!s||!r||(i&&s.contains(i)?s.insertBefore(r,i):s.appendChild(r))},m=()=>{r&&(r.remove(),r=null),n=null,o=!1,e?.onCleanupEnd?.()},u=t();if(r=a.cloneNode(!0),n&&n.getIsAnimating()&&o){const f=n.getCurrentState();if(n.stop(),o=!1,!u.in){r=null,m();return}Promise.resolve(u.in(r)).then(async h=>{const x=r&&await u.out?.(r);x?.prepare&&r&&x.prepare(r),p(),n=C.fromState(f,{from:0,to:1,spring:h.spring,onStart:h.onStart,onUpdate:y=>{h.tick?.(y)},onComplete:()=>{h.onEnd?.(),m()}}),n.backward()});return}if(!n||!n.getIsAnimating()||!o){if(o=!1,!u.out){r=null,m();return}Promise.resolve(u.out(r)).then(f=>{r&&f.prepare?.(r),p(),n=new C({from:1,to:0,spring:f.spring,onStart:f.onStart,onUpdate:h=>{f.tick?.(h)},onComplete:()=>{f.onEnd?.(),m()}}),n.forward()})}}return a=>a?(s=a.parentElement,i=a.nextElementSibling,t().in&&l(a),()=>{c(a)}):void 0}const J=new Map,Q=new Map;function Ne(t,e){J.set(t,e);let n=Q.get(t);return n||(n=Pe(()=>{const r=J.get(t);return r||(console.warn(`Transition "${String(t)}" not found`),{})},{onCleanupEnd:()=>ke(t)}),Q.set(t,n),n)}function ke(t){J.delete(t),Q.delete(t)}function Ue(t){return Ne(t.key,{in:t.in,out:t.out})}function $e(t){let e=null;const n=[...t.transitions],r=[];for(const u of t.transitions)u.symmetric&&(n.some(h=>h.from===u.to&&h.to===u.from)||r.push({from:u.to,to:u.from,transition:u.transition}));n.push(...r);let s=null;const i=new Map;let o=null;const l=()=>{s&&o&&i.set(o,{x:s.scrollLeft,y:s.scrollTop})},c=(u,f)=>{s||(s=Bt.getScrollingElement(u),s.addEventListener("scroll",l,{passive:!0})),o=f},a=()=>{const u=e?.from,f=e?.to,h=u&&i.has(u)?i.get(u):{x:0,y:0},x=f&&i.has(f)?i.get(f):{x:0,y:0};return{x:-x.x+h.x,y:-x.y+h.y}};function p(){if(e?.from&&e?.to){const f=qe(e.from,e.to,n)||t.defaultTransition,x={scrollOffset:a()};f&&(f.out&&e.outResolve&&e.outResolve(y=>f.out(y,x)),f.in&&e.inResolve&&e.inResolve(y=>f.in(y,x))),e=null}}const m=async(u,f)=>f==="in"&&(!e||!e.from)?()=>({}):(e||(e={}),f==="out"?(e.from=u,new Promise(h=>{e.outResolve=h,p()})):(e.to=u,new Promise(h=>{e.inResolve=h,p()})));return u=>({key:u,in:async f=>(c(f,u),(await m(u,"in"))(f)),out:async f=>(await m(u,"out"))(f)})}function qe(t,e,n){for(const r of n)if(D(t,r.from)&&D(e,r.to))return r.transition;for(const r of n)if((r.from==="*"||D(t,r.from))&&(r.to==="*"||D(e,r.to)))return r.transition;return null}function D(t,e){if(e==="*")return!0;if(e.endsWith("/*")){const n=e.slice(0,-2);return t===n||t.startsWith(n+"/")}return t===e}const Nt=Ue,kt=X.createContext(null),Le=kt.Provider,Be=()=>{const t=X.useContext(kt);if(!t)throw new Error("useSsgoi must be used within SsgoiProvider");return t},_e=({config:t,children:e})=>{const n=X.useMemo(()=>$e(t),[t]);return ht.jsx(Le,{value:n,children:e})},We=({children:t,id:e})=>{const n=Be();return ht.jsx("div",{ref:Nt(n(e)),"data-ssgoi-transition":e,children:t})};exports.Ssgoi=_e;exports.SsgoiTransition=We;exports.transition=Nt;
|
package/dist/index.d.ts
ADDED