feat: angular component

This commit is contained in:
Brian Pooe 2023-10-11 21:29:55 +02:00
parent 71571f8e3c
commit 423cd21da6
37 changed files with 6712 additions and 57 deletions

2
.gitignore vendored
View file

@ -37,3 +37,5 @@ testem.log
# System Files # System Files
.DS_Store .DS_Store
Thumbs.db Thumbs.db
.angular

View file

@ -1,3 +1,4 @@
# Add files here to ignore them from prettier formatting # Add files here to ignore them from prettier formatting
/dist /dist
/coverage /coverage
.angular

View file

@ -1,57 +1,55 @@
# Payspace # Payspace
<a alt="Nx logo" href="https://nx.dev" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-logo.png" width="45"></a> Applications was built using nx monorepo -> https://nx.dev/
**This workspace has been generated by [Nx, a Smart, fast and extensible build system.](https://nx.dev)**
## Generate code
If you happen to use Nx plugins, you can leverage code generators that might come with it.
Run `nx list` to get a list of available plugins and whether they have generators. Then run `nx list <plugin-name>` to see what generators are available.
Learn more about [Nx generators on the docs](https://nx.dev/plugin-features/use-code-generators).
## Running tasks ## Running tasks
To execute tasks with Nx use the following syntax: To run Part 1: HTML/CSS use the following syntax:
``` `
nx <target> <project> <...options> npm run part1
``` `
You can also run multiple targets: To run Part 2: JavaScript use the following syntax:
``` `
nx run-many -t <target1> <target2> npm run part2
``` `
..or add `-p` to filter specific projects To run Part 3: Angular Component use the following syntax:
``` `
nx run-many -t <target1> <target2> -p <proj1> <proj2> npm run part3
``` `
To run Part 4: Problem-Solving use the following syntax:
`
npm run part4
`
To run Part 5: Code Review use the following syntax:
`
npm run part5
`
Targets can be defined in the `package.json` or `projects.json`. Learn more [in the docs](https://nx.dev/core-features/run-tasks). Targets can be defined in the `package.json` or `projects.json`. Learn more [in the docs](https://nx.dev/core-features/run-tasks).
## Want better Editor Integration?
Have a look at the [Nx Console extensions](https://nx.dev/nx-console). It provides autocomplete support, a UI for exploring and running tasks & generators, and more! Available for VSCode, IntelliJ and comes with a LSP for Vim users.
## Ready to deploy? ## Ready to deploy?
Just run `nx build demoapp` to build the application. The build artifacts will be stored in the `dist/` directory, ready to be deployed. `npm run part1:build`
## Set up CI! `npm run part2:build`
Nx comes with local caching already built-in (check your `nx.json`). On CI you might want to go a step further. `npm run part3:build`
- [Set up remote caching](https://nx.dev/core-features/share-your-cache) `npm run part4:build`
- [Set up task distribution across multiple machines](https://nx.dev/core-features/distribute-task-execution)
- [Learn more how to setup CI](https://nx.dev/recipes/ci)
## Connect with us! `npm run part5:build`
- [Join the community](https://nx.dev/community) The build artifacts will be stored in the `dist/` directory, ready to be deployed.
- [Subscribe to the Nx Youtube Channel](https://www.youtube.com/@nxdevtools)
- [Follow us on Twitter](https://twitter.com/nxdevtools) ## Author
Brian Pooe

13
nx.json
View file

@ -62,6 +62,19 @@
"linter": "eslint", "linter": "eslint",
"unitTestRunner": "jest", "unitTestRunner": "jest",
"e2eTestRunner": "none" "e2eTestRunner": "none"
},
"@nx/angular:application": {
"style": "scss",
"linter": "eslint",
"unitTestRunner": "jest",
"e2eTestRunner": "none"
},
"@nx/angular:library": {
"linter": "eslint",
"unitTestRunner": "jest"
},
"@nx/angular:component": {
"style": "scss"
} }
} }
} }

6081
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -5,12 +5,28 @@
"scripts": { "scripts": {
"part1": "nx run part-1-html-css:serve", "part1": "nx run part-1-html-css:serve",
"part2": "nx run part-2-javascript:serve", "part2": "nx run part-2-javascript:serve",
"part3": "nx run part-3-angular:serve",
"part4": "nx run part-4-problem-solving:serve", "part4": "nx run part-4-problem-solving:serve",
"part5": "nx run part-5-code-review:serve" "part5": "nx run part-5-code-review:serve",
"part1:build": "nx build part-1-html-css",
"part2:build": "nx build part-2-javascript",
"part3:build": "nx build part-3-angular",
"part4:build": "nx build part-4-problem-solving",
"part5:build": "nx build part-5-code-review"
}, },
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~16.2.0",
"@angular-devkit/core": "~16.2.0",
"@angular-devkit/schematics": "~16.2.0",
"@angular-eslint/eslint-plugin": "~16.0.0",
"@angular-eslint/eslint-plugin-template": "~16.0.0",
"@angular-eslint/template-parser": "~16.0.0",
"@angular/cli": "~16.2.0",
"@angular/compiler-cli": "~16.2.0",
"@angular/language-service": "~16.2.0",
"@nrwl/web": "^16.10.0", "@nrwl/web": "^16.10.0",
"@nx/angular": "^16.10.0",
"@nx/eslint-plugin": "16.10.0", "@nx/eslint-plugin": "16.10.0",
"@nx/jest": "16.10.0", "@nx/jest": "16.10.0",
"@nx/js": "16.10.0", "@nx/js": "16.10.0",
@ -18,6 +34,7 @@
"@nx/web": "16.10.0", "@nx/web": "16.10.0",
"@nx/webpack": "^16.10.0", "@nx/webpack": "^16.10.0",
"@nx/workspace": "16.10.0", "@nx/workspace": "16.10.0",
"@schematics/angular": "~16.2.0",
"@swc/cli": "~0.1.62", "@swc/cli": "~0.1.62",
"@swc/core": "~1.3.85", "@swc/core": "~1.3.85",
"@swc/jest": "0.2.20", "@swc/jest": "0.2.20",
@ -25,20 +42,35 @@
"@types/node": "18.7.1", "@types/node": "18.7.1",
"@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/eslint-plugin": "^5.60.1",
"@typescript-eslint/parser": "^5.60.1", "@typescript-eslint/parser": "^5.60.1",
"autoprefixer": "^10.4.0",
"eslint": "~8.46.0", "eslint": "~8.46.0",
"eslint-config-prettier": "8.1.0", "eslint-config-prettier": "8.1.0",
"jest": "^29.4.1", "jest": "^29.4.1",
"jest-environment-jsdom": "^29.4.1", "jest-environment-jsdom": "^29.4.1",
"jest-preset-angular": "~13.1.0",
"jsonc-eslint-parser": "^2.1.0",
"nx": "16.10.0", "nx": "16.10.0",
"postcss": "^8.4.5",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.5.5", "prettier-plugin-tailwindcss": "^0.5.5",
"swc-loader": "0.1.15", "swc-loader": "0.1.15",
"tailwindcss": "^3.0.2",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"ts-node": "10.9.1", "ts-node": "10.9.1",
"typescript": "~5.1.3" "typescript": "~5.1.3"
}, },
"dependencies": { "dependencies": {
"@angular/animations": "~16.2.0",
"@angular/common": "~16.2.0",
"@angular/compiler": "~16.2.0",
"@angular/core": "~16.2.0",
"@angular/forms": "~16.2.0",
"@angular/platform-browser": "~16.2.0",
"@angular/platform-browser-dynamic": "~16.2.0",
"@angular/router": "~16.2.0",
"@swc/helpers": "~0.5.2", "@swc/helpers": "~0.5.2",
"tslib": "^2.3.0" "rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.13.0"
} }
} }

