├── .editorconfig ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── tasks.json ├── README.md ├── docs ├── 3rdpartylicenses.txt ├── 404.html ├── assets │ └── snippets │ │ ├── .gitkeep │ │ ├── defer-accordion │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-error │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-loading-vs-placeholder │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-multiple │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-nested │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-npm-package │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-hover │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-idle │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-immediate │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-interaction │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-timer │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-on-viewport │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-prefetch │ │ ├── html.html │ │ └── ts.html │ │ ├── defer-when-condition │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-accordion-content-a │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-accordion-content-b │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-accordion-content-c │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-error │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-loading-vs-placeholder │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-multiple-a │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-multiple-b │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-multiple-c │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-nested-further │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-nested │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-hover │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-idle │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-immediate │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-interaction │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-timer │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-on-viewport │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-prefetch │ │ ├── html.html │ │ └── ts.html │ │ ├── lazy-shared │ │ ├── html.html │ │ └── ts.html │ │ └── lazy-when-condition │ │ ├── html.html │ │ └── ts.html ├── chunk-3FNJ2ZMJ.js ├── chunk-427AOKNY.js ├── chunk-4KX6UJK3.js ├── chunk-4MHHKHG5.js ├── chunk-5GYVHAEO.js ├── chunk-5XD2OXE3.js ├── chunk-66XS4QWB.js ├── chunk-6DAJ2A5H.js ├── chunk-7GWIDXD6.js ├── chunk-AICA3QS6.js ├── chunk-ATSHXKZ7.js ├── chunk-AWMYU3NT.js ├── chunk-CKZQZNXB.js ├── chunk-DN5YT25O.js ├── chunk-DO5JAS45.js ├── chunk-DOMWCVYK.js ├── chunk-EATVXNW4.js ├── chunk-ECGOT6LA.js ├── chunk-F4UHNG5O.js ├── chunk-FDEO2DTO.js ├── chunk-FQ7G2Z4C.js ├── chunk-G5I3UZZN.js ├── chunk-H5L4WFXW.js ├── chunk-II6QMHP6.js ├── chunk-KEPCVLWQ.js ├── chunk-KYJRYBID.js ├── chunk-LHI7OLGB.js ├── chunk-LIVYS4BP.js ├── chunk-LJZ5A7MJ.js ├── chunk-M2XFULLM.js ├── chunk-NJOMRXVD.js ├── chunk-OEUOV4Z3.js ├── chunk-OJTWMRHI.js ├── chunk-PEUG7PPS.js ├── chunk-QJPZIJLW.js ├── chunk-RURXA3RU.js ├── chunk-S55KTJ74.js ├── chunk-SH32YSIN.js ├── chunk-SXNGXTZF.js ├── chunk-T3KMG43A.js ├── chunk-TJ5IR3FS.js ├── chunk-UKHOVCAU.js ├── chunk-UXHIX3CP.js ├── chunk-X23RBJFR.js ├── chunk-XHH54KLV.js ├── chunk-Y462ALH4.js ├── chunk-YZGQRNTL.js ├── chunk-ZNB2FFWI.js ├── favicon.ico ├── index.html ├── main-NL24VXDT.js ├── polyfills-LZBJRJJE.js └── styles-CUQVMV3G.css ├── nx.json ├── package-lock.json ├── package.json ├── project.json ├── scripts └── build-code-snippets.mjs ├── src ├── app │ ├── about.component.ts │ ├── app.component.ts │ ├── app.config.ts │ ├── app.routes.ts │ ├── box.component.ts │ ├── button.component.ts │ ├── defer-guide.component.ts │ ├── defer-usecases │ │ ├── defer-accordion.ts │ │ ├── defer-error.ts │ │ ├── defer-loading-vs-placeholder.ts │ │ ├── defer-multiple.ts │ │ ├── defer-nested.ts │ │ ├── defer-npm-package.ts │ │ ├── defer-on-hover.ts │ │ ├── defer-on-idle.ts │ │ ├── defer-on-immediate.ts │ │ ├── defer-on-interaction.ts │ │ ├── defer-on-timer.ts │ │ ├── defer-on-viewport.ts │ │ ├── defer-prefetch.ts │ │ ├── defer-when-condition.ts │ │ ├── highlight.directive.ts │ │ ├── lazy-accordion-content-a.ts │ │ ├── lazy-accordion-content-b.ts │ │ ├── lazy-accordion-content-c.ts │ │ ├── lazy-error.ts │ │ ├── lazy-loading-vs-placeholder.ts │ │ ├── lazy-multiple-a.ts │ │ ├── lazy-multiple-b.ts │ │ ├── lazy-multiple-c.ts │ │ ├── lazy-nested-further.ts │ │ ├── lazy-nested.ts │ │ ├── lazy-on-hover.ts │ │ ├── lazy-on-idle.ts │ │ ├── lazy-on-immediate.ts │ │ ├── lazy-on-interaction.ts │ │ ├── lazy-on-timer.ts │ │ ├── lazy-on-viewport.ts │ │ ├── lazy-prefetch.ts │ │ ├── lazy-shared.ts │ │ ├── lazy-when-condition.ts │ │ ├── legacy │ │ │ ├── legacy.module.ts │ │ │ └── non-standalone.ts │ │ ├── loader.ts │ │ ├── stupid-case-pipe.ts │ │ └── use-case-container.ts │ └── ui-snippet-dialog-content │ │ ├── ui-snippet-dialog-content.css │ │ └── ui-snippet-dialog-content.ts ├── assets │ ├── .gitkeep │ └── snippets │ │ └── .gitkeep ├── favicon.ico ├── index.html ├── main.ts └── styles.css ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://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 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.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 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | 44 | src/assets/snippets/**/* 45 | !src/assets/snippets/.gitkeep 46 | .nx/cache 47 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "angular.ng-template", 4 | "nrwl.angular-console" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Defer 2 | 3 | image 4 | -------------------------------------------------------------------------------- /docs/assets/snippets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/angular-defer/46a03f44c6a81e8a3f707165d6eed008d6543278/docs/assets/snippets/.gitkeep -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-accordion-content-a/html.html: -------------------------------------------------------------------------------- 1 |
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
2 | 
3 | 
4 | 5 |
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum</p>
6 | 
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-accordion-content-a/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-accordion-content-a',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyAccordionContentAComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-accordion-content-a',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyAccordionContentAComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-accordion-content-b/html.html: -------------------------------------------------------------------------------- 1 |
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</p>
2 | 
3 | 
4 | 5 |
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</p>
6 | 
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-accordion-content-b/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-accordion-content-b',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyAccordionContentBComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-accordion-content-b',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyAccordionContentBComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-accordion-content-c/html.html: -------------------------------------------------------------------------------- 1 |
<p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
2 | 
3 | 
4 | 5 |
<p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?</p>
6 | 
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-error/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-error</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-error</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-error/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-error',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyErrorComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-error',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyErrorComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-loading-vs-placeholder/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-loading-vs-placeholder</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-loading-vs-placeholder</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-loading-vs-placeholder/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-loading-vs-placeholder',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyLoadingVsPlaceholder {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-loading-vs-placeholder',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyLoadingVsPlaceholder {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-a/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-multiple-a</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-multiple-a</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-a/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-multiple-a',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyMultipleAComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-multiple-a',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyMultipleAComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-b/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-multiple-b</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-multiple-b</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-b/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-multiple-b',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyMultipleBComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-multiple-b',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyMultipleBComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-c/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-multiple-c</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-multiple-c</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-multiple-c/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-multiple-c',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyMultipleCComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-multiple-c',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyMultipleCComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-nested-further/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-nested-further</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-nested-further</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-nested-further/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-nested-further',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyNestedFurtherComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-nested-further',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyNestedFurtherComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-nested/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-nested</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-nested</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-nested/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-nested',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyNestedComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-nested',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyNestedComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-hover/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-hover</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-hover</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-hover/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-hover',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnHoverComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-hover',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnHoverComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-idle/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-idle</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-idle</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-idle/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-idle',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnIdleComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-idle',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnIdleComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-immediate/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-immediate</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-immediate</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-immediate/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-immediate',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnImmediateComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-immediate',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnImmediateComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-interaction/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-interaction</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-interaction</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-interaction/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-interaction',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnInteractionComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-interaction',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnInteractionComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-timer/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-timer</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-timer</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-timer/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-timer',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnTimerComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-timer',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnTimerComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-viewport/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-on-viewport</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-on-viewport</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-on-viewport/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-on-viewport',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyOnViewportComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-on-viewport',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyOnViewportComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-prefetch/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-prefetch</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-prefetch</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-prefetch/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-prefetch',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyPrefetchComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-prefetch',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyPrefetchComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-shared/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-shared</h2>
 2 | <content><em>this component is <strong>shared</strong> across multiple routes</em></content>
 3 | <ng-content></ng-content>
 4 | 
5 | 6 |
<h2>lazy-shared</h2>
 7 | <content><em>this component is <strong>shared</strong> across multiple routes</em></content>
 8 | <ng-content></ng-content>
 9 | 
10 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-shared/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-shared',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazySharedComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-shared',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazySharedComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-when-condition/html.html: -------------------------------------------------------------------------------- 1 |
<h2>lazy-when-condition</h2>
2 | <ng-content></ng-content>
3 | 
4 | 5 |
<h2>lazy-when-condition</h2>
6 | <ng-content></ng-content>
7 | 
8 | -------------------------------------------------------------------------------- /docs/assets/snippets/lazy-when-condition/ts.html: -------------------------------------------------------------------------------- 1 |
import { Component } from '@angular/core';
 2 | 
 3 | @Component({
 4 |   selector: 'lazy-when-condition',
 5 |   standalone: true,
 6 |   templateUrl: 'component.html',
 7 | })
 8 | export class LazyWhenConditionComponent {
 9 | }
10 | 
11 | 
12 | 13 |
import { Component } from '@angular/core';
14 | 
15 | @Component({
16 |   selector: 'lazy-when-condition',
17 |   standalone: true,
18 |   templateUrl: 'component.html',
19 | })
20 | export class LazyWhenConditionComponent {
21 | }
22 | 
23 | 
24 | -------------------------------------------------------------------------------- /docs/chunk-3FNJ2ZMJ.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as r,jb as a,kb as s,mb as c,rb as l}from"./chunk-OJTWMRHI.js";var p=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-nested-further"]],standalone:!0,features:[l],ngContentSelectors:p,decls:3,vars:0,template:function(n,d){n&1&&(a(),i(0,"h2"),c(1,"lazy-nested-further"),r(),s(2))},encapsulation:2});let t=e;return t})();export{u as LazyNestedFurtherComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-4KX6UJK3.js: -------------------------------------------------------------------------------- 1 | import{Z as o}from"./chunk-OJTWMRHI.js";function i(e){return[...e].map((t,n)=>n%2==0?t.toUpperCase():t.toLowerCase()).join("")}var u=(()=>{let t=class t{transform(r){return i(r)}};t.\u0275fac=function(p){return new(p||t)},t.\u0275pipe=o({name:"StUpIdCaSe",type:t,pure:!0,standalone:!0});let e=t;return e})();export{u as a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-4MHHKHG5.js: -------------------------------------------------------------------------------- 1 | import{d as v,e as w,f as E}from"./chunk-5XD2OXE3.js";import{a as u}from"./chunk-SH32YSIN.js";import{a as g}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as m,Sa as a,Ua as d,Va as p,W as l,bb as c,cb as t,db as n,eb as s,mb as e,nb as f,rb as x,sb as h,tb as S}from"./chunk-OJTWMRHI.js";var C=()=>[w,import("./chunk-KYJRYBID.js").then(i=>i.LazyOnViewportComponent),import("./chunk-7GWIDXD6.js").then(i=>i.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(i=>i.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(i=>i.HighlightDirective)];function y(i,o){i&1&&(t(0,"lazy-on-viewport")(1,"article"),e(2," some "),t(3,"code"),e(4,"@defer (on viewport)"),n(),e(5," content "),n()(),t(6,"lazy-shared")(7,"article"),e(8," some "),t(9,"code"),e(10,"@defer (on viewport)"),n(),e(11," content "),n()(),t(12,"non-standalone")(13,"article"),e(14," some "),t(15,"code"),e(16,"@defer (on viewport)"),n(),e(17," content "),n()(),t(18,"h2"),e(19,"pipe"),n(),e(20),h(21,"StUpIdCaSe"),t(22,"h2"),e(23,"directive"),n(),t(24,"div",5),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),n()),i&2&&(m(20),f(" ",S(21,1,"Lazy loaded pipe here")," "))}function _(i,o){i&1&&s(0,"loader")}function b(i,o){i&1&&(t(0,"span"),e(1,"waiting to get into the viewport"),n())}function O(i,o){i&1&&e(0," something went wrong! ")}var A=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=l({type:o,selectors:[["defer-on-viewport"]],standalone:!0,features:[x],decls:39,vars:0,consts:[["href","https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API"],[1,"scroll-container","box"],[1,"scroll-page"],[1e3,100],[500],["highlight",""]],template:function(r,I){r&1&&(t(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),t(3,"code"),e(4,"viewport"),n(),e(5," would trigger the deferred block when the specified content enters the viewport using the "),t(6,"a",0),e(7,"IntersectionObserver"),n(),e(8," API. This could be the placeholder content or an element reference."),n(),t(9,"content"),e(10,"\u{1F4DA} "),t(11,"code"),e(12,"viewport"),n(),e(13," trigger "),t(14,"strong"),e(15,"with no parameters"),n(),e(16," can only be placed on an "),t(17,"code"),e(18,"@defer"),n(),e(19," that has a "),t(20,"code"),e(21,"@placeholder"),n(),e(22," block with exactly one root element node."),n()(),t(23,"div",1)(24,"div",2),e(25,"scroll down..."),n(),t(26,"div",2),e(27,"and some more..."),n(),t(28,"div",2),e(29,"a little bit more..."),n(),t(30,"div",2),e(31,"you're almost done..."),n(),t(32,"div"),a(33,y,26,3)(34,_,1,0)(35,b,2,0)(36,O,1,0),p(37,33,C,34,35,36,3,4,d),c(0,-1),n()())},dependencies:[v,E,g,u],styles:[".scroll-container[_ngcontent-%COMP%]{border:1px solid var(--main-accent-color);border-radius:6px;width:75%;height:250px;max-height:50%;overflow-y:scroll;scroll-behavior:smooth}.scroll-page[_ngcontent-%COMP%]{display:flex;align-items:center;justify-content:center;height:100%;font-size:2em}"]});let i=o;return i})();export{A as DeferOnViewportComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-5GYVHAEO.js: -------------------------------------------------------------------------------- 1 | import{a as g}from"./chunk-DOMWCVYK.js";import{d as S,e as c,f as C}from"./chunk-5XD2OXE3.js";import{a as E}from"./chunk-SH32YSIN.js";import{a as v}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{$a as d,Ha as h,Sa as m,Ua as l,Va as a,W as f,cb as n,db as i,eb as p,mb as e,nb as x,rb as s,sb as u,tb as D}from"./chunk-OJTWMRHI.js";var y=()=>[c,import("./chunk-ATSHXKZ7.js").then(t=>t.LazyOnHoverComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(t=>t.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(t=>t.HighlightDirective)],H=()=>[c,import("./chunk-ATSHXKZ7.js").then(t=>t.LazyOnHoverComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent)];function O(t,o){t&1&&(n(0,"lazy-on-hover")(1,"article"),e(2," some "),n(3,"code"),e(4,"@defer (on hover)"),i(),e(5," content "),i()(),n(6,"lazy-shared")(7,"article"),e(8," some "),n(9,"code"),e(10,"@defer (on hover)"),i(),e(11," content "),i()(),n(12,"non-standalone")(13,"article"),e(14," some "),n(15,"code"),e(16,"@defer (on hover)"),i(),e(17," content "),i()(),n(18,"h2"),e(19,"pipe"),i(),e(20),u(21,"StUpIdCaSe"),n(22,"h2"),e(23,"directive"),i(),n(24,"div",3),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),i()),t&2&&(h(20),x(" ",D(21,1,"Lazy loaded pipe here")," "))}function z(t,o){t&1&&p(0,"loader")}function T(t,o){t&1&&(n(0,"app-button"),e(1,"\u{1F449} "),n(2,"strong"),e(3,"hover me"),i(),e(4," (the placeholder) to load content \u{1F448}"),i())}function L(t,o){t&1&&e(0," something went wrong! ")}function w(t,o){t&1&&(n(0,"lazy-on-hover")(1,"article"),e(2," some "),n(3,"code"),e(4,"@defer (on hover(el))"),i(),e(5," content "),i()(),n(6,"lazy-shared")(7,"article"),e(8," some "),n(9,"code"),e(10,"@defer (on hover(el))"),i(),e(11," content "),i()(),n(12,"non-standalone")(13,"article"),e(14," some "),n(15,"code"),e(16,"@defer (on hover(el))"),i(),e(17," content "),i()())}function b(t,o){t&1&&p(0,"loader")}function F(t,o){t&1&&e(0," something went wrong! ")}var j=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=f({type:o,selectors:[["defer-on-hover"]],standalone:!0,features:[s],decls:31,vars:0,consts:[[1e3,100],[500],["el",""],["highlight",""]],template:function(r,I){r&1&&(n(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),n(3,"code"),e(4,"hover"),i(),e(5," triggers deferred loading when the mouse has hovered over the trigger area. Events used for this are "),n(6,"code"),e(7,"mouseenter"),i(),e(8," and "),n(9,"code"),e(10,"focusin"),i(),e(11,"."),i()(),m(12,O,26,3)(13,z,1,0)(14,T,5,0)(15,L,1,0),a(16,12,y,13,14,15,0,1,l),d(0,-1),n(18,"div"),e(19,"...OR"),i(),n(20,"app-button",null,2),e(22,"\u{1F449} "),n(23,"strong"),e(24,"hover this guy"),i(),e(25," (element with a template variable) to load content \u{1F448}"),i(),m(26,w,18,0)(27,b,1,0)(28,F,1,0),a(29,26,H,27,null,28,0,null,l),d(20))},dependencies:[S,C,v,E,g],encapsulation:2});let t=o;return t})();export{j as DeferOnHoverComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-66XS4QWB.js: -------------------------------------------------------------------------------- 1 | import{a as E}from"./chunk-DOMWCVYK.js";import{d as f,f as D}from"./chunk-5XD2OXE3.js";import{a as S}from"./chunk-SH32YSIN.js";import"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as a,Sa as m,Ua as d,Va as p,W as r,ab as c,cb as t,db as n,mb as e,nb as s,rb as u,sb as h,tb as x}from"./chunk-OJTWMRHI.js";var k=()=>[import("./chunk-TJ5IR3FS.js").then(i=>i.StUpIdCaSePipe)];function w(i,o){i&1&&(t(0,"h2"),e(1,"pipe"),n(),e(2),h(3,"StUpIdCaSe")),i&2&&(a(2),s(" ",x(3,1,"Lazy loaded pipe here")," "))}function C(i,o){i&1&&(t(0,"app-button"),e(1,"\u{1F449} "),t(2,"strong"),e(3,"interact with me"),n(),e(4," \u{1F448}"),n())}var F=(()=>{let o=class o{};o.\u0275fac=function(l){return new(l||o)},o.\u0275cmp=r({type:o,selectors:[["defer-npm-package"]],standalone:!0,features:[u],decls:60,vars:0,consts:[["href","https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel/modulepreload"],[500]],template:function(l,y){l&1&&(t(0,"app-box")(1,"content"),e(2,"\u{1F590}\uFE0F only the "),t(3,"code"),e(4,"StUpIdCaSe"),n(),e(5," pipe is a deferrable here (no components). However, it's the only code which uses an external npm package, "),t(6,"code"),e(7,"stupid-case"),n(),e(8,"."),n(),t(9,"content"),e(10,"\u{1F590}\uFE0F follow these steps:"),t(11,"ul")(12,"li"),e(13,"in the devtools/network, search for the last chunk loaded (the only one loaded within this defer), e.g. "),t(14,"pre"),e(15,"chunk-DHY7UALU.js"),n(),e(16,"It will include code which looks like this:"),t(17,"pre"),e(18,`import { 2 | StUpIdCaSePipe 3 | } from "/chunk-BYHJVGJ4.js"; 4 | export { 5 | StUpIdCaSePipe 6 | };`),n(),e(19,"In this case, "),t(20,"code"),e(21,"DHY7UALU"),n(),e(22," is the chunk with the "),t(23,"strong"),e(24,"pipe"),n(),e(25,", whereas "),t(26,"code"),e(27,"BYHJVGJ4"),n(),e(28," is the chunk with the "),t(29,"strong"),e(30,"npm package"),n(),e(31,"."),n(),t(32,"li"),e(33,"at the top of network tab, filter requests by "),t(34,"code"),e(35,"BYHJVGJ4"),n(),e(36," and you'd see the content on the npm package."),n(),t(37,"li"),e(38,"\u{1F914} Now, where/when/who initiated loading it?"),n(),t(39,"li"),e(40,"Clear the Network request filter and filter by type: "),t(41,"code"),e(42,"Doc"),n(),e(43," (Document, HTML, the index.html file). Scroll to the end of HTML/HEAD where you'd find:"),t(44,"pre"),e(45,''),n(),e(46,"Angular is "),t(47,"strong"),e(48,"preloading"),n(),e(49," the module for later use in a "),t(50,"strong"),e(51,"non-sequential manner"),n(),e(52," (faster) once the document has been created. Read more about "),t(53,"a",0),e(54,"modulepreload"),n(),e(55,"."),n()()()(),m(56,w,4,3)(57,C,5,0),p(58,56,k,null,57,null,null,1,d),c(0,-1))},dependencies:[f,D,S,E],encapsulation:2});let i=o;return i})();export{F as DeferNPMPackageComponent}; 7 | -------------------------------------------------------------------------------- /docs/chunk-6DAJ2A5H.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as r,jb as a,kb as c,mb as s,rb as l}from"./chunk-OJTWMRHI.js";var p=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-timer"]],standalone:!0,features:[l],ngContentSelectors:p,decls:3,vars:0,template:function(n,f){n&1&&(a(),i(0,"h2"),s(1,"lazy-on-timer"),r(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnTimerComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-7GWIDXD6.js: -------------------------------------------------------------------------------- 1 | import{a}from"./chunk-CKZQZNXB.js";import"./chunk-OJTWMRHI.js";export{a as LazySharedComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-AICA3QS6.js: -------------------------------------------------------------------------------- 1 | import{a}from"./chunk-DOMWCVYK.js";import"./chunk-LIVYS4BP.js";import"./chunk-OJTWMRHI.js";export{a as ButtonComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-ATSHXKZ7.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as r,jb as a,kb as c,mb as s,rb as l}from"./chunk-OJTWMRHI.js";var f=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-hover"]],standalone:!0,features:[l],ngContentSelectors:f,decls:3,vars:0,template:function(n,m){n&1&&(a(),i(0,"h2"),s(1,"lazy-on-hover"),r(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnHoverComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-AWMYU3NT.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as l,mb as c,rb as s}from"./chunk-OJTWMRHI.js";var d=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-loading-vs-placeholder"]],standalone:!0,features:[s],ngContentSelectors:d,decls:3,vars:0,template:function(n,f){n&1&&(r(),i(0,"h2"),c(1,"lazy-loading-vs-placeholder"),a(),l(2))},encapsulation:2});let t=e;return t})();export{u as LazyLoadingVsPlaceholder}; 2 | -------------------------------------------------------------------------------- /docs/chunk-CKZQZNXB.js: -------------------------------------------------------------------------------- 1 | import{W as a,cb as n,db as i,jb as s,kb as c,mb as t,rb as l}from"./chunk-OJTWMRHI.js";var d=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(r){return new(r||e)},e.\u0275cmp=a({type:e,selectors:[["lazy-shared"]],standalone:!0,features:[l],ngContentSelectors:d,decls:9,vars:0,template:function(r,p){r&1&&(s(),n(0,"h2"),t(1,"lazy-shared"),i(),n(2,"content")(3,"em"),t(4,"this component is "),n(5,"strong"),t(6,"shared"),i(),t(7," across multiple routes"),i()(),c(8))},encapsulation:2});let o=e;return o})();export{u as a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-DN5YT25O.js: -------------------------------------------------------------------------------- 1 | import{W as i,cb as o,db as u,mb as n,rb as s}from"./chunk-OJTWMRHI.js";var c=(()=>{let e=class e{};e.\u0275fac=function(a){return new(a||e)},e.\u0275cmp=i({type:e,selectors:[["lazy-accordion-content-b"]],standalone:!0,features:[s],decls:2,vars:0,template:function(a,m){a&1&&(o(0,"p"),n(1,"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem."),u())},encapsulation:2});let t=e;return t})();export{c as LazyAccordionContentBComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-DO5JAS45.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as c,mb as s,rb as m}from"./chunk-OJTWMRHI.js";var p=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-immediate"]],standalone:!0,features:[m],ngContentSelectors:p,decls:3,vars:0,template:function(n,d){n&1&&(r(),i(0,"h2"),s(1,"lazy-on-immediate"),a(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnImmediateComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-DOMWCVYK.js: -------------------------------------------------------------------------------- 1 | import{h as s}from"./chunk-LIVYS4BP.js";import{W as n,cb as i,db as r,jb as c,kb as l,rb as a}from"./chunk-OJTWMRHI.js";var p=["*"],m=(()=>{let e=class e{};e.\u0275fac=function(t){return new(t||e)},e.\u0275cmp=n({type:e,selectors:[["app-button"]],standalone:!0,features:[a],ngContentSelectors:p,decls:2,vars:0,template:function(t,v){t&1&&(c(),i(0,"button"),l(1),r())},dependencies:[s],styles:["button[_ngcontent-%COMP%]{background-color:color-mix(in srgb,var(--vivid-pink) 10%,white);border-radius:3px;border:1px solid var(--vivid-pink);box-shadow:#ffffffb3 0 1px inset;box-sizing:border-box;color:var(--vivid-pink);cursor:pointer;display:inline-block;font-weight:400;margin:8px .8em;outline:none;padding:8px .8em;position:relative;text-align:center;text-decoration:none;user-select:none;-webkit-user-select:none;touch-action:manipulation;vertical-align:baseline;white-space:nowrap}button[_ngcontent-%COMP%]:hover, button[_ngcontent-%COMP%]:focus{background-color:color-mix(in srgb,var(--electric-violet) 10%,white);color:var(--electric-violet);border-color:var(--electric-violet)}button[_ngcontent-%COMP%]:focus{box-shadow:0 0 0 4px color-mix(in srgb,var(--electric-violet) 30%,white)}button[_ngcontent-%COMP%]:active{background-color:color-mix(in srgb,var(--electric-violet) 10%,white);color:var(--electric-violet);border-color:var(--electric-violet);box-shadow:none}"]});let o=e;return o})();export{m as a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-EATVXNW4.js: -------------------------------------------------------------------------------- 1 | import{d as S,e as C,f as E}from"./chunk-5XD2OXE3.js";import{a as g}from"./chunk-SH32YSIN.js";import{a as D}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as a,Sa as l,Ua as d,Va as p,W as m,Za as f,cb as i,db as n,eb as c,mb as t,nb as s,rb as x,sb as h,tb as u}from"./chunk-OJTWMRHI.js";var _=()=>[C,import("./chunk-6DAJ2A5H.js").then(e=>e.LazyOnTimerComponent),import("./chunk-7GWIDXD6.js").then(e=>e.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(e=>e.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(e=>e.HighlightDirective)];function y(e,o){e&1&&(i(0,"lazy-on-timer")(1,"article"),t(2," some "),i(3,"code"),t(4,"@defer (on timer(2000ms))"),n(),t(5," content "),n()(),i(6,"lazy-shared")(7,"article"),t(8," some "),i(9,"code"),t(10,"@defer (on timer(2000ms))"),n(),t(11," content "),n()(),i(12,"non-standalone")(13,"article"),t(14," some "),i(15,"code"),t(16,"@defer (on timer(2000ms))"),n(),t(17," content "),n()(),i(18,"h2"),t(19,"pipe"),n(),t(20),h(21,"StUpIdCaSe"),i(22,"h2"),t(23,"directive"),n(),i(24,"div",2),t(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),n()),e&2&&(a(20),s(" ",u(21,1,"Lazy loaded pipe here")," "))}function v(e,o){e&1&&c(0,"loader")}function O(e,o){e&1&&t(0," wait for the timer... ")}function z(e,o){e&1&&t(0," something went wrong! ")}var P=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=m({type:o,selectors:[["defer-on-timer"]],standalone:!0,features:[x],decls:12,vars:0,consts:[[1e3,100],[500],["highlight",""]],template:function(r,L){r&1&&(i(0,"app-box")(1,"content"),t(2,"\u{1F4DA} "),i(3,"code"),t(4,"timer(x)"),n(),t(5," would trigger after a specified duration."),n()(),l(6,y,26,3)(7,v,1,0)(8,O,1,0)(9,z,1,0),p(10,6,_,7,8,9,0,1,d),f(2e3))},dependencies:[S,E,D,g],encapsulation:2});let e=o;return e})();export{P as DeferOnTimerComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-ECGOT6LA.js: -------------------------------------------------------------------------------- 1 | import{d as g,e as C,f as E}from"./chunk-5XD2OXE3.js";import{a as S}from"./chunk-SH32YSIN.js";import{a as D}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as r,Sa as d,Ua as l,Va as p,W as a,Ya as c,cb as i,db as n,eb as f,mb as e,nb as h,rb as s,sb as x,tb as u}from"./chunk-OJTWMRHI.js";var y=()=>[C,import("./chunk-DO5JAS45.js").then(t=>t.LazyOnImmediateComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(t=>t.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(t=>t.HighlightDirective)];function I(t,o){t&1&&(i(0,"lazy-on-immediate")(1,"article"),e(2," some "),i(3,"code"),e(4,"@defer (on immediate)"),n(),e(5," content "),n()(),i(6,"lazy-shared")(7,"article"),e(8," some "),i(9,"code"),e(10,"@defer (on immediate)"),n(),e(11," content "),n()(),i(12,"non-standalone")(13,"article"),e(14," some "),i(15,"code"),e(16,"@defer (on immediate)"),n(),e(17," content "),n()(),i(18,"h2"),e(19,"pipe"),n(),e(20),x(21,"StUpIdCaSe"),i(22,"h2"),e(23,"directive"),n(),i(24,"div",2),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),n()),t&2&&(r(20),h(" ",u(21,1,"Lazy loaded pipe here")," "))}function v(t,o){t&1&&f(0,"loader")}function O(t,o){t&1&&(e(0," that should load "),i(1,"strong"),e(2,"immediate"),n(),e(3,"... "))}function z(t,o){t&1&&e(0," something went wrong! ")}var P=(()=>{let o=class o{};o.\u0275fac=function(m){return new(m||o)},o.\u0275cmp=a({type:o,selectors:[["defer-on-immediate"]],standalone:!0,features:[s],decls:12,vars:0,consts:[[1e3,100],[500],["highlight",""]],template:function(m,L){m&1&&(i(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),i(3,"code"),e(4,"immediate"),n(),e(5," triggers the deferred load immediately, meaning once the client has finished rendering, the defer chunk would then start fetching right away."),n()(),d(6,I,26,3)(7,v,1,0)(8,O,4,0)(9,z,1,0),p(10,6,y,7,8,9,0,1,l),c())},dependencies:[g,E,D,S],encapsulation:2});let t=o;return t})();export{P as DeferOnImmediateComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-F4UHNG5O.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as c,kb as r,mb as l,rb as s}from"./chunk-OJTWMRHI.js";var m=["*"],d=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-multiple-c"]],standalone:!0,features:[s],ngContentSelectors:m,decls:3,vars:0,template:function(n,f){n&1&&(c(),i(0,"h2"),l(1,"lazy-multiple-c"),a(),r(2))},encapsulation:2});let t=e;return t})();export{d as LazyMultipleCComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-FDEO2DTO.js: -------------------------------------------------------------------------------- 1 | import{W as n,cb as o,db as a,mb as r,rb as u}from"./chunk-OJTWMRHI.js";var d=(()=>{let e=class e{};e.\u0275fac=function(i){return new(i||e)},e.\u0275cmp=n({type:e,selectors:[["lazy-accordion-content-a"]],standalone:!0,features:[u],decls:2,vars:0,template:function(i,s){i&1&&(o(0,"p"),r(1,"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"),a())},encapsulation:2});let t=e;return t})();export{d as LazyAccordionContentAComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-FQ7G2Z4C.js: -------------------------------------------------------------------------------- 1 | import{a as _}from"./chunk-DOMWCVYK.js";import{d as S,e as E,f as g}from"./chunk-5XD2OXE3.js";import{a as C}from"./chunk-SH32YSIN.js";import{a as D}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as m,Sa as l,Ua as d,Va as c,W as a,ab as p,cb as n,db as i,eb as f,mb as e,nb as x,rb as h,sb as s,tb as u}from"./chunk-OJTWMRHI.js";var I=()=>[E,import("./chunk-NJOMRXVD.js").then(t=>t.LazyOnInteractionComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(t=>t.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(t=>t.HighlightDirective)];function v(t,o){t&1&&(n(0,"lazy-on-interaction")(1,"article"),e(2," some "),n(3,"code"),e(4,"@defer (on interaction)"),i(),e(5," content "),i()(),n(6,"lazy-shared")(7,"article"),e(8," some "),n(9,"code"),e(10,"@defer (on interaction)"),i(),e(11," content "),i()(),n(12,"non-standalone")(13,"article"),e(14," some "),n(15,"code"),e(16,"@defer (on interaction)"),i(),e(17," content "),i()(),n(18,"h2"),e(19,"pipe"),i(),e(20),s(21,"StUpIdCaSe"),n(22,"h2"),e(23,"directive"),i(),n(24,"div",2),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),i()),t&2&&(m(20),x(" ",u(21,1,"Lazy loaded pipe here")," "))}function w(t,o){t&1&&f(0,"loader")}function O(t,o){t&1&&(n(0,"app-button"),e(1,"\u{1F449} "),n(2,"strong"),e(3,"interact with me"),i(),e(4," (the placeholder) to load content \u{1F448}"),i())}function z(t,o){t&1&&e(0," something went wrong! ")}var U=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=a({type:o,selectors:[["defer-on-interaction"]],standalone:!0,features:[h],decls:18,vars:0,consts:[[1e3,100],[500],["highlight",""]],template:function(r,L){r&1&&(n(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),n(3,"code"),e(4,"interaction"),i(),e(5," will trigger the deferred block when the user interacts with the specified element through "),n(6,"code"),e(7,"click"),i(),e(8," or "),n(9,"code"),e(10,"keydown"),i(),e(11," events."),i()(),l(12,v,26,3)(13,w,1,0)(14,O,5,0)(15,z,1,0),c(16,12,I,13,14,15,0,1,d),p(0,-1))},dependencies:[S,g,D,C,_],encapsulation:2});let t=o;return t})();export{U as DeferOnInteractionComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-G5I3UZZN.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as r,db as i,jb as a,kb as c,mb as s,rb as l}from"./chunk-OJTWMRHI.js";var f=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-error"]],standalone:!0,features:[l],ngContentSelectors:f,decls:3,vars:0,template:function(n,m){n&1&&(a(),r(0,"h2"),s(1,"lazy-error"),i(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyErrorComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-H5L4WFXW.js: -------------------------------------------------------------------------------- 1 | import{a as b,b as E,c as w,d as _,e as y,f as M}from"./chunk-5XD2OXE3.js";import{a as v}from"./chunk-SH32YSIN.js";import{a as D}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as r,Pa as m,Sa as c,Ua as s,Va as h,W as a,Wa as p,cb as i,db as n,eb as f,hb as x,mb as e,nb as u,rb as C,sb as g,tb as S}from"./chunk-OJTWMRHI.js";var T=()=>[y,import("./chunk-PEUG7PPS.js").then(t=>t.LazyWhenConditionComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(t=>t.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(t=>t.HighlightDirective)];function W(t,o){t&1&&(i(0,"lazy-when-condition")(1,"article"),e(2," some "),i(3,"code"),e(4,"@defer (when isVisible)"),n(),e(5," content "),n()(),i(6,"lazy-shared")(7,"article"),e(8," some "),i(9,"code"),e(10,"@defer (when isVisible)"),n(),e(11," content "),n()(),i(12,"non-standalone")(13,"article"),e(14," some "),i(15,"code"),e(16,"@defer (when isVisible)"),n(),e(17," content "),n()(),i(18,"h2"),e(19,"pipe"),n(),e(20),g(21,"StUpIdCaSe"),i(22,"h2"),e(23,"directive"),n(),i(24,"div",3),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),n()),t&2&&(r(20),u(" ",S(21,1,"Lazy loaded pipe here")," "))}function z(t,o){t&1&&f(0,"loader")}function F(t,o){t&1&&(e(0," placeholder is shown before "),i(1,"code"),e(2,"@defer"),n(),e(3," is triggered "))}function L(t,o){t&1&&e(0," something went wrong! ")}var q=(()=>{let o=class o{constructor(){this.isVisible=!1}};o.\u0275fac=function(l){return new(l||o)},o.\u0275cmp=a({type:o,selectors:[["defer-when-condition"]],standalone:!0,features:[C],decls:31,vars:2,consts:[["type","checkbox",3,"ngModel","ngModelChange"],[1e3,100],[500],["highlight",""]],template:function(l,d){l&1&&(i(0,"app-box")(1,"content"),e(2,"\u{1F4DA} if the "),i(3,"code"),e(4,"when"),n(),e(5," condition switches back to "),i(6,"code"),e(7,"false"),n(),e(8,", the defer block is "),i(9,"strong"),e(10,"not reverted back"),n(),e(11," to the placeholder. The swap is a one-time operation. If the content within the block should be conditionally rendered, an "),i(12,"code"),e(13,"if"),n(),e(14," condition can be used within the block itself."),n(),i(15,"content"),e(16,"\u{1F590}\uFE0F toggle the checkbox; when checked, the "),i(17,"code"),e(18,"@defer (when isVisible)"),n(),e(19," condition will switch to true."),n(),i(20,"div")(21,"label")(22,"input",0),x("ngModelChange",function(k){return d.isVisible=k}),n(),i(23,"code"),e(24,"isVisible"),n()()()(),c(25,W,26,3)(26,z,1,0)(27,F,4,0)(28,L,1,0),h(29,25,T,26,27,28,1,2,s)),l&2&&(r(22),m("ngModel",d.isVisible),r(7),p(d.isVisible))},dependencies:[_,b,E,w,M,D,v],encapsulation:2});let t=o;return t})();export{q as DeferWhenConditionComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-II6QMHP6.js: -------------------------------------------------------------------------------- 1 | import{d as p,f as D}from"./chunk-5XD2OXE3.js";import{a as u}from"./chunk-SH32YSIN.js";import"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Sa as m,Ua as a,Va as l,W as d,Za as f,ab as s,cb as o,db as i,mb as t,rb as c}from"./chunk-OJTWMRHI.js";var h=()=>[import("./chunk-AICA3QS6.js").then(e=>e.ButtonComponent),import("./chunk-S55KTJ74.js").then(e=>e.LazyNestedComponent)],x=()=>[import("./chunk-3FNJ2ZMJ.js").then(e=>e.LazyNestedFurtherComponent)];function C(e,n){e&1&&(o(0,"lazy-nested-further")(1,"article"),t(2," some "),o(3,"code"),t(4,"@defer (on interaction)"),i(),t(5," content "),i()())}function g(e,n){e&1&&(o(0,"app-button"),t(1,"\u{1F449} interact with me (the placeholder) to load content \u{1F448}"),i())}function S(e,n){e&1&&(o(0,"lazy-nested")(1,"article"),t(2," some "),o(3,"code"),t(4,"@defer (on timer(2s))"),i(),t(5," content "),m(6,C,6,0)(7,g,2,0),l(8,6,x,null,7,null,null,0,a),s(0,-1),i()())}function y(e,n){e&1&&t(0," waiting 2s... ")}var L=(()=>{let n=class n{};n.\u0275fac=function(r){return new(r||n)},n.\u0275cmp=d({type:n,selectors:[["defer-nested"]],standalone:!0,features:[c],decls:12,vars:0,consts:[[500]],template:function(r,E){r&1&&(o(0,"app-box")(1,"content"),t(2,"\u{1F4DA} When you have "),o(3,"strong"),t(4,"nested"),i(),o(5,"code"),t(6,"@defer"),i(),t(7," blocks, make sure that an inner one has a different set of conditions, so that they don't trigger at the same time, causing cascading requests."),i()(),m(8,S,10,0)(9,y,1,0),l(10,8,h,null,9,null,null,0,a),f(2e3))},dependencies:[p,D,u],encapsulation:2});let e=n;return e})();export{L as DeferNestedComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-KEPCVLWQ.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as c,mb as l,rb as s}from"./chunk-OJTWMRHI.js";var d=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-idle"]],standalone:!0,features:[s],ngContentSelectors:d,decls:3,vars:0,template:function(n,f){n&1&&(r(),i(0,"h2"),l(1,"lazy-on-idle"),a(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnIdleComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-KYJRYBID.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as r,jb as a,kb as c,mb as s,rb as p}from"./chunk-OJTWMRHI.js";var f=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-viewport"]],standalone:!0,features:[p],ngContentSelectors:f,decls:3,vars:0,template:function(n,m){n&1&&(a(),i(0,"h2"),s(1,"lazy-on-viewport"),r(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnViewportComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-LHI7OLGB.js: -------------------------------------------------------------------------------- 1 | import{b as H,d as S}from"./chunk-427AOKNY.js";import"./chunk-LIVYS4BP.js";import{$ as p,Aa as h,Fa as b,Ha as l,Oa as g,Pa as u,Sa as v,Ta as C,U as d,W as x,aa as m,cb as s,db as r,eb as y,fb as P,hb as _,ib as o,mb as c,rb as M}from"./chunk-OJTWMRHI.js";function w(n,e){if(n&1){let t=P();s(0,"div",2)(1,"ul",3)(2,"li",4)(3,"a",5),_("click",function(){return p(t),o().activePanelId.set("html"),m(!1)}),c(4," HTML "),r()(),s(5,"li",4)(6,"a",6),_("click",function(){return p(t),o().activePanelId.set("ts"),m(!1)}),c(7," TS "),r()()(),s(8,"div",7),y(9,"div",8)(10,"div",9),r()()}if(n&2){let t=o();l(2),g("aria-selected",t.activePanelId()==="html"),l(3),g("aria-selected",t.activePanelId()==="ts"),l(4),u("innerHTML",t.snippets().htmlHtml,h)("hidden",t.activePanelId()!=="html"),l(1),u("innerHTML",t.snippets().tsHtml,h)("hidden",t.activePanelId()!=="ts")}}function T(){let n=d(S),e=d(H),t=b({tsHtml:"",htmlHtml:""});return Promise.all([fetch(`/angular-defer/assets/snippets${n.url}/ts.html`).then(i=>i.text()),fetch(`/angular-defer/assets/snippets${n.url}/html.html`).then(i=>i.text())]).then(([i,a])=>{t.set({tsHtml:e.bypassSecurityTrustHtml(i),htmlHtml:e.bypassSecurityTrustHtml(a)})}),t.asReadonly()}var z=(()=>{let e=class e{constructor(){this.snippets=T(),this.activePanelId=b("html")}};e.\u0275fac=function(a){return new(a||e)},e.\u0275cmp=x({type:e,selectors:[["app-snippet-dialog-content"]],standalone:!0,features:[M],decls:3,vars:1,consts:[["id","tabs-title",1,"sr-only"],["class","tabs-container"],[1,"tabs-container"],["aria-labelledby","tabs-title","role","tablist"],["role","tab"],["id","html-tab","href","#html",3,"click"],["id","ts-tab","href","#ts",3,"click"],[1,"tabs-panels"],["id","html","aria-labelledby","html-tab",3,"innerHTML","hidden"],["id","ts","aria-labelledby","ts-tab",3,"innerHTML","hidden"]],template:function(a,f){a&1&&(s(0,"span",0),c(1,"Snippet Tabs"),r(),v(2,w,11,6,"div",1)),a&2&&(l(2),C(2,f.snippets().tsHtml&&f.snippets().htmlHtml?2:-1))},styles:[".sr-only[_ngcontent-%COMP%]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}[_nghost-%COMP%]{flex:1}.tabs-container[_ngcontent-%COMP%]{height:100%;display:flex;flex-direction:column}.tabs-panels[_ngcontent-%COMP%]{flex:1}.tabs-panels[_ngcontent-%COMP%] > div[_ngcontent-%COMP%]{height:100%}.tabs-panels[_ngcontent-%COMP%] > div[_ngcontent-%COMP%] pre{overflow:auto;padding:1rem;height:98%}[role=tablist][_ngcontent-%COMP%]{display:flex;list-style-type:none;gap:1rem;padding-inline-start:1rem;align-items:center}[role=tab][_ngcontent-%COMP%]{padding:1rem}[aria-selected=true][_ngcontent-%COMP%]{border-radius:.5rem;border:1px solid var(--main-accent-color);box-shadow:3px 3px 5px var(--main-accent-color)}"],changeDetection:0});let n=e;return n})();export{z as SnippetDialogContent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-LJZ5A7MJ.js: -------------------------------------------------------------------------------- 1 | import{a as g}from"./chunk-DOMWCVYK.js";import"./chunk-CKZQZNXB.js";import"./chunk-4KX6UJK3.js";import"./chunk-QJPZIJLW.js";import{d as u,f as D}from"./chunk-5XD2OXE3.js";import{a as x}from"./chunk-SH32YSIN.js";import{a as h}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Sa as a,Ua as c,Va as l,W as m,_a as d,ab as f,cb as t,db as n,eb as p,mb as e,rb as s}from"./chunk-OJTWMRHI.js";var C=()=>[import("./chunk-ZNB2FFWI.js").then(i=>i.LazyPrefetchComponent)];function E(i,o){i&1&&(t(0,"lazy-prefetch")(1,"article"),e(2," some content "),n()())}function y(i,o){i&1&&p(0,"loader")}function w(i,o){i&1&&(t(0,"app-button"),e(1,"\u{1F449} "),t(2,"strong"),e(3,"interact with me"),n(),e(4," \u{1F448} "),t(5,"div")(6,"code"),e(7,"prefetch on timer(2s)"),n(),e(8," will start after 2 seconds pass "),n()())}function _(i,o){i&1&&e(0," something went wrong! ")}var H=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=m({type:o,selectors:[["defer-prefetch"]],standalone:!0,features:[s],decls:34,vars:0,consts:[[1e3,100],[500]],template:function(r,P){r&1&&(t(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),t(3,"code"),e(4,"@defer"),n(),e(5," allows to specify conditions when prefetching of the dependencies should be triggered. You can use a special "),t(6,"code"),e(7,"prefetch"),n(),e(8," keyword. "),t(9,"code"),e(10,"prefetch"),n(),e(11," syntax works similarly to the main defer conditions, and accepts "),t(12,"code"),e(13,"when"),n(),e(14," and/or "),t(15,"code"),e(16,"on"),n(),e(17," to declare the trigger."),n(),t(18,"content"),e(19,"\u{1F4A1} Common pattern: "),t(20,"code"),e(21,"@defer (on interaction; prefetch on idle)"),n(),e(22," - display something as the user really needs it, but prefetch when the browser is not busy."),n(),t(23,"content"),e(24,"\u{1F590}\uFE0F loading itself is triggered by interaction in the example below. Prefetching starts "),t(25,"code"),e(26,"on timer(2s)"),n(),e(27,"."),n()(),a(28,E,3,0)(29,y,1,0)(30,w,9,0)(31,_,1,0),l(32,28,C,29,30,31,0,1,c),f(0,-1),d(2e3))},dependencies:[u,D,h,x,g],encapsulation:2});let i=o;return i})();export{H as DeferPrefetchComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-M2XFULLM.js: -------------------------------------------------------------------------------- 1 | import{a as D}from"./chunk-DOMWCVYK.js";import{d as x,f as h}from"./chunk-5XD2OXE3.js";import{a as u}from"./chunk-SH32YSIN.js";import{a as f}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Sa as a,Ua as d,Va as m,W as c,ab as r,cb as t,db as i,eb as s,mb as e,rb as p}from"./chunk-OJTWMRHI.js";var E=()=>[import("./chunk-AWMYU3NT.js").then(n=>n.LazyLoadingVsPlaceholder)],S=()=>[import("./chunk-AWMYU3NT.js").then(n=>n.LazyLoadingVsPlaceholder)];function _(n,o){n&1&&(t(0,"lazy-loading-vs-placeholder")(1,"article"),e(2," some content "),i()())}function C(n,o){n&1&&s(0,"loader")}function L(n,o){n&1&&(t(0,"app-button"),e(1,"\u{1F449} "),t(2,"strong"),e(3,"interact with me \u{1F448}"),i(),t(4,"div")(5,"code"),e(6,"@placeholder (minimum 500ms)"),i(),e(7," / "),t(8,"code"),e(9,"@loading (minimum 1s)"),i()()())}function y(n,o){n&1&&(t(0,"lazy-loading-vs-placeholder")(1,"article"),e(2," some content "),i()())}function v(n,o){n&1&&s(0,"loader")}function P(n,o){n&1&&(t(0,"app-button"),e(1,"\u{1F449} "),t(2,"strong"),e(3,"interact with me"),i(),e(4," \u{1F448} "),t(5,"div")(6,"code"),e(7,"@placeholder (minimum 500ms)"),i(),e(8," / "),t(9,"code"),e(10,"@loading (minimum 1s; after 100ms)"),i()()())}var M=(()=>{let o=class o{};o.\u0275fac=function(l){return new(l||o)},o.\u0275cmp=c({type:o,selectors:[["defer-loading-vs-placeholder"]],standalone:!0,features:[p],decls:69,vars:0,consts:[[1e3],[500],[1e3,100]],template:function(l,w){l&1&&(t(0,"app-box")(1,"content"),e(2,"\u{1F914} do "),t(3,"code"),e(4,"@placeholder"),i(),e(5," and "),t(6,"code"),e(7,"@loading"),i(),e(8," sound too familiar to each other?"),i(),t(9,"content"),e(10,"\u{1F4A1} TL;DR; "),t(11,"code"),e(12,"@placeholder"),i(),e(13," is shown "),t(14,"strong"),e(15,"BEFORE"),i(),e(16," loading starts, whereas "),t(17,"code"),e(18,"@loading"),i(),e(19," is shown "),t(20,"strong"),e(21,"WHILE"),i(),e(22," the lazy chunk is being loaded"),i(),t(23,"content"),e(24,"\u{1F590}\uFE0F demo below includes "),t(25,"code"),e(26,"@placeholder (minimum 500ms)"),i(),e(27," & "),t(28,"code"),e(29,"@loading (minimum 1s; after 10ms)"),i(),e(30,". The "),t(31,"code"),e(32,"@placeholder"),i(),e(33," is displayed before loading is triggered (via "),t(34,"code"),e(35,"interaction"),i(),e(36,"). Once loading is triggered, "),t(37,"code"),e(38,"@loading"),i(),e(39," will displayed for at least 1s ("),t(40,"code"),e(41,"minimum 1s"),i(),e(42,"). But there are 2 examples: in the first one "),t(43,"code"),e(44,"@loading"),i(),e(45," is displayed with no conditions; in the second one "),t(46,"strong"),e(47,"loading"),i(),e(48," has to last at least 100ms ("),t(49,"code"),e(50,"after 100ms"),i(),e(51,") until its shown."),i(),t(52,"content"),e(53,"\u{1F4A1} it's user-friendly to avoid blinking loaders (show up and immediately disappear), so most of the times you'd like to use the "),t(54,"code"),e(55,"after 100ms"),i(),e(56," or so."),i()(),t(57,"div"),a(58,_,3,0)(59,C,1,0)(60,L,10,0),m(61,58,E,59,60,null,0,1,d),r(0,-1),i(),t(63,"div"),a(64,y,3,0)(65,v,1,0)(66,P,11,0),m(67,64,S,65,66,null,2,1,d),r(0,-1),i())},dependencies:[x,h,f,u,D],encapsulation:2});let n=o;return n})();export{M as DeferLoadingVsPlaceholderComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-NJOMRXVD.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as c,mb as s,rb as l}from"./chunk-OJTWMRHI.js";var f=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-on-interaction"]],standalone:!0,features:[l],ngContentSelectors:f,decls:3,vars:0,template:function(n,m){n&1&&(r(),i(0,"h2"),s(1,"lazy-on-interaction"),a(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyOnInteractionComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-OEUOV4Z3.js: -------------------------------------------------------------------------------- 1 | import"./chunk-DOMWCVYK.js";import{d as D,e as E,f as C}from"./chunk-5XD2OXE3.js";import{a as g}from"./chunk-SH32YSIN.js";import{a as S}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Ha as d,Sa as a,Ua as m,Va as p,W as l,Xa as c,cb as n,db as i,eb as f,mb as e,nb as s,rb as x,sb as h,tb as u}from"./chunk-OJTWMRHI.js";var _=()=>[E,import("./chunk-KEPCVLWQ.js").then(t=>t.LazyOnIdleComponent),import("./chunk-7GWIDXD6.js").then(t=>t.LazySharedComponent),import("./chunk-TJ5IR3FS.js").then(t=>t.StUpIdCaSePipe),import("./chunk-T3KMG43A.js").then(t=>t.HighlightDirective)];function v(t,o){t&1&&(n(0,"lazy-on-idle")(1,"article"),e(2," some "),n(3,"code"),e(4,"@defer (on idle)"),i(),e(5," content "),i()(),n(6,"lazy-shared")(7,"article"),e(8," some "),n(9,"code"),e(10,"@defer (on idle)"),i(),e(11," content "),i()(),n(12,"non-standalone")(13,"article"),e(14," some "),n(15,"code"),e(16,"@defer (on idle)"),i(),e(17," content "),i()(),n(18,"h2"),e(19,"pipe"),i(),e(20),h(21,"StUpIdCaSe"),n(22,"h2"),e(23,"directive"),i(),n(24,"div",3),e(25,"lazy loaded directive - I'm highlighted lol \u{1F979}"),i()),t&2&&(d(20),s(" ",u(21,1,"Lazy loaded pipe here")," "))}function y(t,o){t&1&&f(0,"loader")}function b(t,o){t&1&&(e(0," just wait for "),n(1,"strong"),e(2,"idle"),i(),e(3,"... "))}function w(t,o){t&1&&e(0," something went wrong! ")}var B=(()=>{let o=class o{};o.\u0275fac=function(r){return new(r||o)},o.\u0275cmp=l({type:o,selectors:[["defer-on-idle"]],standalone:!0,features:[x],decls:29,vars:0,consts:[["href","https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback"],[1e3,100],[500],["highlight",""]],template:function(r,z){r&1&&(n(0,"app-box")(1,"content"),e(2,"\u{1F4DA} "),n(3,"code"),e(4,"idle"),i(),e(5," will trigger the deferred loading once the browser "),n(6,"strong"),e(7,"has reached an idle state"),i(),e(8," (detected using the "),n(9,"a",0),e(10,"requestIdleCallback"),i(),e(11," API under the hood). "),n(12,"strong"),e(13,"This is the default behavior"),i(),e(14," with a defer block."),i(),n(15,"content"),e(16,"\u{1F4DA} "),n(17,"code"),e(18,"idle"),i(),e(19," trigger "),n(20,"strong"),e(21,"cannot have parameters"),i(),e(22,"."),i()(),a(23,v,26,3)(24,y,1,0)(25,b,4,0)(26,w,1,0),p(27,23,_,24,25,26,1,2,m),c())},dependencies:[D,C,S,g],encapsulation:2});let t=o;return t})();export{B as DeferOnIdleComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-PEUG7PPS.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as c,kb as r,mb as s,rb as l}from"./chunk-OJTWMRHI.js";var d=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-when-condition"]],standalone:!0,features:[l],ngContentSelectors:d,decls:3,vars:0,template:function(n,f){n&1&&(c(),i(0,"h2"),s(1,"lazy-when-condition"),a(),r(2))},encapsulation:2});let t=e;return t})();export{u as LazyWhenConditionComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-QJPZIJLW.js: -------------------------------------------------------------------------------- 1 | import{Ca as i,Ia as n,Y as r}from"./chunk-OJTWMRHI.js";var c=e=>getComputedStyle(document.documentElement).getPropertyValue(e),a=(()=>{let t=class t{constructor(o){this.colors=["--orange-red","--vivid-pink","--electric-violet"].map(c),this.changeColor(o)}changeColor(o){o.nativeElement.style.color=this.colors[Math.floor(Math.random()*this.colors.length)],setInterval(()=>{o.nativeElement.style.color=this.colors[Math.floor(Math.random()*this.colors.length)]},500)}};t.\u0275fac=function(l){return new(l||t)(n(i))},t.\u0275dir=r({type:t,selectors:[["","highlight",""]],standalone:!0});let e=t;return e})();export{a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-RURXA3RU.js: -------------------------------------------------------------------------------- 1 | import{W as i,cb as o,db as d,eb as a,rb as s}from"./chunk-OJTWMRHI.js";var g=(()=>{let n=class n{};n.\u0275fac=function(e){return new(e||n)},n.\u0275cmp=i({type:n,selectors:[["loader"]],standalone:!0,features:[s],decls:13,vars:0,consts:[[1,"lds-spinner"]],template:function(e,l){e&1&&(o(0,"div",0),a(1,"div")(2,"div")(3,"div")(4,"div")(5,"div")(6,"div")(7,"div")(8,"div")(9,"div")(10,"div")(11,"div")(12,"div"),d())},styles:['.lds-spinner[_ngcontent-%COMP%]{color:official;display:inline-block;position:relative;width:80px;height:80px}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]{transform-origin:40px 40px;animation:_ngcontent-%COMP%_lds-spinner 1.2s linear infinite}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:after{content:" ";display:block;position:absolute;top:3px;left:37px;width:6px;height:18px;border-radius:20%;background:var(--vivid-pink)}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(1){transform:rotate(0);animation-delay:-1.1s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(2){transform:rotate(30deg);animation-delay:-1s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(3){transform:rotate(60deg);animation-delay:-.9s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(4){transform:rotate(90deg);animation-delay:-.8s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(5){transform:rotate(120deg);animation-delay:-.7s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(6){transform:rotate(150deg);animation-delay:-.6s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(7){transform:rotate(180deg);animation-delay:-.5s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(8){transform:rotate(210deg);animation-delay:-.4s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(9){transform:rotate(240deg);animation-delay:-.3s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(10){transform:rotate(270deg);animation-delay:-.2s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(11){transform:rotate(300deg);animation-delay:-.1s}.lds-spinner[_ngcontent-%COMP%] div[_ngcontent-%COMP%]:nth-child(12){transform:rotate(330deg);animation-delay:0s}@keyframes _ngcontent-%COMP%_lds-spinner{0%{opacity:1}to{opacity:0}}']});let t=n;return t})();export{g as a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-S55KTJ74.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as s,mb as c,rb as l}from"./chunk-OJTWMRHI.js";var d=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-nested"]],standalone:!0,features:[l],ngContentSelectors:d,decls:3,vars:0,template:function(n,f){n&1&&(r(),i(0,"h2"),c(1,"lazy-nested"),a(),s(2))},encapsulation:2});let t=e;return t})();export{u as LazyNestedComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-SH32YSIN.js: -------------------------------------------------------------------------------- 1 | import{h as p}from"./chunk-LIVYS4BP.js";import{W as n,cb as r,db as a,jb as i,kb as c,rb as d}from"./chunk-OJTWMRHI.js";var l=["*"],x=(()=>{let e=class e{};e.\u0275fac=function(t){return new(t||e)},e.\u0275cmp=n({type:e,selectors:[["app-box"]],standalone:!0,features:[d],ngContentSelectors:l,decls:2,vars:0,template:function(t,m){t&1&&(i(),r(0,"div"),c(1),a())},dependencies:[p],styles:["[_nghost-%COMP%]{display:block;max-width:75%;margin:10px;padding:10px;border-radius:6px;background-color:var(--main-background-color);border:1px solid var(--main-accent-color);box-shadow:3px 3px 5px var(--main-accent-color)}"]});let o=e;return o})();export{x as a}; 2 | -------------------------------------------------------------------------------- /docs/chunk-SXNGXTZF.js: -------------------------------------------------------------------------------- 1 | import{a as E}from"./chunk-SH32YSIN.js";import"./chunk-LIVYS4BP.js";import{$a as g,Ca as x,Sa as p,U as h,Va as f,W as v,Za as u,c,cb as n,d as s,db as o,eb as _,hb as C,mb as t,rb as y}from"./chunk-OJTWMRHI.js";var k=()=>[import("./chunk-FDEO2DTO.js").then(e=>e.LazyAccordionContentAComponent)],S=()=>[import("./chunk-DN5YT25O.js").then(e=>e.LazyAccordionContentBComponent)],A=()=>[import("./chunk-XHH54KLV.js").then(e=>e.LazyAccordionContentCComponent)];function O(e,i){e&1&&_(0,"lazy-accordion-content-a")}function T(e,i){e&1&&_(0,"lazy-accordion-content-b")}function w(e,i){e&1&&_(0,"lazy-accordion-content-c")}var P=(()=>{var i,d,l;let r=class r{constructor(){s(this,i,h(x));s(this,d,c(this,i).nativeElement.getElementsByClassName("accordion"));s(this,l,c(this,i).nativeElement.getElementsByClassName("panel"))}toggleVisible(m){c(this,d)[m].classList.toggle("active");for(let a of c(this,l))a.style.display="none";c(this,l)[m].style.display="block"}};i=new WeakMap,d=new WeakMap,l=new WeakMap,r.\u0275fac=function(a){return new(a||r)},r.\u0275cmp=v({type:r,selectors:[["defer-accordion"]],standalone:!0,features:[y],decls:42,vars:0,consts:[[1,"accordion-content"],[1,"accordion",3,"click"],["accordionA",""],[1,"panel"],["accordionB",""],["accordionC",""]],template:function(a,b){a&1&&(n(0,"app-box")(1,"content"),t(2,"\u{1F590}\uFE0F each accordion section uses: "),n(3,"code"),t(4,"@defer (on hover(accordion); on timer(5s))"),o(),t(5,":"),n(6,"ul")(7,"li"),t(8,"when "),n(9,"strong"),t(10,"two (or more) different triggers"),o(),t(11," are declared, the first one that takes place triggers actual loading"),o(),n(12,"li"),t(13,"accordion section could start loading on "),n(14,"strong"),t(15,"interaction"),o(),t(16," (when clicked), but loading on "),n(17,"strong"),t(18,"hover"),o(),t(19," is usually better, since loading will start before the user actually clicks it."),o()()()(),n(20,"section",0)(21,"button",1,2),C("click",function(){return b.toggleVisible(0)}),t(23,"Section A"),o(),n(24,"div",3),p(25,O,1,0),f(26,25,k),u(5e3),g(21),o(),n(28,"button",1,4),C("click",function(){return b.toggleVisible(1)}),t(30,"Section B"),o(),n(31,"div",3),p(32,T,1,0),f(33,32,S),u(5e3),g(28),o(),n(35,"button",1,5),C("click",function(){return b.toggleVisible(2)}),t(37,"Section C"),o(),n(38,"div",3),p(39,w,1,0),f(40,39,A),u(5e3),g(35),o()())},dependencies:[E],styles:[".accordion[_ngcontent-%COMP%]{background-color:var(--main-background-color);color:var(--text-color);cursor:pointer;padding:18px;width:100%;text-align:left;border:none;outline:none;transition:.4s}.active[_ngcontent-%COMP%], .accordion[_ngcontent-%COMP%]:hover{background-color:var(--secondary-background-color)}.panel[_ngcontent-%COMP%]{padding:0 18px;background-color:var(--main-background-color);display:none;overflow:hidden}.accordion-content[_ngcontent-%COMP%]{margin:10px;width:75%}"]});let e=r;return e})();export{P as DeferAccordionComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-T3KMG43A.js: -------------------------------------------------------------------------------- 1 | import{a}from"./chunk-QJPZIJLW.js";import"./chunk-OJTWMRHI.js";export{a as HighlightDirective}; 2 | -------------------------------------------------------------------------------- /docs/chunk-TJ5IR3FS.js: -------------------------------------------------------------------------------- 1 | import{a}from"./chunk-4KX6UJK3.js";import"./chunk-OJTWMRHI.js";export{a as StUpIdCaSePipe}; 2 | -------------------------------------------------------------------------------- /docs/chunk-UKHOVCAU.js: -------------------------------------------------------------------------------- 1 | import{a as E}from"./chunk-DOMWCVYK.js";import{d as p,f as x}from"./chunk-5XD2OXE3.js";import{a as D}from"./chunk-SH32YSIN.js";import{a as s}from"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Sa as m,Ua as a,Va as d,W as l,ab as f,cb as t,db as r,eb as c,mb as e,rb as u}from"./chunk-OJTWMRHI.js";var g=()=>[import("./chunk-G5I3UZZN.js").then(n=>n.LazyErrorComponent)];function C(n,i){n&1&&(t(0,"lazy-error")(1,"article"),e(2," some "),t(3,"code"),e(4,"@defer (on idle)"),r(),e(5," content "),r()())}function S(n,i){n&1&&c(0,"loader")}function _(n,i){n&1&&(t(0,"app-button"),e(1,"\u{1F449} "),t(2,"strong"),e(3,"interact with me"),r(),e(4," \u{1F448}"),r())}function y(n,i){n&1&&e(0," something went wrong! \u{1F62D} ")}var M=(()=>{let i=class i{};i.\u0275fac=function(o){return new(o||i)},i.\u0275cmp=l({type:i,selectors:[["defer-nested"]],standalone:!0,features:[u],decls:30,vars:0,consts:[["href","https://github.com/angular/angular/issues/52800"],[1e3,100],[500]],template:function(o,w){o&1&&(t(0,"app-box")(1,"content"),e(2,"\u{1F4DA} The "),t(3,"code"),e(4,"@error"),r(),e(5," block allows you to declare content that will be shown if deferred loading fails."),r(),t(6,"content"),e(7,"\u{1F590}\uFE0F first, trigger HTTP request failure within your devtools: "),t(8,"em"),e(9,"Network"),r(),e(10," tab -> right-click on one of the dynamic chunks loaded -> "),t(11,"strong"),e(12,"Block request URL/domain"),r(),e(13," -> and now trigger "),t(14,"code"),e(15,"@defer"),r()(),t(16,"content"),e(17,"\u{1F170}\uFE0F Currently there's no built-in "),t(18,"code"),e(19,"retry"),r(),e(20," option available. More info in "),t(21,"a",0),e(22,"this GH issue"),r(),e(23,"."),r()(),m(24,C,6,0)(25,S,1,0)(26,_,5,0)(27,y,1,0),d(28,24,g,25,26,27,1,2,a),f(0,-1))},dependencies:[p,x,s,D,E],encapsulation:2});let n=i;return n})();export{M as DeferErrorComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-UXHIX3CP.js: -------------------------------------------------------------------------------- 1 | import{a as D}from"./chunk-DOMWCVYK.js";import{d,f}from"./chunk-5XD2OXE3.js";import{a as s}from"./chunk-SH32YSIN.js";import"./chunk-RURXA3RU.js";import"./chunk-LIVYS4BP.js";import{Sa as r,Ua as a,Va as p,W as m,ab as u,cb as n,db as i,mb as t,rb as c}from"./chunk-OJTWMRHI.js";var C=()=>[import("./chunk-Y462ALH4.js").then(e=>e.LazyMultipleAComponent),import("./chunk-YZGQRNTL.js").then(e=>e.LazyMultipleBComponent),import("./chunk-F4UHNG5O.js").then(e=>e.LazyMultipleCComponent)];function y(e,o){e&1&&(n(0,"lazy-multiple-a")(1,"article"),t(2," some content "),i()(),n(3,"lazy-multiple-b")(4,"article"),t(5," some content "),i()(),n(6,"lazy-multiple-c")(7,"article"),t(8," some content "),i()())}function h(e,o){e&1&&(n(0,"app-button"),t(1,"\u{1F449} "),n(2,"strong"),t(3,"interact with me"),i(),t(4," \u{1F448}"),i())}var g=(()=>{let o=class o{};o.\u0275fac=function(l){return new(l||o)},o.\u0275cmp=m({type:o,selectors:[["defer-multiple"]],standalone:!0,features:[c],decls:12,vars:0,consts:[[500]],template:function(l,E){l&1&&(n(0,"app-box")(1,"content"),t(2,"\u{1F4DA} When you have multiple deferrable components (or directives, pipes) in a "),n(3,"code"),t(4,"@defer"),i(),t(5," block, their chunks would be loaded simultaneously"),i(),n(6,"content"),t(7,"\u{1F590}\uFE0F Actually, many examples on this site embed multiple deferrable items \u{1F609}"),i()(),r(8,y,9,0)(9,h,5,0),p(10,8,C,null,9,null,null,0,a),u(0,-1))},dependencies:[d,f,s,D],encapsulation:2});let e=o;return e})();export{g as DeferMultipleComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-X23RBJFR.js: -------------------------------------------------------------------------------- 1 | import{c as x}from"./chunk-427AOKNY.js";import"./chunk-LIVYS4BP.js";import{$ as p,Ha as f,Sa as u,Ta as C,Ua as b,Va as h,W as _,Xa as k,aa as m,ba as n,ca as l,cb as o,db as i,eb as r,fb as v,hb as g,lb as s,mb as w,rb as M}from"./chunk-OJTWMRHI.js";var P=()=>[import("./chunk-LHI7OLGB.js").then(e=>e.SnippetDialogContent)];function D(e,t){e&1&&(n(),l(),r(0,"app-snippet-dialog-content"))}function T(e,t){e&1&&(n(),l(),o(0,"p"),w(1,"Loading snippets..."),i())}function V(e,t){e&1&&(n(),u(0,D,1,0)(1,T,2,0),h(2,0,P,1,null,null,6,null,b),k())}var E=(()=>{let t=class t{};t.\u0275fac=function(a){return new(a||t)},t.\u0275cmp=_({type:t,selectors:[["ng-component"]],hostAttrs:[1,"use-case-container"],standalone:!0,features:[M],decls:10,vars:1,consts:[[1,"code-btn",3,"click"],["xmlns","http://www.w3.org/2000/svg","fill","none","viewBox","0 0 24 24","stroke-width","1.5","stroke","currentColor","data-slot","icon",1,"w-6","h-6"],["stroke-linecap","round","stroke-linejoin","round","d","M17.25 6.75 22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3-4.5 16.5"],["codeDialog",""],["autofocus","",3,"click"],["stroke-linecap","round","stroke-linejoin","round","d","M6 18 18 6M6 6l12 12"],[500,60]],template:function(a,y){if(a&1){let c=v();r(0,"router-outlet"),o(1,"button",0),g("click",function(){p(c);let d=s(5);return m(d.showModal())}),n(),o(2,"svg",1),r(3,"path",2),i()(),l(),o(4,"dialog",null,3)(6,"button",4),g("click",function(){p(c);let d=s(5);return m(d.close())}),n(),o(7,"svg",1),r(8,"path",5),i()(),u(9,V,4,0),i()}if(a&2){let c=s(5);f(9),C(9,c.open?9:-1)}},dependencies:[x],styles:["button[_ngcontent-%COMP%]{cursor:pointer;padding:.5rem;border-radius:.5rem;background:-webkit-linear-gradient(var(--angle),var(--orange-red) 0%,var(--vivid-pink) 50%,var(--electric-violet) 100%);-webkit-background-clip:text;-moz-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;-moz-text-fill-color:transparent}button.code-btn[_ngcontent-%COMP%]{position:absolute;bottom:1rem;right:1rem}button[_ngcontent-%COMP%] svg[_ngcontent-%COMP%]{width:2rem;height:2rem;color:var(--main-accent-color);stroke-width:2}dialog[_ngcontent-%COMP%]{position:relative;overflow:clip;height:80%;width:80%;border-radius:.5rem;background-color:var(--main-background-color);border:1px solid var(--main-accent-color);box-shadow:3px 3px 5px var(--main-accent-color)}dialog[_ngcontent-%COMP%]:has([open]){display:flex;flex-direction:column}dialog[_ngcontent-%COMP%] button[_ngcontent-%COMP%]{position:absolute;right:1rem}dialog[_ngcontent-%COMP%] button[_ngcontent-%COMP%] svg[_ngcontent-%COMP%]{width:1rem;height:1rem}[_ngcontent-%COMP%]::backdrop{background:#000;opacity:.75}"],changeDetection:0});let e=t;return e})();export{E as default}; 2 | -------------------------------------------------------------------------------- /docs/chunk-XHH54KLV.js: -------------------------------------------------------------------------------- 1 | import{W as a,cb as n,db as o,mb as u,rb as r}from"./chunk-OJTWMRHI.js";var c=(()=>{let e=class e{};e.\u0275fac=function(i){return new(i||e)},e.\u0275cmp=a({type:e,selectors:[["lazy-accordion-content-c"]],standalone:!0,features:[r],decls:2,vars:0,template:function(i,m){i&1&&(n(0,"p"),u(1,"Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?"),o())},encapsulation:2});let t=e;return t})();export{c as LazyAccordionContentCComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-Y462ALH4.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as l,mb as c,rb as s}from"./chunk-OJTWMRHI.js";var m=["*"],d=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-multiple-a"]],standalone:!0,features:[s],ngContentSelectors:m,decls:3,vars:0,template:function(n,f){n&1&&(r(),i(0,"h2"),c(1,"lazy-multiple-a"),a(),l(2))},encapsulation:2});let t=e;return t})();export{d as LazyMultipleAComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-YZGQRNTL.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as a,jb as r,kb as l,mb as c,rb as s}from"./chunk-OJTWMRHI.js";var m=["*"],d=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-multiple-b"]],standalone:!0,features:[s],ngContentSelectors:m,decls:3,vars:0,template:function(n,f){n&1&&(r(),i(0,"h2"),c(1,"lazy-multiple-b"),a(),l(2))},encapsulation:2});let t=e;return t})();export{d as LazyMultipleBComponent}; 2 | -------------------------------------------------------------------------------- /docs/chunk-ZNB2FFWI.js: -------------------------------------------------------------------------------- 1 | import{W as o,cb as i,db as r,jb as a,kb as c,mb as s,rb as p}from"./chunk-OJTWMRHI.js";var f=["*"],u=(()=>{let e=class e{};e.\u0275fac=function(n){return new(n||e)},e.\u0275cmp=o({type:e,selectors:[["lazy-prefetch"]],standalone:!0,features:[p],ngContentSelectors:f,decls:3,vars:0,template:function(n,m){n&1&&(a(),i(0,"h2"),s(1,"lazy-prefetch"),r(),c(2))},encapsulation:2});let t=e;return t})();export{u as LazyPrefetchComponent}; 2 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/angular-defer/46a03f44c6a81e8a3f707165d6eed008d6543278/docs/favicon.ico -------------------------------------------------------------------------------- /docs/styles-CUQVMV3G.css: -------------------------------------------------------------------------------- 1 | @media (prefers-color-scheme: light){:root{--background-color: #ffffff;--text-color: #000000;--angle: 90deg;--orange-red: oklch(63.32% .24 31.68);--vivid-pink: oklch(69.02% .277 332.77);--electric-violet: oklch(53.18% .28 296.97);--main-accent-color: var(--electric-violet);--main-background-color: color-mix( in srgb, var(--electric-violet) 10%, white );--secondary-background-color: color-mix( in srgb, var(--electric-violet) 30%, white )}.shiki.dark-plus{display:none}}@media (prefers-color-scheme: dark){:root{--background-color: #000000;--text-color: #ffffff;--angle: 90deg;--orange-red: oklch(63.32% .24 31.68);--vivid-pink: oklch(69.02% .277 332.77);--electric-violet: oklch(53.18% .28 296.97);--main-accent-color: var(--vivid-pink);--main-background-color: color-mix( in srgb, var(--electric-violet) 30%, black );--secondary-background-color: color-mix( in srgb, var(--electric-violet) 60%, black )}.shiki.light-plus{display:none}}body{color:var(--text-color);background-color:var(--background-color)}:root{font-family:Lato,sans-serif}.angular-gradient{background:-webkit-linear-gradient(var(--angle),var(--orange-red) 0%,var(--vivid-pink) 50%,var(--electric-violet) 100%)}.box{margin:10px;padding:10px;border-radius:6px;background-color:var(--main-background-color);border:1px solid var(--main-accent-color);box-shadow:3px 3px 5px var(--main-accent-color)}code:not(:has(span)){margin-bottom:20px;font-weight:700;background:-webkit-linear-gradient(var(--angle),var(--orange-red) 0%,var(--vivid-pink) 50%,var(--electric-violet) 100%);-webkit-background-clip:text;-moz-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;-moz-text-fill-color:transparent}pre{margin:10px 20px}a{text-decoration:none;color:var(--main-accent-color)}content{display:block;margin:4px 0} 2 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "targetDefaults": { 3 | "build": { 4 | "cache": true, 5 | "dependsOn": ["build-snippets", "^build"], 6 | "inputs": ["production", "^production"] 7 | }, 8 | "build-snippets": { 9 | "cache": true, 10 | "inputs": ["{projectRoot}/src/app/defer-usecases/**/*"] 11 | }, 12 | "test": { 13 | "cache": true, 14 | "inputs": ["default", "^production"] 15 | } 16 | }, 17 | "affected": { 18 | "defaultBase": "main" 19 | }, 20 | "namedInputs": { 21 | "sharedGlobals": [], 22 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 23 | "production": [ 24 | "default", 25 | "!{projectRoot}/tsconfig.spec.json", 26 | "!{projectRoot}/**/*.spec.[jt]s" 27 | ] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-defer", 3 | "author": "Tomasz Ducin ", 4 | "private": true, 5 | "version": "0.0.0", 6 | "node": ">=20.9.0", 7 | "scripts": { 8 | "ng": "ng", 9 | "start": "nx serve", 10 | "build": "nx build", 11 | "build-pages": "rm -rf docs && nx build && mv docs/browser/* docs && cp docs/index.html docs/404.html && rm -rf docs/browser", 12 | "watch": "nx build --watch --configuration development", 13 | "test": "nx test" 14 | }, 15 | "dependencies": { 16 | "@angular/animations": "^17.0.0", 17 | "@angular/common": "^17.0.0", 18 | "@angular/compiler": "^17.0.0", 19 | "@angular/core": "^17.0.0", 20 | "@angular/forms": "^17.0.0", 21 | "@angular/platform-browser": "^17.0.0", 22 | "@angular/platform-browser-dynamic": "^17.0.0", 23 | "@angular/router": "^17.0.0", 24 | "rxjs": "~7.8.0", 25 | "stupid-case": "^1.0.0", 26 | "tslib": "^2.3.0", 27 | "zone.js": "~0.14.2" 28 | }, 29 | "devDependencies": { 30 | "@angular-devkit/build-angular": "^17.0.7", 31 | "@angular-devkit/core": "^17.0.7", 32 | "@angular-devkit/schematics": "^17.0.7", 33 | "@angular/cli": "^17.0.7", 34 | "@angular/compiler-cli": "^17.0.0", 35 | "@nx/angular": "17.2.6", 36 | "@nx/workspace": "17.2.6", 37 | "@schematics/angular": "^17.0.7", 38 | "@types/jasmine": "~5.1.0", 39 | "jasmine-core": "~5.1.0", 40 | "karma": "~6.4.0", 41 | "karma-chrome-launcher": "~3.2.0", 42 | "karma-coverage": "~2.2.0", 43 | "karma-jasmine": "~5.1.0", 44 | "karma-jasmine-html-reporter": "~2.1.0", 45 | "markdown-it": "^14.0.0", 46 | "nx": "17.2.6", 47 | "shiki": "^0.14.7", 48 | "typescript": "~5.2.2" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /project.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "node_modules/nx/schemas/project-schema.json", 3 | "name": "angular-defer", 4 | "projectType": "application", 5 | "generators": {}, 6 | "sourceRoot": "src", 7 | "prefix": "app", 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:application", 11 | "options": { 12 | "outputPath": "dist/angular-defer", 13 | "index": "src/index.html", 14 | "browser": "src/main.ts", 15 | "polyfills": ["zone.js"], 16 | "tsConfig": "tsconfig.app.json", 17 | "assets": ["src/favicon.ico", "src/assets"], 18 | "styles": ["src/styles.css"], 19 | "scripts": [] 20 | }, 21 | "configurations": { 22 | "production": { 23 | "outputPath": "docs", 24 | "baseHref": "/angular-defer/", 25 | "budgets": [ 26 | { 27 | "type": "initial", 28 | "maximumWarning": "500kb", 29 | "maximumError": "1mb" 30 | }, 31 | { 32 | "type": "anyComponentStyle", 33 | "maximumWarning": "2kb", 34 | "maximumError": "4kb" 35 | } 36 | ], 37 | "outputHashing": "all" 38 | }, 39 | "development": { 40 | "optimization": false, 41 | "extractLicenses": false, 42 | "sourceMap": true 43 | } 44 | }, 45 | "defaultConfiguration": "production" 46 | }, 47 | "serve": { 48 | "dependsOn": ["build-snippets"], 49 | "executor": "@angular-devkit/build-angular:dev-server", 50 | "configurations": { 51 | "production": { 52 | "buildTarget": "angular-defer:build:production" 53 | }, 54 | "development": { 55 | "buildTarget": "angular-defer:build:development" 56 | } 57 | }, 58 | "defaultConfiguration": "development" 59 | }, 60 | "build-snippets": { 61 | "command": "node ./scripts/build-code-snippets.mjs" 62 | }, 63 | "extract-i18n": { 64 | "executor": "@angular-devkit/build-angular:extract-i18n", 65 | "options": { 66 | "buildTarget": "angular-defer:build" 67 | } 68 | }, 69 | "test": { 70 | "executor": "@angular-devkit/build-angular:karma", 71 | "options": { 72 | "polyfills": ["zone.js", "zone.js/testing"], 73 | "tsConfig": "tsconfig.spec.json", 74 | "assets": ["src/favicon.ico", "src/assets"], 75 | "styles": ["src/styles.css"], 76 | "scripts": [] 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/app/about.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { LoaderComponent } from './defer-usecases/loader'; 4 | 5 | @Component({ 6 | selector: 'app-about', 7 | standalone: true, 8 | imports: [CommonModule, LoaderComponent], 9 | styles: ` 10 | `, 11 | template: ` 12 |
13 |

about this app

14 | 30 |
31 | ` 32 | }) 33 | export class AboutComponent { 34 | } 35 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig } from '@angular/core'; 2 | import { provideRouter } from '@angular/router'; 3 | 4 | import { routes } from './app.routes'; 5 | 6 | export const appConfig: ApplicationConfig = { 7 | providers: [provideRouter(routes)] 8 | }; 9 | -------------------------------------------------------------------------------- /src/app/box.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | @Component({ 5 | selector: 'app-box', 6 | standalone: true, 7 | imports: [CommonModule], 8 | styles: ` 9 | :host { 10 | display: block; 11 | max-width: 75%; 12 | margin: 10px; 13 | padding: 10px; 14 | border-radius: 6px; 15 | background-color: var(--main-background-color); 16 | border: 1px solid var(--main-accent-color); 17 | box-shadow: 3px 3px 5px var(--main-accent-color); 18 | } 19 | `, 20 | template: ` 21 |
22 | 23 |
24 | ` 25 | }) 26 | export class BoxComponent { 27 | } 28 | -------------------------------------------------------------------------------- /src/app/button.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | @Component({ 5 | selector: 'app-button', 6 | standalone: true, 7 | imports: [CommonModule], 8 | styles: ` 9 | button { 10 | background-color: color-mix(in srgb, var(--vivid-pink) 10%, white); 11 | border-radius: 3px; 12 | border: 1px solid var(--vivid-pink); 13 | box-shadow: rgba(255, 255, 255, .7) 0 1px 0 0 inset; 14 | box-sizing: border-box; 15 | color: var(--vivid-pink); 16 | cursor: pointer; 17 | display: inline-block; 18 | font-weight: 400; 19 | margin: 8px .8em; 20 | outline: none; 21 | padding: 8px .8em; 22 | position: relative; 23 | text-align: center; 24 | text-decoration: none; 25 | user-select: none; 26 | -webkit-user-select: none; 27 | touch-action: manipulation; 28 | vertical-align: baseline; 29 | white-space: nowrap; 30 | } 31 | 32 | button:hover, 33 | button:focus { 34 | background-color: color-mix(in srgb, var(--electric-violet) 10%, white); 35 | color: var(--electric-violet); 36 | border-color: var(--electric-violet); 37 | } 38 | 39 | button:focus { 40 | box-shadow: 0 0 0 4px color-mix(in srgb, var(--electric-violet) 30%, white); 41 | } 42 | 43 | button:active { 44 | background-color: color-mix(in srgb, var(--electric-violet) 10%, white); 45 | color: var(--electric-violet); 46 | border-color: var(--electric-violet); 47 | box-shadow: none; 48 | } 49 | `, 50 | template: ` 51 | 54 | ` 55 | }) 56 | export class ButtonComponent { 57 | } 58 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-accordion.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, inject } from '@angular/core'; 2 | import { BoxComponent } from '../box.component'; 3 | import { LazyAccordionContentAComponent } from './lazy-accordion-content-a'; 4 | import { LazyAccordionContentBComponent } from './lazy-accordion-content-b'; 5 | import { LazyAccordionContentCComponent } from './lazy-accordion-content-c'; 6 | 7 | @Component({ 8 | selector: 'defer-accordion', 9 | standalone: true, 10 | imports: [BoxComponent, LazyAccordionContentAComponent, LazyAccordionContentBComponent, LazyAccordionContentCComponent], 11 | styles: ` 12 | .accordion { 13 | background-color: var(--main-background-color); 14 | color: var(--text-color); 15 | cursor: pointer; 16 | padding: 18px; 17 | width: 100%; 18 | text-align: left; 19 | border: none; 20 | outline: none; 21 | transition: 0.4s; 22 | } 23 | 24 | .active, .accordion:hover { 25 | background-color: var(--secondary-background-color); 26 | } 27 | 28 | .panel { 29 | padding: 0 18px; 30 | background-color: var(--main-background-color); 31 | display: none; 32 | overflow: hidden; 33 | } 34 | 35 | .accordion-content { 36 | margin: 10px; 37 | width: 75%; 38 | } 39 | `, 40 | template: ` 41 | 42 | 🖐️ each accordion section uses: @defer (on hover(accordion); on timer(5s)):
    43 |
  • when two (or more) different triggers are declared, the first one that takes place triggers actual loading
  • 44 |
  • accordion section could start loading on interaction (when clicked), but loading on hover is usually better, since loading will start before the user actually clicks it.
  • 45 |
46 |
47 | 48 |
49 | 50 |
51 | @defer (on hover(accordionA); on timer(5s)){ 52 | 53 | } 54 |
55 | 56 | 57 |
58 | @defer (on hover(accordionB); on timer(5s)){ 59 | 60 | } 61 |
62 | 63 | 64 |
65 | @defer (on hover(accordionC); on timer(5s)){ 66 | 67 | } 68 |
69 |
70 | `, 71 | }) 72 | export class DeferAccordionComponent { 73 | #elementRef = inject(ElementRef); 74 | 75 | #buttons = this.#elementRef.nativeElement.getElementsByClassName('accordion'); 76 | #panels = this.#elementRef.nativeElement.getElementsByClassName('panel'); 77 | 78 | toggleVisible(sectionIndex: number) { 79 | this.#buttons[sectionIndex].classList.toggle('active'); 80 | for (const panel of this.#panels){ 81 | panel.style.display = 'none'; 82 | } 83 | this.#panels[sectionIndex].style.display = 'block'; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-error.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component' 7 | import { LegacyModule } from './legacy/legacy.module'; 8 | import { LazyErrorComponent } from './lazy-error'; 9 | 10 | @Component({ 11 | selector: 'defer-nested', 12 | standalone: true, 13 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyErrorComponent], 14 | template: ` 15 | 16 | 📚 The @error block allows you to declare content that will be shown if deferred loading fails. 17 | 🖐️ first, trigger HTTP request failure within your devtools: Network tab -> right-click on one of the dynamic chunks loaded -> Block request URL/domain -> and now trigger @defer 18 | 🅰️ Currently there's no built-in retry option available. More info in this GH issue. 19 | 20 | 21 | @defer (on interaction) { 22 | 23 |
24 | some @defer (on idle) content 25 |
26 |
27 | 28 | } @placeholder (minimum 500ms) { 29 | 👉 interact with me 👈 30 | } @loading (after 100ms; minimum 1s) { 31 | 32 | } @error { 33 | something went wrong! 😭 34 | } 35 | `, 36 | }) 37 | export class DeferErrorComponent { 38 | } 39 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-loading-vs-placeholder.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LegacyModule } from './legacy/legacy.module'; 8 | import { LazyLoadingVsPlaceholder } from './lazy-loading-vs-placeholder'; 9 | 10 | @Component({ 11 | selector: 'defer-loading-vs-placeholder', 12 | standalone: true, 13 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyLoadingVsPlaceholder], 14 | template: ` 15 | 16 | 🤔 do @placeholder and @loading sound too familiar to each other? 17 | 💡 TL;DR; @placeholder is shown BEFORE loading starts, whereas @loading is shown WHILE the lazy chunk is being loaded 18 | 🖐️ demo below includes @placeholder (minimum 500ms) & @loading (minimum 1s; after 10ms). The @placeholder is displayed before loading is triggered (via interaction). Once loading is triggered, @loading will displayed for at least 1s (minimum 1s). But there are 2 examples: in the first one @loading is displayed with no conditions; in the second one loading has to last at least 100ms (after 100ms) until its shown. 19 | 💡 it's user-friendly to avoid blinking loaders (show up and immediately disappear), so most of the times you'd like to use the after 100ms or so. 20 | 21 | 22 |
23 | @defer (on interaction) { 24 | 25 |
26 | some content 27 |
28 |
29 | } @placeholder (minimum 500ms) { 30 | 👉 interact with me 👈 31 |
32 | @placeholder (minimum 500ms) / @loading (minimum 1s) 33 |
34 | } @loading (minimum 1s) { 35 | 36 | } 37 | 38 |
39 |
40 | 41 | @defer (on interaction) { 42 | 43 |
44 | some content 45 |
46 |
47 | } @placeholder (minimum 500ms) { 48 | 👉 interact with me 👈 49 |
50 | @placeholder (minimum 500ms) / @loading (minimum 1s; after 100ms) 51 |
52 |
53 | } @loading (minimum 1s; after 100ms) { 54 | 55 | } 56 |
57 | `, 58 | }) 59 | export class DeferLoadingVsPlaceholderComponent { 60 | } 61 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-multiple.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyMultipleAComponent } from './lazy-multiple-a'; 8 | import { LazyMultipleBComponent } from './lazy-multiple-b'; 9 | import { LazyMultipleCComponent } from './lazy-multiple-c'; 10 | import { LegacyModule } from './legacy/legacy.module'; 11 | 12 | @Component({ 13 | selector: 'defer-multiple', 14 | standalone: true, 15 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyMultipleAComponent, LazyMultipleBComponent, LazyMultipleCComponent], 16 | template: ` 17 | 18 | 📚 When you have multiple deferrable components (or directives, pipes) in a @defer block, their chunks would be loaded simultaneously 19 | 🖐️ Actually, many examples on this site embed multiple deferrable items 😉 20 | 21 | 22 | @defer (on interaction) { 23 | 24 |
25 | some content 26 |
27 |
28 | 29 |
30 | some content 31 |
32 |
33 | 34 |
35 | some content 36 |
37 |
38 | } @placeholder (minimum 500ms) { 39 | 👉 interact with me 👈 40 | } 41 | `, 42 | }) 43 | export class DeferMultipleComponent { 44 | } 45 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-nested.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyNestedComponent } from './lazy-nested'; 8 | import { LegacyModule } from './legacy/legacy.module'; 9 | import { LazyNestedFurtherComponent } from './lazy-nested-further'; 10 | 11 | @Component({ 12 | selector: 'defer-nested', 13 | standalone: true, 14 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyNestedComponent, LazyNestedFurtherComponent], 15 | template: ` 16 | 17 | 📚 When you have nested @defer blocks, make sure that an inner one has a different set of conditions, so that they don't trigger at the same time, causing cascading requests. 18 | 19 | 20 | @defer (on timer(2s)) { 21 | 22 |
23 | some @defer (on timer(2s)) content 24 | 25 | @defer (on interaction) { 26 | 27 |
28 | some @defer (on interaction) content 29 |
30 |
31 | } @placeholder (minimum 500ms) { 32 | 👉 interact with me (the placeholder) to load content 👈 33 | } 34 | 35 |
36 |
37 | } @placeholder (minimum 500ms) { 38 | waiting 2s... 39 | } 40 | `, 41 | }) 42 | export class DeferNestedComponent { 43 | } 44 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-npm-package.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LegacyModule } from './legacy/legacy.module'; 8 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 9 | 10 | @Component({ 11 | selector: 'defer-npm-package', 12 | standalone: true, 13 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, StUpIdCaSePipe], 14 | template: ` 15 | 16 | 🖐️ only the StUpIdCaSe pipe is a deferrable here (no components). However, it's the only code which uses an external npm package, stupid-case. 17 | 🖐️ follow these steps:
    18 |
  • in the devtools/network, search for the last chunk loaded (the only one loaded within this defer), e.g.
    chunk-DHY7UALU.js
    It will include code which looks like this:
    import {
    19 |   StUpIdCaSePipe
    20 | } from "/chunk-BYHJVGJ4.js";
    21 | export {
    22 |   StUpIdCaSePipe
    23 | };
    In this case, DHY7UALU is the chunk with the pipe, whereas BYHJVGJ4 is the chunk with the npm package.
  • 24 |
  • at the top of network tab, filter requests by BYHJVGJ4 and you'd see the content on the npm package.
  • 25 |
  • 🤔 Now, where/when/who initiated loading it?
  • 26 |
  • Clear the Network request filter and filter by type: Doc (Document, HTML, the index.html file). Scroll to the end of HTML/HEAD where you'd find:
    <link rel="modulepreload" href="chunk-BYHJVGJ4.js">
    Angular is preloading the module for later use in a non-sequential manner (faster) once the document has been created. Read more about modulepreload.
  • 27 |
