Skip to content

Commit

Permalink
feat: add View Transition API package (#117)
Browse files Browse the repository at this point in the history
Co-authored-by: vsevolod arutyunov <v.arutyunov@tinkoff.ru>
  • Loading branch information
sevaru and vsevolod arutyunov authored Sep 20, 2023
1 parent f922e92 commit fe9eb3e
Show file tree
Hide file tree
Showing 30 changed files with 863 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ jobs:
speech,
storage,
workers,
view-transition,
]
name: ${{ matrix.project }}
steps:
Expand Down Expand Up @@ -128,6 +129,11 @@ jobs:
directory: ./coverage/workers/
flags: summary,workers
name: workers
- uses: codecov/codecov-action@v3.1.3
with:
directory: ./coverage/view-transition/
flags: summary,view-transition
name: view-transition

concurrency:
group: test-${{ github.workflow }}-${{ github.ref }}
Expand Down
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"typescript.tsdk": "node_modules/typescript/lib"
}
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ High quality lightweight wrappers for native Web APIs for idiomatic use with Ang
- [`@ng-web-apis/storage`](https://github.com/taiga-family/ng-web-apis/blob/main/libs/storage/CHANGELOG.md)
- [`@ng-web-apis/universal`](https://github.com/taiga-family/ng-web-apis/blob/main/libs/universal/CHANGELOG.md)
- [`@ng-web-apis/workers`](https://github.com/taiga-family/ng-web-apis/blob/main/libs/workers/CHANGELOG.md)
- [`@ng-web-apis/view-transition`](https://github.com/taiga-family/ng-web-apis/blob/main/libs/view-transition/CHANGELOG.md)

## Core team

Expand Down
6 changes: 6 additions & 0 deletions apps/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ export const appRoutes: Routes = [
loadChildren: async () =>
(await import(`./pages/workers/workers-page.module`)).WorkersPageModule,
},
{
path: DemoPath.ViewTransitionPage,
loadChildren: async () =>
(await import(`./pages/view-transition/view-transition-page.module`))
.ViewTransitionPageModule,
},
{
path: '',
redirectTo: DemoPath.HomePage,
Expand Down
1 change: 1 addition & 0 deletions apps/demo/src/app/constants/demo-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export enum DemoPath {
PermissionsPage = `permissions`,
StoragePage = `storage`,
WorkersPage = `workers`,
ViewTransitionPage = `view-transition`,
}
15 changes: 15 additions & 0 deletions apps/demo/src/app/pages/home/home-page.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,18 @@ <h2>Workers</h2>
class="icon"
/>
</a>
<a class="link" [routerLink]="['/', link.ViewTransitionPage]">
<div>
<h2>View Transition</h2>
A library for declarative use of
<strong>View Transition API</strong>
with Angular
</div>
<img
src="assets/images/view-transition.svg"
width="64"
height="64"
alt="View transition API logo"
class="icon"
/>
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<h2>How to use</h2>
<p>
Usage is pretty simple: just import service in your component and call
<code>startViewTransition</code>
on it.
</p>
<pre><code [highlight]="codeSample" [languages]="['ts']"></code></pre>
<h2>Basic example</h2>

<ng-container
*tuiLet="{ detailInfo: detailInfo$ | async, activeIndex: activeIndex$ | async } as context"
>
<div *ngIf="!context.detailInfo" class="photos">
<div
*ngFor="let item of data; let index = index"
class="photo"
(click)="open(index)"
>
<span class="author">
Photo by
<a target="_blank" [href]="item.url">{{item.author}}</a>
</span>
<img
[src]="item.src"
[style.viewTransitionName]="context.activeIndex === index ? 'expandable-image' : null"
/>
</div>
</div>

<div *ngIf="context.detailInfo" class="expanded-photo">
<img [src]="context.detailInfo.src" (click)="close()" />
</div>
</ng-container>

<a tuiLink href="https://www.pexels.com" target="_blank">
Photos provided by Pexels
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
:host {
display: flex;
align-items: center;
flex-direction: column;
}

.photos {
display: flex;
justify-content: center;
align-items: flex-start;
flex-wrap: wrap;
gap: 1rem;
margin: 1rem 0;
}

.photo {
width: 12rem;
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;

.author {
margin-bottom: 0.5rem;

a:hover {
text-decoration: underline;
}
}

img {
display: block;
width: 100%;
border-radius: 0.5rem;
transition: transform 0.2s;

&:hover {
transform: scale(1.05);
}
}
}

.expanded-photo {
margin: 0 auto 1rem;
width: 20rem;
display: flex;
cursor: pointer;

img {
display: block;
view-transition-name: expandable-image;
border-radius: 1rem;
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.2);
width: 100%;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {ChangeDetectionStrategy, ChangeDetectorRef, Component} from '@angular/core';
import {BehaviorSubject, takeUntil} from 'rxjs';
import {ViewTransitionService} from '@ng-web-apis/view-transition';
import {TuiDestroyService} from '@taiga-ui/cdk';

interface Photo {
src: string;
author: string;
url: string;
}

const PHOTOS: readonly Photo[] = [
{
src: 'https://images.pexels.com/photos/16316785/pexels-photo-16316785/free-photo-of-fluffy-cat-on-blooming-tree-background.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
author: 'Peng Louis',
url: 'https://www.pexels.com/photo/fluffy-cat-on-blooming-tree-background-16316785/',
},
{
src: 'https://images.pexels.com/photos/6001385/pexels-photo-6001385.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
author: 'Sam Lion',
url: 'https://www.pexels.com/photo/cute-curious-cat-watching-video-on-laptop-sitting-on-couch-6001385/',
},
{
src: 'https://images.pexels.com/photos/7210265/pexels-photo-7210265.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1',
author: 'Blue Bird',
url: 'https://www.pexels.com/photo/ginger-cat-sleeping-on-ground-in-autumn-7210265/',
},
];

const USAGE_SAMPLE = `
// 1) Import service throught DI
// In Constructor
constructor(private viewTransitionService: ViewTransitionService) {}
// or with inject (Angular 14+)
private service = inject(ViewTransitionService);
// 2) Call startViewTransition method and pass callback that would change the DOM
private showMyComponent(): void {
this.viewTransitionService.startViewTransition(() => {
this.showMyComponent = true;
// You might want to call detectChanges to update the DOM inside startViewTransition callback
this.cdr.detectChanges();
}).subscribe();
}
`;

@Component({
selector: `view-transition-page`,
templateUrl: `./view-transition-page.component.html`,
styleUrls: [`./view-transition-page.component.less`],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [TuiDestroyService],
})
export class ViewTransitionPageComponent {
readonly codeSample = USAGE_SAMPLE;
readonly data = PHOTOS;
readonly activeIndex$ = new BehaviorSubject(-1);
readonly detailInfo$ = new BehaviorSubject<Photo | undefined>(undefined);

constructor(
private readonly viewTransitionService: ViewTransitionService,
private readonly cdr: ChangeDetectorRef,
private readonly destroy$: TuiDestroyService,
) {}

open(index: number): void {
this.activeIndex$.next(index);
this.viewTransitionService
.startViewTransition(() => {
this.detailInfo$.next(this.data[index]);
this.cdr.detectChanges();
})
.pipe(takeUntil(this.destroy$))
.subscribe();
}

close(): void {
this.viewTransitionService
.startViewTransition(() => {
this.detailInfo$.next(undefined);
this.cdr.detectChanges();
this.activeIndex$.next(-1);
})
.pipe(takeUntil(this.destroy$))
.subscribe();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {NgModule} from '@angular/core';
import {ViewTransitionPageComponent} from './view-transition-page.component';
import {RouterModule} from '@angular/router';
import {CommonModule} from '@angular/common';
import {HighlightModule} from 'ngx-highlightjs';
import {TuiLinkModule} from '@taiga-ui/core';
import {TuiLetModule} from '@taiga-ui/cdk';

@NgModule({
imports: [
CommonModule,
HighlightModule,
TuiLinkModule,
TuiLetModule,
RouterModule.forChild([{path: '', component: ViewTransitionPageComponent}]),
],
declarations: [ViewTransitionPageComponent],
})
export class ViewTransitionPageModule {}
15 changes: 15 additions & 0 deletions apps/demo/src/assets/images/view-transition.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions apps/demo/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
"extends": "../../tsconfig.json",
"files": ["src/main.ts", "src/polyfills.ts"],
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": ["webmidi"]
"outDir": "./out-tsc/app"
},
"include": ["**/*.d.ts"],
"angularCompilerOptions": {
Expand Down
2 changes: 1 addition & 1 deletion apps/demo/tsconfig.server.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"compilerOptions": {
"outDir": "./dist/out-tsc-server",
"target": "es2016",
"types": ["node", "webmidi"]
"types": ["node", "webmidi", "dom-view-transitions"]
},
"files": ["src/typings.d.ts", "src/main.server.ts", "server.ts"],
"angularCompilerOptions": {
Expand Down
Empty file.
Loading

0 comments on commit fe9eb3e

Please sign in to comment.