View file

@ -5,29 +5,29 @@ import { filterBooks } from "./book.util";
export class AppElement extends HTMLElement { export class AppElement extends HTMLElement {
connectedCallback() { connectedCallback() {
this.innerHTML = ` this.innerHTML = `
<div class="container mx-auto sm:px-6 lg:px-8"> <div class="container pt-4 mx-auto sm:px-6 lg:px-8">
<!-- Search --> <!-- Search -->
<label for="search" class="block text-sm font-medium leading-6 text-gray-900">Quick search</label> <label for="search" class="block text-sm font-medium leading-6 text-gray-900">Quick search</label>
<div class="relative mt-2 flex items-center"> <div class="relative mt-2 flex items-center">
<input type="text" name="search" id="search" class="block w-full rounded-md border-0 py-1.5 pr-14 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" data-search> <input type="text" name="search" id="search" class="block w-full rounded-md border-0 py-1.5 pr-14 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" data-search>
</div> </div>
<div>
<div> <h2 class="text-sm font-medium text-gray-500 py-6">Books</h2>
<h2 class="text-sm font-medium text-gray-500 py-6">Books</h2> <ul role="list" class="mt-3 grid grid-cols-1 gap-5 sm:grid-cols-2 sm:gap-6 lg:grid-cols-4" data-book-cards-container></ul>
<ul role="list" class="mt-3 grid grid-cols-1 gap-5 sm:grid-cols-2 sm:gap-6 lg:grid-cols-4" data-book-cards-container></ul>
<template data-book-card-template> <template data-book-card-template>
<li class="col-span-1 flex rounded-md shadow-sm"> <li class="col-span-1 flex rounded-md shadow-sm">
<div class="flex w-16 flex-shrink-0 items-center justify-center bg-[#9BD83A] rounded-l-md text-sm font-medium text-gray-900 hover:text-gray-600" data-initials></div> <div class="flex w-16 flex-shrink-0 items-center justify-center bg-[#9BD83A] rounded-l-md text-sm font-medium text-gray-900 hover:text-gray-600" data-initials></div>
<div class="flex flex-1 items-center justify-between truncate rounded-r-md border-b border-r border-t border-gray-200 bg-white hover:text-gray-600"> <div class="flex flex-1 items-center justify-between truncate rounded-r-md border-b border-r border-t border-gray-200 bg-white hover:text-gray-600">
<div class="flex-1 truncate px-4 py-2 text-sm"> <div class="flex-1 truncate px-4 py-2 text-sm">
<a href="#" class="font-medium text-gray-900 hover:text-gray-600" data-title></a><br> <a href="#" class="font-medium text-gray-900 hover:text-gray-600" data-title></a><br>
<a href="#" class="font-medium text-gray-900 hover:text-gray-600" data-author></a> <a href="#" class="font-medium text-gray-900 hover:text-gray-600" data-author></a>
<p class="text-gray-500" data-year></p> <p class="text-gray-500" data-year></p>
</div>
</div> </div>
</div> </li>
</li> </template>
</template>
</div> </div>
</div> </div>

View file

@ -0,0 +1,46 @@
{
"extends": [
"../.eslintrc.json"
],
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"extends": [
"plugin:@nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "payspace",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "payspace",
"style": "kebab-case"
}
]
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@nx/angular-template"
],
"rules": {}
}
]
}

