diff --git a/projects/natural-editor/src/lib/class-dialog/class-dialog.component.ts b/projects/natural-editor/src/lib/class-dialog/class-dialog.component.ts index 5980dccd..96bd16dd 100644 --- a/projects/natural-editor/src/lib/class-dialog/class-dialog.component.ts +++ b/projects/natural-editor/src/lib/class-dialog/class-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef, MatDialogModule} from '@angular/material/dialog'; import {FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {ifValid} from '@ecodev/natural'; @@ -25,6 +25,8 @@ export type ClassDialogData = { imports: [MatDialogModule, FormsModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], }) export class ClassDialogComponent { + private dialogRef = inject>(MatDialogRef); + public readonly classControl = new FormControl('', { validators: Validators.pattern(/(^\s*(-?[_a-zA-Z]+[_a-zA-Z0-9-]*\s*)+)/), nonNullable: true, @@ -33,10 +35,9 @@ export class ClassDialogComponent { class: this.classControl, }); - public constructor( - @Inject(MAT_DIALOG_DATA) data: ClassDialogData, - private dialogRef: MatDialogRef, - ) { + public constructor() { + const data = inject(MAT_DIALOG_DATA); + this.form.setValue(data); } diff --git a/projects/natural-editor/src/lib/color-dialog/color-dialog.component.ts b/projects/natural-editor/src/lib/color-dialog/color-dialog.component.ts index 074d4596..4005fae9 100644 --- a/projects/natural-editor/src/lib/color-dialog/color-dialog.component.ts +++ b/projects/natural-editor/src/lib/color-dialog/color-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef, MatDialogModule} from '@angular/material/dialog'; import {FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {ifValid} from '@ecodev/natural'; @@ -36,6 +36,8 @@ export type ColorDialogData = { ], }) export class ColorDialogComponent { + private dialogRef = inject>(MatDialogRef); + public readonly colors: string[][] = [ [ '#000000', @@ -187,10 +189,9 @@ export class ColorDialogComponent { color: this.colorControl, }); - public constructor( - @Inject(MAT_DIALOG_DATA) data: ColorDialogData, - private dialogRef: MatDialogRef, - ) { + public constructor() { + const data = inject(MAT_DIALOG_DATA); + this.form.setValue(data); } diff --git a/projects/natural-editor/src/lib/custom-css/custom-css.directive.ts b/projects/natural-editor/src/lib/custom-css/custom-css.directive.ts index 6974a8d0..9a11664c 100644 --- a/projects/natural-editor/src/lib/custom-css/custom-css.directive.ts +++ b/projects/natural-editor/src/lib/custom-css/custom-css.directive.ts @@ -1,4 +1,4 @@ -import {Directive, HostBinding, Inject, Input, OnDestroy} from '@angular/core'; +import {Directive, HostBinding, Input, OnDestroy, inject} from '@angular/core'; import {DOCUMENT} from '@angular/common'; /** @@ -44,6 +44,8 @@ let componentCount = 0; standalone: true, }) export class NaturalCustomCssDirective implements OnDestroy { + private readonly document = inject(DOCUMENT); + private style: HTMLStyleElement | null = null; @HostBinding('attr.data-natural-id') private readonly id = 'n' + ++uniqueId; @@ -60,8 +62,6 @@ export class NaturalCustomCssDirective implements OnDestroy { } } - public constructor(@Inject(DOCUMENT) private readonly document: Document) {} - public ngOnDestroy(): void { this.style?.remove(); diff --git a/projects/natural-editor/src/lib/editor/editor.component.spec.ts b/projects/natural-editor/src/lib/editor/editor.component.spec.ts index 609d1e82..10f049a4 100644 --- a/projects/natural-editor/src/lib/editor/editor.component.spec.ts +++ b/projects/natural-editor/src/lib/editor/editor.component.spec.ts @@ -1,6 +1,6 @@ import {ComponentFixture, TestBed} from '@angular/core/testing'; import {NaturalEditorComponent} from './editor.component'; -import {Component, Inject, InjectionToken} from '@angular/core'; +import {Component, InjectionToken, inject} from '@angular/core'; import {By} from '@angular/platform-browser'; import {FormsModule} from '@angular/forms'; import {ImageUploader} from '../utils/image'; @@ -15,9 +15,9 @@ const IMAGE_UPLOADER = new InjectionToken('Image uploader imports: [FormsModule, NaturalEditorComponent], }) class TestHostComponent { - public myValue = ''; + public readonly imageUploader = inject(IMAGE_UPLOADER); - public constructor(@Inject(IMAGE_UPLOADER) public readonly imageUploader: ImageUploader | null) {} + public myValue = ''; } /** diff --git a/projects/natural-editor/src/lib/editor/editor.component.ts b/projects/natural-editor/src/lib/editor/editor.component.ts index 163590b3..ae623386 100644 --- a/projects/natural-editor/src/lib/editor/editor.component.ts +++ b/projects/natural-editor/src/lib/editor/editor.component.ts @@ -1,16 +1,4 @@ -import { - Component, - ElementRef, - EventEmitter, - Inject, - Input, - OnDestroy, - OnInit, - Optional, - Output, - Self, - ViewChild, -} from '@angular/core'; +import {Component, ElementRef, EventEmitter, inject, Input, OnDestroy, OnInit, Output, ViewChild} from '@angular/core'; import {ControlValueAccessor, NgControl} from '@angular/forms'; import {EditorView} from 'prosemirror-view'; import {EditorState, Plugin, Transaction} from 'prosemirror-state'; @@ -63,6 +51,11 @@ import {MatButtonModule} from '@angular/material/button'; ], }) export class NaturalEditorComponent implements OnInit, OnDestroy, ControlValueAccessor { + private readonly ngControl = inject(NgControl, {optional: true, self: true}); + private readonly document = inject(DOCUMENT); + private readonly dialog = inject(MatDialog); + private readonly imagePlugin = inject(ImagePlugin); + private view: EditorView | null = null; @ViewChild('editor', {read: ElementRef, static: true}) private editor!: ElementRef; @@ -99,12 +92,7 @@ export class NaturalEditorComponent implements OnInit, OnDestroy, ControlValueAc public disabled = false; - public constructor( - @Optional() @Self() public readonly ngControl: NgControl, - @Inject(DOCUMENT) private readonly document: Document, - private readonly dialog: MatDialog, - private readonly imagePlugin: ImagePlugin, - ) { + public constructor() { if (this.ngControl !== null) { this.ngControl.valueAccessor = this; } diff --git a/projects/natural-editor/src/lib/id-dialog/id-dialog.component.ts b/projects/natural-editor/src/lib/id-dialog/id-dialog.component.ts index 9e3c8e00..4985e987 100644 --- a/projects/natural-editor/src/lib/id-dialog/id-dialog.component.ts +++ b/projects/natural-editor/src/lib/id-dialog/id-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef, MatDialogModule} from '@angular/material/dialog'; import {FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {ifValid} from '@ecodev/natural'; @@ -25,6 +25,8 @@ export type IdDialogData = { imports: [MatDialogModule, FormsModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], }) export class IdDialogComponent { + private dialogRef = inject>(MatDialogRef); + public readonly idControl = new FormControl('', { validators: Validators.pattern(/(^(-?[_a-zA-Z]+[_a-zA-Z0-9-]*)+)/), nonNullable: true, @@ -33,10 +35,9 @@ export class IdDialogComponent { id: this.idControl, }); - public constructor( - @Inject(MAT_DIALOG_DATA) data: IdDialogData, - private dialogRef: MatDialogRef, - ) { + public constructor() { + const data = inject(MAT_DIALOG_DATA); + this.form.setValue(data); } diff --git a/projects/natural-editor/src/lib/link-dialog/link-dialog.component.ts b/projects/natural-editor/src/lib/link-dialog/link-dialog.component.ts index 161e6609..ac16494d 100644 --- a/projects/natural-editor/src/lib/link-dialog/link-dialog.component.ts +++ b/projects/natural-editor/src/lib/link-dialog/link-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef, MatDialogModule} from '@angular/material/dialog'; import {FormControl, FormGroup, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {ifValid} from '@ecodev/natural'; @@ -18,6 +18,8 @@ export type LinkDialogData = { imports: [MatDialogModule, FormsModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], }) export class LinkDialogComponent { + private dialogRef = inject>(MatDialogRef); + public readonly hrefControl = new FormControl('', {validators: Validators.required, nonNullable: true}); public readonly titleControl = new FormControl('', {nonNullable: true}); public readonly form = new FormGroup({ @@ -25,10 +27,9 @@ export class LinkDialogComponent { title: this.titleControl, }); - public constructor( - @Inject(MAT_DIALOG_DATA) data: LinkDialogData, - private dialogRef: MatDialogRef, - ) { + public constructor() { + const data = inject(MAT_DIALOG_DATA); + this.form.setValue({title: '', ...data}); } diff --git a/projects/natural-editor/src/lib/utils/image.ts b/projects/natural-editor/src/lib/utils/image.ts index 386695f6..366f353e 100644 --- a/projects/natural-editor/src/lib/utils/image.ts +++ b/projects/natural-editor/src/lib/utils/image.ts @@ -2,7 +2,7 @@ import {Decoration, DecorationSet, EditorView} from 'prosemirror-view'; import {EditorState, Plugin} from 'prosemirror-state'; import {Observable} from 'rxjs'; import {Schema} from 'prosemirror-model'; -import {Inject, Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {DOCUMENT} from '@angular/common'; export type ImageUploader = (file: File) => Observable; @@ -11,7 +11,9 @@ export type ImageUploader = (file: File) => Observable; export class ImagePlugin { public readonly plugin: Plugin; - public constructor(@Inject(DOCUMENT) document: Document) { + public constructor() { + const document = inject(DOCUMENT); + // eslint-disable-next-line @typescript-eslint/no-this-alias const self = this; this.plugin = new Plugin({ diff --git a/projects/natural-editor/src/public-api.ts b/projects/natural-editor/src/public-api.ts index a8edd184..1da4280e 100644 --- a/projects/natural-editor/src/public-api.ts +++ b/projects/natural-editor/src/public-api.ts @@ -6,4 +6,4 @@ export {NaturalCustomCssDirective} from './lib/custom-css/custom-css.directive'; export {NaturalEditorComponent} from './lib/editor/editor.component'; -export {ImageUploader} from './lib/utils/image'; +export type {ImageUploader} from './lib/utils/image'; diff --git a/projects/natural/src/lib/classes/abstract-detail.spec.ts b/projects/natural/src/lib/classes/abstract-detail.spec.ts index 83428b5d..8db07ec7 100644 --- a/projects/natural/src/lib/classes/abstract-detail.spec.ts +++ b/projects/natural/src/lib/classes/abstract-detail.spec.ts @@ -2,7 +2,7 @@ import {TestBed} from '@angular/core/testing'; import {MockApolloProvider} from '../testing/mock-apollo.provider'; import {Item, ItemInput, ItemService} from '../testing/item.service'; import {Literal, NaturalAbstractDetail, NaturalAlertService} from '@ecodev/natural'; -import {Component, Injectable} from '@angular/core'; +import {Component, inject, Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, provideRouter, Route, Router} from '@angular/router'; import {RouterTestingHarness} from '@angular/router/testing'; import {BehaviorSubject, of, Subject} from 'rxjs'; @@ -13,7 +13,9 @@ import {provideNoopAnimations} from '@angular/platform-browser/animations'; template: `
Test simple component
`, }) class TestSimpleComponent extends NaturalAbstractDetail { - public constructor(service: ItemService) { + public constructor() { + const service = inject(ItemService); + super('item', service); } } diff --git a/projects/natural/src/lib/classes/abstract-list.spec.ts b/projects/natural/src/lib/classes/abstract-list.spec.ts index 5423b7c1..6afd8533 100644 --- a/projects/natural/src/lib/classes/abstract-list.spec.ts +++ b/projects/natural/src/lib/classes/abstract-list.spec.ts @@ -8,7 +8,7 @@ import { naturalProviders, } from '@ecodev/natural'; import {ItemService} from '../testing/item.service'; -import {Component} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {ActivatedRoute, Data} from '@angular/router'; import {MockApolloProvider} from '../testing/mock-apollo.provider'; @@ -47,7 +47,9 @@ class TestListComponent extends NaturalAbstractList { }, ]; - public constructor(service: ItemService) { + public constructor() { + const service = inject(ItemService); + super(service); } diff --git a/projects/natural/src/lib/modules/alert/alert.service.ts b/projects/natural/src/lib/modules/alert/alert.service.ts index 8c882d76..591d1304 100644 --- a/projects/natural/src/lib/modules/alert/alert.service.ts +++ b/projects/natural/src/lib/modules/alert/alert.service.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {MatDialog} from '@angular/material/dialog'; import {MatSnackBar, MatSnackBarRef, SimpleSnackBar} from '@angular/material/snack-bar'; import {Observable} from 'rxjs'; @@ -8,10 +8,8 @@ import {NaturalConfirmComponent, NaturalConfirmData} from './confirm.component'; providedIn: 'root', }) export class NaturalAlertService { - public constructor( - private readonly dialog: MatDialog, - private readonly snackBar: MatSnackBar, - ) {} + private readonly dialog = inject(MatDialog); + private readonly snackBar = inject(MatSnackBar); /** * Show an informative message in a snack bar diff --git a/projects/natural/src/lib/modules/alert/confirm.component.ts b/projects/natural/src/lib/modules/alert/confirm.component.ts index b0273769..f1c40cab 100644 --- a/projects/natural/src/lib/modules/alert/confirm.component.ts +++ b/projects/natural/src/lib/modules/alert/confirm.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogModule} from '@angular/material/dialog'; import {MatButtonModule} from '@angular/material/button'; @@ -16,5 +16,5 @@ export type NaturalConfirmData = { imports: [MatDialogModule, MatButtonModule], }) export class NaturalConfirmComponent { - public constructor(@Inject(MAT_DIALOG_DATA) public data: NaturalConfirmData) {} + public readonly data = inject(MAT_DIALOG_DATA); } diff --git a/projects/natural/src/lib/modules/avatar/component/avatar.component.ts b/projects/natural/src/lib/modules/avatar/component/avatar.component.ts index 774cf642..2c959bdf 100755 --- a/projects/natural/src/lib/modules/avatar/component/avatar.component.ts +++ b/projects/natural/src/lib/modules/avatar/component/avatar.component.ts @@ -1,4 +1,4 @@ -import {Component, HostBinding, Input, OnChanges, SimpleChanges} from '@angular/core'; +import {Component, HostBinding, Input, OnChanges, SimpleChanges, inject} from '@angular/core'; import {Source} from '../sources/source'; import {AvatarService} from '../service/avatar.service'; import {CommonModule} from '@angular/common'; @@ -58,6 +58,8 @@ type Style = Partial; imports: [CommonModule], }) export class NaturalAvatarComponent implements OnChanges { + private readonly avatarService = inject(AvatarService); + @Input() public image?: string | null; @Input() public initials?: string | null; @Input() public gravatar?: string | null; @@ -85,8 +87,6 @@ export class NaturalAvatarComponent implements OnChanges { private currentIndex = -1; private sources: Source[] = []; - public constructor(private readonly avatarService: AvatarService) {} - /** * Detect inputs change */ diff --git a/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts b/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts index 2781555f..ccbe1b5f 100644 --- a/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts +++ b/projects/natural/src/lib/modules/columns-picker/columns-picker.component.ts @@ -31,6 +31,8 @@ import {CommonModule} from '@angular/common'; }) export class NaturalColumnsPickerComponent implements OnChanges { private readonly destroyRef = inject(DestroyRef); + private readonly breakpointObserver = inject(BreakpointObserver); + private _selections?: string[]; private _availableColumns: Required[] = []; @@ -85,8 +87,6 @@ export class NaturalColumnsPickerComponent implements OnChanges { public readonly isMobile = this.breakpointObserver.observe(Breakpoints.XSmall).pipe(map(result => result.matches)); - public constructor(private readonly breakpointObserver: BreakpointObserver) {} - private initColumns(): void { this._availableColumns?.forEach(col => { col.checked = this._selections?.length ? this._selections.includes(col.id) : col.checked; diff --git a/projects/natural/src/lib/modules/columns-picker/public-api.ts b/projects/natural/src/lib/modules/columns-picker/public-api.ts index a7cb85b3..bc7b9c49 100644 --- a/projects/natural/src/lib/modules/columns-picker/public-api.ts +++ b/projects/natural/src/lib/modules/columns-picker/public-api.ts @@ -2,5 +2,5 @@ * Public API Surface of natural */ -export {AvailableColumn, Button, SubButton} from './types'; +export type {AvailableColumn, Button, SubButton} from './types'; export * from './columns-picker.component'; diff --git a/projects/natural/src/lib/modules/common/directives/background-density.directive.ts b/projects/natural/src/lib/modules/common/directives/background-density.directive.ts index 4d970def..ca869d5f 100644 --- a/projects/natural/src/lib/modules/common/directives/background-density.directive.ts +++ b/projects/natural/src/lib/modules/common/directives/background-density.directive.ts @@ -1,4 +1,4 @@ -import {Directive, ElementRef, Input} from '@angular/core'; +import {Directive, ElementRef, Input, inject} from '@angular/core'; import {densities} from './src-density.directive'; @Directive({ @@ -6,6 +6,8 @@ import {densities} from './src-density.directive'; standalone: true, }) export class NaturalBackgroundDensityDirective { + private readonly elementRef = inject>(ElementRef); + /** * Automatically apply background image selection based on screen density. * @@ -53,6 +55,4 @@ export class NaturalBackgroundDensityDirective { this.elementRef.nativeElement.style.backgroundImage = responsive; } } - - public constructor(private readonly elementRef: ElementRef) {} } diff --git a/projects/natural/src/lib/modules/common/directives/linkable-tab.directive.ts b/projects/natural/src/lib/modules/common/directives/linkable-tab.directive.ts index 100a1a03..98ed5197 100644 --- a/projects/natural/src/lib/modules/common/directives/linkable-tab.directive.ts +++ b/projects/natural/src/lib/modules/common/directives/linkable-tab.directive.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, DestroyRef, Directive, inject, Input} from '@angular/core'; +import {AfterViewInit, DestroyRef, Directive, Input, inject} from '@angular/core'; import {MatTab, MatTabGroup} from '@angular/material/tabs'; import {ActivatedRoute, RouteConfigLoadEnd, RouteConfigLoadStart, Router} from '@angular/router'; import {clone} from 'lodash-es'; @@ -28,18 +28,18 @@ function getTabId(tab: MatTab): string { }) export class NaturalLinkableTabDirective implements AfterViewInit { private readonly destroyRef = inject(DestroyRef); + private readonly component = inject(MatTabGroup); + private readonly route = inject(ActivatedRoute); + private readonly router = inject(Router); + /** * If false, disables the persistent navigation */ @Input() public naturalLinkableTab: boolean | '' = true; private isLoadingRouteConfig = false; - public constructor( - private readonly component: MatTabGroup, - private readonly route: ActivatedRoute, - private readonly router: Router, - ) { - router.events.pipe(takeUntilDestroyed()).subscribe(event => { + public constructor() { + this.router.events.pipe(takeUntilDestroyed()).subscribe(event => { if (event instanceof RouteConfigLoadStart) { this.isLoadingRouteConfig = true; } else if (event instanceof RouteConfigLoadEnd) { diff --git a/projects/natural/src/lib/modules/common/directives/src-density.directive.ts b/projects/natural/src/lib/modules/common/directives/src-density.directive.ts index 8ff81941..1ca4eb95 100644 --- a/projects/natural/src/lib/modules/common/directives/src-density.directive.ts +++ b/projects/natural/src/lib/modules/common/directives/src-density.directive.ts @@ -1,4 +1,4 @@ -import {Directive, ElementRef, Input} from '@angular/core'; +import {Directive, ElementRef, Input, inject} from '@angular/core'; export function densities(src: string, forImageSet: boolean): string { const match = /^(.*\/)(\d+)$/.exec(src); @@ -33,6 +33,8 @@ export function densities(src: string, forImageSet: boolean): string { standalone: true, }) export class NaturalSrcDensityDirective { + private readonly elementRef = inject>(ElementRef); + /** * Automatically apply image selection based on screen density. * @@ -67,6 +69,4 @@ export class NaturalSrcDensityDirective { this.elementRef.nativeElement.src = src; this.elementRef.nativeElement.srcset = densities(src, false); } - - public constructor(private readonly elementRef: ElementRef) {} } diff --git a/projects/natural/src/lib/modules/common/pipes/enum.pipe.ts b/projects/natural/src/lib/modules/common/pipes/enum.pipe.ts index 65bb2efa..ff3a5d02 100644 --- a/projects/natural/src/lib/modules/common/pipes/enum.pipe.ts +++ b/projects/natural/src/lib/modules/common/pipes/enum.pipe.ts @@ -1,4 +1,4 @@ -import {Pipe, PipeTransform} from '@angular/core'; +import {Pipe, PipeTransform, inject} from '@angular/core'; import {NaturalEnumService} from '../../../services/enum.service'; import {Observable} from 'rxjs'; @@ -12,7 +12,7 @@ import {Observable} from 'rxjs'; standalone: true, }) export class NaturalEnumPipe implements PipeTransform { - public constructor(private readonly enumService: NaturalEnumService) {} + private readonly enumService = inject(NaturalEnumService); public transform(value: any, enumName: string): Observable { return this.enumService.getValueName(value, enumName); diff --git a/projects/natural/src/lib/modules/common/public-api.ts b/projects/natural/src/lib/modules/common/public-api.ts index 02259242..9254e21f 100644 --- a/projects/natural/src/lib/modules/common/public-api.ts +++ b/projects/natural/src/lib/modules/common/public-api.ts @@ -10,10 +10,9 @@ export {NaturalTimeAgoPipe} from './pipes/time-ago.pipe'; export * from './services/memory-storage'; export {NaturalSrcDensityDirective} from './directives/src-density.directive'; export {NaturalBackgroundDensityDirective} from './directives/background-density.directive'; -export { - NATURAL_SEO_CONFIG, +export {NATURAL_SEO_CONFIG, NaturalSeoService} from './services/seo.service'; +export type { NaturalSeoConfig, - NaturalSeoService, NaturalSeo, NaturalSeoBasic, NaturalSeoResolve, diff --git a/projects/natural/src/lib/modules/common/services/seo.service.ts b/projects/natural/src/lib/modules/common/services/seo.service.ts index 44237a06..8a981774 100644 --- a/projects/natural/src/lib/modules/common/services/seo.service.ts +++ b/projects/natural/src/lib/modules/common/services/seo.service.ts @@ -1,5 +1,5 @@ import {DOCUMENT} from '@angular/common'; -import {Inject, Injectable, InjectionToken, LOCALE_ID} from '@angular/core'; +import {Injectable, InjectionToken, LOCALE_ID, inject} from '@angular/core'; import {Meta, Title} from '@angular/platform-browser'; import {ActivatedRouteSnapshot, Data, NavigationEnd, PRIMARY_OUTLET, Router} from '@angular/router'; import {NaturalDialogTriggerComponent} from '../../dialog-trigger/dialog-trigger.component'; @@ -147,19 +147,20 @@ type ResolvedData = { providedIn: 'root', }) export class NaturalSeoService { + private readonly router = inject(Router); + private readonly titleService = inject(Title); + private readonly metaTagService = inject(Meta); + private readonly document = inject(DOCUMENT); + private locale = inject(LOCALE_ID); + private routeData?: Data; private config: NaturalSeoConfigPlain = { applicationName: '', }; - public constructor( - @Inject(NATURAL_SEO_CONFIG) configToken: NaturalSeoConfig, - private readonly router: Router, - private readonly titleService: Title, - private readonly metaTagService: Meta, - @Inject(DOCUMENT) private readonly document: Document, - @Inject(LOCALE_ID) private locale: string, - ) { + public constructor() { + const configToken = inject(NATURAL_SEO_CONFIG); + combineLatest({ config: configToken instanceof Observable ? configToken.pipe(startWith(this.config)) : of(configToken), navigationEnd: this.router.events.pipe(filter(event => event instanceof NavigationEnd)), diff --git a/projects/natural/src/lib/modules/dialog-trigger/dialog-trigger.component.ts b/projects/natural/src/lib/modules/dialog-trigger/dialog-trigger.component.ts index 3e50ee74..62be9e26 100644 --- a/projects/natural/src/lib/modules/dialog-trigger/dialog-trigger.component.ts +++ b/projects/natural/src/lib/modules/dialog-trigger/dialog-trigger.component.ts @@ -1,5 +1,5 @@ import {ComponentType} from '@angular/cdk/portal'; -import {Component, OnDestroy} from '@angular/core'; +import {Component, OnDestroy, inject} from '@angular/core'; import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog'; import {ActivatedRoute, Router, RouterLink} from '@angular/router'; @@ -22,15 +22,15 @@ export type NaturalDialogTriggerRedirectionValues = RouterLink['routerLink'] | n standalone: true, }) export class NaturalDialogTriggerComponent implements OnDestroy { + private readonly dialog = inject(MatDialog); + private readonly route = inject(ActivatedRoute); + private readonly router = inject(Router); + private readonly dialogRef: MatDialogRef; private readonly triggerConfig: NaturalDialogTriggerRoutingData; - public constructor( - private readonly dialog: MatDialog, - private readonly route: ActivatedRoute, - private readonly router: Router, - ) { + public constructor() { // Data from activated route this.triggerConfig = this.route.snapshot.data.trigger as NaturalDialogTriggerRoutingData; diff --git a/projects/natural/src/lib/modules/dropdown-components/public-api.ts b/projects/natural/src/lib/modules/dropdown-components/public-api.ts index cb2a0360..4d43c40c 100644 --- a/projects/natural/src/lib/modules/dropdown-components/public-api.ts +++ b/projects/natural/src/lib/modules/dropdown-components/public-api.ts @@ -1,26 +1,34 @@ /* * Public API Surface of natural-search dropdown components */ -export {TypeSelectConfiguration, TypeSelectItem, TypeSelectComponent} from './type-select/type-select.component'; +export { + type TypeSelectConfiguration, + type TypeSelectItem, + TypeSelectComponent, +} from './type-select/type-select.component'; export { - TypeSelectNaturalConfiguration, + type TypeSelectNaturalConfiguration, TypeNaturalSelectComponent, } from './type-natural-select/type-natural-select.component'; -export {TypeNumberConfiguration, TypeNumberComponent} from './type-number/type-number.component'; +export {type TypeNumberConfiguration, TypeNumberComponent} from './type-number/type-number.component'; export { - TypeHierarchicSelectorConfiguration, + type TypeHierarchicSelectorConfiguration, TypeHierarchicSelectorComponent, } from './type-hierarchic-selector/type-hierarchic-selector.component'; -export {TypeDateConfiguration, TypeDateComponent} from './type-date/type-date.component'; +export {type TypeDateConfiguration, TypeDateComponent} from './type-date/type-date.component'; -export {TypeDateRangeConfiguration, TypeDateRangeComponent} from './type-date-range/type-date-range.component'; +export {type TypeDateRangeConfiguration, TypeDateRangeComponent} from './type-date-range/type-date-range.component'; export {TypeTextComponent, InvalidWithValueStateMatcher} from './type-text/type-text.component'; -export {TypeBooleanConfiguration, TypeBooleanComponent} from './type-boolean/type-boolean.component'; -export {TypeOptionsConfiguration, TypeOption, TypeOptionsComponent} from './type-options/type-options.component'; -export {possibleComparableOperators, PossibleComparableOpertorKeys} from './types'; +export {type TypeBooleanConfiguration, TypeBooleanComponent} from './type-boolean/type-boolean.component'; +export { + type TypeOptionsConfiguration, + type TypeOption, + TypeOptionsComponent, +} from './type-options/type-options.component'; +export {possibleComparableOperators, type PossibleComparableOpertorKeys} from './types'; diff --git a/projects/natural/src/lib/modules/dropdown-components/type-boolean/type-boolean.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-boolean/type-boolean.component.ts index e6f5ae6d..9e07adab 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-boolean/type-boolean.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-boolean/type-boolean.component.ts @@ -1,10 +1,9 @@ import {CommonModule} from '@angular/common'; -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import {NATURAL_DROPDOWN_DATA, NaturalDropdownData} from '../../search/dropdown-container/dropdown.service'; import {DropdownComponent} from '../../search/types/dropdown-component'; import {TypeOptionsComponent, TypeOptionsConfiguration} from '../type-options/type-options.component'; -import {NaturalDropdownRef} from '../../search/dropdown-container/dropdown-ref'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; export type TypeBooleanConfiguration = { @@ -18,10 +17,9 @@ export type TypeBooleanConfiguration = { imports: [FormsModule, ReactiveFormsModule, CommonModule, MatButtonToggleModule], }) export class TypeBooleanComponent extends TypeOptionsComponent implements DropdownComponent { - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData, - dropdownRef: NaturalDropdownRef, - ) { + public constructor() { + const data = inject>(NATURAL_DROPDOWN_DATA); + // Set up options from hardcoded conditions with custom labels from config const configuration: TypeOptionsConfiguration = { options: [ @@ -41,6 +39,6 @@ export class TypeBooleanComponent extends TypeOptionsComponent implements Dropdo ...{configuration: configuration}, }; - super(typeOptionsData, dropdownRef); + super(typeOptionsData); } } diff --git a/projects/natural/src/lib/modules/dropdown-components/type-date-range/type-date-range.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-date-range/type-date-range.component.ts index 1ae4ee48..ee4c3605 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-date-range/type-date-range.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-date-range/type-date-range.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import { AbstractControl, FormControl, @@ -68,6 +68,9 @@ function toGreaterThanFrom(dateAdapter: DateAdapter): ValidatorFn { imports: [FormsModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatDatepickerModule], }) export class TypeDateRangeComponent implements DropdownComponent { + private dateAdapter = inject>(DateAdapter); + private dateFormats = inject(MAT_DATE_FORMATS); + public readonly renderedValue = new BehaviorSubject(''); public readonly configuration: Required>; public readonly matcher = new InvalidWithValueStateMatcher(); @@ -83,11 +86,9 @@ export class TypeDateRangeComponent implements DropdownComponent { max: null, }; - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData>, - private dateAdapter: DateAdapter, - @Inject(MAT_DATE_FORMATS) private dateFormats: MatDateFormats, - ) { + public constructor() { + const data = inject>>(NATURAL_DROPDOWN_DATA); + this.configuration = {...this.defaults, ...data.configuration}; merge(this.fromCtrl.valueChanges, this.toCtrl.valueChanges).subscribe(() => { diff --git a/projects/natural/src/lib/modules/dropdown-components/type-date/type-date.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-date/type-date.component.ts index 86d086b7..89569aa3 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-date/type-date.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-date/type-date.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {FormControl, FormGroup, ValidatorFn, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {DateAdapter, MAT_DATE_FORMATS, MatDateFormats, MatOptionModule} from '@angular/material/core'; import {BehaviorSubject, merge} from 'rxjs'; @@ -35,6 +35,9 @@ export type TypeDateConfiguration = { ], }) export class TypeDateComponent implements DropdownComponent { + private dateAdapter = inject>(DateAdapter); + private dateFormats = inject(MAT_DATE_FORMATS); + public readonly renderedValue = new BehaviorSubject(''); public readonly configuration: Required>; public readonly operatorCtrl = new FormControl('equal', {nonNullable: true}); @@ -53,11 +56,9 @@ export class TypeDateComponent implements DropdownComponent { max: null, }; - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData>, - private dateAdapter: DateAdapter, - @Inject(MAT_DATE_FORMATS) private dateFormats: MatDateFormats, - ) { + public constructor() { + const data = inject>>(NATURAL_DROPDOWN_DATA); + this.configuration = {...this.defaults, ...data.configuration}; this.todayCtrl.valueChanges.pipe(takeUntilDestroyed()).subscribe(isToday => { diff --git a/projects/natural/src/lib/modules/dropdown-components/type-number/type-number.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-number/type-number.component.ts index 9b7edf21..e4db24d4 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-number/type-number.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-number/type-number.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {FormControl, FormGroup, ValidatorFn, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {BehaviorSubject, merge} from 'rxjs'; import {FilterGroupConditionField} from '../../search/classes/graphql-doctrine.types'; @@ -26,6 +26,8 @@ export type TypeNumberConfiguration = { imports: [FormsModule, ReactiveFormsModule, MatFormFieldModule, MatSelectModule, MatOptionModule, MatInputModule], }) export class TypeNumberComponent implements DropdownComponent { + protected dropdownRef = inject(NaturalDropdownRef); + public readonly renderedValue = new BehaviorSubject(''); public readonly configuration: Required; public readonly operatorCtrl = new FormControl('equal', {nonNullable: true}); @@ -43,10 +45,9 @@ export class TypeNumberComponent implements DropdownComponent { step: null, }; - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData, - protected dropdownRef: NaturalDropdownRef, - ) { + public constructor() { + const data = inject>(NATURAL_DROPDOWN_DATA); + this.configuration = {...this.defaults, ...data.configuration}; merge(this.operatorCtrl.valueChanges, this.valueCtrl.valueChanges).subscribe(() => { diff --git a/projects/natural/src/lib/modules/dropdown-components/type-options/type-options.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-options/type-options.component.ts index c69b0fa4..1809ed64 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-options/type-options.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-options/type-options.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject, Inject} from '@angular/core'; import {FormControl, FormsModule, ReactiveFormsModule, Validators} from '@angular/forms'; import {MatButtonToggleModule} from '@angular/material/button-toggle'; import {BehaviorSubject} from 'rxjs'; @@ -33,10 +33,10 @@ export class TypeOptionsComponent implements DropdownComponent { private readonly defaults: Required = { options: [], }; + protected readonly dropdownRef = inject(NaturalDropdownRef); public constructor( - @Inject(NATURAL_DROPDOWN_DATA) public data: NaturalDropdownData, - protected dropdownRef: NaturalDropdownRef, + @Inject(NATURAL_DROPDOWN_DATA) public readonly data: NaturalDropdownData, ) { this.configuration = {...this.defaults, ...data.configuration}; diff --git a/projects/natural/src/lib/modules/dropdown-components/type-select/type-select.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-select/type-select.component.ts index f2fad13f..6f46d3fb 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-select/type-select.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-select/type-select.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, DestroyRef, inject, Inject, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, DestroyRef, inject, ViewChild} from '@angular/core'; import {MatListModule, MatSelectionList} from '@angular/material/list'; import {BehaviorSubject, merge, Observable, of} from 'rxjs'; import {FilterGroupConditionField, Scalar} from '../../search/classes/graphql-doctrine.types'; @@ -59,7 +59,9 @@ export class TypeSelectComponent implements DropdownComponent, AfterViewInit { operators: true, }; - public constructor(@Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData) { + public constructor() { + const data = inject>(NATURAL_DROPDOWN_DATA); + this.configuration = {...this.defaults, ...data.configuration}; // Immediately initValidators and everytime the operator change later diff --git a/projects/natural/src/lib/modules/dropdown-components/type-text/type-text.component.ts b/projects/natural/src/lib/modules/dropdown-components/type-text/type-text.component.ts index 54a338de..a40ef46c 100644 --- a/projects/natural/src/lib/modules/dropdown-components/type-text/type-text.component.ts +++ b/projects/natural/src/lib/modules/dropdown-components/type-text/type-text.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {FormControl, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms'; import {ErrorStateMatcher} from '@angular/material/core'; import {BehaviorSubject} from 'rxjs'; @@ -25,14 +25,15 @@ export class InvalidWithValueStateMatcher implements ErrorStateMatcher { imports: [MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule], }) export class TypeTextComponent implements DropdownComponent { + protected dropdownRef = inject(NaturalDropdownRef); + public readonly renderedValue = new BehaviorSubject(''); public readonly formCtrl = new FormControl('', {nonNullable: true}); public readonly matcher = new InvalidWithValueStateMatcher(); - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) data: NaturalDropdownData, - protected dropdownRef: NaturalDropdownRef, - ) { + public constructor() { + const data = inject>(NATURAL_DROPDOWN_DATA); + this.formCtrl.valueChanges.subscribe(value => { this.renderedValue.next(value === null ? '' : this.formCtrl.value + ''); }); diff --git a/projects/natural/src/lib/modules/file/component/file.component.ts b/projects/natural/src/lib/modules/file/component/file.component.ts index 3895d816..1f6b6879 100644 --- a/projects/natural/src/lib/modules/file/component/file.component.ts +++ b/projects/natural/src/lib/modules/file/component/file.component.ts @@ -2,12 +2,12 @@ import { Component, EventEmitter, HostBinding, - Inject, Input, OnChanges, OnInit, Output, SimpleChanges, + inject, } from '@angular/core'; import {AbstractControl} from '@angular/forms'; import {Observable, of, Subject, tap} from 'rxjs'; @@ -39,6 +39,10 @@ import {NaturalBackgroundDensityDirective} from '../../common/directives/backgro ], }) export class NaturalFileComponent implements OnInit, OnChanges { + private readonly naturalFileService = inject(NaturalFileService); + private readonly alertService = inject(NaturalAlertService); + private readonly document = inject(DOCUMENT); + @HostBinding('style.height.px') @Input() public height = 250; @Input() public action: 'upload' | 'download' | null = null; @@ -86,12 +90,6 @@ export class NaturalFileComponent implements OnInit, OnChanges { public imagePreview = ''; public filePreview: string | null = null; - public constructor( - private readonly naturalFileService: NaturalFileService, - private readonly alertService: NaturalAlertService, - @Inject(DOCUMENT) private readonly document: Document, - ) {} - public ngOnChanges(changes: SimpleChanges): void { if (changes.model && changes.model.previousValue !== changes.model.currentValue) { this.updateImage(); diff --git a/projects/natural/src/lib/modules/file/file.service.ts b/projects/natural/src/lib/modules/file/file.service.ts index 1efc7f76..73596600 100644 --- a/projects/natural/src/lib/modules/file/file.service.ts +++ b/projects/natural/src/lib/modules/file/file.service.ts @@ -1,4 +1,4 @@ -import {Inject, Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Subject} from 'rxjs'; import {FileSelection} from './abstract-file'; import {FileModel} from './types'; @@ -9,6 +9,8 @@ import {DOCUMENT} from '@angular/common'; providedIn: 'root', }) export class NaturalFileService { + private readonly document = inject(DOCUMENT); + /** * Allow to subscribe to selected files in the entire application. So a * child component is able to receive a file that was dropped on a parent @@ -19,8 +21,6 @@ export class NaturalFileService { */ public readonly filesChanged = new Subject(); - public constructor(@Inject(DOCUMENT) private readonly document: Document) {} - public getDownloadLink(model: FileModel | null): null | string { const window = this.document.defaultView; if (!window) { diff --git a/projects/natural/src/lib/modules/file/public-api.ts b/projects/natural/src/lib/modules/file/public-api.ts index cd2d969c..2bd308da 100644 --- a/projects/natural/src/lib/modules/file/public-api.ts +++ b/projects/natural/src/lib/modules/file/public-api.ts @@ -5,6 +5,6 @@ export * from './file-drop.directive'; export * from './file-select.directive'; export * from './file.service'; -export {InvalidFile, FileSelection} from './abstract-file'; +export type {InvalidFile, FileSelection} from './abstract-file'; export * from './component/file.component'; export * from './types'; diff --git a/projects/natural/src/lib/modules/fixed-button-detail/fixed-button-detail.component.ts b/projects/natural/src/lib/modules/fixed-button-detail/fixed-button-detail.component.ts index 4d27beb5..eeb488c6 100644 --- a/projects/natural/src/lib/modules/fixed-button-detail/fixed-button-detail.component.ts +++ b/projects/natural/src/lib/modules/fixed-button-detail/fixed-button-detail.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, Output} from '@angular/core'; +import {Component, EventEmitter, Input, Output, inject} from '@angular/core'; import {FormGroup} from '@angular/forms'; import {ActivatedRoute} from '@angular/router'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; @@ -43,7 +43,9 @@ export class NaturalFixedButtonDetailComponent { @Output() public readonly create = new EventEmitter(); @Output() public readonly delete = new EventEmitter(); - public constructor(route: ActivatedRoute) { + public constructor() { + const route = inject(ActivatedRoute); + route.params.pipe(takeUntilDestroyed()).subscribe(() => (this.canChange = true)); } diff --git a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.component.ts b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.component.ts index 4725b319..cbfec337 100644 --- a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.component.ts +++ b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef, MatDialogModule} from '@angular/material/dialog'; import {clone, defaults} from 'lodash-es'; import {NaturalSearchFacets} from '../../search/types/facet'; @@ -58,6 +58,9 @@ export type HierarchicDialogConfig = { imports: [MatDialogModule, NaturalHierarchicSelectorComponent, MatButtonModule], }) export class NaturalHierarchicSelectorDialogComponent { + private dialogRef = + inject>(MatDialogRef); + /** * Set of hierarchic configurations to pass as attribute to HierarchicComponent */ @@ -68,10 +71,9 @@ export class NaturalHierarchicSelectorDialogComponent { */ public searchSelectionsOutput: NaturalSearchSelections | undefined | null; - public constructor( - @Inject(MAT_DIALOG_DATA) data: HierarchicDialogConfig, - private dialogRef: MatDialogRef, - ) { + public constructor() { + const data = inject(MAT_DIALOG_DATA); + this.config = defaults(data, {multiple: true, allowUnselect: true}); this.searchSelectionsOutput = this.config.searchSelections; } diff --git a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.service.ts b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.service.ts index 6f31a144..3376d8fc 100644 --- a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.service.ts +++ b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.service.ts @@ -1,4 +1,4 @@ -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog'; import {defaults} from 'lodash-es'; import { @@ -9,7 +9,7 @@ import { @Injectable({providedIn: 'root'}) export class NaturalHierarchicSelectorDialogService { - public constructor(private readonly dialog: MatDialog) {} + private readonly dialog = inject(MatDialog); public open( hierarchicConfig: HierarchicDialogConfig, diff --git a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.component.ts b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.component.ts index 15791b1b..67c58efc 100644 --- a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.component.ts +++ b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.component.ts @@ -55,6 +55,8 @@ import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; }) export class NaturalHierarchicSelectorComponent implements OnInit, OnChanges { private readonly destroyRef = inject(DestroyRef); + private readonly hierarchicSelectorService = inject(NaturalHierarchicSelectorService); + /** * Function that receives a model and returns a string for display value */ @@ -128,8 +130,6 @@ export class NaturalHierarchicSelectorComponent implements OnInit, OnChanges { */ private flatNodeMap: Map = new Map(); - public constructor(private readonly hierarchicSelectorService: NaturalHierarchicSelectorService) {} - /** * Angular OnChange implementation */ diff --git a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.service.ts b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.service.ts index 95e8839e..1eb75068 100644 --- a/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.service.ts +++ b/projects/natural/src/lib/modules/hierarchic-selector/hierarchic-selector/hierarchic-selector.service.ts @@ -1,4 +1,4 @@ -import {Injectable, Injector} from '@angular/core'; +import {Injectable, Injector, inject} from '@angular/core'; import {intersection} from 'lodash-es'; import {BehaviorSubject, first, forkJoin, Observable} from 'rxjs'; import {finalize, map} from 'rxjs/operators'; @@ -25,6 +25,8 @@ type ContextualizedConfig = { @Injectable({providedIn: 'root'}) export class NaturalHierarchicSelectorService { + private readonly injector = inject(Injector); + /** * Stores the global result of the tree * This observable contains Node. @@ -39,8 +41,6 @@ export class NaturalHierarchicSelectorService { */ private configuration: NaturalHierarchicConfiguration[] = []; - public constructor(private readonly injector: Injector) {} - /** * Init component by saving the complete configuration, and then retrieving root elements. * Updates **another** observable (this.dataChange) when data is retrieved. diff --git a/projects/natural/src/lib/modules/icon/icon.directive.ts b/projects/natural/src/lib/modules/icon/icon.directive.ts index 73da95bc..dfc7ffb8 100644 --- a/projects/natural/src/lib/modules/icon/icon.directive.ts +++ b/projects/natural/src/lib/modules/icon/icon.directive.ts @@ -1,4 +1,4 @@ -import {Directive, Host, HostBinding, Inject, InjectionToken, Input, Optional, Self} from '@angular/core'; +import {Directive, HostBinding, InjectionToken, Input, inject} from '@angular/core'; import {MatIcon, MatIconRegistry} from '@angular/material/icon'; import {DomSanitizer} from '@angular/platform-browser'; @@ -42,6 +42,11 @@ const naturalRegistered: unique symbol = Symbol('Natural icon registered'); standalone: true, }) export class NaturalIconDirective { + private readonly matIconRegistry = inject(MatIconRegistry); + private readonly domSanitizer = inject(DomSanitizer); + private readonly config = inject(NATURAL_ICONS_CONFIG, {optional: true}); + private readonly matIconComponent = inject(MatIcon, {host: true, self: true}); + @HostBinding('style.font-size.px') @HostBinding('style.min-height.px') @HostBinding('style.min-width.px') @@ -49,12 +54,9 @@ export class NaturalIconDirective { @HostBinding('class') private classes = ''; - public constructor( - private readonly matIconRegistry: MatIconRegistry, - private readonly domSanitizer: DomSanitizer, - @Optional() @Inject(NATURAL_ICONS_CONFIG) private readonly config: NaturalIconsConfig | null, - @Host() @Self() public readonly matIconComponent: MatIcon, - ) { + public constructor() { + const config = this.config; + this.registerIcons(config ?? {}); } diff --git a/projects/natural/src/lib/modules/logger/error-handler.ts b/projects/natural/src/lib/modules/logger/error-handler.ts index 22b5ac2d..3a7aa047 100644 --- a/projects/natural/src/lib/modules/logger/error-handler.ts +++ b/projects/natural/src/lib/modules/logger/error-handler.ts @@ -1,6 +1,6 @@ import {DOCUMENT} from '@angular/common'; import {HttpClient, HttpHeaders} from '@angular/common/http'; -import {ErrorHandler, Inject, Injectable, InjectionToken, Optional} from '@angular/core'; +import {ErrorHandler, Injectable, InjectionToken, inject} from '@angular/core'; import {catchError, EMPTY, first, Observable, of} from 'rxjs'; export type NaturalLoggerType = { @@ -47,12 +47,12 @@ export const NaturalLoggerConfigExtra = new InjectionToken( providedIn: 'root', }) export class NaturalErrorHandler extends ErrorHandler { - public constructor( - private readonly http: HttpClient, - @Inject(DOCUMENT) private readonly document: Document, - @Optional() @Inject(NaturalLoggerConfigUrl) private readonly url: string, - @Optional() @Inject(NaturalLoggerConfigExtra) private readonly loggerExtra?: NaturalLoggerExtra, - ) { + private readonly http = inject(HttpClient); + private readonly document = inject(DOCUMENT); + private readonly url = inject(NaturalLoggerConfigUrl, {optional: true}); + private readonly loggerExtra = inject(NaturalLoggerConfigExtra, {optional: true}); + + public constructor() { super(); } diff --git a/projects/natural/src/lib/modules/logger/public-api.ts b/projects/natural/src/lib/modules/logger/public-api.ts index 6ed86829..a0e981bd 100644 --- a/projects/natural/src/lib/modules/logger/public-api.ts +++ b/projects/natural/src/lib/modules/logger/public-api.ts @@ -4,10 +4,5 @@ export {provideErrorHandler} from './error.module'; -export { - NaturalErrorHandler, - NaturalLoggerConfigExtra, - NaturalLoggerConfigUrl, - NaturalLoggerExtra, - NaturalLoggerType, -} from './error-handler'; +export {NaturalErrorHandler, NaturalLoggerConfigExtra, NaturalLoggerConfigUrl} from './error-handler'; +export type {NaturalLoggerExtra, NaturalLoggerType} from './error-handler'; diff --git a/projects/natural/src/lib/modules/matomo/matomo.service.ts b/projects/natural/src/lib/modules/matomo/matomo.service.ts index 9330ce5b..3240f879 100644 --- a/projects/natural/src/lib/modules/matomo/matomo.service.ts +++ b/projects/natural/src/lib/modules/matomo/matomo.service.ts @@ -1,4 +1,4 @@ -import {Inject, Injectable, PLATFORM_ID} from '@angular/core'; +import {inject, Injectable, PLATFORM_ID} from '@angular/core'; import {NavigationEnd, Router} from '@angular/router'; import {DOCUMENT, isPlatformBrowser} from '@angular/common'; import {Subscription} from 'rxjs'; @@ -34,18 +34,16 @@ type Paq = { providedIn: 'root', }) export class NaturalMatomoService { - private subscription: Subscription | null = null; - private readonly isBrowser: boolean; + private readonly router = inject(Router); + private readonly document = inject(DOCUMENT); + private readonly titleService = inject(Title); + private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID)); private readonly window: WindowProxy & typeof globalThis & {_paq?: Paq}; + + private subscription: Subscription | null = null; private referrerUrl = ''; - public constructor( - private readonly router: Router, - @Inject(DOCUMENT) private readonly document: Document, - @Inject(PLATFORM_ID) public readonly platformId: object, - private readonly titleService: Title, - ) { - this.isBrowser = isPlatformBrowser(platformId); + public constructor() { const window = this.document.defaultView; if (!window) { throw new Error('Could not init MatomoService `window` is undefined'); diff --git a/projects/natural/src/lib/modules/panels/panels.component.ts b/projects/natural/src/lib/modules/panels/panels.component.ts index 27b45b09..bddfc100 100644 --- a/projects/natural/src/lib/modules/panels/panels.component.ts +++ b/projects/natural/src/lib/modules/panels/panels.component.ts @@ -1,4 +1,4 @@ -import {Component, OnDestroy} from '@angular/core'; +import {Component, OnDestroy, inject} from '@angular/core'; import {ActivatedRoute} from '@angular/router'; import {NaturalPanelsService} from './panels.service'; @@ -8,12 +8,13 @@ import {NaturalPanelsService} from './panels.service'; standalone: true, }) export class NaturalPanelsComponent implements OnDestroy { + private readonly panelsService = inject(NaturalPanelsService); + // PanelsComponent is kind of a "ghost" component to respond to an url matcher in route config, // An UrlMatcher (matcher attribute) is required to catch urls with an undefined number of params in url after a given param /panels/ - public constructor( - private readonly panelsService: NaturalPanelsService, - route: ActivatedRoute, - ) { + public constructor() { + const route = inject(ActivatedRoute); + this.panelsService.start(route); } diff --git a/projects/natural/src/lib/modules/panels/panels.service.ts b/projects/natural/src/lib/modules/panels/panels.service.ts index 6c9d1f05..49a8f32c 100644 --- a/projects/natural/src/lib/modules/panels/panels.service.ts +++ b/projects/natural/src/lib/modules/panels/panels.service.ts @@ -1,6 +1,6 @@ import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout'; import {ComponentType} from '@angular/cdk/portal'; -import {Inject, Injectable, Injector, runInInjectionContext} from '@angular/core'; +import {Injectable, Injector, runInInjectionContext, inject} from '@angular/core'; import {takeUntilDestroyed} from '@angular/core/rxjs-interop'; import {MatDialog, MatDialogConfig} from '@angular/material/dialog'; import {ActivatedRoute, DefaultUrlSerializer, NavigationError, Router, UrlSegment} from '@angular/router'; @@ -33,6 +33,11 @@ function compareConfigs(a: NaturalPanelConfig, b: NaturalPanelConfig): boolean { providedIn: 'root', }) export class NaturalPanelsService { + private readonly router = inject(Router); + private readonly dialog = inject(MatDialog); + private readonly injector = inject(Injector); + private hooksConfig = inject(PanelsHooksConfig); + private readonly panelWidth = '960px'; /** @@ -91,13 +96,9 @@ export class NaturalPanelsService { */ private isVertical = false; - public constructor( - private readonly router: Router, - private readonly dialog: MatDialog, - private readonly injector: Injector, - @Inject(PanelsHooksConfig) private hooksConfig: NaturalPanelsHooksConfig, - breakpointObserver: BreakpointObserver, - ) { + public constructor() { + const breakpointObserver = inject(BreakpointObserver); + // Watch media to know if display panels horizontally or vertically breakpointObserver .observe(Breakpoints.XSmall) diff --git a/projects/natural/src/lib/modules/relations/relations.component.ts b/projects/natural/src/lib/modules/relations/relations.component.ts index 71f8cabd..565a168e 100644 --- a/projects/natural/src/lib/modules/relations/relations.component.ts +++ b/projects/natural/src/lib/modules/relations/relations.component.ts @@ -14,7 +14,7 @@ import { import {MatPaginatorModule, PageEvent} from '@angular/material/paginator'; import {NaturalDataSource, PaginatedData} from '../../classes/data-source'; import {NaturalQueryVariablesManager, PaginationInput, QueryVariables} from '../../classes/query-variable-manager'; -import {HierarchicFiltersConfiguration} from '../../modules/hierarchic-selector/classes/hierarchic-filters-configuration'; +import {HierarchicFiltersConfiguration} from '../hierarchic-selector/classes/hierarchic-filters-configuration'; import {LinkableObject, NaturalLinkMutationService} from '../../services/link-mutation.service'; import {NaturalHierarchicConfiguration} from '../hierarchic-selector/classes/hierarchic-configuration'; import {HierarchicDialogConfig} from '../hierarchic-selector/hierarchic-selector-dialog/hierarchic-selector-dialog.component'; @@ -77,6 +77,8 @@ export class NaturalRelationsComponent< implements OnInit, OnChanges { private readonly destroyRef = inject(DestroyRef); + private readonly linkMutationService = inject(NaturalLinkMutationService); + private readonly hierarchicSelectorDialog = inject(NaturalHierarchicSelectorDialogService); @ViewChild(NaturalSelectComponent) private select?: NaturalSelectComponent; @ContentChild(TemplateRef) public itemTemplate?: TemplateRef; @@ -171,11 +173,6 @@ export class NaturalRelationsComponent< public readonly removing = new Set(); - public constructor( - private readonly linkMutationService: NaturalLinkMutationService, - private readonly hierarchicSelectorDialog: NaturalHierarchicSelectorDialogService, - ) {} - /** * The filter used to filter relations * diff --git a/projects/natural/src/lib/modules/search/dropdown-container/dropdown-container.component.ts b/projects/natural/src/lib/modules/search/dropdown-container/dropdown-container.component.ts index 36df7d5c..68f1a249 100644 --- a/projects/natural/src/lib/modules/search/dropdown-container/dropdown-container.component.ts +++ b/projects/natural/src/lib/modules/search/dropdown-container/dropdown-container.component.ts @@ -6,12 +6,12 @@ import { ComponentRef, ElementRef, EmbeddedViewRef, - Inject, InjectionToken, OnDestroy, TemplateRef, ViewChild, ViewEncapsulation, + inject, } from '@angular/core'; import {Subject} from 'rxjs'; import {naturalDropdownAnimations} from './dropdown-container-animations'; @@ -40,6 +40,10 @@ export const NATURAL_DROPDOWN_CONTAINER_DATA = new InjectionToken>(ElementRef); + private readonly focusTrapFactory = inject(ConfigurableFocusTrapFactory); + public readonly data = inject(NATURAL_DROPDOWN_CONTAINER_DATA); + @ViewChild(CdkPortalOutlet, {static: true}) public portalOutlet!: CdkPortalOutlet; @ViewChild(TemplateRef, {static: true}) public templateRef!: TemplateRef; @@ -54,11 +58,7 @@ export class NaturalDropdownContainerComponent extends BasePortalOutlet implemen private focusTrap: FocusTrap | null = null; private elementFocusedBeforeDialogWasOpened: HTMLElement | null = null; - public constructor( - private readonly elementRef: ElementRef, - private readonly focusTrapFactory: ConfigurableFocusTrapFactory, - @Inject(NATURAL_DROPDOWN_CONTAINER_DATA) public data: NaturalDropdownContainerData, - ) { + public constructor() { super(); } diff --git a/projects/natural/src/lib/modules/search/dropdown-container/dropdown.service.ts b/projects/natural/src/lib/modules/search/dropdown-container/dropdown.service.ts index e262ae46..cea462aa 100644 --- a/projects/natural/src/lib/modules/search/dropdown-container/dropdown.service.ts +++ b/projects/natural/src/lib/modules/search/dropdown-container/dropdown.service.ts @@ -1,6 +1,6 @@ import {FlexibleConnectedPositionStrategy, Overlay, OverlayConfig} from '@angular/cdk/overlay'; import {ComponentPortal, ComponentType} from '@angular/cdk/portal'; -import {ComponentRef, ElementRef, Injectable, InjectionToken, Injector, StaticProvider} from '@angular/core'; +import {ComponentRef, ElementRef, Injectable, InjectionToken, Injector, StaticProvider, inject} from '@angular/core'; import {takeUntil} from 'rxjs/operators'; import {FilterGroupConditionField} from '../classes/graphql-doctrine.types'; import { @@ -23,10 +23,8 @@ export const NATURAL_DROPDOWN_DATA = new InjectionToken('Na providedIn: 'root', }) export class NaturalDropdownService { - public constructor( - private readonly overlay: Overlay, - private readonly injector: Injector, - ) {} + private readonly overlay = inject(Overlay); + private readonly injector = inject(Injector); public open( component: ComponentType, diff --git a/projects/natural/src/lib/modules/search/facet-selector/facet-selector.component.ts b/projects/natural/src/lib/modules/search/facet-selector/facet-selector.component.ts index f5130d3d..bccb78a0 100644 --- a/projects/natural/src/lib/modules/search/facet-selector/facet-selector.component.ts +++ b/projects/natural/src/lib/modules/search/facet-selector/facet-selector.component.ts @@ -1,4 +1,4 @@ -import {Component, Inject} from '@angular/core'; +import {Component, inject} from '@angular/core'; import {BehaviorSubject} from 'rxjs'; import {FilterGroupConditionField} from '../../search/classes/graphql-doctrine.types'; import {NaturalDropdownRef} from '../../search/dropdown-container/dropdown-ref'; @@ -21,18 +21,14 @@ export type FacetSelectorConfiguration = { imports: [MatListModule], }) export class FacetSelectorComponent implements DropdownComponent { + public readonly data = inject>(NATURAL_DROPDOWN_DATA); + protected dropdownRef = inject(NaturalDropdownRef); + // Never has a real value public readonly renderedValue = new BehaviorSubject(''); - public facets: NaturalSearchFacets; + public facets = this.data.configuration.facets; public selection: Facet | null = null; - public constructor( - @Inject(NATURAL_DROPDOWN_DATA) public data: NaturalDropdownData, - protected dropdownRef: NaturalDropdownRef, - ) { - this.facets = data.configuration.facets; - } - /** * Get value, including rich object types */ diff --git a/projects/natural/src/lib/modules/search/input/input.component.ts b/projects/natural/src/lib/modules/search/input/input.component.ts index 05136a0f..87b9e98c 100644 --- a/projects/natural/src/lib/modules/search/input/input.component.ts +++ b/projects/natural/src/lib/modules/search/input/input.component.ts @@ -14,6 +14,7 @@ import { Output, StaticProvider, ViewChild, + inject, } from '@angular/core'; import {FormControl, FormsModule, ReactiveFormsModule, ValidationErrors, ValidatorFn} from '@angular/forms'; import {ErrorStateMatcher, MatRipple, MatRippleModule} from '@angular/material/core'; @@ -69,6 +70,10 @@ function isComponentValid(component: DropdownComponent): ValidatorFn { ], }) export class NaturalInputComponent implements OnInit, OnChanges, OnDestroy { + private readonly element = inject>(ElementRef); + private readonly dropdownService = inject(NaturalDropdownService); + private readonly injector = inject(EnvironmentInjector); + /** * Controls the ripple effect, used when opening a dropdown */ @@ -169,12 +174,6 @@ export class NaturalInputComponent implements OnInit, OnChanges, OnDestroy { this.neutralizeDropdownOpening = false; } - public constructor( - private readonly element: ElementRef, - private readonly dropdownService: NaturalDropdownService, - private readonly injector: EnvironmentInjector, - ) {} - public ngOnChanges(): void { if (!this.facets && this.selection) { setTimeout(() => this.clear()); diff --git a/projects/natural/src/lib/modules/search/public-api.ts b/projects/natural/src/lib/modules/search/public-api.ts index 18619368..3b872462 100644 --- a/projects/natural/src/lib/modules/search/public-api.ts +++ b/projects/natural/src/lib/modules/search/public-api.ts @@ -1,11 +1,11 @@ /* * Public API Surface of natural-search */ -export {NaturalDropdownData} from './dropdown-container/dropdown.service'; -export {FilterGroupConditionField, Filter} from './classes/graphql-doctrine.types'; -export {DropdownComponent} from './types/dropdown-component'; -export {FlagFacet, DropdownFacet, Facet, NaturalSearchFacets} from './types/facet'; -export {NaturalSearchSelections, NaturalSearchSelection} from './types/values'; +export type {NaturalDropdownData} from './dropdown-container/dropdown.service'; +export type {FilterGroupConditionField, Filter} from './classes/graphql-doctrine.types'; +export type {DropdownComponent} from './types/dropdown-component'; +export type {FlagFacet, DropdownFacet, Facet, NaturalSearchFacets} from './types/facet'; +export type {NaturalSearchSelections, NaturalSearchSelection} from './types/values'; export {NaturalDropdownRef} from './dropdown-container/dropdown-ref'; export {NATURAL_DROPDOWN_DATA} from './dropdown-container/dropdown.service'; export {toGraphQLDoctrineFilter} from './classes/graphql-doctrine'; diff --git a/projects/natural/src/lib/modules/search/search/search.component.ts b/projects/natural/src/lib/modules/search/search/search.component.ts index 17de7aa7..8d935a09 100644 --- a/projects/natural/src/lib/modules/search/search/search.component.ts +++ b/projects/natural/src/lib/modules/search/search/search.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, OnChanges, Output} from '@angular/core'; +import {Component, EventEmitter, Input, OnChanges, Output, inject} from '@angular/core'; import {deepClone} from '../classes/utils'; import {NaturalSearchFacets} from '../types/facet'; import {GroupSelections, NaturalSearchSelections} from '../types/values'; @@ -28,6 +28,8 @@ import {CommonModule} from '@angular/common'; ], }) export class NaturalSearchComponent implements OnChanges { + private readonly breakpointObserver = inject(BreakpointObserver); + /** * Placeholder for last input (the free search input) */ @@ -68,8 +70,6 @@ export class NaturalSearchComponent implements OnChanges { public readonly isMobile = this.breakpointObserver.observe(Breakpoints.XSmall).pipe(map(result => result.matches)); - public constructor(private readonly breakpointObserver: BreakpointObserver) {} - public ngOnChanges(): void { if (!this.facets) { this.facets = []; diff --git a/projects/natural/src/lib/modules/select/select-enum/select-enum.component.ts b/projects/natural/src/lib/modules/select/select-enum/select-enum.component.ts index ddbaba9f..131410aa 100644 --- a/projects/natural/src/lib/modules/select/select-enum/select-enum.component.ts +++ b/projects/natural/src/lib/modules/select/select-enum/select-enum.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit, Optional, Self} from '@angular/core'; +import {Component, Input, OnInit, inject} from '@angular/core'; import {ControlValueAccessor, FormsModule, NgControl, ReactiveFormsModule} from '@angular/forms'; import {Observable} from 'rxjs'; import {IEnum, NaturalEnumService} from '../../../services/enum.service'; @@ -18,6 +18,8 @@ type V = IEnum['value'] | IEnum['value'][]; imports: [MatFormFieldModule, MatSelectModule, FormsModule, ReactiveFormsModule, CommonModule, MatOptionModule], }) export class NaturalSelectEnumComponent extends AbstractSelect implements OnInit, ControlValueAccessor { + private readonly enumService = inject(NaturalEnumService); + /** * The name of the enum type, eg: `"ActionStatus"` */ @@ -40,10 +42,9 @@ export class NaturalSelectEnumComponent extends AbstractSelect implements public items?: Observable; - public constructor( - private readonly enumService: NaturalEnumService, - @Optional() @Self() ngControl: NgControl | null, - ) { + public constructor() { + const ngControl = inject(NgControl, {optional: true, self: true}); + super(ngControl); } diff --git a/projects/natural/src/lib/modules/select/select-hierarchic/select-hierarchic.component.ts b/projects/natural/src/lib/modules/select/select-hierarchic/select-hierarchic.component.ts index f79cdb49..01888693 100644 --- a/projects/natural/src/lib/modules/select/select-hierarchic/select-hierarchic.component.ts +++ b/projects/natural/src/lib/modules/select/select-hierarchic/select-hierarchic.component.ts @@ -1,4 +1,4 @@ -import {Component, Input, OnInit, Optional, Self} from '@angular/core'; +import {Component, inject, Input, OnInit} from '@angular/core'; import {ControlValueAccessor, FormsModule, NgControl, ReactiveFormsModule} from '@angular/forms'; import {MatDialogConfig} from '@angular/material/dialog'; import {Literal} from '../../../types/types'; @@ -66,6 +66,8 @@ export class NaturalSelectHierarchicComponent extends AbstractSelect implements OnInit, ControlValueAccessor { + private readonly hierarchicSelectorDialogService = inject(NaturalHierarchicSelectorDialogService); + /** * If provided cause a new select button to appear */ @@ -94,10 +96,9 @@ export class NaturalSelectHierarchicComponent */ private lockOpenDialog = false; - public constructor( - private readonly hierarchicSelectorDialogService: NaturalHierarchicSelectorDialogService, - @Optional() @Self() ngControl: NgControl | null, - ) { + public constructor() { + const ngControl = inject(NgControl, {optional: true, self: true}); + super(ngControl); } diff --git a/projects/natural/src/lib/modules/sidenav/sidenav-container/sidenav-container.component.ts b/projects/natural/src/lib/modules/sidenav/sidenav-container/sidenav-container.component.ts index f5037af7..e37cab5d 100644 --- a/projects/natural/src/lib/modules/sidenav/sidenav-container/sidenav-container.component.ts +++ b/projects/natural/src/lib/modules/sidenav/sidenav-container/sidenav-container.component.ts @@ -1,4 +1,4 @@ -import {Component, HostBinding, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; +import {Component, HostBinding, Input, OnDestroy, OnInit, ViewChild, inject} from '@angular/core'; import {MatDrawer, MatSidenav, MatSidenavModule} from '@angular/material/sidenav'; import {NaturalSidenavService} from '../sidenav.service'; import {CommonModule} from '@angular/common'; @@ -12,6 +12,8 @@ import {CommonModule} from '@angular/common'; imports: [MatSidenavModule, CommonModule], }) export class NaturalSidenavContainerComponent implements OnInit, OnDestroy { + public readonly sidenavService = inject(NaturalSidenavService); + /** * Unique identifier used for the local storage */ @@ -44,8 +46,6 @@ export class NaturalSidenavContainerComponent implements OnInit, OnDestroy { */ @ViewChild(MatSidenav, {static: true}) public menuSidenav!: MatSidenav; - public constructor(public readonly sidenavService: NaturalSidenavService) {} - public get isMinimized(): boolean { return this.sidenavService.isMinimized; } diff --git a/projects/natural/src/lib/modules/sidenav/sidenav.service.ts b/projects/natural/src/lib/modules/sidenav/sidenav.service.ts index f2d5fdb8..ba6b6734 100644 --- a/projects/natural/src/lib/modules/sidenav/sidenav.service.ts +++ b/projects/natural/src/lib/modules/sidenav/sidenav.service.ts @@ -1,4 +1,4 @@ -import {DestroyRef, Inject, inject, Injectable} from '@angular/core'; +import {DestroyRef, inject, Injectable} from '@angular/core'; import {MatDrawerMode} from '@angular/material/sidenav'; import {NavigationEnd, Router} from '@angular/router'; import {filter} from 'rxjs/operators'; @@ -26,6 +26,11 @@ function assert(value: T): asserts value { @Injectable({providedIn: 'root'}) export class NaturalSidenavService { private readonly destroyRef = inject(DestroyRef); + private readonly breakpointObserver = inject(BreakpointObserver); + private readonly router = inject(Router); + private readonly sessionStorage = inject(SESSION_STORAGE); + private readonly naturalSidenavStackService = inject(NaturalSidenavStackService); + /** * Navigation modes * First is for desktop view @@ -68,13 +73,6 @@ export class NaturalSidenavService { private openedStorageKeyWithName: string | null = null; private _isMobileView = false; - public constructor( - public readonly breakpointObserver: BreakpointObserver, - private readonly router: Router, - @Inject(SESSION_STORAGE) private readonly sessionStorage: NaturalStorage, - private readonly naturalSidenavStackService: NaturalSidenavStackService, - ) {} - public get activeMode(): MatDrawerMode { return this.mode; } diff --git a/projects/natural/src/lib/services/enum.service.ts b/projects/natural/src/lib/services/enum.service.ts index 1d970c51..e263afae 100644 --- a/projects/natural/src/lib/services/enum.service.ts +++ b/projects/natural/src/lib/services/enum.service.ts @@ -1,5 +1,5 @@ import {Apollo, gql} from 'apollo-angular'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {Observable} from 'rxjs'; import {map} from 'rxjs/operators'; @@ -36,7 +36,7 @@ export type IEnum = { providedIn: 'root', }) export class NaturalEnumService { - public constructor(private readonly apollo: Apollo) {} + private readonly apollo = inject(Apollo); /** * Return a list of observable enumerables considering the given name diff --git a/projects/natural/src/lib/services/link-mutation.service.ts b/projects/natural/src/lib/services/link-mutation.service.ts index bc282833..236196a3 100644 --- a/projects/natural/src/lib/services/link-mutation.service.ts +++ b/projects/natural/src/lib/services/link-mutation.service.ts @@ -1,6 +1,6 @@ import {Apollo, gql} from 'apollo-angular'; import {FetchResult} from '@apollo/client/core'; -import {Injectable} from '@angular/core'; +import {Injectable, inject} from '@angular/core'; import {clone} from 'lodash-es'; import {forkJoin, Observable, of} from 'rxjs'; import {map, switchMap} from 'rxjs/operators'; @@ -68,13 +68,13 @@ type Mutation = { providedIn: 'root', }) export class NaturalLinkMutationService { + private readonly apollo = inject(Apollo); + /** * Receives the list of available mutations */ private allMutations?: Mutation[]; - public constructor(private readonly apollo: Apollo) {} - /** * Link two objects together */ diff --git a/projects/natural/src/lib/services/persistence.service.ts b/projects/natural/src/lib/services/persistence.service.ts index 2eb2dbf8..33405fb3 100644 --- a/projects/natural/src/lib/services/persistence.service.ts +++ b/projects/natural/src/lib/services/persistence.service.ts @@ -1,4 +1,4 @@ -import {Inject, Injectable, InjectionToken, Optional} from '@angular/core'; +import {inject, Injectable, InjectionToken} from '@angular/core'; import {ActivatedRoute, NavigationExtras, Router} from '@angular/router'; import {clone} from 'lodash-es'; import {NaturalStorage, SESSION_STORAGE} from '../modules/common/services/memory-storage'; @@ -19,14 +19,10 @@ export const NATURAL_PERSISTENCE_VALIDATOR = new InjectionToken true); - } + private readonly router = inject(Router); + private readonly sessionStorage = inject(SESSION_STORAGE); + private readonly isValid = + inject(NATURAL_PERSISTENCE_VALIDATOR, {optional: true}) ?? (() => true); // By default, anything is valid /** * Persist in url and local storage the given value with the given key. diff --git a/projects/natural/src/lib/testing/mock-apollo.provider.ts b/projects/natural/src/lib/testing/mock-apollo.provider.ts index 4b6231d6..bb04bf5c 100644 --- a/projects/natural/src/lib/testing/mock-apollo.provider.ts +++ b/projects/natural/src/lib/testing/mock-apollo.provider.ts @@ -1,7 +1,7 @@ import {Apollo, gql} from 'apollo-angular'; import {ApolloClient, InMemoryCache} from '@apollo/client/core'; import {SchemaLink} from '@apollo/client/link/schema'; -import {Injectable, NgZone, Provider} from '@angular/core'; +import {Injectable, NgZone, Provider, inject} from '@angular/core'; import {buildSchema} from 'graphql'; import {addMocksToSchema, IMocks} from '@graphql-tools/mock'; @@ -186,7 +186,9 @@ function createMockClient(): ApolloClient { providedIn: 'root', }) class MockApollo extends Apollo { - public constructor(ngZone: NgZone) { + public constructor() { + const ngZone = inject(NgZone); + super(ngZone); super.client = createMockClient(); diff --git a/projects/natural/src/public-api.ts b/projects/natural/src/public-api.ts index 2972d134..38cb1125 100644 --- a/projects/natural/src/public-api.ts +++ b/projects/natural/src/public-api.ts @@ -20,14 +20,11 @@ export * from './lib/services/abstract-model.service'; export {NaturalDebounceService} from './lib/services/debounce.service'; export * from './lib/services/enum.service'; export * from './lib/services/link-mutation.service'; -export { - NaturalPersistenceService, - NATURAL_PERSISTENCE_VALIDATOR, - PersistenceValidator, -} from './lib/services/persistence.service'; +export {NaturalPersistenceService, NATURAL_PERSISTENCE_VALIDATOR} from './lib/services/persistence.service'; +export type {PersistenceValidator} from './lib/services/persistence.service'; export * from './lib/services/swiss-parsing-date-adapter.service'; -export { +export type { ExtractResolve, ExtractTall, ExtractTallOne, diff --git a/tsconfig.json b/tsconfig.json index 135ff0af..a29d626b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,9 +15,10 @@ "strictNullChecks": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "isolatedModules": true, "typeRoots": ["node_modules/@types"], "lib": ["ES2022", "dom"], - "skipLibCheck": true, "paths": { "@ecodev/natural": ["projects/natural/src/public-api"], "@ecodev/natural-editor": ["projects/natural-editor/src/public-api"]