Skip to content

Commit d817e4e

Browse files
Chau TranChau Tran
Chau Tran
authored and
Chau Tran
committed
feat(suspense): init
1 parent 9c49dce commit d817e4e

14 files changed

+255
-1
lines changed

libs/suspense/.eslintrc.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"extends": ["../../.eslintrc.json"],
3+
"ignorePatterns": ["!**/*"],
4+
"overrides": [
5+
{
6+
"files": ["*.ts"],
7+
"rules": {
8+
"@angular-eslint/directive-selector": [
9+
"error",
10+
{
11+
"type": "attribute",
12+
"prefix": "ngt",
13+
"style": "camelCase"
14+
}
15+
],
16+
"@angular-eslint/component-selector": [
17+
"error",
18+
{
19+
"type": "element",
20+
"prefix": "ngt",
21+
"style": "kebab-case"
22+
}
23+
]
24+
},
25+
"extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"]
26+
},
27+
{
28+
"files": ["*.html"],
29+
"extends": ["plugin:@nx/angular-template"],
30+
"rules": {}
31+
}
32+
]
33+
}

libs/suspense/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# suspense
2+
3+
This library was generated with [Nx](https://nx.dev).
4+
5+
## Running unit tests
6+
7+
Run `nx test suspense` to execute the unit tests.

libs/suspense/jest.config.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-disable */
2+
export default {
3+
displayName: 'suspense',
4+
preset: '../../jest.preset.js',
5+
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
6+
coverageDirectory: '../../coverage/libs/suspense',
7+
transform: {
8+
'^.+\\.(ts|mjs|js|html)$': [
9+
'jest-preset-angular',
10+
{
11+
tsconfig: '<rootDir>/tsconfig.spec.json',
12+
stringifyContentPathRegex: '\\.(html|svg)$',
13+
},
14+
],
15+
},
16+
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
17+
snapshotSerializers: [
18+
'jest-preset-angular/build/serializers/no-ng-attributes',
19+
'jest-preset-angular/build/serializers/ng-snapshot',
20+
'jest-preset-angular/build/serializers/html-comment',
21+
],
22+
};

libs/suspense/ng-package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3+
"dest": "../../dist/libs/suspense",
4+
"lib": {
5+
"entryFile": "src/index.ts"
6+
}
7+
}

libs/suspense/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "angular-three-suspense",
3+
"version": "0.0.1",
4+
"peerDependencies": {
5+
"@angular/common": "^16.0.0",
6+
"@angular/core": "^16.0.0"
7+
},
8+
"dependencies": {
9+
"tslib": "^2.3.0"
10+
},
11+
"sideEffects": false
12+
}

libs/suspense/project.json

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "suspense",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "libs/suspense/src",
5+
"prefix": "ngt",
6+
"tags": [],
7+
"projectType": "library",
8+
"targets": {
9+
"build": {
10+
"executor": "@nx/angular:package",
11+
"outputs": ["{workspaceRoot}/dist/{projectRoot}"],
12+
"options": {
13+
"project": "libs/suspense/ng-package.json"
14+
},
15+
"configurations": {
16+
"production": {
17+
"tsConfig": "libs/suspense/tsconfig.lib.prod.json"
18+
},
19+
"development": {
20+
"tsConfig": "libs/suspense/tsconfig.lib.json"
21+
}
22+
},
23+
"defaultConfiguration": "production"
24+
},
25+
"test": {
26+
"executor": "@nx/jest:jest",
27+
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
28+
"options": {
29+
"jestConfig": "libs/suspense/jest.config.ts",
30+
"passWithNoTests": true
31+
},
32+
"configurations": {
33+
"ci": {
34+
"ci": true,
35+
"codeCoverage": true
36+
}
37+
}
38+
},
39+
"lint": {
40+
"executor": "@nx/linter:eslint",
41+
"outputs": ["{options.outputFile}"],
42+
"options": {
43+
"lintFilePatterns": ["libs/suspense/**/*.ts", "libs/suspense/**/*.html"]
44+
}
45+
}
46+
}
47+
}

libs/suspense/src/index.ts

Whitespace-only changes.

