Skip to content

Commit 2a24034

Browse files
committed
docs(www): enhance code blocks
1 parent 3c4b66e commit 2a24034

File tree

109 files changed

+3392
-793
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+3392
-793
lines changed

projects/www/src/app/components/docs/code-example.component.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
1-
import { Component, Input } from '@angular/core';
1+
import { Component, inject, Input, PLATFORM_ID, signal } from '@angular/core';
2+
import { isPlatformServer } from '@angular/common';
3+
import { CodeHighlightPipe } from './code-highlight.pipe';
4+
import { ExamplesService } from '@ngrx-io/app/examples/examples.service';
25

36
@Component({
47
selector: 'ngrx-code-example',
58
standalone: true,
9+
imports: [CodeHighlightPipe],
610
template: `
711
<div class="header">{{ header }}</div>
812
<div class="body">
9-
<ng-content></ng-content>
13+
@if(path) {
14+
<div [innerHTML]="codeContent() | ngrxCodeHighlight"></div>
15+
}@else{
16+
<ng-content />
17+
}
1018
</div>
1119
`,
1220
styles: [
@@ -35,4 +43,22 @@ import { Component, Input } from '@angular/core';
3543
})
3644
export class CodeExampleComponent {
3745
@Input() header: string = '';
46+
@Input() path: string = '';
47+
@Input() region: string = '';
48+
@Input() language: string = 'typescript';
49+
50+
private exampleService = inject(ExamplesService);
51+
private platformId = inject(PLATFORM_ID);
52+
protected codeContent = signal('');
53+
54+
async ngAfterViewInit(): Promise<void> {
55+
if (isPlatformServer(this.platformId)) return;
56+
if (!this.path) return;
57+
58+
const content = await this.exampleService.extractSnippet(
59+
this.path,
60+
this.region
61+
);
62+
this.codeContent.set(content);
63+
}
3864
}
Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,33 @@
1-
import { Pipe, PipeTransform } from '@angular/core';
2-
import hljs from 'highlight.js/lib/core';
3-
import typescript from 'highlight.js/lib/languages/typescript';
1+
import { inject, Pipe, PipeTransform } from '@angular/core';
2+
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
3+
import { ngrxTheme } from '@ngrx-io/shared/ngrx-shiki-theme';
4+
import {
5+
BundledLanguage,
6+
BundledTheme,
7+
getHighlighter,
8+
HighlighterGeneric,
9+
} from 'shiki';
410

5-
hljs.registerLanguage('typescript', typescript);
11+
let highlighter: HighlighterGeneric<BundledLanguage, BundledTheme>;
12+
getHighlighter({
13+
langs: ['typescript'],
14+
themes: [ngrxTheme],
15+
}).then((h) => (highlighter = h));
616

717
@Pipe({
818
name: 'ngrxCodeHighlight',
9-
pure: true,
1019
standalone: true,
20+
pure: true,
1121
})
1222
export class CodeHighlightPipe implements PipeTransform {
13-
transform(code: string): string {
14-
return hljs.highlight(code, { language: 'typescript' }).value;
23+
private sanitizer = inject(DomSanitizer);
24+
25+
transform(code: string): SafeHtml {
26+
const html = highlighter?.codeToHtml(code, {
27+
lang: 'typescript',
28+
theme: 'ngrx-theme',
29+
});
30+
31+
return this.sanitizer.bypassSecurityTrustHtml(html);
1532
}
1633
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'app-root',
5+
template: `
6+
<paginator
7+
[length]="100"
8+
[pageSize]="10"
9+
[pageSizeOptions]="[5, 10, 25, 100]"
10+
(page)="log($event)"
11+
>
12+
</paginator>
13+
`,
14+
})
15+
export class AppComponent {
16+
log(obj: unknown) {
17+
console.log(obj);
18+
}
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { NgModule } from '@angular/core';
2+
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
3+
import { ReactiveFormsModule } from '@angular/forms';
4+
import { MatNativeDateModule } from '@angular/material/core';
5+
import { MatFormFieldModule } from '@angular/material/form-field';
6+
import { MatSelectModule } from '@angular/material/select';
7+
import { MatTooltipModule } from '@angular/material/tooltip';
8+
9+
import { AppComponent } from './app.component';
10+
import { PaginatorComponent } from './paginator.component';
11+
12+
@NgModule({
13+
imports: [
14+
BrowserAnimationsModule,
15+
MatNativeDateModule,
16+
ReactiveFormsModule,
17+
MatFormFieldModule,
18+
MatSelectModule,
19+
MatTooltipModule,
20+
],
21+
declarations: [AppComponent, PaginatorComponent],
22+
bootstrap: [AppComponent],
23+
})
24+
export class AppModule {}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import {
2+
Component,
3+
Input,
4+
ChangeDetectionStrategy,
5+
Output,
6+
ViewEncapsulation,
7+
} from '@angular/core';
8+
import { PaginatorStore } from './paginator.store';
9+
10+
@Component({
11+
selector: 'paginator',
12+
templateUrl: 'paginator.html',
13+
host: {
14+
class: 'mat-paginator',
15+
},
16+
styleUrls: ['./paginator.scss'],
17+
encapsulation: ViewEncapsulation.None,
18+
changeDetection: ChangeDetectionStrategy.OnPush,
19+
providers: [PaginatorStore],
20+
})
21+
export class PaginatorComponent {
22+
// #docregion inputs
23+
@Input() set pageIndex(value: string | number) {
24+
this.paginatorStore.setPageIndex(value);
25+
}
26+
27+
@Input() set length(value: string | number) {
28+
this.paginatorStore.setLength(value);
29+
}
30+
31+
@Input() set pageSize(value: string | number) {
32+
this.paginatorStore.setPageSize(value);
33+
}
34+
35+
@Input() set pageSizeOptions(value: readonly number[]) {
36+
this.paginatorStore.setPageSizeOptions(value);
37+
}
38+
// #enddocregion inputs
39+
40+
// #docregion selectors
41+
// Outputing the event directly from the page$ Observable<PageEvent> property.
42+
/** Event emitted when the paginator changes the page size or page index. */
43+
@Output() readonly page = this.paginatorStore.page$;
44+
45+
// ViewModel for the PaginatorComponent
46+
readonly vm$ = this.paginatorStore.vm$;
47+
// #enddocregion selectors
48+
49+
constructor(private readonly paginatorStore: PaginatorStore) {}
50+
51+
// #docregion updating-state
52+
changePageSize(newPageSize: number) {
53+
this.paginatorStore.changePageSize(newPageSize);
54+
}
55+
nextPage() {
56+
this.paginatorStore.nextPage();
57+
}
58+
firstPage() {
59+
this.paginatorStore.firstPage();
60+
}
61+
previousPage() {
62+
this.paginatorStore.previousPage();
63+
}
64+
lastPage() {
65+
this.paginatorStore.lastPage();
66+
}
67+
// #enddocregion updating-state
68+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<div class="mat-paginator-outer-container" *ngIf="vm$ | async as vm">
2+
<div class="mat-paginator-container">
3+
<div class="mat-paginator-page-size">
4+
<div class="mat-paginator-page-size-label">
5+
Items per page
6+
</div>
7+
8+
<mat-form-field
9+
*ngIf="vm.pageSizeOptions.length > 1"
10+
class="mat-paginator-page-size-select">
11+
<mat-select
12+
[value]="vm.pageSize"
13+
(selectionChange)="changePageSize($any($event).value)">
14+
<mat-option *ngFor="let pageSizeOption of vm.pageSizeOptions" [value]="pageSizeOption">
15+
{{pageSizeOption}}
16+
</mat-option>
17+
</mat-select>
18+
</mat-form-field>
19+
20+
<div
21+
class="mat-paginator-page-size-value"
22+
*ngIf="vm.pageSizeOptions.length <= 1">{{vm.pageSize}}</div>
23+
</div>
24+
25+
<div class="mat-paginator-range-actions">
26+
<div class="mat-paginator-range-label">
27+
{{vm.rangeLabel}}
28+
</div>
29+
30+
<button mat-icon-button type="button"
31+
class="mat-paginator-navigation-first"
32+
(click)="firstPage()"
33+
matTooltip="First page"
34+
[matTooltipDisabled]="!vm.hasPreviousPage"
35+
[matTooltipPosition]="'above'"
36+
[disabled]="!vm.hasPreviousPage">
37+
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
38+
<path d="M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"/>
39+
</svg>
40+
</button>
41+
<button mat-icon-button type="button"
42+
class="mat-paginator-navigation-previous"
43+
(click)="previousPage()"
44+
[attr.aria-label]="'Previous Page'"
45+
[matTooltip]="'Previous Page'"
46+
[matTooltipDisabled]="!vm.hasPreviousPage"
47+
[matTooltipPosition]="'above'"
48+
[disabled]="!vm.hasPreviousPage">
49+
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
50+
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
51+
</svg>
52+
</button>
53+
<button mat-icon-button type="button"
54+
class="mat-paginator-navigation-next"
55+
(click)="nextPage()"
56+
[attr.aria-label]="'Next Page'"
57+
[matTooltip]="'Next Page'"
58+
[matTooltipDisabled]="!vm.hasNextPage"
59+
[matTooltipPosition]="'above'"
60+
[disabled]="!vm.hasNextPage">
61+
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
62+
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
63+
</svg>
64+
</button>
65+
<button mat-icon-button type="button"
66+
class="mat-paginator-navigation-last"
67+
(click)="lastPage()"
68+
[attr.aria-label]="'Last Page'"
69+
[matTooltip]="'Last Page'"
70+
[matTooltipDisabled]="!vm.hasNextPage"
71+
[matTooltipPosition]="'above'"
72+
[disabled]="!vm.hasNextPage">
73+
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
74+
<path d="M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z"/>
75+
</svg>
76+
</button>
77+
</div>
78+
</div>
79+
</div>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
@import '~@angular/material/prebuilt-themes/indigo-pink.css';
2+
/* Add application styles & imports to this file! */
3+
4+
5+
$mat-paginator-padding: 0 8px;
6+
$mat-paginator-page-size-margin-right: 8px;
7+
8+
$mat-paginator-items-per-page-label-margin: 0 4px;
9+
$mat-paginator-selector-margin: 6px 4px 0 4px;
10+
$mat-paginator-selector-trigger-width: 56px;
11+
$mat-paginator-selector-trigger-outline-width: 64px;
12+
$mat-paginator-selector-trigger-fill-width: 64px;
13+
14+
$mat-paginator-range-label-margin: 0 32px 0 24px;
15+
$mat-paginator-button-icon-size: 28px;
16+
17+
.mat-paginator {
18+
display: block;
19+
}
20+
21+
// Note: this wrapper element is only used to get the flexbox vertical centering to work
22+
// with the `min-height` on IE11. It can be removed if we drop support for IE.
23+
.mat-paginator-outer-container {
24+
display: flex;
25+
}
26+
27+
.mat-paginator-container {
28+
display: flex;
29+
align-items: center;
30+
justify-content: flex-end;
31+
padding: $mat-paginator-padding;
32+
flex-wrap: wrap-reverse;
33+
width: 100%;
34+
}
35+
36+
.mat-paginator-page-size {
37+
display: flex;
38+
align-items: baseline;
39+
margin-right: $mat-paginator-page-size-margin-right;
40+
41+
[dir='rtl'] & {
42+
margin-right: 0;
43+
margin-left: $mat-paginator-page-size-margin-right;
44+
}
45+
}
46+
47+
.mat-paginator-page-size-label {
48+
margin: $mat-paginator-items-per-page-label-margin;
49+
}
50+
51+
.mat-paginator-page-size-select {
52+
margin: $mat-paginator-selector-margin;
53+
width: $mat-paginator-selector-trigger-width;
54+
55+
&.mat-form-field-appearance-outline {
56+
width: $mat-paginator-selector-trigger-outline-width;
57+
}
58+
59+
&.mat-form-field-appearance-fill {
60+
width: $mat-paginator-selector-trigger-fill-width;
61+
}
62+
}
63+
64+
.mat-paginator-range-label {
65+
margin: $mat-paginator-range-label-margin;
66+
}
67+
68+
.mat-paginator-range-actions {
69+
display: flex;
70+
align-items: center;
71+
}
72+
73+
.mat-paginator-icon {
74+
width: $mat-paginator-button-icon-size;
75+
fill: currentColor;
76+
77+
[dir='rtl'] & {
78+
transform: rotate(180deg);
79+
}
80+
}

0 commit comments

Comments
 (0)