From c87ab6e07cd2a48f96bdee858c36af8949c8896a Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 12 Dec 2023 15:54:00 +0100 Subject: [PATCH] Added simple typing challenge --- README.md | 20 +- package-lock.json | 420 +++++++++++++++++- package.json | 4 + src/app/app.component.html | 338 +------------- src/app/app.component.ts | 3 +- src/app/challenge/challenge.component.html | 16 + src/app/challenge/challenge.component.scss | 0 src/app/challenge/challenge.component.spec.ts | 23 + src/app/challenge/challenge.component.ts | 40 ++ src/app/challenge/sentenceProvider.ts | 62 +++ src/app/letter/letter.component.html | 1 + src/app/letter/letter.component.scss | 0 src/app/letter/letter.component.spec.ts | 23 + src/app/letter/letter.component.ts | 34 ++ src/assets/sentences.txt | 50 +++ src/styles.scss | 4 +- tailwind.config.js | 9 + 17 files changed, 687 insertions(+), 360 deletions(-) create mode 100644 src/app/challenge/challenge.component.html create mode 100644 src/app/challenge/challenge.component.scss create mode 100644 src/app/challenge/challenge.component.spec.ts create mode 100644 src/app/challenge/challenge.component.ts create mode 100644 src/app/challenge/sentenceProvider.ts create mode 100644 src/app/letter/letter.component.html create mode 100644 src/app/letter/letter.component.scss create mode 100644 src/app/letter/letter.component.spec.ts create mode 100644 src/app/letter/letter.component.ts create mode 100644 src/assets/sentences.txt create mode 100644 tailwind.config.js diff --git a/README.md b/README.md index 20f6473..5c1fbd7 100644 --- a/README.md +++ b/README.md @@ -6,22 +6,6 @@ This project was generated with [Angular CLI](https://github.com/angular/angular Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. -## Code scaffolding +# Simple typing challenge -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. +Try to type the shown text as fast as possible. diff --git a/package-lock.json b/package-lock.json index 4dc6575..a8ed586 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,15 +25,31 @@ "@angular/cli": "^17.0.3", "@angular/compiler-cli": "^17.0.0", "@types/jasmine": "~5.1.0", + "autoprefixer": "^10.4.16", + "daisyui": "^4.4.19", "jasmine-core": "~5.1.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", + "postcss": "^8.4.32", + "tailwindcss": "^3.3.6", "typescript": "~5.2.2" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", @@ -185,6 +201,34 @@ } } }, + "node_modules/@angular-devkit/build-angular/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/@angular-devkit/build-webpack": { "version": "0.1700.6", "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1700.6.tgz", @@ -3729,6 +3773,12 @@ "node": ">=4" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -3754,6 +3804,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -4483,6 +4539,15 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001568", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz", @@ -5157,6 +5222,16 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-selector-tokenizer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", @@ -5181,12 +5256,40 @@ "node": ">=4" } }, + "node_modules/culori": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", "dev": true }, + "node_modules/daisyui": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.4.19.tgz", + "integrity": "sha512-IjOLWwnndD4N7Ut5CDxbUsaVtbqXPeVHM92IcgxGFxpuOd3CCKW/PAXZH6JoBTHFRaN57vB9XqEhdWm5yC+bPA==", + "dev": true, + "dependencies": { + "css-selector-tokenizer": "^0.8", + "culori": "^3", + "picocolors": "^1", + "postcss-js": "^4" + }, + "engines": { + "node": ">=16.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/daisyui" + } + }, "node_modules/date-format": { "version": "4.0.14", "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", @@ -5303,6 +5406,12 @@ "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", "dev": true }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -5315,6 +5424,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/dns-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", @@ -6129,6 +6244,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -7968,6 +8089,15 @@ } } }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", @@ -8729,6 +8859,17 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -9109,6 +9250,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", @@ -9625,6 +9775,15 @@ "node": ">=6" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/piscina": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.1.0.tgz", @@ -9739,9 +9898,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", + "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", "dev": true, "funding": [ { @@ -9758,7 +9917,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -9766,6 +9925,86 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/postcss-loader": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", @@ -9847,6 +10086,25 @@ "postcss": "^8.1.0" } }, + "node_modules/postcss-nested": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", + "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.11" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, "node_modules/postcss-selector-parser": { "version": "6.0.13", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", @@ -10027,6 +10285,24 @@ "node": ">= 0.8" } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/read-package-json": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", @@ -11341,6 +11617,57 @@ "node": ">=6" } }, + "node_modules/sucrase": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz", + "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "7.1.6", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11374,6 +11701,55 @@ "node": ">=0.10" } }, + "node_modules/tailwindcss": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.6.tgz", + "integrity": "sha512-AKjF7qbbLvLaPieoKeTjG1+FyNZT6KaJMJPFeQyLfIp7l82ggH1fbHJSsYIvnbTFQOlkh+gBYpyby5GT1LIdLw==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.19.1", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -11572,6 +11948,27 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", @@ -11629,6 +12026,12 @@ "tree-kill": "cli.js" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -12863,6 +13266,15 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index d50c3ff..06481b1 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,16 @@ "@angular/cli": "^17.0.3", "@angular/compiler-cli": "^17.0.0", "@types/jasmine": "~5.1.0", + "autoprefixer": "^10.4.16", + "daisyui": "^4.4.19", "jasmine-core": "~5.1.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", "karma-coverage": "~2.2.0", "karma-jasmine": "~5.1.0", "karma-jasmine-html-reporter": "~2.1.0", + "postcss": "^8.4.32", + "tailwindcss": "^3.3.6", "typescript": "~5.2.2" } } diff --git a/src/app/app.component.html b/src/app/app.component.html index 1b7f2c3..b593fa5 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,336 +1,2 @@ - - - - - - - - - - - -
-
-
- -

Hello, {{ title }}

-

Congratulations! Your app is running. 🎉

-
- -
-
- @for (item of [ - { title: 'Explore the Docs', link: 'https://angular.dev' }, - { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' }, - { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' }, - { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' }, - { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' }, - ]; track item.title) { - - {{ item.title }} - - - - - } -
- -
-
-
- - - - - - - - - - - + + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 25b9212..d84c815 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,11 +1,12 @@ import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterOutlet } from '@angular/router'; +import {ChallengeComponent} from "./challenge/challenge.component"; @Component({ selector: 'app-root', standalone: true, - imports: [CommonModule, RouterOutlet], + imports: [CommonModule, RouterOutlet, ChallengeComponent], templateUrl: './app.component.html', styleUrl: './app.component.scss' }) diff --git a/src/app/challenge/challenge.component.html b/src/app/challenge/challenge.component.html new file mode 100644 index 0000000..d296a82 --- /dev/null +++ b/src/app/challenge/challenge.component.html @@ -0,0 +1,16 @@ +
+ +
+