libs/suspense/src/lib/suspense.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
Component,
4+
ContentChild,
5+
Directive,
6+
InjectionToken,
7+
TemplateRef,
8+
ViewChild,
9+
ViewContainerRef,
10+
assertInInjectionContext,
11+
inject,
12+
signal,
13+
type Signal,
14+
} from '@angular/core';
15+
import { ObservableInput } from 'rxjs';
16+
17+
export type NgtSuspenseApi = {
18+
operations: Array<() => ObservableInput<unknown>>;
19+
unwrapped: Signal<unknown>;
20+
};
21+
22+
export const SUSPENSE_API = new InjectionToken<NgtSuspenseApi>('Suspense API');
23+
24+
export function suspense<TValue>(cb: () => ObservableInput<TValue>): Signal<TValue> {
25+
assertInInjectionContext(suspense);
26+
const suspenseApi = inject(SUSPENSE_API);
27+
suspenseApi.operations.push(cb);
28+
return suspenseApi.unwrapped as Signal<TValue>;
29+
}
30+
31+
@Directive({ selector: 'ng-template[fallback]', standalone: true })
32+
export class NgtSuspenseFallback {}
33+
34+
@Component({
35+
selector: 'ngt-suspense',
36+
standalone: true,
37+
template: `
38+
<ng-template #content>
39+
<ng-content />
40+
</ng-template>
41+
<ng-container #anchor />
42+
`,
43+
host: { style: 'display: contents' },
44+
providers: [
45+
{
46+
provide: SUSPENSE_API,
47+
useValue: {
48+
operations: [],
49+
unwrapped: signal(null),
50+
},
51+
},
52+
],
53+
changeDetection: ChangeDetectionStrategy.OnPush,
54+
})
55+
export class NgtSuspense {
56+
readonly #suspenseApi = inject(SUSPENSE_API, { self: true });
57+
58+
@ContentChild(NgtSuspenseFallback, { read: TemplateRef }) fallbackTemplate?: TemplateRef<unknown>;
59+
@ViewChild('content', { read: TemplateRef, static: true }) contentTemplate!: TemplateRef<unknown>;
60+
@ViewChild('anchor', { read: ViewContainerRef, static: true }) anchor!: ViewContainerRef;
61+
62+
ngOnInit() {}
63+
}

libs/suspense/src/test-setup.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import 'jest-preset-angular/setup-jest';

libs/suspense/tsconfig.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es2022",
4+
"useDefineForClassFields": false,
5+
"forceConsistentCasingInFileNames": true,
6+
"strict": true,
7+
"noImplicitOverride": true,
8+
"noPropertyAccessFromIndexSignature": true,
9+
"noImplicitReturns": true,
10+
"noFallthroughCasesInSwitch": true
11+
},
12+
"files": [],
13+
"include": [],
14+
"references": [
15+
{
16+
"path": "./tsconfig.lib.json"
17+
},
18+
{
19+
"path": "./tsconfig.spec.json"
20+
}
21+
],
22+
"extends": "../../tsconfig.base.json",
23+
"angularCompilerOptions": {
24+
"enableI18nLegacyMessageIdFormat": false,
25+
"strictInjectionParameters": true,
26+
"strictInputAccessModifiers": true,
27+
"strictTemplates": true
28+
}
29+
}

libs/suspense/tsconfig.lib.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/out-tsc",
5+
"declaration": true,
6+
"declarationMap": true,
7+
"inlineSources": true,
8+
"types": []
9+
},
10+
"exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
11+
"include": ["src/**/*.ts"]
12+
}

libs/suspense/tsconfig.lib.prod.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "./tsconfig.lib.json",
3+
"compilerOptions": {
4+
"declarationMap": false
5+
},
6+
"angularCompilerOptions": {
7+
"compilationMode": "partial"
8+
}
9+
}

libs/suspense/tsconfig.spec.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "../../dist/out-tsc",
5+
"module": "commonjs",
6+
"target": "es2016",
7+
"types": ["jest", "node"]
8+
},
9+
"files": ["src/test-setup.ts"],
10+
"include": ["jest.config.ts", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts"]
11+
}

tsconfig.base.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"angular-three-soba": ["libs/soba/src/index.ts"],
2424
"angular-three-soba/abstractions": ["libs/soba/abstractions/src/index.ts"],
2525
"angular-three-soba/controls": ["libs/soba/controls/src/index.ts"],
26-
"angular-three-soba/staging": ["libs/soba/staging/src/index.ts"]
26+
"angular-three-soba/staging": ["libs/soba/staging/src/index.ts"],
27+
"angular-three-suspense": ["libs/suspense/src/index.ts"]
2728
}
2829
},
2930
"exclude": ["node_modules", "tmp"]

0 commit comments

Comments
 (0)