From 4b797dc1013bda5493a9939a187b4ceffcb643ae Mon Sep 17 00:00:00 2001 From: Maksim Dolgikh Date: Fri, 29 Dec 2023 12:50:43 +0400 Subject: [PATCH] chore: created part1 and part2 --- .eslintrc.json | 2 +- .prettierrc | 3 +- README.md | 4 +- e2e/playwright.config.ts | 2 +- e2e/project.json | 2 +- e2e/src/example.spec.ts | 2 +- jest.config.ts | 4 +- nx.json | 2 +- package-lock.json | 4 +- package.json | 2 +- project.json | 12 +++--- src/app/animations/collapse.ts | 20 ---------- src/app/app.component.html | 21 +--------- src/app/app.component.scss | 17 --------- src/app/app.component.ts | 38 ++----------------- src/app/part-1/animations/collapse.ts | 30 +++++++++++++++ .../components/bonus/bonus.component.html | 1 + .../components/bonus/bonus.component.scss | 8 ++++ .../components/bonus/bonus.component.ts | 28 ++++++++++++++ .../part-1/reusable-animations.component.html | 22 +++++++++++ .../part-1/reusable-animations.component.scss | 11 ++++++ .../part-1/reusable-animations.component.ts | 30 +++++++++++++++ src/app/part-2/animations/fade.ts | 25 ++++++++++++ .../components/item}/item.component.html | 0 .../components/item}/item.component.scss | 1 + .../components/item}/item.component.ts | 0 .../part-2/disable-animations.component.html | 14 +++++++ .../part-2/disable-animations.component.scss | 25 ++++++++++++ .../part-2/disable-animations.component.ts | 35 +++++++++++++++++ .../part-2/tokens/animation-params.token.ts | 24 ++++++++++++ src/index.html | 2 +- src/styles.scss | 21 +++++++++- 32 files changed, 301 insertions(+), 111 deletions(-) delete mode 100644 src/app/animations/collapse.ts create mode 100644 src/app/part-1/animations/collapse.ts create mode 100644 src/app/part-1/components/bonus/bonus.component.html create mode 100644 src/app/part-1/components/bonus/bonus.component.scss create mode 100644 src/app/part-1/components/bonus/bonus.component.ts create mode 100644 src/app/part-1/reusable-animations.component.html create mode 100644 src/app/part-1/reusable-animations.component.scss create mode 100644 src/app/part-1/reusable-animations.component.ts create mode 100644 src/app/part-2/animations/fade.ts rename src/app/{components/angular-animation => part-2/components/item}/item.component.html (100%) rename src/app/{components/angular-animation => part-2/components/item}/item.component.scss (81%) rename src/app/{components/angular-animation => part-2/components/item}/item.component.ts (100%) create mode 100644 src/app/part-2/disable-animations.component.html create mode 100644 src/app/part-2/disable-animations.component.scss create mode 100644 src/app/part-2/disable-animations.component.ts create mode 100644 src/app/part-2/tokens/animation-params.token.ts diff --git a/.eslintrc.json b/.eslintrc.json index b119aeb..bcb0c2b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,7 +25,7 @@ "error", { "type": "attribute", - "prefix": "agnularPreferReduceMotion", + "prefix": "angularPreferReduceMotion", "style": "camelCase" } ], diff --git a/.prettierrc b/.prettierrc index 544138b..2ddc965 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,3 +1,4 @@ { - "singleQuote": true + "singleQuote": true, + "printWidth": 80 } diff --git a/README.md b/README.md index c22f3be..6161ed3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# AgnularPreferReduceMotion +# angularPreferReduceMotion @@ -7,7 +7,7 @@ ## Start the app -To start the development server run `nx serve agnular-prefer-reduce-motion`. Open your browser and navigate to http://localhost:4200/. Happy coding! +To start the development server run `nx serve angular-prefer-reduce-motion`. Open your browser and navigate to http://localhost:4200/. Happy coding! ## Generate code diff --git a/e2e/playwright.config.ts b/e2e/playwright.config.ts index 87ec692..79de591 100644 --- a/e2e/playwright.config.ts +++ b/e2e/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ }, /* Run your local dev server before starting the tests */ webServer: { - command: 'npx nx serve agnular-prefer-reduce-motion', + command: 'npx nx serve angular-prefer-reduce-motion', url: 'http://localhost:4200', reuseExistingServer: !process.env.CI, cwd: workspaceRoot, diff --git a/e2e/project.json b/e2e/project.json index e636b97..9fd6bcc 100644 --- a/e2e/project.json +++ b/e2e/project.json @@ -16,5 +16,5 @@ "outputs": ["{options.outputFile}"] } }, - "implicitDependencies": ["agnular-prefer-reduce-motion"] + "implicitDependencies": ["angular-prefer-reduce-motion"] } diff --git a/e2e/src/example.spec.ts b/e2e/src/example.spec.ts index fa8f1f3..19c82a3 100644 --- a/e2e/src/example.spec.ts +++ b/e2e/src/example.spec.ts @@ -1,6 +1,6 @@ import { test, expect } from '@playwright/test'; -test('has title', async ({ page }) => { +test('has title', async ({ page }): Promise => { await page.goto('/'); // Expect h1 to contain a substring. diff --git a/jest.config.ts b/jest.config.ts index afec572..50dec44 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -1,9 +1,9 @@ /* eslint-disable */ export default { - displayName: 'agnular-prefer-reduce-motion', + displayName: 'angular-prefer-reduce-motion', preset: './jest.preset.js', setupFilesAfterEnv: ['/src/test-setup.ts'], - coverageDirectory: './coverage/agnular-prefer-reduce-motion', + coverageDirectory: './coverage/angular-prefer-reduce-motion', transform: { '^.+\\.(ts|mjs|js|html)$': [ 'jest-preset-angular', diff --git a/nx.json b/nx.json index 1841c6c..895d798 100644 --- a/nx.json +++ b/nx.json @@ -65,5 +65,5 @@ "style": "scss" } }, - "defaultProject": "agnular-prefer-reduce-motion" + "defaultProject": "angular-prefer-reduce-motion" } diff --git a/package-lock.json b/package-lock.json index 8240899..cbb7143 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@agnular-prefer-reduce-motion/source", + "name": "@angular-prefer-reduce-motion/source", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@agnular-prefer-reduce-motion/source", + "name": "@angular-prefer-reduce-motion/source", "version": "0.0.0", "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 6bf19a1..697033b 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@agnular-prefer-reduce-motion/source", + "name": "@angular-prefer-reduce-motion/source", "version": "0.0.0", "license": "MIT", "scripts": { diff --git a/project.json b/project.json index ee7a64c..c7f7fcc 100644 --- a/project.json +++ b/project.json @@ -1,8 +1,8 @@ { - "name": "agnular-prefer-reduce-motion", + "name": "angular-prefer-reduce-motion", "$schema": "node_modules/nx/schemas/project-schema.json", "projectType": "application", - "prefix": "agnular-prefer-reduce-motion", + "prefix": "angular-prefer-reduce-motion", "sourceRoot": "./src", "tags": [], "targets": { @@ -10,7 +10,7 @@ "executor": "@angular-devkit/build-angular:application", "outputs": ["{options.outputPath}"], "options": { - "outputPath": "dist/agnular-prefer-reduce-motion", + "outputPath": "dist/angular-prefer-reduce-motion", "index": "./src/index.html", "browser": "./src/main.ts", "polyfills": ["zone.js"], @@ -48,10 +48,10 @@ "executor": "@angular-devkit/build-angular:dev-server", "configurations": { "production": { - "buildTarget": "agnular-prefer-reduce-motion:build:production" + "buildTarget": "angular-prefer-reduce-motion:build:production" }, "development": { - "buildTarget": "agnular-prefer-reduce-motion:build:development" + "buildTarget": "angular-prefer-reduce-motion:build:development" } }, "defaultConfiguration": "development" @@ -59,7 +59,7 @@ "extract-i18n": { "executor": "@angular-devkit/build-angular:extract-i18n", "options": { - "buildTarget": "agnular-prefer-reduce-motion:build" + "buildTarget": "angular-prefer-reduce-motion:build" } }, "lint": { diff --git a/src/app/animations/collapse.ts b/src/app/animations/collapse.ts deleted file mode 100644 index 56660b1..0000000 --- a/src/app/animations/collapse.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { animate, style, transition, trigger } from '@angular/animations'; - -const TRANSITION = '{{duration}}ms linear'; -const DURATION = {params: {duration: 300}}; - -const leavedStyle = style({opacity: 0}); -const enteredStyle = style({opacity: 1}); - -export const AN_COLLAPSE = trigger('collapse', [ - transition( - ':enter', - [leavedStyle, animate(TRANSITION, enteredStyle)], - DURATION, - ), - transition( - ':leave', - [enteredStyle, animate(TRANSITION, leavedStyle)], - DURATION, - ), -]); diff --git a/src/app/app.component.html b/src/app/app.component.html index 656c53d..d96369f 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,20 +1,3 @@ - - -
- - Angular animation item - - - - Css animation item - -
+ + diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 334225c..e69de29 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -1,17 +0,0 @@ -:host { - display: flex; - flex-direction: column; - gap: 8px; - - .show { - opacity: 1; - } - - .hide { - opacity: 0; - } - - .css-animation { - transition: all 300ms linear; - } -} diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5ff4d21..da2268e 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,42 +1,12 @@ -import { AnimationOptions, AnimationEvent } from '@angular/animations'; -import { NgClass, NgIf } from '@angular/common'; import { Component } from '@angular/core'; -import { AN_COLLAPSE } from './animations/collapse'; -import { ItemComponent } from './components/angular-animation/item.component'; +import { ReusableAnimationsComponent } from './part-1/reusable-animations.component'; +import { DisableAnimationsComponent } from './part-2/disable-animations.component'; @Component({ standalone: true, - imports: [ItemComponent, NgIf, NgClass], + imports: [ReusableAnimationsComponent, DisableAnimationsComponent], selector: 'app-root', templateUrl: './app.component.html', styleUrl: './app.component.scss', - animations: [ - AN_COLLAPSE - ] }) -export class AppComponent { - show = true - - options: AnimationOptions & { value: boolean } = { - value: true, - params: { - duration: 400 - } - }; - - onAnimationEvent(event: AnimationEvent ) { - switch (event.phaseName) { - case 'start': { - console.time('animation'); - break - } - case 'done': { - console.timeEnd('animation'); - break; - } - default: { - break - } - } - } -} +export class AppComponent {} diff --git a/src/app/part-1/animations/collapse.ts b/src/app/part-1/animations/collapse.ts new file mode 100644 index 0000000..f081e5c --- /dev/null +++ b/src/app/part-1/animations/collapse.ts @@ -0,0 +1,30 @@ +import { + animate, + animation, + AnimationOptions, + style, + transition, + trigger, +} from '@angular/animations'; + +const closedStyle = style({ height: 0 }); +const openStyle = style({ height: '*' }); +const animateTimings = '{{duration}}ms linear'; +const defaultOptions: AnimationOptions = { params: { duration: 300 } }; + +export const collapse = trigger('collapse', [ + transition( + ':enter', + animation([closedStyle, animate(animateTimings, openStyle)]), + defaultOptions + ), + transition( + ':leave', + animation([openStyle, animate(animateTimings, closedStyle)]), + defaultOptions + ), +]); + +export interface ReusableAnimationOptions extends AnimationOptions { + value?: State; +} diff --git a/src/app/part-1/components/bonus/bonus.component.html b/src/app/part-1/components/bonus/bonus.component.html new file mode 100644 index 0000000..6dbc743 --- /dev/null +++ b/src/app/part-1/components/bonus/bonus.component.html @@ -0,0 +1 @@ + diff --git a/src/app/part-1/components/bonus/bonus.component.scss b/src/app/part-1/components/bonus/bonus.component.scss new file mode 100644 index 0000000..b79916c --- /dev/null +++ b/src/app/part-1/components/bonus/bonus.component.scss @@ -0,0 +1,8 @@ +:host { + display: flex; + flex-direction: column; + gap: 8px; + align-items: center; + background: #f3dfdf; + width: 100px; +} diff --git a/src/app/part-1/components/bonus/bonus.component.ts b/src/app/part-1/components/bonus/bonus.component.ts new file mode 100644 index 0000000..046ecc6 --- /dev/null +++ b/src/app/part-1/components/bonus/bonus.component.ts @@ -0,0 +1,28 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { collapse, ReusableAnimationOptions } from '../../animations/collapse'; + +@Component({ + selector: 'app-bonus', + standalone: true, + imports: [CommonModule], + templateUrl: './bonus.component.html', + styleUrl: './bonus.component.scss', + animations: [collapse], + host: { + '[@collapse]': 'animationOptions', + }, +}) +export class BonusComponent implements OnInit { + @Input() + public collapseDuration: number = 300; + + public animationOptions!: ReusableAnimationOptions + + public ngOnInit(): void { + this.animationOptions = { + value: '_', + params: { duration: this.collapseDuration }, + }; + } +} diff --git a/src/app/part-1/reusable-animations.component.html b/src/app/part-1/reusable-animations.component.html new file mode 100644 index 0000000..1511e37 --- /dev/null +++ b/src/app/part-1/reusable-animations.component.html @@ -0,0 +1,22 @@ +
+ +
+ +
+
+
Slow
+
+
+
Fast
+
+
+ +
+ + +
Duration {{duration}} ms
+
+
+
diff --git a/src/app/part-1/reusable-animations.component.scss b/src/app/part-1/reusable-animations.component.scss new file mode 100644 index 0000000..c3e53e2 --- /dev/null +++ b/src/app/part-1/reusable-animations.component.scss @@ -0,0 +1,11 @@ +:host { + .example-block { + background: #b59e9e; + width: 100px; + } + + .block { + width: 100px; + height: 100px; + } +} diff --git a/src/app/part-1/reusable-animations.component.ts b/src/app/part-1/reusable-animations.component.ts new file mode 100644 index 0000000..0589a7c --- /dev/null +++ b/src/app/part-1/reusable-animations.component.ts @@ -0,0 +1,30 @@ +import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { collapse, ReusableAnimationOptions } from './animations/collapse'; +import { BonusComponent } from './components/bonus/bonus.component'; + +@Component({ + selector: 'app-reusable-animations', + standalone: true, + imports: [CommonModule, BonusComponent], + templateUrl: './reusable-animations.component.html', + styleUrl: './reusable-animations.component.scss', + animations: [collapse], + host: { + '[class.flex]': 'true', + '[class.flex-column]': 'true', + }, +}) +export class ReusableAnimationsComponent { + public state: boolean = false; + public slowAnimation: ReusableAnimationOptions = { + value: '_', + params: { duration: 800 }, + }; + public fastAnimation: ReusableAnimationOptions = { + value: '_', + params: { duration: 200 }, + }; + + public durations = [1000, 800, 600, 400, 200, 0] +} diff --git a/src/app/part-2/animations/fade.ts b/src/app/part-2/animations/fade.ts new file mode 100644 index 0000000..b2838e2 --- /dev/null +++ b/src/app/part-2/animations/fade.ts @@ -0,0 +1,25 @@ +import { + animate, + style, + transition, + trigger, +} from '@angular/animations'; + +const leavedStyle = style({ opacity: 0 }); +const enteredStyle = style({ opacity: 1 }); + +const animateTimings = '{{duration}}ms linear'; +const defaultOptions = {params: {duration: 300}}; + +export const fade = trigger('fade', [ + transition( + ':enter', + [leavedStyle, animate(animateTimings, enteredStyle)], + defaultOptions, + ), + transition( + ':leave', + [enteredStyle, animate(animateTimings, leavedStyle)], + defaultOptions, + ), +]); diff --git a/src/app/components/angular-animation/item.component.html b/src/app/part-2/components/item/item.component.html similarity index 100% rename from src/app/components/angular-animation/item.component.html rename to src/app/part-2/components/item/item.component.html diff --git a/src/app/components/angular-animation/item.component.scss b/src/app/part-2/components/item/item.component.scss similarity index 81% rename from src/app/components/angular-animation/item.component.scss rename to src/app/part-2/components/item/item.component.scss index 1051f7d..98a86c9 100644 --- a/src/app/components/angular-animation/item.component.scss +++ b/src/app/part-2/components/item/item.component.scss @@ -3,4 +3,5 @@ width: 200px; padding: 8px 12px; outline: 1px solid #a4a4a4; + border-radius: 4px; } diff --git a/src/app/components/angular-animation/item.component.ts b/src/app/part-2/components/item/item.component.ts similarity index 100% rename from src/app/components/angular-animation/item.component.ts rename to src/app/part-2/components/item/item.component.ts diff --git a/src/app/part-2/disable-animations.component.html b/src/app/part-2/disable-animations.component.html new file mode 100644 index 0000000..b628f30 --- /dev/null +++ b/src/app/part-2/disable-animations.component.html @@ -0,0 +1,14 @@ + + +
+ + Angular animation item + + + + Css animation item + +
diff --git a/src/app/part-2/disable-animations.component.scss b/src/app/part-2/disable-animations.component.scss new file mode 100644 index 0000000..d01f88f --- /dev/null +++ b/src/app/part-2/disable-animations.component.scss @@ -0,0 +1,25 @@ +:host { + .toggle { + width: 100px; + } + + .item { + background: #ffa6a6; + + @media (prefers-reduced-motion: reduce) { + background: #8eff8a; + } + } + + .show { + opacity: 1; + } + + .hide { + opacity: 0; + } + + .css-animation { + transition: opacity var(--animation-duration) linear; + } +} diff --git a/src/app/part-2/disable-animations.component.ts b/src/app/part-2/disable-animations.component.ts new file mode 100644 index 0000000..955b6d8 --- /dev/null +++ b/src/app/part-2/disable-animations.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReusableAnimationOptions } from '../part-1/animations/collapse'; +import { fade } from './animations/fade'; +import { ItemComponent } from './components/item/item.component'; +import { ANIMATION_PARAMS_TOKEN, TAnimationParams } from './tokens/animation-params.token'; + +@Component({ + selector: 'app-disable-animations', + standalone: true, + imports: [CommonModule, ItemComponent], + templateUrl: './disable-animations.component.html', + styleUrl: './disable-animations.component.scss', + animations: [fade], + host: { + '[class.flex]': 'true', + '[class.flex-column]': 'true', + }, +}) +export class DisableAnimationsComponent { + state = false; + + constructor( + @Inject(ANIMATION_PARAMS_TOKEN) + public globalAnimationParams: TAnimationParams + ) {} + + public animationOptions: ReusableAnimationOptions = { + value: '_', + params: { + // current params + ...this.globalAnimationParams + } + } +} diff --git a/src/app/part-2/tokens/animation-params.token.ts b/src/app/part-2/tokens/animation-params.token.ts new file mode 100644 index 0000000..1c0f691 --- /dev/null +++ b/src/app/part-2/tokens/animation-params.token.ts @@ -0,0 +1,24 @@ +import { AnimationOptions } from '@angular/animations'; +import { DOCUMENT } from '@angular/common'; +import { inject, InjectionToken } from '@angular/core'; + +function isReducedMotion(): boolean { + const windowRef = inject(DOCUMENT).defaultView; + const isReduce = windowRef?.matchMedia?.( + '(prefers-reduced-motion: reduce)' + ).matches; + + return isReduce ?? false; +} + +export type TAnimationParams = AnimationOptions['params'] & { + duration: number; +}; + +export const ANIMATION_PARAMS_TOKEN = new InjectionToken( + 'ANIMATION_PARAMS_TOKEN', + { + factory: () => ({ duration: isReducedMotion() ? 0 : 300 }), + providedIn: 'root', + } +); diff --git a/src/index.html b/src/index.html index 93045db..93f69cd 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ - agnular-prefer-reduce-motion + angular-prefer-reduce-motion diff --git a/src/styles.scss b/src/styles.scss index 90d4ee0..6462aa2 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1 +1,20 @@ -/* You can add global styles to this file, and also import other style files */ +:root { + --animation-duration: 300ms; +} + +@media (prefers-reduced-motion: reduce) { + :root { + --animation-duration: 0ms; + } +} + + +.flex { + display: flex; + gap: 8px; + + &-column { + flex-direction: column; + } +} +