osl-base-extended 0.1.11 → 0.1.13

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.
@@ -1,23 +1,23 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, Inject, inject, Injector, Injectable, EventEmitter, Output, Input, HostListener, ViewChild, NgModule } from '@angular/core';
2
+ import { Component, Inject, inject, Injector, Injectable, InjectionToken, EventEmitter, Output, Input, HostListener, ViewChild, NgModule } from '@angular/core';
3
3
  import * as i1 from '@angular/material/dialog';
4
4
  import { MAT_DIALOG_DATA, MatDialogModule, MatDialog } from '@angular/material/dialog';
5
5
  import { MatSnackBar } from '@angular/material/snack-bar';
6
6
  import { Router } from '@angular/router';
7
7
  import * as i1$2 from '@angular/common';
8
- import { NgTemplateOutlet } from '@angular/common';
8
+ import { NgTemplateOutlet, NgComponentOutlet } from '@angular/common';
9
9
  import * as i3 from '@angular/material/button';
10
10
  import { MatIconButton, MatButtonModule } from '@angular/material/button';
11
11
  import * as i2 from '@angular/material/icon';
12
12
  import { MatIconModule } from '@angular/material/icon';
13
13
  import { HttpHeaders, HttpParams, HttpClient } from '@angular/common/http';
14
- import { firstValueFrom, timeout } from 'rxjs';
14
+ import { firstValueFrom, timeout, debounceTime, distinctUntilChanged } from 'rxjs';
15
15
  import * as i1$1 from '@angular/forms';
16
16
  import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
17
17
  import * as i2$1 from '@angular/material/form-field';
18
18
  import { MatFormFieldModule, MatHint } from '@angular/material/form-field';
19
19
  import { MatInputModule } from '@angular/material/input';
20
- import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
20
+ import { debounceTime as debounceTime$1, distinctUntilChanged as distinctUntilChanged$1 } from 'rxjs/operators';
21
21
 
22
22
  class OslBaseExtended {
23
23
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslBaseExtended, deps: [], target: i0.ɵɵFactoryTarget.Component });
@@ -39,13 +39,15 @@ class DialogWrapper {
39
39
  this.dialogData.formBody = data.formBody;
40
40
  this.dialogData.formFooter = data.formFooter;
41
41
  this.dialogData.data = data.data;
42
+ this.dialogData.dialogRef = dialogRef;
43
+ this.dialogData.component = data.component;
42
44
  }
