├── .circleci └── config.yml ├── .editorconfig ├── .eslintrc.json ├── .firebaserc ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── extensions.json ├── README.md ├── angular.json ├── apps ├── .gitkeep ├── reactive-code-animations-e2e │ ├── .eslintrc.json │ ├── cypress.json │ ├── src │ │ ├── fixtures │ │ │ └── example.json │ │ ├── integration │ │ │ └── app.spec.ts │ │ ├── plugins │ │ │ └── index.js │ │ └── support │ │ │ ├── app.po.ts │ │ │ ├── commands.ts │ │ │ └── index.ts │ ├── tsconfig.e2e.json │ └── tsconfig.json └── reactive-code-animations │ ├── .browserslistrc │ ├── .eslintrc.json │ ├── jest.config.js │ ├── src │ ├── app │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ └── app.module.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── illustration1-code.svg │ │ ├── illustration1-keyboard.svg │ │ ├── illustration1-nx-cloud-layer.svg │ │ ├── illustration1-nx-layer.svg │ │ └── spongebob │ │ │ ├── gary-01.png │ │ │ ├── gary-02.png │ │ │ ├── gary-03.png │ │ │ ├── patrick-01.png │ │ │ ├── patrick-02.png │ │ │ ├── patrick-03.png │ │ │ ├── spongebob-01.png │ │ │ ├── spongebob-02.png │ │ │ └── spongebob-03.png │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.svg │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.scss │ └── test-setup.ts │ ├── tsconfig.app.json │ ├── tsconfig.editor.json │ ├── tsconfig.json │ └── tsconfig.spec.json ├── decorate-angular-cli.js ├── firebase.json ├── jest.config.js ├── jest.preset.js ├── libs ├── examples │ ├── carousel │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.js │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── lib │ │ │ │ ├── carousel │ │ │ │ │ ├── carousel.component.html │ │ │ │ │ ├── carousel.component.scss │ │ │ │ │ └── carousel.component.ts │ │ │ │ └── examples-carousel.module.ts │ │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json │ ├── click-counter │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.js │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── lib │ │ │ │ ├── chart-data.function.ts │ │ │ │ ├── click-counter │ │ │ │ │ ├── click-counter.component.html │ │ │ │ │ ├── click-counter.component.scss │ │ │ │ │ ├── click-counter.component.spec.ts │ │ │ │ │ └── click-counter.component.ts │ │ │ │ ├── examples-click-counter.module.ts │ │ │ │ ├── imperative-click-counter │ │ │ │ │ ├── imperative-click-counter.component.css │ │ │ │ │ ├── imperative-click-counter.component.html │ │ │ │ │ ├── imperative-click-counter.component.spec.ts │ │ │ │ │ └── imperative-click-counter.component.ts │ │ │ │ ├── line-chart │ │ │ │ │ ├── line-chart.component.html │ │ │ │ │ ├── line-chart.component.scss │ │ │ │ │ ├── line-chart.component.spec.ts │ │ │ │ │ └── line-chart.component.ts │ │ │ │ └── windowed-count.function.ts │ │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json │ └── series │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.js │ │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── examples-series.module.ts │ │ │ └── series-example │ │ │ │ ├── series-example.component.html │ │ │ │ ├── series-example.component.scss │ │ │ │ └── series-example.component.ts │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json ├── shared │ ├── animations │ │ ├── .eslintrc.json │ │ ├── README.md │ │ ├── jest.config.js │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── lib │ │ │ │ ├── drop.animation.ts │ │ │ │ ├── fade.animation.ts │ │ │ │ ├── lift.animation.ts │ │ │ │ ├── rotate.animation.ts │ │ │ │ └── slide.animation.ts │ │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json │ └── carousel │ │ ├── .eslintrc.json │ │ ├── jest.config.js │ │ ├── src │ │ ├── index.ts │ │ ├── lib │ │ │ ├── carousel-item │ │ │ │ ├── carousel-item.component.html │ │ │ │ ├── carousel-item.component.scss │ │ │ │ └── carousel-item.component.ts │ │ │ ├── carousel │ │ │ │ ├── auto-advance.operator.ts │ │ │ │ ├── carousel.component.html │ │ │ │ ├── carousel.component.scss │ │ │ │ ├── carousel.component.ts │ │ │ │ └── carousel.utils.ts │ │ │ └── shared-carousel.module.ts │ │ └── test-setup.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.lib.json │ │ └── tsconfig.spec.json └── styles │ ├── _variables.scss │ └── base.scss ├── nx.json ├── package.json ├── tools ├── generators │ └── .gitkeep └── tsconfig.tools.json ├── tsconfig.base.json └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | node: circleci/node@3.0.0 5 | 6 | commands: 7 | npm_install: 8 | description: "Install & Cache Dependencies" 9 | steps: 10 | - run: npm install 11 | - save_cache: 12 | key: rca-{{ checksum "package-lock.json" }} 13 | paths: 14 | - ~/.cache 15 | - node_modules 16 | 17 | restore_npm_cache: 18 | description: "Restore Cached Dependencies" 19 | steps: 20 | - restore_cache: 21 | keys: 22 | - rca-{{ checksum "package-lock.json" }} 23 | - rca- # used if checksum fails 24 | 25 | setup: 26 | description: "Setup Executor" 27 | steps: 28 | - checkout 29 | - attach_workspace: 30 | at: ~/project 31 | 32 | jobs: 33 | initialize: 34 | executor: 35 | name: node/default 36 | steps: 37 | - checkout 38 | - restore_npm_cache 39 | - npm_install 40 | - persist_to_workspace: 41 | root: ~/project 42 | paths: 43 | - node_modules 44 | - dist 45 | 46 | lint: 47 | executor: 48 | name: node/default 49 | steps: 50 | - setup 51 | - run: 52 | name: Lint all affected projects 53 | command: npx nx affected:lint --base=main --head=HEAD 54 | 55 | build: 56 | executor: 57 | name: node/default 58 | steps: 59 | - setup 60 | - run: 61 | name: Build all affected projects 62 | command: npx nx affected:build --base=main --head=HEAD 63 | 64 | test: 65 | executor: 66 | name: node/default 67 | steps: 68 | - setup 69 | - run: 70 | name: Test all affected projects 71 | command: npx nx affected:test --base=main --head=HEAD 72 | 73 | workflows: 74 | verify: 75 | jobs: 76 | - initialize 77 | - lint: 78 | requires: 79 | - initialize 80 | - test: 81 | requires: 82 | - initialize 83 | - build: 84 | requires: 85 | - initialize 86 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nrwl/nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nrwl/nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] } 16 | ] 17 | } 18 | ] 19 | } 20 | }, 21 | { 22 | "files": ["*.ts", "*.tsx"], 23 | "extends": ["plugin:@nrwl/nx/typescript"], 24 | "rules": {} 25 | }, 26 | { 27 | "files": ["*.js", "*.jsx"], 28 | "extends": ["plugin:@nrwl/nx/javascript"], 29 | "rules": {} 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "targets": { 3 | "reactive-code-and-animations": { 4 | "hosting": { 5 | "reactive-code-animations": [ 6 | "reactive-code-and-animations" 7 | ] 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | .firebase 37 | 38 | # System Files 39 | .DS_Store 40 | Thumbs.db 41 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "nrwl.angular-console", 4 | "angular.ng-template", 5 | "ms-vscode.vscode-typescript-tslint-plugin", 6 | "esbenp.prettier-vscode", 7 | "firsttris.vscode-jest-runner" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reactive Code + Animations Examples 2 | Examples from "Best Friends Forever: Reactive Code + Animations" at [ng-conf 2021](https://www.2021.ng-conf.org/). 3 | 4 | This project was generated using [Nx](https://nx.dev). 5 | 6 |

7 | 8 | 🔎 **Nx is a set of Angular CLI power-ups for modern development.** 9 | 10 | ## ☁ Nx Cloud 11 | 12 | ### Computation Memoization in the Cloud 13 | 14 |

