@sd-angular/core 19.0.0-beta.70 → 19.0.0-beta.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/scss/ckeditor5.scss +1 -2
- package/components/modal/index.d.ts +1 -1
- package/components/modal/src/modal.component.d.ts +24 -0
- package/components/upload-file/src/configurations/upload-file.configuration.d.ts +33 -0
- package/components/upload-file/src/upload-file.component.d.ts +5 -2
- package/fesm2022/sd-angular-core-components-document-builder.mjs +1 -1
- package/fesm2022/sd-angular-core-components-document-builder.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-import-excel.mjs +1 -1
- package/fesm2022/sd-angular-core-components-import-excel.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-modal.mjs +57 -91
- package/fesm2022/sd-angular-core-components-modal.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-preview.mjs +1 -1
- package/fesm2022/sd-angular-core-components-preview.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-side-drawer.mjs +2 -2
- package/fesm2022/sd-angular-core-components-side-drawer.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-table.mjs +9 -7
- package/fesm2022/sd-angular-core-components-table.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-upload-file.mjs +62 -10
- package/fesm2022/sd-angular-core-components-upload-file.mjs.map +1 -1
- package/fesm2022/sd-angular-core-components-workflow.mjs +13 -13
- package/fesm2022/sd-angular-core-components-workflow.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs +158 -197
- package/fesm2022/sd-angular-core-forms-chip-calendar.mjs.map +1 -1
- package/fesm2022/sd-angular-core-forms-chip.mjs +173 -203
- package/fesm2022/sd-angular-core-forms-chip.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-layout.mjs +2 -3
- package/fesm2022/sd-angular-core-modules-layout.mjs.map +1 -1
- package/fesm2022/sd-angular-core-modules-permission.mjs +160 -74
- package/fesm2022/sd-angular-core-modules-permission.mjs.map +1 -1
- package/fesm2022/sd-angular-core.mjs +0 -1
- package/fesm2022/sd-angular-core.mjs.map +1 -1
- package/forms/chip/src/chip.component.d.ts +35 -44
- package/forms/chip-calendar/src/chip-calendar.component.d.ts +35 -42
- package/modules/layout/services/menu/menu.model.d.ts +1 -0
- package/modules/permission/src/configurations/permission.configuration.d.ts +56 -2
- package/modules/permission/src/directives/permission.directive.d.ts +5 -8
- package/modules/permission/src/guards/permission.guard.d.ts +2 -1
- package/modules/permission/src/services/permission.service.d.ts +6 -9
- package/package.json +44 -52
- package/public-api.d.ts +0 -1
- package/sd-angular-core-19.0.0-beta.72.tgz +0 -0
- package/components/modal/src/modal/modal.component.d.ts +0 -31
- package/fesm2022/sd-angular-core-guards-permission.mjs +0 -155
- package/fesm2022/sd-angular-core-guards-permission.mjs.map +0 -1
- package/fesm2022/sd-angular-core-guards.mjs +0 -6
- package/fesm2022/sd-angular-core-guards.mjs.map +0 -1
- package/guards/index.d.ts +0 -1
- package/guards/permission/index.d.ts +0 -4
- package/guards/permission/src/configurations/index.d.ts +0 -1
- package/guards/permission/src/configurations/permission.configuration.d.ts +0 -8
- package/guards/permission/src/directives/index.d.ts +0 -1
- package/guards/permission/src/directives/permission.directive.d.ts +0 -12
- package/guards/permission/src/guards/index.d.ts +0 -1
- package/guards/permission/src/guards/permission.guard.d.ts +0 -13
- package/guards/permission/src/services/index.d.ts +0 -1
- package/guards/permission/src/services/permission.service.d.ts +0 -15
- package/sd-angular-core-19.0.0-beta.70.tgz +0 -0
|
@@ -1,127 +1,93 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
|
3
|
+
import { signal, viewChild, input, booleanAttribute, output, inject, DestroyRef, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
|
+
import { MatBottomSheet, MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
|
6
6
|
import { MatButtonModule } from '@angular/material/button';
|
|
7
|
-
import
|
|
8
|
-
import { MatDialogModule } from '@angular/material/dialog';
|
|
7
|
+
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
|
9
8
|
import { MatDividerModule } from '@angular/material/divider';
|
|
10
|
-
import * as
|
|
9
|
+
import * as i1 from '@angular/material/icon';
|
|
11
10
|
import { MatIconModule } from '@angular/material/icon';
|
|
12
11
|
import { SdUtilities } from '@sd-angular/core/utilities';
|
|
13
|
-
import { Subscription } from 'rxjs';
|
|
14
12
|
|
|
15
13
|
class SdModal {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
isOpened = false;
|
|
30
|
-
alreadyOpened = false;
|
|
14
|
+
static index = signal(0);
|
|
15
|
+
templateRef = viewChild.required('templateRef');
|
|
16
|
+
modal = viewChild('modal');
|
|
17
|
+
title = input('', { transform: (v) => v ?? '' });
|
|
18
|
+
color = input('primary', { transform: (v) => v ?? 'primary' });
|
|
19
|
+
width = input('md', { transform: (v) => v ?? 'md' });
|
|
20
|
+
height = input('auto', { transform: (v) => v ?? 'auto' });
|
|
21
|
+
view = input(undefined, { transform: (v) => v ?? undefined });
|
|
22
|
+
modalClass = input('', { transform: (v) => v ?? '' });
|
|
23
|
+
lazyLoadContent = input(true, { transform: booleanAttribute });
|
|
24
|
+
sdClosed = output();
|
|
25
|
+
isOpened = signal(false);
|
|
26
|
+
alreadyOpened = signal(false);
|
|
31
27
|
#isMobile = false;
|
|
28
|
+
#resolvedWidth = 'md';
|
|
32
29
|
#bottomSheetRef;
|
|
33
30
|
#dialogRef;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.bottomSheet = bottomSheet;
|
|
31
|
+
#dialog = inject(MatDialog);
|
|
32
|
+
#bottomSheet = inject(MatBottomSheet);
|
|
33
|
+
#destroyRef = inject(DestroyRef);
|
|
34
|
+
constructor() {
|
|
39
35
|
this.#isMobile = SdUtilities.isMobile();
|
|
40
36
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
case 'sm':
|
|
52
|
-
this.width = '40vw';
|
|
53
|
-
break;
|
|
54
|
-
case 'sx':
|
|
55
|
-
this.width = '20vw';
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
37
|
+
#resolveWidth() {
|
|
38
|
+
const w = this.width() || '80vw';
|
|
39
|
+
if (this.#isMobile)
|
|
40
|
+
return w;
|
|
41
|
+
switch (w) {
|
|
42
|
+
case 'lg': return '80vw';
|
|
43
|
+
case 'md': return '60vw';
|
|
44
|
+
case 'sm': return '40vw';
|
|
45
|
+
case 'sx': return '20vw';
|
|
46
|
+
default: return w;
|
|
58
47
|
}
|
|
59
48
|
}
|
|
60
|
-
ngOnDestroy() {
|
|
61
|
-
this.subcription.unsubscribe();
|
|
62
|
-
}
|
|
63
49
|
open = () => {
|
|
64
|
-
if (this.isOpened) {
|
|
50
|
+
if (this.isOpened()) {
|
|
65
51
|
return;
|
|
66
52
|
}
|
|
67
|
-
this.
|
|
68
|
-
this.
|
|
69
|
-
this
|
|
70
|
-
if ((!this.view && this.#isMobile) || this.view === 'bottom-sheet') {
|
|
71
|
-
this.#bottomSheetRef = this
|
|
72
|
-
this
|
|
73
|
-
this
|
|
53
|
+
this.alreadyOpened.set(true);
|
|
54
|
+
this.isOpened.set(true);
|
|
55
|
+
this.#resolvedWidth = this.#resolveWidth();
|
|
56
|
+
if ((!this.view() && this.#isMobile) || this.view() === 'bottom-sheet') {
|
|
57
|
+
this.#bottomSheetRef = this.#bottomSheet.open(this.templateRef(), { panelClass: this.modalClass() });
|
|
58
|
+
this.#bottomSheetRef.afterDismissed()
|
|
59
|
+
.pipe(takeUntilDestroyed(this.#destroyRef))
|
|
60
|
+
.subscribe(() => {
|
|
61
|
+
this.isOpened.set(false);
|
|
74
62
|
this.sdClosed.emit();
|
|
75
|
-
})
|
|
63
|
+
});
|
|
76
64
|
}
|
|
77
65
|
else {
|
|
78
|
-
this.#dialogRef = this
|
|
79
|
-
width: this
|
|
80
|
-
maxWidth: this
|
|
66
|
+
this.#dialogRef = this.#dialog.open(this.templateRef(), {
|
|
67
|
+
width: this.#resolvedWidth,
|
|
68
|
+
maxWidth: this.#resolvedWidth,
|
|
69
|
+
panelClass: this.modalClass(),
|
|
81
70
|
disableClose: true, // mặc định ko cho đóng modal khi click out side
|
|
82
71
|
});
|
|
83
|
-
this
|
|
84
|
-
this
|
|
72
|
+
this.#dialogRef.afterClosed()
|
|
73
|
+
.pipe(takeUntilDestroyed(this.#destroyRef))
|
|
74
|
+
.subscribe(() => {
|
|
75
|
+
this.isOpened.set(false);
|
|
85
76
|
this.sdClosed.emit();
|
|
86
|
-
})
|
|
77
|
+
});
|
|
87
78
|
}
|
|
88
79
|
};
|
|
89
80
|
close = () => {
|
|
90
|
-
this.ref.markForCheck();
|
|
91
81
|
this.#bottomSheetRef?.dismiss();
|
|
92
82
|
this.#dialogRef?.close();
|
|
93
83
|
};
|
|
94
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdModal, deps: [
|
|
95
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdModal, isStandalone: true, selector: "sd-modal", inputs: { title: "title", color: "color", width: "width", height: "height", view: "view", lazyLoadContent: "lazyLoadContent" }, outputs: { sdClosed: "sdClosed" }, viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["templateRef"], descendants: true }, { propertyName: "modal", first: true, predicate: ["modal"], descendants: true }], ngImport: i0, template: "<ng-template #templateRef>\r\n @if (!lazyLoadContent || alreadyOpened) {\r\n <!-- Header -->\r\n <!-- D\u00F9ng scss thu\u1EA7n -->\r\n @if (title) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <div class=\"T18M\">{{ title }}</div>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh
|
|
84
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
85
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdModal, isStandalone: true, selector: "sd-modal", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, modalClass: { classPropertyName: "modalClass", publicName: "modalClass", isSignal: true, isRequired: false, transformFunction: null }, lazyLoadContent: { classPropertyName: "lazyLoadContent", publicName: "lazyLoadContent", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sdClosed: "sdClosed" }, viewQueries: [{ propertyName: "templateRef", first: true, predicate: ["templateRef"], descendants: true, isSignal: true }, { propertyName: "modal", first: true, predicate: ["modal"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #templateRef>\r\n @if (!lazyLoadContent() || alreadyOpened()) {\r\n <!-- Header -->\r\n <!-- D\u00F9ng scss thu\u1EA7n -->\r\n @if (title()) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n <div class=\"T18M\">{{ title() }}</div>\r\n </ng-content>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh\">\r\n <ng-content></ng-content>\r\n </div>\r\n <!-- Footer -->\r\n <!-- <mat-divider></mat-divider> -->\r\n <div class=\"d-flex align-items-center p-8\" #footer>\r\n <ng-content select=\"[sdFooterLeft]\"></ng-content>\r\n <div class=\"ml-auto\">\r\n <ng-content select=\"[sdFooterRight]\"></ng-content>\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-template #templateRef>\r\n @if(!lazyLoadContent || alreadyOpened) {\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n }\r\n <ng-container *ngIf=\"!lazyLoadContent || alreadyOpened\">\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n <div class=\"d-flex flex-column px-12 px-md-24 pb-6 overflow-auto w-full mh-full\">\r\n <ng-content></ng-content>\r\n </div>\r\n </ng-container>\r\n</ng-template> -->\r\n", styles: ["button:focus{outline:none!important}.mat-dialog-container{padding:0!important}.mat-dialog-container .mat-dialog-content{max-height:80vh}.mat-dialog-container .mat-dialog-actions{min-height:auto;margin-bottom:0;padding:0}.mat-bottom-sheet-container{max-height:\"inherit\"}sd-modal-header{padding:12px 24px;display:block;width:100%}@media(max-width:640px){sd-modal-header{padding:12px}}.cdk-global-overlay-wrapper .mat-bottom-sheet-container{padding:0;min-width:100vw;box-sizing:border-box;outline:0;max-height:80vh;overflow:hidden;border-top-left-radius:4px;border-top-right-radius:4px;display:flex;flex-direction:column}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatBottomSheetModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatButtonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
96
86
|
}
|
|
97
87
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdModal, decorators: [{
|
|
98
88
|
type: Component,
|
|
99
|
-
args: [{ selector: 'sd-modal', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, MatIconModule, MatBottomSheetModule, MatDialogModule, MatDividerModule, MatButtonModule], template: "<ng-template #templateRef>\r\n @if (!lazyLoadContent || alreadyOpened) {\r\n <!-- Header -->\r\n <!-- D\u00F9ng scss thu\u1EA7n -->\r\n @if (title) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <div class=\"T18M\">{{ title }}</div>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh
|
|
100
|
-
}], ctorParameters: () => [
|
|
101
|
-
type: ViewChild,
|
|
102
|
-
args: ['templateRef']
|
|
103
|
-
}], title: [{
|
|
104
|
-
type: Input
|
|
105
|
-
}], color: [{
|
|
106
|
-
type: Input
|
|
107
|
-
}], width: [{
|
|
108
|
-
type: Input
|
|
109
|
-
}], height: [{
|
|
110
|
-
type: Input
|
|
111
|
-
}], view: [{
|
|
112
|
-
type: Input
|
|
113
|
-
}], lazyLoadContent: [{
|
|
114
|
-
type: Input
|
|
115
|
-
}], sdClosed: [{
|
|
116
|
-
type: Output
|
|
117
|
-
}], modal: [{
|
|
118
|
-
type: ViewChild,
|
|
119
|
-
args: ['modal']
|
|
120
|
-
}] } });
|
|
121
|
-
|
|
122
|
-
// export * from './src/modal/modal-header/modal-header.component';
|
|
123
|
-
// export * from './src/modal/modal-body/modal-body.component';
|
|
124
|
-
// export * from './src/modal/modal-footer/modal-footer.component';
|
|
89
|
+
args: [{ selector: 'sd-modal', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, MatIconModule, MatBottomSheetModule, MatDialogModule, MatDividerModule, MatButtonModule], template: "<ng-template #templateRef>\r\n @if (!lazyLoadContent() || alreadyOpened()) {\r\n <!-- Header -->\r\n <!-- D\u00F9ng scss thu\u1EA7n -->\r\n @if (title()) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n <div class=\"T18M\">{{ title() }}</div>\r\n </ng-content>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh\">\r\n <ng-content></ng-content>\r\n </div>\r\n <!-- Footer -->\r\n <!-- <mat-divider></mat-divider> -->\r\n <div class=\"d-flex align-items-center p-8\" #footer>\r\n <ng-content select=\"[sdFooterLeft]\"></ng-content>\r\n <div class=\"ml-auto\">\r\n <ng-content select=\"[sdFooterRight]\"></ng-content>\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-template #templateRef>\r\n @if(!lazyLoadContent || alreadyOpened) {\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n }\r\n <ng-container *ngIf=\"!lazyLoadContent || alreadyOpened\">\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n <div class=\"d-flex flex-column px-12 px-md-24 pb-6 overflow-auto w-full mh-full\">\r\n <ng-content></ng-content>\r\n </div>\r\n </ng-container>\r\n</ng-template> -->\r\n", styles: ["button:focus{outline:none!important}.mat-dialog-container{padding:0!important}.mat-dialog-container .mat-dialog-content{max-height:80vh}.mat-dialog-container .mat-dialog-actions{min-height:auto;margin-bottom:0;padding:0}.mat-bottom-sheet-container{max-height:\"inherit\"}sd-modal-header{padding:12px 24px;display:block;width:100%}@media(max-width:640px){sd-modal-header{padding:12px}}.cdk-global-overlay-wrapper .mat-bottom-sheet-container{padding:0;min-width:100vw;box-sizing:border-box;outline:0;max-height:80vh;overflow:hidden;border-top-left-radius:4px;border-top-right-radius:4px;display:flex;flex-direction:column}\n"] }]
|
|
90
|
+
}], ctorParameters: () => [] });
|
|
125
91
|
|
|
126
92
|
/**
|
|
127
93
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-modal.mjs","sources":["../../../projects/sd-angular/components/modal/src/modal/modal.component.ts","../../../projects/sd-angular/components/modal/src/modal/modal.component.html","../../../projects/sd-angular/components/modal/index.ts","../../../projects/sd-angular/components/modal/sd-angular-core-components-modal.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnDestroy,\n OnInit,\n Output,\n TemplateRef,\n ViewChild\n} from '@angular/core';\nimport { MatBottomSheet, MatBottomSheetModule, MatBottomSheetRef } from '@angular/material/bottom-sheet';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog';\nimport { MatDividerModule } from '@angular/material/divider';\nimport { MatIconModule } from '@angular/material/icon';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdColor, SdSize } from '@sd-angular/core/utilities/models';\nimport { Subscription } from 'rxjs';\n\n@Component({\n selector: 'sd-modal',\n templateUrl: './modal.component.html',\n styleUrls: ['./modal.component.scss'],\n // encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, MatIconModule, MatBottomSheetModule, MatDialogModule, MatDividerModule, MatButtonModule],\n})\nexport class SdModal implements OnInit, OnDestroy {\n static index = 0;\n @ViewChild('templateRef') templateRef!: TemplateRef<any>;\n @Input() title?: string;\n @Input() color: SdColor = 'primary';\n @Input() width: SdSize | string = 'md';\n @Input() height = 'auto';\n @Input() view?: 'dialog' | 'bottom-sheet';\n @Input() lazyLoadContent = true;\n @Output() sdClosed = new EventEmitter();\n @ViewChild('modal') modal!: ElementRef;\n isOpened = false;\n alreadyOpened = false;\n #isMobile = false;\n #bottomSheetRef!: MatBottomSheetRef<any>;\n #dialogRef!: MatDialogRef<any>;\n private subcription = new Subscription();\n constructor(\n private ref: ChangeDetectorRef,\n private dialog: MatDialog,\n private bottomSheet: MatBottomSheet\n ) {\n this.#isMobile = SdUtilities.isMobile();\n }\n ngOnInit(): void {\n this.width = this.width || '80vw';\n if (!this.#isMobile) {\n switch (this.width) {\n case 'lg':\n this.width = '80vw';\n break;\n case 'md':\n this.width = '60vw';\n break;\n case 'sm':\n this.width = '40vw';\n break;\n case 'sx':\n this.width = '20vw';\n break;\n }\n }\n }\n\n ngOnDestroy() {\n this.subcription.unsubscribe();\n }\n\n open = (): void => {\n if (this.isOpened) {\n return;\n }\n this.ref.markForCheck();\n this.alreadyOpened = true;\n this.isOpened = true;\n if ((!this.view && this.#isMobile) || this.view === 'bottom-sheet') {\n this.#bottomSheetRef = this.bottomSheet.open(this.templateRef);\n this.subcription.add(\n this.#bottomSheetRef.afterDismissed().subscribe(() => {\n this.isOpened = false;\n this.sdClosed.emit();\n })\n );\n } else {\n this.#dialogRef = this.dialog.open(this.templateRef, {\n width: this.width,\n maxWidth: this.width,\n disableClose: true, // mặc định ko cho đóng modal khi click out side\n });\n this.subcription.add(\n this.#dialogRef.afterClosed().subscribe(() => {\n this.isOpened = false;\n this.sdClosed.emit();\n })\n );\n }\n };\n\n close = (): void => {\n this.ref.markForCheck();\n this.#bottomSheetRef?.dismiss();\n this.#dialogRef?.close();\n };\n}\n","<ng-template #templateRef>\r\n @if (!lazyLoadContent || alreadyOpened) {\r\n <!-- Header -->\r\n <!-- Dùng scss thuần -->\r\n @if (title) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <div class=\"T18M\">{{ title }}</div>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh;\">\r\n <ng-content></ng-content>\r\n </div>\r\n <!-- Footer -->\r\n <!-- <mat-divider></mat-divider> -->\r\n <div class=\"d-flex align-items-center p-16\" #footer>\r\n <ng-content select=\"[sdFooterLeft]\"></ng-content>\r\n <div class=\"ml-auto\">\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-template #templateRef>\r\n @if(!lazyLoadContent || alreadyOpened) {\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n }\r\n <ng-container *ngIf=\"!lazyLoadContent || alreadyOpened\">\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n <div class=\"d-flex flex-column px-12 px-md-24 pb-6 overflow-auto w-full mh-full\">\r\n <ng-content></ng-content>\r\n </div>\r\n </ng-container>\r\n</ng-template> -->\r\n","export * from './src/modal/modal.component';\n// export * from './src/modal/modal-header/modal-header.component';\n// export * from './src/modal/modal-body/modal-body.component';\n// export * from './src/modal/modal-footer/modal-footer.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-modal.mjs","sources":["../../../projects/sd-angular/components/modal/src/modal.component.ts","../../../projects/sd-angular/components/modal/src/modal.component.html","../../../projects/sd-angular/components/modal/sd-angular-core-components-modal.ts"],"sourcesContent":["import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n TemplateRef,\n booleanAttribute,\n inject,\n input,\n output,\n signal,\n viewChild\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { MatBottomSheet, MatBottomSheetModule, MatBottomSheetRef } from '@angular/material/bottom-sheet';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDialog, MatDialogModule, MatDialogRef } from '@angular/material/dialog';\nimport { MatDividerModule } from '@angular/material/divider';\nimport { MatIconModule } from '@angular/material/icon';\nimport { SdUtilities } from '@sd-angular/core/utilities';\nimport { SdColor, SdSize } from '@sd-angular/core/utilities/models';\n\n@Component({\n selector: 'sd-modal',\n templateUrl: './modal.component.html',\n styleUrls: ['./modal.component.scss'],\n // encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: true,\n imports: [CommonModule, MatIconModule, MatBottomSheetModule, MatDialogModule, MatDividerModule, MatButtonModule],\n})\nexport class SdModal {\n static index = signal(0);\n\n templateRef = viewChild.required<TemplateRef<any>>('templateRef');\n modal = viewChild<ElementRef>('modal');\n\n title = input<string, string | null | undefined>('', { transform: (v) => v ?? '' });\n color = input<SdColor, SdColor | null | undefined>('primary', { transform: (v) => v ?? 'primary' });\n width = input<SdSize | string, SdSize | string | null | undefined>('md', { transform: (v) => v ?? 'md' });\n height = input<string, string | null | undefined>('auto', { transform: (v) => v ?? 'auto' });\n view = input<'dialog' | 'bottom-sheet' | undefined, 'dialog' | 'bottom-sheet' | null | undefined>(undefined, { transform: (v) => v ?? undefined });\n modalClass = input<string | string[] | Record<string, boolean>, string | string[] | Record<string, boolean> | null | undefined>('', { transform: (v) => v ?? '' });\n lazyLoadContent = input(true, { transform: booleanAttribute });\n\n sdClosed = output<void>();\n\n isOpened = signal(false);\n alreadyOpened = signal(false);\n\n #isMobile = false;\n #resolvedWidth = 'md';\n #bottomSheetRef!: MatBottomSheetRef<any>;\n #dialogRef!: MatDialogRef<any>;\n\n #dialog = inject(MatDialog);\n #bottomSheet = inject(MatBottomSheet);\n #destroyRef = inject(DestroyRef);\n\n constructor() {\n this.#isMobile = SdUtilities.isMobile();\n }\n\n #resolveWidth(): string {\n const w = this.width() || '80vw';\n if (this.#isMobile) return w;\n switch (w) {\n case 'lg': return '80vw';\n case 'md': return '60vw';\n case 'sm': return '40vw';\n case 'sx': return '20vw';\n default: return w;\n }\n }\n\n open = (): void => {\n if (this.isOpened()) {\n return;\n }\n this.alreadyOpened.set(true);\n this.isOpened.set(true);\n this.#resolvedWidth = this.#resolveWidth();\n\n if ((!this.view() && this.#isMobile) || this.view() === 'bottom-sheet') {\n this.#bottomSheetRef = this.#bottomSheet.open(this.templateRef(), { panelClass: this.modalClass() as string | string[] });\n this.#bottomSheetRef.afterDismissed()\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n this.isOpened.set(false);\n this.sdClosed.emit();\n });\n } else {\n this.#dialogRef = this.#dialog.open(this.templateRef(), {\n width: this.#resolvedWidth,\n maxWidth: this.#resolvedWidth,\n panelClass: this.modalClass() as string | string[],\n disableClose: true, // mặc định ko cho đóng modal khi click out side\n });\n this.#dialogRef.afterClosed()\n .pipe(takeUntilDestroyed(this.#destroyRef))\n .subscribe(() => {\n this.isOpened.set(false);\n this.sdClosed.emit();\n });\n }\n };\n\n close = (): void => {\n this.#bottomSheetRef?.dismiss();\n this.#dialogRef?.close();\n };\n}\n","<ng-template #templateRef>\r\n @if (!lazyLoadContent() || alreadyOpened()) {\r\n <!-- Header -->\r\n <!-- Dùng scss thuần -->\r\n @if (title()) {\r\n <div class=\"d-flex align-items-center p-16\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n <div class=\"T18M\">{{ title() }}</div>\r\n </ng-content>\r\n <div class=\"d-flex align-items-center ml-auto\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n <ng-content select=\"[sdHeader]\"></ng-content>\r\n <mat-icon class=\"text-secondary pointer\" fontIcon=\"close\" (click)=\"close()\"></mat-icon>\r\n </div>\r\n </div>\r\n }\r\n <!-- <mat-divider></mat-divider> -->\r\n <!-- Body -->\r\n <div class=\"overflow-auto w-full px-16\" style=\"max-height: 80vh\">\r\n <ng-content></ng-content>\r\n </div>\r\n <!-- Footer -->\r\n <!-- <mat-divider></mat-divider> -->\r\n <div class=\"d-flex align-items-center p-8\" #footer>\r\n <ng-content select=\"[sdFooterLeft]\"></ng-content>\r\n <div class=\"ml-auto\">\r\n <ng-content select=\"[sdFooterRight]\"></ng-content>\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<!-- <ng-template #templateRef>\r\n @if(!lazyLoadContent || alreadyOpened) {\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n }\r\n <ng-container *ngIf=\"!lazyLoadContent || alreadyOpened\">\r\n <sd-modal-header *ngIf=\"title\">\r\n <span [innerHtml]=\"title\"></span>\r\n <div class=\"d-flex align-items-center\">\r\n <ng-content select=\"[sdModalHeaderRight]\"></ng-content>\r\n <button type=\"button\" (click)=\"close()\" mat-icon-button>\r\n <mat-icon fontIcon=\"close\"></mat-icon>\r\n </button>\r\n </div>\r\n </sd-modal-header>\r\n <div class=\"d-flex flex-column px-12 px-md-24 pb-6 overflow-auto w-full mh-full\">\r\n <ng-content></ng-content>\r\n </div>\r\n </ng-container>\r\n</ng-template> -->\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -93,7 +93,7 @@ class SdPreviewImage {
|
|
|
93
93
|
this.activeIndex = 0;
|
|
94
94
|
};
|
|
95
95
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPreviewImage, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
96
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdPreviewImage, isStandalone: true, selector: "sd-preview-image", outputs: { close: "close" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal [title]=\"title\" (sdClosed)=\"close.emit()\" #modal>\r\n <div class=\"p-16\" style=\"overflow: hidden; height: 100%\">\r\n <!-- Main image -->\r\n @if (images.length) {\r\n <div style=\"gap: 8px;\" class=\"image-gallery\">\r\n <div class=\"thumbnail-container\">\r\n @for (image of images; track image.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"thumbnail-wrapper\"\r\n (click)=\"onClickThumbnailImage(i)\"\r\n [ngStyle]=\"{\r\n border: activeIndex === i ? '2px solid #2962ff' : 'none'\r\n }\">\r\n @if (image.src) {\r\n <img fill loading=\"lazy\" [ngSrc]=\"image.src\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n } @else {\r\n <img fill loading=\"lazy\" [src]=\"image.blobSrc\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"main-image-container\" #mainImage>\r\n @let activedImage = images[activeIndex];\r\n @if (activedImage.src) {\r\n <img fill priority [ngSrc]=\"activedImage.src\" class=\"main-image\" alt=\"Main display image\" />\r\n } @else {\r\n <img fill priority [src]=\"activedImage.blobSrc!\" class=\"main-image\" alt=\"Main display image\" />\r\n }\r\n <sd-button prefixIcon=\"arrow_forward_ios\" class=\"next-icon\" (click)=\"updateCurrentImage(1)\"></sd-button>\r\n <sd-button prefixIcon=\"arrow_back_ios_new\" class=\"back-icon\" (click)=\"updateCurrentImage(-1)\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"no-image d-flex justify-content-center align-items-center flex-column m-20\" style=\"height: 80%\">\r\n <i class=\"icon-no-image mb-16\"></i>\r\n <div>Kh\u00F4ng c\u00F3 th\u00F4ng tin \u1EA3nh</div>\r\n </div>\r\n }\r\n </div>\r\n</sd-modal>\r\n", styles: [".image-gallery{display:flex;width:100%;max-height:60vh;min-height:60vh}.image-gallery .main-image-container{flex:1;position:relative}.image-gallery .main-image-container .next-icon{position:absolute;top:45%;right:10px;cursor:pointer;color:#000;z-index:9999}.image-gallery .main-image-container .back-icon{position:absolute;top:45%;left:0;cursor:pointer;color:#000;z-index:9999}.image-gallery .thumbnail-container{width:120px;overflow-y:auto;display:flex;flex-direction:column;gap:8px;box-sizing:border-box}.image-gallery .thumbnail-wrapper{position:relative;width:100px;aspect-ratio:1;flex:0 0 auto;overflow:hidden;padding:0;border:none;background:transparent}.image-gallery .thumbnail-wrapper .thumbnail-img{object-fit:cover;width:100%;height:100%;display:block}.image-gallery .main-image{object-fit:contain;width:100%;height:100%;display:block}\n"], dependencies: [{ kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "lazyLoadContent"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
96
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdPreviewImage, isStandalone: true, selector: "sd-preview-image", outputs: { close: "close" }, viewQueries: [{ propertyName: "modal", first: true, predicate: SdModal, descendants: true }], ngImport: i0, template: "<sd-modal [title]=\"title\" (sdClosed)=\"close.emit()\" #modal>\r\n <div class=\"p-16\" style=\"overflow: hidden; height: 100%\">\r\n <!-- Main image -->\r\n @if (images.length) {\r\n <div style=\"gap: 8px;\" class=\"image-gallery\">\r\n <div class=\"thumbnail-container\">\r\n @for (image of images; track image.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"thumbnail-wrapper\"\r\n (click)=\"onClickThumbnailImage(i)\"\r\n [ngStyle]=\"{\r\n border: activeIndex === i ? '2px solid #2962ff' : 'none'\r\n }\">\r\n @if (image.src) {\r\n <img fill loading=\"lazy\" [ngSrc]=\"image.src\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n } @else {\r\n <img fill loading=\"lazy\" [src]=\"image.blobSrc\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"main-image-container\" #mainImage>\r\n @let activedImage = images[activeIndex];\r\n @if (activedImage.src) {\r\n <img fill priority [ngSrc]=\"activedImage.src\" class=\"main-image\" alt=\"Main display image\" />\r\n } @else {\r\n <img fill priority [src]=\"activedImage.blobSrc!\" class=\"main-image\" alt=\"Main display image\" />\r\n }\r\n <sd-button prefixIcon=\"arrow_forward_ios\" class=\"next-icon\" (click)=\"updateCurrentImage(1)\"></sd-button>\r\n <sd-button prefixIcon=\"arrow_back_ios_new\" class=\"back-icon\" (click)=\"updateCurrentImage(-1)\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"no-image d-flex justify-content-center align-items-center flex-column m-20\" style=\"height: 80%\">\r\n <i class=\"icon-no-image mb-16\"></i>\r\n <div>Kh\u00F4ng c\u00F3 th\u00F4ng tin \u1EA3nh</div>\r\n </div>\r\n }\r\n </div>\r\n</sd-modal>\r\n", styles: [".image-gallery{display:flex;width:100%;max-height:60vh;min-height:60vh}.image-gallery .main-image-container{flex:1;position:relative}.image-gallery .main-image-container .next-icon{position:absolute;top:45%;right:10px;cursor:pointer;color:#000;z-index:9999}.image-gallery .main-image-container .back-icon{position:absolute;top:45%;left:0;cursor:pointer;color:#000;z-index:9999}.image-gallery .thumbnail-container{width:120px;overflow-y:auto;display:flex;flex-direction:column;gap:8px;box-sizing:border-box}.image-gallery .thumbnail-wrapper{position:relative;width:100px;aspect-ratio:1;flex:0 0 auto;overflow:hidden;padding:0;border:none;background:transparent}.image-gallery .thumbnail-wrapper .thumbnail-img{object-fit:cover;width:100%;height:100%;display:block}.image-gallery .main-image{object-fit:contain;width:100%;height:100%;display:block}\n"], dependencies: [{ kind: "component", type: SdModal, selector: "sd-modal", inputs: ["title", "color", "width", "height", "view", "modalClass", "lazyLoadContent"], outputs: ["sdClosed"] }, { kind: "component", type: SdButton, selector: "sd-button", inputs: ["autoId", "type", "color", "size", "fontSet", "title", "width", "tooltip", "prefixIcon", "suffixIcon", "disabled", "loading", "block", "htmlType"], outputs: ["click"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgOptimizedImage, selector: "img[ngSrc]", inputs: ["ngSrc", "ngSrcset", "sizes", "width", "height", "loading", "priority", "loaderParams", "disableOptimizedSrcset", "fill", "placeholder", "placeholderConfig", "src", "srcset"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
97
97
|
}
|
|
98
98
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdPreviewImage, decorators: [{
|
|
99
99
|
type: Component,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-preview.mjs","sources":["../../../projects/sd-angular/components/preview/src/preview-image/preview-image.component.ts","../../../projects/sd-angular/components/preview/src/preview-image/preview-image.component.html","../../../projects/sd-angular/components/preview/sd-angular-core-components-preview.ts"],"sourcesContent":["import { CommonModule, NgOptimizedImage } from '@angular/common';\r\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';\r\nimport { SdButton } from '@sd-angular/core/components/button';\r\nimport { SdModal } from '@sd-angular/core/components/modal';\r\nimport * as uuid from 'uuid';\r\n\r\ninterface Image {\r\n id: string;\r\n // Vì NgOptimizedImage không thể sử dụng với blobSrc nên đối với url từ cdn sẽ vẫn lưu ở src\r\n blobSrc: string;\r\n src?: string;\r\n name: string;\r\n size: number;\r\n}\r\n\r\n@Component({\r\n selector: 'sd-preview-image',\r\n imports: [SdModal, SdButton, CommonModule, NgOptimizedImage],\r\n templateUrl: './preview-image.component.html',\r\n styleUrl: './preview-image.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SdPreviewImage {\r\n @ViewChild(SdModal) modal!: SdModal;\r\n @Output() close = new EventEmitter<void>();\r\n\r\n title: string = 'Xem ảnh';\r\n thumbnailPosition: 'right' | 'left' | 'bottom' | 'top' = 'right';\r\n activeIndex = 0;\r\n images: Image[] = [];\r\n constructor(private cd: ChangeDetectorRef) {}\r\n\r\n #loadImages = async (urlOrFiles: (string | File)[]) => {\r\n urlOrFiles = urlOrFiles.filter(url => !!url);\r\n // Xử lý nếu là url thì thực hiện fetch lấy blob rồi từ blob => file\r\n const promises = urlOrFiles.map<Promise<Image | null>>(async urlOrFile => {\r\n if (typeof urlOrFile === 'string') {\r\n return fetch(urlOrFile)\r\n .then(async r => {\r\n const blob = await r.blob();\r\n // Lấy filename dựa vào url src\r\n const baseSrc = urlOrFile.split('?')[0];\r\n const filename = baseSrc.substring(baseSrc.lastIndexOf('/') + 1);\r\n const file = new File([blob], filename);\r\n const image: Image = {\r\n id: uuid.v4(),\r\n blobSrc: URL.createObjectURL(file!),\r\n src: urlOrFile,\r\n name: file!.name,\r\n size: file!.size,\r\n };\r\n return image;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n return null;\r\n });\r\n } else {\r\n if (urlOrFile.type.split('/')[0] === 'image') {\r\n const image: Image = {\r\n id: uuid.v4(),\r\n blobSrc: URL.createObjectURL(urlOrFile),\r\n name: urlOrFile.name,\r\n size: urlOrFile.size,\r\n };\r\n return image;\r\n }\r\n return null;\r\n }\r\n });\r\n this.images = (await Promise.all(promises)).filter(image => image !== null);\r\n };\r\n\r\n // Nên sử dụng urlOrFiles ở tham số khi open thay vì dùng @Input để component sử dụng sẽ chỉ cần map ở hàm khi gọi open thay vì phải mất công map mọi lúc để binding vào @Input\r\n open = async (urlOrFiles: (string | File)[] | undefined | null) => {\r\n if (!Array.isArray(urlOrFiles)) {\r\n return;\r\n }\r\n await this.#loadImages(urlOrFiles);\r\n this.#reset();\r\n this.modal?.open();\r\n this.cd.markForCheck();\r\n };\r\n\r\n onClickThumbnailImage = (index: number) => {\r\n this.activeIndex = index;\r\n this.cd.markForCheck();\r\n };\r\n\r\n updateCurrentImage = (direction: 1 | -1) => {\r\n this.activeIndex = (this.activeIndex + direction + this.images.length) % this.images.length;\r\n this.#scrollView(this.activeIndex, direction === 1 ? 'start' : 'end');\r\n this.cd.markForCheck();\r\n };\r\n\r\n onClose = () => {\r\n this.close.emit();\r\n };\r\n\r\n #scrollView = (index: number, type?: 'center' | 'end' | 'nearest' | 'start') => {\r\n const nameId: string = 'thumbnailImage' + index;\r\n const element = document.getElementById(nameId);\r\n if (!element) {\r\n return;\r\n }\r\n const blockType: ScrollLogicalPosition = type || 'start';\r\n element.scrollIntoView({ behavior: 'smooth', block: blockType });\r\n };\r\n\r\n #reset = () => {\r\n this.activeIndex = 0;\r\n };\r\n}\r\n","<sd-modal [title]=\"title\" (sdClosed)=\"close.emit()\" #modal>\r\n <div class=\"p-16\" style=\"overflow: hidden; height: 100%\">\r\n <!-- Main image -->\r\n @if (images.length) {\r\n <div style=\"gap: 8px;\" class=\"image-gallery\">\r\n <div class=\"thumbnail-container\">\r\n @for (image of images; track image.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"thumbnail-wrapper\"\r\n (click)=\"onClickThumbnailImage(i)\"\r\n [ngStyle]=\"{\r\n border: activeIndex === i ? '2px solid #2962ff' : 'none'\r\n }\">\r\n @if (image.src) {\r\n <img fill loading=\"lazy\" [ngSrc]=\"image.src\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n } @else {\r\n <img fill loading=\"lazy\" [src]=\"image.blobSrc\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"main-image-container\" #mainImage>\r\n @let activedImage = images[activeIndex];\r\n @if (activedImage.src) {\r\n <img fill priority [ngSrc]=\"activedImage.src\" class=\"main-image\" alt=\"Main display image\" />\r\n } @else {\r\n <img fill priority [src]=\"activedImage.blobSrc!\" class=\"main-image\" alt=\"Main display image\" />\r\n }\r\n <sd-button prefixIcon=\"arrow_forward_ios\" class=\"next-icon\" (click)=\"updateCurrentImage(1)\"></sd-button>\r\n <sd-button prefixIcon=\"arrow_back_ios_new\" class=\"back-icon\" (click)=\"updateCurrentImage(-1)\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"no-image d-flex justify-content-center align-items-center flex-column m-20\" style=\"height: 80%\">\r\n <i class=\"icon-no-image mb-16\"></i>\r\n <div>Không có thông tin ảnh</div>\r\n </div>\r\n }\r\n </div>\r\n</sd-modal>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;MAsBa,cAAc,CAAA;AAQL,IAAA,EAAA;AAPA,IAAA,KAAK;AACf,IAAA,KAAK,GAAG,IAAI,YAAY,EAAQ;IAE1C,KAAK,GAAW,SAAS;IACzB,iBAAiB,GAAwC,OAAO;IAChE,WAAW,GAAG,CAAC;IACf,MAAM,GAAY,EAAE;AACpB,IAAA,WAAA,CAAoB,EAAqB,EAAA;QAArB,IAAA,CAAA,EAAE,GAAF,EAAE;IAAsB;AAE5C,IAAA,WAAW,GAAG,OAAO,UAA6B,KAAI;AACpD,QAAA,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC;;QAE5C,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAwB,OAAM,SAAS,KAAG;AACvE,YAAA,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE;gBACjC,OAAO,KAAK,CAAC,SAAS;AACnB,qBAAA,IAAI,CAAC,OAAM,CAAC,KAAG;AACd,oBAAA,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE;;oBAE3B,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACvC,oBAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAChE,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;AACvC,oBAAA,MAAM,KAAK,GAAU;AACnB,wBAAA,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;AACb,wBAAA,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,IAAK,CAAC;AACnC,wBAAA,GAAG,EAAE,SAAS;wBACd,IAAI,EAAE,IAAK,CAAC,IAAI;wBAChB,IAAI,EAAE,IAAK,CAAC,IAAI;qBACjB;AACD,oBAAA,OAAO,KAAK;AACd,gBAAA,CAAC;qBACA,KAAK,CAAC,GAAG,IAAG;AACX,oBAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;AAClB,oBAAA,OAAO,IAAI;AACb,gBAAA,CAAC,CAAC;YACN;iBAAO;AACL,gBAAA,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE;AAC5C,oBAAA,MAAM,KAAK,GAAU;AACnB,wBAAA,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;AACb,wBAAA,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC;wBACvC,IAAI,EAAE,SAAS,CAAC,IAAI;wBACpB,IAAI,EAAE,SAAS,CAAC,IAAI;qBACrB;AACD,oBAAA,OAAO,KAAK;gBACd;AACA,gBAAA,OAAO,IAAI;YACb;AACF,QAAA,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,GAAG,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC;AAC7E,IAAA,CAAC;;AAGD,IAAA,IAAI,GAAG,OAAO,UAAgD,KAAI;QAChE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YAC9B;QACF;AACA,QAAA,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE;AACb,QAAA,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;AAClB,QAAA,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE;AACxB,IAAA,CAAC;AAED,IAAA,qBAAqB,GAAG,CAAC,KAAa,KAAI;AACxC,QAAA,IAAI,CAAC,WAAW,GAAG,KAAK;AACxB,QAAA,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE;AACxB,IAAA,CAAC;AAED,IAAA,kBAAkB,GAAG,CAAC,SAAiB,KAAI;QACzC,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM;AAC3F,QAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,KAAK,CAAC,GAAG,OAAO,GAAG,KAAK,CAAC;AACrE,QAAA,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE;AACxB,IAAA,CAAC;IAED,OAAO,GAAG,MAAK;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;AACnB,IAAA,CAAC;AAED,IAAA,WAAW,GAAG,CAAC,KAAa,EAAE,IAA6C,KAAI;AAC7E,QAAA,MAAM,MAAM,GAAW,gBAAgB,GAAG,KAAK;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE;YACZ;QACF;AACA,QAAA,MAAM,SAAS,GAA0B,IAAI,IAAI,OAAO;AACxD,QAAA,OAAO,CAAC,cAAc,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAClE,IAAA,CAAC;IAED,MAAM,GAAG,MAAK;AACZ,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC;AACtB,IAAA,CAAC;wGAzFU,cAAc,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;4FAAd,cAAc,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,OAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EACd,OAAO,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECvBpB,ghEAyCA,EAAA,MAAA,EAAA,CAAA,k1BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDxBY,OAAO,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,OAAA,EAAA,OAAA,EAAA,QAAA,EAAA,MAAA,EAAA,iBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,SAAA,EAAA,OAAA,EAAA,OAAA,EAAA,SAAA,EAAA,YAAA,EAAA,YAAA,EAAA,UAAA,EAAA,SAAA,EAAA,OAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,OAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,YAAY,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,gBAAgB,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,UAAA,EAAA,cAAA,EAAA,wBAAA,EAAA,MAAA,EAAA,aAAA,EAAA,mBAAA,EAAA,KAAA,EAAA,QAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;4FAKhD,cAAc,EAAA,UAAA,EAAA,CAAA;kBAP1B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,EAAA,OAAA,EACnB,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,CAAC,EAAA,eAAA,EAG3C,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,ghEAAA,EAAA,MAAA,EAAA,CAAA,k1BAAA,CAAA,EAAA;sFAG3B,KAAK,EAAA,CAAA;sBAAxB,SAAS;uBAAC,OAAO;gBACR,KAAK,EAAA,CAAA;sBAAd;;;AExBH;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-preview.mjs","sources":["../../../projects/sd-angular/components/preview/src/preview-image/preview-image.component.ts","../../../projects/sd-angular/components/preview/src/preview-image/preview-image.component.html","../../../projects/sd-angular/components/preview/sd-angular-core-components-preview.ts"],"sourcesContent":["import { CommonModule, NgOptimizedImage } from '@angular/common';\r\nimport { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';\r\nimport { SdButton } from '@sd-angular/core/components/button';\r\nimport { SdModal } from '@sd-angular/core/components/modal';\r\nimport * as uuid from 'uuid';\r\n\r\ninterface Image {\r\n id: string;\r\n // Vì NgOptimizedImage không thể sử dụng với blobSrc nên đối với url từ cdn sẽ vẫn lưu ở src\r\n blobSrc: string;\r\n src?: string;\r\n name: string;\r\n size: number;\r\n}\r\n\r\n@Component({\r\n selector: 'sd-preview-image',\r\n imports: [SdModal, SdButton, CommonModule, NgOptimizedImage],\r\n templateUrl: './preview-image.component.html',\r\n styleUrl: './preview-image.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SdPreviewImage {\r\n @ViewChild(SdModal) modal!: SdModal;\r\n @Output() close = new EventEmitter<void>();\r\n\r\n title: string = 'Xem ảnh';\r\n thumbnailPosition: 'right' | 'left' | 'bottom' | 'top' = 'right';\r\n activeIndex = 0;\r\n images: Image[] = [];\r\n constructor(private cd: ChangeDetectorRef) {}\r\n\r\n #loadImages = async (urlOrFiles: (string | File)[]) => {\r\n urlOrFiles = urlOrFiles.filter(url => !!url);\r\n // Xử lý nếu là url thì thực hiện fetch lấy blob rồi từ blob => file\r\n const promises = urlOrFiles.map<Promise<Image | null>>(async urlOrFile => {\r\n if (typeof urlOrFile === 'string') {\r\n return fetch(urlOrFile)\r\n .then(async r => {\r\n const blob = await r.blob();\r\n // Lấy filename dựa vào url src\r\n const baseSrc = urlOrFile.split('?')[0];\r\n const filename = baseSrc.substring(baseSrc.lastIndexOf('/') + 1);\r\n const file = new File([blob], filename);\r\n const image: Image = {\r\n id: uuid.v4(),\r\n blobSrc: URL.createObjectURL(file!),\r\n src: urlOrFile,\r\n name: file!.name,\r\n size: file!.size,\r\n };\r\n return image;\r\n })\r\n .catch(err => {\r\n console.error(err);\r\n return null;\r\n });\r\n } else {\r\n if (urlOrFile.type.split('/')[0] === 'image') {\r\n const image: Image = {\r\n id: uuid.v4(),\r\n blobSrc: URL.createObjectURL(urlOrFile),\r\n name: urlOrFile.name,\r\n size: urlOrFile.size,\r\n };\r\n return image;\r\n }\r\n return null;\r\n }\r\n });\r\n this.images = (await Promise.all(promises)).filter(image => image !== null);\r\n };\r\n\r\n // Nên sử dụng urlOrFiles ở tham số khi open thay vì dùng @Input để component sử dụng sẽ chỉ cần map ở hàm khi gọi open thay vì phải mất công map mọi lúc để binding vào @Input\r\n open = async (urlOrFiles: (string | File)[] | undefined | null) => {\r\n if (!Array.isArray(urlOrFiles)) {\r\n return;\r\n }\r\n await this.#loadImages(urlOrFiles);\r\n this.#reset();\r\n this.modal?.open();\r\n this.cd.markForCheck();\r\n };\r\n\r\n onClickThumbnailImage = (index: number) => {\r\n this.activeIndex = index;\r\n this.cd.markForCheck();\r\n };\r\n\r\n updateCurrentImage = (direction: 1 | -1) => {\r\n this.activeIndex = (this.activeIndex + direction + this.images.length) % this.images.length;\r\n this.#scrollView(this.activeIndex, direction === 1 ? 'start' : 'end');\r\n this.cd.markForCheck();\r\n };\r\n\r\n onClose = () => {\r\n this.close.emit();\r\n };\r\n\r\n #scrollView = (index: number, type?: 'center' | 'end' | 'nearest' | 'start') => {\r\n const nameId: string = 'thumbnailImage' + index;\r\n const element = document.getElementById(nameId);\r\n if (!element) {\r\n return;\r\n }\r\n const blockType: ScrollLogicalPosition = type || 'start';\r\n element.scrollIntoView({ behavior: 'smooth', block: blockType });\r\n };\r\n\r\n #reset = () => {\r\n this.activeIndex = 0;\r\n };\r\n}\r\n","<sd-modal [title]=\"title\" (sdClosed)=\"close.emit()\" #modal>\r\n <div class=\"p-16\" style=\"overflow: hidden; height: 100%\">\r\n <!-- Main image -->\r\n @if (images.length) {\r\n <div style=\"gap: 8px;\" class=\"image-gallery\">\r\n <div class=\"thumbnail-container\">\r\n @for (image of images; track image.id; let i = $index) {\r\n <button\r\n type=\"button\"\r\n class=\"thumbnail-wrapper\"\r\n (click)=\"onClickThumbnailImage(i)\"\r\n [ngStyle]=\"{\r\n border: activeIndex === i ? '2px solid #2962ff' : 'none'\r\n }\">\r\n @if (image.src) {\r\n <img fill loading=\"lazy\" [ngSrc]=\"image.src\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n } @else {\r\n <img fill loading=\"lazy\" [src]=\"image.blobSrc\" alt=\"thumbnail\" [id]=\"image.id\" class=\"thumbnail-img\" />\r\n }\r\n </button>\r\n }\r\n </div>\r\n <div class=\"main-image-container\" #mainImage>\r\n @let activedImage = images[activeIndex];\r\n @if (activedImage.src) {\r\n <img fill priority [ngSrc]=\"activedImage.src\" class=\"main-image\" alt=\"Main display image\" />\r\n } @else {\r\n <img fill priority [src]=\"activedImage.blobSrc!\" class=\"main-image\" alt=\"Main display image\" />\r\n }\r\n <sd-button prefixIcon=\"arrow_forward_ios\" class=\"next-icon\" (click)=\"updateCurrentImage(1)\"></sd-button>\r\n <sd-button prefixIcon=\"arrow_back_ios_new\" class=\"back-icon\" (click)=\"updateCurrentImage(-1)\"></sd-button>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"no-image d-flex justify-content-center align-items-center flex-column m-20\" style=\"height: 80%\">\r\n <i class=\"icon-no-image mb-16\"></i>\r\n <div>Không có thông tin ảnh</div>\r\n </div>\r\n }\r\n </div>\r\n</sd-modal>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -108,11 +108,11 @@ class SdSideDrawer extends SdBaseSecureComponent {
|
|
|
108
108
|
this.isHovered$ = merge(mouseEnter$, mouseLeave$).pipe(startWith(false), distinctUntilChanged(), takeUntil(this.#destroy$));
|
|
109
109
|
}
|
|
110
110
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdSideDrawer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
111
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdSideDrawer, isStandalone: true, selector: "sd-side-drawer", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, hideClose: { classPropertyName: "hideClose", publicName: "hideClose", isSignal: true, isRequired: false, transformFunction: null }, disableBackdropClose: { classPropertyName: "disableBackdropClose", publicName: "disableBackdropClose", isSignal: true, isRequired: false, transformFunction: null }, drawerClass: { classPropertyName: "drawerClass", publicName: "drawerClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sdClosed: "sdClosed" }, viewQueries: [{ propertyName: "portal", first: true, predicate: CdkPortal, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"
|
|
111
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.17", type: SdSideDrawer, isStandalone: true, selector: "sd-side-drawer", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, hideClose: { classPropertyName: "hideClose", publicName: "hideClose", isSignal: true, isRequired: false, transformFunction: null }, disableBackdropClose: { classPropertyName: "disableBackdropClose", publicName: "disableBackdropClose", isSignal: true, isRequired: false, transformFunction: null }, drawerClass: { classPropertyName: "drawerClass", publicName: "drawerClass", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sdClosed: "sdClosed" }, viewQueries: [{ propertyName: "portal", first: true, predicate: CdkPortal, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"c-header\">\r\n <div class=\"sd-side-drawer-title\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n {{ title() }}\r\n </ng-content>\r\n </div>\r\n <div class=\"sd-side-drawer-header-actions\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n @if (!hideClose()) {\r\n <button type=\"button\" class=\"sd-side-drawer-close-btn\" (click)=\"close()\" aria-label=\"Close\">\r\n <svg\r\n viewBox=\"0 0 24 24\"\r\n width=\"24\"\r\n height=\"24\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n fill=\"none\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n @if (isOpened) {\r\n <div class=\"sd-side-drawer-body\">\r\n <div class=\"sd-side-drawer-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"sd-side-drawer-footer\">\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (isOpened) {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"sd-side-drawer-backdrop\"\r\n (click)=\"disableBackdropClose() ? null : close()\"\r\n (wheel)=\"preventScroll($event)\"\r\n (touchmove)=\"preventScroll($event)\"></div>\r\n }\r\n</ng-template>\r\n", styles: [".sd-side-drawer{position:fixed;right:0;top:0;bottom:0;background-color:#fff;z-index:999;display:flex;flex-direction:column;opacity:0;visibility:hidden;transform:translate3d(100%,0,0);transition:all .3s ease-in-out;pointer-events:none;box-shadow:0 .4px .8px #0000001a,0 3px 6px #0003}.sd-side-drawer-active{opacity:1;visibility:visible;pointer-events:all;transform:translateZ(0)}.sd-side-drawer-header{min-height:64px;padding:12px 16px;display:flex;align-items:center;justify-content:space-between}.sd-side-drawer-header-actions{display:flex;align-items:center;gap:8px}.sd-side-drawer-title{font-size:20px;line-height:28px;font-weight:500;flex:1;margin-right:16px}.sd-side-drawer-close-btn{background:transparent;border:none;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--sd-secondary-color, #666);border-radius:50%;transition:background-color .2s,color .2s}.sd-side-drawer-close-btn:hover{background-color:#0000000a;color:var(--sd-primary-color, #333)}.sd-side-drawer-close-btn:focus{outline:none;background-color:#00000014}.sd-side-drawer-body{flex:1;position:relative}.sd-side-drawer-content{position:absolute;padding:0 16px 16px;inset:0;overflow:auto}.sd-side-drawer-footer{border-top:1px solid #dde0e5;padding:8px}.sd-side-drawer-backdrop{background-color:#0006;border:0;outline:none!important;position:fixed;inset:0;z-index:99;width:100%;height:100%;transition:all .3s ease-in-out}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i2.CdkPortal, selector: "[cdkPortal]", exportAs: ["cdkPortal"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
112
112
|
}
|
|
113
113
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdSideDrawer, decorators: [{
|
|
114
114
|
type: Component,
|
|
115
|
-
args: [{ selector: 'sd-side-drawer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PortalModule], template: "<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"
|
|
115
|
+
args: [{ selector: 'sd-side-drawer', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, PortalModule], template: "<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"c-header\">\r\n <div class=\"sd-side-drawer-title\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n {{ title() }}\r\n </ng-content>\r\n </div>\r\n <div class=\"sd-side-drawer-header-actions\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n @if (!hideClose()) {\r\n <button type=\"button\" class=\"sd-side-drawer-close-btn\" (click)=\"close()\" aria-label=\"Close\">\r\n <svg\r\n viewBox=\"0 0 24 24\"\r\n width=\"24\"\r\n height=\"24\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n fill=\"none\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n @if (isOpened) {\r\n <div class=\"sd-side-drawer-body\">\r\n <div class=\"sd-side-drawer-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"sd-side-drawer-footer\">\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (isOpened) {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"sd-side-drawer-backdrop\"\r\n (click)=\"disableBackdropClose() ? null : close()\"\r\n (wheel)=\"preventScroll($event)\"\r\n (touchmove)=\"preventScroll($event)\"></div>\r\n }\r\n</ng-template>\r\n", styles: [".sd-side-drawer{position:fixed;right:0;top:0;bottom:0;background-color:#fff;z-index:999;display:flex;flex-direction:column;opacity:0;visibility:hidden;transform:translate3d(100%,0,0);transition:all .3s ease-in-out;pointer-events:none;box-shadow:0 .4px .8px #0000001a,0 3px 6px #0003}.sd-side-drawer-active{opacity:1;visibility:visible;pointer-events:all;transform:translateZ(0)}.sd-side-drawer-header{min-height:64px;padding:12px 16px;display:flex;align-items:center;justify-content:space-between}.sd-side-drawer-header-actions{display:flex;align-items:center;gap:8px}.sd-side-drawer-title{font-size:20px;line-height:28px;font-weight:500;flex:1;margin-right:16px}.sd-side-drawer-close-btn{background:transparent;border:none;padding:8px;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--sd-secondary-color, #666);border-radius:50%;transition:background-color .2s,color .2s}.sd-side-drawer-close-btn:hover{background-color:#0000000a;color:var(--sd-primary-color, #333)}.sd-side-drawer-close-btn:focus{outline:none;background-color:#00000014}.sd-side-drawer-body{flex:1;position:relative}.sd-side-drawer-content{position:absolute;padding:0 16px 16px;inset:0;overflow:auto}.sd-side-drawer-footer{border-top:1px solid #dde0e5;padding:8px}.sd-side-drawer-backdrop{background-color:#0006;border:0;outline:none!important;position:fixed;inset:0;z-index:99;width:100%;height:100%;transition:all .3s ease-in-out}\n"] }]
|
|
116
116
|
}], ctorParameters: () => [] });
|
|
117
117
|
|
|
118
118
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sd-angular-core-components-side-drawer.mjs","sources":["../../../projects/sd-angular/components/side-drawer/src/side-drawer.component.ts","../../../projects/sd-angular/components/side-drawer/src/side-drawer.component.html","../../../projects/sd-angular/components/side-drawer/sd-angular-core-components-side-drawer.ts"],"sourcesContent":["import { CdkPortal, DomPortalOutlet, PortalModule } from '@angular/cdk/portal';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n ApplicationRef,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n DestroyRef,\r\n EmbeddedViewRef,\r\n Injector,\r\n ViewContainerRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n output,\r\n viewChild\r\n} from '@angular/core';\r\nimport { SdBaseSecureComponent } from '@sd-angular/core/components/base';\r\nimport { SdLoadingService } from '@sd-angular/core/services';\r\nimport * as uuid from 'uuid';\r\nimport { fromEvent, merge, Observable, Subject } from 'rxjs';\r\nimport { map, takeUntil, startWith, distinctUntilChanged } from 'rxjs/operators';\r\n\r\n@Component({\r\n selector: 'sd-side-drawer',\r\n templateUrl: './side-drawer.component.html',\r\n styleUrls: ['./side-drawer.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, PortalModule],\r\n})\r\nexport class SdSideDrawer extends SdBaseSecureComponent {\r\n id = `I${uuid.v4()}`;\r\n \r\n portal = viewChild.required(CdkPortal);\r\n \r\n title = input<string>('');\r\n width = input<string>('480px');\r\n hideClose = input<boolean, boolean | ''>(false, { transform: booleanAttribute });\r\n disableBackdropClose = input<boolean, boolean | ''>(false, { transform: booleanAttribute });\r\n\r\n // Custom CSS class added to the root side-drawer container \r\n drawerClass = input<any>('');\r\n\r\n sdClosed = output<void>();\r\n\r\n #embeddedViewRef!: EmbeddedViewRef<any>;\r\n isOpened = false;\r\n isLoading = false;\r\n isHovered$!: Observable<boolean>;\r\n #destroy$ = new Subject<void>();\r\n #previousBodyOverflow: string | null = null;\r\n\r\n #viewContainerRef = inject(ViewContainerRef);\r\n #ar = inject(ApplicationRef);\r\n #injector = inject(Injector);\r\n #ref = inject(ChangeDetectorRef);\r\n #loadingService = inject(SdLoadingService);\r\n #destroyRef = inject(DestroyRef);\r\n\r\n constructor() {\r\n super();\r\n\r\n // Thay thế ngAfterViewInit, tự động chạy nội dung này khi DOM sẵn sàng để render\r\n afterNextRender(() => {\r\n // 1. Gắn portal vào body và lưu lại EmbeddedViewRef\r\n const outlet = new DomPortalOutlet(document.body, this.#viewContainerRef, this.#ar, this.#injector);\r\n this.#embeddedViewRef = outlet.attachTemplatePortal(this.portal());\r\n \r\n // 2. Setup sự kiện hover ngay sau khi DOM thật đã được in ra\r\n this.#setupHoverSubscription();\r\n });\r\n\r\n // Thay thế ngOnDestroy bằng logic destroy trực tiếp \r\n this.#destroyRef.onDestroy(() => {\r\n this.#destroy$.next();\r\n this.#destroy$.complete();\r\n \r\n if (this.#embeddedViewRef) {\r\n this.#embeddedViewRef.destroy();\r\n }\r\n \r\n if (this.isOpened) {\r\n if (this.#previousBodyOverflow !== null) {\r\n document.body.style.overflow = this.#previousBodyOverflow;\r\n } else {\r\n document.body.style.overflow = '';\r\n }\r\n }\r\n });\r\n }\r\n\r\n open = () => {\r\n this.#ref.markForCheck();\r\n this.isOpened = true;\r\n \r\n // Chặn scroll ở document body\r\n this.#previousBodyOverflow = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n };\r\n\r\n close = () => {\r\n this.#ref.markForCheck();\r\n this.isOpened = false;\r\n this.sdClosed.emit();\r\n this.stopLoading();\r\n \r\n // Khôi phục lại scroll ở document body\r\n if (this.#previousBodyOverflow !== null) {\r\n document.body.style.overflow = this.#previousBodyOverflow;\r\n this.#previousBodyOverflow = null;\r\n } else {\r\n document.body.style.overflow = '';\r\n }\r\n };\r\n\r\n startLoading = () => {\r\n this.isLoading = true;\r\n this.#loadingService.stop(`#${this.id}`);\r\n this.#loadingService.start(`#${this.id}`);\r\n };\r\n\r\n stopLoading = () => {\r\n this.isLoading = false;\r\n this.#loadingService.stop(`#${this.id}`);\r\n };\r\n\r\n preventScroll = (event: Event) => {\r\n event.preventDefault();\r\n };\r\n\r\n #setupHoverSubscription(): void {\r\n if (!this.#embeddedViewRef) return;\r\n\r\n // 3. Lấy DOM element trực tiếp từ rootNodes của EmbeddedViewRef\r\n const rootNodes = this.#embeddedViewRef.rootNodes;\r\n const element = rootNodes.find(\r\n (node) => node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).classList?.contains('sd-side-drawer')\r\n );\r\n\r\n if (!element) {\r\n console.warn('SdSideDrawer: Cannot find sd-side-drawer element to attach hover event');\r\n return;\r\n }\r\n\r\n // 4. Gắn event listeners trực tiếp lên element thật\r\n const mouseEnter$ = fromEvent(element, 'mouseenter').pipe(map(() => true));\r\n const mouseLeave$ = fromEvent(element, 'mouseleave').pipe(map(() => false));\r\n\r\n this.isHovered$ = merge(mouseEnter$, mouseLeave$).pipe(\r\n startWith(false),\r\n distinctUntilChanged(),\r\n takeUntil(this.#destroy$)\r\n );\r\n }\r\n}","<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"sd-side-drawer-header\">\r\n <div class=\"sd-side-drawer-title\">\r\n {{ title() }}\r\n <ng-content select=\"[sdHeaderLeft]\"></ng-content>\r\n </div>\r\n <div class=\"sd-side-drawer-header-actions\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n @if (!hideClose()) {\r\n <button type=\"button\" class=\"sd-side-drawer-close-btn\" (click)=\"close()\" aria-label=\"Close\">\r\n <svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" stroke=\"currentColor\" stroke-width=\"2\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n @if (isOpened) {\r\n <div class=\"sd-side-drawer-body\">\r\n <div class=\"sd-side-drawer-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"sd-side-drawer-footer\">\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (isOpened) {\r\n <button \r\n type=\"button\"\r\n class=\"sd-side-drawer-backdrop\" \r\n (click)=\"disableBackdropClose() ? null : close()\"\r\n (wheel)=\"preventScroll($event)\"\r\n (touchmove)=\"preventScroll($event)\"\r\n >\r\n </button>\r\n }\r\n</ng-template>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sd-angular-core-components-side-drawer.mjs","sources":["../../../projects/sd-angular/components/side-drawer/src/side-drawer.component.ts","../../../projects/sd-angular/components/side-drawer/src/side-drawer.component.html","../../../projects/sd-angular/components/side-drawer/sd-angular-core-components-side-drawer.ts"],"sourcesContent":["import { CdkPortal, DomPortalOutlet, PortalModule } from '@angular/cdk/portal';\r\nimport { CommonModule } from '@angular/common';\r\nimport {\r\n ApplicationRef,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n DestroyRef,\r\n EmbeddedViewRef,\r\n Injector,\r\n ViewContainerRef,\r\n afterNextRender,\r\n booleanAttribute,\r\n inject,\r\n input,\r\n output,\r\n viewChild\r\n} from '@angular/core';\r\nimport { SdBaseSecureComponent } from '@sd-angular/core/components/base';\r\nimport { SdLoadingService } from '@sd-angular/core/services';\r\nimport * as uuid from 'uuid';\r\nimport { fromEvent, merge, Observable, Subject } from 'rxjs';\r\nimport { map, takeUntil, startWith, distinctUntilChanged } from 'rxjs/operators';\r\n\r\n@Component({\r\n selector: 'sd-side-drawer',\r\n templateUrl: './side-drawer.component.html',\r\n styleUrls: ['./side-drawer.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n standalone: true,\r\n imports: [CommonModule, PortalModule],\r\n})\r\nexport class SdSideDrawer extends SdBaseSecureComponent {\r\n id = `I${uuid.v4()}`;\r\n \r\n portal = viewChild.required(CdkPortal);\r\n \r\n title = input<string>('');\r\n width = input<string>('480px');\r\n hideClose = input<boolean, boolean | ''>(false, { transform: booleanAttribute });\r\n disableBackdropClose = input<boolean, boolean | ''>(false, { transform: booleanAttribute });\r\n\r\n // Custom CSS class added to the root side-drawer container \r\n drawerClass = input<any>('');\r\n\r\n sdClosed = output<void>();\r\n\r\n #embeddedViewRef!: EmbeddedViewRef<any>;\r\n isOpened = false;\r\n isLoading = false;\r\n isHovered$!: Observable<boolean>;\r\n #destroy$ = new Subject<void>();\r\n #previousBodyOverflow: string | null = null;\r\n\r\n #viewContainerRef = inject(ViewContainerRef);\r\n #ar = inject(ApplicationRef);\r\n #injector = inject(Injector);\r\n #ref = inject(ChangeDetectorRef);\r\n #loadingService = inject(SdLoadingService);\r\n #destroyRef = inject(DestroyRef);\r\n\r\n constructor() {\r\n super();\r\n\r\n // Thay thế ngAfterViewInit, tự động chạy nội dung này khi DOM sẵn sàng để render\r\n afterNextRender(() => {\r\n // 1. Gắn portal vào body và lưu lại EmbeddedViewRef\r\n const outlet = new DomPortalOutlet(document.body, this.#viewContainerRef, this.#ar, this.#injector);\r\n this.#embeddedViewRef = outlet.attachTemplatePortal(this.portal());\r\n \r\n // 2. Setup sự kiện hover ngay sau khi DOM thật đã được in ra\r\n this.#setupHoverSubscription();\r\n });\r\n\r\n // Thay thế ngOnDestroy bằng logic destroy trực tiếp \r\n this.#destroyRef.onDestroy(() => {\r\n this.#destroy$.next();\r\n this.#destroy$.complete();\r\n \r\n if (this.#embeddedViewRef) {\r\n this.#embeddedViewRef.destroy();\r\n }\r\n \r\n if (this.isOpened) {\r\n if (this.#previousBodyOverflow !== null) {\r\n document.body.style.overflow = this.#previousBodyOverflow;\r\n } else {\r\n document.body.style.overflow = '';\r\n }\r\n }\r\n });\r\n }\r\n\r\n open = () => {\r\n this.#ref.markForCheck();\r\n this.isOpened = true;\r\n \r\n // Chặn scroll ở document body\r\n this.#previousBodyOverflow = document.body.style.overflow;\r\n document.body.style.overflow = 'hidden';\r\n };\r\n\r\n close = () => {\r\n this.#ref.markForCheck();\r\n this.isOpened = false;\r\n this.sdClosed.emit();\r\n this.stopLoading();\r\n \r\n // Khôi phục lại scroll ở document body\r\n if (this.#previousBodyOverflow !== null) {\r\n document.body.style.overflow = this.#previousBodyOverflow;\r\n this.#previousBodyOverflow = null;\r\n } else {\r\n document.body.style.overflow = '';\r\n }\r\n };\r\n\r\n startLoading = () => {\r\n this.isLoading = true;\r\n this.#loadingService.stop(`#${this.id}`);\r\n this.#loadingService.start(`#${this.id}`);\r\n };\r\n\r\n stopLoading = () => {\r\n this.isLoading = false;\r\n this.#loadingService.stop(`#${this.id}`);\r\n };\r\n\r\n preventScroll = (event: Event) => {\r\n event.preventDefault();\r\n };\r\n\r\n #setupHoverSubscription(): void {\r\n if (!this.#embeddedViewRef) return;\r\n\r\n // 3. Lấy DOM element trực tiếp từ rootNodes của EmbeddedViewRef\r\n const rootNodes = this.#embeddedViewRef.rootNodes;\r\n const element = rootNodes.find(\r\n (node) => node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).classList?.contains('sd-side-drawer')\r\n );\r\n\r\n if (!element) {\r\n console.warn('SdSideDrawer: Cannot find sd-side-drawer element to attach hover event');\r\n return;\r\n }\r\n\r\n // 4. Gắn event listeners trực tiếp lên element thật\r\n const mouseEnter$ = fromEvent(element, 'mouseenter').pipe(map(() => true));\r\n const mouseLeave$ = fromEvent(element, 'mouseleave').pipe(map(() => false));\r\n\r\n this.isHovered$ = merge(mouseEnter$, mouseLeave$).pipe(\r\n startWith(false),\r\n distinctUntilChanged(),\r\n takeUntil(this.#destroy$)\r\n );\r\n }\r\n}","<ng-template cdkPortal>\r\n <div\r\n [id]=\"id\"\r\n class=\"sd-side-drawer\"\r\n [ngStyle]=\"{ width: width() }\"\r\n [ngClass]=\"drawerClass()\"\r\n [class.sd-side-drawer-active]=\"isOpened\"\r\n #drawerContainer>\r\n @if (isOpened) {\r\n <ng-container>\r\n <div class=\"c-header\">\r\n <div class=\"sd-side-drawer-title\">\r\n <ng-content select=\"[sdHeaderLeft]\">\r\n {{ title() }}\r\n </ng-content>\r\n </div>\r\n <div class=\"sd-side-drawer-header-actions\">\r\n <ng-content select=\"[sdHeaderRight]\"></ng-content>\r\n @if (!hideClose()) {\r\n <button type=\"button\" class=\"sd-side-drawer-close-btn\" (click)=\"close()\" aria-label=\"Close\">\r\n <svg\r\n viewBox=\"0 0 24 24\"\r\n width=\"24\"\r\n height=\"24\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n fill=\"none\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n </button>\r\n }\r\n </div>\r\n </div>\r\n @if (isOpened) {\r\n <div class=\"sd-side-drawer-body\">\r\n <div class=\"sd-side-drawer-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n </div>\r\n }\r\n <div class=\"sd-side-drawer-footer\">\r\n <ng-content select=\"[sdFooter]\"></ng-content>\r\n </div>\r\n </ng-container>\r\n }\r\n </div>\r\n @if (isOpened) {\r\n <div\r\n aria-hidden=\"true\"\r\n class=\"sd-side-drawer-backdrop\"\r\n (click)=\"disableBackdropClose() ? null : close()\"\r\n (wheel)=\"preventScroll($event)\"\r\n (touchmove)=\"preventScroll($event)\"></div>\r\n }\r\n</ng-template>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|