28 |
29 | 30 | @defer (on interaction) { 31 |

pipe

32 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 33 | } @placeholder (minimum 500ms) { 34 | 👉 interact with me 👈 35 | } 36 | `, 37 | }) 38 | export class DeferNPMPackageComponent { 39 | } 40 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-hover.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyOnHoverComponent } from './lazy-on-hover'; 8 | import { LazySharedComponent } from './lazy-shared'; 9 | import { LegacyModule } from './legacy/legacy.module'; 10 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 11 | import { HighlightDirective } from './highlight.directive'; 12 | 13 | @Component({ 14 | selector: 'defer-on-hover', 15 | standalone: true, 16 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyOnHoverComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 17 | template: ` 18 | 19 | 📚 hover triggers deferred loading when the mouse has hovered over the trigger area. Events used for this are mouseenter and focusin. 20 | 21 | 22 | @defer (on hover) { 23 | 24 |
25 | some @defer (on hover) content 26 |
27 |
28 | 29 |
30 | some @defer (on hover) content 31 |
32 |
33 | 34 |
35 | some @defer (on hover) content 36 |
37 |
38 | 39 |

pipe

40 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 41 | 42 |

directive

43 |
lazy loaded directive - I'm highlighted lol 🥹
44 | } @placeholder (minimum 500ms) { 45 | 👉 hover me (the placeholder) to load content 👈 46 | } @loading (after 100ms; minimum 1s) { 47 | 48 | } @error { 49 | something went wrong! 50 | } 51 | 52 |
...OR
53 | 54 | 👉 hover this guy (element with a template variable) to load content 👈 55 | @defer (on hover(el)) { 56 | 57 |
58 | some @defer (on hover(el)) content 59 |
60 |
61 | 62 |
63 | some @defer (on hover(el)) content 64 |
65 |
66 | 67 |
68 | some @defer (on hover(el)) content 69 |
70 |
71 | } @loading (after 100ms; minimum 1s) { 72 | 73 | } @error { 74 | something went wrong! 75 | } 76 | `, 77 | }) 78 | export class DeferOnHoverComponent { 79 | } 80 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-idle.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyOnIdleComponent } from './lazy-on-idle'; 8 | import { LazySharedComponent } from './lazy-shared'; 9 | import { LegacyModule } from './legacy/legacy.module'; 10 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 11 | import { HighlightDirective } from './highlight.directive'; 12 | 13 | @Component({ 14 | selector: 'defer-on-idle', 15 | standalone: true, 16 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyOnIdleComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 17 | template: ` 18 | 19 | 📚 idle will trigger the deferred loading once the browser has reached an idle state (detected using the requestIdleCallback API under the hood). This is the default behavior with a defer block. 20 | 📚 idle trigger cannot have parameters. 21 | 22 | 23 | @defer (on idle) { 24 | 25 |
26 | some @defer (on idle) content 27 |
28 |
29 | 30 |
31 | some @defer (on idle) content 32 |
33 |
34 | 35 |
36 | some @defer (on idle) content 37 |
38 |
39 | 40 |

pipe

41 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 42 | 43 |

directive

44 |
lazy loaded directive - I'm highlighted lol 🥹
45 | } @placeholder (minimum 500ms) { 46 | just wait for idle... 47 | } @loading (after 100ms; minimum 1s) { 48 | 49 | } @error { 50 | something went wrong! 51 | } 52 | `, 53 | }) 54 | export class DeferOnIdleComponent { 55 | } 56 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-immediate.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { LazySharedComponent } from './lazy-shared'; 7 | import { LazyOnImmediateComponent } from './lazy-on-immediate'; 8 | import { LegacyModule } from './legacy/legacy.module'; 9 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 10 | import { HighlightDirective } from './highlight.directive'; 11 | 12 | @Component({ 13 | selector: 'defer-on-immediate', 14 | standalone: true, 15 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, LazyOnImmediateComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 16 | template: ` 17 | 18 | 📚 immediate triggers the deferred load immediately, meaning once the client has finished rendering, the defer chunk would then start fetching right away. 19 | 20 | 21 | @defer (on immediate) { 22 | 23 |
24 | some @defer (on immediate) content 25 |
26 |
27 | 28 |
29 | some @defer (on immediate) content 30 |
31 |
32 | 33 |
34 | some @defer (on immediate) content 35 |
36 |
37 | 38 |

pipe

39 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 40 | 41 |

directive

42 |
lazy loaded directive - I'm highlighted lol 🥹
43 | } @placeholder (minimum 500ms) { 44 | that should load immediate... 45 | } @loading (after 100ms; minimum 1s) { 46 | 47 | } @error { 48 | something went wrong! 49 | } 50 | `, 51 | }) 52 | export class DeferOnImmediateComponent { 53 | } 54 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-interaction.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyOnInteractionComponent } from './lazy-on-interaction'; 8 | import { LazySharedComponent } from './lazy-shared'; 9 | import { LegacyModule } from './legacy/legacy.module'; 10 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 11 | import { HighlightDirective } from './highlight.directive'; 12 | 13 | @Component({ 14 | selector: 'defer-on-interaction', 15 | standalone: true, 16 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyOnInteractionComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 17 | template: ` 18 | 19 | 📚 interaction will trigger the deferred block when the user interacts with the specified element through click or keydown events. 20 | 21 | 22 | @defer (on interaction) { 23 | 24 |
25 | some @defer (on interaction) content 26 |
27 |
28 | 29 |
30 | some @defer (on interaction) content 31 |
32 |
33 | 34 |
35 | some @defer (on interaction) content 36 |
37 |
38 | 39 |

pipe

40 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 41 | 42 |

directive

43 |
lazy loaded directive - I'm highlighted lol 🥹
44 | } @placeholder (minimum 500ms) { 45 | 👉 interact with me (the placeholder) to load content 👈 46 | } @loading (after 100ms; minimum 1s) { 47 | 48 | } @error { 49 | something went wrong! 50 | } 51 | `, 52 | }) 53 | export class DeferOnInteractionComponent { 54 | } 55 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-timer.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { LazySharedComponent } from './lazy-shared'; 7 | import { LazyOnTimerComponent } from './lazy-on-timer'; 8 | import { LegacyModule } from './legacy/legacy.module'; 9 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 10 | import { HighlightDirective } from './highlight.directive'; 11 | 12 | @Component({ 13 | selector: 'defer-on-timer', 14 | standalone: true, 15 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, LazyOnTimerComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 16 | template: ` 17 | 18 | 📚 timer(x) would trigger after a specified duration. 19 | 20 | 21 | @defer (on timer(2000ms)) { 22 | 23 |
24 | some @defer (on timer(2000ms)) content 25 |
26 |
27 | 28 |
29 | some @defer (on timer(2000ms)) content 30 |
31 |
32 | 33 |
34 | some @defer (on timer(2000ms)) content 35 |
36 |
37 | 38 |

pipe

39 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 40 | 41 |

directive

42 |
lazy loaded directive - I'm highlighted lol 🥹
43 | } @placeholder (minimum 500ms) { 44 | wait for the timer... 45 | } @loading (after 100ms; minimum 1s) { 46 | 47 | } @error { 48 | something went wrong! 49 | } 50 | `, 51 | }) 52 | export class DeferOnTimerComponent { 53 | } 54 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-on-viewport.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { LazyOnViewportComponent } from './lazy-on-viewport'; 7 | import { LazySharedComponent } from './lazy-shared'; 8 | import { LegacyModule } from './legacy/legacy.module'; 9 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 10 | import { HighlightDirective } from './highlight.directive'; 11 | 12 | @Component({ 13 | selector: 'defer-on-viewport', 14 | standalone: true, 15 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, LazyOnViewportComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 16 | styles: ` 17 | .scroll-container { 18 | border: 1px solid var(--main-accent-color); 19 | border-radius: 6px; 20 | width: 75%; 21 | height: 250px; 22 | max-height: 50%; 23 | overflow-y: scroll; 24 | scroll-behavior: smooth; 25 | } 26 | .scroll-page { 27 | display: flex; 28 | align-items: center; 29 | justify-content: center; 30 | height: 100%; 31 | font-size: 2em; 32 | } 33 | `, 34 | template: ` 35 | 36 | 📚 viewport would trigger the deferred block when the specified content enters the viewport using the IntersectionObserver API. This could be the placeholder content or an element reference. 37 | 📚 viewport trigger with no parameters can only be placed on an @defer that has a @placeholder block with exactly one root element node. 38 | 39 | 40 |
41 |
scroll down...
42 |
and some more...
43 |
a little bit more...
44 |
you're almost done...
45 |
46 | 47 | @defer (on viewport) { 48 | 49 |
50 | some @defer (on viewport) content 51 |
52 |
53 | 54 |
55 | some @defer (on viewport) content 56 |
57 |
58 | 59 |
60 | some @defer (on viewport) content 61 |
62 |
63 | 64 |

pipe

65 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 66 | 67 |

directive

68 |
lazy loaded directive - I'm highlighted lol 🥹
69 | } @placeholder (minimum 500ms) { 70 | waiting to get into the viewport 71 | } @loading (after 100ms; minimum 1s) { 72 | 73 | } @error { 74 | something went wrong! 75 | } 76 | 77 |
78 |
79 | `, 80 | }) 81 | export class DeferOnViewportComponent { 82 | } 83 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-prefetch.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LoaderComponent } from './loader'; 5 | import { BoxComponent } from '../box.component'; 6 | import { ButtonComponent } from '../button.component'; 7 | import { LazyPrefetchComponent } from './lazy-prefetch'; 8 | import { LazySharedComponent } from './lazy-shared'; 9 | import { LegacyModule } from './legacy/legacy.module'; 10 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 11 | import { HighlightDirective } from './highlight.directive'; 12 | 13 | @Component({ 14 | selector: 'defer-prefetch', 15 | standalone: true, 16 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, ButtonComponent, LazyPrefetchComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 17 | template: ` 18 | 19 | 📚 @defer allows to specify conditions when prefetching of the dependencies should be triggered. You can use a special prefetch keyword. prefetch syntax works similarly to the main defer conditions, and accepts when and/or on to declare the trigger. 20 | 💡 Common pattern: @defer (on interaction; prefetch on idle) - display something as the user really needs it, but prefetch when the browser is not busy. 21 | 🖐️ loading itself is triggered by interaction in the example below. Prefetching starts on timer(2s). 22 | 23 | 24 | @defer (on interaction; prefetch on timer(2s)) { 25 | 26 |
27 | some content 28 |
29 |
30 | } @placeholder (minimum 500ms) { 31 | 👉 interact with me 👈 32 |
33 | prefetch on timer(2s) will start after 2 seconds pass 34 |
35 |
36 | } @loading (after 100ms; minimum 1s) { 37 | 38 | } @error { 39 | something went wrong! 40 | } 41 | `, 42 | }) 43 | export class DeferPrefetchComponent { 44 | } 45 | -------------------------------------------------------------------------------- /src/app/defer-usecases/defer-when-condition.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { FormsModule } from '@angular/forms'; 3 | 4 | import { LazyWhenConditionComponent } from './lazy-when-condition'; 5 | import { LoaderComponent } from './loader'; 6 | import { BoxComponent } from '../box.component'; 7 | import { LazySharedComponent } from './lazy-shared'; 8 | import { LegacyModule } from './legacy/legacy.module'; 9 | import { StUpIdCaSePipe } from './stupid-case-pipe'; 10 | import { HighlightDirective } from './highlight.directive'; 11 | 12 | @Component({ 13 | selector: 'defer-when-condition', 14 | standalone: true, 15 | imports: [FormsModule, LegacyModule, LoaderComponent, BoxComponent, LazyWhenConditionComponent, LazySharedComponent, StUpIdCaSePipe, HighlightDirective], 16 | template: ` 17 | 18 | 📚 if the when condition switches back to false, the defer block is not reverted back to the placeholder. The swap is a one-time operation. If the content within the block should be conditionally rendered, an if condition can be used within the block itself. 19 | 🖐️ toggle the checkbox; when checked, the @defer (when isVisible) condition will switch to true. 20 |
21 | 25 |
26 |
27 | 28 | @defer (when isVisible) { 29 | 30 |
31 | some @defer (when isVisible) content 32 |
33 |
34 | 35 |
36 | some @defer (when isVisible) content 37 |
38 |
39 | 40 |
41 | some @defer (when isVisible) content 42 |
43 |
44 | 45 |

pipe

46 | {{ "Lazy loaded pipe here" | StUpIdCaSe }} 47 | 48 |

directive

49 |
lazy loaded directive - I'm highlighted lol 🥹
50 | } @placeholder (minimum 500ms) { 51 | placeholder is shown before @defer is triggered 52 | } @loading (after 100ms; minimum 1s) { 53 | 54 | } @error { 55 | something went wrong! 56 | } 57 | `, 58 | }) 59 | export class DeferWhenConditionComponent { 60 | isVisible = false; 61 | } 62 | -------------------------------------------------------------------------------- /src/app/defer-usecases/highlight.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, ElementRef } from '@angular/core'; 2 | 3 | const getCSSVar = (name: string) => 4 | getComputedStyle(document.documentElement) 5 | .getPropertyValue(name) 6 | 7 | @Directive({ 8 | standalone: true, 9 | selector: '[highlight]' 10 | }) 11 | export class HighlightDirective { 12 | 13 | // colors = ['red', 'blue', 'green', 'yellow']; 14 | colors = ['--orange-red', '--vivid-pink', '--electric-violet'].map(getCSSVar); 15 | 16 | constructor(el: ElementRef) { 17 | this.changeColor(el); 18 | } 19 | 20 | changeColor(el: ElementRef) { 21 | el.nativeElement.style.color = this.colors[Math.floor(Math.random() * this.colors.length)] 22 | setInterval(() => { 23 | el.nativeElement.style.color = this.colors[Math.floor(Math.random() * this.colors.length)]; 24 | }, 500); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-accordion-content-a.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-accordion-content-a', 5 | standalone: true, 6 | template: ` 7 |

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