15 | 16 | Visit [Nx Cloud](https://nx.app/) to learn more. 17 | 18 | 19 | ## Quick Start 20 | To start the application, run `npm start` and visit http://localhost:4792/ in your browser. 21 | 22 | ## Tooling 23 | 24 | - [Nx](https://nx.dev/) 25 | - [Nx Cloud](https://nx.app/) 26 | - [Angular](https://angular.io/) 27 | - [Jest](https://jestjs.io/en/) 28 | - [Cypress](https://www.cypress.io/) 29 | - [ESLint](https://eslint.org/) 30 | - [CircleCI](https://circleci.com/) 31 | 32 | Thanks for stopping by! 33 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "cli": { 4 | "defaultCollection": "@nrwl/angular", 5 | "analytics": "fe575fcd-3803-43fc-8564-3c5a17d48e1b" 6 | }, 7 | "defaultProject": "reactive-code-animations", 8 | "schematics": { 9 | "@nrwl/angular": { 10 | "application": { 11 | "linter": "eslint" 12 | }, 13 | "library": { 14 | "linter": "eslint" 15 | }, 16 | "storybook-configuration": { 17 | "linter": "eslint" 18 | } 19 | }, 20 | "@nrwl/angular:application": { 21 | "style": "scss", 22 | "linter": "eslint", 23 | "unitTestRunner": "jest", 24 | "e2eTestRunner": "cypress" 25 | }, 26 | "@nrwl/angular:library": { 27 | "style": "scss", 28 | "linter": "eslint", 29 | "unitTestRunner": "jest" 30 | }, 31 | "@nrwl/angular:component": { 32 | "style": "scss" 33 | } 34 | }, 35 | "projects": { 36 | "reactive-code-animations": { 37 | "projectType": "application", 38 | "root": "apps/reactive-code-animations", 39 | "sourceRoot": "apps/reactive-code-animations/src", 40 | "prefix": "rca", 41 | "architect": { 42 | "build": { 43 | "builder": "@angular-devkit/build-angular:browser", 44 | "options": { 45 | "outputPath": "dist/apps/reactive-code-animations", 46 | "index": "apps/reactive-code-animations/src/index.html", 47 | "main": "apps/reactive-code-animations/src/main.ts", 48 | "polyfills": "apps/reactive-code-animations/src/polyfills.ts", 49 | "tsConfig": "apps/reactive-code-animations/tsconfig.app.json", 50 | "aot": true, 51 | "assets": [ 52 | "apps/reactive-code-animations/src/favicon.ico", 53 | "apps/reactive-code-animations/src/assets" 54 | ], 55 | "styles": ["apps/reactive-code-animations/src/styles.scss"], 56 | "stylePreprocessorOptions": { 57 | "includePaths": ["libs/styles"] 58 | }, 59 | "scripts": [] 60 | }, 61 | "configurations": { 62 | "production": { 63 | "fileReplacements": [ 64 | { 65 | "replace": "apps/reactive-code-animations/src/environments/environment.ts", 66 | "with": "apps/reactive-code-animations/src/environments/environment.prod.ts" 67 | } 68 | ], 69 | "optimization": true, 70 | "outputHashing": "all", 71 | "sourceMap": false, 72 | "namedChunks": false, 73 | "extractLicenses": true, 74 | "vendorChunk": false, 75 | "buildOptimizer": true, 76 | "budgets": [ 77 | { 78 | "type": "initial", 79 | "maximumWarning": "2mb", 80 | "maximumError": "5mb" 81 | }, 82 | { 83 | "type": "anyComponentStyle", 84 | "maximumWarning": "6kb", 85 | "maximumError": "10kb" 86 | } 87 | ] 88 | } 89 | } 90 | }, 91 | "serve": { 92 | "builder": "@angular-devkit/build-angular:dev-server", 93 | "options": { 94 | "browserTarget": "reactive-code-animations:build" 95 | }, 96 | "configurations": { 97 | "production": { 98 | "browserTarget": "reactive-code-animations:build:production" 99 | } 100 | } 101 | }, 102 | "extract-i18n": { 103 | "builder": "@angular-devkit/build-angular:extract-i18n", 104 | "options": { 105 | "browserTarget": "reactive-code-animations:build" 106 | } 107 | }, 108 | "lint": { 109 | "builder": "@nrwl/linter:eslint", 110 | "options": { 111 | "lintFilePatterns": [ 112 | "apps/reactive-code-animations/src/**/*.ts", 113 | "apps/reactive-code-animations/src/**/*.html" 114 | ] 115 | } 116 | }, 117 | "test": { 118 | "builder": "@nrwl/jest:jest", 119 | "outputs": ["coverage/apps/reactive-code-animations"], 120 | "options": { 121 | "jestConfig": "apps/reactive-code-animations/jest.config.js", 122 | "passWithNoTests": true 123 | } 124 | }, 125 | "deploy": { 126 | "builder": "@angular/fire:deploy", 127 | "options": {} 128 | } 129 | } 130 | }, 131 | "reactive-code-animations-e2e": { 132 | "root": "apps/reactive-code-animations-e2e", 133 | "sourceRoot": "apps/reactive-code-animations-e2e/src", 134 | "projectType": "application", 135 | "architect": { 136 | "e2e": { 137 | "builder": "@nrwl/cypress:cypress", 138 | "options": { 139 | "cypressConfig": "apps/reactive-code-animations-e2e/cypress.json", 140 | "tsConfig": "apps/reactive-code-animations-e2e/tsconfig.e2e.json", 141 | "devServerTarget": "reactive-code-animations:serve" 142 | }, 143 | "configurations": { 144 | "production": { 145 | "devServerTarget": "reactive-code-animations:serve:production" 146 | } 147 | } 148 | }, 149 | "lint": { 150 | "builder": "@nrwl/linter:eslint", 151 | "options": { 152 | "lintFilePatterns": [ 153 | "apps/reactive-code-animations-e2e/**/*.{js,ts}" 154 | ] 155 | } 156 | } 157 | } 158 | }, 159 | "styles": { 160 | "projectType": "library", 161 | "root": "libs/styles", 162 | "sourceRoot": "libs/styles/src", 163 | "architect": {} 164 | }, 165 | "shared-animations": { 166 | "projectType": "library", 167 | "root": "libs/shared/animations", 168 | "sourceRoot": "libs/shared/animations/src", 169 | "prefix": "reactive-code-animations", 170 | "architect": { 171 | "lint": { 172 | "builder": "@nrwl/linter:eslint", 173 | "options": { 174 | "lintFilePatterns": [ 175 | "libs/shared/animations/src/**/*.ts", 176 | "libs/shared/animations/src/**/*.html" 177 | ] 178 | } 179 | }, 180 | "test": { 181 | "builder": "@nrwl/jest:jest", 182 | "outputs": ["coverage/libs/shared/animations"], 183 | "options": { 184 | "jestConfig": "libs/shared/animations/jest.config.js", 185 | "passWithNoTests": true 186 | } 187 | } 188 | } 189 | }, 190 | "examples-carousel": { 191 | "projectType": "library", 192 | "root": "libs/examples/carousel", 193 | "sourceRoot": "libs/examples/carousel/src", 194 | "prefix": "rca", 195 | "architect": { 196 | "lint": { 197 | "builder": "@nrwl/linter:eslint", 198 | "options": { 199 | "lintFilePatterns": [ 200 | "libs/examples/carousel/src/**/*.ts", 201 | "libs/examples/carousel/src/**/*.html" 202 | ] 203 | } 204 | }, 205 | "test": { 206 | "builder": "@nrwl/jest:jest", 207 | "outputs": ["coverage/libs/examples/carousel"], 208 | "options": { 209 | "jestConfig": "libs/examples/carousel/jest.config.js", 210 | "passWithNoTests": true 211 | } 212 | } 213 | } 214 | }, 215 | "shared-carousel": { 216 | "projectType": "library", 217 | "root": "libs/shared/carousel", 218 | "sourceRoot": "libs/shared/carousel/src", 219 | "prefix": "rca", 220 | "architect": { 221 | "lint": { 222 | "builder": "@nrwl/linter:eslint", 223 | "options": { 224 | "lintFilePatterns": [ 225 | "libs/shared/carousel/src/**/*.ts", 226 | "libs/shared/carousel/src/**/*.html" 227 | ] 228 | } 229 | }, 230 | "test": { 231 | "builder": "@nrwl/jest:jest", 232 | "outputs": ["coverage/libs/shared/carousel"], 233 | "options": { 234 | "jestConfig": "libs/shared/carousel/jest.config.js", 235 | "passWithNoTests": true 236 | } 237 | } 238 | } 239 | }, 240 | "examples-click-counter": { 241 | "projectType": "library", 242 | "root": "libs/examples/click-counter", 243 | "sourceRoot": "libs/examples/click-counter/src", 244 | "prefix": "reactive-code-animations", 245 | "architect": { 246 | "lint": { 247 | "builder": "@nrwl/linter:eslint", 248 | "options": { 249 | "lintFilePatterns": [ 250 | "libs/examples/click-counter/src/**/*.ts", 251 | "libs/examples/click-counter/src/**/*.html" 252 | ] 253 | } 254 | }, 255 | "test": { 256 | "builder": "@nrwl/jest:jest", 257 | "outputs": ["coverage/libs/examples/click-counter"], 258 | "options": { 259 | "jestConfig": "libs/examples/click-counter/jest.config.js", 260 | "passWithNoTests": true 261 | } 262 | } 263 | } 264 | }, 265 | "examples-series": { 266 | "projectType": "library", 267 | "root": "libs/examples/series", 268 | "sourceRoot": "libs/examples/series/src", 269 | "prefix": "reactive-code-animations", 270 | "architect": { 271 | "lint": { 272 | "builder": "@nrwl/linter:eslint", 273 | "options": { 274 | "lintFilePatterns": [ 275 | "libs/examples/series/src/**/*.ts", 276 | "libs/examples/series/src/**/*.html" 277 | ] 278 | } 279 | }, 280 | "test": { 281 | "builder": "@nrwl/jest:jest", 282 | "outputs": ["coverage/libs/examples/series"], 283 | "options": { 284 | "jestConfig": "libs/examples/series/jest.config.js", 285 | "passWithNoTests": true 286 | } 287 | } 288 | } 289 | } 290 | } 291 | } 292 | -------------------------------------------------------------------------------- /apps/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/.gitkeep -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "parserOptions": { 8 | "project": "apps/reactive-code-animations-e2e/tsconfig.*?.json" 9 | }, 10 | "rules": {} 11 | }, 12 | { 13 | "files": ["src/plugins/index.js"], 14 | "rules": { 15 | "@typescript-eslint/no-var-requires": "off", 16 | "no-undef": "off" 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "pluginsFile": "./src/plugins/index", 7 | "supportFile": "./src/support/index.ts", 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/reactive-code-animations-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/reactive-code-animations-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | // import { getGreeting } from '../support/app.po'; 2 | 3 | describe('reactive-code-animations', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | // getGreeting().contains('Welcome to reactive-code-animations!'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | const { preprocessTypescript } = require('@nrwl/cypress/plugins/preprocessor'); 15 | 16 | module.exports = (on, config) => { 17 | // `on` is used to hook into various events Cypress emits 18 | // `config` is the resolved Cypress config 19 | 20 | // Preprocess Typescript file using Nx helper 21 | on('file:preprocessor', preprocessTypescript(config)); 22 | }; 23 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"] 8 | }, 9 | "include": ["src/**/*.ts", "src/**/*.js"] 10 | } 11 | -------------------------------------------------------------------------------- /apps/reactive-code-animations-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.e2e.json" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { 12 | "project": ["apps/reactive-code-animations/tsconfig.*?.json"] 13 | }, 14 | "rules": { 15 | "@angular-eslint/directive-selector": [ 16 | "error", 17 | { 18 | "type": "attribute", 19 | "prefix": "rca", 20 | "style": "camelCase" 21 | } 22 | ], 23 | "@angular-eslint/component-selector": [ 24 | "error", 25 | { 26 | "type": "element", 27 | "prefix": "rca", 28 | "style": "kebab-case" 29 | } 30 | ] 31 | } 32 | }, 33 | { 34 | "files": ["*.html"], 35 | "extends": ["plugin:@nrwl/nx/angular-template"], 36 | "rules": {} 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'reactive-code-animations', 3 | preset: '../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../coverage/apps/reactive-code-animations', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Reactive Code + Animations

3 | 11 |
12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | header { 4 | display: flex; 5 | flex-direction: column; 6 | align-items: flex-end; 7 | margin-bottom: 2rem; 8 | } 9 | 10 | .menu-button { 11 | background-color: $main-text; 12 | } 13 | 14 | nav { 15 | margin: 2rem; 16 | margin-top: 0; 17 | 18 | a { 19 | display: inline-block; 20 | text-underline-offset: 3px; 21 | margin: 0 1rem 1rem 0; 22 | 23 | &.active { 24 | font-weight: bold; 25 | } 26 | } 27 | } 28 | 29 | main { 30 | padding: 2rem; 31 | max-width: 1100px; 32 | margin: 0 auto; 33 | min-height: 30rem; 34 | } 35 | 36 | h1 { 37 | padding: 0 3rem 1rem 0; 38 | margin-left: 2rem; 39 | border-bottom: dotted 4px $secondary; 40 | } 41 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | declarations: [AppComponent], 9 | imports: [RouterTestingModule], 10 | }).compileComponents(); 11 | }); 12 | 13 | it('should create the app', () => { 14 | const fixture = TestBed.createComponent(AppComponent); 15 | const app = fixture.componentInstance; 16 | expect(app).toBeTruthy(); 17 | }); 18 | 19 | it('should render title', () => { 20 | const fixture = TestBed.createComponent(AppComponent); 21 | fixture.detectChanges(); 22 | const compiled = fixture.nativeElement; 23 | expect(compiled.querySelector('h1').textContent).toContain( 24 | 'Reactive Code + Animations' 25 | ); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | interface MenuItem { 4 | name: string; 5 | path: string; 6 | } 7 | @Component({ 8 | selector: 'rca-root', 9 | templateUrl: './app.component.html', 10 | styleUrls: ['./app.component.scss'], 11 | }) 12 | export class AppComponent { 13 | menuItems: MenuItem[] = [ 14 | { name: 'Click Counter', path: '/examples/click-counter' }, 15 | { name: 'Series', path: '/examples/series' }, 16 | { name: 'Carousel', path: '/examples/carousel' }, 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 4 | 5 | import { RouterModule } from '@angular/router'; 6 | 7 | import { AppComponent } from './app.component'; 8 | 9 | const APP_ROUTES = [ 10 | { 11 | path: 'examples/carousel', 12 | loadChildren: () => 13 | import('libs/examples/carousel/src/lib/examples-carousel.module').then( 14 | (m) => m.ExamplesCarouselModule 15 | ), 16 | }, 17 | { 18 | path: 'examples/click-counter', 19 | loadChildren: () => 20 | import( 21 | 'libs/examples/click-counter/src/lib/examples-click-counter.module' 22 | ).then((m) => m.ExamplesClickCounterModule), 23 | }, 24 | { 25 | path: 'examples/series', 26 | loadChildren: () => 27 | import('libs/examples/series/src/lib/examples-series.module').then( 28 | (m) => m.ExamplesSeriesModule 29 | ), 30 | }, 31 | { 32 | path: '**', 33 | redirectTo: '/examples/carousel', 34 | pathMatch: 'full', 35 | }, 36 | ]; 37 | 38 | @NgModule({ 39 | declarations: [AppComponent], 40 | imports: [ 41 | BrowserModule, 42 | BrowserAnimationsModule, 43 | RouterModule.forRoot(APP_ROUTES), 44 | ], 45 | providers: [], 46 | bootstrap: [AppComponent], 47 | }) 48 | export class AppModule {} 49 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/.gitkeep -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/illustration1-code.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/illustration1-keyboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/illustration1-nx-cloud-layer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/illustration1-nx-layer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/gary-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/gary-01.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/gary-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/gary-02.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/gary-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/gary-03.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/patrick-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/patrick-01.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/patrick-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/patrick-02.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/patrick-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/patrick-03.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/spongebob-01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/spongebob-01.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/spongebob-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/spongebob-02.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/assets/spongebob/spongebob-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/apps/reactive-code-animations/src/assets/spongebob/spongebob-03.png -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Reactive Code + Animations 6 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic() 12 | .bootstrapModule(AppModule) 13 | .catch((err) => console.error(err)); 14 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | /*************************************************************************************************** 63 | * APPLICATION IMPORTS 64 | */ 65 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/styles.scss: -------------------------------------------------------------------------------- 1 | @import 'base'; 2 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts", "src/polyfills.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/reactive-code-animations/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /decorate-angular-cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching 3 | * and faster execution of tasks. 4 | * 5 | * It does this by: 6 | * 7 | * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. 8 | * - Symlinking the ng to nx command, so all commands run through the Nx CLI 9 | * - Updating the package.json postinstall script to give you control over this script 10 | * 11 | * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. 12 | * Every command you run should work the same when using the Nx CLI, except faster. 13 | * 14 | * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, 15 | * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. 16 | * The Nx CLI simply does some optimizations before invoking the Angular CLI. 17 | * 18 | * To opt out of this patch: 19 | * - Replace occurrences of nx with ng in your package.json 20 | * - Remove the script from your postinstall script in your package.json 21 | * - Delete and reinstall your node_modules 22 | */ 23 | 24 | const fs = require('fs'); 25 | const os = require('os'); 26 | const cp = require('child_process'); 27 | const isWindows = os.platform() === 'win32'; 28 | let output; 29 | try { 30 | output = require('@nrwl/workspace').output; 31 | } catch (e) { 32 | console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.'); 33 | process.exit(0); 34 | } 35 | 36 | /** 37 | * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still 38 | * invoke the Nx CLI and get the benefits of computation caching. 39 | */ 40 | function symlinkNgCLItoNxCLI() { 41 | try { 42 | const ngPath = './node_modules/.bin/ng'; 43 | const nxPath = './node_modules/.bin/nx'; 44 | if (isWindows) { 45 | /** 46 | * This is the most reliable way to create symlink-like behavior on Windows. 47 | * Such that it works in all shells and works with npx. 48 | */ 49 | ['', '.cmd', '.ps1'].forEach(ext => { 50 | if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); 51 | }); 52 | } else { 53 | // If unix-based, symlink 54 | cp.execSync(`ln -sf ./nx ${ngPath}`); 55 | } 56 | } 57 | catch(e) { 58 | output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message }); 59 | throw e; 60 | } 61 | } 62 | 63 | try { 64 | symlinkNgCLItoNxCLI(); 65 | require('@nrwl/cli/lib/decorate-cli').decorateCli(); 66 | output.log({ title: 'Angular CLI has been decorated to enable computation caching.' }); 67 | } catch(e) { 68 | output.error({ title: 'Decoration of the Angular CLI did not complete successfully' }); 69 | } 70 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": [ 3 | { 4 | "target": "reactive-code-animations", 5 | "public": "dist/apps/reactive-code-animations", 6 | "ignore": [ 7 | "**/.*" 8 | ], 9 | "headers": [ 10 | { 11 | "source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)", 12 | "headers": [ 13 | { 14 | "key": "Cache-Control", 15 | "value": "public,max-age=31536000,immutable" 16 | } 17 | ] 18 | } 19 | ], 20 | "rewrites": [ 21 | { 22 | "source": "**", 23 | "destination": "/index.html" 24 | } 25 | ] 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | projects: [ 3 | '/apps/reactive-code-animations', 4 | '/libs/styles', 5 | '/libs/shared/animations', 6 | '/libs/examples/carousel', 7 | '/libs/shared/carousel', 8 | '/libs/examples/click-counter', 9 | '/libs/examples/series', 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nrwl/jest/preset'); 2 | 3 | module.exports = { ...nxPreset }; 4 | -------------------------------------------------------------------------------- /libs/examples/carousel/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { 12 | "project": ["libs/examples/carousel/tsconfig.*?.json"] 13 | }, 14 | "rules": { 15 | "@angular-eslint/directive-selector": [ 16 | "error", 17 | { 18 | "type": "attribute", 19 | "prefix": "rca", 20 | "style": "camelCase" 21 | } 22 | ], 23 | "@angular-eslint/component-selector": [ 24 | "error", 25 | { 26 | "type": "element", 27 | "prefix": "rca", 28 | "style": "kebab-case" 29 | } 30 | ] 31 | } 32 | }, 33 | { 34 | "files": ["*.html"], 35 | "extends": ["plugin:@nrwl/nx/angular-template"], 36 | "rules": {} 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /libs/examples/carousel/README.md: -------------------------------------------------------------------------------- 1 | # examples-carousel 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test examples-carousel` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/examples/carousel/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'examples-carousel', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../../coverage/libs/examples/carousel', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/examples-carousel.module'; 2 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/lib/carousel/carousel.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 14 | 19 | 20 | 21 | 26 | 31 | 36 | 37 | 38 | 43 | 44 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/lib/carousel/carousel.component.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | :host { 4 | display: flex; 5 | justify-content: center; 6 | width: 100%; 7 | } 8 | 9 | .carousel-item-images { 10 | align-items: flex-end; 11 | display: flex; 12 | flex-direction: column; 13 | } 14 | 15 | img { 16 | border-radius: 50%; 17 | } 18 | 19 | .size-sm { 20 | height: 10rem; 21 | width: 10rem; 22 | } 23 | 24 | .size-md { 25 | height: 15rem; 26 | width: 15rem; 27 | } 28 | 29 | .size-lg { 30 | height: 20rem; 31 | width: 20rem; 32 | } 33 | 34 | .size-xl { 35 | height: 25rem; 36 | width: 25rem; 37 | } 38 | 39 | .m-sm { 40 | margin-top: 4rem; 41 | } 42 | 43 | .m-md { 44 | margin-top: 8rem; 45 | } 46 | 47 | .m-lg { 48 | margin-top: 12rem; 49 | } 50 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/lib/carousel/carousel.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'rca-example-carousel', 5 | templateUrl: './carousel.component.html', 6 | styleUrls: ['./carousel.component.scss'], 7 | }) 8 | export class CarouselComponent {} 9 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/lib/examples-carousel.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule, Route } from '@angular/router'; 4 | import { CarouselComponent } from './carousel/carousel.component'; 5 | import { SharedCarouselModule } from '@rca/shared/carousel'; 6 | 7 | export const examplesCarouselRoutes: Route[] = [ 8 | { path: '', component: CarouselComponent }, 9 | ]; 10 | 11 | @NgModule({ 12 | imports: [ 13 | CommonModule, 14 | RouterModule.forChild(examplesCarouselRoutes), 15 | SharedCarouselModule, 16 | ], 17 | declarations: [CarouselComponent], 18 | }) 19 | export class ExamplesCarouselModule {} 20 | -------------------------------------------------------------------------------- /libs/examples/carousel/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /libs/examples/carousel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/examples/carousel/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [], 10 | "lib": ["dom", "es2018"] 11 | }, 12 | "angularCompilerOptions": { 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "enableResourceInlining": true 16 | }, 17 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 18 | "include": ["**/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/examples/carousel/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/examples/click-counter/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { 12 | "project": ["libs/examples/click-counter/tsconfig.*?.json"] 13 | }, 14 | "rules": { 15 | "@angular-eslint/directive-selector": [ 16 | "error", 17 | { 18 | "type": "attribute", 19 | "prefix": "reactive-code-animations", 20 | "style": "camelCase" 21 | } 22 | ], 23 | "@angular-eslint/component-selector": [ 24 | "error", 25 | { 26 | "type": "element", 27 | "prefix": "reactive-code-animations", 28 | "style": "kebab-case" 29 | } 30 | ] 31 | } 32 | }, 33 | { 34 | "files": ["*.html"], 35 | "extends": ["plugin:@nrwl/nx/angular-template"], 36 | "rules": {} 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /libs/examples/click-counter/README.md: -------------------------------------------------------------------------------- 1 | # examples-click-counter 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test examples-click-counter` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/examples/click-counter/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'examples-click-counter', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../../coverage/libs/examples/click-counter', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/examples-click-counter.module'; 2 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/chart-data.function.ts: -------------------------------------------------------------------------------- 1 | import { combineLatest, Observable } from 'rxjs'; 2 | import { map, scan, startWith, tap } from 'rxjs/operators'; 3 | 4 | export interface CreateChartDataParams { 5 | oneSecondWindow: Observable; 6 | fiveSecondWindow: Observable; 7 | fifteenSecondWindow: Observable; 8 | } 9 | 10 | export interface SeriesDataPoint { 11 | clicksPerWindow: number; 12 | timeElapsed: number; 13 | } 14 | 15 | export interface ChartData { 16 | oneSecond: SeriesDataPoint[]; 17 | fiveSeconds: SeriesDataPoint[]; 18 | fifteenSeconds: SeriesDataPoint[]; 19 | } 20 | 21 | export function createChartData({ 22 | oneSecondWindow, 23 | fiveSecondWindow, 24 | fifteenSecondWindow, 25 | }: CreateChartDataParams): Observable { 26 | let startTime: Date; 27 | const initialData: ChartData = { 28 | oneSecond: [{ clicksPerWindow: 0, timeElapsed: 0 }], 29 | fiveSeconds: [{ clicksPerWindow: 0, timeElapsed: 0 }], 30 | fifteenSeconds: [{ clicksPerWindow: 0, timeElapsed: 0 }], 31 | }; 32 | return combineLatest([ 33 | oneSecondWindow, 34 | fiveSecondWindow, 35 | fifteenSecondWindow, 36 | ]).pipe( 37 | tap(() => { 38 | if (!startTime) { 39 | startTime = new Date(); 40 | } 41 | }), 42 | map(([one, five, fifteen]) => { 43 | const date = new Date(); 44 | const timeElapsed = (date as any) - (startTime as any); 45 | return { 46 | one: { clicksPerWindow: one, timeElapsed }, 47 | five: { clicksPerWindow: five, timeElapsed }, 48 | fifteen: { clicksPerWindow: fifteen, timeElapsed }, 49 | }; 50 | }), 51 | scan( 52 | (acc, curr) => ({ 53 | oneSecond: acc.oneSecond.concat([curr.one]), 54 | fiveSeconds: acc.fiveSeconds.concat([curr.five]), 55 | fifteenSeconds: acc.fifteenSeconds.concat([curr.fifteen]), 56 | }), 57 | initialData 58 | ), 59 | startWith(initialData) 60 | ); 61 | } 62 | 63 | export function convertToFormattedData( 64 | chartData: SeriesDataPoint 65 | ): { x: number; y: number } { 66 | return { 67 | x: chartData.timeElapsed / 1000, 68 | y: chartData.clicksPerWindow, 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/click-counter/click-counter.component.html: -------------------------------------------------------------------------------- 1 | 2 |
Clicks in Last Second: {{ lastSecondCounter$ | async }}
3 |
Clicks in Last 5 Seconds: {{ lastFiveSecondsCounter$ | async }}
4 |
Clicks in Last 15 Seconds: {{ lastFifteenSecondsCounter$ | async }}
5 |
Total Count: {{ clickCounter$ | async }}
6 | 9 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/click-counter/click-counter.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/libs/examples/click-counter/src/lib/click-counter/click-counter.component.scss -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/click-counter/click-counter.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ClickCounterComponent } from './click-counter.component'; 4 | 5 | describe('ClickCounterComponent', () => { 6 | let component: ClickCounterComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ClickCounterComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(ClickCounterComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | xit('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/click-counter/click-counter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; 2 | import { fromEvent, Observable } from 'rxjs'; 3 | import { scan, startWith } from 'rxjs/operators'; 4 | import { ChartData, createChartData } from '../chart-data.function'; 5 | import { windowedCount } from '../windowed-count.function'; 6 | 7 | function createClickObservable(target: ElementRef): Observable { 8 | return fromEvent(target.nativeElement, 'click'); 9 | } 10 | 11 | function count(incoming: Observable): Observable { 12 | return incoming.pipe( 13 | scan((acc) => acc + 1, 0), 14 | startWith(0) 15 | ); 16 | } 17 | 18 | @Component({ 19 | selector: 'reactive-code-animations-click-counter', 20 | templateUrl: './click-counter.component.html', 21 | styleUrls: ['./click-counter.component.scss'], 22 | }) 23 | export class ClickCounterComponent implements OnInit { 24 | @ViewChild('button', { static: true }) button: ElementRef; 25 | private _buttonClicks$: Observable; 26 | clickCounter$: Observable; 27 | lastSecondCounter$: Observable; 28 | lastFiveSecondsCounter$: Observable; 29 | lastFifteenSecondsCounter$: Observable; 30 | chartData$: Observable; 31 | 32 | ngOnInit(): void { 33 | this._buttonClicks$ = createClickObservable(this.button); 34 | this.clickCounter$ = this._buttonClicks$.pipe(count); 35 | this.lastSecondCounter$ = this._buttonClicks$.pipe(windowedCount(1000)); 36 | this.lastFiveSecondsCounter$ = this._buttonClicks$.pipe( 37 | windowedCount(5000) 38 | ); 39 | this.lastFifteenSecondsCounter$ = this._buttonClicks$.pipe( 40 | windowedCount(15000) 41 | ); 42 | this.chartData$ = createChartData({ 43 | oneSecondWindow: this.lastSecondCounter$, 44 | fiveSecondWindow: this.lastFiveSecondsCounter$, 45 | fifteenSecondWindow: this.lastFifteenSecondsCounter$, 46 | }); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/examples-click-counter.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule } from '@angular/router'; 4 | import { ClickCounterComponent } from './click-counter/click-counter.component'; 5 | import { LineChartComponent } from './line-chart/line-chart.component'; 6 | import { ImperativeClickCounterComponent } from './imperative-click-counter/imperative-click-counter.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | RouterModule.forChild([ 12 | { path: '', component: ClickCounterComponent }, 13 | { path: 'imperative', component: ImperativeClickCounterComponent }, 14 | ]), 15 | ], 16 | declarations: [ 17 | ClickCounterComponent, 18 | LineChartComponent, 19 | ImperativeClickCounterComponent, 20 | ], 21 | }) 22 | export class ExamplesClickCounterModule {} 23 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/imperative-click-counter/imperative-click-counter.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/libs/examples/click-counter/src/lib/imperative-click-counter/imperative-click-counter.component.css -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/imperative-click-counter/imperative-click-counter.component.html: -------------------------------------------------------------------------------- 1 | 2 |
Total Count: {{ count }}
3 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/imperative-click-counter/imperative-click-counter.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ImperativeClickCounterComponent } from './imperative-click-counter.component'; 4 | 5 | describe('ImperativeClickCounterComponent', () => { 6 | let component: ImperativeClickCounterComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ImperativeClickCounterComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ImperativeClickCounterComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/imperative-click-counter/imperative-click-counter.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'reactive-code-animations-imperative-click-counter', 5 | templateUrl: './imperative-click-counter.component.html', 6 | styleUrls: ['./imperative-click-counter.component.css'], 7 | }) 8 | export class ImperativeClickCounterComponent { 9 | count = 0; 10 | 11 | addOne() { 12 | this.count++; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/line-chart/line-chart.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/line-chart/line-chart.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/libs/examples/click-counter/src/lib/line-chart/line-chart.component.scss -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/line-chart/line-chart.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LineChartComponent } from './line-chart.component'; 4 | 5 | describe('LineChartComponent', () => { 6 | let component: LineChartComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [LineChartComponent], 12 | }).compileComponents(); 13 | }); 14 | 15 | beforeEach(() => { 16 | fixture = TestBed.createComponent(LineChartComponent); 17 | component = fixture.componentInstance; 18 | fixture.detectChanges(); 19 | }); 20 | 21 | xit('should create', () => { 22 | expect(component).toBeTruthy(); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/line-chart/line-chart.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Component, 3 | ElementRef, 4 | Input, 5 | OnChanges, 6 | OnInit, 7 | SimpleChanges, 8 | ViewChild, 9 | } from '@angular/core'; 10 | import { Chart } from 'chart.js'; 11 | import { ChartData, convertToFormattedData } from '../chart-data.function'; 12 | 13 | @Component({ 14 | selector: 'reactive-code-animations-line-chart', 15 | templateUrl: './line-chart.component.html', 16 | styleUrls: ['./line-chart.component.scss'], 17 | }) 18 | export class LineChartComponent implements OnInit, OnChanges { 19 | @ViewChild('canvas', { static: true }) canvas: ElementRef; 20 | @Input() data: ChartData; 21 | chart; 22 | config; 23 | initialized = false; 24 | 25 | ngOnInit(): void { 26 | this.config = { 27 | data: { 28 | datasets: [ 29 | { 30 | label: 'One Second', 31 | data: this.data.oneSecond.map(convertToFormattedData), 32 | borderColor: 'rgb(255, 99, 132)', 33 | backgroundColor: Chart.helpers 34 | .color('rgb(255, 99, 132)') 35 | .alpha(0.2) 36 | .rgbString(), 37 | showLine: true, 38 | lineWidth: 5, 39 | pointRadius: 0, 40 | pointHoverRadius: 0, 41 | }, 42 | { 43 | label: 'Five Seconds', 44 | data: this.data.fiveSeconds.map(convertToFormattedData), 45 | borderColor: 'rgb(54, 162, 235)', 46 | backgroundColor: Chart.helpers 47 | .color('rgb(54, 162, 235)') 48 | .alpha(0.2) 49 | .rgbString(), 50 | showLine: true, 51 | lineWidth: 5, 52 | pointRadius: 0, 53 | pointHoverRadius: 0, 54 | }, 55 | { 56 | label: 'Fifteen Seconds', 57 | data: this.data.fifteenSeconds.map(convertToFormattedData), 58 | borderColor: 'rgb(255, 159, 64)', 59 | backgroundColor: Chart.helpers 60 | .color('rgb(255, 159, 64)') 61 | .alpha(0.2) 62 | .rgbString(), 63 | showLine: true, 64 | lineWidth: 5, 65 | pointRadius: 0, 66 | pointHoverRadius: 0, 67 | animations: { 68 | tension: { 69 | duration: 1000, 70 | easing: 'linear', 71 | from: 1, 72 | to: 0, 73 | loop: true, 74 | }, 75 | }, 76 | }, 77 | ], 78 | }, 79 | type: 'scatter', 80 | options: { 81 | animations: { 82 | tension: { 83 | duration: 1000, 84 | easing: 'linear', 85 | from: 1, 86 | to: 0, 87 | loop: true, 88 | }, 89 | }, 90 | responsive: false, 91 | title: { 92 | display: true, 93 | text: 'Clicks Per Sliding Window', 94 | }, 95 | // tooltips: { 96 | // mode: 'nearest', 97 | // intersect: false, 98 | // }, 99 | // hover: { 100 | // mode: 'nearest', 101 | // intersect: true, 102 | // }, 103 | scales: { 104 | xAxes: [ 105 | { 106 | display: true, 107 | scaleLabel: { 108 | display: true, 109 | labelString: 'Time Elapsed', 110 | }, 111 | ticks: { 112 | min: 0, 113 | max: 1, 114 | }, 115 | }, 116 | ], 117 | yAxes: [ 118 | { 119 | display: true, 120 | scaleLabel: { 121 | display: true, 122 | labelString: 'Clicks Per Window', 123 | }, 124 | ticks: { 125 | min: 0, 126 | max: 1, 127 | }, 128 | }, 129 | ], 130 | }, 131 | }, 132 | }; 133 | const ctx = (document.getElementById( 134 | 'chart' 135 | ) as HTMLCanvasElement).getContext('2d'); 136 | this.chart = new Chart(ctx, this.config); 137 | this.initialized = true; 138 | } 139 | 140 | ngOnChanges(changes: SimpleChanges) { 141 | if (!this.initialized) { 142 | return; 143 | } 144 | if (changes.data) { 145 | for (const property of [ 146 | 'oneSecond', 147 | 'fiveSeconds', 148 | 'fifteenSeconds', 149 | ] as const) { 150 | const lastValueOfCurrent = 151 | changes.data.currentValue[property][ 152 | changes.data.currentValue[property].length - 1 153 | ]; 154 | const lastValueOfPrevious = 155 | changes.data.previousValue[property][ 156 | changes.data.previousValue[property].length - 1 157 | ]; 158 | if ( 159 | lastValueOfCurrent.clicksPerWindow !== 160 | lastValueOfPrevious.clicksPerWindow 161 | ) { 162 | const index = 163 | property === 'oneSecond' ? 0 : property === 'fiveSeconds' ? 1 : 2; 164 | this.config.data.datasets[index].data.push( 165 | convertToFormattedData(lastValueOfCurrent) 166 | ); 167 | this.config.options.scales.xAxes[0].ticks.max = 168 | lastValueOfCurrent.timeElapsed / 1000; 169 | if ( 170 | property === 'fifteenSeconds' && 171 | lastValueOfCurrent.clicksPerWindow > 172 | this.config.options.scales.yAxes[0].ticks.max 173 | ) { 174 | this.config.options.scales.yAxes[0].ticks.max = 175 | lastValueOfCurrent.clicksPerWindow; 176 | } 177 | this.chart.update(); 178 | } 179 | } 180 | } 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/lib/windowed-count.function.ts: -------------------------------------------------------------------------------- 1 | import { Observable, timer } from 'rxjs'; 2 | import { mergeMap, take, map, scan, startWith } from 'rxjs/operators'; 3 | 4 | export function windowedCount(windowLength: number) { 5 | return function (incoming: Observable): Observable { 6 | return incoming.pipe( 7 | mergeMap(() => 8 | timer(0, windowLength).pipe( 9 | take(2), 10 | map((_, i) => (i === 0 ? ('start' as const) : ('stop' as const))) 11 | ) 12 | ), 13 | scan((acc, signal) => (signal === 'start' ? acc + 1 : acc - 1), 0), 14 | startWith(0) 15 | ); 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /libs/examples/click-counter/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /libs/examples/click-counter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/examples/click-counter/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [], 10 | "lib": ["dom", "es2018"] 11 | }, 12 | "angularCompilerOptions": { 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "enableResourceInlining": true 16 | }, 17 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 18 | "include": ["**/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/examples/click-counter/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/examples/series/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { "project": ["libs/examples/series/tsconfig.*?.json"] }, 12 | "rules": { 13 | "@angular-eslint/directive-selector": [ 14 | "error", 15 | { 16 | "type": "attribute", 17 | "prefix": "rca", 18 | "style": "camelCase" 19 | } 20 | ], 21 | "@angular-eslint/component-selector": [ 22 | "error", 23 | { 24 | "type": "element", 25 | "prefix": "rca", 26 | "style": "kebab-case" 27 | } 28 | ] 29 | } 30 | }, 31 | { 32 | "files": ["*.html"], 33 | "extends": ["plugin:@nrwl/nx/angular-template"], 34 | "rules": {} 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /libs/examples/series/README.md: -------------------------------------------------------------------------------- 1 | # examples-series 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test examples-series` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/examples/series/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'examples-series', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../../coverage/libs/examples/series', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/examples/series/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/examples-series.module'; 2 | -------------------------------------------------------------------------------- /libs/examples/series/src/lib/examples-series.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule, Route } from '@angular/router'; 4 | import { SeriesExampleComponent } from './series-example/series-example.component'; 5 | 6 | export const examplesSeriesRoutes: Route[] = [ 7 | { 8 | path: '', 9 | component: SeriesExampleComponent, 10 | }, 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [CommonModule, RouterModule.forChild(examplesSeriesRoutes)], 15 | declarations: [SeriesExampleComponent], 16 | }) 17 | export class ExamplesSeriesModule {} 18 | -------------------------------------------------------------------------------- /libs/examples/series/src/lib/series-example/series-example.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | {{ item }} 5 |
6 |
7 |
8 | 9 |
10 |
11 | 12 |
13 |
14 |
15 | 18 |
19 | -------------------------------------------------------------------------------- /libs/examples/series/src/lib/series-example/series-example.component.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | .blocks { 4 | display: flex; 5 | flex-wrap: wrap; 6 | } 7 | 8 | .block { 9 | background-color: $primary; 10 | color: white; 11 | font-size: 2.5rem; 12 | display: flex; 13 | align-items: center; 14 | justify-content: center; 15 | height: 10rem; 16 | width: 15rem; 17 | margin: 0 1rem 1rem 0; 18 | } 19 | 20 | .load-more-control { 21 | display: flex; 22 | flex-direction: column; 23 | align-items: center; 24 | justify-content: center; 25 | margin: 2rem; 26 | } 27 | 28 | .loading-animation { 29 | display: flex; 30 | justify-content: center; 31 | margin: 2rem; 32 | min-height: 2rem; 33 | } 34 | 35 | .loading-dot { 36 | animation: pulse 1s infinite alternate ease-out; 37 | background-color: $secondary-dark; 38 | border-radius: 50%; 39 | display: block; 40 | height: 1rem; 41 | width: 1rem; 42 | 43 | &:not(:last-child) { 44 | margin-right: 2rem; 45 | } 46 | } 47 | 48 | @keyframes pulse { 49 | from { 50 | transform: scale(0.5); 51 | } 52 | 53 | to { 54 | transform: scale(1); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /libs/examples/series/src/lib/series-example/series-example.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | query, 3 | stagger, 4 | style, 5 | transition, 6 | trigger, 7 | useAnimation, 8 | } from '@angular/animations'; 9 | import { Component } from '@angular/core'; 10 | import { fadeInAnimation, fadeOutAnimation } from '@rca/shared/animations'; 11 | import { BehaviorSubject, timer } from 'rxjs'; 12 | 13 | @Component({ 14 | selector: 'rca-series-example', 15 | templateUrl: './series-example.component.html', 16 | styleUrls: ['./series-example.component.scss'], 17 | animations: [ 18 | trigger('rotateInStaggeredAnimation', [ 19 | transition('* => *', [ 20 | query( 21 | ':enter', 22 | [ 23 | style({ opacity: 0 }), 24 | stagger(100, [useAnimation(fadeInAnimation)]), 25 | ], 26 | { 27 | optional: true, 28 | } 29 | ), 30 | query(':leave', [stagger(0, [useAnimation(fadeOutAnimation)])], { 31 | optional: true, 32 | }), 33 | ]), 34 | ]), 35 | ], 36 | }) 37 | export class SeriesExampleComponent { 38 | items = ['a', 'b', 'c', 'd']; 39 | items$ = new BehaviorSubject>(this.items); 40 | complete = false; 41 | isLoading = false; 42 | 43 | trackByFn(index, item) { 44 | return index; 45 | } 46 | 47 | loadMore() { 48 | this.isLoading = true; 49 | timer(3000).subscribe((_) => { 50 | this.items$.next([...this.items, 'e', 'f', 'g', 'h', 'j', 'k', 'l', 'm']); 51 | this.isLoading = false; 52 | this.complete = true; 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /libs/examples/series/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /libs/examples/series/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/examples/series/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [], 10 | "lib": ["dom", "es2018"] 11 | }, 12 | "angularCompilerOptions": { 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "enableResourceInlining": true 16 | }, 17 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 18 | "include": ["**/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/examples/series/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/shared/animations/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { 12 | "project": ["libs/shared/animations/tsconfig.*?.json"] 13 | }, 14 | "rules": { 15 | "@angular-eslint/directive-selector": [ 16 | "error", 17 | { 18 | "type": "attribute", 19 | "prefix": "rca", 20 | "style": "camelCase" 21 | } 22 | ], 23 | "@angular-eslint/component-selector": [ 24 | "error", 25 | { 26 | "type": "element", 27 | "prefix": "rca", 28 | "style": "kebab-case" 29 | } 30 | ] 31 | } 32 | }, 33 | { 34 | "files": ["*.html"], 35 | "extends": ["plugin:@nrwl/nx/angular-template"], 36 | "rules": {} 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /libs/shared/animations/README.md: -------------------------------------------------------------------------------- 1 | # shared-animations 2 | 3 | This library was generated with [Nx](https://nx.dev). 4 | 5 | ## Running unit tests 6 | 7 | Run `nx test shared-animations` to execute the unit tests. 8 | -------------------------------------------------------------------------------- /libs/shared/animations/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'shared-animations', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../../coverage/libs/shared/animations', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/shared/animations/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/slide.animation'; 2 | export * from './lib/fade.animation'; 3 | export * from './lib/lift.animation'; 4 | export * from './lib/drop.animation'; 5 | export * from './lib/rotate.animation'; 6 | -------------------------------------------------------------------------------- /libs/shared/animations/src/lib/drop.animation.ts: -------------------------------------------------------------------------------- 1 | import { animation, style, animate } from '@angular/animations'; 2 | 3 | export const dropInAnimation = animation( 4 | [ 5 | style({ opacity: '{{ start }}', transform: 'translate({{ startPos }})' }), 6 | animate( 7 | '{{ time }}', 8 | style({ opacity: '{{ end }}', transform: 'translate({{ endPos }})' }) 9 | ), 10 | ], 11 | { 12 | params: { 13 | time: '500ms ease-out', 14 | start: 0, 15 | end: 1, 16 | startPos: '0, -100px', 17 | endPos: '0, 0', 18 | }, 19 | } 20 | ); 21 | 22 | export const dropOutAnimation = animation( 23 | [ 24 | style({ opacity: '{{ start }}', transform: 'translate({{ startPos }})' }), 25 | animate( 26 | '{{ time }}', 27 | style({ opacity: '{{ end }}', transform: 'translate({{ endPos }})' }) 28 | ), 29 | ], 30 | { 31 | params: { 32 | time: '500ms ease-in', 33 | start: 1, 34 | end: 0, 35 | startPos: '0, 0', 36 | endPos: '0, 100px', 37 | }, 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /libs/shared/animations/src/lib/fade.animation.ts: -------------------------------------------------------------------------------- 1 | import { animation, style, animate } from '@angular/animations'; 2 | 3 | export const fadeInAnimation = animation( 4 | [ 5 | style({ opacity: '{{ start }}', transform: 'scale({{ startScale }})' }), 6 | animate( 7 | '{{ time }}', 8 | style({ opacity: '{{ end }}', transform: 'scale({{ endScale }})' }) 9 | ), 10 | ], 11 | { 12 | params: { 13 | time: '500ms ease-out', 14 | start: 0, 15 | end: 1, 16 | startScale: 0.9, 17 | endScale: 1, 18 | }, 19 | } 20 | ); 21 | 22 | export const fadeOutAnimation = animation( 23 | [ 24 | style({ opacity: '{{ start }}', transform: 'scale({{ startScale }})' }), 25 | animate( 26 | '{{ time }}', 27 | style({ opacity: '{{ end }}', transform: 'scale({{ endScale }})' }) 28 | ), 29 | ], 30 | { 31 | params: { 32 | time: '500ms ease-in', 33 | start: 1, 34 | end: 0, 35 | startScale: 1, 36 | endScale: 0.9, 37 | }, 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /libs/shared/animations/src/lib/lift.animation.ts: -------------------------------------------------------------------------------- 1 | import { animation, style, animate } from '@angular/animations'; 2 | 3 | export const liftInAnimation = animation( 4 | [ 5 | style({ opacity: '{{ start }}', transform: 'translate({{ startPos }})' }), 6 | animate( 7 | '{{ time }}', 8 | style({ opacity: '{{ end }}', transform: 'translate({{ endPos }})' }) 9 | ), 10 | ], 11 | { 12 | params: { 13 | time: '500ms ease-out', 14 | start: 0, 15 | end: 1, 16 | startPos: '0, 100px', 17 | endPos: '0, 0', 18 | }, 19 | } 20 | ); 21 | 22 | export const liftOutAnimation = animation( 23 | [ 24 | style({ opacity: '{{ start }}', transform: 'translate({{ startPos }})' }), 25 | animate( 26 | '{{ time }}', 27 | style({ opacity: '{{ end }}', transform: 'translate({{ endPos }})' }) 28 | ), 29 | ], 30 | { 31 | params: { 32 | time: '500ms ease-in', 33 | start: 1, 34 | end: 0, 35 | startPos: '0, 0', 36 | endPos: '0, -100px', 37 | }, 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /libs/shared/animations/src/lib/rotate.animation.ts: -------------------------------------------------------------------------------- 1 | import { animation, style, animate } from '@angular/animations'; 2 | 3 | export const rotateInAnimation = animation( 4 | [ 5 | style({ 6 | opacity: '{{ start }}', 7 | transform: 'translate({{ startPos }}) rotate({{startRotation}})', 8 | }), 9 | animate( 10 | '{{ time }}', 11 | style({ 12 | opacity: '{{ end }}', 13 | transform: 'translate({{ endPos }}) rotate({{endRotation}})', 14 | }) 15 | ), 16 | ], 17 | { 18 | params: { 19 | time: '500ms ease-out', 20 | start: 0, 21 | end: 1, 22 | startPos: '0, -100px', 23 | endPos: '0, 0', 24 | startRotation: '-15deg', 25 | endRotation: '0', 26 | }, 27 | } 28 | ); 29 | 30 | export const rotateOutAnimation = animation( 31 | [ 32 | style({ 33 | opacity: '{{ start }}', 34 | transform: 'translate({{ startPos }}) rotate({{startRotation}})', 35 | }), 36 | animate( 37 | '{{ time }}', 38 | style({ 39 | opacity: '{{ end }}', 40 | transform: 'translate({{ endPos }}) rotate({{endRotation}})', 41 | }) 42 | ), 43 | ], 44 | { 45 | params: { 46 | time: '500ms ease-in', 47 | start: 1, 48 | end: 0, 49 | startPos: '0, 0', 50 | endPos: '0, 100px', 51 | startRotation: '0', 52 | endRotation: '15deg', 53 | }, 54 | } 55 | ); 56 | -------------------------------------------------------------------------------- /libs/shared/animations/src/lib/slide.animation.ts: -------------------------------------------------------------------------------- 1 | import { animation, style, animate } from '@angular/animations'; 2 | 3 | export const slideInAnimation = animation( 4 | [ 5 | style({ opacity: '{{ start }}', height: '{{ startHeight }}' }), 6 | animate( 7 | '{{ time }}', 8 | style({ opacity: '{{ end }}', height: '{{ endHeight }}' }) 9 | ), 10 | ], 11 | { 12 | params: { 13 | time: '500ms ease-out', 14 | start: 0, 15 | end: 1, 16 | startHeight: 0, 17 | endHeight: '*', 18 | }, 19 | } 20 | ); 21 | 22 | export const slideOutAnimation = animation( 23 | [ 24 | style({ opacity: '{{ start }}', height: '{{ startHeight }}' }), 25 | animate( 26 | '{{ time }}', 27 | style({ opacity: '{{ end }}', height: '{{ endHeight }}' }) 28 | ), 29 | ], 30 | { 31 | params: { 32 | time: '500ms ease-in', 33 | start: 1, 34 | end: 0, 35 | startHeight: '*', 36 | endHeight: 0, 37 | }, 38 | } 39 | ); 40 | -------------------------------------------------------------------------------- /libs/shared/animations/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /libs/shared/animations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/shared/animations/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [], 10 | "lib": ["dom", "es2018"] 11 | }, 12 | "angularCompilerOptions": { 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "enableResourceInlining": true 16 | }, 17 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 18 | "include": ["**/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/shared/animations/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/shared/carousel/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "parserOptions": { "project": ["libs/shared/carousel/tsconfig.*?.json"] }, 12 | "rules": { 13 | "@angular-eslint/directive-selector": [ 14 | "error", 15 | { "type": "attribute", "prefix": "rca", "style": "camelCase" } 16 | ], 17 | "@angular-eslint/component-selector": [ 18 | "error", 19 | { "type": "element", "prefix": "rca", "style": "kebab-case" } 20 | ] 21 | } 22 | }, 23 | { 24 | "files": ["*.html"], 25 | "extends": ["plugin:@nrwl/nx/angular-template"], 26 | "rules": {} 27 | } 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /libs/shared/carousel/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'shared-carousel', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsConfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | astTransformers: { 10 | before: [ 11 | 'jest-preset-angular/build/InlineFilesTransformer', 12 | 'jest-preset-angular/build/StripStylesTransformer', 13 | ], 14 | }, 15 | }, 16 | }, 17 | coverageDirectory: '../../../coverage/libs/shared/carousel', 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js', 20 | 'jest-preset-angular/build/AngularSnapshotSerializer.js', 21 | 'jest-preset-angular/build/HTMLCommentSerializer.js', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/shared-carousel.module'; 2 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel-item/carousel-item.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 | 7 |
8 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel-item/carousel-item.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: flex; 3 | justify-content: center; 4 | max-width: 100%; 5 | position: absolute; 6 | width: 100%; 7 | 8 | @media (max-width: 960px) { 9 | flex-direction: column; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel-item/carousel-item.component.ts: -------------------------------------------------------------------------------- 1 | import { transition, trigger, useAnimation } from '@angular/animations'; 2 | import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; 3 | import { dropInAnimation, fadeOutAnimation } from '@rca/shared/animations'; 4 | import { CarouselState } from '../carousel/carousel.utils'; 5 | 6 | @Component({ 7 | selector: 'rca-carousel-item', 8 | templateUrl: './carousel-item.component.html', 9 | styleUrls: ['./carousel-item.component.scss'], 10 | animations: [ 11 | trigger('fadeToCenter1', [ 12 | transition(':enter', [ 13 | useAnimation(dropInAnimation, { 14 | params: { 15 | startPos: '-50px, -50px', 16 | time: '500ms 600ms ease-out', 17 | }, 18 | }), 19 | ]), 20 | transition(':leave', [useAnimation(fadeOutAnimation)]), 21 | ]), 22 | trigger('fadeToCenter2', [ 23 | transition(':enter', [ 24 | useAnimation(dropInAnimation, { 25 | params: { 26 | startPos: '50px, 50px', 27 | time: '500ms 800ms ease-out', 28 | }, 29 | }), 30 | ]), 31 | transition(':leave', [useAnimation(fadeOutAnimation)]), 32 | ]), 33 | trigger('fadeToCenter3', [ 34 | transition(':enter', [ 35 | useAnimation(dropInAnimation, { 36 | params: { 37 | startPos: '50px, -50px', 38 | time: '500ms 1000ms ease-out', 39 | }, 40 | }), 41 | ]), 42 | transition(':leave', [useAnimation(fadeOutAnimation)]), 43 | ]), 44 | ], 45 | changeDetection: ChangeDetectionStrategy.OnPush, 46 | }) 47 | export class CarouselItemComponent { 48 | @Input() state: CarouselState; 49 | @Input() activeState: CarouselState; 50 | } 51 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel/auto-advance.operator.ts: -------------------------------------------------------------------------------- 1 | import { interval, merge, Observable, of } from 'rxjs'; 2 | import { scan, switchMap } from 'rxjs/operators'; 3 | 4 | export function autoAdvance( 5 | period: number, 6 | nextState: (currentState: T) => T 7 | ) { 8 | return function (incoming: Observable): Observable { 9 | return incoming.pipe( 10 | switchMap((currentState) => 11 | merge( 12 | of(currentState), 13 | interval(period).pipe(scan((acc) => nextState(acc), currentState)) 14 | ) 15 | ) 16 | ); 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel/carousel.component.html: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 |
22 | 23 |
24 |
25 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel/carousel.component.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | :host { 4 | display: block; 5 | min-height: 650px; 6 | width: 100%; 7 | } 8 | .carousel-control-container { 9 | justify-content: center; 10 | display: flex; 11 | margin: 1rem; 12 | } 13 | .carousel-control { 14 | display: flex; 15 | justify-content: space-between; 16 | max-width: 40rem; 17 | margin-bottom: 2rem; 18 | width: 10rem; 19 | 20 | @media (max-width: 500px) { 21 | width: 100%; 22 | } 23 | 24 | button { 25 | background-color: #ccc; 26 | border: 0; 27 | border-radius: 50%; 28 | height: 0.75rem; 29 | position: relative; 30 | transition: all 0.3s; 31 | width: 0.75rem; 32 | 33 | &:hover { 34 | transform: scale(2); 35 | } 36 | 37 | &:disabled { 38 | background-color: $primary; 39 | } 40 | 41 | &:last-child { 42 | margin-right: 0; 43 | } 44 | } 45 | } 46 | 47 | .item-container { 48 | width: 100%; 49 | position: relative; 50 | } 51 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel/carousel.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { 3 | CarouselState, 4 | CAROUSEL_STATES, 5 | createReactiveCarouselMachine, 6 | } from './carousel.utils'; 7 | 8 | let _id = 0; 9 | @Component({ 10 | selector: 'rca-carousel', 11 | templateUrl: './carousel.component.html', 12 | styleUrls: ['./carousel.component.scss'], 13 | }) 14 | export class CarouselComponent { 15 | carouselId = `rca-carousel-${_id++}`; 16 | states = CAROUSEL_STATES; 17 | private _reactiveMachine = createReactiveCarouselMachine(); 18 | activeState$ = this._reactiveMachine.activeState$; 19 | 20 | userClick(state: CarouselState) { 21 | this._reactiveMachine.userInitiatedStateChange(state); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/carousel/carousel.utils.ts: -------------------------------------------------------------------------------- 1 | import { merge, Observable, Observer } from 'rxjs'; 2 | import { map, shareReplay, startWith } from 'rxjs/operators'; 3 | import { autoAdvance } from './auto-advance.operator'; 4 | 5 | export const CAROUSEL_STATES = ['spongebob', 'patrick', 'gary'] as const; 6 | 7 | export type CarouselState = typeof CAROUSEL_STATES[number]; 8 | 9 | export interface ReactiveCarouselMachine { 10 | activeState$: Observable; 11 | userInitiatedStateChange: (carouselState: CarouselState) => void; 12 | } 13 | 14 | export function createReactiveCarouselMachine( 15 | timeToAutoAdvance: number = 5000, 16 | initialState: CarouselState = 'spongebob' 17 | ): ReactiveCarouselMachine { 18 | const observers: Record> = { 19 | spongebob: null, 20 | patrick: null, 21 | gary: null, 22 | }; 23 | const userInitiatedActions = CAROUSEL_STATES.reduce((acc, carouselState) => { 24 | acc[carouselState] = new Observable((observer) => { 25 | observers[carouselState] = observer; 26 | }); 27 | return acc; 28 | }, {} as Record>); 29 | const activeState$ = activeCarouselState({ 30 | userInitiatedActions, 31 | initialState, 32 | timeToAutoAdvance, 33 | }); 34 | const userInitiatedStateChange = (carouselState: CarouselState) => { 35 | observers[carouselState].next(); 36 | }; 37 | return { 38 | userInitiatedStateChange, 39 | activeState$, 40 | }; 41 | } 42 | 43 | interface ActiveCarouselItemParams { 44 | userInitiatedActions: Record>; 45 | initialState: CarouselState; 46 | timeToAutoAdvance: number; 47 | } 48 | 49 | function activeCarouselState({ 50 | userInitiatedActions, 51 | initialState, 52 | timeToAutoAdvance, 53 | }: ActiveCarouselItemParams): Observable { 54 | return merge( 55 | ...Object.entries( 56 | userInitiatedActions 57 | ).map( 58 | ([carouselState, userInitiatedObservable]: [ 59 | CarouselState, 60 | Observable 61 | ]) => userInitiatedObservable.pipe(map(() => carouselState)) 62 | ) 63 | ).pipe( 64 | startWith(initialState), 65 | autoAdvance(timeToAutoAdvance, nextState), 66 | shareReplay(1) 67 | ); 68 | } 69 | 70 | function nextState(state: CarouselState): CarouselState { 71 | if (state === 'spongebob') { 72 | return 'patrick'; 73 | } 74 | if (state === 'patrick') { 75 | return 'gary'; 76 | } 77 | return 'spongebob'; 78 | } 79 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/lib/shared-carousel.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { CarouselComponent } from './carousel/carousel.component'; 4 | import { CarouselItemComponent } from './carousel-item/carousel-item.component'; 5 | 6 | @NgModule({ 7 | imports: [CommonModule], 8 | declarations: [CarouselComponent, CarouselItemComponent], 9 | exports: [CarouselComponent, CarouselItemComponent], 10 | }) 11 | export class SharedCarouselModule {} 12 | -------------------------------------------------------------------------------- /libs/shared/carousel/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular'; 2 | -------------------------------------------------------------------------------- /libs/shared/carousel/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.lib.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /libs/shared/carousel/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "target": "es2015", 6 | "declaration": true, 7 | "declarationMap": true, 8 | "inlineSources": true, 9 | "types": [], 10 | "lib": ["dom", "es2018"] 11 | }, 12 | "angularCompilerOptions": { 13 | "skipTemplateCodegen": true, 14 | "strictMetadataEmit": true, 15 | "enableResourceInlining": true 16 | }, 17 | "exclude": ["src/test-setup.ts", "**/*.spec.ts"], 18 | "include": ["**/*.ts"] 19 | } 20 | -------------------------------------------------------------------------------- /libs/shared/carousel/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/styles/_variables.scss: -------------------------------------------------------------------------------- 1 | $light-gray: #efefef; 2 | $dark-gray: #333; 3 | 4 | $primary: #4285f4; 5 | 6 | $secondary: #ff5722; 7 | $secondary-dark: #ce4d25; 8 | 9 | $main-background: $light-gray; 10 | $main-text: $dark-gray; 11 | -------------------------------------------------------------------------------- /libs/styles/base.scss: -------------------------------------------------------------------------------- 1 | @import 'variables'; 2 | 3 | html, 4 | body { 5 | margin: 0; 6 | } 7 | 8 | html { 9 | background-color: $main-background; 10 | box-sizing: border-box; 11 | font-size: 16px; 12 | font-family: 'Recursive', sans-serif; 13 | font-weight: 300; 14 | color: $main-text; 15 | } 16 | 17 | *, 18 | *:before, 19 | *:after { 20 | box-sizing: inherit; 21 | } 22 | 23 | h1 { 24 | font-size: 300%; 25 | margin-top: 2rem; 26 | margin-bottom: 1rem; 27 | } 28 | 29 | h2 { 30 | font-size: 250%; 31 | margin-top: 2rem; 32 | margin-bottom: 1rem; 33 | } 34 | 35 | h3 { 36 | font-size: 200%; 37 | margin-top: 2rem; 38 | margin-bottom: 1rem; 39 | } 40 | 41 | h4 { 42 | font-size: 150%; 43 | margin-top: 2rem; 44 | margin-bottom: 1rem; 45 | } 46 | 47 | h5 { 48 | font-size: 125%; 49 | margin-top: 2rem; 50 | margin-bottom: 1rem; 51 | } 52 | 53 | h6 { 54 | font-size: 90%; 55 | text-transform: uppercase; 56 | letter-spacing: 0.3rem; 57 | margin-top: 1rem; 58 | margin-bottom: 0.5rem; 59 | } 60 | 61 | p { 62 | line-height: 1.5rem; 63 | margin-bottom: 1.5rem; 64 | } 65 | 66 | a { 67 | color: $main-text; 68 | text-decoration: $main-text underline 1px; 69 | text-underline-offset: 2px; 70 | } 71 | 72 | small { 73 | font-size: 85%; 74 | } 75 | 76 | .button { 77 | border: 0; 78 | border-radius: 4px; 79 | background-color: $secondary; 80 | color: white; 81 | cursor: pointer; 82 | font-family: inherit; 83 | font-size: inherit; 84 | font-weight: 600; 85 | padding: 0.75rem 1.5rem; 86 | transition: background-color 0.2s; 87 | 88 | &:not([disabled]) { 89 | &:hover, 90 | &:active { 91 | background-color: $secondary-dark; 92 | } 93 | } 94 | 95 | &[disabled] { 96 | border-color: #aaa; 97 | background-color: #aaa; 98 | color: #777; 99 | cursor: not-allowed; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "implicitDependencies": { 3 | "angular.json": "*", 4 | "package.json": { "dependencies": "*", "devDependencies": "*" }, 5 | "tsconfig.base.json": "*", 6 | "tslint.json": "*", 7 | ".eslintrc.json": "*", 8 | "nx.json": "*" 9 | }, 10 | "affected": { "defaultBase": "main" }, 11 | "npmScope": "reactive-code-animations", 12 | "tasksRunnerOptions": { 13 | "default": { 14 | "runner": "@nrwl/nx-cloud", 15 | "options": { 16 | "cacheableOperations": ["build", "lint", "test", "e2e"], 17 | "accessToken": "MDQ1NjRmOGYtZjdiYi00NTBlLWE0NTgtMTUxZGU0NzAwZTM2fHJlYWQ=", 18 | "canTrackAnalytics": false, 19 | "showUsageWarnings": true 20 | } 21 | } 22 | }, 23 | "projects": { 24 | "reactive-code-animations": { "tags": [] }, 25 | "reactive-code-animations-e2e": { 26 | "tags": [], 27 | "implicitDependencies": ["reactive-code-animations"] 28 | }, 29 | "styles": { "tags": ["type:ui"] }, 30 | "shared-animations": { "tags": ["type:util"] }, 31 | "examples-carousel": { "tags": ["type:feature"] }, 32 | "shared-carousel": { "tags": ["type:ui"] }, 33 | "examples-click-counter": { "tags": ["type:feature"] }, 34 | "examples-series": { "tags": ["type:feature"] } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactive-code-animations", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "nx", 7 | "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main", 8 | "nx": "nx", 9 | "start": "ng serve --port 4792", 10 | "build": "ng build", 11 | "test": "ng test", 12 | "lint": "nx workspace-lint && ng lint", 13 | "e2e": "ng e2e", 14 | "affected:apps": "nx affected:apps", 15 | "affected:libs": "nx affected:libs", 16 | "affected:build": "nx affected:build", 17 | "affected:e2e": "nx affected:e2e", 18 | "affected:test": "nx affected:test", 19 | "affected:lint": "nx affected:lint", 20 | "affected:dep-graph": "nx affected:dep-graph", 21 | "affected": "nx affected", 22 | "format": "nx format:write", 23 | "format:write": "nx format:write", 24 | "format:check": "nx format:check", 25 | "update": "nx migrate latest", 26 | "workspace-generator": "nx workspace-generator", 27 | "dep-graph": "nx dep-graph", 28 | "help": "nx help" 29 | }, 30 | "private": true, 31 | "dependencies": { 32 | "@angular/animations": "^11.2.0", 33 | "@angular/common": "^11.2.0", 34 | "@angular/compiler": "^11.2.0", 35 | "@angular/core": "^11.2.0", 36 | "@angular/fire": "^6.1.4", 37 | "@angular/forms": "^11.2.0", 38 | "@angular/platform-browser": "^11.2.0", 39 | "@angular/platform-browser-dynamic": "^11.2.0", 40 | "@angular/router": "^11.2.0", 41 | "@nrwl/angular": "11.5.1", 42 | "chart.js": "^2.9.4", 43 | "firebase": "^7.0 || ^8.0", 44 | "rxjs": "~6.6.3", 45 | "tslib": "^2.0.0", 46 | "zone.js": "^0.10.2" 47 | }, 48 | "devDependencies": { 49 | "@angular-devkit/architect": ">= 0.900 < 0.1200", 50 | "@angular-devkit/build-angular": "~0.1102.0", 51 | "@angular-eslint/eslint-plugin": "~1.0.0", 52 | "@angular-eslint/eslint-plugin-template": "~1.0.0", 53 | "@angular-eslint/template-parser": "~1.0.0", 54 | "@angular/cli": "~11.0.0", 55 | "@angular/compiler-cli": "^11.2.0", 56 | "@angular/language-service": "^11.2.0", 57 | "@nrwl/cli": "11.5.1", 58 | "@nrwl/cypress": "11.5.1", 59 | "@nrwl/eslint-plugin-nx": "11.5.1", 60 | "@nrwl/jest": "11.5.1", 61 | "@nrwl/linter": "11.5.1", 62 | "@nrwl/nx-cloud": "^13.0.2", 63 | "@nrwl/tao": "11.5.1", 64 | "@nrwl/workspace": "11.5.1", 65 | "@types/jest": "26.0.8", 66 | "@types/node": "12.12.38", 67 | "@typescript-eslint/eslint-plugin": "4.3.0", 68 | "@typescript-eslint/parser": "4.3.0", 69 | "cypress": "^6.0.1", 70 | "dotenv": "6.2.0", 71 | "eslint": "7.10.0", 72 | "eslint-config-prettier": "8.1.0", 73 | "eslint-plugin-cypress": "^2.10.3", 74 | "firebase-tools": "^8.0.0", 75 | "fuzzy": "^0.1.3", 76 | "inquirer": "^6.2.2", 77 | "inquirer-autocomplete-prompt": "^1.0.1", 78 | "jest": "26.2.2", 79 | "jest-preset-angular": "8.3.2", 80 | "open": "^7.0.3", 81 | "prettier": "2.2.1", 82 | "ts-jest": "26.4.0", 83 | "ts-node": "~9.1.1", 84 | "typescript": "~4.0.3" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /tools/generators/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nixallover/reactive-code-animations/272b5349910436044bba27da0dca3394a043340b/tools/generators/.gitkeep -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "baseUrl": ".", 17 | "paths": { 18 | "@rca/styles": ["libs/styles/src/index.ts"], 19 | "@rca/shared/animations": ["libs/shared/animations/src/index.ts"], 20 | "@rca/examples/carousel": ["libs/examples/carousel/src/index.ts"], 21 | "@rca/shared/carousel": ["libs/shared/carousel/src/index.ts"], 22 | "@reactive-code-animations/examples/click-counter": [ 23 | "libs/examples/click-counter/src/index.ts"], 24 | "@rca/examples/series": [ 25 | "libs/examples/series/src/index.ts" 26 | ] 27 | } 28 | }, 29 | "exclude": ["node_modules", "tmp"] 30 | } 31 | --------------------------------------------------------------------------------