43
45
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogWrapper, deps: [{ token: i1.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
44
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DialogWrapper, isStandalone: true, selector: "dialog-wrapper", ngImport: i0, template: "<div class=\"dialog-container\">\n\n <!-- Header -->\n @if(typeof dialogData.header == 'string') {\n <div class=\"dialog-header\" mat-dialog-title>\n <div class=\"dialog-header-left\">\n <div class=\"dialog-icon-ring\">\n <mat-icon class=\"dialog-icon\">\n {{ dialogData.header.startsWith('Add') ? 'add_circle' : dialogData.header.startsWith('Edit') ? 'edit' : 'info' }}\n </mat-icon>\n </div>\n <div class=\"dialog-title-group\">\n <span class=\"dialog-mode-label\">\n {{ dialogData.header.startsWith('Add') ? 'Creating New' : dialogData.header.startsWith('Edit') ? 'Editing' : '' }}\n </span>\n <span class=\"dialog-heading\">{{ dialogData.header }}</span>\n </div>\n </div>\n <button mat-icon-button class=\"dialog-close-btn\" mat-dialog-close>\n <mat-icon>close</mat-icon>\n </button>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"dialogData.header; context: { $implicit: dialogData }\"></ng-container>\n }\n\n <!-- Body -->\n <mat-dialog-content class=\"dialog-content\">\n @if(dialogData.formBody) {\n <div class=\"dialog-body\">\n <ng-container *ngTemplateOutlet=\"dialogData.formBody; context: { $implicit: dialogData }\"></ng-container>\n </div>\n }\n </mat-dialog-content>\n\n <!-- Footer -->\n @if(dialogData.formFooter) {\n <mat-dialog-actions class=\"dialog-actions\">\n <div class=\"dialog-footer\">\n <ng-container *ngTemplateOutlet=\"dialogData.formFooter; context: { $implicit: dialogData }\"></ng-container>\n </div>\n </mat-dialog-actions>\n }\n\n</div>\n", styles: [".dialog-container{display:flex;flex-direction:column;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 16px;background:linear-gradient(135deg,#f0f6ff,#e8f0fe);border-bottom:1px solid rgba(37,99,235,.12);gap:12px}.dialog-header:before{display:none}.dialog-header-left{display:flex;align-items:center;gap:14px;flex:1;min-width:0}.dialog-icon-ring{flex-shrink:0;width:48px;height:48px;border-radius:12px;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px #2563eb4d;animation:icon-pop .25s cubic-bezier(.34,1.56,.64,1)}.dialog-icon{color:#fff;font-size:24px;width:24px;height:24px}.dialog-title-group{display:flex;flex-direction:column;min-width:0}.dialog-mode-label{font-size:11px;font-weight:500;color:var(--osl-primary, #2563eb);text-transform:uppercase;letter-spacing:.6px;line-height:1.2}.dialog-heading{font-size:18px;font-weight:600;color:#111827;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dialog-close-btn{flex-shrink:0;color:#6b7280;transition:color .15s ease,background .15s ease}.dialog-close-btn:hover{color:#111827;background:#0000000f}.dialog-close-btn .mat-icon{font-size:20px;width:20px;height:20px}.dialog-content{padding:0!important;max-height:65vh;overflow-y:auto}.dialog-content::-webkit-scrollbar{width:5px}.dialog-content::-webkit-scrollbar-track{background:transparent}.dialog-content::-webkit-scrollbar-thumb{background:#2563eb33;border-radius:4px}.dialog-body{padding:20px 24px}.dialog-actions{padding:0!important;min-height:unset!important;border-top:1px solid #e5e7eb;background:#fafafa}.dialog-footer{width:100%;padding:14px 24px}@keyframes icon-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.mat-mdc-dialog-title:before{display:none}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { 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: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }] });
46
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DialogWrapper, isStandalone: true, selector: "dialog-wrapper", ngImport: i0, template: "\n@if(dialogData.component){\n <ng-container [ngComponentOutlet]=\"dialogData.component\" [ngComponentOutletInputs]=\"{ data: dialogData }\"></ng-container>\n}\n@else{\n <div class=\"dialog-container\">\n \n <!-- Header -->\n @if(typeof dialogData.header == 'string') {\n <div class=\"dialog-header\" mat-dialog-title>\n <div class=\"dialog-header-left\">\n <div class=\"dialog-icon-ring\">\n <mat-icon class=\"dialog-icon\">\n {{ dialogData.header.startsWith('Add') ? 'add_circle' : dialogData.header.startsWith('Edit') ? 'edit' : 'info' }}\n </mat-icon>\n </div>\n <div class=\"dialog-title-group\">\n <span class=\"dialog-mode-label\">\n {{ dialogData.header.startsWith('Add') ? 'Creating New' : dialogData.header.startsWith('Edit') ? 'Edit' : '' }}\n </span>\n <span class=\"dialog-heading\"> {{ dialogData.header.startsWith('Add') ? dialogData.header.replace('Add','') : dialogData.header.startsWith('Edit') ? dialogData.header.replace('Edit','') : '' }}</span>\n </div>\n </div>\n <button mat-icon-button class=\"dialog-close-btn\" mat-dialog-close>\n <mat-icon>close</mat-icon>\n </button>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"dialogData.header; context: { $implicit: dialogData }\"></ng-container>\n }\n \n <!-- Body -->\n <mat-dialog-content class=\"dialog-content\">\n @if(dialogData.formBody) {\n <div class=\"dialog-body\">\n <ng-container *ngTemplateOutlet=\"dialogData.formBody; context: { $implicit: dialogData }\"></ng-container>\n </div>\n }\n </mat-dialog-content>\n \n <!-- Footer -->\n @if(dialogData.formFooter) {\n <mat-dialog-actions class=\"dialog-actions\">\n <div class=\"dialog-footer\">\n <ng-container *ngTemplateOutlet=\"dialogData.formFooter; context: { $implicit: dialogData }\"></ng-container>\n </div>\n </mat-dialog-actions>\n }\n \n </div>\n\n}\n", styles: [".dialog-container{display:flex;flex-direction:column;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 16px;background:linear-gradient(135deg,#f0f6ff,#e8f0fe);border-bottom:1px solid rgba(37,99,235,.12);gap:12px}.dialog-header:before{display:none}.dialog-header-left{display:flex;align-items:center;gap:14px;flex:1;min-width:0}.dialog-icon-ring{flex-shrink:0;width:48px;height:48px;border-radius:12px;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px #2563eb4d;animation:icon-pop .25s cubic-bezier(.34,1.56,.64,1)}.dialog-icon{color:#fff;font-size:24px;width:24px;height:24px}.dialog-title-group{display:flex;flex-direction:column;min-width:0}.dialog-mode-label{font-size:11px;font-weight:500;color:var(--osl-primary, #2563eb);text-transform:uppercase;letter-spacing:.6px;line-height:1.2}.dialog-heading{font-size:18px;font-weight:600;color:#111827;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dialog-close-btn{flex-shrink:0;color:#6b7280;transition:color .15s ease,background .15s ease}.dialog-close-btn:hover{color:#111827;background:#0000000f}.dialog-close-btn .mat-icon{font-size:20px;width:20px;height:20px}.dialog-content{padding:0!important;max-height:65vh;overflow-y:auto}.dialog-content::-webkit-scrollbar{width:5px}.dialog-content::-webkit-scrollbar-track{background:transparent}.dialog-content::-webkit-scrollbar-thumb{background:#2563eb33;border-radius:4px}.dialog-body{padding:20px 24px}.dialog-actions{padding:0!important;min-height:unset!important;border-top:1px solid #e5e7eb;background:#fafafa}.dialog-footer{width:100%;padding:14px 24px}@keyframes icon-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.mat-mdc-dialog-title:before{display:none}\n"], dependencies: [{ kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { 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: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }] });
45
47
  }
46
48
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogWrapper, decorators: [{
47
49
  type: Component,
48
- args: [{ selector: 'dialog-wrapper', imports: [MatDialogModule, MatIconModule, NgTemplateOutlet, MatIconButton], template: "<div class=\"dialog-container\">\n\n <!-- Header -->\n @if(typeof dialogData.header == 'string') {\n <div class=\"dialog-header\" mat-dialog-title>\n <div class=\"dialog-header-left\">\n <div class=\"dialog-icon-ring\">\n <mat-icon class=\"dialog-icon\">\n {{ dialogData.header.startsWith('Add') ? 'add_circle' : dialogData.header.startsWith('Edit') ? 'edit' : 'info' }}\n </mat-icon>\n </div>\n <div class=\"dialog-title-group\">\n <span class=\"dialog-mode-label\">\n {{ dialogData.header.startsWith('Add') ? 'Creating New' : dialogData.header.startsWith('Edit') ? 'Editing' : '' }}\n </span>\n <span class=\"dialog-heading\">{{ dialogData.header }}</span>\n </div>\n </div>\n <button mat-icon-button class=\"dialog-close-btn\" mat-dialog-close>\n <mat-icon>close</mat-icon>\n </button>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"dialogData.header; context: { $implicit: dialogData }\"></ng-container>\n }\n\n <!-- Body -->\n <mat-dialog-content class=\"dialog-content\">\n @if(dialogData.formBody) {\n <div class=\"dialog-body\">\n <ng-container *ngTemplateOutlet=\"dialogData.formBody; context: { $implicit: dialogData }\"></ng-container>\n </div>\n }\n </mat-dialog-content>\n\n <!-- Footer -->\n @if(dialogData.formFooter) {\n <mat-dialog-actions class=\"dialog-actions\">\n <div class=\"dialog-footer\">\n <ng-container *ngTemplateOutlet=\"dialogData.formFooter; context: { $implicit: dialogData }\"></ng-container>\n </div>\n </mat-dialog-actions>\n }\n\n</div>\n", styles: [".dialog-container{display:flex;flex-direction:column;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 16px;background:linear-gradient(135deg,#f0f6ff,#e8f0fe);border-bottom:1px solid rgba(37,99,235,.12);gap:12px}.dialog-header:before{display:none}.dialog-header-left{display:flex;align-items:center;gap:14px;flex:1;min-width:0}.dialog-icon-ring{flex-shrink:0;width:48px;height:48px;border-radius:12px;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px #2563eb4d;animation:icon-pop .25s cubic-bezier(.34,1.56,.64,1)}.dialog-icon{color:#fff;font-size:24px;width:24px;height:24px}.dialog-title-group{display:flex;flex-direction:column;min-width:0}.dialog-mode-label{font-size:11px;font-weight:500;color:var(--osl-primary, #2563eb);text-transform:uppercase;letter-spacing:.6px;line-height:1.2}.dialog-heading{font-size:18px;font-weight:600;color:#111827;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dialog-close-btn{flex-shrink:0;color:#6b7280;transition:color .15s ease,background .15s ease}.dialog-close-btn:hover{color:#111827;background:#0000000f}.dialog-close-btn .mat-icon{font-size:20px;width:20px;height:20px}.dialog-content{padding:0!important;max-height:65vh;overflow-y:auto}.dialog-content::-webkit-scrollbar{width:5px}.dialog-content::-webkit-scrollbar-track{background:transparent}.dialog-content::-webkit-scrollbar-thumb{background:#2563eb33;border-radius:4px}.dialog-body{padding:20px 24px}.dialog-actions{padding:0!important;min-height:unset!important;border-top:1px solid #e5e7eb;background:#fafafa}.dialog-footer{width:100%;padding:14px 24px}@keyframes icon-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.mat-mdc-dialog-title:before{display:none}\n"] }]
50
+ args: [{ selector: 'dialog-wrapper', imports: [MatDialogModule, MatIconModule, NgTemplateOutlet, MatIconButton, NgComponentOutlet], template: "\n@if(dialogData.component){\n <ng-container [ngComponentOutlet]=\"dialogData.component\" [ngComponentOutletInputs]=\"{ data: dialogData }\"></ng-container>\n}\n@else{\n <div class=\"dialog-container\">\n \n <!-- Header -->\n @if(typeof dialogData.header == 'string') {\n <div class=\"dialog-header\" mat-dialog-title>\n <div class=\"dialog-header-left\">\n <div class=\"dialog-icon-ring\">\n <mat-icon class=\"dialog-icon\">\n {{ dialogData.header.startsWith('Add') ? 'add_circle' : dialogData.header.startsWith('Edit') ? 'edit' : 'info' }}\n </mat-icon>\n </div>\n <div class=\"dialog-title-group\">\n <span class=\"dialog-mode-label\">\n {{ dialogData.header.startsWith('Add') ? 'Creating New' : dialogData.header.startsWith('Edit') ? 'Edit' : '' }}\n </span>\n <span class=\"dialog-heading\"> {{ dialogData.header.startsWith('Add') ? dialogData.header.replace('Add','') : dialogData.header.startsWith('Edit') ? dialogData.header.replace('Edit','') : '' }}</span>\n </div>\n </div>\n <button mat-icon-button class=\"dialog-close-btn\" mat-dialog-close>\n <mat-icon>close</mat-icon>\n </button>\n </div>\n } @else {\n <ng-container *ngTemplateOutlet=\"dialogData.header; context: { $implicit: dialogData }\"></ng-container>\n }\n \n <!-- Body -->\n <mat-dialog-content class=\"dialog-content\">\n @if(dialogData.formBody) {\n <div class=\"dialog-body\">\n <ng-container *ngTemplateOutlet=\"dialogData.formBody; context: { $implicit: dialogData }\"></ng-container>\n </div>\n }\n </mat-dialog-content>\n \n <!-- Footer -->\n @if(dialogData.formFooter) {\n <mat-dialog-actions class=\"dialog-actions\">\n <div class=\"dialog-footer\">\n <ng-container *ngTemplateOutlet=\"dialogData.formFooter; context: { $implicit: dialogData }\"></ng-container>\n </div>\n </mat-dialog-actions>\n }\n \n </div>\n\n}\n", styles: [".dialog-container{display:flex;flex-direction:column;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:20px 20px 16px;background:linear-gradient(135deg,#f0f6ff,#e8f0fe);border-bottom:1px solid rgba(37,99,235,.12);gap:12px}.dialog-header:before{display:none}.dialog-header-left{display:flex;align-items:center;gap:14px;flex:1;min-width:0}.dialog-icon-ring{flex-shrink:0;width:48px;height:48px;border-radius:12px;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px #2563eb4d;animation:icon-pop .25s cubic-bezier(.34,1.56,.64,1)}.dialog-icon{color:#fff;font-size:24px;width:24px;height:24px}.dialog-title-group{display:flex;flex-direction:column;min-width:0}.dialog-mode-label{font-size:11px;font-weight:500;color:var(--osl-primary, #2563eb);text-transform:uppercase;letter-spacing:.6px;line-height:1.2}.dialog-heading{font-size:18px;font-weight:600;color:#111827;line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dialog-close-btn{flex-shrink:0;color:#6b7280;transition:color .15s ease,background .15s ease}.dialog-close-btn:hover{color:#111827;background:#0000000f}.dialog-close-btn .mat-icon{font-size:20px;width:20px;height:20px}.dialog-content{padding:0!important;max-height:65vh;overflow-y:auto}.dialog-content::-webkit-scrollbar{width:5px}.dialog-content::-webkit-scrollbar-track{background:transparent}.dialog-content::-webkit-scrollbar-thumb{background:#2563eb33;border-radius:4px}.dialog-body{padding:20px 24px}.dialog-actions{padding:0!important;min-height:unset!important;border-top:1px solid #e5e7eb;background:#fafafa}.dialog-footer{width:100%;padding:14px 24px}@keyframes icon-pop{0%{transform:scale(.6);opacity:0}to{transform:scale(1);opacity:1}}.mat-mdc-dialog-title:before{display:none}\n"] }]
49
51
  }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: Dialog, decorators: [{
50
52
  type: Inject,
51
53
  args: [MAT_DIALOG_DATA]
@@ -55,6 +57,8 @@ class Dialog {
55
57
  formBody;
56
58
  formFooter;
57
59
  data;
60
+ component;
61
+ dialogRef;
58
62
  }
59
63
 
60
64
  class DeleteConfirmation {
@@ -110,14 +114,17 @@ class baseComponent {
110
114
  duration: 3000
111
115
  });
112
116
  }
113
- openDialog(header, formBody, formFooter, width = '40vw', data) {
117
+ openDialog(header, formBody, formFooter, width = '40vw', data, component) {
114
118
  const dialogData = {
115
119
  header: header,
116
120
  formBody: formBody,
117
- formFooter: formFooter
121
+ formFooter: formFooter,
122
+ data: data,
123
+ component: component
118
124
  };
119
125
  const dialogRef = this._injector.get(MatDialog)?.open(DialogWrapper, {
120
126
  width: width,
127
+ maxWidth: '80vw',
121
128
  data: { ...dialogData, ...data },
122
129
  });
123
130
  return dialogRef;
@@ -147,6 +154,12 @@ class Httpbase {
147
154
  getEndPoint(methodName) {
148
155
  return `${this.baseUrl}${this.controllerName}/${methodName}`;
149
156
  }
157
+ async getConfig() {
158
+ return await this.get('getConfig');
159
+ }
160
+ async search(body) {
161
+ return await this.post('Search', body);
162
+ }
150
163
  getHeaders() {
151
164
  const token = localStorage.getItem('token');
152
165
  return new HttpHeaders({
@@ -154,12 +167,13 @@ class Httpbase {
154
167
  Authorization: token ? `Bearer ${token}` : '',
155
168
  });
156
169
  }
157
- handleSuccess(statusCode, result) {
170
+ handleSuccess(statusCode, result, header) {
158
171
  return {
159
172
  isSuccessful: statusCode >= 200 && statusCode < 300,
160
173
  error: '',
161
174
  result: result,
162
175
  statusCode: statusCode,
176
+ headers: header
163
177
  };
164
178
  }
165
179
  handleError(error) {
@@ -213,7 +227,7 @@ class Httpbase {
213
227
  headers: this.getHeaders(),
214
228
  })
215
229
  .pipe(timeout(30000)));
216
- return this.handleSuccess(res.status, res.body);
230
+ return this.handleSuccess(res.status, res.body, res.headers);
217
231
  }
218
232
  catch (error) {
219
233
  return this.handleError(error);
@@ -228,7 +242,7 @@ class Httpbase {
228
242
  params: this.buildParams(params || []),
229
243
  })
230
244
  .pipe(timeout(30000)));
231
- return this.handleSuccess(res.status, res.body);
245
+ return this.handleSuccess(res.status, res.body, res.headers);
232
246
  }
233
247
  catch (error) {
234
248
  return this.handleError(error);
@@ -236,6 +250,8 @@ class Httpbase {
236
250
  }
237
251
  }
238
252
 
253
+ const AUTOCOMPLETE_LISTER_COMPONENT = new InjectionToken('AUTOCOMPLETE_LISTER_COMPONENT');
254
+
239
255
  class DatasourceCacheService {
240
256
  cache = new Map();
241
257
  pending = new Map();
@@ -348,11 +364,11 @@ class Oslinput {
348
364
  return result;
349
365
  }
350
366
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Oslinput, deps: [], target: i0.ɵɵFactoryTarget.Component });
351
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: Oslinput, isStandalone: false, selector: "osl-input", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", type: "type", placeholder: "placeholder", mask: "mask", min: "min", max: "max", minLength: "minLength", maxLength: "maxLength", prefixIcon: "prefixIcon", suffixIcon: "suffixIcon" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, ngImport: i0, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"myField.touched && myField.invalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n\n <div class=\"input-wrapper\" [class.plain]=\"!hasWrapper\" [class.error]=\"myField.touched && myField.invalid\" [class.input-disabled]=\"disabled\">\n @if(prefixIcon) {\n <mat-icon class=\"input-icon prefix-icon\">{{prefixIcon}}</mat-icon>\n }\n <input\n [type]=\"inputType\"\n [ngModel]=\"model\"\n (ngModelChange)=\"onModelChange($event)\"\n (change)=\"onChange()\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.minlength]=\"minLength\"\n [attr.maxlength]=\"maxLength\"\n [email]=\"type === 'email'\"\n #myField=\"ngModel\"\n class=\"inner-input\"\n >\n @if(type === 'password') {\n <button type=\"button\" class=\"password-toggle\" (click)=\"togglePassword()\" tabindex=\"-1\">\n <mat-icon>{{showPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n }\n @if(suffixIcon && type !== 'password') {\n <mat-icon class=\"input-icon suffix-icon\">{{suffixIcon}}</mat-icon>\n }\n </div>\n\n @if(myField.touched && myField.invalid) {\n @if(myField.errors?.['required']) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n } @else if(myField.errors?.['email']) {\n <mat-hint class=\"hint\">Please enter a valid email address.</mat-hint>\n } @else if(myField.errors?.['minlength']) {\n <mat-hint class=\"hint\">Minimum {{minLength}} characters required.</mat-hint>\n } @else if(myField.errors?.['maxlength']) {\n <mat-hint class=\"hint\">Maximum {{maxLength}} characters allowed.</mat-hint>\n } @else if(myField.errors?.['min']) {\n <mat-hint class=\"hint\">Value must be at least {{min}}.</mat-hint>\n } @else if(myField.errors?.['max']) {\n <mat-hint class=\"hint\">Value must be at most {{max}}.</mat-hint>\n }\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.input-wrapper{display:flex;align-items:center;height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);border:1px solid var(--osl-border-color);padding:0 8px;gap:6px;transition:border-color .5s}.input-wrapper:focus-within{border-color:var(--osl-focus-border-color)}.input-wrapper.error{border-color:var(--osl-error-color)}.input-wrapper.input-disabled{background:#f5f5f5;opacity:.7;cursor:not-allowed}.input-wrapper.plain{padding:0;border:none;height:auto;gap:0}.input-wrapper.plain .inner-input{border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);padding:5px;height:var(--osl-control-height)}.input-wrapper.plain .inner-input:focus{border-color:var(--osl-focus-border-color)}.input-wrapper.plain .inner-input.error{border-color:var(--osl-error-color)}.inner-input{flex:1;min-width:0;height:100%;border:none;outline:none;font-size:var(--osl-text-font-size);background:transparent;width:100%}.inner-input:disabled{cursor:not-allowed;background:transparent}.inner-input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.input-icon{font-size:18px;width:18px;height:18px;color:#888;flex-shrink:0;-webkit-user-select:none;user-select:none}.password-toggle{display:flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:#888;flex-shrink:0}.password-toggle mat-icon{font-size:18px;width:18px;height:18px}.password-toggle:hover{color:#333}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}@keyframes shake{0%{transform:translate(0)}25%{transform:translate(-10px)}50%{transform:translate(10px)}75%{transform:translate(-10px)}to{transform:translate(0)}}.error input{border:1px solid var(--osl-danger)!important;animation:shake .3s ease-in-out}\n"], dependencies: [{ kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { 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$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
367
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: Oslinput, isStandalone: false, selector: "osl-input", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", type: "type", placeholder: "placeholder", mask: "mask", min: "min", max: "max", minLength: "minLength", maxLength: "maxLength", prefixIcon: "prefixIcon", suffixIcon: "suffixIcon" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, ngImport: i0, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"myField.touched && myField.invalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n\n <div class=\"input-wrapper\" [class.plain]=\"!hasWrapper\" [class.error]=\"myField.touched && myField.invalid\" [class.input-disabled]=\"disabled\">\n @if(prefixIcon) {\n <mat-icon class=\"input-icon prefix-icon\">{{prefixIcon}}</mat-icon>\n }\n <input\n [type]=\"inputType\"\n [ngModel]=\"model\"\n (ngModelChange)=\"onModelChange($event)\"\n (change)=\"onChange()\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.minlength]=\"minLength\"\n [attr.maxlength]=\"maxLength\"\n [email]=\"type === 'email'\"\n #myField=\"ngModel\"\n class=\"inner-input\"\n >\n @if(type === 'password') {\n <button type=\"button\" class=\"password-toggle\" (click)=\"togglePassword()\" tabindex=\"-1\">\n <mat-icon>{{showPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n }\n @if(suffixIcon && type !== 'password') {\n <mat-icon class=\"input-icon suffix-icon\">{{suffixIcon}}</mat-icon>\n }\n </div>\n\n @if(myField.touched && myField.invalid) {\n @if(myField.errors?.['required']) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n } @else if(myField.errors?.['email']) {\n <mat-hint class=\"hint\">Please enter a valid email address.</mat-hint>\n } @else if(myField.errors?.['minlength']) {\n <mat-hint class=\"hint\">Minimum {{minLength}} characters required.</mat-hint>\n } @else if(myField.errors?.['maxlength']) {\n <mat-hint class=\"hint\">Maximum {{maxLength}} characters allowed.</mat-hint>\n } @else if(myField.errors?.['min']) {\n <mat-hint class=\"hint\">Value must be at least {{min}}.</mat-hint>\n } @else if(myField.errors?.['max']) {\n <mat-hint class=\"hint\">Value must be at most {{max}}.</mat-hint>\n }\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.input-wrapper{display:flex;align-items:center;height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);border:1px solid var(--osl-border-color);padding:0 8px;gap:6px;transition:border-color .5s}.input-wrapper:focus-within{border-color:var(--osl-focus-border-color)}.input-wrapper.error{border-color:var(--osl-error-color)}.input-wrapper.input-disabled{background:#f5f5f5;opacity:.7;cursor:not-allowed}.input-wrapper.plain{padding:0;border:none;height:auto;gap:0}.input-wrapper.plain .inner-input{border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);padding:5px;height:var(--osl-control-height)}.input-wrapper.plain .inner-input:focus{border-color:var(--osl-focus-border-color)}.input-wrapper.plain .inner-input.error{border-color:var(--osl-error-color)}.inner-input{flex:1;min-width:0;height:100%;border:none;outline:none;font-size:var(--osl-text-font-size);background:transparent;width:100%}.inner-input:disabled{cursor:not-allowed;background:transparent}.inner-input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.input-icon{font-size:18px;width:18px;height:18px;color:#888;flex-shrink:0;-webkit-user-select:none;user-select:none}.password-toggle{display:flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:#888;flex-shrink:0}.password-toggle mat-icon{font-size:18px;width:18px;height:18px}.password-toggle:hover{color:#333}.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.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { 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$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
352
368
  }
353
369
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Oslinput, decorators: [{
354
370
  type: Component,
355
- args: [{ selector: 'osl-input', standalone: false, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"myField.touched && myField.invalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n\n <div class=\"input-wrapper\" [class.plain]=\"!hasWrapper\" [class.error]=\"myField.touched && myField.invalid\" [class.input-disabled]=\"disabled\">\n @if(prefixIcon) {\n <mat-icon class=\"input-icon prefix-icon\">{{prefixIcon}}</mat-icon>\n }\n <input\n [type]=\"inputType\"\n [ngModel]=\"model\"\n (ngModelChange)=\"onModelChange($event)\"\n (change)=\"onChange()\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.minlength]=\"minLength\"\n [attr.maxlength]=\"maxLength\"\n [email]=\"type === 'email'\"\n #myField=\"ngModel\"\n class=\"inner-input\"\n >\n @if(type === 'password') {\n <button type=\"button\" class=\"password-toggle\" (click)=\"togglePassword()\" tabindex=\"-1\">\n <mat-icon>{{showPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n }\n @if(suffixIcon && type !== 'password') {\n <mat-icon class=\"input-icon suffix-icon\">{{suffixIcon}}</mat-icon>\n }\n </div>\n\n @if(myField.touched && myField.invalid) {\n @if(myField.errors?.['required']) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n } @else if(myField.errors?.['email']) {\n <mat-hint class=\"hint\">Please enter a valid email address.</mat-hint>\n } @else if(myField.errors?.['minlength']) {\n <mat-hint class=\"hint\">Minimum {{minLength}} characters required.</mat-hint>\n } @else if(myField.errors?.['maxlength']) {\n <mat-hint class=\"hint\">Maximum {{maxLength}} characters allowed.</mat-hint>\n } @else if(myField.errors?.['min']) {\n <mat-hint class=\"hint\">Value must be at least {{min}}.</mat-hint>\n } @else if(myField.errors?.['max']) {\n <mat-hint class=\"hint\">Value must be at most {{max}}.</mat-hint>\n }\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.input-wrapper{display:flex;align-items:center;height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);border:1px solid var(--osl-border-color);padding:0 8px;gap:6px;transition:border-color .5s}.input-wrapper:focus-within{border-color:var(--osl-focus-border-color)}.input-wrapper.error{border-color:var(--osl-error-color)}.input-wrapper.input-disabled{background:#f5f5f5;opacity:.7;cursor:not-allowed}.input-wrapper.plain{padding:0;border:none;height:auto;gap:0}.input-wrapper.plain .inner-input{border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);padding:5px;height:var(--osl-control-height)}.input-wrapper.plain .inner-input:focus{border-color:var(--osl-focus-border-color)}.input-wrapper.plain .inner-input.error{border-color:var(--osl-error-color)}.inner-input{flex:1;min-width:0;height:100%;border:none;outline:none;font-size:var(--osl-text-font-size);background:transparent;width:100%}.inner-input:disabled{cursor:not-allowed;background:transparent}.inner-input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.input-icon{font-size:18px;width:18px;height:18px;color:#888;flex-shrink:0;-webkit-user-select:none;user-select:none}.password-toggle{display:flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:#888;flex-shrink:0}.password-toggle mat-icon{font-size:18px;width:18px;height:18px}.password-toggle:hover{color:#333}.hint{color:var(--osl-error-color);margin-top:2px;font-size:var(--osl-hint-font-size)}.txt-clr-red{color:var(--osl-error-color)}@keyframes shake{0%{transform:translate(0)}25%{transform:translate(-10px)}50%{transform:translate(10px)}75%{transform:translate(-10px)}to{transform:translate(0)}}.error input{border:1px solid var(--osl-danger)!important;animation:shake .3s ease-in-out}\n"] }]
371
+ args: [{ selector: 'osl-input', standalone: false, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"myField.touched && myField.invalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n\n <div class=\"input-wrapper\" [class.plain]=\"!hasWrapper\" [class.error]=\"myField.touched && myField.invalid\" [class.input-disabled]=\"disabled\">\n @if(prefixIcon) {\n <mat-icon class=\"input-icon prefix-icon\">{{prefixIcon}}</mat-icon>\n }\n <input\n [type]=\"inputType\"\n [ngModel]=\"model\"\n (ngModelChange)=\"onModelChange($event)\"\n (change)=\"onChange()\"\n [required]=\"required\"\n [disabled]=\"disabled\"\n [placeholder]=\"placeholder\"\n [attr.min]=\"min || null\"\n [attr.max]=\"max || null\"\n [attr.minlength]=\"minLength\"\n [attr.maxlength]=\"maxLength\"\n [email]=\"type === 'email'\"\n #myField=\"ngModel\"\n class=\"inner-input\"\n >\n @if(type === 'password') {\n <button type=\"button\" class=\"password-toggle\" (click)=\"togglePassword()\" tabindex=\"-1\">\n <mat-icon>{{showPassword ? 'visibility_off' : 'visibility'}}</mat-icon>\n </button>\n }\n @if(suffixIcon && type !== 'password') {\n <mat-icon class=\"input-icon suffix-icon\">{{suffixIcon}}</mat-icon>\n }\n </div>\n\n @if(myField.touched && myField.invalid) {\n @if(myField.errors?.['required']) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n } @else if(myField.errors?.['email']) {\n <mat-hint class=\"hint\">Please enter a valid email address.</mat-hint>\n } @else if(myField.errors?.['minlength']) {\n <mat-hint class=\"hint\">Minimum {{minLength}} characters required.</mat-hint>\n } @else if(myField.errors?.['maxlength']) {\n <mat-hint class=\"hint\">Maximum {{maxLength}} characters allowed.</mat-hint>\n } @else if(myField.errors?.['min']) {\n <mat-hint class=\"hint\">Value must be at least {{min}}.</mat-hint>\n } @else if(myField.errors?.['max']) {\n <mat-hint class=\"hint\">Value must be at most {{max}}.</mat-hint>\n }\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.input-wrapper{display:flex;align-items:center;height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);border:1px solid var(--osl-border-color);padding:0 8px;gap:6px;transition:border-color .5s}.input-wrapper:focus-within{border-color:var(--osl-focus-border-color)}.input-wrapper.error{border-color:var(--osl-error-color)}.input-wrapper.input-disabled{background:#f5f5f5;opacity:.7;cursor:not-allowed}.input-wrapper.plain{padding:0;border:none;height:auto;gap:0}.input-wrapper.plain .inner-input{border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);padding:5px;height:var(--osl-control-height)}.input-wrapper.plain .inner-input:focus{border-color:var(--osl-focus-border-color)}.input-wrapper.plain .inner-input.error{border-color:var(--osl-error-color)}.inner-input{flex:1;min-width:0;height:100%;border:none;outline:none;font-size:var(--osl-text-font-size);background:transparent;width:100%}.inner-input:disabled{cursor:not-allowed;background:transparent}.inner-input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.input-icon{font-size:18px;width:18px;height:18px;color:#888;flex-shrink:0;-webkit-user-select:none;user-select:none}.password-toggle{display:flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:#888;flex-shrink:0}.password-toggle mat-icon{font-size:18px;width:18px;height:18px}.password-toggle:hover{color:#333}.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"] }]
356
372
  }], propDecorators: { label: [{
357
373
  type: Input,
358
374
  args: ['label']
@@ -659,8 +675,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
659
675
  type: Output
660
676
  }] } });