Typing Challenge

+
+ +
+ +
+
diff --git a/src/app/challenge/challenge.component.scss b/src/app/challenge/challenge.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/challenge/challenge.component.spec.ts b/src/app/challenge/challenge.component.spec.ts new file mode 100644 index 0000000..5ef7f47 --- /dev/null +++ b/src/app/challenge/challenge.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ChallengeComponent } from './challenge.component'; + +describe('ChallengeComponent', () => { + let component: ChallengeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ChallengeComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ChallengeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/challenge/challenge.component.ts b/src/app/challenge/challenge.component.ts new file mode 100644 index 0000000..9bddd3f --- /dev/null +++ b/src/app/challenge/challenge.component.ts @@ -0,0 +1,40 @@ +import {Component} from '@angular/core'; +import {LetterComponent} from "../letter/letter.component"; +import {NgForOf} from "@angular/common"; +import sentences from "./sentenceProvider"; + +@Component({ + selector: 'app-challenge', + standalone: true, + imports: [ + LetterComponent, + NgForOf + ], + templateUrl: './challenge.component.html', + styleUrl: './challenge.component.scss' +}) +export class ChallengeComponent { + text = this.getSentence(); + enteredText = ""; + + getSentence() { + const sentenceArray = sentences.split('\n'); + return sentenceArray[Math.floor(Math.random() * sentenceArray.length)]; + } + + getText() { + this.text = this.text.replace(/ /g, '\u00A0'); + return this.text.split('') + } + + onChangeInput($event: Event) { + const target = $event.target as HTMLInputElement; + this.enteredText = target.value; + console.log() + } + + nextSentence() { + // Shitty way to do this, but no knowledge of a better way at the moment + window.location.reload(); + } +} diff --git a/src/app/challenge/sentenceProvider.ts b/src/app/challenge/sentenceProvider.ts new file mode 100644 index 0000000..6ebe8ff --- /dev/null +++ b/src/app/challenge/sentenceProvider.ts @@ -0,0 +1,62 @@ +let sentences = `It isn't true that my mattress is made of cotton candy. +Had he known what was going to happen, he would have never stepped into the shower. +You're good at English when you know the difference between a man eating chicken and a man-eating chicken. +The tart lemonade quenched her thirst, but not her longing. +People keep telling me "orange" but I still prefer "pink". +Her hair was windswept as she rode in the black convertible. +The water flowing down the river didn’t look that powerful from the car +Mom didn’t understand why no one else wanted a hot tub full of jello. +Everybody should read Chaucer to improve their everyday vocabulary. +It must be five o'clock somewhere. +He was 100% into fasting with her until he understood that meant he couldn't eat. +The sunblock was handed to the girl before practice, but the burned skin was proof she did not apply it. +The estate agent quickly marked out his territory on the dance floor. +If you like tuna and tomato sauce, try combining the two, it’s really not as bad as it sounds. +He said he was not there yesterday; however, many people saw him there. +Normal activities took extraordinary amounts of concentration at the high altitude. +The snow-covered path was no help in finding his way out of the back-country. +Instead of a bachelorette party +She opened up her third bottle of wine of the night. +I’m a living furnace. +The spa attendant applied the deep cleaning mask to the gentleman’s back. +She couldn't understand why nobody else could see that the sky is full of cotton candy. +Beach-combing replaced wine tasting as his new obsession. +The teenage boy was accused of breaking his arm simply to get out of the test. +Thirty years later, she still thought it was okay to put the toilet paper roll under rather than over. +As the asteroid hurtled toward earth, Becky was upset her dentist appointment had been canceled. +The old apple revels in its authority. +Too many prisons have become early coffins. +Despite what your teacher may have told you, there is a wrong way to wield a lasso. +Situps are a terrible way to end your day. +The lyrics of the song sounded like fingernails on a chalkboard. +Don't put peanut butter on the dog's nose. +Today we gathered moss for my uncle's wedding. +She wrote him a long letter, but he didn't read it. +He didn’t want to go to the dentist, yet he went anyway. +It was obvious she was hot, sweaty, and tired. +Smoky the Bear secretly started the fires. +If you don't like toenails, you probably shouldn't look at your feet. +His mind was blown that there was nothing in space except space itself. +The urgent care center was flooded with patients after the news of a new deadly virus was made public. +The fact that there's a stairway to heaven and a highway to hell explains life well. +Watching the geriatric men’s softball team brought back memories of 3 yr olds playing t-ball. +Chocolate covered crickets were his favorite snack. +Henry couldn't decide if he was an auto mechanic or a priest. +Various sea birds are elegant, but nothing is as elegant as a gliding pelican. +The thick foliage and intertwined vines made the hike nearly impossible. +The bird had a belief that it was really a groundhog. +She had some amazing news to share but nobody to share it with. +The light in his life was actually a fire burning all around him. +Two seats were vacant. +The toilet paper floated in the air, but she was thankful it wasn't a spider. +I flushed the spider down the toilet. +The hummingbird's wings blurred while it eagerly sipped the sugar water from the feeder. +Getting up at dawn is for the birds. +Sucking on the ice cube made the toothache less painful. +Shitting rainbows is a disgusting way to describe something amazing. +The fish dreamed of escaping the fishbowl and into the toilet where he saw his friend go. +The fish listened intently to what the frogs had to say. +Buying deodorant is a rite of passage for young teens. +A floating human heart is a creepy thing to see in the middle of the ocean.`; + +export default sentences; diff --git a/src/app/letter/letter.component.html b/src/app/letter/letter.component.html new file mode 100644 index 0000000..ecc6a51 --- /dev/null +++ b/src/app/letter/letter.component.html @@ -0,0 +1 @@ +

{{letter}}

diff --git a/src/app/letter/letter.component.scss b/src/app/letter/letter.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/letter/letter.component.spec.ts b/src/app/letter/letter.component.spec.ts new file mode 100644 index 0000000..d0953e5 --- /dev/null +++ b/src/app/letter/letter.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LetterComponent } from './letter.component'; + +describe('LetterComponent', () => { + let component: LetterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [LetterComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LetterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/letter/letter.component.ts b/src/app/letter/letter.component.ts new file mode 100644 index 0000000..dea3f1e --- /dev/null +++ b/src/app/letter/letter.component.ts @@ -0,0 +1,34 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'app-letter', + standalone: true, + imports: [], + templateUrl: './letter.component.html', + styleUrl: './letter.component.scss' +}) +export class LetterComponent { + @Input() letter: string = " "; + @Input() entered: boolean = false; + @Input() correct: boolean = false; + @Input() isNext: boolean = false; + + getColor() { + if(!this.entered) { + return ''; + } + + if (this.correct) { + return 'text-green-500'; + } else { + return 'text-red-500'; + } + } + + getSize() { + if(this.isNext) { + return 'font-bold'; + } + return ""; + } +} diff --git a/src/assets/sentences.txt b/src/assets/sentences.txt new file mode 100644 index 0000000..3c2bb3d --- /dev/null +++ b/src/assets/sentences.txt @@ -0,0 +1,50 @@ +It isn't true that my mattress is made of cotton candy. +Had he known what was going to happen, he would have never stepped into the shower. +You're good at English when you know the difference between a man eating chicken and a man-eating chicken. +The tart lemonade quenched her thirst, but not her longing. +People keep telling me "orange" but I still prefer "pink". +Her hair was windswept as she rode in the black convertible. +The water flowing down the river didn’t look that powerful from the car +Mom didn’t understand why no one else wanted a hot tub full of jello. +Everybody should read Chaucer to improve their everyday vocabulary. +It must be five o'clock somewhere. +He was 100% into fasting with her until he understood that meant he couldn't eat. +The sunblock was handed to the girl before practice, but the burned skin was proof she did not apply it. +The estate agent quickly marked out his territory on the dance floor. +If you like tuna and tomato sauce, try combining the two, it’s really not as bad as it sounds. +He said he was not there yesterday; however, many people saw him there. +Normal activities took extraordinary amounts of concentration at the high altitude. +The snow-covered path was no help in finding his way out of the back-country. +Instead of a bachelorette party +She opened up her third bottle of wine of the night. +I’m a living furnace. +The spa attendant applied the deep cleaning mask to the gentleman’s back. +She couldn't understand why nobody else could see that the sky is full of cotton candy. +Beach-combing replaced wine tasting as his new obsession. +The teenage boy was accused of breaking his arm simply to get out of the test. +Thirty years later, she still thought it was okay to put the toilet paper roll under rather than over. +As the asteroid hurtled toward earth, Becky was upset her dentist appointment had been canceled. +The old apple revels in its authority. +Too many prisons have become early coffins. +Despite what your teacher may have told you, there is a wrong way to wield a lasso. +Situps are a terrible way to end your day. +The lyrics of the song sounded like fingernails on a chalkboard. +Don't put peanut butter on the dog's nose. +Today we gathered moss for my uncle's wedding. +She wrote him a long letter, but he didn't read it. +He didn’t want to go to the dentist, yet he went anyway. +It was obvious she was hot, sweaty, and tired. +Smoky the Bear secretly started the fires. +If you don't like toenails, you probably shouldn't look at your feet. +His mind was blown that there was nothing in space except space itself. +The urgent care center was flooded with patients after the news of a new deadly virus was made public. +The fact that there's a stairway to heaven and a highway to hell explains life well. +Watching the geriatric men’s softball team brought back memories of 3 yr olds playing t-ball. +Chocolate covered crickets were his favorite snack. +Henry couldn't decide if he was an auto mechanic or a priest. +Various sea birds are elegant, but nothing is as elegant as a gliding pelican. +The thick foliage and intertwined vines made the hike nearly impossible. +The bird had a belief that it was really a groundhog. +She had some amazing news to share but nobody to share it with. +The light in his life was actually a fire burning all around him. +Two seats were vacant. diff --git a/src/styles.scss b/src/styles.scss index 90d4ee0..b5c61c9 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1 +1,3 @@ -/* You can add global styles to this file, and also import other style files */ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..ddeb52a --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{html,js,ts}"], + theme: { + extend: {}, + }, + plugins: [require("daisyui")], +} +