@yoozsoft/yoozsoft-ng 6.0.4 → 6.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs +142 -112
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs +111 -92
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs +6 -3
- package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs +2 -2
- package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs +17 -13
- package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs +6 -3
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs +316 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs +104 -97
- package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs +96 -48
- package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs.map +1 -1
- package/package.json +5 -1
- package/types/yoozsoft-yoozsoft-ng-autocomplete.d.ts +27 -24
- package/types/yoozsoft-yoozsoft-ng-dropdown.d.ts +35 -23
- package/types/yoozsoft-yoozsoft-ng-file-upload.d.ts +2 -1
- package/types/yoozsoft-yoozsoft-ng-navbar.d.ts +1 -0
- package/types/yoozsoft-yoozsoft-ng-progress.d.ts +9 -9
- package/types/yoozsoft-yoozsoft-ng-select.d.ts +2 -1
- package/types/yoozsoft-yoozsoft-ng-table.d.ts +124 -0
- package/types/yoozsoft-yoozsoft-ng-tiff-viewer.d.ts +35 -39
- package/types/yoozsoft-yoozsoft-ng-toast.d.ts +43 -33
- package/assets/js/UTIF.js-master/package.json +0 -24
- package/autocomplete/package.json +0 -4
- package/datepicker/package.json +0 -4
- package/directives/package.json +0 -4
- package/dropdown/package.json +0 -4
- package/file-upload/package.json +0 -4
- package/footer/package.json +0 -4
- package/loading/package.json +0 -4
- package/navbar/package.json +0 -4
- package/overlay/package.json +0 -4
- package/pagination/package.json +0 -4
- package/password-strength/package.json +0 -4
- package/progress/package.json +0 -4
- package/select/package.json +0 -4
- package/sidebar/package.json +0 -4
- package/tiff-viewer/package.json +0 -4
- package/toast/package.json +0 -4
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
import * as i2 from '@angular/cdk/scrolling';
|
|
2
2
|
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
3
|
-
import { NgTemplateOutlet, NgClass } from '@angular/common';
|
|
3
|
+
import { isPlatformBrowser, NgTemplateOutlet, NgClass } from '@angular/common';
|
|
4
4
|
import * as i0 from '@angular/core';
|
|
5
|
-
import { EventEmitter,
|
|
5
|
+
import { signal, EventEmitter, inject, PLATFORM_ID, DestroyRef, effect, TemplateRef, forwardRef, Output, Input, ContentChild, ViewChild, Component } from '@angular/core';
|
|
6
6
|
import * as i1 from '@angular/forms';
|
|
7
7
|
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
8
|
-
import {
|
|
8
|
+
import { catchError, of } from 'rxjs';
|
|
9
9
|
|
|
10
10
|
class YsAutocompleteComponent {
|
|
11
11
|
elRef;
|
|
12
|
-
searchTerm = '';
|
|
13
|
-
filteredOptions = [];
|
|
14
|
-
selectedOptions = [];
|
|
15
|
-
showDropdown = false;
|
|
16
|
-
activeIndex = -1;
|
|
17
|
-
error = null;
|
|
12
|
+
searchTerm = signal('', ...(ngDevMode ? [{ debugName: "searchTerm" }] : []));
|
|
13
|
+
filteredOptions = signal([], ...(ngDevMode ? [{ debugName: "filteredOptions" }] : []));
|
|
14
|
+
selectedOptions = signal([], ...(ngDevMode ? [{ debugName: "selectedOptions" }] : []));
|
|
15
|
+
showDropdown = signal(false, ...(ngDevMode ? [{ debugName: "showDropdown" }] : []));
|
|
16
|
+
activeIndex = signal(-1, ...(ngDevMode ? [{ debugName: "activeIndex" }] : []));
|
|
17
|
+
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : []));
|
|
18
|
+
inputRef;
|
|
19
|
+
_loading = signal(false, ...(ngDevMode ? [{ debugName: "_loading" }] : []));
|
|
20
|
+
set loading(value) { this._loading.set(!!value); }
|
|
21
|
+
get loading() { return this._loading(); }
|
|
22
|
+
loadingMessage = 'Loading...';
|
|
18
23
|
/** Array or async function */
|
|
19
|
-
|
|
24
|
+
_options = [];
|
|
25
|
+
set options(value) {
|
|
26
|
+
this._options = value;
|
|
27
|
+
if (Array.isArray(value)) {
|
|
28
|
+
this.filteredOptions.set(value);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
get options() {
|
|
32
|
+
return this._options;
|
|
33
|
+
}
|
|
20
34
|
/** Label display field */
|
|
21
35
|
optionLabel = 'label';
|
|
22
36
|
/** placeholder */
|
|
@@ -31,8 +45,10 @@ class YsAutocompleteComponent {
|
|
|
31
45
|
styleClass;
|
|
32
46
|
/** Badge style class on Multiple choice mode */
|
|
33
47
|
badgeStyleClass = 'text-bg-light';
|
|
34
|
-
|
|
35
|
-
|
|
48
|
+
removeIconClass = 'fa fa-times';
|
|
49
|
+
searchIconClass = 'fa fa-search';
|
|
50
|
+
spinnerIconClass = 'fa fa-spinner fa-spin';
|
|
51
|
+
multipleCheckIconClass = 'fa fa-check';
|
|
36
52
|
/** No results found message */
|
|
37
53
|
noResultMessage = 'No results found.';
|
|
38
54
|
/** Infinite scroll feature enabled */
|
|
@@ -42,50 +58,55 @@ class YsAutocompleteComponent {
|
|
|
42
58
|
// [virtualScrollOptions]="options"
|
|
43
59
|
/** Event to request more items */
|
|
44
60
|
loadMore = new EventEmitter();
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
/** Output selection after removed item */
|
|
48
|
-
removed = new EventEmitter();
|
|
49
|
-
search$ = new Subject();
|
|
61
|
+
/** Return selected options */
|
|
62
|
+
selectionChange = new EventEmitter();
|
|
50
63
|
_onChange = () => { };
|
|
51
64
|
_onTouched = () => { };
|
|
52
|
-
inputRef;
|
|
53
65
|
get isArrayItems() { return Array.isArray(this.options); }
|
|
54
66
|
get isFunctionItems() { return typeof this.options === 'function'; }
|
|
55
67
|
constructor(elRef) {
|
|
56
68
|
this.elRef = elRef;
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
69
|
+
const platformId = inject(PLATFORM_ID);
|
|
70
|
+
if (isPlatformBrowser(platformId)) {
|
|
71
|
+
const handler = (event) => {
|
|
72
|
+
if (!this.elRef.nativeElement.contains(event.target)) {
|
|
73
|
+
this.showDropdown.set(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
document.addEventListener('click', handler);
|
|
77
|
+
inject(DestroyRef).onDestroy(() => {
|
|
78
|
+
document.removeEventListener('click', handler);
|
|
79
|
+
});
|
|
61
80
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
.
|
|
67
|
-
this.
|
|
68
|
-
|
|
69
|
-
return fetchFn(term).pipe(catchError((err) => {
|
|
70
|
-
this.error = 'Error receiving data!';
|
|
81
|
+
effect(() => {
|
|
82
|
+
const term = this.searchTerm();
|
|
83
|
+
if (typeof this._options === 'function') {
|
|
84
|
+
this._loading.set(true);
|
|
85
|
+
this.error.set(null);
|
|
86
|
+
this._options(term).pipe(catchError(err => {
|
|
87
|
+
this.error.set('Error receiving data!');
|
|
71
88
|
console.error(err);
|
|
72
89
|
return of([]);
|
|
73
|
-
}))
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
90
|
+
})).subscribe(results => {
|
|
91
|
+
this.filteredOptions.set(results);
|
|
92
|
+
this._loading.set(false);
|
|
93
|
+
if (results.length > 0) {
|
|
94
|
+
this.showDropdown.set(true); // فقط اگر نتایج داریم
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.showDropdown.set(false); // یا همون default
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
});
|
|
81
102
|
}
|
|
82
103
|
/** For the initial value of FormControl */
|
|
83
104
|
writeValue(value) {
|
|
84
105
|
if (this.multiple) {
|
|
85
|
-
this.selectedOptions
|
|
106
|
+
this.selectedOptions.set(value ? [...value] : []);
|
|
86
107
|
}
|
|
87
108
|
else {
|
|
88
|
-
this.searchTerm
|
|
109
|
+
this.searchTerm.set(value ? this.getLabel(value) : '');
|
|
89
110
|
}
|
|
90
111
|
}
|
|
91
112
|
registerOnChange(fn) {
|
|
@@ -100,56 +121,67 @@ class YsAutocompleteComponent {
|
|
|
100
121
|
this.inputRef.nativeElement.disabled = isDisabled;
|
|
101
122
|
}
|
|
102
123
|
}
|
|
103
|
-
onSearchChange() {
|
|
104
|
-
|
|
105
|
-
if (Array.isArray(this.
|
|
124
|
+
onSearchChange(term) {
|
|
125
|
+
this.searchTerm.set(term.trim());
|
|
126
|
+
if (Array.isArray(this._options)) {
|
|
106
127
|
const lower = term.toLowerCase();
|
|
107
|
-
this.filteredOptions
|
|
108
|
-
this.showDropdown
|
|
109
|
-
}
|
|
110
|
-
else if (typeof this.options === 'function') {
|
|
111
|
-
this.search$.next(term);
|
|
128
|
+
this.filteredOptions.set(this._options.filter(item => this.getLabel(item).toLowerCase().includes(lower)));
|
|
129
|
+
this.showDropdown.set(true);
|
|
112
130
|
}
|
|
113
131
|
if (!this.multiple && !term) {
|
|
114
132
|
this.clearSelection();
|
|
115
133
|
}
|
|
116
134
|
}
|
|
117
135
|
getLabel(item) {
|
|
118
|
-
if (
|
|
136
|
+
if (item === null || item === undefined)
|
|
119
137
|
return '';
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
138
|
+
// string / number
|
|
139
|
+
if (typeof item === 'string' || typeof item === 'number') {
|
|
140
|
+
return String(item);
|
|
141
|
+
}
|
|
142
|
+
// object
|
|
143
|
+
if (this.optionLabel && item[this.optionLabel] != null) {
|
|
144
|
+
return String(item[this.optionLabel]);
|
|
124
145
|
}
|
|
125
146
|
return '';
|
|
126
147
|
}
|
|
148
|
+
isEqual(a, b) {
|
|
149
|
+
if (typeof a !== 'object' && typeof b !== 'object') {
|
|
150
|
+
return a === b;
|
|
151
|
+
}
|
|
152
|
+
return this.getLabel(a) === this.getLabel(b);
|
|
153
|
+
}
|
|
127
154
|
onSelect(item) {
|
|
128
155
|
if (this.multiple) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
this.
|
|
137
|
-
this.
|
|
138
|
-
this.
|
|
156
|
+
this.selectedOptions.update(list => list.some(x => this.isEqual(x, item))
|
|
157
|
+
? list.filter(x => !this.isEqual(x, item)) // ✅ حذف
|
|
158
|
+
: [...list, item] // ✅ اضافه
|
|
159
|
+
);
|
|
160
|
+
const value = this.selectedOptions();
|
|
161
|
+
this._onChange(value);
|
|
162
|
+
this._onTouched();
|
|
163
|
+
this.selectionChange.emit(value);
|
|
164
|
+
this.searchTerm.set('');
|
|
165
|
+
this.showDropdown.set(true);
|
|
166
|
+
this.onSearchChange(this.searchTerm());
|
|
139
167
|
}
|
|
140
168
|
else {
|
|
141
|
-
this.searchTerm
|
|
169
|
+
this.searchTerm.set(this.getLabel(item));
|
|
142
170
|
this._onChange(item);
|
|
143
171
|
this._onTouched();
|
|
144
|
-
this.
|
|
145
|
-
this.showDropdown
|
|
172
|
+
this.selectionChange.emit(item);
|
|
173
|
+
this.showDropdown.set(false);
|
|
146
174
|
}
|
|
147
|
-
this.activeIndex
|
|
175
|
+
this.activeIndex.set(-1);
|
|
148
176
|
}
|
|
149
177
|
removeItem(item) {
|
|
150
|
-
|
|
151
|
-
this.
|
|
152
|
-
|
|
178
|
+
const prev = this.selectedOptions();
|
|
179
|
+
this.selectedOptions.update(list => list.filter(x => this.getLabel(x) !== this.getLabel(item)));
|
|
180
|
+
if (prev !== this.selectedOptions()) {
|
|
181
|
+
const value = this.selectedOptions();
|
|
182
|
+
this._onChange(value);
|
|
183
|
+
this.selectionChange.emit(value);
|
|
184
|
+
}
|
|
153
185
|
}
|
|
154
186
|
onScroll(event) {
|
|
155
187
|
if (!this.infiniteScroll || this.loading)
|
|
@@ -158,63 +190,61 @@ class YsAutocompleteComponent {
|
|
|
158
190
|
const nearBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 10;
|
|
159
191
|
if (nearBottom) {
|
|
160
192
|
// Request more items
|
|
161
|
-
this.loadMore.emit(this.searchTerm);
|
|
193
|
+
this.loadMore.emit(this.searchTerm());
|
|
162
194
|
}
|
|
163
195
|
}
|
|
164
196
|
clearSelection() {
|
|
165
197
|
if (this.multiple) {
|
|
166
|
-
this.selectedOptions
|
|
167
|
-
this.
|
|
168
|
-
this.
|
|
198
|
+
this.selectedOptions.set([]);
|
|
199
|
+
const value = this.selectedOptions();
|
|
200
|
+
this._onChange(value);
|
|
201
|
+
this.selectionChange.emit(value);
|
|
169
202
|
}
|
|
170
203
|
else {
|
|
171
|
-
this.searchTerm
|
|
204
|
+
this.searchTerm.set('');
|
|
172
205
|
this._onChange(null);
|
|
173
|
-
this.
|
|
206
|
+
this.selectionChange.emit(null);
|
|
174
207
|
}
|
|
175
|
-
this.showDropdown
|
|
208
|
+
// this.showDropdown.set(false);
|
|
176
209
|
}
|
|
177
|
-
/** Keyboard control */
|
|
178
210
|
handleKeyboard(event) {
|
|
179
|
-
|
|
211
|
+
const list = this.filteredOptions();
|
|
212
|
+
if (!this.showDropdown() || list.length === 0)
|
|
180
213
|
return;
|
|
181
214
|
switch (event.key) {
|
|
182
215
|
case 'ArrowDown':
|
|
183
|
-
|
|
216
|
+
// برو به آیتم بعدی
|
|
217
|
+
this.activeIndex.update(i => (i + 1) % list.length);
|
|
184
218
|
event.preventDefault();
|
|
185
219
|
break;
|
|
186
220
|
case 'ArrowUp':
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
this.filteredOptions.length;
|
|
221
|
+
// برو به آیتم قبلی
|
|
222
|
+
this.activeIndex.update(i => (i - 1 + list.length) % list.length);
|
|
190
223
|
event.preventDefault();
|
|
191
224
|
break;
|
|
192
225
|
case 'Enter':
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
226
|
+
const index = this.activeIndex();
|
|
227
|
+
if (index >= 0 && index < list.length) {
|
|
228
|
+
this.onSelect(list[index]);
|
|
196
229
|
}
|
|
230
|
+
event.preventDefault();
|
|
197
231
|
break;
|
|
198
232
|
case 'Escape':
|
|
199
|
-
this.showDropdown
|
|
233
|
+
this.showDropdown.set(false);
|
|
200
234
|
break;
|
|
201
235
|
}
|
|
202
236
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const clickedInside = this.elRef.nativeElement.contains(event.target);
|
|
206
|
-
if (!clickedInside) {
|
|
207
|
-
this.showDropdown = false;
|
|
208
|
-
}
|
|
237
|
+
isSelected(item) {
|
|
238
|
+
return this.selectedOptions().some(x => this.isEqual(x, item));
|
|
209
239
|
}
|
|
210
240
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: YsAutocompleteComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
211
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: YsAutocompleteComponent, isStandalone: true, selector: "ys-autocomplete", inputs: { options: "options", optionLabel: "optionLabel", placeholder: "placeholder", multiple: "multiple", showClear: "showClear", disabled: "disabled", styleClass: "styleClass", badgeStyleClass: "badgeStyleClass",
|
|
241
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: YsAutocompleteComponent, isStandalone: true, selector: "ys-autocomplete", inputs: { loading: "loading", loadingMessage: "loadingMessage", options: "options", optionLabel: "optionLabel", placeholder: "placeholder", multiple: "multiple", showClear: "showClear", disabled: "disabled", styleClass: "styleClass", badgeStyleClass: "badgeStyleClass", removeIconClass: "removeIconClass", searchIconClass: "searchIconClass", spinnerIconClass: "spinnerIconClass", multipleCheckIconClass: "multipleCheckIconClass", noResultMessage: "noResultMessage", infiniteScroll: "infiniteScroll", virtualScroll: "virtualScroll", virtualScrollItemSize: "virtualScrollItemSize" }, outputs: { loadMore: "loadMore", selectionChange: "selectionChange" }, providers: [
|
|
212
242
|
{
|
|
213
243
|
provide: NG_VALUE_ACCESSOR,
|
|
214
244
|
useExisting: forwardRef(() => YsAutocompleteComponent),
|
|
215
245
|
multi: true,
|
|
216
246
|
},
|
|
217
|
-
], queries: [{ propertyName: "itemTemplate", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true }], ngImport: i0, template: "<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions.length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions; track
|
|
247
|
+
], queries: [{ propertyName: "itemTemplate", first: true, predicate: TemplateRef, descendants: true }], viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputRef"], descendants: true }], ngImport: i0, template: "<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions().length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions(); track $index) {\r\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [ngClass]=\"badgeStyleClass\">\r\n {{ getLabel(item) }}\r\n <i class=\"{{removeIconClass}} ms-2 cursor-pointer\" (click)=\"removeItem(item)\"></i>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [ngModel]=\"searchTerm()\"\r\n (ngModelChange)=\"onSearchChange($event)\" (keydown)=\"handleKeyboard($event)\"\r\n (focus)=\"showDropdown.set(true)\" [ngClass]=\"styleClass\" />\r\n\r\n @if (showClear) {\r\n @if ((multiple && selectedOptions().length > 0) || (!multiple && searchTerm())) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"{{removeIconClass}}\"></span>\r\n </button>\r\n }\r\n }\r\n <span class=\"input-group-text\" (click)=\"showDropdown.set( !showDropdown())\">\r\n <i class=\"{{searchIconClass}}\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (showDropdown()) {\r\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\r\n @if (loading) {\r\n <div class=\"list-group-item text-center\">\r\n <i class=\"{{spinnerIconClass}} me-2\"></i>{{ loadingMessage }}\r\n </div>\r\n }\r\n @else if (error()) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error() }}</div>\r\n }\r\n @else if (filteredOptions().length === 0) {\r\n <div class=\"list-group-item text-muted text-center\">\r\n {{ noResultMessage }}\r\n </div>\r\n }\r\n <!-- \u2705 \u062D\u0627\u0644\u062A Virtual Scroll \u0628\u0631\u0627\u06CC \u0644\u06CC\u0633\u062A\u200C\u0647\u0627\u06CC \u0628\u0632\u0631\u06AF -->\r\n @else if (virtualScroll && filteredOptions().length > 100) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </cdk-virtual-scroll-viewport>\r\n }\r\n <!-- \u2705 \u062D\u0627\u0644\u062A \u0645\u0639\u0645\u0648\u0644\u06CC \u0628\u0631\u0627\u06CC \u0644\u06CC\u0633\u062A\u200C\u0647\u0627\u06CC \u06A9\u0648\u0686\u06A9 -->\r\n @else {\r\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll\" (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n</div>", styles: [".ys-autocomplete .dropdown-container,.ys-autocomplete .list-group{z-index:1000;max-height:200px}.ys-autocomplete cdk-virtual-scroll-viewport{height:200px;display:block}.ys-autocomplete .list-group-item-action{font-size:13px;font-weight:500;line-height:22px;text-transform:uppercase}.ys-autocomplete .list-group-item-action.selected{color:var(--bs-list-group-action-hover-color);background-color:var(--bs-list-group-action-hover-bg)}.ys-autocomplete .btn-clear:hover{background-color:var(--bs-btn-hover-bg)}.ys-autocomplete .badge{font-size:.9rem;cursor:default;font-weight:var(--bs-body-font-weight)}.ys-autocomplete .badge i{cursor:pointer;font-size:.8rem}.ys-autocomplete .badge:hover{font-weight:var(--bs-badge-font-weight)}\n"], dependencies: [{ 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"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ScrollingModule }, { kind: "directive", type: i2.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "component", type: i2.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }] });
|
|
218
248
|
}
|
|
219
249
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: YsAutocompleteComponent, decorators: [{
|
|
220
250
|
type: Component,
|
|
@@ -224,8 +254,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
224
254
|
useExisting: forwardRef(() => YsAutocompleteComponent),
|
|
225
255
|
multi: true,
|
|
226
256
|
},
|
|
227
|
-
], template: "<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions.length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions; track
|
|
228
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: {
|
|
257
|
+
], template: "<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions().length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions(); track $index) {\r\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [ngClass]=\"badgeStyleClass\">\r\n {{ getLabel(item) }}\r\n <i class=\"{{removeIconClass}} ms-2 cursor-pointer\" (click)=\"removeItem(item)\"></i>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [ngModel]=\"searchTerm()\"\r\n (ngModelChange)=\"onSearchChange($event)\" (keydown)=\"handleKeyboard($event)\"\r\n (focus)=\"showDropdown.set(true)\" [ngClass]=\"styleClass\" />\r\n\r\n @if (showClear) {\r\n @if ((multiple && selectedOptions().length > 0) || (!multiple && searchTerm())) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"{{removeIconClass}}\"></span>\r\n </button>\r\n }\r\n }\r\n <span class=\"input-group-text\" (click)=\"showDropdown.set( !showDropdown())\">\r\n <i class=\"{{searchIconClass}}\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (showDropdown()) {\r\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\r\n @if (loading) {\r\n <div class=\"list-group-item text-center\">\r\n <i class=\"{{spinnerIconClass}} me-2\"></i>{{ loadingMessage }}\r\n </div>\r\n }\r\n @else if (error()) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error() }}</div>\r\n }\r\n @else if (filteredOptions().length === 0) {\r\n <div class=\"list-group-item text-muted text-center\">\r\n {{ noResultMessage }}\r\n </div>\r\n }\r\n <!-- \u2705 \u062D\u0627\u0644\u062A Virtual Scroll \u0628\u0631\u0627\u06CC \u0644\u06CC\u0633\u062A\u200C\u0647\u0627\u06CC \u0628\u0632\u0631\u06AF -->\r\n @else if (virtualScroll && filteredOptions().length > 100) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </cdk-virtual-scroll-viewport>\r\n }\r\n <!-- \u2705 \u062D\u0627\u0644\u062A \u0645\u0639\u0645\u0648\u0644\u06CC \u0628\u0631\u0627\u06CC \u0644\u06CC\u0633\u062A\u200C\u0647\u0627\u06CC \u06A9\u0648\u0686\u06A9 -->\r\n @else {\r\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll\" (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n</div>", styles: [".ys-autocomplete .dropdown-container,.ys-autocomplete .list-group{z-index:1000;max-height:200px}.ys-autocomplete cdk-virtual-scroll-viewport{height:200px;display:block}.ys-autocomplete .list-group-item-action{font-size:13px;font-weight:500;line-height:22px;text-transform:uppercase}.ys-autocomplete .list-group-item-action.selected{color:var(--bs-list-group-action-hover-color);background-color:var(--bs-list-group-action-hover-bg)}.ys-autocomplete .btn-clear:hover{background-color:var(--bs-btn-hover-bg)}.ys-autocomplete .badge{font-size:.9rem;cursor:default;font-weight:var(--bs-body-font-weight)}.ys-autocomplete .badge i{cursor:pointer;font-size:.8rem}.ys-autocomplete .badge:hover{font-weight:var(--bs-badge-font-weight)}\n"] }]
|
|
258
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { inputRef: [{
|
|
259
|
+
type: ViewChild,
|
|
260
|
+
args: ['inputRef']
|
|
261
|
+
}], loading: [{
|
|
262
|
+
type: Input
|
|
263
|
+
}], loadingMessage: [{
|
|
264
|
+
type: Input
|
|
265
|
+
}], options: [{
|
|
229
266
|
type: Input
|
|
230
267
|
}], optionLabel: [{
|
|
231
268
|
type: Input
|
|
@@ -244,9 +281,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
244
281
|
type: Input
|
|
245
282
|
}], badgeStyleClass: [{
|
|
246
283
|
type: Input
|
|
247
|
-
}],
|
|
284
|
+
}], removeIconClass: [{
|
|
248
285
|
type: Input
|
|
249
|
-
}],
|
|
286
|
+
}], searchIconClass: [{
|
|
287
|
+
type: Input
|
|
288
|
+
}], spinnerIconClass: [{
|
|
289
|
+
type: Input
|
|
290
|
+
}], multipleCheckIconClass: [{
|
|
250
291
|
type: Input
|
|
251
292
|
}], noResultMessage: [{
|
|
252
293
|
type: Input
|
|
@@ -258,19 +299,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
|
|
|
258
299
|
type: Input
|
|
259
300
|
}], loadMore: [{
|
|
260
301
|
type: Output
|
|
261
|
-
}],
|
|
262
|
-
type: Output
|
|
263
|
-
}], removed: [{
|
|
302
|
+
}], selectionChange: [{
|
|
264
303
|
type: Output
|
|
265
|
-
}], inputRef: [{
|
|
266
|
-
type: ViewChild,
|
|
267
|
-
args: ['inputRef']
|
|
268
|
-
}], handleKeyboard: [{
|
|
269
|
-
type: HostListener,
|
|
270
|
-
args: ['keydown', ['$event']]
|
|
271
|
-
}], onClickOutside: [{
|
|
272
|
-
type: HostListener,
|
|
273
|
-
args: ['document:click', ['$event']]
|
|
274
304
|
}] } });
|
|
275
305
|
|
|
276
306
|
/*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yoozsoft-yoozsoft-ng-autocomplete.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.html","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/yoozsoft-yoozsoft-ng-autocomplete.ts"],"sourcesContent":["import { ScrollingModule } from '@angular/cdk/scrolling';\r\nimport { NgClass, NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ContentChild, ElementRef, EventEmitter, forwardRef, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { catchError, debounceTime, distinctUntilChanged, Observable, of, Subject, switchMap } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ys-autocomplete',\r\n imports: [FormsModule, NgTemplateOutlet, NgClass, ScrollingModule],\r\n templateUrl: './ys-autocomplete.component.html',\r\n styleUrl: './ys-autocomplete.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsAutocompleteComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsAutocompleteComponent implements ControlValueAccessor {\r\n\r\n searchTerm = '';\r\n filteredOptions: any[] = [];\r\n selectedOptions: any[] = [];\r\n showDropdown = false;\r\n activeIndex = -1;\r\n error: string | null = null;\r\n\r\n /** Array or async function */\r\n @Input() options?: any[] | ((term: string) => Observable<any[]>);\r\n\r\n /** Label display field */\r\n @Input() optionLabel = 'label';\r\n\r\n /** placeholder */\r\n @Input() placeholder: string = '';\r\n\r\n /** Multiple choice mode */\r\n @Input() multiple = false;\r\n\r\n /** Button to clear selection */\r\n @Input() showClear = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** Custom template */\r\n @ContentChild(TemplateRef) itemTemplate?: TemplateRef<any>;\r\n\r\n @Input() styleClass?: string;\r\n /** Badge style class on Multiple choice mode */\r\n @Input() badgeStyleClass: string = 'text-bg-light';\r\n @Input() loading: boolean = false;\r\n @Input() loadingMessage: string = 'Loading...';\r\n /** No results found message */\r\n @Input() noResultMessage: string = 'No results found.';\r\n\r\n /** Infinite scroll feature enabled */\r\n @Input() infiniteScroll = false;\r\n\r\n @Input() virtualScroll: boolean = true;\r\n @Input() virtualScrollItemSize: number = 36;\r\n // [virtualScrollOptions]=\"options\"\r\n\r\n /** Event to request more items */\r\n @Output() loadMore = new EventEmitter<string>();\r\n\r\n /** Output selection */\r\n @Output() selected = new EventEmitter<any>();\r\n /** Output selection after removed item */\r\n @Output() removed = new EventEmitter<any>();\r\n\r\n private search$ = new Subject<string>();\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n @ViewChild('inputRef') inputRef!: ElementRef<HTMLInputElement>;\r\n\r\n get isArrayItems(): boolean { return Array.isArray(this.options); }\r\n get isFunctionItems(): boolean { return typeof this.options === 'function'; }\r\n\r\n constructor(private elRef: ElementRef) { }\r\n\r\n ngOnInit() {\r\n if (Array.isArray(this.options)) {\r\n this.filteredOptions = this.options;\r\n }\r\n\r\n /** Only in async function mode */\r\n if (typeof this.options === 'function') {\r\n const fetchFn = this.options as (term: string) => Observable<any[]>;\r\n this.search$\r\n .pipe(\r\n debounceTime(300),\r\n distinctUntilChanged(),\r\n switchMap((term) => {\r\n this.loading = true;\r\n this.error = null;\r\n return fetchFn(term).pipe(\r\n catchError((err) => {\r\n this.error = 'Error receiving data!';\r\n console.error(err);\r\n return of([]);\r\n })\r\n );\r\n })\r\n )\r\n .subscribe((results) => {\r\n this.filteredOptions = results;\r\n this.loading = false;\r\n this.showDropdown = true;\r\n });\r\n }\r\n\r\n }\r\n\r\n /** For the initial value of FormControl */\r\n writeValue(value: any): void {\r\n if (this.multiple) {\r\n this.selectedOptions = value ? [...value] : [];\r\n } else {\r\n this.searchTerm = value ? this.getLabel(value) : '';\r\n }\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n if (this.inputRef) {\r\n this.inputRef.nativeElement.disabled = isDisabled;\r\n }\r\n }\r\n\r\n onSearchChange() {\r\n const term = this.searchTerm.trim();\r\n\r\n if (Array.isArray(this.options)) {\r\n const lower = term.toLowerCase();\r\n this.filteredOptions = this.options.filter((item) =>\r\n this.getLabel(item).toLowerCase().includes(lower)\r\n );\r\n this.showDropdown = this.filteredOptions.length >= 0;\r\n } else if (typeof this.options === 'function') {\r\n this.search$.next(term);\r\n }\r\n\r\n if (!this.multiple && !term) {\r\n this.clearSelection();\r\n }\r\n }\r\n\r\n getLabel(item: any): string {\r\n if (!item) return '';\r\n if (typeof item === 'string') return item;\r\n if (item && this.optionLabel && item[this.optionLabel]) {\r\n return item[this.optionLabel];\r\n }\r\n return '';\r\n }\r\n\r\n onSelect(item: any) {\r\n if (this.multiple) {\r\n const exists = this.selectedOptions.some(\r\n (x) => this.getLabel(x) === this.getLabel(item)\r\n );\r\n if (!exists) {\r\n this.selectedOptions.push(item);\r\n this._onChange(this.selectedOptions);\r\n this._onTouched();\r\n this.selected.emit(this.selectedOptions);\r\n }\r\n this.searchTerm = '';\r\n this.showDropdown = true;\r\n this.onSearchChange();\r\n } else {\r\n this.searchTerm = this.getLabel(item);\r\n this._onChange(item);\r\n this._onTouched();\r\n this.selected.emit(item);\r\n this.showDropdown = false;\r\n }\r\n\r\n this.activeIndex = -1;\r\n }\r\n\r\n removeItem(item: any) {\r\n this.selectedOptions = this.selectedOptions.filter(\r\n (x) => this.getLabel(x) !== this.getLabel(item)\r\n );\r\n this._onChange(this.selectedOptions);\r\n this.removed.emit(this.selectedOptions);\r\n }\r\n\r\n onScroll(event: Event) {\r\n if (!this.infiniteScroll || this.loading) return;\r\n\r\n const target = event.target as HTMLElement;\r\n const nearBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 10;\r\n\r\n if (nearBottom) {\r\n // Request more items\r\n this.loadMore.emit(this.searchTerm);\r\n }\r\n }\r\n\r\n clearSelection() {\r\n if (this.multiple) {\r\n this.selectedOptions = [];\r\n this._onChange(this.selectedOptions);\r\n this.removed.emit(this.selectedOptions);\r\n } else {\r\n this.searchTerm = '';\r\n this._onChange(null);\r\n this.selected.emit(null);\r\n }\r\n\r\n this.showDropdown = false;\r\n }\r\n\r\n /** Keyboard control */\r\n @HostListener('keydown', ['$event'])\r\n handleKeyboard(event: KeyboardEvent) {\r\n if (!this.showDropdown || this.filteredOptions.length === 0) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n this.activeIndex = (this.activeIndex + 1) % this.filteredOptions.length;\r\n event.preventDefault();\r\n break;\r\n case 'ArrowUp':\r\n this.activeIndex =\r\n (this.activeIndex - 1 + this.filteredOptions.length) %\r\n this.filteredOptions.length;\r\n event.preventDefault();\r\n break;\r\n case 'Enter':\r\n if (this.activeIndex >= 0) {\r\n this.onSelect(this.filteredOptions[this.activeIndex]);\r\n event.preventDefault();\r\n }\r\n break;\r\n case 'Escape':\r\n this.showDropdown = false;\r\n break;\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.showDropdown = false;\r\n }\r\n }\r\n\r\n}\r\n","<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions.length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions; track item) {\r\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [ngClass]=\"badgeStyleClass\">\r\n {{ getLabel(item) }}\r\n <i class=\"fa fa-times ms-2 cursor-pointer\" (click)=\"removeItem(item)\"></i>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [(ngModel)]=\"searchTerm\"\r\n (input)=\"onSearchChange()\" (focus)=\"showDropdown = true\" [ngClass]=\"styleClass\" />\r\n\r\n @if (showClear) {\r\n @if ((multiple && selectedOptions.length > 0) || (!multiple && searchTerm)) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-times\"></span>\r\n </button>\r\n }\r\n }\r\n <span class=\"input-group-text\" (click)=\"showDropdown = !showDropdown\">\r\n <i class=\"fa fa-search\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (showDropdown) {\r\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\r\n @if (loading) {\r\n <div class=\"list-group-item text-center\">\r\n <i class=\"fa fa-spinner fa-spin me-2\"></i>{{ loadingMessage }}\r\n </div>\r\n }\r\n @else if (error) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error }}</div>\r\n }\r\n @else if (filteredOptions.length === 0) {\r\n <div class=\"list-group-item text-muted text-center\">\r\n {{ noResultMessage }}\r\n </div>\r\n }\r\n <!-- ✅ حالت Virtual Scroll برای لیستهای بزرگ -->\r\n @else if (virtualScroll && filteredOptions.length > 100) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredOptions; track item; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex\"\r\n (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </cdk-virtual-scroll-viewport>\r\n }\r\n <!-- ✅ حالت معمولی برای لیستهای کوچک -->\r\n @else {\r\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll\" (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions; track item; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex\"\r\n (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n</div>","/*\r\n * Public API Surface of ys-autocomplete\r\n */\r\n\r\nexport * from './src/ys-autocomplete/ys-autocomplete.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-autocomplete.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/src/ys-autocomplete/ys-autocomplete.component.html","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/autocomplete/yoozsoft-yoozsoft-ng-autocomplete.ts"],"sourcesContent":["import { ScrollingModule } from '@angular/cdk/scrolling';\r\nimport { isPlatformBrowser, NgClass, NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ContentChild, DestroyRef, effect, ElementRef, EventEmitter, forwardRef, inject, Input, Output, PLATFORM_ID, signal, TemplateRef, ViewChild } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { catchError, Observable, of } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ys-autocomplete',\r\n imports: [FormsModule, NgTemplateOutlet, NgClass, ScrollingModule],\r\n templateUrl: './ys-autocomplete.component.html',\r\n styleUrl: './ys-autocomplete.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsAutocompleteComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsAutocompleteComponent implements ControlValueAccessor {\r\n\r\n searchTerm = signal('');\r\n filteredOptions = signal<any[]>([]);\r\n selectedOptions = signal<any[]>([]);\r\n showDropdown = signal(false);\r\n activeIndex = signal(-1);\r\n error = signal<string | null>(null);\r\n\r\n @ViewChild('inputRef') inputRef!: ElementRef<HTMLInputElement>;\r\n\r\n private _loading = signal(false);\r\n @Input()\r\n set loading(value: boolean) { this._loading.set(!!value); }\r\n get loading() { return this._loading(); }\r\n\r\n @Input() loadingMessage: string = 'Loading...';\r\n\r\n /** Array or async function */\r\n private _options: any[] | ((term: string) => Observable<any[]>) = [];\r\n\r\n @Input()\r\n set options(value: any[] | ((term: string) => Observable<any[]>)) {\r\n this._options = value;\r\n\r\n if (Array.isArray(value)) {\r\n this.filteredOptions.set(value);\r\n }\r\n\r\n }\r\n\r\n get options() {\r\n return this._options;\r\n }\r\n\r\n /** Label display field */\r\n @Input() optionLabel = 'label';\r\n\r\n /** placeholder */\r\n @Input() placeholder: string = '';\r\n\r\n /** Multiple choice mode */\r\n @Input() multiple = false;\r\n\r\n /** Button to clear selection */\r\n @Input() showClear = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** Custom template */\r\n @ContentChild(TemplateRef) itemTemplate?: TemplateRef<any>;\r\n\r\n @Input() styleClass?: string;\r\n /** Badge style class on Multiple choice mode */\r\n @Input() badgeStyleClass: string = 'text-bg-light';\r\n @Input() removeIconClass: string = 'fa fa-times';\r\n @Input() searchIconClass: string = 'fa fa-search';\r\n @Input() spinnerIconClass: string = 'fa fa-spinner fa-spin';\r\n @Input() multipleCheckIconClass: string = 'fa fa-check';\r\n\r\n /** No results found message */\r\n @Input() noResultMessage: string = 'No results found.';\r\n\r\n /** Infinite scroll feature enabled */\r\n @Input() infiniteScroll = false;\r\n\r\n @Input() virtualScroll: boolean = true;\r\n @Input() virtualScrollItemSize: number = 36;\r\n // [virtualScrollOptions]=\"options\"\r\n\r\n /** Event to request more items */\r\n @Output() loadMore = new EventEmitter<string>();\r\n\r\n /** Return selected options */\r\n @Output() selectionChange = new EventEmitter<any>();\r\n\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n get isArrayItems(): boolean { return Array.isArray(this.options); }\r\n get isFunctionItems(): boolean { return typeof this.options === 'function'; }\r\n\r\n constructor(private elRef: ElementRef) {\r\n\r\n const platformId = inject(PLATFORM_ID);\r\n\r\n if (isPlatformBrowser(platformId)) {\r\n const handler = (event: MouseEvent) => {\r\n if (!this.elRef.nativeElement.contains(event.target)) {\r\n this.showDropdown.set(false);\r\n }\r\n };\r\n\r\n document.addEventListener('click', handler);\r\n\r\n inject(DestroyRef).onDestroy(() => {\r\n document.removeEventListener('click', handler);\r\n });\r\n }\r\n\r\n effect(() => {\r\n const term = this.searchTerm();\r\n\r\n if (typeof this._options === 'function') {\r\n this._loading.set(true);\r\n this.error.set(null);\r\n\r\n this._options(term).pipe(\r\n catchError(err => {\r\n this.error.set('Error receiving data!');\r\n console.error(err);\r\n return of([]);\r\n })\r\n ).subscribe(results => {\r\n this.filteredOptions.set(results);\r\n this._loading.set(false);\r\n\r\n if (results.length > 0) {\r\n this.showDropdown.set(true); // فقط اگر نتایج داریم\r\n } else {\r\n this.showDropdown.set(false); // یا همون default\r\n }\r\n\r\n });\r\n }\r\n });\r\n\r\n }\r\n\r\n /** For the initial value of FormControl */\r\n writeValue(value: any): void {\r\n if (this.multiple) {\r\n this.selectedOptions.set(value ? [...value] : []);\r\n } else {\r\n this.searchTerm.set(value ? this.getLabel(value) : '');\r\n }\r\n }\r\n\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n if (this.inputRef) {\r\n this.inputRef.nativeElement.disabled = isDisabled;\r\n }\r\n }\r\n\r\n onSearchChange(term: string) {\r\n this.searchTerm.set(term.trim());\r\n\r\n if (Array.isArray(this._options)) {\r\n const lower = term.toLowerCase();\r\n this.filteredOptions.set(\r\n this._options.filter(item =>\r\n this.getLabel(item).toLowerCase().includes(lower)\r\n )\r\n );\r\n this.showDropdown.set(true);\r\n }\r\n\r\n if (!this.multiple && !term) {\r\n this.clearSelection();\r\n }\r\n }\r\n\r\n getLabel(item: any): string {\r\n if (item === null || item === undefined) return '';\r\n\r\n // string / number\r\n if (typeof item === 'string' || typeof item === 'number') {\r\n return String(item);\r\n }\r\n\r\n // object\r\n if (this.optionLabel && item[this.optionLabel] != null) {\r\n return String(item[this.optionLabel]);\r\n }\r\n\r\n return '';\r\n }\r\n\r\n private isEqual(a: any, b: any): boolean {\r\n if (typeof a !== 'object' && typeof b !== 'object') {\r\n return a === b;\r\n }\r\n return this.getLabel(a) === this.getLabel(b);\r\n }\r\n\r\n onSelect(item: any) {\r\n if (this.multiple) {\r\n this.selectedOptions.update(list =>\r\n list.some(x => this.isEqual(x, item))\r\n ? list.filter(x => !this.isEqual(x, item)) // ✅ حذف\r\n : [...list, item] // ✅ اضافه\r\n );\r\n\r\n const value = this.selectedOptions();\r\n this._onChange(value);\r\n this._onTouched();\r\n this.selectionChange.emit(value);\r\n\r\n this.searchTerm.set('');\r\n this.showDropdown.set(true);\r\n this.onSearchChange(this.searchTerm());\r\n\r\n } else {\r\n this.searchTerm.set(this.getLabel(item));\r\n this._onChange(item);\r\n this._onTouched();\r\n this.selectionChange.emit(item);\r\n this.showDropdown.set(false);\r\n }\r\n\r\n this.activeIndex.set(-1);\r\n }\r\n\r\n\r\n removeItem(item: any) {\r\n const prev = this.selectedOptions();\r\n\r\n this.selectedOptions.update(list =>\r\n list.filter(x => this.getLabel(x) !== this.getLabel(item))\r\n );\r\n\r\n if (prev !== this.selectedOptions()) {\r\n const value = this.selectedOptions();\r\n this._onChange(value);\r\n this.selectionChange.emit(value);\r\n }\r\n }\r\n\r\n onScroll(event: Event) {\r\n if (!this.infiniteScroll || this.loading) return;\r\n\r\n const target = event.target as HTMLElement;\r\n const nearBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 10;\r\n\r\n if (nearBottom) {\r\n // Request more items\r\n this.loadMore.emit(this.searchTerm());\r\n }\r\n }\r\n\r\n clearSelection() {\r\n if (this.multiple) {\r\n this.selectedOptions.set([]);\r\n const value = this.selectedOptions();\r\n this._onChange(value);\r\n this.selectionChange.emit(value);\r\n } else {\r\n this.searchTerm.set('');\r\n this._onChange(null);\r\n this.selectionChange.emit(null);\r\n }\r\n\r\n // this.showDropdown.set(false);\r\n }\r\n\r\n handleKeyboard(event: KeyboardEvent) {\r\n const list = this.filteredOptions();\r\n if (!this.showDropdown() || list.length === 0) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n // برو به آیتم بعدی\r\n this.activeIndex.update(i => (i + 1) % list.length);\r\n event.preventDefault();\r\n break;\r\n case 'ArrowUp':\r\n // برو به آیتم قبلی\r\n this.activeIndex.update(i => (i - 1 + list.length) % list.length);\r\n event.preventDefault();\r\n break;\r\n case 'Enter':\r\n const index = this.activeIndex();\r\n if (index >= 0 && index < list.length) {\r\n this.onSelect(list[index]);\r\n }\r\n event.preventDefault();\r\n break;\r\n case 'Escape':\r\n this.showDropdown.set(false);\r\n break;\r\n }\r\n }\r\n\r\n isSelected(item: any): boolean {\r\n return this.selectedOptions().some(x => this.isEqual(x, item));\r\n }\r\n\r\n}\r\n","<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple && selectedOptions().length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedOptions(); track $index) {\r\n <span class=\"badge me-1 mb-1 p-2 d-flex align-items-center\" [ngClass]=\"badgeStyleClass\">\r\n {{ getLabel(item) }}\r\n <i class=\"{{removeIconClass}} ms-2 cursor-pointer\" (click)=\"removeItem(item)\"></i>\r\n </span>\r\n }\r\n </div>\r\n }\r\n\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [placeholder]=\"placeholder\" [ngModel]=\"searchTerm()\"\r\n (ngModelChange)=\"onSearchChange($event)\" (keydown)=\"handleKeyboard($event)\"\r\n (focus)=\"showDropdown.set(true)\" [ngClass]=\"styleClass\" />\r\n\r\n @if (showClear) {\r\n @if ((multiple && selectedOptions().length > 0) || (!multiple && searchTerm())) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"{{removeIconClass}}\"></span>\r\n </button>\r\n }\r\n }\r\n <span class=\"input-group-text\" (click)=\"showDropdown.set( !showDropdown())\">\r\n <i class=\"{{searchIconClass}}\"></i>\r\n </span>\r\n </div>\r\n </div>\r\n\r\n @if (showDropdown()) {\r\n <div class=\"dropdown-container position-absolute w-100 shadow-sm bg-white border rounded\">\r\n @if (loading) {\r\n <div class=\"list-group-item text-center\">\r\n <i class=\"{{spinnerIconClass}} me-2\"></i>{{ loadingMessage }}\r\n </div>\r\n }\r\n @else if (error()) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error() }}</div>\r\n }\r\n @else if (filteredOptions().length === 0) {\r\n <div class=\"list-group-item text-muted text-center\">\r\n {{ noResultMessage }}\r\n </div>\r\n }\r\n <!-- ✅ حالت Virtual Scroll برای لیستهای بزرگ -->\r\n @else if (virtualScroll && filteredOptions().length > 100) {\r\n <cdk-virtual-scroll-viewport [itemSize]=\"virtualScrollItemSize\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </cdk-virtual-scroll-viewport>\r\n }\r\n <!-- ✅ حالت معمولی برای لیستهای کوچک -->\r\n @else {\r\n <ul class=\"list-group w-100 overflow-y-auto\" [class.scrollable]=\"infiniteScroll\" (scroll)=\"onScroll($event)\">\r\n @for (item of filteredOptions(); track $index; let i = $index) {\r\n <li class=\"list-group-item list-group-item-action\" [class.active]=\"i === activeIndex()\"\r\n [class.selected]=\"isSelected(item)\" (click)=\"onSelect(item)\">\r\n @if (itemTemplate) {\r\n <ng-container *ngTemplateOutlet=\"itemTemplate; context: { $implicit: item }\"></ng-container>\r\n } @else {\r\n @if(multiple){\r\n <i class=\"{{multipleCheckIconClass}} me-1 text-success\" [class.invisible]=\"!isSelected(item)\">\r\n </i>\r\n }\r\n {{ getLabel(item) }}\r\n }\r\n </li>\r\n }\r\n </ul>\r\n }\r\n </div>\r\n }\r\n\r\n</div>","/*\r\n * Public API Surface of ys-autocomplete\r\n */\r\n\r\nexport * from './src/ys-autocomplete/ys-autocomplete.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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"}
|