661
677
 
662
- class OslAutocomplete {
678
+ class OslAutocomplete extends baseComponent {
663
679
  elRef;
680
+ cdr;
664
681
  label = '';
665
682
  required = false;
666
683
  disabled = false;
@@ -670,16 +687,58 @@ class OslAutocomplete {
670
687
  valueField = '';
671
688
  placeholder = 'Type to search...';
672
689
  loading = false;
690
+ searchType = 'Local';
691
+ methodName = '';
692
+ configMethodName = '';
693
+ service;
694
+ object;
673
695
  modelChange = new EventEmitter();
674
696
  changeEv = new EventEmitter();
697
+ listerComponent = inject(AUTOCOMPLETE_LISTER_COMPONENT);
698
+ inputControl = new FormControl('');
675
699
  inputValue = '';
676
700
  showDropdown = false;
677
701
  filteredItems = [];
678
702
  touched = false;
679
- constructor(elRef) {
703
+ constructor(elRef, cdr) {
704
+ super();
680
705
  this.elRef = elRef;
706
+ this.cdr = cdr;
707
+ }
708
+ openLister() {
709
+ const inputLister = {
710
+ title: this.label,
711
+ methodName: this.methodName,
712
+ configMethodName: this.configMethodName,
713
+ service: this.service,
714
+ };
715
+ const dialogRef = this.openDialog(undefined, undefined, undefined, '60vw', inputLister, this.listerComponent);
716
+ dialogRef.afterClosed().subscribe((selectedRow) => {
717
+ if (selectedRow && selectedRow[this.valueField]) {
718
+ this.datasource = [selectedRow];
719
+ this.filteredItems = [...this.datasource];
720
+ this.selectItem(selectedRow);
721
+ }
722
+ });
681
723
  }
682
724
  ngOnInit() {
725
+ if (this.searchType == 'Api' && this.methodName && this.service) {
726
+ this.placeholder = 'Type to Search Or Press Enter';
727
+ this.inputControl.valueChanges
728
+ .pipe(debounceTime(500), distinctUntilChanged())
729
+ .subscribe(async (value) => {
730
+ const res = await this.service[this.methodName](value);
731
+ if (!res.isSuccessful)
732
+ return;
733
+ this.datasource = res.result;
734
+ this.filteredItems = res.result;
735
+ this.cdr.markForCheck();
736
+ });
737
+ if (this.object) {
738
+ this.datasource = [this.object];
739
+ }
740
+ }
741
+ this.cdr.markForCheck();
683
742
  this.filteredItems = [...this.datasource];
684
743
  this.syncInputFromModel();
685
744
  }
@@ -689,16 +748,19 @@ class OslAutocomplete {
689
748
  }
690
749
  syncInputFromModel() {
691
750
  if (this.model !== null && this.model !== undefined) {
692
- const found = this.datasource.find(item => this.getValue(item) === this.model);
751
+ const found = this.datasource.find((item) => this.getValue(item) === this.model);
693
752
  if (found)
694
753
  this.inputValue = this.getDisplay(found);
754
+ this.inputControl.setValue(this.getDisplay(found));
695
755
  }
696
756
  else {
697
757
  this.inputValue = '';
758
+ this.inputControl.setValue('');
698
759
  }
760
+ this.cdr.markForCheck();
699
761
  }
700
762
  getDisplay(item) {
701
- return this.displayField ? item[this.displayField] : String(item);
763
+ return item && this.displayField ? item[this.displayField] : String(item);
702
764
  }
703
765
  getValue(item) {
704
766
  return this.valueField ? item[this.valueField] : item;
@@ -707,32 +769,46 @@ class OslAutocomplete {
707
769
  return this.touched && this.required && !this.model;
708
770
  }
709
771
  onInput(val) {
710
- this.inputValue = val;
711
- this.showDropdown = true;
712
- this.filteredItems = this.datasource.filter(item => this.getDisplay(item).toLowerCase().includes(val.toLowerCase()));
713
- if (!val) {
714
- this.model = null;
715
- this.modelChange.emit(null);
772
+ this.model = null;
773
+ if (this.searchType == 'Local') {
774
+ this.inputValue = val;
775
+ this.inputControl.setValue(val);
776
+ this.showDropdown = true;
777
+ this.filteredItems = this.datasource.filter((item) => this.getDisplay(item)?.toLowerCase()?.includes(val?.toLowerCase()));
778
+ if (!val) {
779
+ this.model = null;
780
+ this.modelChange.emit(null);
781
+ }
716
782
  }
717
783
  }
718
784
  onFocus() {
719
785
  if (this.loading)
720
786
  return;
721
787
  this.showDropdown = true;
722
- this.filteredItems = this.datasource.filter(item => this.getDisplay(item).toLowerCase().includes(this.inputValue.toLowerCase()));
788
+ this.filteredItems = this.datasource.filter((item) => this.getDisplay(item)?.toLowerCase()?.includes(this.inputValue?.toLowerCase()));
789
+ }
790
+ onFocusOut() {
791
+ if (this.inputValue && this.filteredItems.length == 1) {
792
+ this.selectItem(this.filteredItems[0]);
793
+ }
794
+ if (!this.model) {
795
+ this.clearValue();
796
+ }
723
797
  }
724
798
  onBlur() {
725
799
  this.touched = true;
726
800
  }
727
801
  clearValue(event) {
728
- event.stopPropagation();
802
+ event?.stopPropagation();
729
803
  this.inputValue = '';
804
+ this.inputControl.setValue('');
730
805
  this.model = null;
731
806
  this.modelChange.emit(null);
732
807
  this.changeEv.emit(null);
733
808
  }
734
809
  selectItem(item) {
735
810
  this.inputValue = this.getDisplay(item);
811
+ this.inputControl.setValue(this.getDisplay(item));
736
812
  this.model = this.getValue(item);
737
813
  this.modelChange.emit(this.model);
738
814
  this.changeEv.emit(this.model);
@@ -743,13 +819,13 @@ class OslAutocomplete {
743
819
  this.showDropdown = false;
744
820
  }
745
821
  }
746
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocomplete, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
747
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslAutocomplete, isStandalone: false, selector: "osl-autocomplete", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", datasource: "datasource", displayField: "displayField", valueField: "valueField", placeholder: "placeholder", loading: "loading" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n <div class=\"autocomplete-wrapper\" [class.error]=\"isInvalid\">\n <input\n [value]=\"inputValue\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [disabled]=\"disabled || loading\"\n [class.error]=\"isInvalid\"\n [placeholder]=\"loading ? 'Loading...' : placeholder\"\n autocomplete=\"off\"\n >\n @if(loading) {\n <span class=\"ac-spinner\"></span>\n } @else if(inputValue && !disabled) {\n <button type=\"button\" class=\"ac-clear\" (mousedown)=\"clearValue($event)\" tabindex=\"-1\" title=\"Clear\">\n <mat-icon>close</mat-icon>\n </button>\n }\n @if(showDropdown && !loading) {\n <div class=\"dropdown\">\n @if(filteredItems.length > 0) {\n @for(item of filteredItems; track item) {\n <div class=\"dropdown-item\" (mousedown)=\"selectItem(item)\">{{getDisplay(item)}}</div>\n }\n } @else {\n <div class=\"no-results\">No results found</div>\n }\n </div>\n }\n </div>\n @if(isInvalid) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.autocomplete-wrapper{position:relative;display:flex;align-items:center}.autocomplete-wrapper input{height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);outline:none;border:1px solid var(--osl-border-color);padding:0 30px 0 8px;font-size:var(--osl-text-font-size);transition:border-color .5s}.autocomplete-wrapper input:focus{border-color:var(--osl-focus-border-color)}.autocomplete-wrapper input:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.7}.autocomplete-wrapper input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.autocomplete-wrapper input.error{border-color:var(--osl-error-color)}.ac-spinner{position:absolute;right:8px;width:14px;height:14px;border:2px solid var(--osl-border-color);border-top-color:var(--osl-focus-border-color);border-radius:50%;animation:ac-spin .7s linear infinite;pointer-events:none}@keyframes ac-spin{to{transform:rotate(360deg)}}.ac-clear{position:absolute;right:6px;display:flex;align-items:center;background:none;border:none;padding:0;cursor:pointer;color:#aaa}.ac-clear mat-icon{font-size:16px;width:16px;height:16px}.ac-clear:hover{color:#333}.dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;background:#fff;border:1px solid var(--osl-border-color);border-top:none;border-radius:0 0 var(--osl-border-radius) var(--osl-border-radius);max-height:200px;overflow-y:auto;box-shadow:0 4px 8px #00000014}.dropdown-item{padding:8px 10px;font-size:var(--osl-label-font-size);cursor:pointer}.dropdown-item:hover{background:#f5f5f5}.no-results{padding:8px 10px;font-size:var(--osl-label-font-size);color:#aaa;font-style:italic}.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$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
822
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocomplete, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
823
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslAutocomplete, isStandalone: false, selector: "osl-autocomplete", inputs: { label: "label", required: "required", disabled: "disabled", model: "model", datasource: "datasource", displayField: "displayField", valueField: "valueField", placeholder: "placeholder", loading: "loading", searchType: "searchType", methodName: "methodName", configMethodName: "configMethodName", service: "service", object: "object" }, outputs: { modelChange: "modelChange", changeEv: "changeEv" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n <div class=\"autocomplete-wrapper\" [class.error]=\"isInvalid\" [class.autocomplete-wrapper--api]=\"searchType == 'Api'\">\n <input\n [value]=\"inputValue\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (focusout)=\"onFocusOut()\"\n [disabled]=\"disabled || loading\"\n [formControl]=\"inputControl\"\n [class.error]=\"isInvalid\"\n [placeholder]=\"loading ? 'Loading...' : placeholder\"\n autocomplete=\"off\"\n (keyup.enter)=\"searchType == 'Api' ? openLister() : null\"\n >\n @if(loading) {\n <span class=\"ac-spinner\"></span>\n } @else {\n @if(inputValue && !disabled) {\n <button type=\"button\" class=\"ac-clear\" [class.ac-clear--shifted]=\"searchType == 'Api'\" (mousedown)=\"clearValue($event)\" tabindex=\"-1\" title=\"Clear\">\n <mat-icon>close</mat-icon>\n </button>\n }\n @if(searchType == 'Api' && !disabled) {\n <button type=\"button\" class=\"ac-lister-btn\" (mousedown)=\"$event.preventDefault(); openLister()\" tabindex=\"-1\" title=\"Browse list or press Enter\">\n <!-- <img src=\"assets/enter (2).png\" alt=\"Enter\" class=\"ac-lister-img\"> -->\n <mat-icon>manage_search</mat-icon>\n </button>\n }\n }\n @if(showDropdown && !loading) {\n <div class=\"dropdown\">\n @if(filteredItems.length > 0) {\n @for(item of filteredItems; track item) {\n <div class=\"dropdown-item\" (mousedown)=\"selectItem(item)\">{{getDisplay(item)}}</div>\n }\n } @else {\n @if(searchType == 'Local'){\n <div class=\"no-results\">No results found</div>\n }\n }\n </div>\n }\n </div>\n @if(isInvalid) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.autocomplete-wrapper{position:relative;display:flex;align-items:center}.autocomplete-wrapper input{height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);outline:none;border:1px solid var(--osl-border-color);padding:0 30px 0 8px;font-size:var(--osl-text-font-size);transition:border-color .5s}.autocomplete-wrapper input:focus{border-color:var(--osl-focus-border-color)}.autocomplete-wrapper input:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.7}.autocomplete-wrapper input::placeholder{font-size:var(--osl-label-font-size);color:#aaa;font-size:12px}.autocomplete-wrapper input.error{border-color:var(--osl-error-color)}.ac-spinner{position:absolute;right:8px;width:14px;height:14px;border:2px solid var(--osl-border-color);border-top-color:var(--osl-focus-border-color);border-radius:50%;animation:ac-spin .7s linear infinite;pointer-events:none}@keyframes ac-spin{to{transform:rotate(360deg)}}.ac-clear{position:absolute;right:6px;display:flex;align-items:center;background:none;border:none;padding:0;cursor:pointer;color:#aaa}.ac-clear mat-icon{font-size:16px;width:16px;height:16px}.ac-clear:hover{color:#333}.ac-clear--shifted{right:40px}.ac-lister-btn{position:absolute;right:5px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:2px;cursor:pointer;border-radius:4px;color:#aaa;opacity:.75;transition:opacity .15s,transform .1s}.ac-lister-btn:hover{opacity:1}.ac-lister-btn:active{transform:translateY(calc(-50% + 1px))}.ac-lister-img{width:24px;height:24px;display:block;pointer-events:none}.autocomplete-wrapper--api input{padding-right:64px}.dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;background:#fff;border:1px solid var(--osl-border-color);border-top:none;border-radius:0 0 var(--osl-border-radius) var(--osl-border-radius);max-height:200px;overflow-y:auto;box-shadow:0 4px 8px #00000014}.dropdown-item{padding:8px 10px;font-size:var(--osl-label-font-size);cursor:pointer}.dropdown-item:hover{background:#f5f5f5}.no-results{padding:8px 10px;font-size:var(--osl-label-font-size);color:#aaa;font-style:italic}.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.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
748
824
  }
749
825
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocomplete, decorators: [{
750
826
  type: Component,
751
- args: [{ selector: 'osl-autocomplete', standalone: false, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n <div class=\"autocomplete-wrapper\" [class.error]=\"isInvalid\">\n <input\n [value]=\"inputValue\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n [disabled]=\"disabled || loading\"\n [class.error]=\"isInvalid\"\n [placeholder]=\"loading ? 'Loading...' : placeholder\"\n autocomplete=\"off\"\n >\n @if(loading) {\n <span class=\"ac-spinner\"></span>\n } @else if(inputValue && !disabled) {\n <button type=\"button\" class=\"ac-clear\" (mousedown)=\"clearValue($event)\" tabindex=\"-1\" title=\"Clear\">\n <mat-icon>close</mat-icon>\n </button>\n }\n @if(showDropdown && !loading) {\n <div class=\"dropdown\">\n @if(filteredItems.length > 0) {\n @for(item of filteredItems; track item) {\n <div class=\"dropdown-item\" (mousedown)=\"selectItem(item)\">{{getDisplay(item)}}</div>\n }\n } @else {\n <div class=\"no-results\">No results found</div>\n }\n </div>\n }\n </div>\n @if(isInvalid) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.autocomplete-wrapper{position:relative;display:flex;align-items:center}.autocomplete-wrapper input{height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);outline:none;border:1px solid var(--osl-border-color);padding:0 30px 0 8px;font-size:var(--osl-text-font-size);transition:border-color .5s}.autocomplete-wrapper input:focus{border-color:var(--osl-focus-border-color)}.autocomplete-wrapper input:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.7}.autocomplete-wrapper input::placeholder{font-size:var(--osl-label-font-size);color:#aaa}.autocomplete-wrapper input.error{border-color:var(--osl-error-color)}.ac-spinner{position:absolute;right:8px;width:14px;height:14px;border:2px solid var(--osl-border-color);border-top-color:var(--osl-focus-border-color);border-radius:50%;animation:ac-spin .7s linear infinite;pointer-events:none}@keyframes ac-spin{to{transform:rotate(360deg)}}.ac-clear{position:absolute;right:6px;display:flex;align-items:center;background:none;border:none;padding:0;cursor:pointer;color:#aaa}.ac-clear mat-icon{font-size:16px;width:16px;height:16px}.ac-clear:hover{color:#333}.dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;background:#fff;border:1px solid var(--osl-border-color);border-top:none;border-radius:0 0 var(--osl-border-radius) var(--osl-border-radius);max-height:200px;overflow-y:auto;box-shadow:0 4px 8px #00000014}.dropdown-item{padding:8px 10px;font-size:var(--osl-label-font-size);cursor:pointer}.dropdown-item:hover{background:#f5f5f5}.no-results{padding:8px 10px;font-size:var(--osl-label-font-size);color:#aaa;font-style:italic}.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"] }]
752
- }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{
827
+ args: [{ selector: 'osl-autocomplete', standalone: false, template: "<div class=\"d-flex flex-column\">\n <label class=\"label\" [class.txt-clr-red]=\"isInvalid\">\n {{label}} <span class=\"txt-clr-red\">{{required?'*':''}}</span>\n </label>\n <div class=\"autocomplete-wrapper\" [class.error]=\"isInvalid\" [class.autocomplete-wrapper--api]=\"searchType == 'Api'\">\n <input\n [value]=\"inputValue\"\n (input)=\"onInput($any($event.target).value)\"\n (focus)=\"onFocus()\"\n (blur)=\"onBlur()\"\n (focusout)=\"onFocusOut()\"\n [disabled]=\"disabled || loading\"\n [formControl]=\"inputControl\"\n [class.error]=\"isInvalid\"\n [placeholder]=\"loading ? 'Loading...' : placeholder\"\n autocomplete=\"off\"\n (keyup.enter)=\"searchType == 'Api' ? openLister() : null\"\n >\n @if(loading) {\n <span class=\"ac-spinner\"></span>\n } @else {\n @if(inputValue && !disabled) {\n <button type=\"button\" class=\"ac-clear\" [class.ac-clear--shifted]=\"searchType == 'Api'\" (mousedown)=\"clearValue($event)\" tabindex=\"-1\" title=\"Clear\">\n <mat-icon>close</mat-icon>\n </button>\n }\n @if(searchType == 'Api' && !disabled) {\n <button type=\"button\" class=\"ac-lister-btn\" (mousedown)=\"$event.preventDefault(); openLister()\" tabindex=\"-1\" title=\"Browse list or press Enter\">\n <!-- <img src=\"assets/enter (2).png\" alt=\"Enter\" class=\"ac-lister-img\"> -->\n <mat-icon>manage_search</mat-icon>\n </button>\n }\n }\n @if(showDropdown && !loading) {\n <div class=\"dropdown\">\n @if(filteredItems.length > 0) {\n @for(item of filteredItems; track item) {\n <div class=\"dropdown-item\" (mousedown)=\"selectItem(item)\">{{getDisplay(item)}}</div>\n }\n } @else {\n @if(searchType == 'Local'){\n <div class=\"no-results\">No results found</div>\n }\n }\n </div>\n }\n </div>\n @if(isInvalid) {\n <mat-hint class=\"hint\">{{label}} is Required!</mat-hint>\n }\n</div>\n", styles: [".label{font-size:var(--osl-label-font-size);margin-bottom:5px}.autocomplete-wrapper{position:relative;display:flex;align-items:center}.autocomplete-wrapper input{height:var(--osl-control-height);width:100%;border-radius:var(--osl-border-radius);outline:none;border:1px solid var(--osl-border-color);padding:0 30px 0 8px;font-size:var(--osl-text-font-size);transition:border-color .5s}.autocomplete-wrapper input:focus{border-color:var(--osl-focus-border-color)}.autocomplete-wrapper input:disabled{background:#f5f5f5;cursor:not-allowed;opacity:.7}.autocomplete-wrapper input::placeholder{font-size:var(--osl-label-font-size);color:#aaa;font-size:12px}.autocomplete-wrapper input.error{border-color:var(--osl-error-color)}.ac-spinner{position:absolute;right:8px;width:14px;height:14px;border:2px solid var(--osl-border-color);border-top-color:var(--osl-focus-border-color);border-radius:50%;animation:ac-spin .7s linear infinite;pointer-events:none}@keyframes ac-spin{to{transform:rotate(360deg)}}.ac-clear{position:absolute;right:6px;display:flex;align-items:center;background:none;border:none;padding:0;cursor:pointer;color:#aaa}.ac-clear mat-icon{font-size:16px;width:16px;height:16px}.ac-clear:hover{color:#333}.ac-clear--shifted{right:40px}.ac-lister-btn{position:absolute;right:5px;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:2px;cursor:pointer;border-radius:4px;color:#aaa;opacity:.75;transition:opacity .15s,transform .1s}.ac-lister-btn:hover{opacity:1}.ac-lister-btn:active{transform:translateY(calc(-50% + 1px))}.ac-lister-img{width:24px;height:24px;display:block;pointer-events:none}.autocomplete-wrapper--api input{padding-right:64px}.dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;background:#fff;border:1px solid var(--osl-border-color);border-top:none;border-radius:0 0 var(--osl-border-radius) var(--osl-border-radius);max-height:200px;overflow-y:auto;box-shadow:0 4px 8px #00000014}.dropdown-item{padding:8px 10px;font-size:var(--osl-label-font-size);cursor:pointer}.dropdown-item:hover{background:#f5f5f5}.no-results{padding:8px 10px;font-size:var(--osl-label-font-size);color:#aaa;font-style:italic}.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"] }]
828
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { label: [{
753
829
  type: Input,
754
830
  args: ['label']
755
831
  }], required: [{
@@ -776,6 +852,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
776
852
  }], loading: [{
777
853
  type: Input,
778
854
  args: ['loading']
855
+ }], searchType: [{
856
+ type: Input,
857
+ args: ['searchType']
858
+ }], methodName: [{
859
+ type: Input,
860
+ args: ['methodName']
861
+ }], configMethodName: [{
862
+ type: Input,
863
+ args: ['configMethodName']
864
+ }], service: [{
865
+ type: Input,
866
+ args: ['service']
867
+ }], object: [{
868
+ type: Input,
869
+ args: ['object']
779
870
  }], modelChange: [{
780
871
  type: Output
781
872
  }], changeEv: [{
@@ -1077,10 +1168,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1077
1168
  }] } });
1078
1169
 
1079
1170
  class DynamicForm {
1171
+ cdr;
1080
1172
  elements = [];
1081
- model = {};
1173
+ model;
1082
1174
  modelChange = new EventEmitter();
1083
1175
  datasourceCache = inject(DatasourceCacheService);
1176
+ constructor(cdr) {
1177
+ this.cdr = cdr;
1178
+ }
1084
1179
  ngOnInit() {
1085
1180
  this.loadApiDatasources();
1086
1181
  }
@@ -1092,15 +1187,19 @@ class DynamicForm {
1092
1187
  loadApiDatasources() {
1093
1188
  this._loadForList(this.elements);
1094
1189
  }
1095
- _loadForList(list) {
1190
+ async _loadForList(list) {
1096
1191
  for (const elem of list) {
1097
1192
  if (elem.elementType === 'fieldset' && elem.rows?.length) {
1098
1193
  this._loadForList(elem.rows);
1099
1194
  }
1100
- else if (elem.apiService && elem.apiMethod) {
1101
- this.datasourceCache
1102
- .load(elem.apiService, elem.apiMethod, elem.apiBody)
1103
- .then((data) => (elem.datasource = data));
1195
+ else if (elem.apiService && elem.apiMethod && elem.searchType == 'Local') {
1196
+ elem.loadingIf = () => true;
1197
+ const data = await this.datasourceCache.load(elem.apiService, elem.apiMethod, elem.apiBody);
1198
+ elem.loadingIf = () => false;
1199
+ this.cdr.markForCheck();
1200
+ if (data && data.length > 0) {
1201
+ elem.datasource = data;
1202
+ }
1104
1203
  }
1105
1204
  }
1106
1205
  }
@@ -1108,13 +1207,13 @@ class DynamicForm {
1108
1207
  this.model[key] = event;
1109
1208
  this.modelChange.emit(this.model);
1110
1209
  }
1111
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, deps: [], target: i0.ɵɵFactoryTarget.Component });
1112
- 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" }, outputs: { modelChange: "modelChange" }, usesOnChanges: true, ngImport: i0, template: "@if(elements && elements.length > 0) {\n <div class=\"row 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'\">\n <osl-input\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-textarea\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-select\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-radio\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-file-upload\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-datepicker\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDate || ''\"\n [maxDate]=\"elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-checkbox\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\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\">\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\n \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: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }] });
1210
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1211
+ 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" }, outputs: { modelChange: "modelChange" }, usesOnChanges: true, ngImport: i0, template: "@if(elements && elements.length > 0) {\n <div class=\"row 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'\">\n <osl-input\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-textarea\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-select\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-radio\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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)=\"elem.change ? elem.change(model) : null\"\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 \n \n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-file-upload\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-datepicker\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDate || ''\"\n [maxDate]=\"elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-checkbox\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\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\">\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\n \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: "component", type: Oslinput, selector: "osl-input", inputs: ["label", "required", "disabled", "model", "type", "placeholder", "mask", "min", "max", "minLength", "maxLength", "prefixIcon", "suffixIcon"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel"], 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"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }] });
1113
1212
  }
1114
1213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DynamicForm, decorators: [{
1115
1214
  type: Component,
1116
- args: [{ selector: 'osl-dynamic-form', standalone: false, template: "@if(elements && elements.length > 0) {\n <div class=\"row 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'\">\n <osl-input\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-textarea\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-select\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-radio\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-file-upload\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-datepicker\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDate || ''\"\n [maxDate]=\"elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-checkbox\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\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\">\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\n \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"] }]
1117
- }], propDecorators: { elements: [{
1215
+ args: [{ selector: 'osl-dynamic-form', standalone: false, template: "@if(elements && elements.length > 0) {\n <div class=\"row 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'\">\n <osl-input\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-input>\n </div>\n }\n\n @case (\"textarea\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-textarea\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-textarea>\n </div>\n }\n\n @case (\"select\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-select\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-select>\n </div>\n }\n\n @case (\"radio\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-radio\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-radio>\n </div>\n }\n\n @case (\"slide-toggle\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-slide-toggle\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-slide-toggle>\n </div>\n }\n\n @case (\"autocomplete\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-autocomplete\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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)=\"elem.change ? elem.change(model) : null\"\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 \n \n ></osl-autocomplete>\n </div>\n }\n\n @case (\"file-uploader\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-file-upload\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-file-upload>\n </div>\n }\n\n @case (\"datepicker\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-datepicker\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!elem.disabled\"\n [required]=\"elem.requiredIf ? elem.requiredIf(model) : !!elem.required\"\n [dateType]=\"elem.dateType || 'date'\"\n [placeholder]=\"elem.placeholder || ''\"\n [minDate]=\"elem.minDate || ''\"\n [maxDate]=\"elem.maxDate || ''\"\n (changeEv)=\"elem.change ? elem.change(model) : null\"\n [(model)]=\"model[elem.key]\"\n ></osl-datepicker>\n </div>\n }\n\n @case (\"checkbox\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\n <osl-checkbox\n [label]=\"elem.label\"\n [disabled]=\"elem.disabledIf ? elem.disabledIf() : !!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 ></osl-checkbox>\n </div>\n }\n\n @case (\"button\") {\n <div [class]=\"'col-md-'+elem.columns+' mt-2'\">\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\">\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\n \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"] }]
1216
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { elements: [{
1118
1217
  type: Input,
1119
1218
  args: ['elements']
1120
1219
  }], model: [{
@@ -1130,7 +1229,7 @@ class OslSearchbar {
1130
1229
  searchQuery = "";
1131
1230
  searchControl = new FormControl('');
1132
1231
  ngOnInit() {
1133
- this.searchControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged()).subscribe(value => {
1232
+ this.searchControl.valueChanges.pipe(debounceTime$1(300), distinctUntilChanged$1()).subscribe(value => {
1134
1233
  this.onSearch.emit(value);
1135
1234
  });
1136
1235
  }
@@ -1162,11 +1261,13 @@ class OslGrid {
1162
1261
  tableHeight = 'calc(100vh - 200px)';
1163
1262
  /** When true, shows skeleton loading rows instead of data. */
1164
1263
  loading = false;
1264
+ isSelectable = false;
1165
1265
  pageChange = new EventEmitter();
1166
1266
  pageSizeChange = new EventEmitter();
1167
1267
  sortChange = new EventEmitter();
1168
1268
  editClick = new EventEmitter();
1169
1269
  deleteClick = new EventEmitter();
1270
+ onRowClick = new EventEmitter();
1170
1271
  currentPage = 1;
1171
1272
  sortKey = '';
1172
1273
  sortAsc = true;
@@ -1174,6 +1275,9 @@ class OslGrid {
1174
1275
  get skeletonRows() {
1175
1276
  return Array.from({ length: Math.min(this.pageSize, 10) });
1176
1277
  }
1278
+ get skeletonColumns() {
1279
+ return Array.from({ length: 5 });
1280
+ }
1177
1281
  get _total() {
1178
1282
  return this.autoMode ? this.datasource.length : this.totalRecords;
1179
1283
  }
@@ -1258,11 +1362,11 @@ class OslGrid {
1258
1362
  return raw !== null && raw !== undefined && raw !== '' ? raw : '--';
1259
1363
  }
1260
1364
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslGrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
1261
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslGrid, isStandalone: false, selector: "osl-grid", inputs: { columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", totalRecords: "totalRecords", tableHeight: "tableHeight", loading: "loading" }, outputs: { datasourceChange: "datasourceChange", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", editClick: "editClick", deleteClick: "deleteClick" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"osl-grid-wrapper\">\n\n <div class=\"osl-grid-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-grid-table\">\n <thead class=\"osl-grid-thead\">\n <tr>\n @for (col of columns; track col.key; let last = $last) {\n <th\n class=\"osl-grid-th\"\n [class.osl-grid-th--last]=\"last\"\n [class.osl-grid-th--actions]=\"col.isActions\"\n (click)=\"sort(col.key, col.isActions)\"\n >\n @if (!col.isActions) {\n <span class=\"osl-grid-th-inner\">\n {{ col.label }}\n <span class=\"osl-grid-sort-icon\" [class.osl-grid-sort-icon--active]=\"sortKey === col.key\">\n @if (sortKey === col.key) {\n {{ sortAsc ? '\u2191' : '\u2193' }}\n } @else {\n <span class=\"osl-grid-sort-icon--idle\">\u21C5</span>\n }\n </span>\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-grid-row osl-grid-row--skeleton\">\n @for (col of columns; track col.key; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\" [class.osl-grid-td--actions]=\"col.isActions\">\n @if (col.isActions) {\n <div class=\"osl-skeleton osl-skeleton--actions\"></div>\n } @else {\n <div class=\"osl-skeleton\"></div>\n }\n </td>\n }\n </tr>\n }\n } @else {\n @if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length\" class=\"osl-grid-empty\">\n <div class=\"d-flex align-items-center justify-content-center floating-element\">\n <div class=\"mx-4\">\n <p class=\"f-s-20 f-w-600 text-start\">No Records match the <br> current filters.</p>\n <p class=\"text-start\">Expecting to see new Records? Try again in <br> a few seconds as the system catches up</p>\n </div>\n <i class=\"icon\"></i>\n\n </div>\n </td>\n </tr>\n }\n @for (row of pagedData; track $index) {\n <tr class=\"osl-grid-row\">\n @for (col of columns; track col.key; let last = $last) {\n @if (col.isActions) {\n <td class=\"osl-grid-td osl-grid-td--actions\" [class.osl-grid-td--last]=\"last\">\n <button class=\"osl-grid-icon-btn\" (click)=\"editClick.emit(row)\" title=\"Edit\">\n <mat-icon>mode_edit_outline</mat-icon>\n </button>\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteClick.emit(row)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </td>\n } @else {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">{{ getCellValue(row, col) }}</td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-grid-pagination\">\n\n <span class=\"osl-grid-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} records\n } @else {\n No records\n }\n </span>\n\n <div class=\"osl-grid-pagination__controls\">\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\" title=\"First page\">\n \u00AB\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\" title=\"Previous page\">\n \u2039 Prev\n </button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-grid-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-grid-page-btn osl-grid-page-btn--num\"\n [class.osl-grid-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Next page\">\n Next \u203A\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Last page\">\n \u00BB\n </button>\n </div>\n\n <div class=\"osl-grid-pagination__size\">\n <select class=\"osl-grid-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\n", styles: [".osl-grid-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);border-radius:var(--osl-border-radius);overflow:hidden;background:#fff}.osl-grid-table-container{overflow-x:auto;overflow-y:auto;min-height:200px}.osl-grid-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-grid-thead{position:sticky;top:0;z-index:2}.osl-grid-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 14px;text-align:left;border-bottom:2px solid var(--osl-border-color);border-right:1px solid var(--osl-border-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.osl-grid-th:hover{background:#e5e7eb}.osl-grid-th--last{border-right:none}.osl-grid-th-inner{display:inline-flex;align-items:center;gap:6px}.osl-grid-sort-icon{font-size:11px;color:#9ca3af}.osl-grid-sort-icon--active{color:var(--osl-primary)}.osl-grid-sort-icon--idle{opacity:.35}.osl-grid-row{border-bottom:1px solid #f3f4f6;transition:background .12s}.osl-grid-row:hover{background:#f9fafb}.osl-grid-row:last-child{border-bottom:none}.osl-grid-td{padding:10px 14px;color:#111827;font-size:var(--osl-text-font-size);vertical-align:middle;white-space:nowrap;border-right:1px solid #f3f4f6}.osl-grid-td--last{border-right:none}.osl-grid-empty{padding:48px 16px;text-align:center;color:#9ca3af;font-size:var(--osl-text-font-size)}.osl-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-grid-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-grid-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-grid-pagination__size{display:flex;align-items:center;min-width:120px;justify-content:flex-end}.osl-grid-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-grid-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-grid-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-grid-page-btn--nav{font-size:12px;color:#6b7280}.osl-grid-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-grid-page-btn--active{background:var(--osl-primary);border-color:var(--osl-primary);color:#fff;font-weight:600}.osl-grid-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover);border-color:var(--osl-primary-hover)}.osl-grid-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-grid-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-grid-page-size:focus{border-color:var(--osl-focus-border-color)}.osl-grid-th--actions{width:80px;min-width:80px;cursor:default;text-align:center}.osl-grid-th--actions:hover{background:#f3f4f6}.osl-grid-td--actions{width:80px;min-width:80px;text-align:center;padding:6px 8px;white-space:nowrap}.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}@keyframes osl-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-skeleton{height:14px;border-radius:4px;background:#e5e7eb;animation:osl-skeleton-pulse 1.4s ease-in-out infinite;width:80%}.osl-skeleton--actions{width:52px;margin:0 auto}.osl-grid-row--skeleton{pointer-events:none}.icon{background-repeat:no-repeat;background-position:center;display:inline-block!important;vertical-align:middle;width:18%;height:250px;background-image:url('data:image/svg+xml,<svg width=\"147\" height=\"134\" viewBox=\"0 0 147 134\" xmlns=\"http://www.w3.org/2000/svg\">%0A <g fill=\"none\" fill-rule=\"evenodd\">%0A <path d=\"M2.143 94.537c-2.858-1.65-2.858-4.35 0-6l66.1-38.163c2.858-1.65 7.534-1.65 10.392 0l66.101 38.163c2.858 1.65 2.858 4.35 0 6l-66.1 38.163c-2.859 1.65-7.535 1.65-10.393 0l-66.1-38.162z\" fill=\"%23EAF0F6\" fill-opacity=\".75\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0\" fill=\"%23FFF\"/>%0A <path d=\"M82.974 42.77c-5.498 1.128-11.537 1.124-17.03-.013L46.688 88.68h.007c1.089-3.023 3.637-5.9 7.679-8.233 11.065-6.39 29.172-6.39 40.237 0 2.902 1.674 5.02 3.632 6.4 5.719L82.975 42.77z\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114zM74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0\" fill=\"%23F2F5F8\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279\" fill=\"%23F2F5F8\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" fill=\"%23FFF\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" fill=\"%23F2F5F8\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114\" fill=\"%23F2F5F8\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265\" fill=\"%23FFF\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748\" fill=\"%23FFF\"/>%0A <path d=\"M101.012 86.166L82.974 42.77c-5.499 1.127-11.537 1.123-17.031-.014L46.687 88.679h.007\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M121.68 10.236l-11.902 4.361M115.666 23.734l-5.239-2.47M119 25.306l-.753-.356M106.763 7.402l-.803 1.704M109.781 1l-1.81 3.84\" stroke=\"%23CBD6E5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A </g>%0A</svg>%0A');background-size:100%;animation:moveUpDown 3s ease-in-out infinite}@keyframes moveUpDown{0%,to{transform:translateY(0)}50%{transform:translateY(-15px)}}\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"] }] });
1365
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslGrid, isStandalone: false, selector: "osl-grid", inputs: { columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", totalRecords: "totalRecords", tableHeight: "tableHeight", loading: "loading", isSelectable: "isSelectable" }, outputs: { datasourceChange: "datasourceChange", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", editClick: "editClick", deleteClick: "deleteClick", onRowClick: "onRowClick" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"osl-grid-wrapper\">\n\n <div class=\"osl-grid-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-grid-table\">\n <thead class=\"osl-grid-thead\">\n <tr>\n @if (loading && columns.length === 0) {\n @for (sk of skeletonColumns; track $index) {\n <th class=\"osl-grid-th osl-grid-th--skeleton\">\n <div class=\"osl-skeleton osl-skeleton--header\"></div>\n </th>\n }\n } @else {\n @for (col of columns; track col.key; let last = $last) {\n <th\n class=\"osl-grid-th\"\n [class.osl-grid-th--last]=\"last\"\n [class.osl-grid-th--actions]=\"col.isActions\"\n (click)=\"sort(col.key, col.isActions)\"\n >\n @if (!col.isActions) {\n <span class=\"osl-grid-th-inner\">\n {{ col.label }}\n <span class=\"osl-grid-sort-icon\" [class.osl-grid-sort-icon--active]=\"sortKey === col.key\">\n @if (sortKey === col.key) {\n {{ sortAsc ? '\u2191' : '\u2193' }}\n } @else {\n <span class=\"osl-grid-sort-icon--idle\">\u21C5</span>\n }\n </span>\n </span>\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-grid-row osl-grid-row--skeleton\">\n @if (columns.length > 0) {\n @for (col of columns; track col.key; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\" [class.osl-grid-td--actions]=\"col.isActions\">\n @if (col.isActions) {\n <div class=\"osl-skeleton osl-skeleton--actions\"></div>\n } @else {\n <div class=\"osl-skeleton\"></div>\n }\n </td>\n }\n } @else {\n @for (sk2 of skeletonColumns; track $index; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">\n <div class=\"osl-skeleton\"></div>\n </td>\n }\n }\n </tr>\n }\n } @else {\n @if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length\" class=\"osl-grid-empty\">\n <div class=\"d-flex align-items-center justify-content-center floating-element\">\n <div class=\"mx-4\">\n <p class=\"f-s-20 f-w-600 text-start\">No Records match the <br> current filters.</p>\n <p class=\"text-start\">Expecting to see new Records? Try again in <br> a few seconds as the system catches up</p>\n </div>\n <i class=\"icon\"></i>\n\n </div>\n </td>\n </tr>\n }\n @for (row of pagedData; track $index) {\n <tr class=\"osl-grid-row\" [class.pointer]=\"isSelectable\" (click)=\"onRowClick.emit(row)\">\n @for (col of columns; track col.key; let last = $last) {\n @if (col.isActions) {\n <td class=\"osl-grid-td osl-grid-td--actions\" [class.osl-grid-td--last]=\"last\">\n <button class=\"osl-grid-icon-btn\" (click)=\"editClick.emit(row)\" title=\"Edit\">\n <mat-icon>mode_edit_outline</mat-icon>\n </button>\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteClick.emit(row)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </td>\n } @else {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">{{ getCellValue(row, col) }}</td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-grid-pagination\">\n\n <span class=\"osl-grid-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} records\n } @else {\n No records\n }\n </span>\n\n <div class=\"osl-grid-pagination__controls\">\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\" title=\"First page\">\n \u00AB\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\" title=\"Previous page\">\n \u2039 Prev\n </button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-grid-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-grid-page-btn osl-grid-page-btn--num\"\n [class.osl-grid-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Next page\">\n Next \u203A\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Last page\">\n \u00BB\n </button>\n </div>\n\n <div class=\"osl-grid-pagination__size\">\n <select class=\"osl-grid-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\n", styles: [".osl-grid-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);border-radius:var(--osl-border-radius);overflow:hidden;background:#fff}.osl-grid-table-container{overflow-x:auto;overflow-y:auto;min-height:200px}.osl-grid-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-grid-thead{position:sticky;top:0;z-index:2}.osl-grid-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 14px;text-align:left;border-bottom:2px solid var(--osl-border-color);border-right:1px solid var(--osl-border-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.osl-grid-th:hover{background:#e5e7eb}.osl-grid-th--last{border-right:none}.osl-grid-th-inner{display:inline-flex;align-items:center;gap:6px}.osl-grid-sort-icon{font-size:11px;color:#9ca3af}.osl-grid-sort-icon--active{color:var(--osl-primary)}.osl-grid-sort-icon--idle{opacity:.35}.osl-grid-row{border-bottom:1px solid #f3f4f6;transition:background .12s}.osl-grid-row:hover{background:#f9fafb}.osl-grid-row:last-child{border-bottom:none}.osl-grid-td{padding:10px 14px;color:#111827;font-size:var(--osl-text-font-size);vertical-align:middle;white-space:nowrap;border-right:1px solid #f3f4f6}.osl-grid-td--last{border-right:none}.osl-grid-empty{padding:48px 16px;text-align:center;color:#9ca3af;font-size:var(--osl-text-font-size)}.osl-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-grid-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-grid-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-grid-pagination__size{display:flex;align-items:center;min-width:120px;justify-content:flex-end}.osl-grid-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-grid-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-grid-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-grid-page-btn--nav{font-size:12px;color:#6b7280}.osl-grid-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-grid-page-btn--active{background:var(--osl-primary);border-color:var(--osl-primary);color:#fff;font-weight:600}.osl-grid-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover);border-color:var(--osl-primary-hover)}.osl-grid-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-grid-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-grid-page-size:focus{border-color:var(--osl-focus-border-color)}.osl-grid-th--actions{width:80px;min-width:80px;cursor:default;text-align:center}.osl-grid-th--actions:hover{background:#f3f4f6}.osl-grid-td--actions{width:80px;min-width:80px;text-align:center;padding:6px 8px;white-space:nowrap}.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}@keyframes osl-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-skeleton{height:14px;border-radius:4px;background:#e5e7eb;animation:osl-skeleton-pulse 1.4s ease-in-out infinite;width:80%}.osl-skeleton--actions{width:52px;margin:0 auto}.osl-skeleton--header{height:11px;width:65%;background:#d1d5db;border-radius:3px}.osl-grid-th--skeleton{cursor:default;pointer-events:none}.osl-grid-row--skeleton{pointer-events:none}.icon{background-repeat:no-repeat;background-position:center;display:inline-block!important;vertical-align:middle;width:18%;height:250px;background-image:url('data:image/svg+xml,<svg width=\"147\" height=\"134\" viewBox=\"0 0 147 134\" xmlns=\"http://www.w3.org/2000/svg\">%0A <g fill=\"none\" fill-rule=\"evenodd\">%0A <path d=\"M2.143 94.537c-2.858-1.65-2.858-4.35 0-6l66.1-38.163c2.858-1.65 7.534-1.65 10.392 0l66.101 38.163c2.858 1.65 2.858 4.35 0 6l-66.1 38.163c-2.859 1.65-7.535 1.65-10.393 0l-66.1-38.162z\" fill=\"%23EAF0F6\" fill-opacity=\".75\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0\" fill=\"%23FFF\"/>%0A <path d=\"M82.974 42.77c-5.498 1.128-11.537 1.124-17.03-.013L46.688 88.68h.007c1.089-3.023 3.637-5.9 7.679-8.233 11.065-6.39 29.172-6.39 40.237 0 2.902 1.674 5.02 3.632 6.4 5.719L82.975 42.77z\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114zM74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0\" fill=\"%23F2F5F8\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279\" fill=\"%23F2F5F8\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" fill=\"%23FFF\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" fill=\"%23F2F5F8\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114\" fill=\"%23F2F5F8\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265\" fill=\"%23FFF\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748\" fill=\"%23FFF\"/>%0A <path d=\"M101.012 86.166L82.974 42.77c-5.499 1.127-11.537 1.123-17.031-.014L46.687 88.679h.007\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M121.68 10.236l-11.902 4.361M115.666 23.734l-5.239-2.47M119 25.306l-.753-.356M106.763 7.402l-.803 1.704M109.781 1l-1.81 3.84\" stroke=\"%23CBD6E5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A </g>%0A</svg>%0A');background-size:100%;animation:moveUpDown 3s ease-in-out infinite}@keyframes moveUpDown{0%,to{transform:translateY(0)}50%{transform:translateY(-15px)}}.pointer{cursor:pointer}\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"] }] });
1262
1366
  }
1263
1367
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslGrid, decorators: [{
1264
1368
  type: Component,
1265
- args: [{ selector: 'osl-grid', standalone: false, template: "<div class=\"osl-grid-wrapper\">\n\n <div class=\"osl-grid-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-grid-table\">\n <thead class=\"osl-grid-thead\">\n <tr>\n @for (col of columns; track col.key; let last = $last) {\n <th\n class=\"osl-grid-th\"\n [class.osl-grid-th--last]=\"last\"\n [class.osl-grid-th--actions]=\"col.isActions\"\n (click)=\"sort(col.key, col.isActions)\"\n >\n @if (!col.isActions) {\n <span class=\"osl-grid-th-inner\">\n {{ col.label }}\n <span class=\"osl-grid-sort-icon\" [class.osl-grid-sort-icon--active]=\"sortKey === col.key\">\n @if (sortKey === col.key) {\n {{ sortAsc ? '\u2191' : '\u2193' }}\n } @else {\n <span class=\"osl-grid-sort-icon--idle\">\u21C5</span>\n }\n </span>\n </span>\n }\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-grid-row osl-grid-row--skeleton\">\n @for (col of columns; track col.key; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\" [class.osl-grid-td--actions]=\"col.isActions\">\n @if (col.isActions) {\n <div class=\"osl-skeleton osl-skeleton--actions\"></div>\n } @else {\n <div class=\"osl-skeleton\"></div>\n }\n </td>\n }\n </tr>\n }\n } @else {\n @if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length\" class=\"osl-grid-empty\">\n <div class=\"d-flex align-items-center justify-content-center floating-element\">\n <div class=\"mx-4\">\n <p class=\"f-s-20 f-w-600 text-start\">No Records match the <br> current filters.</p>\n <p class=\"text-start\">Expecting to see new Records? Try again in <br> a few seconds as the system catches up</p>\n </div>\n <i class=\"icon\"></i>\n\n </div>\n </td>\n </tr>\n }\n @for (row of pagedData; track $index) {\n <tr class=\"osl-grid-row\">\n @for (col of columns; track col.key; let last = $last) {\n @if (col.isActions) {\n <td class=\"osl-grid-td osl-grid-td--actions\" [class.osl-grid-td--last]=\"last\">\n <button class=\"osl-grid-icon-btn\" (click)=\"editClick.emit(row)\" title=\"Edit\">\n <mat-icon>mode_edit_outline</mat-icon>\n </button>\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteClick.emit(row)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </td>\n } @else {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">{{ getCellValue(row, col) }}</td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-grid-pagination\">\n\n <span class=\"osl-grid-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} records\n } @else {\n No records\n }\n </span>\n\n <div class=\"osl-grid-pagination__controls\">\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\" title=\"First page\">\n \u00AB\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\" title=\"Previous page\">\n \u2039 Prev\n </button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-grid-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-grid-page-btn osl-grid-page-btn--num\"\n [class.osl-grid-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Next page\">\n Next \u203A\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Last page\">\n \u00BB\n </button>\n </div>\n\n <div class=\"osl-grid-pagination__size\">\n <select class=\"osl-grid-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\n", styles: [".osl-grid-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);border-radius:var(--osl-border-radius);overflow:hidden;background:#fff}.osl-grid-table-container{overflow-x:auto;overflow-y:auto;min-height:200px}.osl-grid-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-grid-thead{position:sticky;top:0;z-index:2}.osl-grid-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 14px;text-align:left;border-bottom:2px solid var(--osl-border-color);border-right:1px solid var(--osl-border-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.osl-grid-th:hover{background:#e5e7eb}.osl-grid-th--last{border-right:none}.osl-grid-th-inner{display:inline-flex;align-items:center;gap:6px}.osl-grid-sort-icon{font-size:11px;color:#9ca3af}.osl-grid-sort-icon--active{color:var(--osl-primary)}.osl-grid-sort-icon--idle{opacity:.35}.osl-grid-row{border-bottom:1px solid #f3f4f6;transition:background .12s}.osl-grid-row:hover{background:#f9fafb}.osl-grid-row:last-child{border-bottom:none}.osl-grid-td{padding:10px 14px;color:#111827;font-size:var(--osl-text-font-size);vertical-align:middle;white-space:nowrap;border-right:1px solid #f3f4f6}.osl-grid-td--last{border-right:none}.osl-grid-empty{padding:48px 16px;text-align:center;color:#9ca3af;font-size:var(--osl-text-font-size)}.osl-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-grid-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-grid-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-grid-pagination__size{display:flex;align-items:center;min-width:120px;justify-content:flex-end}.osl-grid-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-grid-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-grid-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-grid-page-btn--nav{font-size:12px;color:#6b7280}.osl-grid-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-grid-page-btn--active{background:var(--osl-primary);border-color:var(--osl-primary);color:#fff;font-weight:600}.osl-grid-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover);border-color:var(--osl-primary-hover)}.osl-grid-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-grid-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-grid-page-size:focus{border-color:var(--osl-focus-border-color)}.osl-grid-th--actions{width:80px;min-width:80px;cursor:default;text-align:center}.osl-grid-th--actions:hover{background:#f3f4f6}.osl-grid-td--actions{width:80px;min-width:80px;text-align:center;padding:6px 8px;white-space:nowrap}.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}@keyframes osl-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-skeleton{height:14px;border-radius:4px;background:#e5e7eb;animation:osl-skeleton-pulse 1.4s ease-in-out infinite;width:80%}.osl-skeleton--actions{width:52px;margin:0 auto}.osl-grid-row--skeleton{pointer-events:none}.icon{background-repeat:no-repeat;background-position:center;display:inline-block!important;vertical-align:middle;width:18%;height:250px;background-image:url('data:image/svg+xml,<svg width=\"147\" height=\"134\" viewBox=\"0 0 147 134\" xmlns=\"http://www.w3.org/2000/svg\">%0A <g fill=\"none\" fill-rule=\"evenodd\">%0A <path d=\"M2.143 94.537c-2.858-1.65-2.858-4.35 0-6l66.1-38.163c2.858-1.65 7.534-1.65 10.392 0l66.101 38.163c2.858 1.65 2.858 4.35 0 6l-66.1 38.163c-2.859 1.65-7.535 1.65-10.393 0l-66.1-38.162z\" fill=\"%23EAF0F6\" fill-opacity=\".75\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0\" fill=\"%23FFF\"/>%0A <path d=\"M82.974 42.77c-5.498 1.128-11.537 1.124-17.03-.013L46.688 88.68h.007c1.089-3.023 3.637-5.9 7.679-8.233 11.065-6.39 29.172-6.39 40.237 0 2.902 1.674 5.02 3.632 6.4 5.719L82.975 42.77z\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114zM74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0\" fill=\"%23F2F5F8\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279\" fill=\"%23F2F5F8\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" fill=\"%23FFF\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" fill=\"%23F2F5F8\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114\" fill=\"%23F2F5F8\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265\" fill=\"%23FFF\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748\" fill=\"%23FFF\"/>%0A <path d=\"M101.012 86.166L82.974 42.77c-5.499 1.127-11.537 1.123-17.031-.014L46.687 88.679h.007\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M121.68 10.236l-11.902 4.361M115.666 23.734l-5.239-2.47M119 25.306l-.753-.356M106.763 7.402l-.803 1.704M109.781 1l-1.81 3.84\" stroke=\"%23CBD6E5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A </g>%0A</svg>%0A');background-size:100%;animation:moveUpDown 3s ease-in-out infinite}@keyframes moveUpDown{0%,to{transform:translateY(0)}50%{transform:translateY(-15px)}}\n"] }]
1369
+ args: [{ selector: 'osl-grid', standalone: false, template: "<div class=\"osl-grid-wrapper\">\n\n <div class=\"osl-grid-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-grid-table\">\n <thead class=\"osl-grid-thead\">\n <tr>\n @if (loading && columns.length === 0) {\n @for (sk of skeletonColumns; track $index) {\n <th class=\"osl-grid-th osl-grid-th--skeleton\">\n <div class=\"osl-skeleton osl-skeleton--header\"></div>\n </th>\n }\n } @else {\n @for (col of columns; track col.key; let last = $last) {\n <th\n class=\"osl-grid-th\"\n [class.osl-grid-th--last]=\"last\"\n [class.osl-grid-th--actions]=\"col.isActions\"\n (click)=\"sort(col.key, col.isActions)\"\n >\n @if (!col.isActions) {\n <span class=\"osl-grid-th-inner\">\n {{ col.label }}\n <span class=\"osl-grid-sort-icon\" [class.osl-grid-sort-icon--active]=\"sortKey === col.key\">\n @if (sortKey === col.key) {\n {{ sortAsc ? '\u2191' : '\u2193' }}\n } @else {\n <span class=\"osl-grid-sort-icon--idle\">\u21C5</span>\n }\n </span>\n </span>\n }\n </th>\n }\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-grid-row osl-grid-row--skeleton\">\n @if (columns.length > 0) {\n @for (col of columns; track col.key; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\" [class.osl-grid-td--actions]=\"col.isActions\">\n @if (col.isActions) {\n <div class=\"osl-skeleton osl-skeleton--actions\"></div>\n } @else {\n <div class=\"osl-skeleton\"></div>\n }\n </td>\n }\n } @else {\n @for (sk2 of skeletonColumns; track $index; let last = $last) {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">\n <div class=\"osl-skeleton\"></div>\n </td>\n }\n }\n </tr>\n }\n } @else {\n @if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length\" class=\"osl-grid-empty\">\n <div class=\"d-flex align-items-center justify-content-center floating-element\">\n <div class=\"mx-4\">\n <p class=\"f-s-20 f-w-600 text-start\">No Records match the <br> current filters.</p>\n <p class=\"text-start\">Expecting to see new Records? Try again in <br> a few seconds as the system catches up</p>\n </div>\n <i class=\"icon\"></i>\n\n </div>\n </td>\n </tr>\n }\n @for (row of pagedData; track $index) {\n <tr class=\"osl-grid-row\" [class.pointer]=\"isSelectable\" (click)=\"onRowClick.emit(row)\">\n @for (col of columns; track col.key; let last = $last) {\n @if (col.isActions) {\n <td class=\"osl-grid-td osl-grid-td--actions\" [class.osl-grid-td--last]=\"last\">\n <button class=\"osl-grid-icon-btn\" (click)=\"editClick.emit(row)\" title=\"Edit\">\n <mat-icon>mode_edit_outline</mat-icon>\n </button>\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteClick.emit(row)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n </td>\n } @else {\n <td class=\"osl-grid-td\" [class.osl-grid-td--last]=\"last\">{{ getCellValue(row, col) }}</td>\n }\n }\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-grid-pagination\">\n\n <span class=\"osl-grid-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} records\n } @else {\n No records\n }\n </span>\n\n <div class=\"osl-grid-pagination__controls\">\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\" title=\"First page\">\n \u00AB\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\" title=\"Previous page\">\n \u2039 Prev\n </button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-grid-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-grid-page-btn osl-grid-page-btn--num\"\n [class.osl-grid-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\"\n >\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Next page\">\n Next \u203A\n </button>\n <button class=\"osl-grid-page-btn osl-grid-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\" title=\"Last page\">\n \u00BB\n </button>\n </div>\n\n <div class=\"osl-grid-pagination__size\">\n <select class=\"osl-grid-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\n", styles: [".osl-grid-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);border-radius:var(--osl-border-radius);overflow:hidden;background:#fff}.osl-grid-table-container{overflow-x:auto;overflow-y:auto;min-height:200px}.osl-grid-table{width:100%;border-collapse:collapse;table-layout:auto}.osl-grid-thead{position:sticky;top:0;z-index:2}.osl-grid-th{background:#f3f4f6;color:#4b5563;font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.04em;padding:10px 14px;text-align:left;border-bottom:2px solid var(--osl-border-color);border-right:1px solid var(--osl-border-color);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none}.osl-grid-th:hover{background:#e5e7eb}.osl-grid-th--last{border-right:none}.osl-grid-th-inner{display:inline-flex;align-items:center;gap:6px}.osl-grid-sort-icon{font-size:11px;color:#9ca3af}.osl-grid-sort-icon--active{color:var(--osl-primary)}.osl-grid-sort-icon--idle{opacity:.35}.osl-grid-row{border-bottom:1px solid #f3f4f6;transition:background .12s}.osl-grid-row:hover{background:#f9fafb}.osl-grid-row:last-child{border-bottom:none}.osl-grid-td{padding:10px 14px;color:#111827;font-size:var(--osl-text-font-size);vertical-align:middle;white-space:nowrap;border-right:1px solid #f3f4f6}.osl-grid-td--last{border-right:none}.osl-grid-empty{padding:48px 16px;text-align:center;color:#9ca3af;font-size:var(--osl-text-font-size)}.osl-grid-pagination{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 16px;border-top:1px solid var(--osl-border-color);background:#f9fafb;flex-shrink:0;flex-wrap:wrap}.osl-grid-pagination__info{font-size:12px;color:#6b7280;white-space:nowrap;min-width:120px}.osl-grid-pagination__controls{display:flex;align-items:center;gap:3px;flex-wrap:nowrap}.osl-grid-pagination__size{display:flex;align-items:center;min-width:120px;justify-content:flex-end}.osl-grid-page-btn{display:inline-flex;align-items:center;justify-content:center;height:30px;padding:0 10px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:13px;font-family:inherit;cursor:pointer;transition:background .12s,border-color .12s,color .12s;white-space:nowrap}.osl-grid-page-btn:hover:not(:disabled){background:#f3f4f6;border-color:#9ca3af}.osl-grid-page-btn:disabled{opacity:.35;cursor:not-allowed}.osl-grid-page-btn--nav{font-size:12px;color:#6b7280}.osl-grid-page-btn--num{min-width:30px;padding:0;font-size:13px}.osl-grid-page-btn--active{background:var(--osl-primary);border-color:var(--osl-primary);color:#fff;font-weight:600}.osl-grid-page-btn--active:hover:not(:disabled){background:var(--osl-primary-hover);border-color:var(--osl-primary-hover)}.osl-grid-page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;color:#9ca3af;font-size:13px;pointer-events:none}.osl-grid-page-size{height:30px;padding:0 8px;border:1px solid var(--osl-border-color);border-radius:var(--osl-border-radius);background:#fff;color:#374151;font-size:12px;font-family:inherit;cursor:pointer;outline:none}.osl-grid-page-size:focus{border-color:var(--osl-focus-border-color)}.osl-grid-th--actions{width:80px;min-width:80px;cursor:default;text-align:center}.osl-grid-th--actions:hover{background:#f3f4f6}.osl-grid-td--actions{width:80px;min-width:80px;text-align:center;padding:6px 8px;white-space:nowrap}.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}@keyframes osl-skeleton-pulse{0%,to{opacity:1}50%{opacity:.4}}.osl-skeleton{height:14px;border-radius:4px;background:#e5e7eb;animation:osl-skeleton-pulse 1.4s ease-in-out infinite;width:80%}.osl-skeleton--actions{width:52px;margin:0 auto}.osl-skeleton--header{height:11px;width:65%;background:#d1d5db;border-radius:3px}.osl-grid-th--skeleton{cursor:default;pointer-events:none}.osl-grid-row--skeleton{pointer-events:none}.icon{background-repeat:no-repeat;background-position:center;display:inline-block!important;vertical-align:middle;width:18%;height:250px;background-image:url('data:image/svg+xml,<svg width=\"147\" height=\"134\" viewBox=\"0 0 147 134\" xmlns=\"http://www.w3.org/2000/svg\">%0A <g fill=\"none\" fill-rule=\"evenodd\">%0A <path d=\"M2.143 94.537c-2.858-1.65-2.858-4.35 0-6l66.1-38.163c2.858-1.65 7.534-1.65 10.392 0l66.101 38.163c2.858 1.65 2.858 4.35 0 6l-66.1 38.163c-2.859 1.65-7.535 1.65-10.393 0l-66.1-38.162z\" fill=\"%23EAF0F6\" fill-opacity=\".75\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0\" fill=\"%23FFF\"/>%0A <path d=\"M82.974 42.77c-5.498 1.128-11.537 1.124-17.03-.013L46.688 88.68h.007c1.089-3.023 3.637-5.9 7.679-8.233 11.065-6.39 29.172-6.39 40.237 0 2.902 1.674 5.02 3.632 6.4 5.719L82.975 42.77z\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114zM74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748z\" stroke=\"%23CBD6E5\" stroke-width=\"5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0\" fill=\"%23FFF\"/>%0A <path d=\"M92.296 32.687c9.792-5.653 9.792-14.905 0-20.558-9.792-5.653-25.815-5.653-35.607 0-9.792 5.653-9.793 14.905 0 20.558 9.792 5.653 25.815 5.653 35.607 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0\" fill=\"%23F2F5F8\"/>%0A <path d=\"M87.338 30.07c7.3-4.214 7.3-11.11 0-15.325s-19.244-4.215-26.544 0c-7.3 4.214-7.3 11.111 0 15.325 7.3 4.214 19.244 4.214 26.544 0z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279\" fill=\"%23F2F5F8\"/>%0A <path d=\"M92.296 32.687c-9.792 5.653-25.815 5.653-35.607 0-4.896-2.827-7.344-6.553-7.344-10.28v6.703c0 3.726 2.448 7.452 7.344 10.279 9.792 5.653 25.815 5.653 35.607 0 4.896-2.827 7.344-6.553 7.344-10.28v-6.701c0 3.726-2.448 7.452-7.344 10.279z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" fill=\"%23FFF\"/>%0A <path d=\"M100.274 42.398l3.987-6.33-7.217-4.818-.011-.008-.004-.002v.001c-.481-.273-1.14-.234-1.867.185-1.46.843-2.654 2.912-2.654 4.598 0 .801.275 1.368.715 1.661l-.003.006.056.038.018.011 6.98 4.658z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" fill=\"%23F2F5F8\"/>%0A <path d=\"M119.293 42.398l-14.095-8.168c-.745-.432-1.772-.374-2.904.28-2.259 1.303-4.107 4.505-4.107 7.113 0 1.32.475 2.241 1.235 2.664l-.002.004 14.179 8.201\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114\" fill=\"%23F2F5F8\"/>%0A <path d=\"M120.635 45.115c0-2.609-1.848-3.676-4.107-2.37-2.26 1.303-4.108 4.504-4.108 7.113 0 2.608 1.848 3.676 4.108 2.371 2.26-1.304 4.107-4.505 4.107-7.114z\" stroke=\"%23CBD6E5\"/>%0A <path d=\"M74.333 12.076c-3.027 1.608-5.823 3.647-8.256 6.062-2.93 2.909-5.318 6.35-7.064 10.092.601.496 1.271.97 2.03 1.408 3.03 1.748 6.86 2.749 10.812 3.023 1.165-3.821 2.893-7.457 5.26-10.67 2.245-3.048 5.088-5.688 8.321-7.65-3.252-1.476-7.168-2.232-11.103-2.265\" fill=\"%23FFF\"/>%0A <path d=\"M87.55 15.472c-3.979 1.873-7.243 5.108-9.606 8.83-1.669 2.63-2.918 5.49-3.927 8.443 1.232.002 2.462-.07 3.674-.208 1.76-3.001 3.973-6.521 5.967-8.772 1.998-2.255 4.375-4.226 7.071-5.545-.784-.996-1.852-1.922-3.179-2.748\" fill=\"%23FFF\"/>%0A <path d=\"M101.012 86.166L82.974 42.77c-5.499 1.127-11.537 1.123-17.031-.014L46.687 88.679h.007\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M94.611 80.446c11.065 6.39 11.065 16.843 0 23.231-11.065 6.39-29.172 6.39-40.238 0-11.065-6.388-11.065-16.842 0-23.23 11.066-6.39 29.173-6.39 40.238 0z\" stroke=\"%23CBD6E5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-dasharray=\"2,3,0,0\"/>%0A <path d=\"M121.68 10.236l-11.902 4.361M115.666 23.734l-5.239-2.47M119 25.306l-.753-.356M106.763 7.402l-.803 1.704M109.781 1l-1.81 3.84\" stroke=\"%23CBD6E5\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>%0A </g>%0A</svg>%0A');background-size:100%;animation:moveUpDown 3s ease-in-out infinite}@keyframes moveUpDown{0%,to{transform:translateY(0)}50%{transform:translateY(-15px)}}.pointer{cursor:pointer}\n"] }]
1266
1370
  }], propDecorators: { columns: [{
1267
1371
  type: Input,
1268
1372
  args: ['columns']
@@ -1289,6 +1393,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1289
1393
  }], loading: [{
1290
1394
  type: Input,
1291
1395
  args: ['loading']
1396
+ }], isSelectable: [{
1397
+ type: Input,
1398
+ args: ['isSelectable']
1292
1399
  }], pageChange: [{
1293
1400
  type: Output
1294
1401
  }], pageSizeChange: [{
@@ -1299,12 +1406,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1299
1406
  type: Output
1300
1407
  }], deleteClick: [{
1301
1408
  type: Output
1409
+ }], onRowClick: [{
1410
+ type: Output
1302
1411
  }] } });
1303
1412
 
1304
1413
  class OslSetup {
1305
1414
  _injector = inject(Injector);
1306
1415
  formBodyTpl;
1307
1416
  formFooterTpl;
1417
+ searchbar;
1308
1418
  // ── Inputs ────────────────────────────────────────────────────
1309
1419
  title = '';
1310
1420
  columns = [];
@@ -1318,7 +1428,9 @@ class OslSetup {
1318
1428
  dialogWidth = "50vw";
1319
1429
  /** Dynamic form elements — when provided, enables Add/Edit dialog and action column. */
1320
1430
  formElements = [];
1431
+ beforeDisplay;
1321
1432
  onAddEditFn;
1433
+ isLister = false;
1322
1434
  // ── Outputs ───────────────────────────────────────────────────
1323
1435
  onSearch = new EventEmitter();
1324
1436
  onAdd = new EventEmitter();
@@ -1328,6 +1440,7 @@ class OslSetup {
1328
1440
  pageChange = new EventEmitter();
1329
1441
  pageSizeChange = new EventEmitter();
1330
1442
  sortChange = new EventEmitter();
1443
+ onRowClick = new EventEmitter();
1331
1444
  // ── Dialog state ──────────────────────────────────────────────
1332
1445
  dialogModel = {};
1333
1446
  dialogMode = 'add';
@@ -1339,11 +1452,22 @@ class OslSetup {
1339
1452
  get columnsWithActions() {
1340
1453
  if (!this.hasForm)
1341
1454
  return this.columns;
1455
+ if (this.isLister) {
1456
+ return [...this.columns];
1457
+ }
1342
1458
  return [{ key: '__actions', label: '', isActions: true }, ...this.columns];
1343
1459
  }
1460
+ onPageChange(eventEmitter, event) {
1461
+ eventEmitter.emit({ ...event, searchValue: this.searchbar?.searchControl?.value });
1462
+ }
1344
1463
  openAddDialog() {
1345
1464
  this.dialogMode = 'add';
1346
- this.dialogModel = {};
1465
+ if (this.beforeDisplay) {
1466
+ this.dialogModel = this.beforeDisplay(this.dialogModel);
1467
+ }
1468
+ else {
1469
+ this.dialogModel = {};
1470
+ }
1347
1471
  this.onAdd.emit();
1348
1472
  if (this.onAddEditFn) {
1349
1473
  this.onAddEditFn();
@@ -1353,7 +1477,12 @@ class OslSetup {
1353
1477
  }
1354
1478
  openEditDialog(row) {
1355
1479
  this.dialogMode = 'edit';
1356
- this.dialogModel = { ...row };
1480
+ if (this.beforeDisplay) {
1481
+ this.dialogModel = this.beforeDisplay(row);
1482
+ }
1483
+ else {
1484
+ this.dialogModel = { ...row };
1485
+ }
1357
1486
  this.onEdit.emit(row);
1358
1487
  if (this.onAddEditFn) {
1359
1488
  this.onAddEditFn(row);
@@ -1364,7 +1493,7 @@ class OslSetup {
1364
1493
  onDeleteClick(row) {
1365
1494
  const dialogData = {
1366
1495
  title: 'Delete ' + this.title,
1367
- message: `Are you sure you want to delete this ${this.title.toLowerCase()}? This action cannot be undone.`,
1496
+ message: `Are you sure you want to delete this ${this.title?.toLowerCase()}? This action cannot be undone.`,
1368
1497
  confirmText: 'Delete',
1369
1498
  cancelText: 'Cancel',
1370
1499
  };
@@ -1398,17 +1527,20 @@ class OslSetup {
1398
1527
  });
1399
1528
  }
1400
1529
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslSetup, deps: [], target: i0.ɵɵFactoryTarget.Component });
1401
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: OslSetup, isStandalone: false, selector: "osl-setup", inputs: { title: "title", columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", tableHeight: "tableHeight", totalRecords: "totalRecords", loading: "loading", dialogWidth: "dialogWidth", formElements: "formElements", onAddEditFn: "onAddEditFn" }, outputs: { onSearch: "onSearch", onAdd: "onAdd", onSave: "onSave", onEdit: "onEdit", onDelete: "onDelete", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange" }, viewQueries: [{ propertyName: "formBodyTpl", first: true, predicate: ["formBodyTpl"], descendants: true }, { propertyName: "formFooterTpl", first: true, predicate: ["formFooterTpl"], descendants: true }], ngImport: i0, template: "<div class=\"p-2\">\n\n <!-- Header -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar class=\"mx-2\" (onSearch)=\"onSearch.emit($event)\"></osl-searchbar>\n <osl-button\n variant=\"secondary\"\n size=\"sm\"\n [label]=\"'Add ' + title\"\n (clickEv)=\"openAddDialog()\"\n ></osl-button>\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n [columns]=\"columnsWithActions\"\n [datasource]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n (sortChange)=\"sortChange.emit($event)\"\n />\n </div>\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n <button mat-stroked-button class=\"dialog-cancel-btn\" (click)=\"cancelDialog()\">\n <mat-icon>close</mat-icon>\n Cancel\n </button>\n <button mat-flat-button class=\"dialog-save-btn\" (click)=\"saveDialog()\">\n <mat-icon>{{ dialogMode === 'add' ? 'add_circle' : 'save' }}</mat-icon>\n {{ dialogMode === 'add' ? 'Add ' + title : 'Save Changes' }}\n </button>\n </div>\n</ng-template>\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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: DynamicForm, selector: "osl-dynamic-form", inputs: ["elements", "model"], outputs: ["modelChange"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }, { kind: "component", type: OslSearchbar, selector: "osl-searchbar", inputs: ["label"], outputs: ["onSearch"] }, { kind: "component", type: OslGrid, selector: "osl-grid", inputs: ["columns", "datasource", "isPaginated", "pageSize", "autoMode", "totalRecords", "tableHeight", "loading"], outputs: ["datasourceChange", "pageChange", "pageSizeChange", "sortChange", "editClick", "deleteClick"] }] });
1530
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: OslSetup, isStandalone: false, selector: "osl-setup", inputs: { title: "title", columns: "columns", datasource: "datasource", isPaginated: "isPaginated", pageSize: "pageSize", autoMode: "autoMode", tableHeight: "tableHeight", totalRecords: "totalRecords", loading: "loading", dialogWidth: "dialogWidth", formElements: "formElements", beforeDisplay: "beforeDisplay", onAddEditFn: "onAddEditFn", isLister: "isLister" }, outputs: { onSearch: "onSearch", onAdd: "onAdd", onSave: "onSave", onEdit: "onEdit", onDelete: "onDelete", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", onRowClick: "onRowClick" }, viewQueries: [{ propertyName: "formBodyTpl", first: true, predicate: ["formBodyTpl"], descendants: true }, { propertyName: "formFooterTpl", first: true, predicate: ["formFooterTpl"], descendants: true }, { propertyName: "searchbar", first: true, predicate: ["searchbar"], descendants: true }], ngImport: i0, template: "<div class=\"p-2\">\n\n <!-- Header -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearch.emit($event)\"></osl-searchbar>\n @if(!isLister){\n <osl-button \n variant=\"secondary\"\n size=\"sm\"\n [label]=\"'Add ' + title\"\n (clickEv)=\"openAddDialog()\"\n ></osl-button>\n\n }\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n [columns]=\"columnsWithActions\"\n [datasource]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"onPageChange(pageChange,$event)\"\n (pageSizeChange)=\"onPageChange(pageSizeChange,$event)\"\n (sortChange)=\"sortChange.emit($event)\"\n [isSelectable]=\"isLister\";\n (onRowClick)=\"onRowClick.emit($event)\"\n />\n </div>\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n\n \n <button mat-flat-button class=\"dialog-save-btn\" (click)=\"saveDialog()\">\n <!-- <mat-icon>{{ dialogMode === 'add' ? 'add_circle' : 'save' }}</mat-icon> -->\n Save\n </button>\n </div>\n</ng-template>\n\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"], dependencies: [{ kind: "component", type: i3.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: DynamicForm, selector: "osl-dynamic-form", inputs: ["elements", "model"], outputs: ["modelChange"] }, { kind: "component", type: OslButton, selector: "osl-button", inputs: ["label", "icon", "variant", "size", "disabled", "loading", "type", "fullWidth"], outputs: ["clickEv"] }, { kind: "component", type: OslSearchbar, selector: "osl-searchbar", inputs: ["label"], outputs: ["onSearch"] }, { kind: "component", type: OslGrid, selector: "osl-grid", inputs: ["columns", "datasource", "isPaginated", "pageSize", "autoMode", "totalRecords", "tableHeight", "loading", "isSelectable"], outputs: ["datasourceChange", "pageChange", "pageSizeChange", "sortChange", "editClick", "deleteClick", "onRowClick"] }] });
1402
1531
  }
1403
1532
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslSetup, decorators: [{
1404
1533
  type: Component,
1405
- args: [{ selector: 'osl-setup', standalone: false, template: "<div class=\"p-2\">\n\n <!-- Header -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar class=\"mx-2\" (onSearch)=\"onSearch.emit($event)\"></osl-searchbar>\n <osl-button\n variant=\"secondary\"\n size=\"sm\"\n [label]=\"'Add ' + title\"\n (clickEv)=\"openAddDialog()\"\n ></osl-button>\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n [columns]=\"columnsWithActions\"\n [datasource]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"pageChange.emit($event)\"\n (pageSizeChange)=\"pageSizeChange.emit($event)\"\n (sortChange)=\"sortChange.emit($event)\"\n />\n </div>\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n <button mat-stroked-button class=\"dialog-cancel-btn\" (click)=\"cancelDialog()\">\n <mat-icon>close</mat-icon>\n Cancel\n </button>\n <button mat-flat-button class=\"dialog-save-btn\" (click)=\"saveDialog()\">\n <mat-icon>{{ dialogMode === 'add' ? 'add_circle' : 'save' }}</mat-icon>\n {{ dialogMode === 'add' ? 'Add ' + title : 'Save Changes' }}\n </button>\n </div>\n</ng-template>\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"] }]
1534
+ args: [{ selector: 'osl-setup', standalone: false, template: "<div class=\"p-2\">\n\n <!-- Header -->\n <div class=\"osl-setup-header\">\n <h5 class=\"mb-0\">{{ title }}</h5>\n <div class=\"d-flex align-items-center gap-2\">\n <osl-searchbar #searchbar class=\"mx-2\" (onSearch)=\"onSearch.emit($event)\"></osl-searchbar>\n @if(!isLister){\n <osl-button \n variant=\"secondary\"\n size=\"sm\"\n [label]=\"'Add ' + title\"\n (clickEv)=\"openAddDialog()\"\n ></osl-button>\n\n }\n </div>\n </div>\n\n <!-- Grid -->\n <div class=\"osl-setup-body my-2\">\n <osl-grid\n [columns]=\"columnsWithActions\"\n [datasource]=\"datasource\"\n [isPaginated]=\"isPaginated\"\n [pageSize]=\"pageSize\"\n [autoMode]=\"autoMode\"\n [tableHeight]=\"tableHeight\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n (editClick)=\"openEditDialog($event)\"\n (deleteClick)=\"onDeleteClick($event)\"\n (pageChange)=\"onPageChange(pageChange,$event)\"\n (pageSizeChange)=\"onPageChange(pageSizeChange,$event)\"\n (sortChange)=\"sortChange.emit($event)\"\n [isSelectable]=\"isLister\";\n (onRowClick)=\"onRowClick.emit($event)\"\n />\n </div>\n\n</div>\n\n<!-- Dialog: Form Body -->\n<ng-template #formBodyTpl>\n <osl-dynamic-form\n [elements]=\"formElements\"\n [(model)]=\"dialogModel\"\n ></osl-dynamic-form>\n</ng-template>\n\n<!-- Dialog: Form Footer -->\n<ng-template #formFooterTpl>\n <div class=\"osl-setup-dialog-footer\">\n\n \n <button mat-flat-button class=\"dialog-save-btn\" (click)=\"saveDialog()\">\n <!-- <mat-icon>{{ dialogMode === 'add' ? 'add_circle' : 'save' }}</mat-icon> -->\n Save\n </button>\n </div>\n</ng-template>\n\n", styles: [".osl-setup-header{display:flex;align-items:center;justify-content:space-between}.osl-setup-dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;width:100%}.dialog-cancel-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;border-color:var(--osl-border-color, #d1d5db);color:var(--osl-secondary, #6b7280);border-radius:var(--osl-border-radius, 4px);padding:0 16px;transition:all .2s ease}.dialog-cancel-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-cancel-btn:hover{border-color:#9ca3af;background:#f9fafb;color:#374151}.dialog-save-btn{display:flex;align-items:center;gap:6px;height:38px;font-size:13px;font-weight:500;background:linear-gradient(135deg,var(--osl-primary, #2563eb),#3b82f6);color:#fff;border-radius:var(--osl-border-radius, 4px);padding:0 18px;transition:all .2s ease;box-shadow:0 2px 8px #2563eb40}.dialog-save-btn mat-icon{font-size:17px;width:17px;height:17px}.dialog-save-btn:hover{background:linear-gradient(135deg,var(--osl-primary-hover, #1d4ed8),#2563eb);box-shadow:0 4px 14px #2563eb66;transform:translateY(-1px)}.dialog-save-btn:active{transform:translateY(0);box-shadow:0 2px 8px #2563eb40}\n"] }]
1406
1535
  }], propDecorators: { formBodyTpl: [{
1407
1536
  type: ViewChild,
1408
1537
  args: ['formBodyTpl']
1409
1538
  }], formFooterTpl: [{
1410
1539
  type: ViewChild,
1411
1540
  args: ['formFooterTpl']
1541
+ }], searchbar: [{
1542
+ type: ViewChild,
1543
+ args: ['searchbar']
1412
1544
  }], title: [{
1413
1545
  type: Input,
1414
1546
  args: ['title']
@@ -1442,9 +1574,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1442
1574
  }], formElements: [{
1443
1575
  type: Input,
1444
1576
  args: ['formElements']
1577
+ }], beforeDisplay: [{
1578
+ type: Input,
1579
+ args: ['beforeDisplay']
1445
1580
  }], onAddEditFn: [{
1446
1581
  type: Input,
1447
1582
  args: ['onAddEditFn']
1583
+ }], isLister: [{
1584
+ type: Input,
1585
+ args: ['isLister']
1448
1586
  }], onSearch: [{
1449
1587
  type: Output
1450
1588
  }], onAdd: [{
@@ -1461,6 +1599,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1461
1599
  type: Output
1462
1600
  }], sortChange: [{
1463
1601
  type: Output
1602
+ }], onRowClick: [{
1603
+ type: Output
1464
1604
  }] } });
1465
1605
 
1466
1606
  class OslFormGrid {
@@ -1570,7 +1710,7 @@ class OslFormGrid {
1570
1710
  return !!col.formElem?.required || !!col.formElem?.requiredIf;
1571
1711
  }
1572
1712
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFormGrid, deps: [], target: i0.ɵɵFactoryTarget.Component });
1573
- 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" }, outputs: { datasourceChange: "datasourceChange", rowAdd: "rowAdd", rowDelete: "rowDelete" }, ngImport: i0, template: "<div class=\"osl-fg-wrapper\">\n\n <div class=\"osl-fg-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-fg-table\">\n\n <thead class=\"osl-fg-thead\">\n <tr>\n <!-- Actions column: + add button in header -->\n @if (hasActions) {\n <th class=\"osl-fg-th osl-fg-th--actions\">\n @if (canAdd) {\n <button class=\"osl-grid-icon-btn\" (click)=\"addRow()\" [disabled]=\"loading\" title=\"Add row\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </th>\n }\n @for (col of columns; track col.key) {\n <th class=\"osl-fg-th\" [style.width]=\"col.width\">\n {{ col.displayName }}\n @if (colRequired(col)) {\n <span class=\"osl-fg-th-required\">*</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-fg-row osl-fg-row--skeleton\">\n @if (hasActions) {\n <td class=\"osl-fg-td osl-fg-td--actions\">\n <div class=\"osl-fg-skeleton osl-fg-skeleton--sm\"></div>\n </td>\n }\n @for (col of columns; track col.key) {\n <td class=\"osl-fg-td\"><div class=\"osl-fg-skeleton\"></div></td>\n }\n </tr>\n }\n\n } @else if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length + (hasActions ? 1 : 0)\" class=\"osl-fg-empty\">\n <div class=\"osl-fg-empty-inner\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\n </svg>\n <p>No rows yet.{{ canAdd ? ' Use + to get started.' : '' }}</p>\n </div>\n </td>\n </tr>\n\n } @else {\n @for (row of pagedData; track $index; let i = $index) {\n <tr class=\"osl-fg-row\">\n\n <!-- Delete button first -->\n @if (hasActions) {\n <td class=\"osl-fg-td osl-fg-td--actions\">\n @if (canDelete) {\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteRow(i)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n <!-- <button class=\"osl-fg-delete-btn\" (click)=\"deleteRow(i)\" title=\"Delete row\">\n <mat-icon>delete_outline</mat-icon>\n </button> -->\n }\n </td>\n }\n\n @for (col of columns; track col.key) {\n <td class=\"osl-fg-td\" [style.width]=\"col.width\">\n @if (col.formElem) {\n <div class=\"osl-fg-cell-form\">\n @switch (col.formElem.elementType) {\n\n @case ('textbox') {\n <osl-input\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [type]=\"col.formElem.inputType || 'text'\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [mask]=\"col.formElem.mask || ''\"\n [min]=\"col.formElem.min ?? ''\"\n [max]=\"col.formElem.max ?? ''\"\n [minLength]=\"col.formElem.minLength ?? null\"\n [maxLength]=\"col.formElem.maxLength ?? null\"\n [prefixIcon]=\"col.formElem.prefixIcon || ''\"\n [suffixIcon]=\"col.formElem.suffixIcon || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-input>\n }\n\n @case ('textarea') {\n <osl-textarea\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [rows]=\"col.formElem.textareaRows || 3\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [maxLength]=\"col.formElem.maxLength ?? null\"\n [minLength]=\"col.formElem.minLength ?? null\"\n [characterCounter]=\"!!col.formElem.characterCounter\"\n [resize]=\"col.formElem.resize || 'none'\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-textarea>\n }\n\n @case ('select') {\n <osl-select\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [placeholder]=\"col.formElem.selectPlaceholder || col.displayName\"\n [loading]=\"isLoading(row, col.formElem)\"\n [clearable]=\"!!col.formElem.clearable\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-select>\n }\n\n @case ('autocomplete') {\n <osl-autocomplete\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [placeholder]=\"col.formElem.autocompletePlaceholder || col.displayName\"\n [loading]=\"isLoading(row, col.formElem)\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-autocomplete>\n }\n\n @case ('radio') {\n <osl-radio\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [inline]=\"!!col.formElem.inline\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-radio>\n }\n\n @case ('checkbox') {\n <osl-checkbox\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [indeterminate]=\"!!col.formElem.indeterminate\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-checkbox>\n }\n\n @case ('slide-toggle') {\n <osl-slide-toggle\n [label]=\"''\"\n [disabled]=\"isDisabled(col.formElem)\"\n [labelPosition]=\"col.formElem.labelPosition || 'after'\"\n [trueLabel]=\"col.formElem.trueLabel || ''\"\n [falseLabel]=\"col.formElem.falseLabel || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-slide-toggle>\n }\n\n @case ('datepicker') {\n <osl-datepicker\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [dateType]=\"col.formElem.dateType || 'date'\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [minDate]=\"col.formElem.minDate || ''\"\n [maxDate]=\"col.formElem.maxDate || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-datepicker>\n }\n\n @case ('file-uploader') {\n <osl-file-upload\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [accept]=\"col.formElem.accept || ''\"\n [multiple]=\"!!col.formElem.multiple\"\n [maxSize]=\"col.formElem.maxFileSize || 0\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-file-upload>\n }\n\n }\n </div>\n } @else {\n <span class=\"osl-fg-cell-text\">{{ row[col.key] ?? '--' }}</span>\n }\n </td>\n }\n\n </tr>\n }\n }\n\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-fg-pagination\">\n\n <span class=\"osl-fg-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} rows\n } @else {\n No rows\n }\n </span>\n\n <div class=\"osl-fg-pagination__controls\">\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\">\u00AB</button>\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\">\u2039 Prev</button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-fg-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-fg-page-btn osl-fg-page-btn--num\"\n [class.osl-fg-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\">\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\">Next \u203A</button>\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\">\u00BB</button>\n </div>\n\n <div class=\"osl-fg-pagination__size\">\n <select class=\"osl-fg-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\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-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"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslAutocomplete, selector: "osl-autocomplete", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate"], outputs: ["modelChange", "changeEv"] }] });
1713
+ 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" }, outputs: { datasourceChange: "datasourceChange", rowAdd: "rowAdd", rowDelete: "rowDelete" }, ngImport: i0, template: "<div class=\"osl-fg-wrapper\">\n\n <div class=\"osl-fg-table-container\" [style.height]=\"tableHeight\">\n <table class=\"osl-fg-table\">\n\n <thead class=\"osl-fg-thead\">\n <tr>\n <!-- Actions column: + add button in header -->\n @if (hasActions) {\n <th class=\"osl-fg-th osl-fg-th--actions\">\n @if (canAdd) {\n <button class=\"osl-grid-icon-btn\" (click)=\"addRow()\" [disabled]=\"loading\" title=\"Add row\">\n <mat-icon>add</mat-icon>\n </button>\n }\n </th>\n }\n @for (col of columns; track col.key) {\n <th class=\"osl-fg-th\" [style.width]=\"col.width\">\n {{ col.displayName }}\n @if (colRequired(col)) {\n <span class=\"osl-fg-th-required\">*</span>\n }\n </th>\n }\n </tr>\n </thead>\n\n <tbody>\n\n @if (loading) {\n @for (sk of skeletonRows; track $index) {\n <tr class=\"osl-fg-row osl-fg-row--skeleton\">\n @if (hasActions) {\n <td class=\"osl-fg-td osl-fg-td--actions\">\n <div class=\"osl-fg-skeleton osl-fg-skeleton--sm\"></div>\n </td>\n }\n @for (col of columns; track col.key) {\n <td class=\"osl-fg-td\"><div class=\"osl-fg-skeleton\"></div></td>\n }\n </tr>\n }\n\n } @else if (pagedData.length === 0) {\n <tr>\n <td [attr.colspan]=\"columns.length + (hasActions ? 1 : 0)\" class=\"osl-fg-empty\">\n <div class=\"osl-fg-empty-inner\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/>\n <line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\"/>\n <line x1=\"9\" y1=\"9\" x2=\"9\" y2=\"21\"/>\n </svg>\n <p>No rows yet.{{ canAdd ? ' Use + to get started.' : '' }}</p>\n </div>\n </td>\n </tr>\n\n } @else {\n @for (row of pagedData; track $index; let i = $index) {\n <tr class=\"osl-fg-row\">\n\n <!-- Delete button first -->\n @if (hasActions) {\n <td class=\"osl-fg-td osl-fg-td--actions\">\n @if (canDelete) {\n <button class=\"osl-grid-icon-btn osl-grid-icon-btn--danger\" (click)=\"deleteRow(i)\" title=\"Delete\">\n <mat-icon>delete_outline</mat-icon>\n </button>\n <!-- <button class=\"osl-fg-delete-btn\" (click)=\"deleteRow(i)\" title=\"Delete row\">\n <mat-icon>delete_outline</mat-icon>\n </button> -->\n }\n </td>\n }\n\n @for (col of columns; track col.key) {\n <td class=\"osl-fg-td\" [style.width]=\"col.width\">\n @if (col.formElem) {\n <div class=\"osl-fg-cell-form\">\n @switch (col.formElem.elementType) {\n\n @case ('textbox') {\n <osl-input\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [type]=\"col.formElem.inputType || 'text'\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [mask]=\"col.formElem.mask || ''\"\n [min]=\"col.formElem.min ?? ''\"\n [max]=\"col.formElem.max ?? ''\"\n [minLength]=\"col.formElem.minLength ?? null\"\n [maxLength]=\"col.formElem.maxLength ?? null\"\n [prefixIcon]=\"col.formElem.prefixIcon || ''\"\n [suffixIcon]=\"col.formElem.suffixIcon || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-input>\n }\n\n @case ('textarea') {\n <osl-textarea\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [rows]=\"col.formElem.textareaRows || 3\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [maxLength]=\"col.formElem.maxLength ?? null\"\n [minLength]=\"col.formElem.minLength ?? null\"\n [characterCounter]=\"!!col.formElem.characterCounter\"\n [resize]=\"col.formElem.resize || 'none'\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-textarea>\n }\n\n @case ('select') {\n <osl-select\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [placeholder]=\"col.formElem.selectPlaceholder || col.displayName\"\n [loading]=\"isLoading(row, col.formElem)\"\n [clearable]=\"!!col.formElem.clearable\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-select>\n }\n\n @case ('autocomplete') {\n <osl-autocomplete\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [placeholder]=\"col.formElem.autocompletePlaceholder || col.displayName\"\n [loading]=\"isLoading(row, col.formElem)\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-autocomplete>\n }\n\n @case ('radio') {\n <osl-radio\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [datasource]=\"col.formElem.datasource || []\"\n [displayField]=\"col.formElem.displayField || ''\"\n [valueField]=\"col.formElem.valueField || ''\"\n [inline]=\"!!col.formElem.inline\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-radio>\n }\n\n @case ('checkbox') {\n <osl-checkbox\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [indeterminate]=\"!!col.formElem.indeterminate\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-checkbox>\n }\n\n @case ('slide-toggle') {\n <osl-slide-toggle\n [label]=\"''\"\n [disabled]=\"isDisabled(col.formElem)\"\n [labelPosition]=\"col.formElem.labelPosition || 'after'\"\n [trueLabel]=\"col.formElem.trueLabel || ''\"\n [falseLabel]=\"col.formElem.falseLabel || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-slide-toggle>\n }\n\n @case ('datepicker') {\n <osl-datepicker\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [dateType]=\"col.formElem.dateType || 'date'\"\n [placeholder]=\"col.formElem.placeholder || col.displayName\"\n [minDate]=\"col.formElem.minDate || ''\"\n [maxDate]=\"col.formElem.maxDate || ''\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-datepicker>\n }\n\n @case ('file-uploader') {\n <osl-file-upload\n [label]=\"''\"\n [required]=\"false\"\n [disabled]=\"isDisabled(col.formElem)\"\n [accept]=\"col.formElem.accept || ''\"\n [multiple]=\"!!col.formElem.multiple\"\n [maxSize]=\"col.formElem.maxFileSize || 0\"\n [model]=\"row[col.key]\"\n (modelChange)=\"onCellChange(row, col, $event)\"\n (changeEv)=\"col.formElem.change ? col.formElem.change(row) : null\">\n </osl-file-upload>\n }\n\n }\n </div>\n } @else {\n <span class=\"osl-fg-cell-text\">{{ row[col.key] ?? '--' }}</span>\n }\n </td>\n }\n\n </tr>\n }\n }\n\n </tbody>\n </table>\n </div>\n\n @if (isPaginated) {\n <div class=\"osl-fg-pagination\">\n\n <span class=\"osl-fg-pagination__info\">\n @if (loading) {\n Loading...\n } @else if (_total > 0) {\n {{ startRecord }}\u2013{{ endRecord }} of {{ _total }} rows\n } @else {\n No rows\n }\n </span>\n\n <div class=\"osl-fg-pagination__controls\">\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(1)\" [disabled]=\"currentPage === 1 || loading\">\u00AB</button>\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage - 1)\" [disabled]=\"currentPage === 1 || loading\">\u2039 Prev</button>\n\n @for (page of pageNumbers; track $index) {\n @if (page === -1) {\n <span class=\"osl-fg-page-ellipsis\">\u2026</span>\n } @else {\n <button\n class=\"osl-fg-page-btn osl-fg-page-btn--num\"\n [class.osl-fg-page-btn--active]=\"page === currentPage\"\n [disabled]=\"loading\"\n (click)=\"goToPage(page)\">\n {{ page }}\n </button>\n }\n }\n\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(currentPage + 1)\" [disabled]=\"currentPage === totalPages || loading\">Next \u203A</button>\n <button class=\"osl-fg-page-btn osl-fg-page-btn--nav\" (click)=\"goToPage(totalPages)\" [disabled]=\"currentPage === totalPages || loading\">\u00BB</button>\n </div>\n\n <div class=\"osl-fg-pagination__size\">\n <select class=\"osl-fg-page-size\" [ngModel]=\"pageSize\" (ngModelChange)=\"onPageSizeChange($event)\" [disabled]=\"loading\">\n @for (opt of pageSizeOptions; track opt) {\n <option [value]=\"opt\">{{ opt }} per page</option>\n }\n </select>\n </div>\n\n </div>\n }\n\n</div>\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-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"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: Osltextarea, selector: "osl-textarea", inputs: ["label", "rows", "required", "disabled", "model", "placeholder", "maxLength", "minLength", "characterCounter", "resize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSelect, selector: "osl-select", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "placeholder", "loading", "clearable"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslRadio, selector: "osl-radio", inputs: ["label", "required", "disabled", "model", "datasource", "displayField", "valueField", "inline"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslSlideToggle, selector: "osl-slide-toggle", inputs: ["label", "disabled", "model", "labelPosition", "trueLabel", "falseLabel"], 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"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslFileUpload, selector: "osl-file-upload", inputs: ["label", "required", "disabled", "model", "accept", "multiple", "maxSize"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslDatepicker, selector: "osl-datepicker", inputs: ["label", "required", "disabled", "model", "dateType", "placeholder", "minDate", "maxDate"], outputs: ["modelChange", "changeEv"] }, { kind: "component", type: OslCheckbox, selector: "osl-checkbox", inputs: ["label", "disabled", "required", "model", "indeterminate"], outputs: ["modelChange", "changeEv"] }] });
1574
1714
  }
1575
1715
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslFormGrid, decorators: [{
1576
1716
  type: Component,
@@ -1607,6 +1747,69 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1607
1747
  type: Output
1608
1748
  }] } });