8 | `, 9 | }) 10 | export class LazyAccordionContentAComponent { 11 | } 12 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-accordion-content-b.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-accordion-content-b', 5 | standalone: true, 6 | template: ` 7 |

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

8 | `, 9 | }) 10 | export class LazyAccordionContentBComponent { 11 | } 12 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-accordion-content-c.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-accordion-content-c', 5 | standalone: true, 6 | template: ` 7 |

Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?

8 | `, 9 | }) 10 | export class LazyAccordionContentCComponent { 11 | } 12 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-error.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-error', 5 | standalone: true, 6 | template: ` 7 |

lazy-error

8 | 9 | `, 10 | }) 11 | export class LazyErrorComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-loading-vs-placeholder.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-loading-vs-placeholder', 5 | standalone: true, 6 | template: ` 7 |

lazy-loading-vs-placeholder

8 | 9 | `, 10 | }) 11 | export class LazyLoadingVsPlaceholder { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-multiple-a.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-multiple-a', 5 | standalone: true, 6 | template: ` 7 |

lazy-multiple-a

8 | 9 | `, 10 | }) 11 | export class LazyMultipleAComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-multiple-b.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-multiple-b', 5 | standalone: true, 6 | template: ` 7 |

lazy-multiple-b

8 | 9 | `, 10 | }) 11 | export class LazyMultipleBComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-multiple-c.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-multiple-c', 5 | standalone: true, 6 | template: ` 7 |

