@yoozsoft/yoozsoft-ng 5.3.2 → 5.3.4

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.
@@ -2,9 +2,19 @@ import * as i0 from '@angular/core';
2
2
  import { TemplateRef, EventEmitter } from '@angular/core';
3
3
  import { ControlValueAccessor } from '@angular/forms';
4
4
 
5
+ interface OptionItem<T> {
6
+ label?: string;
7
+ value: T;
8
+ styleClass?: string;
9
+ icon?: string;
10
+ disabled?: boolean;
11
+ }
12
+
5
13
  declare class YsDropdownComponent implements ControlValueAccessor {
6
14
  /** لیست گزینه‌ها */
7
- options: any[];
15
+ private _options;
16
+ set options(value: any[]);
17
+ get options(): any[];
8
18
  optionLabel: string;
9
19
  placeholder: string;
10
20
  searchPlaceholder: string;
@@ -33,7 +43,7 @@ declare class YsDropdownComponent implements ControlValueAccessor {
33
43
  registerOnChange(fn: any): void;
34
44
  registerOnTouched(fn: any): void;
35
45
  setDisabledState?(isDisabled: boolean): void;
36
- get displayLabel(): string;
46
+ private normalizeOptions;
37
47
  get selectedLabels(): string;
38
48
  toggleDropdown(): void;
39
49
  filterOptions(): any[];
@@ -49,3 +59,4 @@ declare class YsDropdownComponent implements ControlValueAccessor {
49
59
  }
50
60
 
51
61
  export { YsDropdownComponent };
62
+ export type { OptionItem };
@@ -6,7 +6,9 @@ import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
6
6
 
7
7
  class YsDropdownComponent {
8
8
  /** لیست گزینه‌ها */
9
- options = [];
9
+ _options = [];
10
+ set options(value) { this._options = this.normalizeOptions(value); }
11
+ get options() { return this._options; }
10
12
  optionLabel = 'label';
11
13
  placeholder = '';
12
14
  searchPlaceholder = '';
@@ -48,24 +50,43 @@ class YsDropdownComponent {
48
50
  setDisabledState(isDisabled) {
49
51
  this.disabled = isDisabled;
50
52
  }
51
- get displayLabel() {
52
- if (this.multiple) {
53
- const count = Array.isArray(this.selected) ? this.selected.length : 0;
54
- return count ? `${count} مورد انتخاب شده` : 'انتخاب کنید';
55
- }
56
- // تکه‌ی ایمن: از options (که همیشه آرایه است ولی بازهم چک می‌کنیم)
57
- const label = this.options?.find(o => o.value === this.selected)?.label;
58
- return label ?? 'انتخاب کنید';
53
+ normalizeOptions(list) {
54
+ if (!Array.isArray(list))
55
+ return [];
56
+ return list.map(item => {
57
+ // 1. اگر primitive بود
58
+ if (['string', 'number', 'boolean'].includes(typeof item)) {
59
+ return {
60
+ raw: item,
61
+ label: String(item),
62
+ value: item
63
+ };
64
+ }
65
+ // 2. اگر OptionItem<T> بود
66
+ if ('value' in item) {
67
+ return {
68
+ raw: item,
69
+ label: item.label ?? String(item.value),
70
+ value: item.value,
71
+ ...item
72
+ };
73
+ }
74
+ // 3. object معمولی
75
+ return {
76
+ raw: item,
77
+ label: item[this.optionLabel] ?? JSON.stringify(item),
78
+ value: item
79
+ };
80
+ });
59
81
  }
60
82
  get selectedLabels() {
61
- if (this.multiple && Array.isArray(this.selected)) {
62
- if (this.selected.length > this.selectedMaxLength) {
63
- return this.selectedMaxLengthTemplate.replace('{length}', this.selected.length + '');
64
- }
65
- return this.selected.map(x => x[this.optionLabel]).join(this.selectionSeparator);
83
+ if (this.multiple) {
84
+ const items = this.options.filter(o => this.selected?.includes(o.value));
85
+ return items.map(o => o.label).join(this.selectionSeparator);
66
86
  }
67
87
  else {
68
- return this.selected ? this.selected[this.optionLabel] : '';
88
+ const item = this.options.find(o => o.value === this.selected);
89
+ return item?.label ?? '';
69
90
  }
70
91
  }
71
92
  toggleDropdown() {
@@ -87,24 +108,27 @@ class YsDropdownComponent {
87
108
  selectOption(option) {
88
109
  if (option.disabled)
89
110
  return;
111
+ const returnedValue = option.value; // مقدار نهایی برای فرم
90
112
  if (this.multiple) {
91
- const exists = this.selected?.some((x) => x === option);
113
+ const exists = this.selected?.some((x) => x === returnedValue);
92
114
  this.selected = exists
93
- ? this.selected.filter((x) => x !== option)
94
- : [...(this.selected || []), option];
115
+ ? this.selected.filter((x) => x !== returnedValue)
116
+ : [...(this.selected || []), returnedValue];
95
117
  }
96
118
  else {
97
- this.selected = option;
119
+ this.selected = returnedValue;
98
120
  this.isOpen = false;
99
121
  }
100
122
  this._onChange(this.selected);
101
- this._onTouched();
102
123
  this.selectionChange.emit(this.selected);
103
124
  }
104
125
  isSelected(option) {
105
- return this.multiple
106
- ? this.selected?.includes(option)
107
- : this.selected === option;
126
+ if (this.multiple) {
127
+ return Array.isArray(this.selected)
128
+ ? this.selected.includes(option.value)
129
+ : false;
130
+ }
131
+ return this.selected === option.value;
108
132
  }
109
133
  clearSelection() {
110
134
  this.selected = this.multiple ? [] : null;
@@ -172,7 +196,7 @@ class YsDropdownComponent {
172
196
  useExisting: forwardRef(() => YsDropdownComponent),
173
197
  multi: true,
174
198
  },
175
- ], ngImport: i0, template: "<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <span>{{option[optionLabel]}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>", styles: [".ys-dropdown .dropdown-toggle:after{display:none}.ys-dropdown .dropdown-menu{max-height:200px}.ys-dropdown .dropdown-item.highlighted{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
199
+ ], ngImport: i0, template: "<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" [disabled]=\"disabled\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"disabled\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\r\n [disabled]=\"disabled\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <!-- <span>{{option[optionLabel]}}</span> -->\r\n <span>{{option.label}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>", styles: [".ys-dropdown .dropdown-toggle:after{display:none}.ys-dropdown .dropdown-menu{max-height:200px}.ys-dropdown .dropdown-item.highlighted{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
176
200
  }
177
201
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsDropdownComponent, decorators: [{
178
202
  type: Component,
@@ -182,7 +206,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
182
206
  useExisting: forwardRef(() => YsDropdownComponent),
183
207
  multi: true,
184
208
  },
185
- ], template: "<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <span>{{option[optionLabel]}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>", styles: [".ys-dropdown .dropdown-toggle:after{display:none}.ys-dropdown .dropdown-menu{max-height:200px}.ys-dropdown .dropdown-item.highlighted{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}\n"] }]
209
+ ], template: "<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" [disabled]=\"disabled\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"disabled\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\r\n [disabled]=\"disabled\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <!-- <span>{{option[optionLabel]}}</span> -->\r\n <span>{{option.label}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>", styles: [".ys-dropdown .dropdown-toggle:after{display:none}.ys-dropdown .dropdown-menu{max-height:200px}.ys-dropdown .dropdown-item.highlighted{color:var(--bs-dropdown-link-hover-color);background-color:var(--bs-dropdown-link-hover-bg)}\n"] }]
186
210
  }], propDecorators: { options: [{
187
211
  type: Input
188
212
  }], optionLabel: [{
@@ -1 +1 @@
1
- {"version":3,"file":"yoozsoft-yoozsoft-ng-dropdown.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.html","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/yoozsoft-yoozsoft-ng-dropdown.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ElementRef, EventEmitter, forwardRef, HostListener, inject, Input, Output, TemplateRef } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'ys-dropdown',\r\n imports: [NgTemplateOutlet, FormsModule],\r\n templateUrl: './ys-dropdown.component.html',\r\n styleUrl: './ys-dropdown.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsDropdownComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsDropdownComponent implements ControlValueAccessor {\r\n\r\n /** لیست گزینه‌ها */\r\n @Input() options: any[] = [];\r\n @Input() optionLabel: string = 'label';\r\n @Input() placeholder: string = '';\r\n @Input() searchPlaceholder: string = '';\r\n @Input() selectedMaxLength: number = 3;\r\n @Input() selectedMaxLengthTemplate: string = '{length} items selected';\r\n @Input() selectionSeparator: string = \", \";\r\n\r\n /** انتخاب چندگانه یا تکی */\r\n @Input() multiple: boolean = false;\r\n\r\n @Input() showClear: boolean = false;\r\n\r\n /** تمپلیت سفارشی برای آیتم‌ها */\r\n @Input() itemTemplate?: TemplateRef<any>;\r\n\r\n /** مقدار انتخاب‌شده */\r\n @Input() selected: any[] | any = this.multiple ? [] : null;\r\n\r\n /** قابلیت جستجو */\r\n @Input() searchable: boolean = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** رویداد خروجی هنگام تغییر انتخاب */\r\n @Output() selectionChange = new EventEmitter<any>();\r\n\r\n searchTerm = '';\r\n isOpen = false;\r\n highlightedIndex: number = -1;\r\n\r\n private elRef = inject(ElementRef)\r\n\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n writeValue(obj: any): void {\r\n if (this.multiple) {\r\n this.selected = obj ? [...obj] : [];\r\n } else {\r\n this.selected = obj;\r\n }\r\n }\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n get displayLabel(): string {\r\n if (this.multiple) {\r\n const count = Array.isArray(this.selected) ? this.selected.length : 0;\r\n return count ? `${count} مورد انتخاب شده` : 'انتخاب کنید';\r\n }\r\n\r\n // تکه‌ی ایمن: از options (که همیشه آرایه است ولی بازهم چک می‌کنیم)\r\n const label = this.options?.find(o => o.value === this.selected)?.label;\r\n return label ?? 'انتخاب کنید';\r\n }\r\n\r\n get selectedLabels(): string {\r\n if (this.multiple && Array.isArray(this.selected)) {\r\n if (this.selected.length > this.selectedMaxLength) {\r\n return this.selectedMaxLengthTemplate.replace('{length}', this.selected.length + '')\r\n }\r\n return this.selected.map(x => x[this.optionLabel]).join(this.selectionSeparator);\r\n } else {\r\n return this.selected ? this.selected[this.optionLabel] : '';\r\n }\r\n }\r\n\r\n toggleDropdown() {\r\n this.isOpen = !this.isOpen;\r\n if (this.isOpen) {\r\n this.highlightedIndex = -1;\r\n }\r\n }\r\n\r\n filterOptions(): any[] {\r\n let list = this.options;\r\n if (this.searchable && this.searchTerm.trim()) {\r\n const term = this.searchTerm.toLowerCase();\r\n list = this.options.filter(opt =>\r\n opt[this.optionLabel].toLowerCase().includes(term)\r\n );\r\n }\r\n // هر بار جستجو انجام شد index ریست بشه\r\n this.highlightedIndex = Math.min(this.highlightedIndex, list.length - 1);\r\n return list;\r\n }\r\n\r\n selectOption(option: any) {\r\n if (option.disabled) return;\r\n\r\n if (this.multiple) {\r\n const exists = this.selected?.some((x: any) => x === option);\r\n this.selected = exists\r\n ? this.selected.filter((x: any) => x !== option)\r\n : [...(this.selected || []), option];\r\n } else {\r\n this.selected = option;\r\n this.isOpen = false;\r\n }\r\n\r\n this._onChange(this.selected);\r\n this._onTouched();\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n isSelected(option: any): boolean {\r\n return this.multiple\r\n ? this.selected?.includes(option)\r\n : this.selected === option;\r\n }\r\n\r\n clearSelection() {\r\n this.selected = this.multiple ? [] : null;\r\n this._onChange(this.selected);\r\n this._onTouched();\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent) {\r\n const filtered = this.filterOptions();\r\n if (!filtered.length) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.highlightedIndex = (this.highlightedIndex + 1) % filtered.length;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.highlightedIndex = this.highlightedIndex > 0 ? this.highlightedIndex - 1 : filtered.length - 1;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n if (this.highlightedIndex >= 0 && this.highlightedIndex < filtered.length) {\r\n this.selectOption(filtered[this.highlightedIndex]);\r\n }\r\n break;\r\n case 'Escape':\r\n this.isOpen = false;\r\n break;\r\n }\r\n }\r\n\r\n scrollToHighlighted() {\r\n // تأخیر جزئی برای اطمینان از رندر کامل\r\n setTimeout(() => {\r\n const dropdown = this.elRef.nativeElement.querySelector('.dropdown-menu');\r\n const items = dropdown?.querySelectorAll('.dropdown-item');\r\n const activeItem = items?.[this.highlightedIndex] as HTMLElement;\r\n if (activeItem && dropdown) {\r\n const itemTop = activeItem.offsetTop;\r\n const itemBottom = itemTop + activeItem.offsetHeight;\r\n const dropdownScrollTop = dropdown.scrollTop;\r\n const dropdownHeight = dropdown.clientHeight;\r\n\r\n if (itemBottom > dropdownScrollTop + dropdownHeight) {\r\n dropdown.scrollTop = itemBottom - dropdownHeight;\r\n } else if (itemTop < dropdownScrollTop) {\r\n dropdown.scrollTop = itemTop;\r\n }\r\n }\r\n });\r\n }\r\n\r\n\r\n /** Close by clicking outside */\r\n @HostListener('document:click', ['$event'])\r\n onClickOutside(event: MouseEvent) {\r\n const clickedInside = this.elRef.nativeElement.contains(event.target);\r\n if (!clickedInside) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n}\r\n","<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <span>{{option[optionLabel]}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-dropdown\r\n */\r\n\r\nexport * from './src/ys-dropdown/ys-dropdown.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yoozsoft-yoozsoft-ng-dropdown.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.html","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/yoozsoft-yoozsoft-ng-dropdown.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ElementRef, EventEmitter, forwardRef, HostListener, inject, Input, Output, TemplateRef } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\ninterface ItemTemplate {\r\n raw: any;\r\n label: string;\r\n value: any;\r\n}\r\n\r\n@Component({\r\n selector: 'ys-dropdown',\r\n imports: [NgTemplateOutlet, FormsModule],\r\n templateUrl: './ys-dropdown.component.html',\r\n styleUrl: './ys-dropdown.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsDropdownComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsDropdownComponent implements ControlValueAccessor {\r\n\r\n /** لیست گزینه‌ها */\r\n private _options: any[] = [];\r\n @Input()\r\n set options(value: any[]) { this._options = this.normalizeOptions(value); }\r\n get options() { return this._options; }\r\n\r\n @Input() optionLabel: string = 'label';\r\n @Input() placeholder: string = '';\r\n @Input() searchPlaceholder: string = '';\r\n @Input() selectedMaxLength: number = 3;\r\n @Input() selectedMaxLengthTemplate: string = '{length} items selected';\r\n @Input() selectionSeparator: string = \", \";\r\n\r\n /** انتخاب چندگانه یا تکی */\r\n @Input() multiple: boolean = false;\r\n\r\n @Input() showClear: boolean = false;\r\n\r\n /** تمپلیت سفارشی برای آیتم‌ها */\r\n @Input() itemTemplate?: TemplateRef<any>;\r\n\r\n /** مقدار انتخاب‌شده */\r\n @Input() selected: any[] | any = this.multiple ? [] : null;\r\n\r\n /** قابلیت جستجو */\r\n @Input() searchable: boolean = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** رویداد خروجی هنگام تغییر انتخاب */\r\n @Output() selectionChange = new EventEmitter<any>();\r\n\r\n searchTerm = '';\r\n isOpen = false;\r\n highlightedIndex: number = -1;\r\n\r\n private elRef = inject(ElementRef)\r\n\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n writeValue(obj: any): void {\r\n if (this.multiple) {\r\n this.selected = obj ? [...obj] : [];\r\n } else {\r\n this.selected = obj;\r\n }\r\n }\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n private normalizeOptions(list: any[]): any[] {\r\n if (!Array.isArray(list)) return [];\r\n\r\n return list.map(item => {\r\n\r\n // 1. اگر primitive بود\r\n if (['string', 'number', 'boolean'].includes(typeof item)) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: String(item),\r\n value: item\r\n };\r\n }\r\n\r\n // 2. اگر OptionItem<T> بود\r\n if ('value' in item) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item.label ?? String(item.value),\r\n value: item.value,\r\n ...item\r\n };\r\n }\r\n\r\n // 3. object معمولی\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item[this.optionLabel] ?? JSON.stringify(item),\r\n value: item\r\n };\r\n });\r\n }\r\n\r\n get selectedLabels(): string {\r\n if (this.multiple) {\r\n const items = this.options.filter(o => this.selected?.includes(o.value));\r\n return items.map(o => o.label).join(this.selectionSeparator);\r\n } else {\r\n const item = this.options.find(o => o.value === this.selected);\r\n return item?.label ?? '';\r\n }\r\n }\r\n\r\n toggleDropdown() {\r\n this.isOpen = !this.isOpen;\r\n if (this.isOpen) {\r\n this.highlightedIndex = -1;\r\n }\r\n }\r\n\r\n filterOptions(): any[] {\r\n let list = this.options;\r\n if (this.searchable && this.searchTerm.trim()) {\r\n const term = this.searchTerm.toLowerCase();\r\n list = this.options.filter(opt =>\r\n opt[this.optionLabel].toLowerCase().includes(term)\r\n );\r\n }\r\n // هر بار جستجو انجام شد index ریست بشه\r\n this.highlightedIndex = Math.min(this.highlightedIndex, list.length - 1);\r\n return list;\r\n }\r\n\r\n selectOption(option: any) {\r\n if (option.disabled) return;\r\n\r\n const returnedValue = option.value; // مقدار نهایی برای فرم\r\n\r\n if (this.multiple) {\r\n const exists = this.selected?.some((x: any) => x === returnedValue);\r\n this.selected = exists\r\n ? this.selected.filter((x: any) => x !== returnedValue)\r\n : [...(this.selected || []), returnedValue];\r\n } else {\r\n this.selected = returnedValue;\r\n this.isOpen = false;\r\n }\r\n\r\n this._onChange(this.selected);\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n isSelected(option: any): boolean {\r\n if (this.multiple) {\r\n return Array.isArray(this.selected)\r\n ? this.selected.includes(option.value)\r\n : false;\r\n }\r\n\r\n return this.selected === option.value;\r\n }\r\n\r\n clearSelection() {\r\n this.selected = this.multiple ? [] : null;\r\n this._onChange(this.selected);\r\n this._onTouched();\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent) {\r\n const filtered = this.filterOptions();\r\n if (!filtered.length) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.highlightedIndex = (this.highlightedIndex + 1) % filtered.length;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.highlightedIndex = this.highlightedIndex > 0 ? this.highlightedIndex - 1 : filtered.length - 1;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n if (this.highlightedIndex >= 0 && this.highlightedIndex < filtered.length) {\r\n this.selectOption(filtered[this.highlightedIndex]);\r\n }\r\n break;\r\n case 'Escape':\r\n this.isOpen = false;\r\n break;\r\n }\r\n }\r\n\r\n scrollToHighlighted() {\r\n // تأخیر جزئی برای اطمینان از رندر کامل\r\n setTimeout(() => {\r\n const dropdown = this.elRef.nativeElement.querySelector('.dropdown-menu');\r\n const items = dropdown?.querySelectorAll('.dropdown-item');\r\n const activeItem = items?.[this.highlightedIndex] as HTMLElement;\r\n if (activeItem && dropdown) {\r\n const itemTop = activeItem.offsetTop;\r\n const itemBottom = itemTop + activeItem.offsetHeight;\r\n const dropdownScrollTop = dropdown.scrollTop;\r\n const dropdownHeight = dropdown.clientHeight;\r\n\r\n if (itemBottom > dropdownScrollTop + dropdownHeight) {\r\n dropdown.scrollTop = itemBottom - dropdownHeight;\r\n } else if (itemTop < dropdownScrollTop) {\r\n dropdown.scrollTop = itemTop;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /** Close by clicking outside */\r\n @HostListener('document:click', ['$event'])\r\n onClickOutside(event: MouseEvent) {\r\n const clickedInside = this.elRef.nativeElement.contains(event.target);\r\n if (!clickedInside) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n}\r\n","<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" [disabled]=\"disabled\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"disabled\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\r\n [disabled]=\"disabled\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <!-- <span>{{option[optionLabel]}}</span> -->\r\n <span>{{option.label}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-dropdown\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/ys-dropdown/ys-dropdown.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -104,11 +104,11 @@ class YsSidebarComponent {
104
104
  // }
105
105
  }
106
106
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsSidebarComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component });
107
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsSidebarComponent, isStandalone: true, selector: "ys-sidebar", inputs: { items: "items", profile: "profile", styleClass: "styleClass", itemsStyleClass: "itemsStyleClass" }, ngImport: i0, template: "<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div\r\n class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"item.routerLink\"\r\n [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen}\" data-bs-toggle=\"dropend\"\r\n role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\"\r\n role=\"button\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>", styles: ["@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.transition-ease{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar{height:100%;width:300px;position:absolute;top:0;left:0;z-index:1000}.sidebar .sidebar-profile .user-image{width:75px;height:75px;overflow:hidden}.sidebar .sidebar-profile .profile-details{-webkit-animation:fadeIn 1.5s;animation:fadeIn 1.5s}.sidebar .sidebar-profile .profile-details .role{font-size:.7rem;letter-spacing:1px}.sidebar .sidebar-menu .dropdown-toggle:after{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar .sidebar-menu .dropdown-toggle.toggled:after{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sidebar .sidebar-menu .nav-sub-items{display:none;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}.sidebar .sidebar-menu .nav-sub-items .nav-link{height:3em;line-height:3em;font-size:11px}.show{display:block!important}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
107
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsSidebarComponent, isStandalone: true, selector: "ys-sidebar", inputs: { items: "items", profile: "profile", styleClass: "styleClass", itemsStyleClass: "itemsStyleClass" }, ngImport: i0, template: "<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [ngClass]=\"{'disabled': item.disabled}\"\r\n [routerLink]=\"item.routerLink\" [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen, 'disabled': item.disabled}\"\r\n data-bs-toggle=\"dropend\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\" role=\"button\"\r\n [ngClass]=\"{'disabled': subItem.disabled}\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>", styles: ["@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.transition-ease{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar{height:100%;width:300px;position:absolute;top:0;left:0;z-index:1000}.sidebar .sidebar-profile .user-image{width:75px;height:75px;overflow:hidden}.sidebar .sidebar-profile .profile-details{-webkit-animation:fadeIn 1.5s;animation:fadeIn 1.5s}.sidebar .sidebar-profile .profile-details .role{font-size:.7rem;letter-spacing:1px}.sidebar .sidebar-menu .dropdown-toggle:after{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar .sidebar-menu .dropdown-toggle.toggled:after{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sidebar .sidebar-menu .nav-sub-items{display:none;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}.sidebar .sidebar-menu .nav-sub-items .nav-link{height:3em;line-height:3em;font-size:11px}.show{display:block!important}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }] });
108
108
  }
109
109
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsSidebarComponent, decorators: [{
110
110
  type: Component,
111
- args: [{ selector: 'ys-sidebar', imports: [NgClass, RouterLink, RouterLinkActive], template: "<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div\r\n class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"item.routerLink\"\r\n [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen}\" data-bs-toggle=\"dropend\"\r\n role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\"\r\n role=\"button\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>", styles: ["@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.transition-ease{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar{height:100%;width:300px;position:absolute;top:0;left:0;z-index:1000}.sidebar .sidebar-profile .user-image{width:75px;height:75px;overflow:hidden}.sidebar .sidebar-profile .profile-details{-webkit-animation:fadeIn 1.5s;animation:fadeIn 1.5s}.sidebar .sidebar-profile .profile-details .role{font-size:.7rem;letter-spacing:1px}.sidebar .sidebar-menu .dropdown-toggle:after{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar .sidebar-menu .dropdown-toggle.toggled:after{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sidebar .sidebar-menu .nav-sub-items{display:none;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}.sidebar .sidebar-menu .nav-sub-items .nav-link{height:3em;line-height:3em;font-size:11px}.show{display:block!important}\n"] }]
111
+ args: [{ selector: 'ys-sidebar', imports: [NgClass, RouterLink, RouterLinkActive], template: "<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [ngClass]=\"{'disabled': item.disabled}\"\r\n [routerLink]=\"item.routerLink\" [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen, 'disabled': item.disabled}\"\r\n data-bs-toggle=\"dropend\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\" role=\"button\"\r\n [ngClass]=\"{'disabled': subItem.disabled}\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>", styles: ["@-webkit-keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.transition-ease{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar{height:100%;width:300px;position:absolute;top:0;left:0;z-index:1000}.sidebar .sidebar-profile .user-image{width:75px;height:75px;overflow:hidden}.sidebar .sidebar-profile .profile-details{-webkit-animation:fadeIn 1.5s;animation:fadeIn 1.5s}.sidebar .sidebar-profile .profile-details .role{font-size:.7rem;letter-spacing:1px}.sidebar .sidebar-menu .dropdown-toggle:after{-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.sidebar .sidebar-menu .dropdown-toggle.toggled:after{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.sidebar .sidebar-menu .nav-sub-items{display:none;-webkit-animation:fadeIn 1s;animation:fadeIn 1s}.sidebar .sidebar-menu .nav-sub-items .nav-link{height:3em;line-height:3em;font-size:11px}.show{display:block!important}\n"] }]
112
112
  }], ctorParameters: () => [{ type: i1.Router }], propDecorators: { items: [{
113
113
  type: Input
114
114
  }], profile: [{
@@ -1 +1 @@
1
- {"version":3,"file":"yoozsoft-yoozsoft-ng-sidebar.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/services/sidebar.service.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/ys-sidebar/ys-sidebar.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/ys-sidebar/ys-sidebar.component.html","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/yoozsoft-yoozsoft-ng-sidebar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class SidebarService {\r\n\r\n constructor() { }\r\n\r\n private _isSidebarToggled$ = new BehaviorSubject<boolean>(true);\r\n\r\n private _isSidebar$ = new BehaviorSubject<boolean>(false);\r\n\r\n /**\r\n * Sidebar toggled state. Default value is true.\r\n */\r\n get isSidebarToggled$() { return this._isSidebarToggled$.asObservable(); }\r\n\r\n /**\r\n * Sidebar display state. Default value is false.\r\n */\r\n get isSidebar$() { return this._isSidebar$.asObservable(); }\r\n\r\n /**\r\n * Change sidebar toggle state.\r\n */\r\n toggleSidebar() {\r\n this._isSidebarToggled$.next(!this._isSidebarToggled$.value);\r\n }\r\n\r\n /**\r\n * Set sidebar toggle state.\r\n * @param isToggled \r\n */\r\n setIsSidebarToggled(isToggled: boolean) {\r\n this._isSidebarToggled$.next(isToggled);\r\n }\r\n\r\n /**\r\n * Set sidebar toggle state.\r\n * @param isSidebar \r\n */\r\n setIsSidebar(isSidebar: boolean) {\r\n this._isSidebar$.next(isSidebar);\r\n }\r\n\r\n /**\r\n * Return sidebar toggle state.\r\n */\r\n get sidebarState() {\r\n return this._isSidebarToggled$.getValue()\r\n }\r\n\r\n}\r\n","import { NgClass } from '@angular/common';\r\nimport { Component, Input, OnDestroy } from '@angular/core';\r\nimport { NavigationEnd, Router, RouterLink, RouterLinkActive } from '@angular/router';\r\nimport { Subscription } from 'rxjs';\r\nimport { SidebarItem, SidebarItemActive, UserProfile } from '../models';\r\n\r\n@Component({\r\n selector: 'ys-sidebar',\r\n imports: [NgClass, RouterLink, RouterLinkActive],\r\n templateUrl: './ys-sidebar.component.html',\r\n styleUrl: './ys-sidebar.component.scss'\r\n})\r\nexport class YsSidebarComponent implements OnDestroy {\r\n\r\n private subscription: Subscription;\r\n private currentItem?: SidebarItemActive;\r\n private currentItemState: boolean[] = [];\r\n\r\n private _items: SidebarItemActive[] = [];\r\n @Input()\r\n get items(): SidebarItemActive[] { return this._items };\r\n set items(value: SidebarItem[]) { this._items = value; }\r\n\r\n @Input() profile: UserProfile | null = null;\r\n @Input() styleClass?: string;\r\n @Input() itemsStyleClass?: string;\r\n\r\n constructor(private router: Router) {\r\n this.subscription = router.events.subscribe(e => {\r\n if (e instanceof NavigationEnd) {\r\n this.currentItem = undefined;\r\n this.currentItemState = [];\r\n }\r\n })\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n get fullName(): string { return `${this.profile?.firstName} ${this.profile?.lastName}`; }\r\n\r\n openItem(item: SidebarItemActive): void {\r\n if (item.isOpen) {\r\n item.isOpen = !item.isOpen;\r\n return;\r\n }\r\n\r\n this.items.forEach(x => x.isOpen = false);\r\n item.isOpen = !item.isOpen;\r\n }\r\n\r\n isDropdown(item: SidebarItem): boolean {\r\n return (item.items?.length ?? 0) > 0;\r\n }\r\n\r\n onRouterLinkActive(isActive: boolean, item: SidebarItemActive) {\r\n this.currentItemState.push(isActive);\r\n\r\n if (!isActive && this.currentItem == item) {\r\n if (this.currentItemState.length == 2 && this.currentItemState[0] && !this.currentItemState[1]) {\r\n return;\r\n }\r\n }\r\n\r\n this.currentItem = item;\r\n item.isActive = isActive;\r\n // if (isActive) {\r\n // this.items.forEach(x => x.isOpen = false);\r\n // item.isOpen = true;\r\n // }\r\n }\r\n\r\n}\r\n","<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div\r\n class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"item.routerLink\"\r\n [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen}\" data-bs-toggle=\"dropend\"\r\n role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\"\r\n [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\"\r\n role=\"button\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\"\r\n [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>","/*\r\n * Public API Surface of ys-sidebar\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/services';\r\nexport * from './src/ys-sidebar/ys-sidebar.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yoozsoft-yoozsoft-ng-sidebar.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/services/sidebar.service.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/ys-sidebar/ys-sidebar.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/src/ys-sidebar/ys-sidebar.component.html","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/sidebar/yoozsoft-yoozsoft-ng-sidebar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { BehaviorSubject } from 'rxjs';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class SidebarService {\r\n\r\n constructor() { }\r\n\r\n private _isSidebarToggled$ = new BehaviorSubject<boolean>(true);\r\n\r\n private _isSidebar$ = new BehaviorSubject<boolean>(false);\r\n\r\n /**\r\n * Sidebar toggled state. Default value is true.\r\n */\r\n get isSidebarToggled$() { return this._isSidebarToggled$.asObservable(); }\r\n\r\n /**\r\n * Sidebar display state. Default value is false.\r\n */\r\n get isSidebar$() { return this._isSidebar$.asObservable(); }\r\n\r\n /**\r\n * Change sidebar toggle state.\r\n */\r\n toggleSidebar() {\r\n this._isSidebarToggled$.next(!this._isSidebarToggled$.value);\r\n }\r\n\r\n /**\r\n * Set sidebar toggle state.\r\n * @param isToggled \r\n */\r\n setIsSidebarToggled(isToggled: boolean) {\r\n this._isSidebarToggled$.next(isToggled);\r\n }\r\n\r\n /**\r\n * Set sidebar toggle state.\r\n * @param isSidebar \r\n */\r\n setIsSidebar(isSidebar: boolean) {\r\n this._isSidebar$.next(isSidebar);\r\n }\r\n\r\n /**\r\n * Return sidebar toggle state.\r\n */\r\n get sidebarState() {\r\n return this._isSidebarToggled$.getValue()\r\n }\r\n\r\n}\r\n","import { NgClass } from '@angular/common';\r\nimport { Component, Input, OnDestroy } from '@angular/core';\r\nimport { NavigationEnd, Router, RouterLink, RouterLinkActive } from '@angular/router';\r\nimport { Subscription } from 'rxjs';\r\nimport { SidebarItem, SidebarItemActive, UserProfile } from '../models';\r\n\r\n@Component({\r\n selector: 'ys-sidebar',\r\n imports: [NgClass, RouterLink, RouterLinkActive],\r\n templateUrl: './ys-sidebar.component.html',\r\n styleUrl: './ys-sidebar.component.scss'\r\n})\r\nexport class YsSidebarComponent implements OnDestroy {\r\n\r\n private subscription: Subscription;\r\n private currentItem?: SidebarItemActive;\r\n private currentItemState: boolean[] = [];\r\n\r\n private _items: SidebarItemActive[] = [];\r\n @Input()\r\n get items(): SidebarItemActive[] { return this._items };\r\n set items(value: SidebarItem[]) { this._items = value; }\r\n\r\n @Input() profile: UserProfile | null = null;\r\n @Input() styleClass?: string;\r\n @Input() itemsStyleClass?: string;\r\n\r\n constructor(private router: Router) {\r\n this.subscription = router.events.subscribe(e => {\r\n if (e instanceof NavigationEnd) {\r\n this.currentItem = undefined;\r\n this.currentItemState = [];\r\n }\r\n })\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subscription.unsubscribe();\r\n }\r\n\r\n get fullName(): string { return `${this.profile?.firstName} ${this.profile?.lastName}`; }\r\n\r\n openItem(item: SidebarItemActive): void {\r\n if (item.isOpen) {\r\n item.isOpen = !item.isOpen;\r\n return;\r\n }\r\n\r\n this.items.forEach(x => x.isOpen = false);\r\n item.isOpen = !item.isOpen;\r\n }\r\n\r\n isDropdown(item: SidebarItem): boolean {\r\n return (item.items?.length ?? 0) > 0;\r\n }\r\n\r\n onRouterLinkActive(isActive: boolean, item: SidebarItemActive) {\r\n this.currentItemState.push(isActive);\r\n\r\n if (!isActive && this.currentItem == item) {\r\n if (this.currentItemState.length == 2 && this.currentItemState[0] && !this.currentItemState[1]) {\r\n return;\r\n }\r\n }\r\n\r\n this.currentItem = item;\r\n item.isActive = isActive;\r\n // if (isActive) {\r\n // this.items.forEach(x => x.isOpen = false);\r\n // item.isOpen = true;\r\n // }\r\n }\r\n\r\n}\r\n","<aside class=\"sidebar card overflow-auto shadow-sm transition-ease\" [ngClass]=\"styleClass\">\r\n @if (profile) {\r\n <div>\r\n @if (profile.image || fullName || profile.role) {\r\n <div class=\"sidebar-profile d-flex flex-column justify-content-center pt-3\">\r\n @if (profile.image) {\r\n <div class=\"image-wrapper\" [ngClass]=\"{'mb-3': fullName || profile.role}\">\r\n <div class=\"user-image rounded-circle m-auto transition-ease\">\r\n <img src=\"{{profile.image.src}}\" class=\"img-fluid\" alt=\"{{profile.image.alt}}\">\r\n </div>\r\n </div>\r\n }\r\n @if (fullName || profile.role) {\r\n <div class=\"profile-details d-flex flex-column text-center transition-ease\">\r\n @if (fullName) {\r\n <strong class=\"text-uppercase name\">{{fullName || ''}}</strong>\r\n }\r\n @if (profile.role) {\r\n <small class=\"text-uppercase role\">{{profile.role}}</small>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <hr />\r\n </div>\r\n }\r\n\r\n <div class=\"sidebar-menu\" [ngClass]=\"{'pt-2': !profile}\">\r\n <ul class=\"sidebar-items nav nav-pills flex-column mx-2\" [ngClass]=\"itemsStyleClass\">\r\n @for (item of items; track item) {\r\n @if (item.isDivider) {\r\n <hr class=\"sidebar-divider\" />\r\n }\r\n @if (!item.isDivider) {\r\n @if (!isDropdown(item)) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [ngClass]=\"{'disabled': item.disabled}\"\r\n [routerLink]=\"item.routerLink\" [routerLinkActive]=\"['active']\" role=\"button\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n @if (isDropdown(item)) {\r\n <li class=\"nav-item d-block dropend\">\r\n <a class=\"nav-link d-flex align-items-center dropdown-toggle\"\r\n [ngClass]=\"{'active': item.isActive , 'toggled': item.isOpen, 'disabled': item.disabled}\"\r\n data-bs-toggle=\"dropend\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\"\r\n (click)=\"openItem(item); item.onClick && item.onClick($event)\">\r\n @if (item.iconClass) {\r\n <i [ngClass]=\"item.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{item.label}}</span>\r\n @if (item.badgeLabel) {\r\n <span class=\"badge bg-info me-1\" [ngClass]=\"item.badgeStyleClass\">{{item.badgeLabel}}</span>\r\n }\r\n </a>\r\n <ul class=\"nav-sub-items nav nav-pills flex-column rounded shadow-sm mb-2 mx-2\"\r\n [ngClass]=\"{'show': item.isOpen}\">\r\n @for (subItem of item.items; track subItem) {\r\n @if (subItem.isDivider) {\r\n <hr class=\"sidebar-divider my-1\" />\r\n }\r\n @if (!subItem.isDivider) {\r\n <li class=\"nav-item d-block\">\r\n <a class=\"nav-link d-flex align-items-center\" [routerLink]=\"subItem.routerLink\" role=\"button\"\r\n [ngClass]=\"{'disabled': subItem.disabled}\" [routerLinkActive]=\"['active']\"\r\n (isActiveChange)=\"this.onRouterLinkActive($event, item)\"\r\n (click)=\"subItem.onClick && subItem.onClick($event)\">\r\n @if (subItem.iconClass) {\r\n <i [ngClass]=\"subItem.iconClass\"></i>\r\n }\r\n <span class=\"link-label ms-3 me-auto\">{{subItem.label}}</span>\r\n @if (subItem.badgeLabel) {\r\n <span class=\"badge bg-info\" [ngClass]=\"subItem.badgeStyleClass\">{{subItem.badgeLabel}}</span>\r\n }\r\n </a>\r\n </li>\r\n }\r\n }\r\n </ul>\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n </div>\r\n</aside>","/*\r\n * Public API Surface of ys-sidebar\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/services';\r\nexport * from './src/ys-sidebar/ys-sidebar.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -27,6 +27,7 @@ class YsTiffViewerComponent {
27
27
  styleClass;
28
28
  /**Message displayed before filling the input buffer */
29
29
  noFileMessage = "No image file";
30
+ noFileStyleClass;
30
31
  /**First button icon class */
31
32
  firstIconClass = 'fa fa-fast-backward';
32
33
  /**Previous button icon class */
@@ -101,11 +102,11 @@ class YsTiffViewerComponent {
101
102
  this.putImage(this.currentIFDIndex);
102
103
  }
103
104
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsTiffViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
104
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsTiffViewerComponent, isStandalone: true, selector: "ys-tiff-viewer", inputs: { buffer: "buffer", currentPageReportTemplate: "currentPageReportTemplate", styleClass: "styleClass", noFileMessage: "noFileMessage", firstIconClass: "firstIconClass", previousIconClass: "previousIconClass", nextIconClass: "nextIconClass", lastIconClass: "lastIconClass" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["tiffCanvas"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span>{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
105
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsTiffViewerComponent, isStandalone: true, selector: "ys-tiff-viewer", inputs: { buffer: "buffer", currentPageReportTemplate: "currentPageReportTemplate", styleClass: "styleClass", noFileMessage: "noFileMessage", noFileStyleClass: "noFileStyleClass", firstIconClass: "firstIconClass", previousIconClass: "previousIconClass", nextIconClass: "nextIconClass", lastIconClass: "lastIconClass" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["tiffCanvas"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
105
106
  }
106
107
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsTiffViewerComponent, decorators: [{
107
108
  type: Component,
108
- args: [{ selector: 'ys-tiff-viewer', imports: [NgClass], template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span>{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"] }]
109
+ args: [{ selector: 'ys-tiff-viewer', imports: [NgClass], template: "<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: [".backdrop{background-color:rgba(var(--bs-dark-rgb),.3)}\n"] }]
109
110
  }], propDecorators: { canvasRef: [{
110
111
  type: ViewChild,
111
112
  args: ['tiffCanvas', { static: true }]
@@ -117,6 +118,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
117
118
  type: Input
118
119
  }], noFileMessage: [{
119
120
  type: Input
121
+ }], noFileStyleClass: [{
122
+ type: Input
120
123
  }], firstIconClass: [{
121
124
  type: Input
122
125
  }], previousIconClass: [{
@@ -1 +1 @@
1
- {"version":3,"file":"yoozsoft-yoozsoft-ng-tiff-viewer.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.html","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/yoozsoft-yoozsoft-ng-tiff-viewer.ts"],"sourcesContent":["import { NgClass } from '@angular/common';\r\nimport { Component, ElementRef, Input, ViewChild } from '@angular/core';\r\n\r\ndeclare var UTIF: any;\r\n\r\n@Component({\r\n selector: 'ys-tiff-viewer',\r\n imports: [NgClass],\r\n templateUrl: './ys-tiff-viewer.component.html',\r\n styleUrl: './ys-tiff-viewer.component.scss'\r\n})\r\nexport class YsTiffViewerComponent {\r\n\r\n @ViewChild('tiffCanvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;\r\n\r\n private canvas: any;\r\n private context: any;\r\n /**image file directories */\r\n private IFDs: any[] = [];\r\n private currentIFDIndex: number = 0;\r\n isDecoding: boolean = false;\r\n\r\n private _buffer: ArrayBuffer | File | Blob | null | undefined;\r\n /**Uint8Array source */\r\n /**ArrayBuffer containing TIFF or EXIF data */\r\n @Input()\r\n get buffer(): ArrayBuffer | File | Blob | null | undefined { return this._buffer; }\r\n set buffer(value: ArrayBuffer | File | Blob | null | undefined) { this._buffer = value; this.convertSource(this._buffer); }\r\n\r\n _currentPageReportTemplate?: string = \"Page {current} of {total}\";\r\n /**Current page report template */\r\n @Input()\r\n get currentPageReportTemplate(): string | undefined {\r\n return this._currentPageReportTemplate?.\r\n replace('{current}', `<strong>${this.currentIFDIndex + 1}</strong>`).\r\n replace('{total}', `<strong>${this.IFDs.length}</strong>`);\r\n }\r\n set currentPageReportTemplate(value: string | undefined) { this._currentPageReportTemplate = value; }\r\n\r\n /**Canvas container style class */\r\n @Input() styleClass?: string;\r\n /**Message displayed before filling the input buffer */\r\n @Input() noFileMessage?: string = \"No image file\";\r\n\r\n /**First button icon class */\r\n @Input() firstIconClass: string = 'fa fa-fast-backward';\r\n /**Previous button icon class */\r\n @Input() previousIconClass: string = 'fa fa-step-backward';\r\n /**Next button icon class */\r\n @Input() nextIconClass: string = 'fa fa-step-forward';\r\n /**Last button icon class */\r\n @Input() lastIconClass: string = 'fa fa-fast-forward';\r\n\r\n get isIFDs(): boolean { return this.IFDs.length > 0; }\r\n get isFirstImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == 0); }\r\n get isLastImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == this.IFDs.length - 1); }\r\n\r\n /**\r\n * Convert buffer to an array of \"IFDs\" (image file directories)\r\n * @param buffer ArrayBuffer containing TIFF or EXIF data\r\n * @returns \r\n */\r\n async convertSource(buffer: ArrayBuffer | File | Blob | null | undefined): Promise<void> {\r\n this.canvas = this.canvasRef.nativeElement;\r\n this.context = this.canvas.getContext(\"2d\");\r\n this.IFDs = [];\r\n this.currentIFDIndex = 0;\r\n\r\n if (!buffer) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n if (buffer instanceof File || buffer instanceof Blob) {\r\n // buffer = await this.getAsByteArray(buffer);\r\n buffer = await buffer.arrayBuffer();\r\n }\r\n\r\n this.isDecoding = true;\r\n\r\n this.IFDs = UTIF.decode(buffer as ArrayBuffer);\r\n this.IFDs.forEach((ifd: any) => UTIF.decodeImage(buffer as ArrayBuffer, ifd));\r\n\r\n this.putImage(this.currentIFDIndex);\r\n this.isDecoding = false;\r\n }\r\n\r\n putImage(index: number): void {\r\n if (!this.IFDs.length) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n const tiffImage = this.IFDs[index];\r\n const rgbaImage = UTIF.toRGBA8(tiffImage); // Uint8Array with RGBA pixels\r\n\r\n const data = new Uint8ClampedArray(rgbaImage);\r\n const imageData = new ImageData(data, tiffImage.width, tiffImage.height);\r\n\r\n this.context.canvas.width = tiffImage.width;\r\n this.context.canvas.height = tiffImage.height;\r\n // Draw image data to the canvas\r\n this.context.putImageData(imageData, 0, 0);\r\n }\r\n\r\n\r\n first(): void {\r\n this.currentIFDIndex = 0;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n previous(): void {\r\n this.currentIFDIndex -= 1;\r\n if (this.currentIFDIndex < 0) {\r\n this.currentIFDIndex = 0;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n next(): void {\r\n this.currentIFDIndex += 1;\r\n if (this.currentIFDIndex > (this.IFDs.length - 1)) {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n last(): void {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n // async getAsByteArray(blob: Blob): Promise<ArrayBuffer> {\r\n // return new Promise((resolve, reject) => {\r\n // const reader = new FileReader();\r\n // reader.onload = () => resolve(reader.result as ArrayBuffer);\r\n // reader.onerror = reject;\r\n // reader.readAsArrayBuffer(blob);\r\n // });\r\n // }\r\n\r\n}\r\n","<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span>{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-sidebar\r\n */\r\n\r\nexport * from './src/ys-tiff-viewer/ys-tiff-viewer.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"yoozsoft-yoozsoft-ng-tiff-viewer.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/src/ys-tiff-viewer/ys-tiff-viewer.component.html","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/tiff-viewer/yoozsoft-yoozsoft-ng-tiff-viewer.ts"],"sourcesContent":["import { NgClass } from '@angular/common';\r\nimport { Component, ElementRef, Input, ViewChild } from '@angular/core';\r\n\r\ndeclare var UTIF: any;\r\n\r\n@Component({\r\n selector: 'ys-tiff-viewer',\r\n imports: [NgClass],\r\n templateUrl: './ys-tiff-viewer.component.html',\r\n styleUrl: './ys-tiff-viewer.component.scss'\r\n})\r\nexport class YsTiffViewerComponent {\r\n\r\n @ViewChild('tiffCanvas', { static: true }) canvasRef!: ElementRef<HTMLCanvasElement>;\r\n\r\n private canvas: any;\r\n private context: any;\r\n /**image file directories */\r\n private IFDs: any[] = [];\r\n private currentIFDIndex: number = 0;\r\n isDecoding: boolean = false;\r\n\r\n private _buffer: ArrayBuffer | File | Blob | null | undefined;\r\n /**Uint8Array source */\r\n /**ArrayBuffer containing TIFF or EXIF data */\r\n @Input()\r\n get buffer(): ArrayBuffer | File | Blob | null | undefined { return this._buffer; }\r\n set buffer(value: ArrayBuffer | File | Blob | null | undefined) { this._buffer = value; this.convertSource(this._buffer); }\r\n\r\n _currentPageReportTemplate?: string = \"Page {current} of {total}\";\r\n /**Current page report template */\r\n @Input()\r\n get currentPageReportTemplate(): string | undefined {\r\n return this._currentPageReportTemplate?.\r\n replace('{current}', `<strong>${this.currentIFDIndex + 1}</strong>`).\r\n replace('{total}', `<strong>${this.IFDs.length}</strong>`);\r\n }\r\n set currentPageReportTemplate(value: string | undefined) { this._currentPageReportTemplate = value; }\r\n\r\n /**Canvas container style class */\r\n @Input() styleClass?: string;\r\n /**Message displayed before filling the input buffer */\r\n @Input() noFileMessage?: string = \"No image file\";\r\n @Input() noFileStyleClass?: string;\r\n\r\n /**First button icon class */\r\n @Input() firstIconClass: string = 'fa fa-fast-backward';\r\n /**Previous button icon class */\r\n @Input() previousIconClass: string = 'fa fa-step-backward';\r\n /**Next button icon class */\r\n @Input() nextIconClass: string = 'fa fa-step-forward';\r\n /**Last button icon class */\r\n @Input() lastIconClass: string = 'fa fa-fast-forward';\r\n\r\n get isIFDs(): boolean { return this.IFDs.length > 0; }\r\n get isFirstImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == 0); }\r\n get isLastImage(): boolean { return !this.isIFDs || (this.currentIFDIndex == this.IFDs.length - 1); }\r\n\r\n /**\r\n * Convert buffer to an array of \"IFDs\" (image file directories)\r\n * @param buffer ArrayBuffer containing TIFF or EXIF data\r\n * @returns \r\n */\r\n async convertSource(buffer: ArrayBuffer | File | Blob | null | undefined): Promise<void> {\r\n this.canvas = this.canvasRef.nativeElement;\r\n this.context = this.canvas.getContext(\"2d\");\r\n this.IFDs = [];\r\n this.currentIFDIndex = 0;\r\n\r\n if (!buffer) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n if (buffer instanceof File || buffer instanceof Blob) {\r\n // buffer = await this.getAsByteArray(buffer);\r\n buffer = await buffer.arrayBuffer();\r\n }\r\n\r\n this.isDecoding = true;\r\n\r\n this.IFDs = UTIF.decode(buffer as ArrayBuffer);\r\n this.IFDs.forEach((ifd: any) => UTIF.decodeImage(buffer as ArrayBuffer, ifd));\r\n\r\n this.putImage(this.currentIFDIndex);\r\n this.isDecoding = false;\r\n }\r\n\r\n putImage(index: number): void {\r\n if (!this.IFDs.length) {\r\n this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);\r\n return;\r\n }\r\n\r\n const tiffImage = this.IFDs[index];\r\n const rgbaImage = UTIF.toRGBA8(tiffImage); // Uint8Array with RGBA pixels\r\n\r\n const data = new Uint8ClampedArray(rgbaImage);\r\n const imageData = new ImageData(data, tiffImage.width, tiffImage.height);\r\n\r\n this.context.canvas.width = tiffImage.width;\r\n this.context.canvas.height = tiffImage.height;\r\n // Draw image data to the canvas\r\n this.context.putImageData(imageData, 0, 0);\r\n }\r\n\r\n\r\n first(): void {\r\n this.currentIFDIndex = 0;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n previous(): void {\r\n this.currentIFDIndex -= 1;\r\n if (this.currentIFDIndex < 0) {\r\n this.currentIFDIndex = 0;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n next(): void {\r\n this.currentIFDIndex += 1;\r\n if (this.currentIFDIndex > (this.IFDs.length - 1)) {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n return;\r\n }\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n last(): void {\r\n this.currentIFDIndex = this.IFDs.length - 1;\r\n this.putImage(this.currentIFDIndex);\r\n }\r\n\r\n // async getAsByteArray(blob: Blob): Promise<ArrayBuffer> {\r\n // return new Promise((resolve, reject) => {\r\n // const reader = new FileReader();\r\n // reader.onload = () => resolve(reader.result as ArrayBuffer);\r\n // reader.onerror = reject;\r\n // reader.readAsArrayBuffer(blob);\r\n // });\r\n // }\r\n\r\n}\r\n","<div class=\"row\">\r\n <div class=\"col d-flex justify-content-between align-items-center\">\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" [ngClass]=\"{'ml-auto': isIFDs}\" type=\"button\" (click)=\"first()\"\r\n [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"firstIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" type=\"button\" (click)=\"previous()\" [disabled]=\"isFirstImage\">\r\n <i [ngClass]=\"previousIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n @if (isIFDs) {\r\n <span [innerHtml]=\"currentPageReportTemplate\">\r\n </span>\r\n }\r\n\r\n <div>\r\n <button class=\"btn btn-outline-primary mb-0 me-2\" type=\"button\" (click)=\"next()\" [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"nextIconClass\"></i>\r\n </button>\r\n <button class=\"btn btn-outline-primary mb-0\" [ngClass]=\"{'mr-auto': isIFDs}\" type=\"button\" (click)=\"last()\"\r\n [disabled]=\"isLastImage\">\r\n <i [ngClass]=\"lastIconClass\"></i>\r\n </button>\r\n </div>\r\n\r\n\r\n </div>\r\n</div>\r\n<div class=\"row\">\r\n <div class=\"col\">\r\n <div class=\"canvas-container card d-flex justify-content-center align-items-center mt-1 {{styleClass}}\">\r\n @if (!isIFDs && noFileMessage) {\r\n <span class=\"my-4\" [ngClass]=\"noFileStyleClass\">{{noFileMessage}}</span>\r\n }\r\n <canvas #tiffCanvas class=\"canvas-image img-fluid\" [ngClass]=\"{'d-none': !isIFDs}\"></canvas>\r\n <div class=\"backdrop position-absolute w-100 h-100 d-flex justify-content-center align-items-center\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n\r\n </div>\r\n <div class=\"spinner-border text-info position-absolute\" style=\"width: 3rem; height: 3rem;\" role=\"status\"\r\n [ngClass]=\"{'d-none': !isDecoding}\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-sidebar\r\n */\r\n\r\nexport * from './src/ys-tiff-viewer/ys-tiff-viewer.component';\r\n\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yoozsoft/yoozsoft-ng",
3
- "version": "5.3.2",
3
+ "version": "5.3.4",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.0.0",
6
6
  "@angular/core": "^20.0.0"
@@ -46,30 +46,34 @@
46
46
  "types": "./datepicker/index.d.ts",
47
47
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs"
48
48
  },
49
- "./file-upload": {
50
- "types": "./file-upload/index.d.ts",
51
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs"
49
+ "./directives": {
50
+ "types": "./directives/index.d.ts",
51
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-directives.mjs"
52
+ },
53
+ "./dropdown": {
54
+ "types": "./dropdown/index.d.ts",
55
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs"
52
56
  },
53
57
  "./footer": {
54
58
  "types": "./footer/index.d.ts",
55
59
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-footer.mjs"
56
60
  },
57
- "./loading": {
58
- "types": "./loading/index.d.ts",
59
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-loading.mjs"
60
- },
61
- "./directives": {
62
- "types": "./directives/index.d.ts",
63
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-directives.mjs"
64
- },
65
61
  "./navbar": {
66
62
  "types": "./navbar/index.d.ts",
67
63
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs"
68
64
  },
65
+ "./loading": {
66
+ "types": "./loading/index.d.ts",
67
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-loading.mjs"
68
+ },
69
69
  "./overlay": {
70
70
  "types": "./overlay/index.d.ts",
71
71
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs"
72
72
  },
73
+ "./pagination": {
74
+ "types": "./pagination/index.d.ts",
75
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs"
76
+ },
73
77
  "./password-strength": {
74
78
  "types": "./password-strength/index.d.ts",
75
79
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs"
@@ -78,13 +82,9 @@
78
82
  "types": "./progress/index.d.ts",
79
83
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-progress.mjs"
80
84
  },
81
- "./dropdown": {
82
- "types": "./dropdown/index.d.ts",
83
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs"
84
- },
85
- "./pagination": {
86
- "types": "./pagination/index.d.ts",
87
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs"
85
+ "./sidebar": {
86
+ "types": "./sidebar/index.d.ts",
87
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs"
88
88
  },
89
89
  "./select": {
90
90
  "types": "./select/index.d.ts",
@@ -94,9 +94,9 @@
94
94
  "types": "./tiff-viewer/index.d.ts",
95
95
  "default": "./fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs"
96
96
  },
97
- "./sidebar": {
98
- "types": "./sidebar/index.d.ts",
99
- "default": "./fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs"
97
+ "./file-upload": {
98
+ "types": "./file-upload/index.d.ts",
99
+ "default": "./fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs"
100
100
  },
101
101
  "./toast": {
102
102
  "types": "./toast/index.d.ts",
@@ -14,6 +14,7 @@ interface SidebarItem {
14
14
  data?: any;
15
15
  onClick?: (event?: any) => void;
16
16
  isDivider?: boolean;
17
+ disabled?: boolean;
17
18
  }
18
19
 
19
20
  interface SidebarItemActive extends SidebarItem {
@@ -22,6 +22,7 @@ declare class YsTiffViewerComponent {
22
22
  styleClass?: string;
23
23
  /**Message displayed before filling the input buffer */
24
24
  noFileMessage?: string;
25
+ noFileStyleClass?: string;
25
26
  /**First button icon class */
26
27
  firstIconClass: string;
27
28
  /**Previous button icon class */
@@ -45,7 +46,7 @@ declare class YsTiffViewerComponent {
45
46
  next(): void;
46
47
  last(): void;
47
48
  static ɵfac: i0.ɵɵFactoryDeclaration<YsTiffViewerComponent, never>;
48
- static ɵcmp: i0.ɵɵComponentDeclaration<YsTiffViewerComponent, "ys-tiff-viewer", never, { "buffer": { "alias": "buffer"; "required": false; }; "currentPageReportTemplate": { "alias": "currentPageReportTemplate"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "noFileMessage": { "alias": "noFileMessage"; "required": false; }; "firstIconClass": { "alias": "firstIconClass"; "required": false; }; "previousIconClass": { "alias": "previousIconClass"; "required": false; }; "nextIconClass": { "alias": "nextIconClass"; "required": false; }; "lastIconClass": { "alias": "lastIconClass"; "required": false; }; }, {}, never, never, true, never>;
49
+ static ɵcmp: i0.ɵɵComponentDeclaration<YsTiffViewerComponent, "ys-tiff-viewer", never, { "buffer": { "alias": "buffer"; "required": false; }; "currentPageReportTemplate": { "alias": "currentPageReportTemplate"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "noFileMessage": { "alias": "noFileMessage"; "required": false; }; "noFileStyleClass": { "alias": "noFileStyleClass"; "required": false; }; "firstIconClass": { "alias": "firstIconClass"; "required": false; }; "previousIconClass": { "alias": "previousIconClass"; "required": false; }; "nextIconClass": { "alias": "nextIconClass"; "required": false; }; "lastIconClass": { "alias": "lastIconClass"; "required": false; }; }, {}, never, never, true, never>;
49
50
  }
50
51
 
51
52
  export { YsTiffViewerComponent };