View file

@ -0,0 +1,22 @@
/* eslint-disable */
export default {
displayName: 'part-3-angular',
preset: '../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
coverageDirectory: '../coverage/part-3-angular',
transform: {
'^.+\\.(ts|mjs|js|html)$': [
'jest-preset-angular',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
stringifyContentPathRegex: '\\.(html|svg)$',
},
],
},
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
'jest-preset-angular/build/serializers/html-comment',
]
};

104
part-3-angular/project.json Normal file
View file

@ -0,0 +1,104 @@
{
"name": "part-3-angular",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"prefix": "payspace",
"sourceRoot": "part-3-angular/src",
"tags": [],
"targets": {
"build": {
"executor": "@angular-devkit/build-angular:browser",
"outputs": [
"{options.outputPath}"
],
"options": {
"outputPath": "dist/part-3-angular",
"index": "part-3-angular/src/index.html",
"main": "part-3-angular/src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "part-3-angular/tsconfig.app.json",
"assets": [
"part-3-angular/src/assets"
],
"styles": [
"part-3-angular/src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"buildOptimizer": false,
"optimization": false,
"vendorChunk": true,
"extractLicenses": false,
"sourceMap": true,
"namedChunks": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"executor": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"browserTarget": "part-3-angular:build:production"
},
"development": {
"browserTarget": "part-3-angular:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"executor": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "part-3-angular:build"
}
},
"lint": {
"executor": "@nx/linter:eslint",
"outputs": [
"{options.outputFile}"
],
"options": {
"lintFilePatterns": [
"part-3-angular/**/*.ts",
"part-3-angular/**/*.html"
]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": [
"{workspaceRoot}/coverage/{projectRoot}"
],
"options": {
"jestConfig": "part-3-angular/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
}
}
}

View file

@ -0,0 +1,7 @@
<div class="container pt-4 mx-auto sm:px-6 lg:px-8">
<payspace-search (searchText)="searchText($event)"></payspace-search>
<h2 class="text-sm font-medium text-gray-500 py-6">Books</h2>
<ul role="list" class="mt-3 grid grid-cols-1 gap-5 sm:grid-cols-2 sm:gap-6 lg:grid-cols-4">
<payspace-book *ngFor="let book of books$ | async" [book]="book" />
</ul>
</div>

View file

@ -0,0 +1,24 @@
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { NxWelcomeComponent } from './nx-welcome.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent, NxWelcomeComponent],
}).compileComponents();
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Welcome part-3-angular');
});
it(`should have as title 'part-3-angular'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('part-3-angular');
});
});

View file

@ -0,0 +1,29 @@
import { Component, OnInit } from "@angular/core";
import { SearchComponent } from "./ui/search/search.component";
import { BookComponent } from "./ui/book/book.component";
import { ApiService } from "./services/api.service";
import { Observable } from "rxjs";
import { Book } from "./models";
import { CommonModule } from "@angular/common";
@Component({
standalone: true,
imports: [SearchComponent, BookComponent, CommonModule],
selector: "payspace-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {
books$: Observable<Book[] | null> = this.apiService.books$;
constructor(private readonly apiService: ApiService) {
}
ngOnInit(): void {
this.apiService.loadBooks();
}
searchText(searchTerm: string = ""): void {
this.apiService.loadBooks(searchTerm, false);
}
}

View file

@ -0,0 +1,6 @@
import { ApplicationConfig } from "@angular/core";
import { provideHttpClient } from "@angular/common/http";
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient()]
};

View file

@ -0,0 +1,6 @@
export interface Book {
author: string;
initials: string;
title: string;
year: number;
}

View file

@ -0,0 +1 @@
export * from "./book.interface";

View file

@ -0,0 +1,43 @@
import { Injectable } from "@angular/core";
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Book } from "../models";
import { BehaviorSubject, catchError, Observable, take, throwError } from "rxjs";
@Injectable({
providedIn: "root"
})
export class ApiService {
private _books: BehaviorSubject<Book[]> = new BehaviorSubject<Book[]>([]);
books$: Observable<Book[]> = this._books.asObservable();
private books: Book[] = [];
getAllBooks$ = this.httpClient.get<Book[]>("/assets/books.json")
.pipe(
take(1),
catchError((error: HttpErrorResponse) => {
console.error("Something went wrong:", error);
return throwError(() => new Error("Something went wrong."));
})
);
constructor(private readonly httpClient: HttpClient) {
}
loadBooks = (searchTerm: string = "", preload = true): void => {
if (preload) {
this.getAllBooks$.subscribe((books: Book[]) => {
this._books.next(books);
this.books = books;
});
return;
}
const filteredBooks: Book[] = this.books.filter((book: Book) =>
book.author.toLowerCase().includes(searchTerm) ||
book.title.toLowerCase().includes(searchTerm)
);
this._books.next(filteredBooks);
};
}

View file

@ -0,0 +1,14 @@
<li class="col-span-1 flex rounded-md shadow-sm">
<div
class="flex w-16 flex-shrink-0 items-center justify-center bg-[#9BD83A] rounded-l-md text-sm font-medium text-gray-900 hover:text-gray-600">
{{book?.initials}}
</div>
<div
class="flex flex-1 items-center justify-between truncate rounded-r-md border-b border-r border-t border-gray-200 bg-white hover:text-gray-600">
<div class="flex-1 truncate px-4 py-2 text-sm">
<a href="#" class="font-medium text-gray-900 hover:text-gray-600">{{book?.title}}</a><br>
<a href="#" class="font-medium text-gray-900 hover:text-gray-600">{{book?.author}}</a>
<p class="text-gray-500">{{book?.year}}</p>
</div>
</div>
</li>

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BookComponent } from './book.component';
describe('BookComponent', () => {
let component: BookComponent;
let fixture: ComponentFixture<BookComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ BookComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(BookComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,14 @@
import { Component, Input } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Book } from "../../models";
@Component({
selector: "payspace-book",
standalone: true,
imports: [CommonModule],
templateUrl: "./book.component.html",
styleUrls: ["./book.component.scss"]
})
export class BookComponent {
@Input() book: Book | null | undefined;
}

View file

@ -0,0 +1,5 @@
<label for="search" class="block text-sm font-medium leading-6 text-gray-900">Quick search</label>
<div class="relative mt-2 flex items-center">
<input [formControl]="search" type="text" name="search" id="search"
class="block w-full rounded-md border-0 py-1.5 pr-14 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
</div>

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SearchComponent } from './search.component';
describe('SearchComponent', () => {
let component: SearchComponent;
let fixture: ComponentFixture<SearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ SearchComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,20 @@
import { Component, Output } from "@angular/core";
import { CommonModule } from "@angular/common";
import { FormControl, ReactiveFormsModule } from "@angular/forms";
import { distinctUntilChanged, filter } from "rxjs";
@Component({
selector: "payspace-search",
standalone: true,
imports: [CommonModule, ReactiveFormsModule],
templateUrl: "./search.component.html",
styleUrls: ["./search.component.scss"]
})
export class SearchComponent {
search = new FormControl("");
@Output() searchText = this.search.valueChanges.pipe(
filter(Boolean),
distinctUntilChanged()
);
}

View file

View file

@ -0,0 +1,26 @@
[
{
"author": "F. Scott Fitzgerald",
"initials": "FS",
"title": "The Great Gatsby",
"year": 1925
},
{
"author": "Harper Lee",
"initials": "HL",
"title": "To Kill a Mockingbird",
"year": 1960
},
{
"author": "Stephenie Meyer",
"initials": "SM",
"title": "Twilight",
"year": 2005
},
{
"author": "Stephen King",
"initials": "S",
"title": "If It Bleeds",
"year": 2020
}
]

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>part-3-angular</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="https://www.payspace.com/wp-content/uploads/2018/03/PS-FAVICON-NEW-2017.png" sizes="32x32" />
<link rel="icon" href="https://www.payspace.com/wp-content/uploads/2018/03/PS-FAVICON-NEW-2017.png" sizes="192x192" />
<link rel="apple-touch-icon" href="https://www.payspace.com/wp-content/uploads/2018/03/PS-FAVICON-NEW-2017.png" />
<meta name="msapplication-TileImage"
content="https://www.payspace.com/wp-content/uploads/2018/03/PS-FAVICON-NEW-2017.png" />
</head>
<body class="h-full">
<payspace-root></payspace-root>
</body>
</html>

View file

@ -0,0 +1,5 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig).catch((err) => console.error(err));

View file

@ -0,0 +1,5 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/* You can add global styles to this file, and also import other style files */

View file

@ -0,0 +1,8 @@
// @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment
globalThis.ngJest = {
testEnvironmentOptions: {
errorOnUnknownElements: true,
errorOnUnknownProperties: true,
},
};
import 'jest-preset-angular/setup-jest';

View file

@ -0,0 +1,14 @@
const { createGlobPatternsForDependencies } = require('@nx/angular/tailwind');
const { join } = require('path');
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
join(__dirname, 'src/**/!(*.stories|*.spec).{ts,html}'),
...createGlobPatternsForDependencies(__dirname),
],
theme: {
extend: {},
},
plugins: [],
};

View file

@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../dist/out-tsc",
"types": []
},
"files": ["src/main.ts"],
"include": ["src/**/*.d.ts"],
"exclude": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts"]
}

View file

@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",
"include": [
"src/**/*.ts"
],
"compilerOptions": {
"types": [
"jest",
"node"
]
}
}

View file

@ -0,0 +1,32 @@
{
"compilerOptions": {
"target": "es2022",
"useDefineForClassFields": false,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./tsconfig.editor.json"
}
],
"extends": "../tsconfig.base.json",
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}

View file

@ -0,0 +1,16 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../dist/out-tsc",
"module": "commonjs",
"target": "es2016",
"types": ["jest", "node"]
},
"files": ["src/test-setup.ts"],
"include": [
"jest.config.ts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}