lazy-multiple-c

8 | 9 | `, 10 | }) 11 | export class LazyMultipleCComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-nested-further.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-nested-further', 5 | standalone: true, 6 | template: ` 7 |

lazy-nested-further

8 | 9 | `, 10 | }) 11 | export class LazyNestedFurtherComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-nested.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-nested', 5 | standalone: true, 6 | template: ` 7 |

lazy-nested

8 | 9 | `, 10 | }) 11 | export class LazyNestedComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-hover.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-hover', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-hover

8 | 9 | `, 10 | }) 11 | export class LazyOnHoverComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-idle.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-idle', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-idle

8 | 9 | `, 10 | }) 11 | export class LazyOnIdleComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-immediate.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-immediate', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-immediate

8 | 9 | `, 10 | }) 11 | export class LazyOnImmediateComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-interaction.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-interaction', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-interaction

8 | 9 | `, 10 | }) 11 | export class LazyOnInteractionComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-timer.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-timer', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-timer

8 | 9 | `, 10 | }) 11 | export class LazyOnTimerComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-on-viewport.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-on-viewport', 5 | standalone: true, 6 | template: ` 7 |

lazy-on-viewport

8 | 9 | `, 10 | }) 11 | export class LazyOnViewportComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-prefetch.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-prefetch', 5 | standalone: true, 6 | template: ` 7 |

