@ssgoi/angular 5.2.0 → 6.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 +13 -59
- package/package.json +2 -23
- package/src/lib/context.ts +7 -6
- package/src/lib/index.ts +1 -6
- package/src/lib/ssgoi-transition.directive.ts +3 -16
- package/src/lib/ssgoi.directive.ts +7 -3
- package/src/lib/types.ts +1 -1
- package/view-transitions/ng-package.json +2 -2
- package/view-transitions/public-api.ts +1 -0
- package/presets/ng-package.json +0 -6
- package/src/lib/presets/index.ts +0 -1
- package/src/lib/transition-scope.directive.ts +0 -54
- package/src/lib/transition.directive.ts +0 -54
- package/src/lib/transitions/index.ts +0 -1
- package/src/lib/view-transitions/index.ts +0 -1
- package/transitions/ng-package.json +0 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @ssgoi/angular
|
|
2
2
|
|
|
3
|
-
Angular bindings for SSGOI that give any Angular 20+ app native-feeling page
|
|
3
|
+
Angular bindings for SSGOI that give any Angular 20+ app native-feeling page transitions powered by the `@ssgoi/core` animation engine.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -16,9 +16,8 @@ yarn add @ssgoi/angular
|
|
|
16
16
|
|
|
17
17
|
- `Ssgoi` directive (selector: `[ssgoi]`) that bootstraps the core transition context on the client and gracefully no-ops during SSR.
|
|
18
18
|
- `SsgoiTransition` directive (selector: `[ssgoiTransition]`) that wires individual route containers into the transition system.
|
|
19
|
-
- `
|
|
20
|
-
-
|
|
21
|
-
- Re-exported transition factories and presets under `@ssgoi/angular/view-transitions`, `@ssgoi/angular/transitions`, and `@ssgoi/angular/presets`.
|
|
19
|
+
- `injectSsgoi()` helper and `SSGOI_CONTEXT` injection token for retrieving the transition context anywhere in your component tree.
|
|
20
|
+
- Re-exported transition factories under `@ssgoi/angular/view-transitions`.
|
|
22
21
|
|
|
23
22
|
## Quick Start
|
|
24
23
|
|
|
@@ -46,7 +45,7 @@ import { fade } from "@ssgoi/angular/view-transitions";
|
|
|
46
45
|
})
|
|
47
46
|
export class AppComponent {
|
|
48
47
|
protected readonly ssgoiConfig = signal<SsgoiConfig>({
|
|
49
|
-
|
|
48
|
+
transitions: [fade({ paths: ["/home", "/about"] })],
|
|
50
49
|
});
|
|
51
50
|
}
|
|
52
51
|
```
|
|
@@ -72,37 +71,10 @@ export class HomeComponent {}
|
|
|
72
71
|
|
|
73
72
|
The value you pass to `[ssgoiTransition]` should uniquely identify the view (commonly the route path).
|
|
74
73
|
|
|
75
|
-
### 3. (Optional) Add element-level transitions
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { Component } from "@angular/core";
|
|
79
|
-
import { TransitionDirective } from "@ssgoi/angular";
|
|
80
|
-
import { fade } from "@ssgoi/angular/transitions";
|
|
81
|
-
|
|
82
|
-
@Component({
|
|
83
|
-
selector: "app-call-to-action",
|
|
84
|
-
standalone: true,
|
|
85
|
-
imports: [TransitionDirective],
|
|
86
|
-
template: `
|
|
87
|
-
<button
|
|
88
|
-
[transition]="{
|
|
89
|
-
key: 'cta',
|
|
90
|
-
in: fade({ duration: 220 }),
|
|
91
|
-
out: fade({ duration: 180 })
|
|
92
|
-
}"
|
|
93
|
-
>
|
|
94
|
-
Get Started
|
|
95
|
-
</button>
|
|
96
|
-
`,
|
|
97
|
-
})
|
|
98
|
-
export class CallToActionComponent {}
|
|
99
|
-
```
|
|
100
|
-
|
|
101
74
|
## How It Works
|
|
102
75
|
|
|
103
76
|
- `Ssgoi` wraps `createSggoiTransitionContext` from `@ssgoi/core` and injects it via `SSGOI_CONTEXT`. The directive guards against the server platform so SSR renders stay deterministic.
|
|
104
77
|
- `SsgoiTransition` reads that context with `injectSsgoi()`, sets `data-ssgoi-transition` on the host, and subscribes the element to the core transition runner.
|
|
105
|
-
- `TransitionDirective` lets any element opt into spring-driven enter/leave effects while sharing the same scheduling primitives as view transitions.
|
|
106
78
|
|
|
107
79
|
Because everything is driven by signals, Angular change detection stays minimal and the bundle remains fully tree-shakeable.
|
|
108
80
|
|
|
@@ -110,37 +82,24 @@ Because everything is driven by signals, Angular change detection stays minimal
|
|
|
110
82
|
|
|
111
83
|
- `Ssgoi`
|
|
112
84
|
- `config: SsgoiConfig` (input, optional) – global transition configuration. Uses `{}` as default.
|
|
85
|
+
- `host: HostAnimation | undefined` (input, optional) – external playback host for debug tooling.
|
|
113
86
|
- `SsgoiTransition`
|
|
114
87
|
- `ssgoiTransition: string` (required input) – identifier for the target view/container.
|
|
115
|
-
- `
|
|
116
|
-
- `transition: TransitionDirectiveConfig` (required input) – accepts any config from `@ssgoi/core`, plus an optional `key` to coordinate enter/leave pairs.
|
|
117
|
-
- `injectSsgoi(): SsgoiContext` – returns a function that looks up transition definitions by id. During SSR it falls back to a no-op implementation so you can call it unconditionally.
|
|
88
|
+
- `injectSsgoi(): SsgoiContext` – returns the adapter context. During SSR it falls back to a no-op implementation so you can call it unconditionally.
|
|
118
89
|
|
|
119
90
|
## Available Transitions
|
|
120
91
|
|
|
121
92
|
View-level factories:
|
|
122
93
|
|
|
123
|
-
```typescript
|
|
124
|
-
import { fade, scroll, drill, hero, pinterest } from "@ssgoi/angular/view-transitions";
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Element-level factories:
|
|
128
|
-
|
|
129
94
|
```typescript
|
|
130
95
|
import {
|
|
131
96
|
fade,
|
|
97
|
+
scroll,
|
|
98
|
+
drill,
|
|
99
|
+
hero,
|
|
132
100
|
slide,
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
blur,
|
|
136
|
-
rotate,
|
|
137
|
-
} from "@ssgoi/angular/transitions";
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Presets that combine common configurations:
|
|
141
|
-
|
|
142
|
-
```typescript
|
|
143
|
-
import { marketingPreset, dashboardPreset } from "@ssgoi/angular/presets";
|
|
101
|
+
zoom,
|
|
102
|
+
} from "@ssgoi/angular/view-transitions";
|
|
144
103
|
```
|
|
145
104
|
|
|
146
105
|
## Sample Configuration
|
|
@@ -150,14 +109,9 @@ import { fade, scroll } from "@ssgoi/angular/view-transitions";
|
|
|
150
109
|
import type { SsgoiConfig } from "@ssgoi/angular";
|
|
151
110
|
|
|
152
111
|
export const config: SsgoiConfig = {
|
|
153
|
-
defaultTransition: fade(),
|
|
154
112
|
transitions: [
|
|
155
|
-
{
|
|
156
|
-
|
|
157
|
-
to: "/about",
|
|
158
|
-
transition: scroll({ direction: "up" }),
|
|
159
|
-
symmetric: true,
|
|
160
|
-
},
|
|
113
|
+
fade({ paths: ["/", "/home"] }),
|
|
114
|
+
scroll({ paths: ["/home", "/about"] }),
|
|
161
115
|
],
|
|
162
116
|
};
|
|
163
117
|
```
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssgoi/angular",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Angular bindings for SSGOI - Native app-like page transitions for Angular applications",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@ssgoi/core": "^
|
|
9
|
+
"@ssgoi/core": "^6.1.0"
|
|
10
10
|
},
|
|
11
11
|
"peerDependencies": {
|
|
12
12
|
"@angular/common": "^20.0.0",
|
|
@@ -53,27 +53,6 @@
|
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=18.0.0"
|
|
55
55
|
},
|
|
56
|
-
"exports": {
|
|
57
|
-
"./package.json": {
|
|
58
|
-
"default": "./package.json"
|
|
59
|
-
},
|
|
60
|
-
".": {
|
|
61
|
-
"types": "./dist/index.d.ts",
|
|
62
|
-
"default": "./dist/fesm2022/ssgoi-angular.mjs"
|
|
63
|
-
},
|
|
64
|
-
"./presets": {
|
|
65
|
-
"types": "./dist/presets/index.d.ts",
|
|
66
|
-
"default": "./dist/fesm2022/ssgoi-angular-presets.mjs"
|
|
67
|
-
},
|
|
68
|
-
"./transitions": {
|
|
69
|
-
"types": "./dist/transitions/index.d.ts",
|
|
70
|
-
"default": "./dist/fesm2022/ssgoi-angular-transitions.mjs"
|
|
71
|
-
},
|
|
72
|
-
"./view-transitions": {
|
|
73
|
-
"types": "./dist/view-transitions/index.d.ts",
|
|
74
|
-
"default": "./dist/fesm2022/ssgoi-angular-view-transitions.mjs"
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
56
|
"sideEffects": false,
|
|
78
57
|
"scripts": {
|
|
79
58
|
"build": "ng-packagr -p ng-package.json",
|
package/src/lib/context.ts
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
import { InjectionToken, inject } from "@angular/core";
|
|
2
|
-
import type { SsgoiContext } from "@ssgoi/core";
|
|
2
|
+
import type { SsgoiContext } from "@ssgoi/core/types";
|
|
3
3
|
|
|
4
4
|
export const SSGOI_CONTEXT = new InjectionToken<SsgoiContext | undefined>(
|
|
5
5
|
"ssgoi-context",
|
|
6
6
|
);
|
|
7
7
|
|
|
8
|
+
const noopContext: SsgoiContext = {
|
|
9
|
+
register: () => {},
|
|
10
|
+
refFor: () => () => {},
|
|
11
|
+
};
|
|
12
|
+
|
|
8
13
|
export function injectSsgoi(): SsgoiContext {
|
|
9
14
|
const context = inject(SSGOI_CONTEXT, { optional: true });
|
|
10
15
|
|
|
11
16
|
if (!context) {
|
|
12
17
|
// During SSR or when not wrapped in <ssgoi>, return a no-op context
|
|
13
18
|
// This prevents errors during server-side rendering
|
|
14
|
-
return
|
|
15
|
-
key: "",
|
|
16
|
-
in: async () => ({}),
|
|
17
|
-
out: async () => ({}),
|
|
18
|
-
});
|
|
19
|
+
return noopContext;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
return context;
|
package/src/lib/index.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
export { Ssgoi } from "./ssgoi.directive";
|
|
2
2
|
export { SsgoiTransition } from "./ssgoi-transition.directive";
|
|
3
|
-
export {
|
|
4
|
-
TransitionDirective,
|
|
5
|
-
TransitionDirectiveConfig,
|
|
6
|
-
} from "./transition.directive";
|
|
7
|
-
export { TransitionScopeDirective } from "./transition-scope.directive";
|
|
8
3
|
export { injectSsgoi, SSGOI_CONTEXT } from "./context";
|
|
9
|
-
export { transition } from "@ssgoi/core";
|
|
10
4
|
export * from "./types";
|
|
5
|
+
export * from "@ssgoi/core";
|
|
@@ -2,28 +2,25 @@ import {
|
|
|
2
2
|
Directive,
|
|
3
3
|
input,
|
|
4
4
|
OnInit,
|
|
5
|
-
OnDestroy,
|
|
6
5
|
AfterViewInit,
|
|
7
6
|
ElementRef,
|
|
8
7
|
inject,
|
|
9
8
|
PLATFORM_ID,
|
|
10
9
|
} from "@angular/core";
|
|
11
10
|
import { isPlatformBrowser } from "@angular/common";
|
|
12
|
-
import { transition } from "@ssgoi/core";
|
|
13
11
|
import { injectSsgoi } from "./context";
|
|
14
12
|
|
|
15
13
|
@Directive({
|
|
16
14
|
selector: "[ssgoiTransition]",
|
|
17
15
|
standalone: true,
|
|
18
16
|
})
|
|
19
|
-
export class SsgoiTransition implements OnInit,
|
|
17
|
+
export class SsgoiTransition implements OnInit, AfterViewInit {
|
|
20
18
|
// The directive attribute value becomes the transition ID
|
|
21
19
|
readonly ssgoiTransition = input.required<string>();
|
|
22
20
|
|
|
23
|
-
private readonly
|
|
21
|
+
private readonly ssgoi = injectSsgoi();
|
|
24
22
|
private readonly el = inject(ElementRef<HTMLElement>);
|
|
25
23
|
private readonly platformId = inject(PLATFORM_ID);
|
|
26
|
-
private cleanup?: () => void;
|
|
27
24
|
|
|
28
25
|
ngOnInit(): void {
|
|
29
26
|
if (!isPlatformBrowser(this.platformId)) {
|
|
@@ -44,16 +41,6 @@ export class SsgoiTransition implements OnInit, OnDestroy, AfterViewInit {
|
|
|
44
41
|
|
|
45
42
|
// Use the host element itself as the transition target
|
|
46
43
|
const targetElement = this.el.nativeElement;
|
|
47
|
-
|
|
48
|
-
const transitionConfig = this.getTransition(this.ssgoiTransition());
|
|
49
|
-
const cleanupResult = transition(transitionConfig)(targetElement);
|
|
50
|
-
|
|
51
|
-
if (cleanupResult) {
|
|
52
|
-
this.cleanup = cleanupResult;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
ngOnDestroy(): void {
|
|
57
|
-
this.cleanup?.();
|
|
44
|
+
this.ssgoi.refFor(this.ssgoiTransition())(targetElement);
|
|
58
45
|
}
|
|
59
46
|
}
|
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
inject,
|
|
7
7
|
} from "@angular/core";
|
|
8
8
|
import { isPlatformBrowser } from "@angular/common";
|
|
9
|
-
import { createSggoiTransitionContext } from "@ssgoi/core";
|
|
10
|
-
import type {
|
|
9
|
+
import { createSggoiTransitionContext } from "@ssgoi/core/internal";
|
|
10
|
+
import type { HostAnimation } from "@ssgoi/core/internal";
|
|
11
|
+
import type { SsgoiConfig, SsgoiContext } from "@ssgoi/core/types";
|
|
11
12
|
import { SSGOI_CONTEXT } from "./context";
|
|
12
13
|
|
|
13
14
|
function createSsgoiContext(component: Ssgoi): SsgoiContext | undefined {
|
|
@@ -18,7 +19,9 @@ function createSsgoiContext(component: Ssgoi): SsgoiContext | undefined {
|
|
|
18
19
|
// Return a no-op context for SSR
|
|
19
20
|
return undefined;
|
|
20
21
|
}
|
|
21
|
-
return createSggoiTransitionContext(component.config()
|
|
22
|
+
return createSggoiTransitionContext(component.config(), {
|
|
23
|
+
host: component.host(),
|
|
24
|
+
});
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
@Directive({
|
|
@@ -34,4 +37,5 @@ function createSsgoiContext(component: Ssgoi): SsgoiContext | undefined {
|
|
|
34
37
|
})
|
|
35
38
|
export class Ssgoi {
|
|
36
39
|
readonly config = input<SsgoiConfig>({});
|
|
40
|
+
readonly host = input<HostAnimation | undefined>(undefined);
|
|
37
41
|
}
|
package/src/lib/types.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type * from "@ssgoi/core";
|
|
1
|
+
export type * from "@ssgoi/core/types";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "@ssgoi/core";
|
package/presets/ng-package.json
DELETED
package/src/lib/presets/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "@ssgoi/core/presets";
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Directive,
|
|
3
|
-
ElementRef,
|
|
4
|
-
OnInit,
|
|
5
|
-
OnDestroy,
|
|
6
|
-
inject,
|
|
7
|
-
PLATFORM_ID,
|
|
8
|
-
} from "@angular/core";
|
|
9
|
-
import { isPlatformBrowser } from "@angular/common";
|
|
10
|
-
import { createTransitionScope } from "@ssgoi/core";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* TransitionScope creates a boundary for local-scoped transitions.
|
|
14
|
-
*
|
|
15
|
-
* Child elements with `scope: 'local'` will:
|
|
16
|
-
* - Skip IN animation when mounted simultaneously with the scope
|
|
17
|
-
* - Skip OUT animation when unmounted simultaneously with the scope
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```html
|
|
21
|
-
* <div transitionScope>
|
|
22
|
-
* <div [transition]="{ scope: 'local', in: ..., out: ... }">
|
|
23
|
-
* Content
|
|
24
|
-
* </div>
|
|
25
|
-
* </div>
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
@Directive({
|
|
29
|
-
selector: "[transitionScope]",
|
|
30
|
-
host: {
|
|
31
|
-
style: "display: contents",
|
|
32
|
-
},
|
|
33
|
-
})
|
|
34
|
-
export class TransitionScopeDirective implements OnInit, OnDestroy {
|
|
35
|
-
private readonly el = inject(ElementRef<HTMLElement>);
|
|
36
|
-
private readonly platformId = inject(PLATFORM_ID);
|
|
37
|
-
private cleanup?: () => void;
|
|
38
|
-
|
|
39
|
-
ngOnInit(): void {
|
|
40
|
-
if (!isPlatformBrowser(this.platformId)) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const cleanupResult = createTransitionScope()(this.el.nativeElement);
|
|
45
|
-
|
|
46
|
-
if (cleanupResult) {
|
|
47
|
-
this.cleanup = cleanupResult;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
ngOnDestroy(): void {
|
|
52
|
-
this.cleanup?.();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Directive,
|
|
3
|
-
ElementRef,
|
|
4
|
-
input,
|
|
5
|
-
OnInit,
|
|
6
|
-
OnDestroy,
|
|
7
|
-
inject,
|
|
8
|
-
PLATFORM_ID,
|
|
9
|
-
} from "@angular/core";
|
|
10
|
-
import { isPlatformBrowser } from "@angular/common";
|
|
11
|
-
import { transition as coreTransition } from "@ssgoi/core";
|
|
12
|
-
import type {
|
|
13
|
-
Transition as CoreTransitionConfig,
|
|
14
|
-
TransitionKey as CoreTransitionKey,
|
|
15
|
-
TransitionScope as CoreTransitionScope,
|
|
16
|
-
} from "@ssgoi/core";
|
|
17
|
-
|
|
18
|
-
export type TransitionDirectiveConfig = CoreTransitionConfig & {
|
|
19
|
-
key?: CoreTransitionKey;
|
|
20
|
-
scope?: CoreTransitionScope;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
@Directive({
|
|
24
|
-
selector: "[transition]",
|
|
25
|
-
})
|
|
26
|
-
export class TransitionDirective implements OnInit, OnDestroy {
|
|
27
|
-
transition = input.required<TransitionDirectiveConfig>();
|
|
28
|
-
|
|
29
|
-
private readonly el = inject(ElementRef<HTMLElement>);
|
|
30
|
-
private readonly platformId = inject(PLATFORM_ID);
|
|
31
|
-
private cleanup?: () => void;
|
|
32
|
-
|
|
33
|
-
ngOnInit(): void {
|
|
34
|
-
if (!isPlatformBrowser(this.platformId)) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const config = this.transition();
|
|
39
|
-
const cleanupResult = coreTransition({
|
|
40
|
-
key: config.key,
|
|
41
|
-
in: config.in,
|
|
42
|
-
out: config.out,
|
|
43
|
-
scope: config.scope,
|
|
44
|
-
})(this.el.nativeElement);
|
|
45
|
-
|
|
46
|
-
if (cleanupResult) {
|
|
47
|
-
this.cleanup = cleanupResult;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
ngOnDestroy(): void {
|
|
52
|
-
this.cleanup?.();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "@ssgoi/core/transitions";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "@ssgoi/core/view-transitions";
|