1609
1749
 
1750
+ class OslAutocompleteLister {
1751
+ dialogRef;
1752
+ cd;
1753
+ data;
1754
+ column = [];
1755
+ datasource = [];
1756
+ autocompleteData;
1757
+ recordCount = 0;
1758
+ loader = false;
1759
+ constructor(dialogRef, cd) {
1760
+ this.dialogRef = dialogRef;
1761
+ this.cd = cd;
1762
+ }
1763
+ async ngAfterViewInit() {
1764
+ this.autocompleteData = this.data?.data;
1765
+ this.loader = true;
1766
+ await this.getConfig();
1767
+ await this.search();
1768
+ // this.loader = false
1769
+ this.cd.markForCheck();
1770
+ }
1771
+ async getConfig() {
1772
+ const res = await this.autocompleteData.service[this.autocompleteData.configMethodName || 'getConfig']();
1773
+ if (!res.isSuccessful)
1774
+ return;
1775
+ this.column = res.result;
1776
+ }
1777
+ async search(searchValue, page = 1, pageSize = 25) {
1778
+ this.loader = true;
1779
+ const res = await this.autocompleteData.service[this.autocompleteData.methodName || 'Search']({
1780
+ page: page,
1781
+ pageSize: pageSize,
1782
+ searchValue
1783
+ });
1784
+ this.cd.markForCheck();
1785
+ if (!res.isSuccessful)
1786
+ return;
1787
+ this.datasource = res.result;
1788
+ setTimeout(() => {
1789
+ this.loader = false;
1790
+ }, 20);
1791
+ this.recordCount = Number(res.headers?.get('recordCount') || 0);
1792
+ }
1793
+ onPageChange(event) {
1794
+ this.search(event.searchValue, event.page, event.pageSize);
1795
+ }
1796
+ onSearch(value) {
1797
+ this.search(value);
1798
+ }
1799
+ onRowClick(event) {
1800
+ this.dialogRef.close(event);
1801
+ }
1802
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocompleteLister, deps: [{ token: i1.MatDialogRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1803
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: OslAutocompleteLister, isStandalone: false, selector: "osl-autocomplete-lister", inputs: { data: "data" }, ngImport: i0, template: "<div class=\"p-4\">\r\n <osl-setup [loading]=\"loader\" [autoMode]=\"false\" [title]=\"autocompleteData?.title\" [totalRecords]=\"recordCount\" (onSearch)=\"onSearch($event)\" (pageSizeChange)=\"onPageChange($event)\" (pageChange)=\"onPageChange($event)\" (onRowClick)=\"onRowClick($event)\" [columns]=\"column\" [datasource]=\"datasource\" [isLister]=\"true\"></osl-setup>\r\n \r\n</div>", styles: [""], dependencies: [{ kind: "component", type: OslSetup, selector: "osl-setup", inputs: ["title", "columns", "datasource", "isPaginated", "pageSize", "autoMode", "tableHeight", "totalRecords", "loading", "dialogWidth", "formElements", "beforeDisplay", "onAddEditFn", "isLister"], outputs: ["onSearch", "onAdd", "onSave", "onEdit", "onDelete", "pageChange", "pageSizeChange", "sortChange", "onRowClick"] }] });
1804
+ }
1805
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: OslAutocompleteLister, decorators: [{
1806
+ type: Component,
1807
+ args: [{ selector: 'osl-autocomplete-lister', standalone: false, template: "<div class=\"p-4\">\r\n <osl-setup [loading]=\"loader\" [autoMode]=\"false\" [title]=\"autocompleteData?.title\" [totalRecords]=\"recordCount\" (onSearch)=\"onSearch($event)\" (pageSizeChange)=\"onPageChange($event)\" (pageChange)=\"onPageChange($event)\" (onRowClick)=\"onRowClick($event)\" [columns]=\"column\" [datasource]=\"datasource\" [isLister]=\"true\"></osl-setup>\r\n \r\n</div>" }]
1808
+ }], ctorParameters: () => [{ type: i1.MatDialogRef }, { type: i0.ChangeDetectorRef }], propDecorators: { data: [{
1809
+ type: Input,
1810
+ args: ['data']
1811
+ }] } });
1812
+
1610
1813
  class FormStructureModule {
1611
1814
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1612
1815
  static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, declarations: [DynamicForm,
@@ -1623,7 +1826,8 @@ class FormStructureModule {
1623
1826
  OslSetup,
1624
1827
  OslSearchbar,
1625
1828
  OslGrid,
1626
- OslFormGrid], imports: [NgTemplateOutlet,
1829
+ OslFormGrid,
1830
+ OslAutocompleteLister], imports: [NgTemplateOutlet,
1627
1831
  FormsModule,
1628
1832
  ReactiveFormsModule,
1629
1833
  MatFormFieldModule,
@@ -1631,8 +1835,7 @@ class FormStructureModule {
1631
1835
  MatHint,
1632
1836
  MatIconModule,
1633
1837
  MatDialogModule,
1634
- MatButtonModule], exports: [DynamicForm,
1635
- Oslinput,
1838
+ MatButtonModule], exports: [DynamicForm, OslSetup, OslGrid, OslFormGrid, Oslinput,
1636
1839
  Osltextarea,
1637
1840
  OslSelect,
1638
1841
  OslRadio,
@@ -1643,10 +1846,10 @@ class FormStructureModule {
1643
1846
  OslCheckbox,
1644
1847
  OslButton,
1645
1848
  OslSetup,
1646
- OslSearchbar,
1647
- OslGrid,
1648
- OslFormGrid] });
1649
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, imports: [FormsModule,
1849
+ OslSearchbar, OslAutocompleteLister] });
1850
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FormStructureModule, providers: [
1851
+ { provide: AUTOCOMPLETE_LISTER_COMPONENT, useValue: OslAutocompleteLister },
1852
+ ], imports: [FormsModule,
1650
1853
  ReactiveFormsModule,
1651
1854
  MatFormFieldModule,
1652
1855
  MatInputModule,
@@ -1673,6 +1876,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1673
1876
  OslSearchbar,
1674
1877
  OslGrid,
1675
1878
  OslFormGrid,
1879
+ OslAutocompleteLister
1676
1880
  ],
