osl-base-extended 4.0.0 → 6.0.0
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.
|
@@ -20,10 +20,10 @@ import * as i6 from '@angular/material/tooltip';
|
|
|
20
20
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
21
21
|
import * as i5 from '@angular/material/datepicker';
|
|
22
22
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
23
|
-
import { MatInputModule } from '@angular/material/input';
|
|
24
23
|
import { MAT_DATE_FORMATS } from '@angular/material/core';
|
|
25
24
|
import * as i4 from '@ngxmc/datetime-picker';
|
|
26
25
|
import { NgxMatDatetimepicker, NgxMatDatepickerInput } from '@ngxmc/datetime-picker';
|
|
26
|
+
import { MatInputModule } from '@angular/material/input';
|
|
27
27
|
import { debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1, switchMap, tap } from 'rxjs/operators';
|
|
28
28
|
import { MatMenuModule } from '@angular/material/menu';
|
|
29
29
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
@@ -108,6 +108,27 @@ class DeleteConfirmationData {
|
|
|
108
108
|
data;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
class ErrorDialog {
|
|
112
|
+
dialogRef;
|
|
113
|
+
data;
|
|
114
|
+
constructor(dialogRef, data) {
|
|
115
|
+
this.dialogRef = dialogRef;
|
|
116
|
+
this.data = data;
|
|
117
|
+
}
|
|
118
|
+
close() {
|
|
119
|
+
this.dialogRef.close();
|
|
120
|
+
}
|
|
121
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ErrorDialog, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
122
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: ErrorDialog, isStandalone: true, selector: "error-dialog", ngImport: i0, template: "<div class=\"ed-container\">\n\n <!-- Header -->\n <div class=\"ed-header\">\n <div class=\"ed-icon-wrapper\">\n <div class=\"ed-icon-ring\">\n <svg class=\"ed-icon-svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n </div>\n </div>\n <button mat-icon-button class=\"ed-close-btn\" (click)=\"close()\" aria-label=\"Close\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"20\" height=\"20\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <mat-dialog-content class=\"ed-body\">\n <h2 class=\"ed-title\">{{ data.title }}</h2>\n <p class=\"ed-subtitle\">\n Please fix the following\n <strong>{{ data.errors.length }}</strong>\n {{ data.errors.length === 1 ? 'issue' : 'issues' }} before proceeding.\n </p>\n <ul class=\"ed-list\">\n @for (err of data.errors; track $index) {\n <li class=\"ed-item\" [style.animation-delay]=\"($index * 60) + 'ms'\">\n <span class=\"ed-item-dot\"></span>\n <span class=\"ed-item-text\">{{ err }}</span>\n </li>\n }\n </ul>\n </mat-dialog-content>\n\n <!-- Actions -->\n <mat-dialog-actions class=\"ed-actions\">\n <button mat-flat-button class=\"ed-confirm-btn\" (click)=\"close()\">\n <svg class=\"ed-btn-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n Got it\n </button>\n </mat-dialog-actions>\n\n</div>\n", styles: ["@charset \"UTF-8\";.ed-container{padding:8px 4px}.ed-header{display:flex;justify-content:space-between;align-items:flex-start;padding:8px 8px 0}.ed-icon-wrapper{display:flex;align-items:center;justify-content:center;flex:1;padding-left:40px}.ed-icon-ring{width:72px;height:72px;border-radius:50%;background:#dc262614;border:2px solid rgba(220,38,38,.2);display:flex;align-items:center;justify-content:center;animation:ed-pulse 2.4s ease-in-out infinite}.ed-icon-svg{width:36px;height:36px;color:var(--osl-danger, #dc2626);animation:ed-bounce 2.4s ease-in-out infinite}.ed-close-btn{color:var(--osl-secondary, #6b7280);flex-shrink:0}.ed-close-btn:hover{color:var(--osl-black, #111827)}.ed-body{padding:16px 24px 4px!important;max-height:320px!important;overflow-y:auto!important;text-align:center}.ed-title{font-size:20px;font-weight:600;color:var(--osl-black, #111827);margin:0 0 8px;line-height:1.3}.ed-subtitle{font-size:13.5px;color:var(--osl-secondary, #6b7280);margin:0 0 16px;line-height:1.5}.ed-list{list-style:none;margin:0;padding:0;text-align:left;display:flex;flex-direction:column;gap:8px}.ed-item{display:flex;align-items:flex-start;gap:10px;background:#dc26260a;border:1px solid rgba(220,38,38,.14);border-left:3px solid var(--osl-danger, #dc2626);border-radius:6px;padding:8px 12px;font-size:13.5px;color:var(--osl-black, #111827);line-height:1.5;opacity:0;animation:ed-slide-in .35s ease forwards}.ed-item-dot{flex-shrink:0;width:6px;height:6px;border-radius:50%;background:var(--osl-danger, #dc2626);margin-top:6px}.ed-item-text{flex:1}.ed-actions{display:flex!important;justify-content:center;padding:16px 24px 20px!important}.ed-confirm-btn{background:var(--osl-danger, #dc2626);color:#fff;border-radius:var(--osl-border-radius, 4px);height:38px;font-size:14px;font-weight:500;display:flex;align-items:center;gap:6px;padding:0 24px;transition:background .2s ease,box-shadow .2s ease;min-width:120px;justify-content:center}.ed-confirm-btn .ed-btn-icon{width:17px;height:17px;flex-shrink:0;color:#fff}.ed-confirm-btn:hover{background:var(--osl-danger-hover, #b91c1c);box-shadow:0 4px 14px #dc262659}.ed-body::-webkit-scrollbar{width:4px}.ed-body::-webkit-scrollbar-track{background:transparent}.ed-body::-webkit-scrollbar-thumb{background:#dc262640;border-radius:4px}@keyframes ed-pulse{0%,to{box-shadow:0 0 #dc262626}50%{box-shadow:0 0 0 10px #dc262600}}@keyframes ed-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}@keyframes ed-slide-in{0%{opacity:0;transform:translate(-12px)}to{opacity:1;transform:translate(0)}}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i2$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
|
|
123
|
+
}
|
|
124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ErrorDialog, decorators: [{
|
|
125
|
+
type: Component,
|
|
126
|
+
args: [{ selector: 'error-dialog', standalone: true, imports: [MatDialogModule, MatButtonModule], template: "<div class=\"ed-container\">\n\n <!-- Header -->\n <div class=\"ed-header\">\n <div class=\"ed-icon-wrapper\">\n <div class=\"ed-icon-ring\">\n <svg class=\"ed-icon-svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z\"/>\n </svg>\n </div>\n </div>\n <button mat-icon-button class=\"ed-close-btn\" (click)=\"close()\" aria-label=\"Close\">\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" width=\"20\" height=\"20\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <mat-dialog-content class=\"ed-body\">\n <h2 class=\"ed-title\">{{ data.title }}</h2>\n <p class=\"ed-subtitle\">\n Please fix the following\n <strong>{{ data.errors.length }}</strong>\n {{ data.errors.length === 1 ? 'issue' : 'issues' }} before proceeding.\n </p>\n <ul class=\"ed-list\">\n @for (err of data.errors; track $index) {\n <li class=\"ed-item\" [style.animation-delay]=\"($index * 60) + 'ms'\">\n <span class=\"ed-item-dot\"></span>\n <span class=\"ed-item-text\">{{ err }}</span>\n </li>\n }\n </ul>\n </mat-dialog-content>\n\n <!-- Actions -->\n <mat-dialog-actions class=\"ed-actions\">\n <button mat-flat-button class=\"ed-confirm-btn\" (click)=\"close()\">\n <svg class=\"ed-btn-icon\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z\"/>\n </svg>\n Got it\n </button>\n </mat-dialog-actions>\n\n</div>\n", styles: ["@charset \"UTF-8\";.ed-container{padding:8px 4px}.ed-header{display:flex;justify-content:space-between;align-items:flex-start;padding:8px 8px 0}.ed-icon-wrapper{display:flex;align-items:center;justify-content:center;flex:1;padding-left:40px}.ed-icon-ring{width:72px;height:72px;border-radius:50%;background:#dc262614;border:2px solid rgba(220,38,38,.2);display:flex;align-items:center;justify-content:center;animation:ed-pulse 2.4s ease-in-out infinite}.ed-icon-svg{width:36px;height:36px;color:var(--osl-danger, #dc2626);animation:ed-bounce 2.4s ease-in-out infinite}.ed-close-btn{color:var(--osl-secondary, #6b7280);flex-shrink:0}.ed-close-btn:hover{color:var(--osl-black, #111827)}.ed-body{padding:16px 24px 4px!important;max-height:320px!important;overflow-y:auto!important;text-align:center}.ed-title{font-size:20px;font-weight:600;color:var(--osl-black, #111827);margin:0 0 8px;line-height:1.3}.ed-subtitle{font-size:13.5px;color:var(--osl-secondary, #6b7280);margin:0 0 16px;line-height:1.5}.ed-list{list-style:none;margin:0;padding:0;text-align:left;display:flex;flex-direction:column;gap:8px}.ed-item{display:flex;align-items:flex-start;gap:10px;background:#dc26260a;border:1px solid rgba(220,38,38,.14);border-left:3px solid var(--osl-danger, #dc2626);border-radius:6px;padding:8px 12px;font-size:13.5px;color:var(--osl-black, #111827);line-height:1.5;opacity:0;animation:ed-slide-in .35s ease forwards}.ed-item-dot{flex-shrink:0;width:6px;height:6px;border-radius:50%;background:var(--osl-danger, #dc2626);margin-top:6px}.ed-item-text{flex:1}.ed-actions{display:flex!important;justify-content:center;padding:16px 24px 20px!important}.ed-confirm-btn{background:var(--osl-danger, #dc2626);color:#fff;border-radius:var(--osl-border-radius, 4px);height:38px;font-size:14px;font-weight:500;display:flex;align-items:center;gap:6px;padding:0 24px;transition:background .2s ease,box-shadow .2s ease;min-width:120px;justify-content:center}.ed-confirm-btn .ed-btn-icon{width:17px;height:17px;flex-shrink:0;color:#fff}.ed-confirm-btn:hover{background:var(--osl-danger-hover, #b91c1c);box-shadow:0 4px 14px #dc262659}.ed-body::-webkit-scrollbar{width:4px}.ed-body::-webkit-scrollbar-track{background:transparent}.ed-body::-webkit-scrollbar-thumb{background:#dc262640;border-radius:4px}@keyframes ed-pulse{0%,to{box-shadow:0 0 #dc262626}50%{box-shadow:0 0 0 10px #dc262600}}@keyframes ed-bounce{0%,to{transform:translateY(0)}50%{transform:translateY(-3px)}}@keyframes ed-slide-in{0%{opacity:0;transform:translate(-12px)}to{opacity:1;transform:translate(0)}}\n"] }]
|
|
127
|
+
}], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: undefined, decorators: [{
|
|
128
|
+
type: Inject,
|
|
129
|
+
args: [MAT_DIALOG_DATA]
|
|
130
|
+
}] }] });
|
|
131
|
+
|
|
111
132
|
class DirtyStateService {
|
|
112
133
|
_isDirty = false;
|
|
113
134
|
_saveCallback;
|
|
@@ -143,11 +164,18 @@ class baseComponent {
|
|
|
143
164
|
}
|
|
144
165
|
this.showSnack(message);
|
|
145
166
|
}
|
|
146
|
-
showError(error) {
|
|
147
|
-
if (Array.isArray(error)) {
|
|
148
|
-
|
|
167
|
+
showError(error, title = 'Validation Failed') {
|
|
168
|
+
if (Array.isArray(error) && error.length > 4) {
|
|
169
|
+
const dialogData = { title, errors: error };
|
|
170
|
+
this._injector.get(MatDialog).open(ErrorDialog, {
|
|
171
|
+
width: '460px',
|
|
172
|
+
data: dialogData,
|
|
173
|
+
disableClose: false,
|
|
174
|
+
});
|
|
175
|
+
return;
|
|
149
176
|
}
|
|
150
|
-
|
|
177
|
+
const message = Array.isArray(error) ? error.join(', ') : error;
|
|
178
|
+
this.showSnack(message);
|
|
151
179
|
}
|
|
152
180
|
navigate(url) {
|
|
153
181
|
this._injector.get(Router).navigate([url]);
|
|
@@ -2028,11 +2056,26 @@ class OslFileUpload {
|
|
|
2028
2056
|
maxSize = 0;
|
|
2029
2057
|
skeletonLoading = false;
|
|
2030
2058
|
skeletonTheme = 'light';
|
|
2059
|
+
/** When 'base64', emits OslFileValue instead of File objects. */
|
|
2060
|
+
fileMode = 'raw';
|
|
2061
|
+
/** Called when user clicks download on a saved file that has no base64 content. */
|
|
2062
|
+
downloadFn = null;
|
|
2031
2063
|
modelChange = new EventEmitter();
|
|
2032
2064
|
changeEv = new EventEmitter();
|
|
2033
2065
|
touched = false;
|
|
2034
2066
|
isDragOver = false;
|
|
2035
2067
|
sizeError = false;
|
|
2068
|
+
get isBase64Mode() {
|
|
2069
|
+
return this.fileMode === 'base64';
|
|
2070
|
+
}
|
|
2071
|
+
get savedFileName() {
|
|
2072
|
+
if (!this.isBase64Mode)
|
|
2073
|
+
return null;
|
|
2074
|
+
return this.model?.fileName ?? null;
|
|
2075
|
+
}
|
|
2076
|
+
get hasSavedContent() {
|
|
2077
|
+
return !!this.model?.fileContent;
|
|
2078
|
+
}
|
|
2036
2079
|
get fileNames() {
|
|
2037
2080
|
if (!this.model)
|
|
2038
2081
|
return '';
|
|
@@ -2041,6 +2084,8 @@ class OslFileUpload {
|
|
|
2041
2084
|
return this.model.name;
|
|
2042
2085
|
}
|
|
2043
2086
|
get isInvalid() {
|
|
2087
|
+
if (this.isBase64Mode)
|
|
2088
|
+
return this.touched && this.required && !this.savedFileName;
|
|
2044
2089
|
return this.touched && this.required && !this.model;
|
|
2045
2090
|
}
|
|
2046
2091
|
onFileChange(event) {
|
|
@@ -2079,6 +2124,18 @@ class OslFileUpload {
|
|
|
2079
2124
|
}
|
|
2080
2125
|
}
|
|
2081
2126
|
}
|
|
2127
|
+
if (this.isBase64Mode) {
|
|
2128
|
+
const file = files[0];
|
|
2129
|
+
const reader = new FileReader();
|
|
2130
|
+
reader.onload = () => {
|
|
2131
|
+
const value = { fileName: file.name, fileContent: reader.result };
|
|
2132
|
+
this.model = value;
|
|
2133
|
+
this.modelChange.emit(value);
|
|
2134
|
+
this.changeEv.emit(value);
|
|
2135
|
+
};
|
|
2136
|
+
reader.readAsDataURL(file);
|
|
2137
|
+
return;
|
|
2138
|
+
}
|
|
2082
2139
|
if (this.multiple) {
|
|
2083
2140
|
this.model = Array.from(files);
|
|
2084
2141
|
}
|
|
@@ -2099,6 +2156,18 @@ class OslFileUpload {
|
|
|
2099
2156
|
this.modelChange.emit(null);
|
|
2100
2157
|
this.changeEv.emit(null);
|
|
2101
2158
|
}
|
|
2159
|
+
onDownload() {
|
|
2160
|
+
const val = this.model;
|
|
2161
|
+
if (val?.fileContent) {
|
|
2162
|
+
const a = document.createElement('a');
|
|
2163
|
+
a.href = val.fileContent;
|
|
2164
|
+
a.download = val.fileName;
|
|
2165
|
+
a.click();
|
|
2166
|
+
}
|
|
2167
|
+
else if (this.downloadFn) {
|
|
2168
|
+
this.downloadFn();
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2102
2171
|
get maxSizeLabel() {
|
|
2103
2172
|
if (!this.maxSize)
|
|
2104
2173
|
return '';
|
|
@@ -2109,11 +2178,11 @@ class OslFileUpload {
|
|
|
2109
2178
|
return `Max ${this.maxSize} B`;
|
|
2110
2179
|
}
|
|
2111
2180
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFileUpload, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2112
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslFileUpload, isStandalone: false, selector: "osl-file-upload", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", accept: "accept", multiple: "multiple", maxSize: "maxSize", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, ngImport: i0, template: "<div class=\"d-flex flex-column\">\r\n <div [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </label>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n [accept]=\"accept\"\r\n [multiple]=\"multiple\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileChange($event)\"\r\n #fileInput\r\n class=\"file-input\"\r\n >\r\n\r\n <div\r\n [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\"\r\n class=\"drop-zone\"\r\n [class.error]=\"isInvalid || sizeError\"\r\n [class.file-disabled]=\"disabled\"\r\n [class.drag-over]=\"isDragOver\"\r\n [class.has-file]=\"!!model\"\r\n (click)=\"triggerInput(fileInput)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave()\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if(!
|
|
2181
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslFileUpload, isStandalone: false, selector: "osl-file-upload", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", accept: "accept", multiple: "multiple", maxSize: "maxSize", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme", fileMode: "fileMode", downloadFn: "downloadFn" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, ngImport: i0, template: "<div class=\"d-flex flex-column\">\r\n <div [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </label>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n [accept]=\"accept\"\r\n [multiple]=\"multiple\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileChange($event)\"\r\n #fileInput\r\n class=\"file-input\"\r\n >\r\n\r\n <div\r\n [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\"\r\n class=\"drop-zone\"\r\n [class.error]=\"isInvalid || sizeError\"\r\n [class.file-disabled]=\"disabled\"\r\n [class.drag-over]=\"isDragOver\"\r\n [class.has-file]=\"isBase64Mode ? !!savedFileName : !!model\"\r\n (click)=\"isBase64Mode && savedFileName ? null : triggerInput(fileInput)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave()\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if(isBase64Mode) {\r\n @if(savedFileName) {\r\n <div class=\"file-list\">\r\n <mat-icon class=\"file-icon\">insert_drive_file</mat-icon>\r\n <span class=\"file-name\">{{ savedFileName }}</span>\r\n <button type=\"button\" class=\"download-btn\" (click)=\"onDownload()\" title=\"Download\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n @if(!disabled) {\r\n <button type=\"button\" class=\"clear-btn\" (click)=\"clearFiles($event)\" title=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"drop-content\">\r\n <mat-icon class=\"upload-icon\">upload_file</mat-icon>\r\n <div class=\"drop-text\">\r\n <span class=\"browse-link\">Browse</span> or drag & drop\r\n </div>\r\n @if(accept) { <div class=\"drop-meta\">{{accept}}</div> }\r\n @if(maxSize) { <div class=\"drop-meta\">{{maxSizeLabel}}</div> }\r\n </div>\r\n }\r\n } @else {\r\n @if(!model) {\r\n <div class=\"drop-content\">\r\n <mat-icon class=\"upload-icon\">upload_file</mat-icon>\r\n <div class=\"drop-text\">\r\n <span class=\"browse-link\">Browse</span> or drag & drop\r\n </div>\r\n @if(accept) { <div class=\"drop-meta\">{{accept}}</div> }\r\n @if(maxSize) { <div class=\"drop-meta\">{{maxSizeLabel}}</div> }\r\n </div>\r\n } @else {\r\n <div class=\"file-list\">\r\n <mat-icon class=\"file-icon\">insert_drive_file</mat-icon>\r\n <span class=\"file-name\">{{fileNames}}</span>\r\n <button type=\"button\" class=\"clear-btn\" (click)=\"clearFiles($event)\" title=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n @if(sizeError) {\r\n <mat-hint class=\"hint\">File exceeds the {{maxSizeLabel}} limit.</mat-hint>\r\n } @else if(isInvalid) {\r\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\r\n }\r\n</div>\r\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px;display:flex;align-items:center;overflow:hidden}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.label-required{flex-shrink:0}.file-input{display:none}.drop-zone{width:100%;min-height:var(--osl-control-height);border-radius:var(--osl-border-radius);border:1.5px dashed var(--osl-border-color);cursor:pointer;transition:border-color .3s,background .3s;display:flex;align-items:center;justify-content:center;padding:8px}.drop-zone:hover:not(.file-disabled){border-color:var(--osl-focus-border-color);background:#00000003}.drop-zone.drag-over{border-color:var(--osl-focus-border-color);background:#00000008}.drop-zone.has-file{border-style:solid;border-color:var(--osl-border-color)}.drop-zone.error{border-color:var(--osl-error-color)}.drop-zone.file-disabled{opacity:.6;cursor:not-allowed;background:#f5f5f5}.drop-content{display:flex;flex-direction:column;align-items:center;gap:4px;color:#888;pointer-events:none}.upload-icon{font-size:28px;width:28px;height:28px;color:#bbb}.drop-text{font-size:var(--osl-label-font-size)}.browse-link{color:var(--osl-focus-border-color);font-weight:500}.drop-meta{font-size:var(--osl-hint-font-size);color:#bbb}.file-list{display:flex;align-items:center;gap:8px;width:100%;pointer-events:none}.file-icon{font-size:20px;width:20px;height:20px;color:#888;flex-shrink:0}.file-name{flex:1;font-size:var(--osl-text-font-size);color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.clear-btn,.download-btn{pointer-events:all;display:flex;align-items:center;background:none;border:none;cursor:pointer;color:#aaa;padding:0;flex-shrink:0}.clear-btn mat-icon,.download-btn mat-icon{font-size:16px;width:16px;height:16px}.clear-btn:hover{color:var(--osl-error-color)}.download-btn:hover{color:var(--osl-focus-border-color)}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}\n"], dependencies: [{ kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }] });
|
|
2113
2182
|
}
|
|
2114
2183
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFileUpload, decorators: [{
|
|
2115
2184
|
type: Component,
|
|
2116
|
-
args: [{ selector: 'osl-file-upload', standalone: false, template: "<div class=\"d-flex flex-column\">\r\n <div [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </label>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n [accept]=\"accept\"\r\n [multiple]=\"multiple\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileChange($event)\"\r\n #fileInput\r\n class=\"file-input\"\r\n >\r\n\r\n <div\r\n [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\"\r\n class=\"drop-zone\"\r\n [class.error]=\"isInvalid || sizeError\"\r\n [class.file-disabled]=\"disabled\"\r\n [class.drag-over]=\"isDragOver\"\r\n [class.has-file]=\"!!model\"\r\n (click)=\"triggerInput(fileInput)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave()\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if(!
|
|
2185
|
+
args: [{ selector: 'osl-file-upload', standalone: false, template: "<div class=\"d-flex flex-column\">\r\n <div [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </label>\r\n </div>\r\n\r\n <input\r\n type=\"file\"\r\n [accept]=\"accept\"\r\n [multiple]=\"multiple\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileChange($event)\"\r\n #fileInput\r\n class=\"file-input\"\r\n >\r\n\r\n <div\r\n [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\"\r\n class=\"drop-zone\"\r\n [class.error]=\"isInvalid || sizeError\"\r\n [class.file-disabled]=\"disabled\"\r\n [class.drag-over]=\"isDragOver\"\r\n [class.has-file]=\"isBase64Mode ? !!savedFileName : !!model\"\r\n (click)=\"isBase64Mode && savedFileName ? null : triggerInput(fileInput)\"\r\n (dragover)=\"onDragOver($event)\"\r\n (dragleave)=\"onDragLeave()\"\r\n (drop)=\"onDrop($event)\"\r\n >\r\n @if(isBase64Mode) {\r\n @if(savedFileName) {\r\n <div class=\"file-list\">\r\n <mat-icon class=\"file-icon\">insert_drive_file</mat-icon>\r\n <span class=\"file-name\">{{ savedFileName }}</span>\r\n <button type=\"button\" class=\"download-btn\" (click)=\"onDownload()\" title=\"Download\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n @if(!disabled) {\r\n <button type=\"button\" class=\"clear-btn\" (click)=\"clearFiles($event)\" title=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"drop-content\">\r\n <mat-icon class=\"upload-icon\">upload_file</mat-icon>\r\n <div class=\"drop-text\">\r\n <span class=\"browse-link\">Browse</span> or drag & drop\r\n </div>\r\n @if(accept) { <div class=\"drop-meta\">{{accept}}</div> }\r\n @if(maxSize) { <div class=\"drop-meta\">{{maxSizeLabel}}</div> }\r\n </div>\r\n }\r\n } @else {\r\n @if(!model) {\r\n <div class=\"drop-content\">\r\n <mat-icon class=\"upload-icon\">upload_file</mat-icon>\r\n <div class=\"drop-text\">\r\n <span class=\"browse-link\">Browse</span> or drag & drop\r\n </div>\r\n @if(accept) { <div class=\"drop-meta\">{{accept}}</div> }\r\n @if(maxSize) { <div class=\"drop-meta\">{{maxSizeLabel}}</div> }\r\n </div>\r\n } @else {\r\n <div class=\"file-list\">\r\n <mat-icon class=\"file-icon\">insert_drive_file</mat-icon>\r\n <span class=\"file-name\">{{fileNames}}</span>\r\n <button type=\"button\" class=\"clear-btn\" (click)=\"clearFiles($event)\" title=\"Remove\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n }\r\n </div>\r\n\r\n @if(sizeError) {\r\n <mat-hint class=\"hint\">File exceeds the {{maxSizeLabel}} limit.</mat-hint>\r\n } @else if(isInvalid) {\r\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\r\n }\r\n</div>\r\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px;display:flex;align-items:center;overflow:hidden}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.label-required{flex-shrink:0}.file-input{display:none}.drop-zone{width:100%;min-height:var(--osl-control-height);border-radius:var(--osl-border-radius);border:1.5px dashed var(--osl-border-color);cursor:pointer;transition:border-color .3s,background .3s;display:flex;align-items:center;justify-content:center;padding:8px}.drop-zone:hover:not(.file-disabled){border-color:var(--osl-focus-border-color);background:#00000003}.drop-zone.drag-over{border-color:var(--osl-focus-border-color);background:#00000008}.drop-zone.has-file{border-style:solid;border-color:var(--osl-border-color)}.drop-zone.error{border-color:var(--osl-error-color)}.drop-zone.file-disabled{opacity:.6;cursor:not-allowed;background:#f5f5f5}.drop-content{display:flex;flex-direction:column;align-items:center;gap:4px;color:#888;pointer-events:none}.upload-icon{font-size:28px;width:28px;height:28px;color:#bbb}.drop-text{font-size:var(--osl-label-font-size)}.browse-link{color:var(--osl-focus-border-color);font-weight:500}.drop-meta{font-size:var(--osl-hint-font-size);color:#bbb}.file-list{display:flex;align-items:center;gap:8px;width:100%;pointer-events:none}.file-icon{font-size:20px;width:20px;height:20px;color:#888;flex-shrink:0}.file-name{flex:1;font-size:var(--osl-text-font-size);color:#333;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.clear-btn,.download-btn{pointer-events:all;display:flex;align-items:center;background:none;border:none;cursor:pointer;color:#aaa;padding:0;flex-shrink:0}.clear-btn mat-icon,.download-btn mat-icon{font-size:16px;width:16px;height:16px}.clear-btn:hover{color:var(--osl-error-color)}.download-btn:hover{color:var(--osl-focus-border-color)}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}\n"] }]
|
|
2117
2186
|
}], propDecorators: { label: [{
|
|
2118
2187
|
type: Input,
|
|
2119
2188
|
args: ['label']
|
|
@@ -2141,6 +2210,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2141
2210
|
}], skeletonTheme: [{
|
|
2142
2211
|
type: Input,
|
|
2143
2212
|
args: ['skeletonTheme']
|
|
2213
|
+
}], fileMode: [{
|
|
2214
|
+
type: Input,
|
|
2215
|
+
args: ['fileMode']
|
|
2216
|
+
}], downloadFn: [{
|
|
2217
|
+
type: Input,
|
|
2218
|
+
args: ['downloadFn']
|
|
2144
2219
|
}], modelChange: [{
|
|
2145
2220
|
type: Output
|
|
2146
2221
|
}], changeEv: [{
|
|
@@ -2246,295 +2321,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2246
2321
|
type: Output
|
|
2247
2322
|
}] } });
|
|
2248
2323
|
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
skeletonLoading = false;
|
|
2257
|
-
skeletonTheme = 'light';
|
|
2258
|
-
modelChange = new EventEmitter();
|
|
2259
|
-
changeEv = new EventEmitter();
|
|
2260
|
-
touched = false;
|
|
2261
|
-
get isInvalid() {
|
|
2262
|
-
return this.touched && this.required && !this.model;
|
|
2263
|
-
}
|
|
2264
|
-
ngOnChanges(changes) {
|
|
2265
|
-
if (changes['indeterminate'] && this.checkboxEl) {
|
|
2266
|
-
this.checkboxEl.nativeElement.indeterminate = this.indeterminate;
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
|
-
ngAfterViewInit() {
|
|
2270
|
-
if (this.checkboxEl) {
|
|
2271
|
-
this.checkboxEl.nativeElement.indeterminate = this.indeterminate;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
onModelChange(event) {
|
|
2275
|
-
this.touched = true;
|
|
2276
|
-
this.model = event;
|
|
2277
|
-
this.modelChange.emit(this.model);
|
|
2278
|
-
this.changeEv.emit(this.model);
|
|
2279
|
-
}
|
|
2280
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2281
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslCheckbox, isStandalone: false, selector: "osl-checkbox", inputs: { label: "label", disabled: "disabled", required: "required", model: "model", indeterminate: "indeterminate", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, viewQueries: [{ propertyName: "checkboxEl", first: true, predicate: ["checkboxEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex flex-column\">\r\n\r\n <label class=\"checkbox-wrapper\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\" [class.checkbox-disabled]=\"disabled\" [class.checkbox-invalid]=\"isInvalid\">\r\n <input\r\n #checkboxEl\r\n type=\"checkbox\"\r\n [ngModel]=\"model\"\r\n (ngModelChange)=\"onModelChange($event)\"\r\n [disabled]=\"disabled\"\r\n >\r\n <span class=\"checkbox-label\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </span>\r\n </label>\r\n @if(isInvalid) {\r\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\r\n }\r\n</div>\r\n", styles: [".checkbox-wrapper{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:var(--osl-label-font-size);width:fit-content;max-width:100%}.checkbox-wrapper input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:#333;flex-shrink:0}.checkbox-wrapper .checkbox-label{-webkit-user-select:none;user-select:none;display:flex;align-items:center;overflow:hidden;min-width:0}.checkbox-wrapper.checkbox-disabled{opacity:.6;cursor:not-allowed}.checkbox-wrapper.checkbox-disabled input[type=checkbox]{cursor:not-allowed}.checkbox-wrapper.checkbox-invalid{color:var(--osl-error-color)}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.label-required{flex-shrink:0}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}\n"], dependencies: [{ kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }] });
|
|
2324
|
+
// ─── Date Utilities ───────────────────────────────────────────────────────────
|
|
2325
|
+
const MONTH_NAMES_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
2326
|
+
const MONTH_NAMES_FULL = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
2327
|
+
const DAY_NAMES_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
2328
|
+
const DAY_NAMES_FULL = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
2329
|
+
function pad(n) {
|
|
2330
|
+
return String(n).padStart(2, '0');
|
|
2282
2331
|
}
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
}], propDecorators: { checkboxEl: [{
|
|
2287
|
-
type: ViewChild,
|
|
2288
|
-
args: ['checkboxEl']
|
|
2289
|
-
}], label: [{
|
|
2290
|
-
type: Input,
|
|
2291
|
-
args: ['label']
|
|
2292
|
-
}], disabled: [{
|
|
2293
|
-
type: Input,
|
|
2294
|
-
args: ['disabled']
|
|
2295
|
-
}], required: [{
|
|
2296
|
-
type: Input,
|
|
2297
|
-
args: ['required']
|
|
2298
|
-
}], model: [{
|
|
2299
|
-
type: Input,
|
|
2300
|
-
args: ['model']
|
|
2301
|
-
}], indeterminate: [{
|
|
2302
|
-
type: Input,
|
|
2303
|
-
args: ['indeterminate']
|
|
2304
|
-
}], skeletonLoading: [{
|
|
2305
|
-
type: Input,
|
|
2306
|
-
args: ['skeletonLoading']
|
|
2307
|
-
}], skeletonTheme: [{
|
|
2308
|
-
type: Input,
|
|
2309
|
-
args: ['skeletonTheme']
|
|
2310
|
-
}], modelChange: [{
|
|
2311
|
-
type: Output
|
|
2312
|
-
}], changeEv: [{
|
|
2313
|
-
type: Output
|
|
2314
|
-
}] } });
|
|
2315
|
-
|
|
2316
|
-
class OslButton {
|
|
2317
|
-
label = 'Button';
|
|
2318
|
-
icon = '';
|
|
2319
|
-
variant = 'primary';
|
|
2320
|
-
size = 'md';
|
|
2321
|
-
disabled = false;
|
|
2322
|
-
loading = false;
|
|
2323
|
-
type = 'button';
|
|
2324
|
-
fullWidth = false;
|
|
2325
|
-
clickEv = new EventEmitter();
|
|
2326
|
-
get classes() {
|
|
2327
|
-
return [
|
|
2328
|
-
'osl-btn',
|
|
2329
|
-
`osl-btn--${this.variant}`,
|
|
2330
|
-
`osl-btn--${this.size}`,
|
|
2331
|
-
this.fullWidth ? 'osl-btn--full' : '',
|
|
2332
|
-
]
|
|
2333
|
-
.filter(Boolean)
|
|
2334
|
-
.join(' ');
|
|
2335
|
-
}
|
|
2336
|
-
onClick() {
|
|
2337
|
-
if (!this.disabled && !this.loading) {
|
|
2338
|
-
this.clickEv.emit();
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2341
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2342
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslButton, isStandalone: false, selector: "osl-button", inputs: { label: "label", icon: "icon", variant: "variant", size: "size", disabled: "disabled", loading: "loading", type: "type", fullWidth: "fullWidth" }, outputs: { clickEv: "clickEv" }, ngImport: i0, template: "@if (variant == 'icon' && icon) {\r\n <button class=\"icon-btn\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n } @else {\r\n <mat-icon>{{ icon }}</mat-icon>\r\n }\r\n </button>\r\n} @else {\r\n <button [class]=\"classes\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n }\r\n <span class=\"osl-btn__label\">{{ label }}</span>\r\n @if (icon) {\r\n <span class=\"osl-btn__label-icon\"\r\n ><mat-icon>{{ icon }}</mat-icon></span\r\n >\r\n }\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";.osl-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:var(--osl-border-radius);cursor:pointer;font-size:var(--osl-label-font-size);font-weight:500;line-height:1;transition:background-color .2s ease,border-color .2s ease,opacity .2s ease;white-space:nowrap;outline:none}.osl-btn--sm{height:28px;padding:0 var(--osl-hint-font-size);font-size:var(--osl-hint-font-size)}.osl-btn--sm mat-icon{font-size:var(--osl-hint-font-size)}.osl-btn--md{height:36px;padding:0 18px;font-size:var(--osl-label-font-size)}.osl-btn--lg{height:44px;padding:0 24px;font-size:16px}.osl-btn--full{width:100%}.osl-btn:disabled{opacity:var(--osl-disabled-opacity);cursor:not-allowed}.osl-btn--primary{background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--primary:hover:not(:disabled){background-color:var(--osl-primary-hover)}.osl-btn--secondary{background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--secondary:hover:not(:disabled){background-color:var(--osl-secondary-hover)}.osl-btn--success{background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--success:hover:not(:disabled){background-color:var(--osl-success-hover)}.osl-btn--danger{background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--danger:hover:not(:disabled){background-color:var(--osl-danger-hover)}.osl-btn--warning{background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--warning:hover:not(:disabled){background-color:var(--osl-warning-hover)}.osl-btn--info{background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn--info:hover:not(:disabled){background-color:var(--osl-info-hover)}.osl-btn--outline-primary{background-color:transparent;border:1.5px solid var(--osl-primary);color:var(--osl-primary)}.osl-btn--outline-primary:hover:not(:disabled){background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--outline-secondary{background-color:transparent;border:1.5px solid var(--osl-secondary);color:var(--osl-secondary)}.osl-btn--outline-secondary:hover:not(:disabled){background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--outline-success{background-color:transparent;border:1.5px solid var(--osl-success);color:var(--osl-success)}.osl-btn--outline-success:hover:not(:disabled){background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--outline-danger{background-color:transparent;border:1.5px solid var(--osl-danger);color:var(--osl-danger)}.osl-btn--outline-danger:hover:not(:disabled){background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--outline-warning{background-color:transparent;border:1.5px solid var(--osl-warning);color:var(--osl-warning)}.osl-btn--outline-warning:hover:not(:disabled){background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--outline-info{background-color:transparent;border:1.5px solid var(--osl-info);color:var(--osl-info)}.osl-btn--outline-info:hover:not(:disabled){background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn__spinner{display:inline-block;width:var(--osl-label-font-size);height:var(--osl-label-font-size);border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:osl-spin .7s linear infinite}@keyframes osl-spin{to{transform:rotate(360deg)}}.osl-btn__label-icon{color:var(--color-white)}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
2343
|
-
}
|
|
2344
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslButton, decorators: [{
|
|
2345
|
-
type: Component,
|
|
2346
|
-
args: [{ selector: 'osl-button', standalone: false, template: "@if (variant == 'icon' && icon) {\r\n <button class=\"icon-btn\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n } @else {\r\n <mat-icon>{{ icon }}</mat-icon>\r\n }\r\n </button>\r\n} @else {\r\n <button [class]=\"classes\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n }\r\n <span class=\"osl-btn__label\">{{ label }}</span>\r\n @if (icon) {\r\n <span class=\"osl-btn__label-icon\"\r\n ><mat-icon>{{ icon }}</mat-icon></span\r\n >\r\n }\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";.osl-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:var(--osl-border-radius);cursor:pointer;font-size:var(--osl-label-font-size);font-weight:500;line-height:1;transition:background-color .2s ease,border-color .2s ease,opacity .2s ease;white-space:nowrap;outline:none}.osl-btn--sm{height:28px;padding:0 var(--osl-hint-font-size);font-size:var(--osl-hint-font-size)}.osl-btn--sm mat-icon{font-size:var(--osl-hint-font-size)}.osl-btn--md{height:36px;padding:0 18px;font-size:var(--osl-label-font-size)}.osl-btn--lg{height:44px;padding:0 24px;font-size:16px}.osl-btn--full{width:100%}.osl-btn:disabled{opacity:var(--osl-disabled-opacity);cursor:not-allowed}.osl-btn--primary{background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--primary:hover:not(:disabled){background-color:var(--osl-primary-hover)}.osl-btn--secondary{background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--secondary:hover:not(:disabled){background-color:var(--osl-secondary-hover)}.osl-btn--success{background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--success:hover:not(:disabled){background-color:var(--osl-success-hover)}.osl-btn--danger{background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--danger:hover:not(:disabled){background-color:var(--osl-danger-hover)}.osl-btn--warning{background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--warning:hover:not(:disabled){background-color:var(--osl-warning-hover)}.osl-btn--info{background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn--info:hover:not(:disabled){background-color:var(--osl-info-hover)}.osl-btn--outline-primary{background-color:transparent;border:1.5px solid var(--osl-primary);color:var(--osl-primary)}.osl-btn--outline-primary:hover:not(:disabled){background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--outline-secondary{background-color:transparent;border:1.5px solid var(--osl-secondary);color:var(--osl-secondary)}.osl-btn--outline-secondary:hover:not(:disabled){background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--outline-success{background-color:transparent;border:1.5px solid var(--osl-success);color:var(--osl-success)}.osl-btn--outline-success:hover:not(:disabled){background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--outline-danger{background-color:transparent;border:1.5px solid var(--osl-danger);color:var(--osl-danger)}.osl-btn--outline-danger:hover:not(:disabled){background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--outline-warning{background-color:transparent;border:1.5px solid var(--osl-warning);color:var(--osl-warning)}.osl-btn--outline-warning:hover:not(:disabled){background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--outline-info{background-color:transparent;border:1.5px solid var(--osl-info);color:var(--osl-info)}.osl-btn--outline-info:hover:not(:disabled){background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn__spinner{display:inline-block;width:var(--osl-label-font-size);height:var(--osl-label-font-size);border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:osl-spin .7s linear infinite}@keyframes osl-spin{to{transform:rotate(360deg)}}.osl-btn__label-icon{color:var(--color-white)}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"] }]
|
|
2347
|
-
}], propDecorators: { label: [{
|
|
2348
|
-
type: Input,
|
|
2349
|
-
args: ['label']
|
|
2350
|
-
}], icon: [{
|
|
2351
|
-
type: Input,
|
|
2352
|
-
args: ['icon']
|
|
2353
|
-
}], variant: [{
|
|
2354
|
-
type: Input,
|
|
2355
|
-
args: ['variant']
|
|
2356
|
-
}], size: [{
|
|
2357
|
-
type: Input,
|
|
2358
|
-
args: ['size']
|
|
2359
|
-
}], disabled: [{
|
|
2360
|
-
type: Input,
|
|
2361
|
-
args: ['disabled']
|
|
2362
|
-
}], loading: [{
|
|
2363
|
-
type: Input,
|
|
2364
|
-
args: ['loading']
|
|
2365
|
-
}], type: [{
|
|
2366
|
-
type: Input,
|
|
2367
|
-
args: ['type']
|
|
2368
|
-
}], fullWidth: [{
|
|
2369
|
-
type: Input,
|
|
2370
|
-
args: ['fullWidth']
|
|
2371
|
-
}], clickEv: [{
|
|
2372
|
-
type: Output
|
|
2373
|
-
}] } });
|
|
2374
|
-
|
|
2375
|
-
class DynamicForm {
|
|
2376
|
-
cdr;
|
|
2377
|
-
elements = [];
|
|
2378
|
-
_model;
|
|
2379
|
-
set model(val) {
|
|
2380
|
-
this._model = val;
|
|
2381
|
-
}
|
|
2382
|
-
get model() {
|
|
2383
|
-
return this._model;
|
|
2384
|
-
}
|
|
2385
|
-
skeletonLoading = false;
|
|
2386
|
-
skeletonTheme = 'light';
|
|
2387
|
-
modelChange = new EventEmitter();
|
|
2388
|
-
datasourceCache = inject(DatasourceCacheService);
|
|
2389
|
-
constructor(cdr) {
|
|
2390
|
-
this.cdr = cdr;
|
|
2391
|
-
}
|
|
2392
|
-
ngOnInit() {
|
|
2393
|
-
this.loadApiDatasources();
|
|
2394
|
-
}
|
|
2395
|
-
ngOnChanges(changes) {
|
|
2396
|
-
if (changes['elements'] || changes['model']) {
|
|
2397
|
-
this.loadApiDatasources();
|
|
2398
|
-
}
|
|
2399
|
-
}
|
|
2400
|
-
loadApiDatasources() {
|
|
2401
|
-
this._loadForList(this.elements);
|
|
2402
|
-
}
|
|
2403
|
-
async _loadForList(list) {
|
|
2404
|
-
for (const elem of list) {
|
|
2405
|
-
if (elem.elementType === 'fieldset' && elem.rows?.length) {
|
|
2406
|
-
this._loadForList(elem.rows);
|
|
2407
|
-
}
|
|
2408
|
-
else if (elem.apiService && elem.apiMethod && (!elem.searchType || elem.searchType == 'Local')) {
|
|
2409
|
-
if (elem.dependsOn?.length) {
|
|
2410
|
-
const allReady = elem.dependsOn.every(k => this.model?.[k] != null);
|
|
2411
|
-
if (!allReady)
|
|
2412
|
-
continue;
|
|
2413
|
-
if (elem.datasource?.length)
|
|
2414
|
-
continue;
|
|
2415
|
-
}
|
|
2416
|
-
elem.loadingIf = () => true;
|
|
2417
|
-
const data = await this.datasourceCache.load(elem.apiService, elem.apiMethod, elem.apiBody ? elem.apiBody(this.model) : null);
|
|
2418
|
-
elem.loadingIf = () => false;
|
|
2419
|
-
this.cdr.markForCheck();
|
|
2420
|
-
if (data && data.length > 0) {
|
|
2421
|
-
elem.datasource = data;
|
|
2422
|
-
}
|
|
2423
|
-
}
|
|
2424
|
-
}
|
|
2425
|
-
}
|
|
2426
|
-
onModelChange(event, key) {
|
|
2427
|
-
this.model[key] = event;
|
|
2428
|
-
this.modelChange.emit(this.model);
|
|
2429
|
-
}
|
|
2430
|
-
onSelectChange(elem, value) {
|
|
2431
|
-
if (!elem.change)
|
|
2432
|
-
return;
|
|
2433
|
-
let selectedObj = undefined;
|
|
2434
|
-
if (elem.datasource) {
|
|
2435
|
-
if (Array.isArray(value)) {
|
|
2436
|
-
selectedObj = value.map(v => elem.datasource.find(item => (elem.valueField ? item[elem.valueField] : item) === v) ?? null);
|
|
2437
|
-
}
|
|
2438
|
-
else if (value !== null && value !== undefined) {
|
|
2439
|
-
selectedObj = elem.datasource.find(item => (elem.valueField ? item[elem.valueField] : item) === (isNaN(Number(value)) ? value : Number(value))) ?? null;
|
|
2440
|
-
}
|
|
2441
|
-
else {
|
|
2442
|
-
selectedObj = null;
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
|
-
elem.change(this.model, undefined, selectedObj);
|
|
2446
|
-
}
|
|
2447
|
-
onFieldChange(elem, value) {
|
|
2448
|
-
this.model[elem.key] = value;
|
|
2449
|
-
this.modelChange.emit(this.model);
|
|
2450
|
-
if (elem.change)
|
|
2451
|
-
this.onSelectChange(elem, value);
|
|
2452
|
-
this._refreshDependents(elem.key);
|
|
2453
|
-
}
|
|
2454
|
-
async _refreshDependents(changedKey) {
|
|
2455
|
-
const dependents = this._flatElements().filter(e => e.dependsOn?.includes(changedKey));
|
|
2456
|
-
for (const dep of dependents) {
|
|
2457
|
-
let valueCleared = false;
|
|
2458
|
-
// If any parent dependency is now null, clear field + datasource without API call
|
|
2459
|
-
const anyDepNull = dep.dependsOn.some(k => this.model[k] == null);
|
|
2460
|
-
if (anyDepNull) {
|
|
2461
|
-
if (this.model[dep.key] != null) {
|
|
2462
|
-
this.model[dep.key] = null;
|
|
2463
|
-
valueCleared = true;
|
|
2464
|
-
}
|
|
2465
|
-
dep.datasource = [];
|
|
2466
|
-
this.cdr.markForCheck();
|
|
2467
|
-
if (valueCleared)
|
|
2468
|
-
await this._refreshDependents(dep.key);
|
|
2469
|
-
continue;
|
|
2470
|
-
}
|
|
2471
|
-
const body = dep.apiBody ? dep.apiBody(this.model) : undefined;
|
|
2472
|
-
if (dep.searchType !== 'Api' && dep.apiService && dep.apiMethod) {
|
|
2473
|
-
dep.loadingIf = () => true;
|
|
2474
|
-
this.cdr.markForCheck();
|
|
2475
|
-
try {
|
|
2476
|
-
const res = await dep.apiService[dep.apiMethod](body);
|
|
2477
|
-
dep.datasource = Array.isArray(res) ? res : (res?.result ?? []);
|
|
2478
|
-
}
|
|
2479
|
-
finally {
|
|
2480
|
-
dep.loadingIf = () => false;
|
|
2481
|
-
}
|
|
2482
|
-
const cur = this.model[dep.key];
|
|
2483
|
-
if (cur != null) {
|
|
2484
|
-
const exists = dep.datasource.some(item => (dep.valueField ? item[dep.valueField] : item) === cur);
|
|
2485
|
-
if (!exists) {
|
|
2486
|
-
this.model[dep.key] = null;
|
|
2487
|
-
valueCleared = true;
|
|
2488
|
-
}
|
|
2489
|
-
}
|
|
2490
|
-
}
|
|
2491
|
-
else if (dep.searchType === 'Api') {
|
|
2492
|
-
if (this.model[dep.key] != null) {
|
|
2493
|
-
this.model[dep.key] = null;
|
|
2494
|
-
valueCleared = true;
|
|
2495
|
-
}
|
|
2496
|
-
}
|
|
2497
|
-
this.cdr.markForCheck();
|
|
2498
|
-
if (valueCleared)
|
|
2499
|
-
await this._refreshDependents(dep.key);
|
|
2500
|
-
}
|
|
2501
|
-
}
|
|
2502
|
-
_flatElements(list = this.elements) {
|
|
2503
|
-
return list.flatMap(e => e.rows?.length ? [e, ...this._flatElements(e.rows)] : [e]);
|
|
2504
|
-
}
|
|
2505
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2506
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DynamicForm, isStandalone: false, selector: "osl-dynamic-form", inputs: { elements: "elements", model: "model", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { modelChange: "modelChange" }, usesOnChanges: true, ngImport: i0, template: "@if(elements && elements.length > 0) {\n <div class=\"row align-items-center w-100\">\n @for(elem of elements; track elem) {\n @if(!(elem.hideIf ? elem.hideIf(model) : elem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: elem }\"></ng-container>\n }\n }\n </div>\n}\n\n<ng-template #formField let-elem>\n @if(elem.hideIf ? !elem.hideIf(model) : true) {\n @switch (elem.elementType) {\n\n @case (\"textbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-input\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [type]=\"elem.inputType || 'text'\"\n [placeholder]=\"elem.placeholder || ''\"\n [mask]=\"elem.mask || ''\"\n [min]=\"elem.min ?? ''\"\n [max]=\"elem.max ?? ''\"\n [minLength]=\"elem.minLength ?? null\"\n [maxLength]=\"elem.maxLength ?? null\"\n [prefixIcon]=\"elem.prefixIcon || ''\"\n [suffixIcon]=\"elem.suffixIcon || ''\"\n [onlyChars]=\"!!elem.onlyChars\"\n [decimalPortion]=\"elem.decimalPortion ?? null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n [isCapitalize]=\"elem.isCapitalize\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-textarea\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [rows]=\"elem.textareaRows || 3\"\n [placeholder]=\"elem.placeholder || ''\"\n [maxLength]=\"elem.maxLength ?? null\"\n [minLength]=\"elem.minLength ?? null\"\n [characterCounter]=\"!!elem.characterCounter\"\n [resize]=\"elem.resize || 'none'\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-select\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.selectPlaceholder || 'Select...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n [clearable]=\"!!elem.clearable\"\n (changeEv)=\"elem.change ? onSelectChange(elem, $event) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-radio\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [inline]=\"!!elem.inline\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [labelPosition]=\"elem.labelPosition || 'after'\"\n [trueLabel]=\"elem.trueLabel || ''\"\n [falseLabel]=\"elem.falseLabel || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.autocompletePlaceholder || 'Type to search...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n (changeEv)=\"onFieldChange(elem, $event)\"\n [(model)]=\"model[elem.key]\"\n [methodName]=\"elem.apiMethod\"\n [service]=\"elem.apiService\"\n [object]=\"model[elem.objectName]\"\n [searchType]=\"elem.searchType\"\n [configMethodName]=\"elem.apiConfigMethod\"\n [isLister]=\"elem.isListerAutocomplete\"\n [apiBody]=\"elem.apiBody\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-file-upload\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [accept]=\"elem.accept || ''\"\n [multiple]=\"!!elem.multiple\"\n [maxSize]=\"elem.maxFileSize || 0\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDateIf ? elem.minDateIf(model) : elem.minDate || ''\"\n [maxDate]=\"elem.maxDateIf ? elem.maxDateIf(model) : elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-checkbox\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [indeterminate]=\"!!elem.indeterminate\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-button\n [label]=\"elem.label\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n variant=\"secondary\"\n (clickEv)=\"elem.change ? elem.change(model) : null\"\n ></osl-button>\n </div>\n }\n\n @case (\"fieldset\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <fieldset class=\"osl-fieldset\">\n @if(elem.label) {\n <legend class=\"osl-fieldset-legend\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n <span class=\"osl-fieldset-legend__text\">{{ elem.label }}</span>\n </legend>\n }\n <div class=\"row w-100 osl-fieldset-body\">\n @for(innerElem of elem.rows; track innerElem) {\n @if(!(innerElem.hideIf ? innerElem.hideIf(model) : innerElem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: innerElem }\"></ng-container>\n }\n }\n </div>\n </fieldset>\n </div>\n }\n\n @case (\"templateRef\"){\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <ng-container *ngTemplateOutlet=\"elem.templateRef; context: { $implicit: elem}\"></ng-container>\n </div>\n }\n\n @case (\"spacer\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n </div>\n }\n\n }\n }\n</ng-template>\n", styles: [".osl-fieldset{border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:10px;padding:0 16px 16px;margin:0;background:linear-gradient(135deg,#f9fafb,#fff);box-shadow:0 1px 4px #0000000d;position:relative;transition:box-shadow .2s}.osl-fieldset:focus-within{box-shadow:0 0 0 3px #6366f114,0 2px 8px #0000000f;border-color:var(--osl-primary, #6366f1)}.osl-fieldset-legend{padding:0 6px;margin-left:8px;line-height:1;float:none;width:auto}.osl-fieldset-legend__text{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;background:#fff;padding:2px 10px;border:1.5px solid var(--osl-border-color, #e5e7eb);box-shadow:0 1px 3px #6366f11a}.osl-fieldset-body{margin-top:4px}\n"], dependencies: [{ kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }, { kind: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon", "skeletonLoading", "skeletonTheme", "onlyChars", "isCapitalize", "decimalPortion"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "searchType", "methodName", "configMethodName", "service", "object", "skeletonLoading", "skeletonTheme", "isLister", "apiBody"], outputs: ["datasourceChange", "modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }] });
|
|
2507
|
-
}
|
|
2508
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, decorators: [{
|
|
2509
|
-
type: Component,
|
|
2510
|
-
args: [{ selector: 'osl-dynamic-form', standalone: false, template: "@if(elements && elements.length > 0) {\n <div class=\"row align-items-center w-100\">\n @for(elem of elements; track elem) {\n @if(!(elem.hideIf ? elem.hideIf(model) : elem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: elem }\"></ng-container>\n }\n }\n </div>\n}\n\n<ng-template #formField let-elem>\n @if(elem.hideIf ? !elem.hideIf(model) : true) {\n @switch (elem.elementType) {\n\n @case (\"textbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-input\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [type]=\"elem.inputType || 'text'\"\n [placeholder]=\"elem.placeholder || ''\"\n [mask]=\"elem.mask || ''\"\n [min]=\"elem.min ?? ''\"\n [max]=\"elem.max ?? ''\"\n [minLength]=\"elem.minLength ?? null\"\n [maxLength]=\"elem.maxLength ?? null\"\n [prefixIcon]=\"elem.prefixIcon || ''\"\n [suffixIcon]=\"elem.suffixIcon || ''\"\n [onlyChars]=\"!!elem.onlyChars\"\n [decimalPortion]=\"elem.decimalPortion ?? null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n [isCapitalize]=\"elem.isCapitalize\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-textarea\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [rows]=\"elem.textareaRows || 3\"\n [placeholder]=\"elem.placeholder || ''\"\n [maxLength]=\"elem.maxLength ?? null\"\n [minLength]=\"elem.minLength ?? null\"\n [characterCounter]=\"!!elem.characterCounter\"\n [resize]=\"elem.resize || 'none'\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-select\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.selectPlaceholder || 'Select...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n [clearable]=\"!!elem.clearable\"\n (changeEv)=\"elem.change ? onSelectChange(elem, $event) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-radio\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [inline]=\"!!elem.inline\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [labelPosition]=\"elem.labelPosition || 'after'\"\n [trueLabel]=\"elem.trueLabel || ''\"\n [falseLabel]=\"elem.falseLabel || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.autocompletePlaceholder || 'Type to search...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n (changeEv)=\"onFieldChange(elem, $event)\"\n [(model)]=\"model[elem.key]\"\n [methodName]=\"elem.apiMethod\"\n [service]=\"elem.apiService\"\n [object]=\"model[elem.objectName]\"\n [searchType]=\"elem.searchType\"\n [configMethodName]=\"elem.apiConfigMethod\"\n [isLister]=\"elem.isListerAutocomplete\"\n [apiBody]=\"elem.apiBody\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-file-upload\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [accept]=\"elem.accept || ''\"\n [multiple]=\"!!elem.multiple\"\n [maxSize]=\"elem.maxFileSize || 0\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDateIf ? elem.minDateIf(model) : elem.minDate || ''\"\n [maxDate]=\"elem.maxDateIf ? elem.maxDateIf(model) : elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-checkbox\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [indeterminate]=\"!!elem.indeterminate\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-button\n [label]=\"elem.label\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n variant=\"secondary\"\n (clickEv)=\"elem.change ? elem.change(model) : null\"\n ></osl-button>\n </div>\n }\n\n @case (\"fieldset\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <fieldset class=\"osl-fieldset\">\n @if(elem.label) {\n <legend class=\"osl-fieldset-legend\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n <span class=\"osl-fieldset-legend__text\">{{ elem.label }}</span>\n </legend>\n }\n <div class=\"row w-100 osl-fieldset-body\">\n @for(innerElem of elem.rows; track innerElem) {\n @if(!(innerElem.hideIf ? innerElem.hideIf(model) : innerElem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: innerElem }\"></ng-container>\n }\n }\n </div>\n </fieldset>\n </div>\n }\n\n @case (\"templateRef\"){\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <ng-container *ngTemplateOutlet=\"elem.templateRef; context: { $implicit: elem}\"></ng-container>\n </div>\n }\n\n @case (\"spacer\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n </div>\n }\n\n }\n }\n</ng-template>\n", styles: [".osl-fieldset{border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:10px;padding:0 16px 16px;margin:0;background:linear-gradient(135deg,#f9fafb,#fff);box-shadow:0 1px 4px #0000000d;position:relative;transition:box-shadow .2s}.osl-fieldset:focus-within{box-shadow:0 0 0 3px #6366f114,0 2px 8px #0000000f;border-color:var(--osl-primary, #6366f1)}.osl-fieldset-legend{padding:0 6px;margin-left:8px;line-height:1;float:none;width:auto}.osl-fieldset-legend__text{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;background:#fff;padding:2px 10px;border:1.5px solid var(--osl-border-color, #e5e7eb);box-shadow:0 1px 3px #6366f11a}.osl-fieldset-body{margin-top:4px}\n"] }]
|
|
2511
|
-
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { elements: [{
|
|
2512
|
-
type: Input,
|
|
2513
|
-
args: ['elements']
|
|
2514
|
-
}], model: [{
|
|
2515
|
-
type: Input,
|
|
2516
|
-
args: ['model']
|
|
2517
|
-
}], skeletonLoading: [{
|
|
2518
|
-
type: Input,
|
|
2519
|
-
args: ['skeletonLoading']
|
|
2520
|
-
}], skeletonTheme: [{
|
|
2521
|
-
type: Input,
|
|
2522
|
-
args: ['skeletonTheme']
|
|
2523
|
-
}], modelChange: [{
|
|
2524
|
-
type: Output
|
|
2525
|
-
}] } });
|
|
2526
|
-
|
|
2527
|
-
// ─── Date Utilities ───────────────────────────────────────────────────────────
|
|
2528
|
-
const MONTH_NAMES_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
2529
|
-
const MONTH_NAMES_FULL = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
|
|
2530
|
-
const DAY_NAMES_SHORT = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
2531
|
-
const DAY_NAMES_FULL = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
2532
|
-
function pad(n) {
|
|
2533
|
-
return String(n).padStart(2, '0');
|
|
2534
|
-
}
|
|
2535
|
-
/** Returns the current date and time. */
|
|
2536
|
-
function now() {
|
|
2537
|
-
return new Date();
|
|
2332
|
+
/** Returns the current date and time. */
|
|
2333
|
+
function now() {
|
|
2334
|
+
return new Date();
|
|
2538
2335
|
}
|
|
2539
2336
|
/** Returns today's date with time set to midnight. */
|
|
2540
2337
|
function today() {
|
|
@@ -2962,6 +2759,284 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2962
2759
|
type: Output
|
|
2963
2760
|
}] } });
|
|
2964
2761
|
|
|
2762
|
+
class OslCheckbox {
|
|
2763
|
+
checkboxEl;
|
|
2764
|
+
label = '';
|
|
2765
|
+
disabled = false;
|
|
2766
|
+
required = false;
|
|
2767
|
+
model = false;
|
|
2768
|
+
indeterminate = false;
|
|
2769
|
+
skeletonLoading = false;
|
|
2770
|
+
skeletonTheme = 'light';
|
|
2771
|
+
modelChange = new EventEmitter();
|
|
2772
|
+
changeEv = new EventEmitter();
|
|
2773
|
+
touched = false;
|
|
2774
|
+
get isInvalid() {
|
|
2775
|
+
return this.touched && this.required && !this.model;
|
|
2776
|
+
}
|
|
2777
|
+
ngOnChanges(changes) {
|
|
2778
|
+
if (changes['indeterminate'] && this.checkboxEl) {
|
|
2779
|
+
this.checkboxEl.nativeElement.indeterminate = this.indeterminate;
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
ngAfterViewInit() {
|
|
2783
|
+
if (this.checkboxEl) {
|
|
2784
|
+
this.checkboxEl.nativeElement.indeterminate = this.indeterminate;
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
onModelChange(event) {
|
|
2788
|
+
this.touched = true;
|
|
2789
|
+
this.model = event;
|
|
2790
|
+
this.modelChange.emit(this.model);
|
|
2791
|
+
this.changeEv.emit(this.model);
|
|
2792
|
+
}
|
|
2793
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2794
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslCheckbox, isStandalone: false, selector: "osl-checkbox", inputs: { label: "label", disabled: "disabled", required: "required", model: "model", indeterminate: "indeterminate", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, viewQueries: [{ propertyName: "checkboxEl", first: true, predicate: ["checkboxEl"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex flex-column\">\r\n\r\n <label class=\"checkbox-wrapper\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\" [class.checkbox-disabled]=\"disabled\" [class.checkbox-invalid]=\"isInvalid\">\r\n <input\r\n #checkboxEl\r\n type=\"checkbox\"\r\n [ngModel]=\"model\"\r\n (ngModelChange)=\"onModelChange($event)\"\r\n [disabled]=\"disabled\"\r\n >\r\n <span class=\"checkbox-label\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </span>\r\n </label>\r\n @if(isInvalid) {\r\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\r\n }\r\n</div>\r\n", styles: [".checkbox-wrapper{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:var(--osl-label-font-size);width:fit-content;max-width:100%}.checkbox-wrapper input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:#333;flex-shrink:0}.checkbox-wrapper .checkbox-label{-webkit-user-select:none;user-select:none;display:flex;align-items:center;overflow:hidden;min-width:0}.checkbox-wrapper.checkbox-disabled{opacity:.6;cursor:not-allowed}.checkbox-wrapper.checkbox-disabled input[type=checkbox]{cursor:not-allowed}.checkbox-wrapper.checkbox-invalid{color:var(--osl-error-color)}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.label-required{flex-shrink:0}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}\n"], dependencies: [{ kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2$2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }] });
|
|
2795
|
+
}
|
|
2796
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslCheckbox, decorators: [{
|
|
2797
|
+
type: Component,
|
|
2798
|
+
args: [{ selector: 'osl-checkbox', standalone: false, template: "<div class=\"d-flex flex-column\">\r\n\r\n <label class=\"checkbox-wrapper\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\" [class.checkbox-disabled]=\"disabled\" [class.checkbox-invalid]=\"isInvalid\">\r\n <input\r\n #checkboxEl\r\n type=\"checkbox\"\r\n [ngModel]=\"model\"\r\n (ngModelChange)=\"onModelChange($event)\"\r\n [disabled]=\"disabled\"\r\n >\r\n <span class=\"checkbox-label\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\r\n <span class=\"label-text\" [title]=\"label\">{{label}}</span><span class=\"txt-clr-red label-required\">{{required?'*':''}}</span>\r\n </span>\r\n </label>\r\n @if(isInvalid) {\r\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\r\n }\r\n</div>\r\n", styles: [".checkbox-wrapper{display:flex;align-items:center;gap:8px;cursor:pointer;font-size:var(--osl-label-font-size);width:fit-content;max-width:100%}.checkbox-wrapper input[type=checkbox]{width:16px;height:16px;cursor:pointer;accent-color:#333;flex-shrink:0}.checkbox-wrapper .checkbox-label{-webkit-user-select:none;user-select:none;display:flex;align-items:center;overflow:hidden;min-width:0}.checkbox-wrapper.checkbox-disabled{opacity:.6;cursor:not-allowed}.checkbox-wrapper.checkbox-disabled input[type=checkbox]{cursor:not-allowed}.checkbox-wrapper.checkbox-invalid{color:var(--osl-error-color)}.label-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}.label-required{flex-shrink:0}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}\n"] }]
|
|
2799
|
+
}], propDecorators: { checkboxEl: [{
|
|
2800
|
+
type: ViewChild,
|
|
2801
|
+
args: ['checkboxEl']
|
|
2802
|
+
}], label: [{
|
|
2803
|
+
type: Input,
|
|
2804
|
+
args: ['label']
|
|
2805
|
+
}], disabled: [{
|
|
2806
|
+
type: Input,
|
|
2807
|
+
args: ['disabled']
|
|
2808
|
+
}], required: [{
|
|
2809
|
+
type: Input,
|
|
2810
|
+
args: ['required']
|
|
2811
|
+
}], model: [{
|
|
2812
|
+
type: Input,
|
|
2813
|
+
args: ['model']
|
|
2814
|
+
}], indeterminate: [{
|
|
2815
|
+
type: Input,
|
|
2816
|
+
args: ['indeterminate']
|
|
2817
|
+
}], skeletonLoading: [{
|
|
2818
|
+
type: Input,
|
|
2819
|
+
args: ['skeletonLoading']
|
|
2820
|
+
}], skeletonTheme: [{
|
|
2821
|
+
type: Input,
|
|
2822
|
+
args: ['skeletonTheme']
|
|
2823
|
+
}], modelChange: [{
|
|
2824
|
+
type: Output
|
|
2825
|
+
}], changeEv: [{
|
|
2826
|
+
type: Output
|
|
2827
|
+
}] } });
|
|
2828
|
+
|
|
2829
|
+
class OslButton {
|
|
2830
|
+
label = 'Button';
|
|
2831
|
+
icon = '';
|
|
2832
|
+
variant = 'primary';
|
|
2833
|
+
size = 'md';
|
|
2834
|
+
disabled = false;
|
|
2835
|
+
loading = false;
|
|
2836
|
+
type = 'button';
|
|
2837
|
+
fullWidth = false;
|
|
2838
|
+
clickEv = new EventEmitter();
|
|
2839
|
+
get classes() {
|
|
2840
|
+
return [
|
|
2841
|
+
'osl-btn',
|
|
2842
|
+
`osl-btn--${this.variant}`,
|
|
2843
|
+
`osl-btn--${this.size}`,
|
|
2844
|
+
this.fullWidth ? 'osl-btn--full' : '',
|
|
2845
|
+
]
|
|
2846
|
+
.filter(Boolean)
|
|
2847
|
+
.join(' ');
|
|
2848
|
+
}
|
|
2849
|
+
onClick() {
|
|
2850
|
+
if (!this.disabled && !this.loading) {
|
|
2851
|
+
this.clickEv.emit();
|
|
2852
|
+
}
|
|
2853
|
+
}
|
|
2854
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslButton, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2855
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslButton, isStandalone: false, selector: "osl-button", inputs: { label: "label", icon: "icon", variant: "variant", size: "size", disabled: "disabled", loading: "loading", type: "type", fullWidth: "fullWidth" }, outputs: { clickEv: "clickEv" }, ngImport: i0, template: "@if (variant == 'icon' && icon) {\r\n <button class=\"icon-btn\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n } @else {\r\n <mat-icon>{{ icon }}</mat-icon>\r\n }\r\n </button>\r\n} @else {\r\n <button [class]=\"classes\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n }\r\n <span class=\"osl-btn__label\">{{ label }}</span>\r\n @if (icon) {\r\n <span class=\"osl-btn__label-icon\"\r\n ><mat-icon>{{ icon }}</mat-icon></span\r\n >\r\n }\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";.osl-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:var(--osl-border-radius);cursor:pointer;font-size:var(--osl-label-font-size);font-weight:500;line-height:1;transition:background-color .2s ease,border-color .2s ease,opacity .2s ease;white-space:nowrap;outline:none}.osl-btn--sm{height:28px;padding:0 var(--osl-hint-font-size);font-size:var(--osl-hint-font-size)}.osl-btn--sm mat-icon{font-size:var(--osl-hint-font-size)}.osl-btn--md{height:36px;padding:0 18px;font-size:var(--osl-label-font-size)}.osl-btn--lg{height:44px;padding:0 24px;font-size:16px}.osl-btn--full{width:100%}.osl-btn:disabled{opacity:var(--osl-disabled-opacity);cursor:not-allowed}.osl-btn--primary{background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--primary:hover:not(:disabled){background-color:var(--osl-primary-hover)}.osl-btn--secondary{background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--secondary:hover:not(:disabled){background-color:var(--osl-secondary-hover)}.osl-btn--success{background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--success:hover:not(:disabled){background-color:var(--osl-success-hover)}.osl-btn--danger{background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--danger:hover:not(:disabled){background-color:var(--osl-danger-hover)}.osl-btn--warning{background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--warning:hover:not(:disabled){background-color:var(--osl-warning-hover)}.osl-btn--info{background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn--info:hover:not(:disabled){background-color:var(--osl-info-hover)}.osl-btn--outline-primary{background-color:transparent;border:1.5px solid var(--osl-primary);color:var(--osl-primary)}.osl-btn--outline-primary:hover:not(:disabled){background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--outline-secondary{background-color:transparent;border:1.5px solid var(--osl-secondary);color:var(--osl-secondary)}.osl-btn--outline-secondary:hover:not(:disabled){background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--outline-success{background-color:transparent;border:1.5px solid var(--osl-success);color:var(--osl-success)}.osl-btn--outline-success:hover:not(:disabled){background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--outline-danger{background-color:transparent;border:1.5px solid var(--osl-danger);color:var(--osl-danger)}.osl-btn--outline-danger:hover:not(:disabled){background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--outline-warning{background-color:transparent;border:1.5px solid var(--osl-warning);color:var(--osl-warning)}.osl-btn--outline-warning:hover:not(:disabled){background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--outline-info{background-color:transparent;border:1.5px solid var(--osl-info);color:var(--osl-info)}.osl-btn--outline-info:hover:not(:disabled){background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn__spinner{display:inline-block;width:var(--osl-label-font-size);height:var(--osl-label-font-size);border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:osl-spin .7s linear infinite}@keyframes osl-spin{to{transform:rotate(360deg)}}.osl-btn__label-icon{color:var(--color-white)}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
2856
|
+
}
|
|
2857
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslButton, decorators: [{
|
|
2858
|
+
type: Component,
|
|
2859
|
+
args: [{ selector: 'osl-button', standalone: false, template: "@if (variant == 'icon' && icon) {\r\n <button class=\"icon-btn\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n } @else {\r\n <mat-icon>{{ icon }}</mat-icon>\r\n }\r\n </button>\r\n} @else {\r\n <button [class]=\"classes\" [type]=\"type\" [disabled]=\"disabled || loading\" (click)=\"onClick()\">\r\n @if (loading) {\r\n <span class=\"osl-btn__spinner\"></span>\r\n }\r\n <span class=\"osl-btn__label\">{{ label }}</span>\r\n @if (icon) {\r\n <span class=\"osl-btn__label-icon\"\r\n ><mat-icon>{{ icon }}</mat-icon></span\r\n >\r\n }\r\n </button>\r\n}\r\n", styles: ["@charset \"UTF-8\";.osl-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:none;border-radius:var(--osl-border-radius);cursor:pointer;font-size:var(--osl-label-font-size);font-weight:500;line-height:1;transition:background-color .2s ease,border-color .2s ease,opacity .2s ease;white-space:nowrap;outline:none}.osl-btn--sm{height:28px;padding:0 var(--osl-hint-font-size);font-size:var(--osl-hint-font-size)}.osl-btn--sm mat-icon{font-size:var(--osl-hint-font-size)}.osl-btn--md{height:36px;padding:0 18px;font-size:var(--osl-label-font-size)}.osl-btn--lg{height:44px;padding:0 24px;font-size:16px}.osl-btn--full{width:100%}.osl-btn:disabled{opacity:var(--osl-disabled-opacity);cursor:not-allowed}.osl-btn--primary{background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--primary:hover:not(:disabled){background-color:var(--osl-primary-hover)}.osl-btn--secondary{background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--secondary:hover:not(:disabled){background-color:var(--osl-secondary-hover)}.osl-btn--success{background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--success:hover:not(:disabled){background-color:var(--osl-success-hover)}.osl-btn--danger{background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--danger:hover:not(:disabled){background-color:var(--osl-danger-hover)}.osl-btn--warning{background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--warning:hover:not(:disabled){background-color:var(--osl-warning-hover)}.osl-btn--info{background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn--info:hover:not(:disabled){background-color:var(--osl-info-hover)}.osl-btn--outline-primary{background-color:transparent;border:1.5px solid var(--osl-primary);color:var(--osl-primary)}.osl-btn--outline-primary:hover:not(:disabled){background-color:var(--osl-primary);color:var(--osl-primary-text)}.osl-btn--outline-secondary{background-color:transparent;border:1.5px solid var(--osl-secondary);color:var(--osl-secondary)}.osl-btn--outline-secondary:hover:not(:disabled){background-color:var(--osl-secondary);color:var(--osl-secondary-text)}.osl-btn--outline-success{background-color:transparent;border:1.5px solid var(--osl-success);color:var(--osl-success)}.osl-btn--outline-success:hover:not(:disabled){background-color:var(--osl-success);color:var(--osl-success-text)}.osl-btn--outline-danger{background-color:transparent;border:1.5px solid var(--osl-danger);color:var(--osl-danger)}.osl-btn--outline-danger:hover:not(:disabled){background-color:var(--osl-danger);color:var(--osl-danger-text)}.osl-btn--outline-warning{background-color:transparent;border:1.5px solid var(--osl-warning);color:var(--osl-warning)}.osl-btn--outline-warning:hover:not(:disabled){background-color:var(--osl-warning);color:var(--osl-warning-text)}.osl-btn--outline-info{background-color:transparent;border:1.5px solid var(--osl-info);color:var(--osl-info)}.osl-btn--outline-info:hover:not(:disabled){background-color:var(--osl-info);color:var(--osl-info-text)}.osl-btn__spinner{display:inline-block;width:var(--osl-label-font-size);height:var(--osl-label-font-size);border:2px solid rgba(255,255,255,.4);border-top-color:#fff;border-radius:50%;animation:osl-spin .7s linear infinite}@keyframes osl-spin{to{transform:rotate(360deg)}}.osl-btn__label-icon{color:var(--color-white)}.icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"] }]
|
|
2860
|
+
}], propDecorators: { label: [{
|
|
2861
|
+
type: Input,
|
|
2862
|
+
args: ['label']
|
|
2863
|
+
}], icon: [{
|
|
2864
|
+
type: Input,
|
|
2865
|
+
args: ['icon']
|
|
2866
|
+
}], variant: [{
|
|
2867
|
+
type: Input,
|
|
2868
|
+
args: ['variant']
|
|
2869
|
+
}], size: [{
|
|
2870
|
+
type: Input,
|
|
2871
|
+
args: ['size']
|
|
2872
|
+
}], disabled: [{
|
|
2873
|
+
type: Input,
|
|
2874
|
+
args: ['disabled']
|
|
2875
|
+
}], loading: [{
|
|
2876
|
+
type: Input,
|
|
2877
|
+
args: ['loading']
|
|
2878
|
+
}], type: [{
|
|
2879
|
+
type: Input,
|
|
2880
|
+
args: ['type']
|
|
2881
|
+
}], fullWidth: [{
|
|
2882
|
+
type: Input,
|
|
2883
|
+
args: ['fullWidth']
|
|
2884
|
+
}], clickEv: [{
|
|
2885
|
+
type: Output
|
|
2886
|
+
}] } });
|
|
2887
|
+
|
|
2888
|
+
class DynamicForm {
|
|
2889
|
+
cdr;
|
|
2890
|
+
elements = [];
|
|
2891
|
+
_model;
|
|
2892
|
+
set model(val) {
|
|
2893
|
+
this._model = val;
|
|
2894
|
+
}
|
|
2895
|
+
get model() {
|
|
2896
|
+
return this._model;
|
|
2897
|
+
}
|
|
2898
|
+
skeletonLoading = false;
|
|
2899
|
+
skeletonTheme = 'light';
|
|
2900
|
+
modelChange = new EventEmitter();
|
|
2901
|
+
datasourceCache = inject(DatasourceCacheService);
|
|
2902
|
+
constructor(cdr) {
|
|
2903
|
+
this.cdr = cdr;
|
|
2904
|
+
}
|
|
2905
|
+
ngOnInit() {
|
|
2906
|
+
this.loadApiDatasources();
|
|
2907
|
+
}
|
|
2908
|
+
ngOnChanges(changes) {
|
|
2909
|
+
if (changes['elements'] || changes['model']) {
|
|
2910
|
+
this.loadApiDatasources();
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
loadApiDatasources() {
|
|
2914
|
+
this._loadForList(this.elements);
|
|
2915
|
+
}
|
|
2916
|
+
async _loadForList(list) {
|
|
2917
|
+
for (const elem of list) {
|
|
2918
|
+
if (elem.elementType === 'fieldset' && elem.rows?.length) {
|
|
2919
|
+
this._loadForList(elem.rows);
|
|
2920
|
+
}
|
|
2921
|
+
else if (elem.apiService && elem.apiMethod && (!elem.searchType || elem.searchType == 'Local')) {
|
|
2922
|
+
if (elem.dependsOn?.length) {
|
|
2923
|
+
const allReady = elem.dependsOn.every(k => this.model?.[k] != null);
|
|
2924
|
+
if (!allReady)
|
|
2925
|
+
continue;
|
|
2926
|
+
if (elem.datasource?.length)
|
|
2927
|
+
continue;
|
|
2928
|
+
}
|
|
2929
|
+
elem.loadingIf = () => true;
|
|
2930
|
+
const data = await this.datasourceCache.load(elem.apiService, elem.apiMethod, elem.apiBody ? elem.apiBody(this.model) : null);
|
|
2931
|
+
elem.loadingIf = () => false;
|
|
2932
|
+
this.cdr.markForCheck();
|
|
2933
|
+
if (data && data.length > 0) {
|
|
2934
|
+
elem.datasource = data;
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
onModelChange(event, key) {
|
|
2940
|
+
this.model[key] = event;
|
|
2941
|
+
this.modelChange.emit(this.model);
|
|
2942
|
+
}
|
|
2943
|
+
onSelectChange(elem, value) {
|
|
2944
|
+
if (!elem.change)
|
|
2945
|
+
return;
|
|
2946
|
+
let selectedObj = undefined;
|
|
2947
|
+
if (elem.datasource) {
|
|
2948
|
+
if (Array.isArray(value)) {
|
|
2949
|
+
selectedObj = value.map(v => elem.datasource.find(item => (elem.valueField ? item[elem.valueField] : item) === v) ?? null);
|
|
2950
|
+
}
|
|
2951
|
+
else if (value !== null && value !== undefined) {
|
|
2952
|
+
selectedObj = elem.datasource.find(item => (elem.valueField ? item[elem.valueField] : item) === (isNaN(Number(value)) ? value : Number(value))) ?? null;
|
|
2953
|
+
}
|
|
2954
|
+
else {
|
|
2955
|
+
selectedObj = null;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
elem.change(this.model, undefined, selectedObj);
|
|
2959
|
+
}
|
|
2960
|
+
onFieldChange(elem, value) {
|
|
2961
|
+
this.model[elem.key] = value;
|
|
2962
|
+
this.modelChange.emit(this.model);
|
|
2963
|
+
if (elem.change)
|
|
2964
|
+
this.onSelectChange(elem, value);
|
|
2965
|
+
this._refreshDependents(elem.key);
|
|
2966
|
+
}
|
|
2967
|
+
async _refreshDependents(changedKey) {
|
|
2968
|
+
const dependents = this._flatElements().filter(e => e.dependsOn?.includes(changedKey));
|
|
2969
|
+
for (const dep of dependents) {
|
|
2970
|
+
let valueCleared = false;
|
|
2971
|
+
// If any parent dependency is now null, clear field + datasource without API call
|
|
2972
|
+
const anyDepNull = dep.dependsOn.some(k => this.model[k] == null);
|
|
2973
|
+
if (anyDepNull) {
|
|
2974
|
+
if (this.model[dep.key] != null) {
|
|
2975
|
+
this.model[dep.key] = null;
|
|
2976
|
+
valueCleared = true;
|
|
2977
|
+
}
|
|
2978
|
+
dep.datasource = [];
|
|
2979
|
+
this.cdr.markForCheck();
|
|
2980
|
+
if (valueCleared)
|
|
2981
|
+
await this._refreshDependents(dep.key);
|
|
2982
|
+
continue;
|
|
2983
|
+
}
|
|
2984
|
+
const body = dep.apiBody ? dep.apiBody(this.model) : undefined;
|
|
2985
|
+
if (dep.searchType !== 'Api' && dep.apiService && dep.apiMethod) {
|
|
2986
|
+
dep.loadingIf = () => true;
|
|
2987
|
+
this.cdr.markForCheck();
|
|
2988
|
+
try {
|
|
2989
|
+
const res = await dep.apiService[dep.apiMethod](body);
|
|
2990
|
+
dep.datasource = Array.isArray(res) ? res : (res?.result ?? []);
|
|
2991
|
+
}
|
|
2992
|
+
finally {
|
|
2993
|
+
dep.loadingIf = () => false;
|
|
2994
|
+
}
|
|
2995
|
+
const cur = this.model[dep.key];
|
|
2996
|
+
if (cur != null) {
|
|
2997
|
+
const exists = dep.datasource.some(item => (dep.valueField ? item[dep.valueField] : item) === cur);
|
|
2998
|
+
if (!exists) {
|
|
2999
|
+
this.model[dep.key] = null;
|
|
3000
|
+
valueCleared = true;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
else if (dep.searchType === 'Api') {
|
|
3005
|
+
if (this.model[dep.key] != null) {
|
|
3006
|
+
this.model[dep.key] = null;
|
|
3007
|
+
valueCleared = true;
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
this.cdr.markForCheck();
|
|
3011
|
+
if (valueCleared)
|
|
3012
|
+
await this._refreshDependents(dep.key);
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
_flatElements(list = this.elements) {
|
|
3016
|
+
return list.flatMap(e => e.rows?.length ? [e, ...this._flatElements(e.rows)] : [e]);
|
|
3017
|
+
}
|
|
3018
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
3019
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DynamicForm, isStandalone: false, selector: "osl-dynamic-form", inputs: { elements: "elements", model: "model", skeletonLoading: "skeletonLoading", skeletonTheme: "skeletonTheme" }, outputs: { modelChange: "modelChange" }, usesOnChanges: true, ngImport: i0, template: "@if(elements && elements.length > 0) {\n <div class=\"row align-items-center w-100\">\n @for(elem of elements; track elem) {\n @if(!(elem.hideIf ? elem.hideIf(model) : elem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: elem }\"></ng-container>\n }\n }\n </div>\n}\n\n<ng-template #formField let-elem>\n @if(elem.hideIf ? !elem.hideIf(model) : true) {\n @switch (elem.elementType) {\n\n @case (\"textbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-input\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [type]=\"elem.inputType || 'text'\"\n [placeholder]=\"elem.placeholder || ''\"\n [mask]=\"elem.mask || ''\"\n [min]=\"elem.min ?? ''\"\n [max]=\"elem.max ?? ''\"\n [minLength]=\"elem.minLength ?? null\"\n [maxLength]=\"elem.maxLength ?? null\"\n [prefixIcon]=\"elem.prefixIcon || ''\"\n [suffixIcon]=\"elem.suffixIcon || ''\"\n [onlyChars]=\"!!elem.onlyChars\"\n [decimalPortion]=\"elem.decimalPortion ?? null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n [isCapitalize]=\"elem.isCapitalize\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-textarea\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [rows]=\"elem.textareaRows || 3\"\n [placeholder]=\"elem.placeholder || ''\"\n [maxLength]=\"elem.maxLength ?? null\"\n [minLength]=\"elem.minLength ?? null\"\n [characterCounter]=\"!!elem.characterCounter\"\n [resize]=\"elem.resize || 'none'\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-select\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.selectPlaceholder || 'Select...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n [clearable]=\"!!elem.clearable\"\n (changeEv)=\"elem.change ? onSelectChange(elem, $event) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-radio\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [inline]=\"!!elem.inline\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [labelPosition]=\"elem.labelPosition || 'after'\"\n [trueLabel]=\"elem.trueLabel || ''\"\n [falseLabel]=\"elem.falseLabel || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.autocompletePlaceholder || 'Type to search...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n (changeEv)=\"onFieldChange(elem, $event)\"\n [(model)]=\"model[elem.key]\"\n [methodName]=\"elem.apiMethod\"\n [service]=\"elem.apiService\"\n [object]=\"model[elem.objectName]\"\n [searchType]=\"elem.searchType\"\n [configMethodName]=\"elem.apiConfigMethod\"\n [isLister]=\"elem.isListerAutocomplete\"\n [apiBody]=\"elem.apiBody\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-file-upload\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [accept]=\"elem.accept || ''\"\n [multiple]=\"!!elem.multiple\"\n [maxSize]=\"elem.maxFileSize || 0\"\n [fileMode]=\"elem.fileMode || 'raw'\"\n [downloadFn]=\"elem.fileDownloadFn ? elem.fileDownloadFn.bind(null, model) : null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDateIf ? elem.minDateIf(model) : elem.minDate || ''\"\n [maxDate]=\"elem.maxDateIf ? elem.maxDateIf(model) : elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"datetimepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datetimepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDatetime]=\"elem.minDatetimeIf ? elem.minDatetimeIf(model) : elem.minDatetime || ''\"\n [maxDatetime]=\"elem.maxDatetimeIf ? elem.maxDatetimeIf(model) : elem.maxDatetime || ''\"\n [format]=\"elem.datetimepickerFormat || 'YYYY-MM-DDTHH:mm'\"\n [showSeconds]=\"!!elem.datetimepickerShowSeconds\"\n [enableMeridian]=\"!!elem.datetimepickerEnableMeridian\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datetimepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-checkbox\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [indeterminate]=\"!!elem.indeterminate\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-button\n [label]=\"elem.label\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n variant=\"secondary\"\n (clickEv)=\"elem.change ? elem.change(model) : null\"\n ></osl-button>\n </div>\n }\n\n @case (\"fieldset\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <fieldset class=\"osl-fieldset\">\n @if(elem.label) {\n <legend class=\"osl-fieldset-legend\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n <span class=\"osl-fieldset-legend__text\">{{ elem.label }}</span>\n </legend>\n }\n <div class=\"row w-100 osl-fieldset-body\">\n @for(innerElem of elem.rows; track innerElem) {\n @if(!(innerElem.hideIf ? innerElem.hideIf(model) : innerElem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: innerElem }\"></ng-container>\n }\n }\n </div>\n </fieldset>\n </div>\n }\n\n @case (\"templateRef\"){\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <ng-container *ngTemplateOutlet=\"elem.templateRef; context: { $implicit: elem}\"></ng-container>\n </div>\n }\n\n @case (\"spacer\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n </div>\n }\n\n }\n }\n</ng-template>\n", styles: [".osl-fieldset{border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:10px;padding:0 16px 16px;margin:0;background:linear-gradient(135deg,#f9fafb,#fff);box-shadow:0 1px 4px #0000000d;position:relative;transition:box-shadow .2s}.osl-fieldset:focus-within{box-shadow:0 0 0 3px #6366f114,0 2px 8px #0000000f;border-color:var(--osl-primary, #6366f1)}.osl-fieldset-legend{padding:0 6px;margin-left:8px;line-height:1;float:none;width:auto}.osl-fieldset-legend__text{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;background:#fff;padding:2px 10px;border:1.5px solid var(--osl-border-color, #e5e7eb);box-shadow:0 1px 3px #6366f11a}.osl-fieldset-body{margin-top:4px}\n"], dependencies: [{ kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: OslSkeletonDirective, selector: "[oslSkeleton]", inputs: ["oslSkeleton", "oslSkeletonType", "oslSkeletonAnimation", "oslSkeletonTheme", "oslSkeletonColor", "oslSkeletonHighlight", "oslSkeletonRadius", "oslSkeletonRows", "oslSkeletonRowGap", "oslSkeletonZIndex", "oslSkeletonDelay", "oslSkeletonDuration", "oslSkeletonMinHeight", "oslSkeletonForceReread", "oslSkeletonCircleSize", "oslSkeletonListItems", "oslSkeletonTableRows", "oslSkeletonTableCols", "oslSkeletonCardLines", "oslSkeletonBgColor"] }, { kind: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon", "skeletonLoading", "skeletonTheme", "onlyChars", "isCapitalize", "decimalPortion"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "searchType", "methodName", "configMethodName", "service", "object", "skeletonLoading", "skeletonTheme", "isLister", "apiBody"], outputs: ["datasourceChange", "modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize", "skeletonLoading", "skeletonTheme", "fileMode", "downloadFn"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatetimepicker, selector: "osl-datetimepicker", inputs: ["label", "required", "disabled", "model", "placeholder", "minDatetime", "maxDatetime", "format", "displayFormat", "showSeconds", "enableMeridian", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }] });
|
|
3020
|
+
}
|
|
3021
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, decorators: [{
|
|
3022
|
+
type: Component,
|
|
3023
|
+
args: [{ selector: 'osl-dynamic-form', standalone: false, template: "@if(elements && elements.length > 0) {\n <div class=\"row align-items-center w-100\">\n @for(elem of elements; track elem) {\n @if(!(elem.hideIf ? elem.hideIf(model) : elem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: elem }\"></ng-container>\n }\n }\n </div>\n}\n\n<ng-template #formField let-elem>\n @if(elem.hideIf ? !elem.hideIf(model) : true) {\n @switch (elem.elementType) {\n\n @case (\"textbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-input\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [type]=\"elem.inputType || 'text'\"\n [placeholder]=\"elem.placeholder || ''\"\n [mask]=\"elem.mask || ''\"\n [min]=\"elem.min ?? ''\"\n [max]=\"elem.max ?? ''\"\n [minLength]=\"elem.minLength ?? null\"\n [maxLength]=\"elem.maxLength ?? null\"\n [prefixIcon]=\"elem.prefixIcon || ''\"\n [suffixIcon]=\"elem.suffixIcon || ''\"\n [onlyChars]=\"!!elem.onlyChars\"\n [decimalPortion]=\"elem.decimalPortion ?? null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n [isCapitalize]=\"elem.isCapitalize\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-textarea\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [rows]=\"elem.textareaRows || 3\"\n [placeholder]=\"elem.placeholder || ''\"\n [maxLength]=\"elem.maxLength ?? null\"\n [minLength]=\"elem.minLength ?? null\"\n [characterCounter]=\"!!elem.characterCounter\"\n [resize]=\"elem.resize || 'none'\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-select\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.selectPlaceholder || 'Select...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n [clearable]=\"!!elem.clearable\"\n (changeEv)=\"elem.change ? onSelectChange(elem, $event) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-radio\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [inline]=\"!!elem.inline\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [labelPosition]=\"elem.labelPosition || 'after'\"\n [trueLabel]=\"elem.trueLabel || ''\"\n [falseLabel]=\"elem.falseLabel || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [datasource]=\"elem.datasource || []\"\n [displayField]=\"elem.displayField || ''\"\n [valueField]=\"elem.valueField || ''\"\n [placeholder]=\"elem.autocompletePlaceholder || 'Type to search...'\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n (changeEv)=\"onFieldChange(elem, $event)\"\n [(model)]=\"model[elem.key]\"\n [methodName]=\"elem.apiMethod\"\n [service]=\"elem.apiService\"\n [object]=\"model[elem.objectName]\"\n [searchType]=\"elem.searchType\"\n [configMethodName]=\"elem.apiConfigMethod\"\n [isLister]=\"elem.isListerAutocomplete\"\n [apiBody]=\"elem.apiBody\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-file-upload\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [accept]=\"elem.accept || ''\"\n [multiple]=\"!!elem.multiple\"\n [maxSize]=\"elem.maxFileSize || 0\"\n [fileMode]=\"elem.fileMode || 'raw'\"\n [downloadFn]=\"elem.fileDownloadFn ? elem.fileDownloadFn.bind(null, model) : null\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDateIf ? elem.minDateIf(model) : elem.minDate || ''\"\n [maxDate]=\"elem.maxDateIf ? elem.maxDateIf(model) : elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"datetimepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-datetimepicker\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDatetime]=\"elem.minDatetimeIf ? elem.minDatetimeIf(model) : elem.minDatetime || ''\"\n [maxDatetime]=\"elem.maxDatetimeIf ? elem.maxDatetimeIf(model) : elem.maxDatetime || ''\"\n [format]=\"elem.datetimepickerFormat || 'YYYY-MM-DDTHH:mm'\"\n [showSeconds]=\"!!elem.datetimepickerShowSeconds\"\n [enableMeridian]=\"!!elem.datetimepickerEnableMeridian\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-datetimepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-checkbox\n [skeletonLoading]=\"skeletonLoading\"\n [skeletonTheme]=\"skeletonTheme\"\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf(model) : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [indeterminate]=\"!!elem.indeterminate\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [model]=\"model[elem.key]\"\n (modelChange)=\"onModelChange($event, elem.key)\"\n ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n <osl-button\n [label]=\"elem.label\"\n [loading]=\"elem.loadingIf ? elem.loadingIf(model) : false\"\n variant=\"secondary\"\n (clickEv)=\"elem.change ? elem.change(model) : null\"\n ></osl-button>\n </div>\n }\n\n @case (\"fieldset\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <fieldset class=\"osl-fieldset\">\n @if(elem.label) {\n <legend class=\"osl-fieldset-legend\" [oslSkeleton]=\"skeletonLoading\" [oslSkeletonTheme]=\"skeletonTheme\">\n <span class=\"osl-fieldset-legend__text\">{{ elem.label }}</span>\n </legend>\n }\n <div class=\"row w-100 osl-fieldset-body\">\n @for(innerElem of elem.rows; track innerElem) {\n @if(!(innerElem.hideIf ? innerElem.hideIf(model) : innerElem.hide)) {\n <ng-container *ngTemplateOutlet=\"formField; context: { $implicit: innerElem }\"></ng-container>\n }\n }\n </div>\n </fieldset>\n </div>\n }\n\n @case (\"templateRef\"){\n <div [class]=\"'col-md-'+elem.columns+' mt-3'\">\n <ng-container *ngTemplateOutlet=\"elem.templateRef; context: { $implicit: elem}\"></ng-container>\n </div>\n }\n\n @case (\"spacer\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\" [attr.data-field-key]=\"elem.key\">\n </div>\n }\n\n }\n }\n</ng-template>\n", styles: [".osl-fieldset{border:1.5px solid var(--osl-border-color, #e5e7eb);border-radius:10px;padding:0 16px 16px;margin:0;background:linear-gradient(135deg,#f9fafb,#fff);box-shadow:0 1px 4px #0000000d;position:relative;transition:box-shadow .2s}.osl-fieldset:focus-within{box-shadow:0 0 0 3px #6366f114,0 2px 8px #0000000f;border-color:var(--osl-primary, #6366f1)}.osl-fieldset-legend{padding:0 6px;margin-left:8px;line-height:1;float:none;width:auto}.osl-fieldset-legend__text{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;background:#fff;padding:2px 10px;border:1.5px solid var(--osl-border-color, #e5e7eb);box-shadow:0 1px 3px #6366f11a}.osl-fieldset-body{margin-top:4px}\n"] }]
|
|
3024
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { elements: [{
|
|
3025
|
+
type: Input,
|
|
3026
|
+
args: ['elements']
|
|
3027
|
+
}], model: [{
|
|
3028
|
+
type: Input,
|
|
3029
|
+
args: ['model']
|
|
3030
|
+
}], skeletonLoading: [{
|
|
3031
|
+
type: Input,
|
|
3032
|
+
args: ['skeletonLoading']
|
|
3033
|
+
}], skeletonTheme: [{
|
|
3034
|
+
type: Input,
|
|
3035
|
+
args: ['skeletonTheme']
|
|
3036
|
+
}], modelChange: [{
|
|
3037
|
+
type: Output
|
|
3038
|
+
}] } });
|
|
3039
|
+
|
|
2965
3040
|
class OslSetupStateService {
|
|
2966
3041
|
_map = new Map();
|
|
2967
3042
|
save(key, state) {
|
|
@@ -4015,7 +4090,7 @@ class OslFormGrid {
|
|
|
4015
4090
|
elem.change(row, i, selectedObj);
|
|
4016
4091
|
}
|
|
4017
4092
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFormGrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4018
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslFormGrid, isStandalone: false, selector: "osl-form-grid", inputs: { columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", canAdd: "canAdd", canDelete: "canDelete", loading: "loading", tableHeight: "tableHeight", footerColumns: "footerColumns" }, outputs: { datasourceChange: "datasourceChange", rowAdd: "rowAdd", rowDelete: "rowDelete" }, ngImport: i0, template: "<div class=\"osl-fg-wrapper\">\r\n\r\n <div class=\"osl-fg-table-container\" [style.height]=\"tableHeight\">\r\n <table class=\"osl-fg-table\">\r\n\r\n <thead class=\"osl-fg-thead\">\r\n <tr>\r\n <!-- Actions column: + add button in header -->\r\n @if (hasActions) {\r\n <th class=\"osl-fg-th osl-fg-th--actions\">\r\n @if (canAdd) {\r\n <button class=\"osl-grid-icon-btn\" (click)=\"addRow()\" [disabled]=\"loading\" title=\"Add row\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n }\r\n </th>\r\n }\r\n @for (col of columns; track col.key) {\r\n <th class=\"osl-fg-th\" [style.width]=\"col.width\">\r\n {{ col.displayName }}\r\n @if (colRequired(col)) {\r\n <span class=\"osl-fg-th-required\">*</span>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n\r\n @if (loading) {\r\n @for (sk of skeletonRows; track $index) {\r\n <tr class=\"osl-fg-row osl-fg-row--skeleton\">\r\n @if (hasActions) {\r\n <td class=\"osl-fg-td osl-fg-td--actions\">\r\n <div class=\"osl-fg-skeleton osl-fg-skeleton--sm\"></div>\r\n </td>\r\n }\r\n @for (col of columns; track col.key) {\r\n <td class=\"osl-fg-td\"><div class=\"osl-fg-skeleton\"></div></td>\r\n }\r\n </tr>\r\n }\r\n\r\n } @else if (pagedData.length === 0) {\r\n <tr>\r\n <td [attr.colspan]=\"columns.length + (hasActions ? 1 : 0)\" class=\"osl-fg-empty\">\r\n <div class=\"osl-fg-empty-inner\">\r\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\r\n </svg>\r\n <p>No rows yet.{{ canAdd ? ' Use + to get started.' : '' }}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n\r\n } @else {\r\n @for (row of pagedData; track $index; let i = $index) {\r\n <tr class=\"osl-fg-row\">\r\n\r\n <!-- Delete button first -->\r\n @if (hasActions) {\r\n <td class=\"osl-fg-td osl-fg-td--actions\">\r\n @if (canDelete) {\r\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteRow(i)\" title=\"Delete\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n }\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key) {\r\n <td class=\"osl-fg-td\" [style.width]=\"col.width\">\r\n @if (col.formElem) {\r\n <div class=\"osl-fg-cell-form\" [style.width]=\"col.width\">\r\n @switch (col.formElem.elementType) {\r\n\r\n @case ('textbox') {\r\n <osl-input\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [type]=\"col.formElem.inputType || 'text'\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [mask]=\"col.formElem.mask || ''\"\r\n [min]=\"col.formElem.min ?? ''\"\r\n [max]=\"col.formElem.max ?? ''\"\r\n [minLength]=\"col.formElem.minLength ?? null\"\r\n [maxLength]=\"col.formElem.maxLength ?? null\"\r\n [prefixIcon]=\"col.formElem.prefixIcon || ''\"\r\n [suffixIcon]=\"col.formElem.suffixIcon || ''\"\r\n [decimalPortion]=\"col.formElem.decimalPortion ?? null\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-input>\r\n }\r\n\r\n @case ('textarea') {\r\n <osl-textarea\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [rows]=\"col.formElem.textareaRows || 3\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [maxLength]=\"col.formElem.maxLength ?? null\"\r\n [minLength]=\"col.formElem.minLength ?? null\"\r\n [characterCounter]=\"!!col.formElem.characterCounter\"\r\n [resize]=\"col.formElem.resize || 'none'\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-textarea>\r\n }\r\n\r\n @case ('select') {\r\n <osl-select\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [placeholder]=\"col.formElem.selectPlaceholder || col.displayName\"\r\n [loading]=\"isLoading(row, col.formElem)\"\r\n [clearable]=\"!!col.formElem.clearable\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? onSelectChange(col, row, i, $event) : null\">\r\n </osl-select>\r\n }\r\n\r\n @case ('autocomplete') {\r\n <osl-autocomplete\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [placeholder]=\"col.formElem.autocompletePlaceholder || col.displayName\"\r\n [loading]=\"isLoading(row, col.formElem)\"\r\n [searchType]=\"col.formElem.searchType ? col.formElem.searchType : 'Local'\"\r\n [methodName]=\"col.formElem.apiMethod || ''\"\r\n [configMethodName]=\"col.formElem.apiConfigMethod || ''\"\r\n [service]=\"col.formElem.apiService\"\r\n [object]=\"col.formElem.objectName ? row[col.formElem.objectName] : null\"\r\n [isLister]=\"!!col.formElem.isListerAutocomplete\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? onSelectChange(col, row, i, $event) : null\">\r\n </osl-autocomplete>\r\n }\r\n\r\n @case ('radio') {\r\n <osl-radio\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [inline]=\"!!col.formElem.inline\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-radio>\r\n }\r\n\r\n @case ('checkbox') {\r\n <osl-checkbox\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [indeterminate]=\"!!col.formElem.indeterminate\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-checkbox>\r\n }\r\n\r\n @case ('slide-toggle') {\r\n <osl-slide-toggle\r\n [label]=\"''\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [labelPosition]=\"col.formElem.labelPosition || 'after'\"\r\n [trueLabel]=\"col.formElem.trueLabel || ''\"\r\n [falseLabel]=\"col.formElem.falseLabel || ''\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-slide-toggle>\r\n }\r\n\r\n @case ('datepicker') {\r\n <osl-datepicker\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [dateType]=\"col.formElem.dateType || 'date'\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [minDate]=\"col.formElem.minDate || ''\"\r\n [maxDate]=\"col.formElem.maxDate || ''\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-datepicker>\r\n }\r\n\r\n @case ('datetimepicker') {\r\n <osl-datetimepicker\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [minDatetime]=\"col.formElem.minDatetime || ''\"\r\n [maxDatetime]=\"col.formElem.maxDatetime || ''\"\r\n [format]=\"col.formElem.datetimepickerFormat || 'YYYY-MM-DDTHH:mm'\"\r\n [showSeconds]=\"!!col.formElem.datetimepickerShowSeconds\"\r\n [enableMeridian]=\"!!col.formElem.datetimepickerEnableMeridian\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-datetimepicker>\r\n }\r\n\r\n @case ('file-uploader') {\r\n <osl-file-upload\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [accept]=\"col.formElem.accept || ''\"\r\n [multiple]=\"!!col.formElem.multiple\"\r\n [maxSize]=\"col.formElem.maxFileSize || 0\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-file-upload>\r\n }\r\n\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"osl-fg-cell-text\">{{ row[col.key] ?? '--' }}</span>\r\n }\r\n </td>\r\n }\r\n\r\n </tr>\r\n }\r\n }\r\n\r\n </tbody>\r\n\r\n @if (footerColumns && footerColumns.length > 0 && datasource && datasource.length > 0) {\r\n <tfoot class=\"osl-fg-tfoot\">\r\n <tr class=\"osl-fg-footer-row\">\r\n @for (fcol of footerColumns; track $index) {\r\n <td\r\n [class]=\"'osl-fg-footer-td ' + (fcol.class || '')\"\r\n [attr.colspan]=\"fcol.colspan || 1\">\r\n {{ fcol.displayFn ? fcol.displayFn(datasource) : (fcol.display || '') }}\r\n </td>\r\n }\r\n </tr>\r\n </tfoot>\r\n }\r\n\r\n </table>\r\n </div>\r\n\r\n @if (isPaginated) {\r\n <div class=\"osl-fg-pagination\">\r\n\r\n <span class=\"osl-fg-pagination__info\">\r\n @if (loading) {\r\n Loading...\r\n } @else if (_total > 0) {\r\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} rows\r\n } @else {\r\n No rows\r\n }\r\n </span>\r\n\r\n <div class=\"osl-fg-pagination__controls\">\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\">\u00AB</button>\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\">\u2039 Prev</button>\r\n\r\n @for (page of pageNumbers; track $index) {\r\n @if (page === -1) {\r\n <span class=\"osl-fg-page-ellipsis\">\u2026</span>\r\n } @else {\r\n <button\r\n class=\"osl-fg-page-btn osl-fg-page-btn--num\"\r\n [class.osl-fg-page-btn--active]=\"page === currentPage\"\r\n [disabled]=\"loading\"\r\n (click)=\"goToPage(page)\">\r\n {{ page }}\r\n </button>\r\n }\r\n }\r\n\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\">Next \u203A</button>\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\">\u00BB</button>\r\n </div>\r\n\r\n <div class=\"osl-fg-pagination__size\">\r\n <select class=\"osl-fg-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\r\n @for (opt of pageSizeOptions; track opt) {\r\n <option [value]=\"opt\">{{ opt }} per page</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".osl-fg-wrapper{display:flex;flex-direction:column;width:100%;font-size:var(--osl-text-font-size);font-family:inherit;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 8px);overflow:hidden;background:#fff}.osl-fg-table-container{overflow-x:auto;overflow-y:auto;min-height:120px}.osl-fg-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-fg-thead{position:sticky;top:0;z-index:2}.osl-fg-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;text-align:left;border-bottom:2px solid var(--osl-border-color, #e5e7eb);border-right:1px solid var(--osl-border-color, #e5e7eb);white-space:nowrap;vertical-align:middle}.osl-fg-th:last-child{border-right:none}.osl-fg-th--actions{width:44px;min-width:44px;text-align:center;padding:6px}.osl-fg-th-required{color:#ef4444;margin-left:2px;font-size:14px;line-height:1;vertical-align:middle}.osl-fg-row{border-bottom:1px solid #f0f0f0;transition:background .1s}.osl-fg-row:nth-child(odd){background:#f8fafc}.osl-fg-row:nth-child(2n){background:#fff}.osl-fg-row:hover{background:#eef2ff!important}.osl-fg-row:last-child{border-bottom:none}.osl-fg-row--skeleton{pointer-events:none}.osl-fg-td{padding:4px 10px;vertical-align:middle;border-right:1px solid #f0f0f0}.osl-fg-td:last-child{border-right:none}.osl-fg-td--actions{width:44px;min-width:44px;text-align:center;padding:4px 6px}.osl-fg-cell-form{min-width:100px}.osl-fg-cell-form ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none!important}.osl-fg-cell-form ::ng-deep .mat-mdc-form-field,.osl-fg-cell-form ::ng-deep mat-form-field{width:100%}.osl-fg-cell-form ::ng-deep .mat-mdc-text-field-wrapper{padding-top:0}.osl-fg-cell-text{color:#111827;font-size:var(--osl-text-font-size)}.osl-fg-add-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;border-radius:6px;background:var(--osl-primary, #6366f1);color:#fff;cursor:pointer;padding:0;box-shadow:0 1px 4px #6366f159;transition:background .15s,box-shadow .15s,transform .1s}.osl-fg-add-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.osl-fg-add-btn:hover:not(:disabled){background:var(--osl-primary-hover, #4f46e5);box-shadow:0 2px 8px #6366f173;transform:scale(1.05)}.osl-fg-add-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}.osl-fg-delete-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid transparent;border-radius:6px;background:transparent;color:#d1d5db;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s}.osl-fg-delete-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.osl-fg-delete-btn:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}.osl-fg-empty{padding:40px 16px;text-align:center}.osl-fg-empty-inner{display:flex;flex-direction:column;align-items:center;gap:10px;color:#9ca3af}.osl-fg-empty-inner svg{opacity:.4}.osl-fg-empty-inner p{margin:0;font-size:13px}@keyframes osl-fg-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-fg-skeleton{height:36px;border-radius:6px;background:#e5e7eb;animation:osl-fg-pulse 1.4s ease-in-out infinite}.osl-fg-skeleton--sm{height:28px;width:28px;border-radius:4px;margin:0 auto}.osl-fg-tfoot{position:sticky;bottom:0;z-index:2}.osl-fg-footer-td{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;text-align:left;border-top:2px solid var(--osl-border-color, #e5e7eb);border-right:1px solid var(--osl-border-color, #e5e7eb);white-space:nowrap;vertical-align:middle}.osl-fg-footer-td:last-child{border-right:none}.osl-fg-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color, #e5e7eb);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-fg-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-fg-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-fg-pagination__size{display:flex;align-items:center;justify-content:flex-end;min-width:120px}.osl-fg-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 6px);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-fg-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-fg-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-fg-page-btn--nav{font-size:12px;color:#6b7280}.osl-fg-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-fg-page-btn--active{background:var(--osl-primary, #6366f1);border-color:var(--osl-primary, #6366f1);color:#fff;font-weight:600}.osl-fg-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover, #4f46e5);border-color:var(--osl-primary-hover, #4f46e5)}.osl-fg-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-fg-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 6px);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-fg-page-size:focus{border-color:var(--osl-primary, #6366f1)}.osl-fg-page-size:disabled{opacity:.4;cursor:not-allowed}.osl-grid-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.osl-grid-icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.osl-grid-icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.osl-grid-icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"], dependencies: [{ kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon", "skeletonLoading", "skeletonTheme", "onlyChars", "isCapitalize", "decimalPortion"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "searchType", "methodName", "configMethodName", "service", "object", "skeletonLoading", "skeletonTheme", "isLister", "apiBody"], outputs: ["datasourceChange", "modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatetimepicker, selector: "osl-datetimepicker", inputs: ["label", "required", "disabled", "model", "placeholder", "minDatetime", "maxDatetime", "format", "displayFormat", "showSeconds", "enableMeridian", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }] });
|
|
4093
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslFormGrid, isStandalone: false, selector: "osl-form-grid", inputs: { columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", canAdd: "canAdd", canDelete: "canDelete", loading: "loading", tableHeight: "tableHeight", footerColumns: "footerColumns" }, outputs: { datasourceChange: "datasourceChange", rowAdd: "rowAdd", rowDelete: "rowDelete" }, ngImport: i0, template: "<div class=\"osl-fg-wrapper\">\r\n\r\n <div class=\"osl-fg-table-container\" [style.height]=\"tableHeight\">\r\n <table class=\"osl-fg-table\">\r\n\r\n <thead class=\"osl-fg-thead\">\r\n <tr>\r\n <!-- Actions column: + add button in header -->\r\n @if (hasActions) {\r\n <th class=\"osl-fg-th osl-fg-th--actions\">\r\n @if (canAdd) {\r\n <button class=\"osl-grid-icon-btn\" (click)=\"addRow()\" [disabled]=\"loading\" title=\"Add row\">\r\n <mat-icon>add</mat-icon>\r\n </button>\r\n }\r\n </th>\r\n }\r\n @for (col of columns; track col.key) {\r\n <th class=\"osl-fg-th\" [style.width]=\"col.width\">\r\n {{ col.displayName }}\r\n @if (colRequired(col)) {\r\n <span class=\"osl-fg-th-required\">*</span>\r\n }\r\n </th>\r\n }\r\n </tr>\r\n </thead>\r\n\r\n <tbody>\r\n\r\n @if (loading) {\r\n @for (sk of skeletonRows; track $index) {\r\n <tr class=\"osl-fg-row osl-fg-row--skeleton\">\r\n @if (hasActions) {\r\n <td class=\"osl-fg-td osl-fg-td--actions\">\r\n <div class=\"osl-fg-skeleton osl-fg-skeleton--sm\"></div>\r\n </td>\r\n }\r\n @for (col of columns; track col.key) {\r\n <td class=\"osl-fg-td\"><div class=\"osl-fg-skeleton\"></div></td>\r\n }\r\n </tr>\r\n }\r\n\r\n } @else if (pagedData.length === 0) {\r\n <tr>\r\n <td [attr.colspan]=\"columns.length + (hasActions ? 1 : 0)\" class=\"osl-fg-empty\">\r\n <div class=\"osl-fg-empty-inner\">\r\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\r\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\r\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\r\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\r\n </svg>\r\n <p>No rows yet.{{ canAdd ? ' Use + to get started.' : '' }}</p>\r\n </div>\r\n </td>\r\n </tr>\r\n\r\n } @else {\r\n @for (row of pagedData; track $index; let i = $index) {\r\n <tr class=\"osl-fg-row\">\r\n\r\n <!-- Delete button first -->\r\n @if (hasActions) {\r\n <td class=\"osl-fg-td osl-fg-td--actions\">\r\n @if (canDelete) {\r\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteRow(i)\" title=\"Delete\">\r\n <mat-icon>delete_outline</mat-icon>\r\n </button>\r\n }\r\n </td>\r\n }\r\n\r\n @for (col of columns; track col.key) {\r\n <td class=\"osl-fg-td\" [style.width]=\"col.width\">\r\n @if (col.formElem) {\r\n <div class=\"osl-fg-cell-form\" [style.width]=\"col.width\">\r\n @switch (col.formElem.elementType) {\r\n\r\n @case ('textbox') {\r\n <osl-input\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [type]=\"col.formElem.inputType || 'text'\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [mask]=\"col.formElem.mask || ''\"\r\n [min]=\"col.formElem.min ?? ''\"\r\n [max]=\"col.formElem.max ?? ''\"\r\n [minLength]=\"col.formElem.minLength ?? null\"\r\n [maxLength]=\"col.formElem.maxLength ?? null\"\r\n [prefixIcon]=\"col.formElem.prefixIcon || ''\"\r\n [suffixIcon]=\"col.formElem.suffixIcon || ''\"\r\n [decimalPortion]=\"col.formElem.decimalPortion ?? null\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-input>\r\n }\r\n\r\n @case ('textarea') {\r\n <osl-textarea\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [rows]=\"col.formElem.textareaRows || 3\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [maxLength]=\"col.formElem.maxLength ?? null\"\r\n [minLength]=\"col.formElem.minLength ?? null\"\r\n [characterCounter]=\"!!col.formElem.characterCounter\"\r\n [resize]=\"col.formElem.resize || 'none'\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-textarea>\r\n }\r\n\r\n @case ('select') {\r\n <osl-select\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [placeholder]=\"col.formElem.selectPlaceholder || col.displayName\"\r\n [loading]=\"isLoading(row, col.formElem)\"\r\n [clearable]=\"!!col.formElem.clearable\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? onSelectChange(col, row, i, $event) : null\">\r\n </osl-select>\r\n }\r\n\r\n @case ('autocomplete') {\r\n <osl-autocomplete\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [placeholder]=\"col.formElem.autocompletePlaceholder || col.displayName\"\r\n [loading]=\"isLoading(row, col.formElem)\"\r\n [searchType]=\"col.formElem.searchType ? col.formElem.searchType : 'Local'\"\r\n [methodName]=\"col.formElem.apiMethod || ''\"\r\n [configMethodName]=\"col.formElem.apiConfigMethod || ''\"\r\n [service]=\"col.formElem.apiService\"\r\n [object]=\"col.formElem.objectName ? row[col.formElem.objectName] : null\"\r\n [isLister]=\"!!col.formElem.isListerAutocomplete\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? onSelectChange(col, row, i, $event) : null\">\r\n </osl-autocomplete>\r\n }\r\n\r\n @case ('radio') {\r\n <osl-radio\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [datasource]=\"col.formElem.datasource || []\"\r\n [displayField]=\"col.formElem.displayField || ''\"\r\n [valueField]=\"col.formElem.valueField || ''\"\r\n [inline]=\"!!col.formElem.inline\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-radio>\r\n }\r\n\r\n @case ('checkbox') {\r\n <osl-checkbox\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [indeterminate]=\"!!col.formElem.indeterminate\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-checkbox>\r\n }\r\n\r\n @case ('slide-toggle') {\r\n <osl-slide-toggle\r\n [label]=\"''\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [labelPosition]=\"col.formElem.labelPosition || 'after'\"\r\n [trueLabel]=\"col.formElem.trueLabel || ''\"\r\n [falseLabel]=\"col.formElem.falseLabel || ''\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-slide-toggle>\r\n }\r\n\r\n @case ('datepicker') {\r\n <osl-datepicker\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [dateType]=\"col.formElem.dateType || 'date'\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [minDate]=\"col.formElem.minDate || ''\"\r\n [maxDate]=\"col.formElem.maxDate || ''\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-datepicker>\r\n }\r\n\r\n @case ('datetimepicker') {\r\n <osl-datetimepicker\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\r\n [minDatetime]=\"col.formElem.minDatetime || ''\"\r\n [maxDatetime]=\"col.formElem.maxDatetime || ''\"\r\n [format]=\"col.formElem.datetimepickerFormat || 'YYYY-MM-DDTHH:mm'\"\r\n [showSeconds]=\"!!col.formElem.datetimepickerShowSeconds\"\r\n [enableMeridian]=\"!!col.formElem.datetimepickerEnableMeridian\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-datetimepicker>\r\n }\r\n\r\n @case ('file-uploader') {\r\n <osl-file-upload\r\n [label]=\"''\"\r\n [required]=\"false\"\r\n [disabled]=\"isDisabled(col.formElem,row,i)\"\r\n [accept]=\"col.formElem.accept || ''\"\r\n [multiple]=\"!!col.formElem.multiple\"\r\n [maxSize]=\"col.formElem.maxFileSize || 0\"\r\n [model]=\"row[col.key]\"\r\n (modelChange)=\"onCellChange(row, col, $event)\"\r\n (changeEv)=\"col.formElem.change ? col.formElem.change(row,i) : null\">\r\n </osl-file-upload>\r\n }\r\n\r\n }\r\n </div>\r\n } @else {\r\n <span class=\"osl-fg-cell-text\">{{ row[col.key] ?? '--' }}</span>\r\n }\r\n </td>\r\n }\r\n\r\n </tr>\r\n }\r\n }\r\n\r\n </tbody>\r\n\r\n @if (footerColumns && footerColumns.length > 0 && datasource && datasource.length > 0) {\r\n <tfoot class=\"osl-fg-tfoot\">\r\n <tr class=\"osl-fg-footer-row\">\r\n @for (fcol of footerColumns; track $index) {\r\n <td\r\n [class]=\"'osl-fg-footer-td ' + (fcol.class || '')\"\r\n [attr.colspan]=\"fcol.colspan || 1\">\r\n {{ fcol.displayFn ? fcol.displayFn(datasource) : (fcol.display || '') }}\r\n </td>\r\n }\r\n </tr>\r\n </tfoot>\r\n }\r\n\r\n </table>\r\n </div>\r\n\r\n @if (isPaginated) {\r\n <div class=\"osl-fg-pagination\">\r\n\r\n <span class=\"osl-fg-pagination__info\">\r\n @if (loading) {\r\n Loading...\r\n } @else if (_total > 0) {\r\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} rows\r\n } @else {\r\n No rows\r\n }\r\n </span>\r\n\r\n <div class=\"osl-fg-pagination__controls\">\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\">\u00AB</button>\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\">\u2039 Prev</button>\r\n\r\n @for (page of pageNumbers; track $index) {\r\n @if (page === -1) {\r\n <span class=\"osl-fg-page-ellipsis\">\u2026</span>\r\n } @else {\r\n <button\r\n class=\"osl-fg-page-btn osl-fg-page-btn--num\"\r\n [class.osl-fg-page-btn--active]=\"page === currentPage\"\r\n [disabled]=\"loading\"\r\n (click)=\"goToPage(page)\">\r\n {{ page }}\r\n </button>\r\n }\r\n }\r\n\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\">Next \u203A</button>\r\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\">\u00BB</button>\r\n </div>\r\n\r\n <div class=\"osl-fg-pagination__size\">\r\n <select class=\"osl-fg-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\r\n @for (opt of pageSizeOptions; track opt) {\r\n <option [value]=\"opt\">{{ opt }} per page</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".osl-fg-wrapper{display:flex;flex-direction:column;width:100%;font-size:var(--osl-text-font-size);font-family:inherit;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 8px);overflow:hidden;background:#fff}.osl-fg-table-container{overflow-x:auto;overflow-y:auto;min-height:120px}.osl-fg-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-fg-thead{position:sticky;top:0;z-index:2}.osl-fg-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;text-align:left;border-bottom:2px solid var(--osl-border-color, #e5e7eb);border-right:1px solid var(--osl-border-color, #e5e7eb);white-space:nowrap;vertical-align:middle}.osl-fg-th:last-child{border-right:none}.osl-fg-th--actions{width:44px;min-width:44px;text-align:center;padding:6px}.osl-fg-th-required{color:#ef4444;margin-left:2px;font-size:14px;line-height:1;vertical-align:middle}.osl-fg-row{border-bottom:1px solid #f0f0f0;transition:background .1s}.osl-fg-row:nth-child(odd){background:#f8fafc}.osl-fg-row:nth-child(2n){background:#fff}.osl-fg-row:hover{background:#eef2ff!important}.osl-fg-row:last-child{border-bottom:none}.osl-fg-row--skeleton{pointer-events:none}.osl-fg-td{padding:4px 10px;vertical-align:middle;border-right:1px solid #f0f0f0}.osl-fg-td:last-child{border-right:none}.osl-fg-td--actions{width:44px;min-width:44px;text-align:center;padding:4px 6px}.osl-fg-cell-form{min-width:100px}.osl-fg-cell-form ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none!important}.osl-fg-cell-form ::ng-deep .mat-mdc-form-field,.osl-fg-cell-form ::ng-deep mat-form-field{width:100%}.osl-fg-cell-form ::ng-deep .mat-mdc-text-field-wrapper{padding-top:0}.osl-fg-cell-text{color:#111827;font-size:var(--osl-text-font-size)}.osl-fg-add-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border:none;border-radius:6px;background:var(--osl-primary, #6366f1);color:#fff;cursor:pointer;padding:0;box-shadow:0 1px 4px #6366f159;transition:background .15s,box-shadow .15s,transform .1s}.osl-fg-add-btn mat-icon{font-size:18px;width:18px;height:18px;line-height:18px}.osl-fg-add-btn:hover:not(:disabled){background:var(--osl-primary-hover, #4f46e5);box-shadow:0 2px 8px #6366f173;transform:scale(1.05)}.osl-fg-add-btn:disabled{opacity:.4;cursor:not-allowed;transform:none}.osl-fg-delete-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid transparent;border-radius:6px;background:transparent;color:#d1d5db;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s}.osl-fg-delete-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.osl-fg-delete-btn:hover{border-color:#fca5a5;color:#ef4444;background:#fef2f2}.osl-fg-empty{padding:40px 16px;text-align:center}.osl-fg-empty-inner{display:flex;flex-direction:column;align-items:center;gap:10px;color:#9ca3af}.osl-fg-empty-inner svg{opacity:.4}.osl-fg-empty-inner p{margin:0;font-size:13px}@keyframes osl-fg-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-fg-skeleton{height:36px;border-radius:6px;background:#e5e7eb;animation:osl-fg-pulse 1.4s ease-in-out infinite}.osl-fg-skeleton--sm{height:28px;width:28px;border-radius:4px;margin:0 auto}.osl-fg-tfoot{position:sticky;bottom:0;z-index:2}.osl-fg-footer-td{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 12px;text-align:left;border-top:2px solid var(--osl-border-color, #e5e7eb);border-right:1px solid var(--osl-border-color, #e5e7eb);white-space:nowrap;vertical-align:middle}.osl-fg-footer-td:last-child{border-right:none}.osl-fg-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color, #e5e7eb);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-fg-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-fg-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-fg-pagination__size{display:flex;align-items:center;justify-content:flex-end;min-width:120px}.osl-fg-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 6px);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-fg-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-fg-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-fg-page-btn--nav{font-size:12px;color:#6b7280}.osl-fg-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-fg-page-btn--active{background:var(--osl-primary, #6366f1);border-color:var(--osl-primary, #6366f1);color:#fff;font-weight:600}.osl-fg-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover, #4f46e5);border-color:var(--osl-primary-hover, #4f46e5)}.osl-fg-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-fg-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color, #e5e7eb);border-radius:var(--osl-border-radius, 6px);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-fg-page-size:focus{border-color:var(--osl-primary, #6366f1)}.osl-fg-page-size:disabled{opacity:.4;cursor:not-allowed}.osl-grid-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border:1.5px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:transparent;color:#6b7280;cursor:pointer;padding:0;transition:border-color .15s,color .15s,background .15s;margin:0 2px}.osl-grid-icon-btn mat-icon{font-size:16px;width:16px;height:16px;line-height:16px}.osl-grid-icon-btn:hover{border-color:var(--osl-primary);color:var(--osl-primary);background:#6366f10f}.osl-grid-icon-btn--danger:hover{border-color:#ef4444;color:#ef4444;background:#ef44440f}\n"], dependencies: [{ kind: "directive", type: i1$1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1$1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon", "skeletonLoading", "skeletonTheme", "onlyChars", "isCapitalize", "decimalPortion"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "searchType", "methodName", "configMethodName", "service", "object", "skeletonLoading", "skeletonTheme", "isLister", "apiBody"], outputs: ["datasourceChange", "modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize", "skeletonLoading", "skeletonTheme", "fileMode", "downloadFn"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatetimepicker, selector: "osl-datetimepicker", inputs: ["label", "required", "disabled", "model", "placeholder", "minDatetime", "maxDatetime", "format", "displayFormat", "showSeconds", "enableMeridian", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate", "skeletonLoading", "skeletonTheme"], outputs: ["modelChange", "changeEv"] }] });
|
|
4019
4094
|
}
|
|
4020
4095
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFormGrid, decorators: [{
|
|
4021
4096
|
type: Component,
|
|
@@ -7368,5 +7443,5 @@ const unsavedChangesGuard = () => {
|
|
|
7368
7443
|
* Generated bundle index. Do not edit.
|
|
7369
7444
|
*/
|
|
7370
7445
|
|
|
7371
|
-
export { array_util as ArrayUtil, date_util as DateUtil, DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DirtyStateService, DynamicForm, FormStructureModule, Httpbase, number_util as NumberUtil, object_util as ObjectUtil, OslAutocomplete, OslAutocompleteLister, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslDatetimepicker, OslDocumentUploader, OslFileUpload, OslFormGrid, OslGrid, OslMenu, OslMenuTriggerFor, OslRadio, OslReportForm, OslReportGrid, OslSearchbar, OslSelect, OslSetup, OslSkeletonDirective, OslSkeletonModule, OslSkeletonThemeService, OslSlideToggle, OslTooltipDirective, OslUserLog, Oslinput, Osltextarea, storage_util as StorageUtil, string_util as StringUtil, UnsavedChangesDialog, validation_util as ValidationUtil, baseComponent, unsavedChangesGuard };
|
|
7446
|
+
export { array_util as ArrayUtil, date_util as DateUtil, DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DirtyStateService, DynamicForm, ErrorDialog, FormStructureModule, Httpbase, number_util as NumberUtil, object_util as ObjectUtil, OslAutocomplete, OslAutocompleteLister, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslDatetimepicker, OslDocumentUploader, OslFileUpload, OslFormGrid, OslGrid, OslMenu, OslMenuTriggerFor, OslRadio, OslReportForm, OslReportGrid, OslSearchbar, OslSelect, OslSetup, OslSkeletonDirective, OslSkeletonModule, OslSkeletonThemeService, OslSlideToggle, OslTooltipDirective, OslUserLog, Oslinput, Osltextarea, storage_util as StorageUtil, string_util as StringUtil, UnsavedChangesDialog, validation_util as ValidationUtil, baseComponent, unsavedChangesGuard };
|
|
7372
7447
|
//# sourceMappingURL=osl-base-extended.mjs.map
|