lazy-prefetch

8 | 9 | `, 10 | }) 11 | export class LazyPrefetchComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-shared.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-shared', 5 | standalone: true, 6 | template: ` 7 |

lazy-shared

8 | this component is shared across multiple routes 9 | 10 | `, 11 | }) 12 | export class LazySharedComponent { 13 | } 14 | -------------------------------------------------------------------------------- /src/app/defer-usecases/lazy-when-condition.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lazy-when-condition', 5 | standalone: true, 6 | template: ` 7 |

lazy-when-condition

8 | 9 | `, 10 | }) 11 | export class LazyWhenConditionComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/legacy/legacy.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { NonStandaloneComponent } from './non-standalone'; 4 | 5 | @NgModule({ 6 | declarations: [ 7 | NonStandaloneComponent 8 | ], 9 | imports: [ 10 | CommonModule 11 | ], 12 | exports: [ 13 | NonStandaloneComponent 14 | ] 15 | }) 16 | export class LegacyModule { } 17 | -------------------------------------------------------------------------------- /src/app/defer-usecases/legacy/non-standalone.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'non-standalone', 5 | template: ` 6 |

non-standalone

7 | this component is NOT standalone 8 | 9 | `, 10 | }) 11 | export class NonStandaloneComponent { 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/loader.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'loader', 5 | standalone: true, 6 | template: ` 7 |
8 | `, 9 | styles: ` 10 | .lds-spinner { 11 | color: official; 12 | display: inline-block; 13 | position: relative; 14 | width: 80px; 15 | height: 80px; 16 | } 17 | .lds-spinner div { 18 | transform-origin: 40px 40px; 19 | animation: lds-spinner 1.2s linear infinite; 20 | } 21 | .lds-spinner div:after { 22 | content: " "; 23 | display: block; 24 | position: absolute; 25 | top: 3px; 26 | left: 37px; 27 | width: 6px; 28 | height: 18px; 29 | border-radius: 20%; 30 | background: var(--vivid-pink); 31 | } 32 | .lds-spinner div:nth-child(1) { 33 | transform: rotate(0deg); 34 | animation-delay: -1.1s; 35 | } 36 | .lds-spinner div:nth-child(2) { 37 | transform: rotate(30deg); 38 | animation-delay: -1s; 39 | } 40 | .lds-spinner div:nth-child(3) { 41 | transform: rotate(60deg); 42 | animation-delay: -0.9s; 43 | } 44 | .lds-spinner div:nth-child(4) { 45 | transform: rotate(90deg); 46 | animation-delay: -0.8s; 47 | } 48 | .lds-spinner div:nth-child(5) { 49 | transform: rotate(120deg); 50 | animation-delay: -0.7s; 51 | } 52 | .lds-spinner div:nth-child(6) { 53 | transform: rotate(150deg); 54 | animation-delay: -0.6s; 55 | } 56 | .lds-spinner div:nth-child(7) { 57 | transform: rotate(180deg); 58 | animation-delay: -0.5s; 59 | } 60 | .lds-spinner div:nth-child(8) { 61 | transform: rotate(210deg); 62 | animation-delay: -0.4s; 63 | } 64 | .lds-spinner div:nth-child(9) { 65 | transform: rotate(240deg); 66 | animation-delay: -0.3s; 67 | } 68 | .lds-spinner div:nth-child(10) { 69 | transform: rotate(270deg); 70 | animation-delay: -0.2s; 71 | } 72 | .lds-spinner div:nth-child(11) { 73 | transform: rotate(300deg); 74 | animation-delay: -0.1s; 75 | } 76 | .lds-spinner div:nth-child(12) { 77 | transform: rotate(330deg); 78 | animation-delay: 0s; 79 | } 80 | @keyframes lds-spinner { 81 | 0% { 82 | opacity: 1; 83 | } 84 | 100% { 85 | opacity: 0; 86 | } 87 | } 88 | `, 89 | }) 90 | export class LoaderComponent {} 91 | -------------------------------------------------------------------------------- /src/app/defer-usecases/stupid-case-pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { StUpIdCaSe } from 'stupid-case' 3 | 4 | @Pipe({ 5 | name: 'StUpIdCaSe', 6 | standalone: true 7 | }) 8 | export class StUpIdCaSePipe implements PipeTransform { 9 | transform(value: string): string { 10 | return StUpIdCaSe(value); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/app/defer-usecases/use-case-container.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeDetectionStrategy, 3 | Component, 4 | } from '@angular/core'; 5 | import { RouterOutlet } from '@angular/router'; 6 | import { SnippetDialogContent } from '../ui-snippet-dialog-content/ui-snippet-dialog-content'; 7 | 8 | @Component({ 9 | changeDetection: ChangeDetectionStrategy.OnPush, 10 | imports: [RouterOutlet, SnippetDialogContent], 11 | host: { class: 'use-case-container' }, 12 | standalone: true, 13 | template: ` 14 | 15 | 32 | 33 | 34 | 51 | @if (codeDialog.open) { 52 | @defer { 53 | 54 | } @loading (after 60ms; minimum 500ms) { 55 |

Loading snippets...

56 | } 57 | } 58 |
59 | `, 60 | styles: ` 61 | button { 62 | cursor: pointer; 63 | 64 | padding: 0.5rem; 65 | border-radius: 0.5rem; 66 | background: -webkit-linear-gradient(var(--angle),var(--orange-red) 0%,var(--vivid-pink) 50%,var(--electric-violet) 100%); 67 | 68 | -webkit-background-clip: text; 69 | -moz-background-clip: text; 70 | background-clip: text; 71 | -webkit-text-fill-color: transparent; 72 | -moz-text-fill-color: transparent; 73 | } 74 | 75 | button.code-btn { 76 | position: absolute; 77 | bottom: 1rem; 78 | right: 1rem; 79 | } 80 | 81 | button svg { 82 | width: 2rem; 83 | height: 2rem; 84 | color: var(--main-accent-color); 85 | 86 | stroke-width: 2; 87 | } 88 | 89 | dialog { 90 | position: relative; 91 | overflow: clip; 92 | 93 | height: 80%; 94 | width: 80%; 95 | 96 | border-radius: 0.5rem; 97 | background-color: var(--main-background-color); 98 | border: 1px solid var(--main-accent-color); 99 | box-shadow: 3px 3px 5px var(--main-accent-color); 100 | } 101 | 102 | dialog:has([open]) { 103 | display: flex; 104 | flex-direction: column; 105 | } 106 | 107 | dialog button { 108 | position: absolute; 109 | right: 1rem; 110 | } 111 | 112 | dialog button svg { 113 | width: 1rem; 114 | height: 1rem; 115 | } 116 | 117 | ::backdrop { 118 | background: #000; 119 | opacity: 0.75; 120 | } 121 | ` 122 | }) 123 | export default class UseCaseContainer {} 124 | -------------------------------------------------------------------------------- /src/app/ui-snippet-dialog-content/ui-snippet-dialog-content.css: -------------------------------------------------------------------------------- 1 | .sr-only { 2 | position: absolute; 3 | width: 1px; 4 | height: 1px; 5 | padding: 0; 6 | margin: -1px; 7 | overflow: hidden; 8 | clip: rect(0, 0, 0, 0); 9 | white-space: nowrap; 10 | border-width: 0; 11 | } 12 | 13 | :host { 14 | flex: 1; 15 | } 16 | 17 | .tabs-container { 18 | height: 100%; 19 | display: flex; 20 | flex-direction: column; 21 | } 22 | 23 | .tabs-panels { 24 | flex: 1; 25 | } 26 | 27 | .tabs-panels > div { 28 | height: 100%; 29 | } 30 | 31 | .tabs-panels > div ::ng-deep pre { 32 | overflow: auto; 33 | padding: 1rem; 34 | height: 98%; 35 | } 36 | 37 | [role="tablist"] { 38 | display: flex; 39 | list-style-type: none; 40 | gap: 1rem; 41 | padding-inline-start: 1rem; 42 | align-items: center; 43 | } 44 | 45 | [role="tab"] { 46 | padding: 1rem; 47 | } 48 | 49 | [aria-selected="true"] { 50 | border-radius: 0.5rem; 51 | border: 1px solid var(--main-accent-color); 52 | box-shadow: 3px 3px 5px var(--main-accent-color); 53 | } 54 | -------------------------------------------------------------------------------- /src/app/ui-snippet-dialog-content/ui-snippet-dialog-content.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ChangeDetectionStrategy, 3 | Component, 4 | inject, 5 | signal, 6 | } from '@angular/core'; 7 | import { DomSanitizer } from '@angular/platform-browser'; 8 | import { Router } from '@angular/router'; 9 | 10 | function injectSnippets() { 11 | const router = inject(Router); 12 | const sanitizer = inject(DomSanitizer); 13 | 14 | const snippets = signal({ tsHtml: '', htmlHtml: '' }); 15 | 16 | Promise.all([ 17 | fetch(`/angular-defer/assets/snippets${router.url}/ts.html`).then((res) => res.text()), 18 | fetch(`/angular-defer/assets/snippets${router.url}/html.html`).then((res) => res.text()), 19 | ]).then(([tsHtml, htmlHtml]) => { 20 | // NOTE: we generate these files so they're safe 21 | snippets.set({ 22 | tsHtml: sanitizer.bypassSecurityTrustHtml(tsHtml) as string, 23 | htmlHtml: sanitizer.bypassSecurityTrustHtml(htmlHtml) as string, 24 | }); 25 | }); 26 | 27 | return snippets.asReadonly(); 28 | } 29 | 30 | @Component({ 31 | selector: 'app-snippet-dialog-content', 32 | standalone: true, 33 | template: ` 34 | Snippet Tabs 35 | 36 | @if (snippets().tsHtml && snippets().htmlHtml) { 37 |
38 | 58 | 59 |
60 |
66 |
72 |
73 |
74 | } 75 | `, 76 | styleUrl: './ui-snippet-dialog-content.css', 77 | changeDetection: ChangeDetectionStrategy.OnPush, 78 | }) 79 | export class SnippetDialogContent { 80 | protected snippets = injectSnippets(); 81 | protected activePanelId = signal('html'); 82 | } 83 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/angular-defer/46a03f44c6a81e8a3f707165d6eed008d6543278/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/snippets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/angular-defer/46a03f44c6a81e8a3f707165d6eed008d6543278/src/assets/snippets/.gitkeep -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ducin/angular-defer/46a03f44c6a81e8a3f707165d6eed008d6543278/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Angular ⚡️ @defer ⚡️ Interactive Examples 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { appConfig } from './app/app.config'; 3 | import { AppComponent } from './app/app.component'; 4 | 5 | bootstrapApplication(AppComponent, appConfig) 6 | .catch((err) => console.error(err)); 7 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | @media (prefers-color-scheme: light) { 2 | :root { 3 | --background-color: #ffffff; 4 | --text-color: #000000; 5 | --angle: 90deg; 6 | --orange-red: oklch(63.32% 0.24 31.68); 7 | --vivid-pink: oklch(69.02% 0.277 332.77); 8 | --electric-violet: oklch(53.18% 0.28 296.97); 9 | 10 | --main-accent-color: var(--electric-violet); 11 | --main-background-color: color-mix( 12 | in srgb, 13 | var(--electric-violet) 10%, 14 | white 15 | ); 16 | --secondary-background-color: color-mix( 17 | in srgb, 18 | var(--electric-violet) 30%, 19 | white 20 | ); 21 | } 22 | 23 | /* the theme name */ 24 | .shiki.dark-plus { 25 | display: none; 26 | } 27 | } 28 | @media (prefers-color-scheme: dark) { 29 | :root { 30 | --background-color: #000000; 31 | --text-color: #ffffff; 32 | --angle: 90deg; 33 | --orange-red: oklch(63.32% 0.24 31.68); 34 | --vivid-pink: oklch(69.02% 0.277 332.77); 35 | --electric-violet: oklch(53.18% 0.28 296.97); 36 | 37 | --main-accent-color: var(--vivid-pink); 38 | --main-background-color: color-mix( 39 | in srgb, 40 | var(--electric-violet) 30%, 41 | black 42 | ); 43 | --secondary-background-color: color-mix( 44 | in srgb, 45 | var(--electric-violet) 60%, 46 | black 47 | ); 48 | } 49 | 50 | /* the theme name */ 51 | .shiki.light-plus { 52 | display: none; 53 | } 54 | } 55 | 56 | body { 57 | color: var(--text-color); 58 | background-color: var(--background-color); 59 | } 60 | 61 | :root { 62 | font-family: "Lato", sans-serif; 63 | } 64 | 65 | .angular-gradient { 66 | background: -webkit-linear-gradient( 67 | var(--angle), 68 | var(--orange-red) 0%, 69 | var(--vivid-pink) 50%, 70 | var(--electric-violet) 100% 71 | ); 72 | } 73 | 74 | .box { 75 | margin: 10px; 76 | padding: 10px; 77 | border-radius: 6px; 78 | background-color: var(--main-background-color); 79 | border: 1px solid var(--main-accent-color); 80 | box-shadow: 3px 3px 5px var(--main-accent-color); 81 | } 82 | 83 | code:not(:has(span)) { 84 | margin-bottom: 20px; 85 | font-weight: 700; 86 | background: -webkit-linear-gradient( 87 | var(--angle), 88 | var(--orange-red) 0%, 89 | var(--vivid-pink) 50%, 90 | var(--electric-violet) 100% 91 | ); 92 | 93 | -webkit-background-clip: text; 94 | -moz-background-clip: text; 95 | background-clip: text; 96 | -webkit-text-fill-color: transparent; 97 | -moz-text-fill-color: transparent; 98 | } 99 | 100 | pre { 101 | margin: 10px 20px; 102 | } 103 | 104 | a { 105 | text-decoration: none; 106 | color: var(--main-accent-color); 107 | } 108 | 109 | content { 110 | display: block; 111 | margin: 4px 0; 112 | } 113 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "outDir": "./dist/out-tsc", 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "noImplicitOverride": true, 9 | "noPropertyAccessFromIndexSignature": true, 10 | "noImplicitReturns": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "skipLibCheck": true, 13 | "esModuleInterop": true, 14 | "sourceMap": true, 15 | "declaration": false, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "ES2022", 20 | "module": "ES2022", 21 | "useDefineForClassFields": false, 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ] 26 | }, 27 | "angularCompilerOptions": { 28 | "enableI18nLegacyMessageIdFormat": false, 29 | "strictInjectionParameters": true, 30 | "strictInputAccessModifiers": true, 31 | "strictTemplates": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "include": [ 11 | "src/**/*.spec.ts", 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | --------------------------------------------------------------------------------