mirror of
https://github.com/Raghu-Ch/angular-challenges.git
synced 2026-02-10 12:53:03 -05:00
feat(doc): move interop rxjs signal
This commit is contained in:
36
apps/angular/interop-rxjs-signal/.eslintrc.json
Normal file
36
apps/angular/interop-rxjs-signal/.eslintrc.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"extends": ["../../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"rules": {
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "app",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "app",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@nx/angular",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": ["*.html"],
|
||||
"extends": ["plugin:@nx/angular-template"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
13
apps/angular/interop-rxjs-signal/README.md
Normal file
13
apps/angular/interop-rxjs-signal/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Interoperability Rxjs/Signal
|
||||
|
||||
> Author: Thomas Laforge
|
||||
|
||||
### Run Application
|
||||
|
||||
```bash
|
||||
npx nx serve angular-interop-rxjs-signal
|
||||
```
|
||||
|
||||
### Documentation and Instruction
|
||||
|
||||
Challenge documentation is [here](https://angular-challenges.vercel.app/challenges/angular/30-angular-interop-rxjs-signal/).
|
||||
22
apps/angular/interop-rxjs-signal/jest.config.ts
Normal file
22
apps/angular/interop-rxjs-signal/jest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/* eslint-disable */
|
||||
export default {
|
||||
displayName: 'angular-interop-rxjs-signal',
|
||||
preset: '../../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
coverageDirectory: '../../../coverage/apps/angular/interop-rxjs-signal',
|
||||
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',
|
||||
],
|
||||
};
|
||||
98
apps/angular/interop-rxjs-signal/project.json
Normal file
98
apps/angular/interop-rxjs-signal/project.json
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"name": "angular-interop-rxjs-signal",
|
||||
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
|
||||
"projectType": "application",
|
||||
"prefix": "app",
|
||||
"sourceRoot": "apps/angular/interop-rxjs-signal/src",
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular-devkit/build-angular:browser",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/apps/angular/interop-rxjs-signal",
|
||||
"index": "apps/angular/interop-rxjs-signal/src/index.html",
|
||||
"main": "apps/angular/interop-rxjs-signal/src/main.ts",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "apps/angular/interop-rxjs-signal/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/angular/interop-rxjs-signal/src/favicon.ico",
|
||||
"apps/angular/interop-rxjs-signal/src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"apps/angular/interop-rxjs-signal/src/styles.scss",
|
||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css"
|
||||
],
|
||||
"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": "angular-interop-rxjs-signal:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "angular-interop-rxjs-signal:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "angular-interop-rxjs-signal:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"apps/angular/interop-rxjs-signal/**/*.ts",
|
||||
"apps/angular/interop-rxjs-signal/**/*.html"
|
||||
]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/angular/interop-rxjs-signal/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
apps/angular/interop-rxjs-signal/src/app/app.component.ts
Normal file
11
apps/angular/interop-rxjs-signal/src/app/app.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { RouterOutlet } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
imports: [RouterOutlet],
|
||||
selector: 'app-root',
|
||||
template: `<router-outlet />`,
|
||||
styles: [''],
|
||||
})
|
||||
export class AppComponent {}
|
||||
29
apps/angular/interop-rxjs-signal/src/app/app.config.ts
Normal file
29
apps/angular/interop-rxjs-signal/src/app/app.config.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { provideHttpClient } from '@angular/common/http';
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||
import { provideRouter, withComponentInputBinding } from '@angular/router';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
provideHttpClient(),
|
||||
provideAnimations(),
|
||||
provideRouter(
|
||||
[
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
loadComponent: () => import('./list/photos.component'),
|
||||
},
|
||||
{
|
||||
path: 'detail',
|
||||
loadComponent: () => import('./detail/detail.component'),
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '',
|
||||
},
|
||||
],
|
||||
withComponentInputBinding()
|
||||
),
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { Component, Input as RouterInput } from '@angular/core';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { Photo } from '../photo.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-photos',
|
||||
standalone: true,
|
||||
imports: [DatePipe, RouterLink],
|
||||
template: `
|
||||
<img src="{{ photo.url_m }}" alt="{{ photo.title }}" class="image" />
|
||||
<p><span class="font-bold">Title:</span> {{ photo.title }}</p>
|
||||
<p><span class="font-bold">Owner:</span> {{ photo.ownername }}</p>
|
||||
<p><span class="font-bold">Date:</span> {{ photo.datetaken | date }}</p>
|
||||
<p><span class="font-bold">Tags:</span> {{ photo.tags }}</p>
|
||||
|
||||
<button
|
||||
class="border border-black rounded-md px-4 py-2 mt-10"
|
||||
routerLink="">
|
||||
Back
|
||||
</button>
|
||||
`,
|
||||
host: {
|
||||
class: 'p-5 block',
|
||||
},
|
||||
})
|
||||
export default class DetailComponent {
|
||||
@RouterInput({
|
||||
required: true,
|
||||
transform: (value: string) => JSON.parse(decodeURIComponent(value)),
|
||||
})
|
||||
photo!: Photo;
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import { NgFor, NgIf } from '@angular/common';
|
||||
import { Component, OnInit, inject } from '@angular/core';
|
||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { RouterLinkWithHref } from '@angular/router';
|
||||
import { LetDirective } from '@ngrx/component';
|
||||
import { provideComponentStore } from '@ngrx/component-store';
|
||||
import { debounceTime, distinctUntilChanged, skipWhile, tap } from 'rxjs';
|
||||
import { Photo } from '../photo.model';
|
||||
import { PhotoStore } from './photos.store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-photos',
|
||||
standalone: true,
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
MatFormFieldModule,
|
||||
MatProgressBarModule,
|
||||
NgIf,
|
||||
NgFor,
|
||||
MatInputModule,
|
||||
LetDirective,
|
||||
RouterLinkWithHref,
|
||||
],
|
||||
template: `
|
||||
<h2 class="text-xl mb-2">Photos</h2>
|
||||
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Search</mat-label>
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
[formControl]="search"
|
||||
placeholder="write an article" />
|
||||
</mat-form-field>
|
||||
|
||||
<ng-container *ngrxLet="vm$ as vm">
|
||||
<section class="flex flex-col">
|
||||
<section class="flex gap-3 items-center">
|
||||
<button
|
||||
[disabled]="vm.page === 1"
|
||||
[class.bg-gray-400]="vm.page === 1"
|
||||
class="text-xl border rounded-md p-3"
|
||||
(click)="store.previousPage()">
|
||||
<
|
||||
</button>
|
||||
<button
|
||||
[disabled]="vm.endOfPage"
|
||||
[class.bg-gray-400]="vm.endOfPage"
|
||||
class="text-xl border rounded-md p-3"
|
||||
(click)="store.nextPage()">
|
||||
>
|
||||
</button>
|
||||
Page :{{ vm.page }} / {{ vm.pages }}
|
||||
</section>
|
||||
<mat-progress-bar
|
||||
mode="query"
|
||||
*ngIf="vm.loading"
|
||||
class="mt-5"></mat-progress-bar>
|
||||
<ul
|
||||
class="flex flex-wrap gap-4"
|
||||
*ngIf="vm.photos && vm.photos.length > 0; else noPhoto">
|
||||
<li *ngFor="let photo of vm.photos; trackBy: trackById">
|
||||
<a routerLink="detail" [queryParams]="{ photo: encode(photo) }">
|
||||
<img
|
||||
src="{{ photo.url_q }}"
|
||||
alt="{{ photo.title }}"
|
||||
class="image" />
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ng-template #noPhoto>
|
||||
<div>No Photos found. Type a search word.</div>
|
||||
</ng-template>
|
||||
<footer class="text-red-500">
|
||||
{{ vm.error }}
|
||||
</footer>
|
||||
</section>
|
||||
</ng-container>
|
||||
`,
|
||||
providers: [provideComponentStore(PhotoStore)],
|
||||
host: {
|
||||
class: 'p-5 block',
|
||||
},
|
||||
})
|
||||
export default class PhotosComponent implements OnInit {
|
||||
store = inject(PhotoStore);
|
||||
readonly vm$ = this.store.vm$.pipe(
|
||||
tap(({ search }) => {
|
||||
if (!this.formInit) {
|
||||
this.search.setValue(search);
|
||||
this.formInit = true;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
private formInit = false;
|
||||
search = new FormControl();
|
||||
|
||||
ngOnInit(): void {
|
||||
this.store.search(
|
||||
this.search.valueChanges.pipe(
|
||||
skipWhile(() => !this.formInit),
|
||||
debounceTime(300),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
trackById(index: number, photo: Photo) {
|
||||
return photo.id;
|
||||
}
|
||||
|
||||
encode(photo: Photo) {
|
||||
return encodeURIComponent(JSON.stringify(photo));
|
||||
}
|
||||
}
|
||||
135
apps/angular/interop-rxjs-signal/src/app/list/photos.store.ts
Normal file
135
apps/angular/interop-rxjs-signal/src/app/list/photos.store.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import {
|
||||
ComponentStore,
|
||||
OnStateInit,
|
||||
OnStoreInit,
|
||||
tapResponse,
|
||||
} from '@ngrx/component-store';
|
||||
import { pipe } from 'rxjs';
|
||||
import { filter, mergeMap, tap } from 'rxjs/operators';
|
||||
import { Photo } from '../photo.model';
|
||||
import { PhotoService } from '../photos.service';
|
||||
|
||||
const PHOTO_STATE_KEY = 'photo_search';
|
||||
|
||||
export interface PhotoState {
|
||||
photos: Photo[];
|
||||
search: string;
|
||||
page: number;
|
||||
pages: number;
|
||||
loading: boolean;
|
||||
error: unknown;
|
||||
}
|
||||
|
||||
const initialState: PhotoState = {
|
||||
photos: [],
|
||||
search: '',
|
||||
page: 1,
|
||||
pages: 1,
|
||||
loading: false,
|
||||
error: '',
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
export class PhotoStore
|
||||
extends ComponentStore<PhotoState>
|
||||
implements OnStoreInit, OnStateInit
|
||||
{
|
||||
private photoService = inject(PhotoService);
|
||||
|
||||
private readonly photos$ = this.select((s) => s.photos);
|
||||
private readonly search$ = this.select((s) => s.search);
|
||||
private readonly page$ = this.select((s) => s.page);
|
||||
private readonly pages$ = this.select((s) => s.pages);
|
||||
private readonly error$ = this.select((s) => s.error);
|
||||
private readonly loading$ = this.select((s) => s.loading);
|
||||
|
||||
private readonly endOfPage$ = this.select(
|
||||
this.page$,
|
||||
this.pages$,
|
||||
(page, pages) => page === pages
|
||||
);
|
||||
|
||||
readonly vm$ = this.select(
|
||||
{
|
||||
photos: this.photos$,
|
||||
search: this.search$,
|
||||
page: this.page$,
|
||||
pages: this.pages$,
|
||||
endOfPage: this.endOfPage$,
|
||||
loading: this.loading$,
|
||||
error: this.error$,
|
||||
},
|
||||
{ debounce: true }
|
||||
);
|
||||
|
||||
ngrxOnStoreInit() {
|
||||
const savedJSONState = localStorage.getItem(PHOTO_STATE_KEY);
|
||||
if (savedJSONState === null) {
|
||||
this.setState(initialState);
|
||||
} else {
|
||||
const savedState = JSON.parse(savedJSONState);
|
||||
this.setState({
|
||||
...initialState,
|
||||
search: savedState.search,
|
||||
page: savedState.page,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngrxOnStateInit() {
|
||||
this.searchPhotos(
|
||||
this.select({
|
||||
search: this.search$,
|
||||
page: this.page$,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
readonly search = this.updater(
|
||||
(state, search: string): PhotoState => ({
|
||||
...state,
|
||||
search,
|
||||
page: 1,
|
||||
})
|
||||
);
|
||||
|
||||
readonly nextPage = this.updater(
|
||||
(state): PhotoState => ({
|
||||
...state,
|
||||
page: state.page + 1,
|
||||
})
|
||||
);
|
||||
|
||||
readonly previousPage = this.updater(
|
||||
(state): PhotoState => ({
|
||||
...state,
|
||||
page: state.page - 1,
|
||||
})
|
||||
);
|
||||
|
||||
readonly searchPhotos = this.effect<{ search: string; page: number }>(
|
||||
pipe(
|
||||
filter(({ search }) => search.length >= 3),
|
||||
tap(() => this.patchState({ loading: true, error: '' })),
|
||||
mergeMap(({ search, page }) =>
|
||||
this.photoService.searchPublicPhotos(search, page).pipe(
|
||||
tapResponse(
|
||||
({ photos: { photo, pages } }) => {
|
||||
this.patchState({
|
||||
loading: false,
|
||||
photos: photo,
|
||||
pages,
|
||||
});
|
||||
localStorage.setItem(
|
||||
PHOTO_STATE_KEY,
|
||||
JSON.stringify({ search, page })
|
||||
);
|
||||
},
|
||||
(error: unknown) => this.patchState({ error, loading: false })
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
10
apps/angular/interop-rxjs-signal/src/app/photo.model.ts
Normal file
10
apps/angular/interop-rxjs-signal/src/app/photo.model.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export interface Photo {
|
||||
id: string;
|
||||
title: string;
|
||||
tags: string;
|
||||
owner: string;
|
||||
ownername: string;
|
||||
datetaken: string;
|
||||
url_q: string;
|
||||
url_m: string;
|
||||
}
|
||||
39
apps/angular/interop-rxjs-signal/src/app/photos.service.ts
Normal file
39
apps/angular/interop-rxjs-signal/src/app/photos.service.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable, inject } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Photo } from './photo.model';
|
||||
|
||||
export interface FlickrAPIResponse {
|
||||
photos: {
|
||||
pages: number;
|
||||
photo: Photo[];
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PhotoService {
|
||||
private http = inject(HttpClient);
|
||||
|
||||
public searchPublicPhotos(
|
||||
searchTerm: string,
|
||||
page: number
|
||||
): Observable<FlickrAPIResponse> {
|
||||
return this.http.get<FlickrAPIResponse>(
|
||||
'https://www.flickr.com/services/rest/',
|
||||
{
|
||||
params: {
|
||||
tags: searchTerm,
|
||||
method: 'flickr.photos.search',
|
||||
format: 'json',
|
||||
nojsoncallback: '1',
|
||||
tag_mode: 'all',
|
||||
media: 'photos',
|
||||
per_page: '30',
|
||||
page,
|
||||
extras: 'tags,date_taken,owner_name,url_q,url_m',
|
||||
api_key: 'c3050d39a5bb308d9921bef0e15c437d',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
BIN
apps/angular/interop-rxjs-signal/src/favicon.ico
Normal file
BIN
apps/angular/interop-rxjs-signal/src/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
13
apps/angular/interop-rxjs-signal/src/index.html
Normal file
13
apps/angular/interop-rxjs-signal/src/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>rxjs-to-signal</title>
|
||||
<base href="/" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
7
apps/angular/interop-rxjs-signal/src/main.ts
Normal file
7
apps/angular/interop-rxjs-signal/src/main.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
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)
|
||||
);
|
||||
5
apps/angular/interop-rxjs-signal/src/styles.scss
Normal file
5
apps/angular/interop-rxjs-signal/src/styles.scss
Normal 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 */
|
||||
2
apps/angular/interop-rxjs-signal/src/test-setup.ts
Normal file
2
apps/angular/interop-rxjs-signal/src/test-setup.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import 'jest-preset-angular/setup-jest';
|
||||
14
apps/angular/interop-rxjs-signal/tailwind.config.js
Normal file
14
apps/angular/interop-rxjs-signal/tailwind.config.js
Normal 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: [],
|
||||
};
|
||||
10
apps/angular/interop-rxjs-signal/tsconfig.app.json
Normal file
10
apps/angular/interop-rxjs-signal/tsconfig.app.json
Normal 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"]
|
||||
}
|
||||
7
apps/angular/interop-rxjs-signal/tsconfig.editor.json
Normal file
7
apps/angular/interop-rxjs-signal/tsconfig.editor.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src/**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"types": ["jest", "node"]
|
||||
}
|
||||
}
|
||||
32
apps/angular/interop-rxjs-signal/tsconfig.json
Normal file
32
apps/angular/interop-rxjs-signal/tsconfig.json
Normal 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
|
||||
}
|
||||
}
|
||||
15
apps/angular/interop-rxjs-signal/tsconfig.spec.json
Normal file
15
apps/angular/interop-rxjs-signal/tsconfig.spec.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node", "@testing-library/jest-dom"]
|
||||
},
|
||||
"files": ["src/test-setup.ts"],
|
||||
"include": [
|
||||
"jest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user