1677
1881
  imports: [
1678
1882
  NgTemplateOutlet,
@@ -1685,9 +1889,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1685
1889
  MatDialogModule,
1686
1890
  MatButtonModule,
1687
1891
  ],
1688
- exports: [
1689
- DynamicForm,
1690
- Oslinput,
1892
+ exports: [DynamicForm, OslSetup, OslGrid, OslFormGrid, Oslinput,
1691
1893
  Osltextarea,
1692
1894
  OslSelect,
1693
1895
  OslRadio,
@@ -1698,9 +1900,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1698
1900
  OslCheckbox,
1699
1901
  OslButton,
1700
1902
  OslSetup,
1701
- OslSearchbar,
1702
- OslGrid,
1703
- OslFormGrid,
1903
+ OslSearchbar, OslAutocompleteLister],
1904
+ providers: [
1905
+ { provide: AUTOCOMPLETE_LISTER_COMPONENT, useValue: OslAutocompleteLister },
1704
1906
  ],
1705
1907
  }]
1706
1908
  }] });
@@ -1713,5 +1915,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1713
1915
  * Generated bundle index. Do not edit.
1714
1916
  */
1715
1917
 
1716
- export { DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DynamicForm, FormStructureModule, Httpbase, OslAutocomplete, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslFileUpload, OslFormGrid, OslGrid, OslRadio, OslSearchbar, OslSelect, OslSetup, OslSlideToggle, Oslinput, Osltextarea, baseComponent };
1918
+ export { DeleteConfirmation, DeleteConfirmationData, Dialog, DialogWrapper, DynamicForm, FormStructureModule, Httpbase, OslAutocomplete, OslAutocompleteLister, OslBaseExtended, OslButton, OslCheckbox, OslDatepicker, OslFileUpload, OslFormGrid, OslGrid, OslRadio, OslSearchbar, OslSelect, OslSetup, OslSlideToggle, Oslinput, Osltextarea, baseComponent };
1717
1919
  //# sourceMappingURL=osl-base-extended.mjs.map