@yoozsoft/yoozsoft-ng 5.1.3 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/autocomplete/index.d.ts +12 -10
- package/dropdown/index.d.ts +51 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs +57 -48
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs +228 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs +5 -5
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs.map +1 -1
- package/package.json +18 -13
- package/select/index.d.ts +2 -2
package/autocomplete/index.d.ts
CHANGED
|
@@ -6,33 +6,35 @@ import { Observable } from 'rxjs';
|
|
|
6
6
|
declare class YsAutocompleteComponent implements ControlValueAccessor {
|
|
7
7
|
private elRef;
|
|
8
8
|
searchTerm: string;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
filteredOptions: any[];
|
|
10
|
+
selectedOptions: any[];
|
|
11
11
|
showDropdown: boolean;
|
|
12
12
|
activeIndex: number;
|
|
13
13
|
error: string | null;
|
|
14
14
|
/** Array or async function */
|
|
15
|
-
|
|
15
|
+
options?: any[] | ((term: string) => Observable<any[]>);
|
|
16
16
|
/** Label display field */
|
|
17
|
-
|
|
17
|
+
optionLabel: string;
|
|
18
18
|
/** placeholder */
|
|
19
|
-
placeholder: string;
|
|
19
|
+
placeholder: string | null;
|
|
20
20
|
/** Multiple choice mode */
|
|
21
21
|
multiple: boolean;
|
|
22
22
|
/** Button to clear selection */
|
|
23
|
-
|
|
23
|
+
showClear: boolean;
|
|
24
24
|
disabled: boolean;
|
|
25
25
|
/** Custom template */
|
|
26
26
|
itemTemplate?: TemplateRef<any>;
|
|
27
27
|
styleClass?: string;
|
|
28
28
|
/** Badge style class on Multiple choice mode */
|
|
29
|
-
badgeStyleClass
|
|
29
|
+
badgeStyleClass: string;
|
|
30
30
|
loading: boolean;
|
|
31
31
|
loadingMessage: string;
|
|
32
32
|
/** No results found message */
|
|
33
33
|
noResultMessage: string;
|
|
34
34
|
/** Infinite scroll feature enabled */
|
|
35
35
|
infiniteScroll: boolean;
|
|
36
|
+
virtualScroll: boolean;
|
|
37
|
+
virtualScrollItemSize: number;
|
|
36
38
|
/** Event to request more items */
|
|
37
39
|
loadMore: EventEmitter<string>;
|
|
38
40
|
/** Output selection */
|
|
@@ -40,8 +42,8 @@ declare class YsAutocompleteComponent implements ControlValueAccessor {
|
|
|
40
42
|
/** Output selection after removed item */
|
|
41
43
|
removed: EventEmitter<any>;
|
|
42
44
|
private search$;
|
|
43
|
-
private
|
|
44
|
-
private
|
|
45
|
+
private _onChange;
|
|
46
|
+
private _onTouched;
|
|
45
47
|
inputRef: ElementRef<HTMLInputElement>;
|
|
46
48
|
get isArrayItems(): boolean;
|
|
47
49
|
get isFunctionItems(): boolean;
|
|
@@ -63,7 +65,7 @@ declare class YsAutocompleteComponent implements ControlValueAccessor {
|
|
|
63
65
|
/** Close by clicking outside */
|
|
64
66
|
onClickOutside(event: MouseEvent): void;
|
|
65
67
|
static ɵfac: i0.ɵɵFactoryDeclaration<YsAutocompleteComponent, never>;
|
|
66
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<YsAutocompleteComponent, "ys-autocomplete", never, { "
|
|
68
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<YsAutocompleteComponent, "ys-autocomplete", never, { "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "showClear": { "alias": "showClear"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "badgeStyleClass": { "alias": "badgeStyleClass"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "loadingMessage": { "alias": "loadingMessage"; "required": false; }; "noResultMessage": { "alias": "noResultMessage"; "required": false; }; "infiniteScroll": { "alias": "infiniteScroll"; "required": false; }; "virtualScroll": { "alias": "virtualScroll"; "required": false; }; "virtualScrollItemSize": { "alias": "virtualScrollItemSize"; "required": false; }; }, { "loadMore": "loadMore"; "selected": "selected"; "removed": "removed"; }, ["itemTemplate"], never, true, never>;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
export { YsAutocompleteComponent };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { TemplateRef, EventEmitter } from '@angular/core';
|
|
3
|
+
import { ControlValueAccessor } from '@angular/forms';
|
|
4
|
+
|
|
5
|
+
declare class YsDropdownComponent implements ControlValueAccessor {
|
|
6
|
+
/** لیست گزینهها */
|
|
7
|
+
options: any[];
|
|
8
|
+
optionLabel: string;
|
|
9
|
+
placeholder: string;
|
|
10
|
+
searchPlaceholder: string;
|
|
11
|
+
selectedMaxLength: number;
|
|
12
|
+
selectedMaxLengthTemplate: string;
|
|
13
|
+
selectionSeparator: string;
|
|
14
|
+
/** انتخاب چندگانه یا تکی */
|
|
15
|
+
multiple: boolean;
|
|
16
|
+
showClear: boolean;
|
|
17
|
+
/** تمپلیت سفارشی برای آیتمها */
|
|
18
|
+
itemTemplate?: TemplateRef<any>;
|
|
19
|
+
/** مقدار انتخابشده */
|
|
20
|
+
selected: any[] | any;
|
|
21
|
+
/** قابلیت جستجو */
|
|
22
|
+
searchable: boolean;
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
/** رویداد خروجی هنگام تغییر انتخاب */
|
|
25
|
+
selectionChange: EventEmitter<any>;
|
|
26
|
+
searchTerm: string;
|
|
27
|
+
isOpen: boolean;
|
|
28
|
+
highlightedIndex: number;
|
|
29
|
+
private elRef;
|
|
30
|
+
private _onChange;
|
|
31
|
+
private _onTouched;
|
|
32
|
+
writeValue(obj: any): void;
|
|
33
|
+
registerOnChange(fn: any): void;
|
|
34
|
+
registerOnTouched(fn: any): void;
|
|
35
|
+
setDisabledState?(isDisabled: boolean): void;
|
|
36
|
+
get displayLabel(): string;
|
|
37
|
+
get selectedLabels(): string;
|
|
38
|
+
toggleDropdown(): void;
|
|
39
|
+
filterOptions(): any[];
|
|
40
|
+
selectOption(option: any): void;
|
|
41
|
+
isSelected(option: any): boolean;
|
|
42
|
+
clearSelection(): void;
|
|
43
|
+
onKeyDown(event: KeyboardEvent): void;
|
|
44
|
+
scrollToHighlighted(): void;
|
|
45
|
+
/** Close by clicking outside */
|
|
46
|
+
onClickOutside(event: MouseEvent): void;
|
|
47
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<YsDropdownComponent, never>;
|
|
48
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<YsDropdownComponent, "ys-dropdown", never, { "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "searchPlaceholder": { "alias": "searchPlaceholder"; "required": false; }; "selectedMaxLength": { "alias": "selectedMaxLength"; "required": false; }; "selectedMaxLengthTemplate": { "alias": "selectedMaxLengthTemplate"; "required": false; }; "selectionSeparator": { "alias": "selectionSeparator"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "showClear": { "alias": "showClear"; "required": false; }; "itemTemplate": { "alias": "itemTemplate"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; "searchable": { "alias": "searchable"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "selectionChange": "selectionChange"; }, never, never, true, never>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export { YsDropdownComponent };
|
|
@@ -10,33 +10,36 @@ import { Subject, debounceTime, distinctUntilChanged, switchMap, catchError, of
|
|
|
10
10
|
class YsAutocompleteComponent {
|
|
11
11
|
elRef;
|
|
12
12
|
searchTerm = '';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
filteredOptions = [];
|
|
14
|
+
selectedOptions = [];
|
|
15
15
|
showDropdown = false;
|
|
16
16
|
activeIndex = -1;
|
|
17
17
|
error = null;
|
|
18
18
|
/** Array or async function */
|
|
19
|
-
|
|
19
|
+
options;
|
|
20
20
|
/** Label display field */
|
|
21
|
-
|
|
21
|
+
optionLabel = 'label';
|
|
22
22
|
/** placeholder */
|
|
23
|
-
placeholder =
|
|
23
|
+
placeholder = null;
|
|
24
24
|
/** Multiple choice mode */
|
|
25
25
|
multiple = false;
|
|
26
26
|
/** Button to clear selection */
|
|
27
|
-
|
|
27
|
+
showClear = false;
|
|
28
28
|
disabled = false;
|
|
29
29
|
/** Custom template */
|
|
30
30
|
itemTemplate;
|
|
31
31
|
styleClass;
|
|
32
32
|
/** Badge style class on Multiple choice mode */
|
|
33
|
-
badgeStyleClass;
|
|
33
|
+
badgeStyleClass = 'text-bg-light';
|
|
34
34
|
loading = false;
|
|
35
35
|
loadingMessage = 'Loading...';
|
|
36
36
|
/** No results found message */
|
|
37
37
|
noResultMessage = 'No results found.';
|
|
38
38
|
/** Infinite scroll feature enabled */
|
|
39
39
|
infiniteScroll = false;
|
|
40
|
+
virtualScroll = true;
|
|
41
|
+
virtualScrollItemSize = 36;
|
|
42
|
+
// [virtualScrollOptions]="options"
|
|
40
43
|
/** Event to request more items */
|
|
41
44
|
loadMore = new EventEmitter();
|
|
42
45
|
/** Output selection */
|
|
@@ -44,21 +47,21 @@ class YsAutocompleteComponent {
|
|
|
44
47
|
/** Output selection after removed item */
|
|
45
48
|
removed = new EventEmitter();
|
|
46
49
|
search$ = new Subject();
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
_onChange = () => { };
|
|
51
|
+
_onTouched = () => { };
|
|
49
52
|
inputRef;
|
|
50
|
-
get isArrayItems() { return Array.isArray(this.
|
|
51
|
-
get isFunctionItems() { return typeof this.
|
|
53
|
+
get isArrayItems() { return Array.isArray(this.options); }
|
|
54
|
+
get isFunctionItems() { return typeof this.options === 'function'; }
|
|
52
55
|
constructor(elRef) {
|
|
53
56
|
this.elRef = elRef;
|
|
54
57
|
}
|
|
55
58
|
ngOnInit() {
|
|
56
|
-
if (Array.isArray(this.
|
|
57
|
-
this.
|
|
59
|
+
if (Array.isArray(this.options)) {
|
|
60
|
+
this.filteredOptions = this.options;
|
|
58
61
|
}
|
|
59
62
|
/** Only in async function mode */
|
|
60
|
-
if (typeof this.
|
|
61
|
-
const fetchFn = this.
|
|
63
|
+
if (typeof this.options === 'function') {
|
|
64
|
+
const fetchFn = this.options;
|
|
62
65
|
this.search$
|
|
63
66
|
.pipe(debounceTime(300), distinctUntilChanged(), switchMap((term) => {
|
|
64
67
|
this.loading = true;
|
|
@@ -70,7 +73,7 @@ class YsAutocompleteComponent {
|
|
|
70
73
|
}));
|
|
71
74
|
}))
|
|
72
75
|
.subscribe((results) => {
|
|
73
|
-
this.
|
|
76
|
+
this.filteredOptions = results;
|
|
74
77
|
this.loading = false;
|
|
75
78
|
this.showDropdown = true;
|
|
76
79
|
});
|
|
@@ -79,17 +82,17 @@ class YsAutocompleteComponent {
|
|
|
79
82
|
/** For the initial value of FormControl */
|
|
80
83
|
writeValue(value) {
|
|
81
84
|
if (this.multiple) {
|
|
82
|
-
this.
|
|
85
|
+
this.selectedOptions = value ? [...value] : [];
|
|
83
86
|
}
|
|
84
87
|
else {
|
|
85
88
|
this.searchTerm = value ? this.getLabel(value) : '';
|
|
86
89
|
}
|
|
87
90
|
}
|
|
88
91
|
registerOnChange(fn) {
|
|
89
|
-
this.
|
|
92
|
+
this._onChange = fn;
|
|
90
93
|
}
|
|
91
94
|
registerOnTouched(fn) {
|
|
92
|
-
this.
|
|
95
|
+
this._onTouched = fn;
|
|
93
96
|
}
|
|
94
97
|
setDisabledState(isDisabled) {
|
|
95
98
|
this.disabled = isDisabled;
|
|
@@ -99,12 +102,12 @@ class YsAutocompleteComponent {
|
|
|
99
102
|
}
|
|
100
103
|
onSearchChange() {
|
|
101
104
|
const term = this.searchTerm.trim();
|
|
102
|
-
if (Array.isArray(this.
|
|
105
|
+
if (Array.isArray(this.options)) {
|
|
103
106
|
const lower = term.toLowerCase();
|
|
104
|
-
this.
|
|
105
|
-
this.showDropdown = this.
|
|
107
|
+
this.filteredOptions = this.options.filter((item) => this.getLabel(item).toLowerCase().includes(lower));
|
|
108
|
+
this.showDropdown = this.filteredOptions.length >= 0;
|
|
106
109
|
}
|
|
107
|
-
else if (typeof this.
|
|
110
|
+
else if (typeof this.options === 'function') {
|
|
108
111
|
this.search$.next(term);
|
|
109
112
|
}
|
|
110
113
|
if (!this.multiple && !term) {
|
|
@@ -116,18 +119,19 @@ class YsAutocompleteComponent {
|
|
|
116
119
|
return '';
|
|
117
120
|
if (typeof item === 'string')
|
|
118
121
|
return item;
|
|
119
|
-
if (item && this.
|
|
120
|
-
return item[this.
|
|
122
|
+
if (item && this.optionLabel && item[this.optionLabel]) {
|
|
123
|
+
return item[this.optionLabel];
|
|
121
124
|
}
|
|
122
125
|
return '';
|
|
123
126
|
}
|
|
124
127
|
onSelect(item) {
|
|
125
128
|
if (this.multiple) {
|
|
126
|
-
const exists = this.
|
|
129
|
+
const exists = this.selectedOptions.some((x) => this.getLabel(x) === this.getLabel(item));
|
|
127
130
|
if (!exists) {
|
|
128
|
-
this.
|
|
129
|
-
this.
|
|
130
|
-
this.
|
|
131
|
+
this.selectedOptions.push(item);
|
|
132
|
+
this._onChange(this.selectedOptions);
|
|
133
|
+
this._onTouched();
|
|
134
|
+
this.selected.emit(this.selectedOptions);
|
|
131
135
|
}
|
|
132
136
|
this.searchTerm = '';
|
|
133
137
|
this.showDropdown = true;
|
|
@@ -135,16 +139,17 @@ class YsAutocompleteComponent {
|
|
|
135
139
|
}
|
|
136
140
|
else {
|
|
137
141
|
this.searchTerm = this.getLabel(item);
|
|
138
|
-
this.
|
|
142
|
+
this._onChange(item);
|
|
143
|
+
this._onTouched();
|
|
139
144
|
this.selected.emit(item);
|
|
140
145
|
this.showDropdown = false;
|
|
141
146
|
}
|
|
142
147
|
this.activeIndex = -1;
|
|
143
148
|
}
|
|
144
149
|
removeItem(item) {
|
|
145
|
-
this.
|
|
146
|
-
this.
|
|
147
|
-
this.removed.emit(this.
|
|
150
|
+
this.selectedOptions = this.selectedOptions.filter((x) => this.getLabel(x) !== this.getLabel(item));
|
|
151
|
+
this._onChange(this.selectedOptions);
|
|
152
|
+
this.removed.emit(this.selectedOptions);
|
|
148
153
|
}
|
|
149
154
|
onScroll(event) {
|
|
150
155
|
if (!this.infiniteScroll || this.loading)
|
|
@@ -158,35 +163,35 @@ class YsAutocompleteComponent {
|
|
|
158
163
|
}
|
|
159
164
|
clearSelection() {
|
|
160
165
|
if (this.multiple) {
|
|
161
|
-
this.
|
|
162
|
-
this.
|
|
163
|
-
this.removed.emit(this.
|
|
166
|
+
this.selectedOptions = [];
|
|
167
|
+
this._onChange(this.selectedOptions);
|
|
168
|
+
this.removed.emit(this.selectedOptions);
|
|
164
169
|
}
|
|
165
170
|
else {
|
|
166
171
|
this.searchTerm = '';
|
|
167
|
-
this.
|
|
172
|
+
this._onChange(null);
|
|
168
173
|
this.selected.emit(null);
|
|
169
174
|
}
|
|
170
175
|
this.showDropdown = false;
|
|
171
176
|
}
|
|
172
177
|
/** Keyboard control */
|
|
173
178
|
handleKeyboard(event) {
|
|
174
|
-
if (!this.showDropdown || this.
|
|
179
|
+
if (!this.showDropdown || this.filteredOptions.length === 0)
|
|
175
180
|
return;
|
|
176
181
|
switch (event.key) {
|
|
177
182
|
case 'ArrowDown':
|
|
178
|
-
this.activeIndex = (this.activeIndex + 1) % this.
|
|
183
|
+
this.activeIndex = (this.activeIndex + 1) % this.filteredOptions.length;
|
|
179
184
|
event.preventDefault();
|
|
180
185
|
break;
|
|
181
186
|
case 'ArrowUp':
|
|
182
187
|
this.activeIndex =
|
|
183
|
-
(this.activeIndex - 1 + this.
|
|
184
|
-
this.
|
|
188
|
+
(this.activeIndex - 1 + this.filteredOptions.length) %
|
|
189
|
+
this.filteredOptions.length;
|
|
185
190
|
event.preventDefault();
|
|
186
191
|
break;
|
|
187
192
|
case 'Enter':
|
|
188
193
|
if (this.activeIndex >= 0) {
|
|
189
|
-
this.onSelect(this.
|
|
194
|
+
this.onSelect(this.filteredOptions[this.activeIndex]);
|
|
190
195
|
event.preventDefault();
|
|
191
196
|
}
|
|
192
197
|
break;
|
|
@@ -203,13 +208,13 @@ class YsAutocompleteComponent {
|
|
|
203
208
|
}
|
|
204
209
|
}
|
|
205
210
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsAutocompleteComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
206
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsAutocompleteComponent, isStandalone: true, selector: "ys-autocomplete", inputs: {
|
|
211
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsAutocompleteComponent, isStandalone: true, selector: "ys-autocomplete", inputs: { options: "options", optionLabel: "optionLabel", placeholder: "placeholder", multiple: "multiple", showClear: "showClear", disabled: "disabled", styleClass: "styleClass", badgeStyleClass: "badgeStyleClass", loading: "loading", loadingMessage: "loadingMessage", noResultMessage: "noResultMessage", infiniteScroll: "infiniteScroll", virtualScroll: "virtualScroll", virtualScrollItemSize: "virtualScrollItemSize" }, outputs: { loadMore: "loadMore", selected: "selected", removed: "removed" }, host: { listeners: { "keydown": "handleKeyboard($event)", "document:click": "onClickOutside($event)" } }, providers: [
|
|
207
212
|
{
|
|
208
213
|
provide: NG_VALUE_ACCESSOR,
|
|
209
214
|
useExisting: forwardRef(() => YsAutocompleteComponent),
|
|
210
215
|
multi: true,
|
|
211
216
|
},
|
|
212
|
-
], 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 &&
|
|
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 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 <!-- \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 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 <!-- \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 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>", 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 .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"] }] });
|
|
213
218
|
}
|
|
214
219
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsAutocompleteComponent, decorators: [{
|
|
215
220
|
type: Component,
|
|
@@ -219,16 +224,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
|
|
|
219
224
|
useExisting: forwardRef(() => YsAutocompleteComponent),
|
|
220
225
|
multi: true,
|
|
221
226
|
},
|
|
222
|
-
], template: "<div class=\"ys-autocomplete position-relative\">\r\n <div class=\"input-group flex-wrap\">\r\n @if (multiple &&
|
|
223
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: {
|
|
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 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 <!-- \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 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 <!-- \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 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>", 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 .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"] }]
|
|
228
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { options: [{
|
|
224
229
|
type: Input
|
|
225
|
-
}],
|
|
230
|
+
}], optionLabel: [{
|
|
226
231
|
type: Input
|
|
227
232
|
}], placeholder: [{
|
|
228
233
|
type: Input
|
|
229
234
|
}], multiple: [{
|
|
230
235
|
type: Input
|
|
231
|
-
}],
|
|
236
|
+
}], showClear: [{
|
|
232
237
|
type: Input
|
|
233
238
|
}], disabled: [{
|
|
234
239
|
type: Input
|
|
@@ -247,6 +252,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
|
|
|
247
252
|
type: Input
|
|
248
253
|
}], infiniteScroll: [{
|
|
249
254
|
type: Input
|
|
255
|
+
}], virtualScroll: [{
|
|
256
|
+
type: Input
|
|
257
|
+
}], virtualScrollItemSize: [{
|
|
258
|
+
type: Input
|
|
250
259
|
}], loadMore: [{
|
|
251
260
|
type: Output
|
|
252
261
|
}], selected: [{
|
|
@@ -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 filteredItems: any[] = [];\r\n selectedItems: 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() items?: any[] | ((term: string) => Observable<any[]>);\r\n\r\n /** Label display field */\r\n @Input() labelField = 'label';\r\n\r\n /** placeholder */\r\n @Input() placeholder = 'Search...';\r\n\r\n /** Multiple choice mode */\r\n @Input() multiple = false;\r\n\r\n /** Button to clear selection */\r\n @Input() isClear = 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;\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 /** 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.items); }\r\n get isFunctionItems(): boolean { return typeof this.items === 'function'; }\r\n\r\n constructor(private elRef: ElementRef) { }\r\n\r\n ngOnInit() {\r\n if (Array.isArray(this.items)) {\r\n this.filteredItems = this.items;\r\n }\r\n\r\n /** Only in async function mode */\r\n if (typeof this.items === 'function') {\r\n const fetchFn = this.items 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.filteredItems = 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.selectedItems = 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.items)) {\r\n const lower = term.toLowerCase();\r\n this.filteredItems = this.items.filter((item) =>\r\n this.getLabel(item).toLowerCase().includes(lower)\r\n );\r\n this.showDropdown = this.filteredItems.length >= 0;\r\n } else if (typeof this.items === '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.labelField && item[this.labelField]) {\r\n return item[this.labelField];\r\n }\r\n return '';\r\n }\r\n\r\n onSelect(item: any) {\r\n if (this.multiple) {\r\n const exists = this.selectedItems.some(\r\n (x) => this.getLabel(x) === this.getLabel(item)\r\n );\r\n if (!exists) {\r\n this.selectedItems.push(item);\r\n this.onChange(this.selectedItems);\r\n this.selected.emit(this.selectedItems);\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.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.selectedItems = this.selectedItems.filter(\r\n (x) => this.getLabel(x) !== this.getLabel(item)\r\n );\r\n this.onChange(this.selectedItems);\r\n this.removed.emit(this.selectedItems);\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.selectedItems = [];\r\n this.onChange(this.selectedItems);\r\n this.removed.emit(this.selectedItems);\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.filteredItems.length === 0) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n this.activeIndex = (this.activeIndex + 1) % this.filteredItems.length;\r\n event.preventDefault();\r\n break;\r\n case 'ArrowUp':\r\n this.activeIndex =\r\n (this.activeIndex - 1 + this.filteredItems.length) %\r\n this.filteredItems.length;\r\n event.preventDefault();\r\n break;\r\n case 'Enter':\r\n if (this.activeIndex >= 0) {\r\n this.onSelect(this.filteredItems[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 && selectedItems.length > 0) {\r\n <div class=\"d-flex flex-wrap\">\r\n @for (item of selectedItems; track item) {\r\n <span class=\"badge text-bg-primary 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 (isClear) {\r\n @if ((multiple && selectedItems.length > 0) || (!multiple && searchTerm)) {\r\n <button class=\"btn btn-outline-danger btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearSelection()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-trash\"></span>\r\n </button>\r\n }\r\n }\r\n @if(showDropdown){\r\n <span class=\"input-group-text\" (click)=\"showDropdown = false\">\r\n <i class=\"fa fa-times\"></i>\r\n </span>\r\n }\r\n @else{\r\n <span class=\"input-group-text\" (click)=\"showDropdown = true\">\r\n <i class=\"fa fa-search\"></i>\r\n </span>\r\n }\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 } @else if (error) {\r\n <div class=\"list-group-item text-danger text-center\">{{ error }}</div>\r\n } @else if (filteredItems.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 (filteredItems.length > 100) {\r\n <cdk-virtual-scroll-viewport itemSize=\"36\" class=\"list-group w-100 overflow-y-auto\">\r\n <ul class=\"list-group w-100\">\r\n @for (item of filteredItems; 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 filteredItems; 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":";;;;;;;;;MAmBa,uBAAuB,CAAA;AAyDd,IAAA,KAAA;IAvDpB,UAAU,GAAG,EAAE;IACf,aAAa,GAAU,EAAE;IACzB,aAAa,GAAU,EAAE;IACzB,YAAY,GAAG,KAAK;IACpB,WAAW,GAAG,CAAC,CAAC;IAChB,KAAK,GAAkB,IAAI;;AAGlB,IAAA,KAAK;;IAGL,UAAU,GAAG,OAAO;;IAGpB,WAAW,GAAG,WAAW;;IAGzB,QAAQ,GAAG,KAAK;;IAGhB,OAAO,GAAG,KAAK;IAEf,QAAQ,GAAY,KAAK;;AAGP,IAAA,YAAY;AAE9B,IAAA,UAAU;;AAEV,IAAA,eAAe;IACf,OAAO,GAAY,KAAK;IACxB,cAAc,GAAW,YAAY;;IAErC,eAAe,GAAW,mBAAmB;;IAG7C,cAAc,GAAG,KAAK;;AAGrB,IAAA,QAAQ,GAAG,IAAI,YAAY,EAAU;;AAGrC,IAAA,QAAQ,GAAG,IAAI,YAAY,EAAO;;AAElC,IAAA,OAAO,GAAG,IAAI,YAAY,EAAO;AAEnC,IAAA,OAAO,GAAG,IAAI,OAAO,EAAU;AAC/B,IAAA,QAAQ,GAAyB,MAAK,GAAI;AAC1C,IAAA,SAAS,GAAe,MAAK,GAAI;AAElB,IAAA,QAAQ;AAE/B,IAAA,IAAI,YAAY,GAAA,EAAc,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,eAAe,GAAA,EAAc,OAAO,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,CAAC;AAEzE,IAAA,WAAA,CAAoB,KAAiB,EAAA;QAAjB,IAAA,CAAA,KAAK,GAAL,KAAK;;IAEzB,QAAQ,GAAA;QACN,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC7B,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK;;;AAIjC,QAAA,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,EAAE;AACpC,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAA4C;AACjE,YAAA,IAAI,CAAC;AACF,iBAAA,IAAI,CACH,YAAY,CAAC,GAAG,CAAC,EACjB,oBAAoB,EAAE,EACtB,SAAS,CAAC,CAAC,IAAI,KAAI;AACjB,gBAAA,IAAI,CAAC,OAAO,GAAG,IAAI;AACnB,gBAAA,IAAI,CAAC,KAAK,GAAG,IAAI;AACjB,gBAAA,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CACvB,UAAU,CAAC,CAAC,GAAG,KAAI;AACjB,oBAAA,IAAI,CAAC,KAAK,GAAG,uBAAuB;AACpC,oBAAA,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC;AAClB,oBAAA,OAAO,EAAE,CAAC,EAAE,CAAC;iBACd,CAAC,CACH;AACH,aAAC,CAAC;AAEH,iBAAA,SAAS,CAAC,CAAC,OAAO,KAAI;AACrB,gBAAA,IAAI,CAAC,aAAa,GAAG,OAAO;AAC5B,gBAAA,IAAI,CAAC,OAAO,GAAG,KAAK;AACpB,gBAAA,IAAI,CAAC,YAAY,GAAG,IAAI;AAC1B,aAAC,CAAC;;;;AAMR,IAAA,UAAU,CAAC,KAAU,EAAA;AACnB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAA,IAAI,CAAC,aAAa,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,EAAE;;aACvC;AACL,YAAA,IAAI,CAAC,UAAU,GAAG,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE;;;AAIvD,IAAA,gBAAgB,CAAC,EAAO,EAAA;AACtB,QAAA,IAAI,CAAC,QAAQ,GAAG,EAAE;;AAGpB,IAAA,iBAAiB,CAAC,EAAO,EAAA;AACvB,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;;AAGrB,IAAA,gBAAgB,CAAE,UAAmB,EAAA;AACnC,QAAA,IAAI,CAAC,QAAQ,GAAG,UAAU;AAC1B,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,GAAG,UAAU;;;IAIrD,cAAc,GAAA;QACZ,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE;QAEnC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC7B,YAAA,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE;AAChC,YAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,KAC1C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAClD;YACD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC;;AAC7C,aAAA,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,UAAU,EAAE;AAC3C,YAAA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;;QAGzB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE;YAC3B,IAAI,CAAC,cAAc,EAAE;;;AAIzB,IAAA,QAAQ,CAAC,IAAS,EAAA;AAChB,QAAA,IAAI,CAAC,IAAI;AAAE,YAAA,OAAO,EAAE;QACpB,IAAI,OAAO,IAAI,KAAK,QAAQ;AAAE,YAAA,OAAO,IAAI;AACzC,QAAA,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACpD,YAAA,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;;AAE9B,QAAA,OAAO,EAAE;;AAGX,IAAA,QAAQ,CAAC,IAAS,EAAA;AAChB,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjB,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CACpC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAChD;YACD,IAAI,CAAC,MAAM,EAAE;AACX,gBAAA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;AAC7B,gBAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;gBACjC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;;AAExC,YAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AACpB,YAAA,IAAI,CAAC,YAAY,GAAG,IAAI;YACxB,IAAI,CAAC,cAAc,EAAE;;aAChB;YACL,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACrC,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;AACxB,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;;AAG3B,QAAA,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;;AAGvB,IAAA,UAAU,CAAC,IAAS,EAAA;AAClB,QAAA,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAC5C,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAChD;AACD,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;QACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;;AAGvC,IAAA,QAAQ,CAAC,KAAY,EAAA;AACnB,QAAA,IAAI,CAAC,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,OAAO;YAAE;AAE1C,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB;AAC1C,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,YAAY,GAAG,EAAE;QAErF,IAAI,UAAU,EAAE;;YAEd,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;;;IAIvC,cAAc,GAAA;AACZ,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE;AACjB,YAAA,IAAI,CAAC,aAAa,GAAG,EAAE;AACvB,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;;aAChC;AACL,YAAA,IAAI,CAAC,UAAU,GAAG,EAAE;AACpB,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnB,YAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;;AAG1B,QAAA,IAAI,CAAC,YAAY,GAAG,KAAK;;;AAK3B,IAAA,cAAc,CAAC,KAAoB,EAAA;QACjC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE;AAE3D,QAAA,QAAQ,KAAK,CAAC,GAAG;AACf,YAAA,KAAK,WAAW;AACd,gBAAA,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM;gBACrE,KAAK,CAAC,cAAc,EAAE;gBACtB;AACF,YAAA,KAAK,SAAS;AACZ,gBAAA,IAAI,CAAC,WAAW;oBACd,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM;AACjD,wBAAA,IAAI,CAAC,aAAa,CAAC,MAAM;gBAC3B,KAAK,CAAC,cAAc,EAAE;gBACtB;AACF,YAAA,KAAK,OAAO;AACV,gBAAA,IAAI,IAAI,CAAC,WAAW,IAAI,CAAC,EAAE;AACzB,oBAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;oBACnD,KAAK,CAAC,cAAc,EAAE;;gBAExB;AACF,YAAA,KAAK,QAAQ;AACX,gBAAA,IAAI,CAAC,YAAY,GAAG,KAAK;gBACzB;;;;AAMN,IAAA,cAAc,CAAC,KAAiB,EAAA;AAC9B,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QACrE,IAAI,CAAC,aAAa,EAAE;AAClB,YAAA,IAAI,CAAC,YAAY,GAAG,KAAK;;;uGAzOlB,uBAAuB,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAvB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,uBAAuB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,UAAA,EAAA,YAAA,EAAA,WAAA,EAAA,aAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,UAAA,EAAA,YAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,SAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,eAAA,EAAA,iBAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,UAAA,EAAA,OAAA,EAAA,SAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,SAAA,EAAA,wBAAA,EAAA,gBAAA,EAAA,wBAAA,EAAA,EAAA,EAAA,SAAA,EARvB;AACT,YAAA;AACE,gBAAA,OAAO,EAAE,iBAAiB;AAC1B,gBAAA,WAAW,EAAE,UAAU,CAAC,MAAM,uBAAuB,CAAC;AACtD,gBAAA,KAAK,EAAE,IAAI;AACZ,aAAA;SACF,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,cAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EA6Ba,WAAW,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,UAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,UAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC9C3B,goIAsFM,EAAA,MAAA,EAAA,CAAA,4RAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED9EM,WAAW,+mBAAE,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,OAAO,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAE,eAAe,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,yBAAA,EAAA,QAAA,EAAA,uCAAA,EAAA,MAAA,EAAA,CAAA,UAAA,EAAA,aAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,wBAAA,EAAA,QAAA,EAAA,6BAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAWtD,uBAAuB,EAAA,UAAA,EAAA,CAAA;kBAbnC,SAAS;+BACE,iBAAiB,EAAA,OAAA,EAClB,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,EAAA,SAAA,EAGvD;AACT,wBAAA;AACE,4BAAA,OAAO,EAAE,iBAAiB;AAC1B,4BAAA,WAAW,EAAE,UAAU,CAAC,6BAA6B,CAAC;AACtD,4BAAA,KAAK,EAAE,IAAI;AACZ,yBAAA;AACF,qBAAA,EAAA,QAAA,EAAA,goIAAA,EAAA,MAAA,EAAA,CAAA,4RAAA,CAAA,EAAA;+EAYQ,KAAK,EAAA,CAAA;sBAAb;gBAGQ,UAAU,EAAA,CAAA;sBAAlB;gBAGQ,WAAW,EAAA,CAAA;sBAAnB;gBAGQ,QAAQ,EAAA,CAAA;sBAAhB;gBAGQ,OAAO,EAAA,CAAA;sBAAf;gBAEQ,QAAQ,EAAA,CAAA;sBAAhB;gBAG0B,YAAY,EAAA,CAAA;sBAAtC,YAAY;uBAAC,WAAW;gBAEhB,UAAU,EAAA,CAAA;sBAAlB;gBAEQ,eAAe,EAAA,CAAA;sBAAvB;gBACQ,OAAO,EAAA,CAAA;sBAAf;gBACQ,cAAc,EAAA,CAAA;sBAAtB;gBAEQ,eAAe,EAAA,CAAA;sBAAvB;gBAGQ,cAAc,EAAA,CAAA;sBAAtB;gBAGS,QAAQ,EAAA,CAAA;sBAAjB;gBAGS,QAAQ,EAAA,CAAA;sBAAjB;gBAES,OAAO,EAAA,CAAA;sBAAhB;gBAMsB,QAAQ,EAAA,CAAA;sBAA9B,SAAS;uBAAC,UAAU;gBAsJrB,cAAc,EAAA,CAAA;sBADb,YAAY;uBAAC,SAAS,EAAE,CAAC,QAAQ,CAAC;gBA6BnC,cAAc,EAAA,CAAA;sBADb,YAAY;uBAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC;;;AExP5C;;AAEG;;ACFH;;AAEG;;;;"}
|
|
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 | null = null;\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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"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { EventEmitter, inject, ElementRef, forwardRef, HostListener, Output, Input, Component } from '@angular/core';
|
|
4
|
+
import * as i1 from '@angular/forms';
|
|
5
|
+
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
|
+
|
|
7
|
+
class YsDropdownComponent {
|
|
8
|
+
/** لیست گزینهها */
|
|
9
|
+
options = [];
|
|
10
|
+
optionLabel = 'label';
|
|
11
|
+
placeholder = '';
|
|
12
|
+
searchPlaceholder = '';
|
|
13
|
+
selectedMaxLength = 3;
|
|
14
|
+
selectedMaxLengthTemplate = '{length} items selected';
|
|
15
|
+
selectionSeparator = ", ";
|
|
16
|
+
/** انتخاب چندگانه یا تکی */
|
|
17
|
+
multiple = false;
|
|
18
|
+
showClear = false;
|
|
19
|
+
/** تمپلیت سفارشی برای آیتمها */
|
|
20
|
+
itemTemplate;
|
|
21
|
+
/** مقدار انتخابشده */
|
|
22
|
+
selected = this.multiple ? [] : null;
|
|
23
|
+
/** قابلیت جستجو */
|
|
24
|
+
searchable = true;
|
|
25
|
+
disabled = false;
|
|
26
|
+
/** رویداد خروجی هنگام تغییر انتخاب */
|
|
27
|
+
selectionChange = new EventEmitter();
|
|
28
|
+
searchTerm = '';
|
|
29
|
+
isOpen = false;
|
|
30
|
+
highlightedIndex = -1;
|
|
31
|
+
elRef = inject(ElementRef);
|
|
32
|
+
_onChange = () => { };
|
|
33
|
+
_onTouched = () => { };
|
|
34
|
+
writeValue(obj) {
|
|
35
|
+
if (this.multiple) {
|
|
36
|
+
this.selected = obj ? [...obj] : [];
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.selected = obj;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
registerOnChange(fn) {
|
|
43
|
+
this._onChange = fn;
|
|
44
|
+
}
|
|
45
|
+
registerOnTouched(fn) {
|
|
46
|
+
this._onTouched = fn;
|
|
47
|
+
}
|
|
48
|
+
setDisabledState(isDisabled) {
|
|
49
|
+
this.disabled = isDisabled;
|
|
50
|
+
}
|
|
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 ?? 'انتخاب کنید';
|
|
59
|
+
}
|
|
60
|
+
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);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return this.selected ? this.selected[this.optionLabel] : '';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
toggleDropdown() {
|
|
72
|
+
this.isOpen = !this.isOpen;
|
|
73
|
+
if (this.isOpen) {
|
|
74
|
+
this.highlightedIndex = -1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
filterOptions() {
|
|
78
|
+
let list = this.options;
|
|
79
|
+
if (this.searchable && this.searchTerm.trim()) {
|
|
80
|
+
const term = this.searchTerm.toLowerCase();
|
|
81
|
+
list = this.options.filter(opt => opt[this.optionLabel].toLowerCase().includes(term));
|
|
82
|
+
}
|
|
83
|
+
// هر بار جستجو انجام شد index ریست بشه
|
|
84
|
+
this.highlightedIndex = Math.min(this.highlightedIndex, list.length - 1);
|
|
85
|
+
return list;
|
|
86
|
+
}
|
|
87
|
+
selectOption(option) {
|
|
88
|
+
if (option.disabled)
|
|
89
|
+
return;
|
|
90
|
+
if (this.multiple) {
|
|
91
|
+
const exists = this.selected?.some((x) => x === option);
|
|
92
|
+
this.selected = exists
|
|
93
|
+
? this.selected.filter((x) => x !== option)
|
|
94
|
+
: [...(this.selected || []), option];
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.selected = option;
|
|
98
|
+
this.isOpen = false;
|
|
99
|
+
}
|
|
100
|
+
this._onChange(this.selected);
|
|
101
|
+
this._onTouched();
|
|
102
|
+
this.selectionChange.emit(this.selected);
|
|
103
|
+
}
|
|
104
|
+
isSelected(option) {
|
|
105
|
+
return this.multiple
|
|
106
|
+
? this.selected?.includes(option)
|
|
107
|
+
: this.selected === option;
|
|
108
|
+
}
|
|
109
|
+
clearSelection() {
|
|
110
|
+
this.selected = this.multiple ? [] : null;
|
|
111
|
+
this._onChange(this.selected);
|
|
112
|
+
this._onTouched();
|
|
113
|
+
this.selectionChange.emit(this.selected);
|
|
114
|
+
}
|
|
115
|
+
onKeyDown(event) {
|
|
116
|
+
const filtered = this.filterOptions();
|
|
117
|
+
if (!filtered.length)
|
|
118
|
+
return;
|
|
119
|
+
switch (event.key) {
|
|
120
|
+
case 'ArrowDown':
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
this.highlightedIndex = (this.highlightedIndex + 1) % filtered.length;
|
|
123
|
+
this.scrollToHighlighted();
|
|
124
|
+
break;
|
|
125
|
+
case 'ArrowUp':
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
this.highlightedIndex = this.highlightedIndex > 0 ? this.highlightedIndex - 1 : filtered.length - 1;
|
|
128
|
+
this.scrollToHighlighted();
|
|
129
|
+
break;
|
|
130
|
+
case 'Enter':
|
|
131
|
+
event.preventDefault();
|
|
132
|
+
if (this.highlightedIndex >= 0 && this.highlightedIndex < filtered.length) {
|
|
133
|
+
this.selectOption(filtered[this.highlightedIndex]);
|
|
134
|
+
}
|
|
135
|
+
break;
|
|
136
|
+
case 'Escape':
|
|
137
|
+
this.isOpen = false;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
scrollToHighlighted() {
|
|
142
|
+
// تأخیر جزئی برای اطمینان از رندر کامل
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
const dropdown = this.elRef.nativeElement.querySelector('.dropdown-menu');
|
|
145
|
+
const items = dropdown?.querySelectorAll('.dropdown-item');
|
|
146
|
+
const activeItem = items?.[this.highlightedIndex];
|
|
147
|
+
if (activeItem && dropdown) {
|
|
148
|
+
const itemTop = activeItem.offsetTop;
|
|
149
|
+
const itemBottom = itemTop + activeItem.offsetHeight;
|
|
150
|
+
const dropdownScrollTop = dropdown.scrollTop;
|
|
151
|
+
const dropdownHeight = dropdown.clientHeight;
|
|
152
|
+
if (itemBottom > dropdownScrollTop + dropdownHeight) {
|
|
153
|
+
dropdown.scrollTop = itemBottom - dropdownHeight;
|
|
154
|
+
}
|
|
155
|
+
else if (itemTop < dropdownScrollTop) {
|
|
156
|
+
dropdown.scrollTop = itemTop;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
/** Close by clicking outside */
|
|
162
|
+
onClickOutside(event) {
|
|
163
|
+
const clickedInside = this.elRef.nativeElement.contains(event.target);
|
|
164
|
+
if (!clickedInside) {
|
|
165
|
+
this.isOpen = false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
169
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsDropdownComponent, isStandalone: true, selector: "ys-dropdown", inputs: { options: "options", optionLabel: "optionLabel", placeholder: "placeholder", searchPlaceholder: "searchPlaceholder", selectedMaxLength: "selectedMaxLength", selectedMaxLengthTemplate: "selectedMaxLengthTemplate", selectionSeparator: "selectionSeparator", multiple: "multiple", showClear: "showClear", itemTemplate: "itemTemplate", selected: "selected", searchable: "searchable", disabled: "disabled" }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
|
|
170
|
+
{
|
|
171
|
+
provide: NG_VALUE_ACCESSOR,
|
|
172
|
+
useExisting: forwardRef(() => YsDropdownComponent),
|
|
173
|
+
multi: true,
|
|
174
|
+
},
|
|
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(isSelected(option)){\r\n <i class=\"fa fa-check text-success ms-auto\"></i>\r\n }\r\n {{option[optionLabel]}}\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
|
+
}
|
|
177
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsDropdownComponent, decorators: [{
|
|
178
|
+
type: Component,
|
|
179
|
+
args: [{ selector: 'ys-dropdown', imports: [NgTemplateOutlet, FormsModule], providers: [
|
|
180
|
+
{
|
|
181
|
+
provide: NG_VALUE_ACCESSOR,
|
|
182
|
+
useExisting: forwardRef(() => YsDropdownComponent),
|
|
183
|
+
multi: true,
|
|
184
|
+
},
|
|
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(isSelected(option)){\r\n <i class=\"fa fa-check text-success ms-auto\"></i>\r\n }\r\n {{option[optionLabel]}}\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
|
+
}], propDecorators: { options: [{
|
|
187
|
+
type: Input
|
|
188
|
+
}], optionLabel: [{
|
|
189
|
+
type: Input
|
|
190
|
+
}], placeholder: [{
|
|
191
|
+
type: Input
|
|
192
|
+
}], searchPlaceholder: [{
|
|
193
|
+
type: Input
|
|
194
|
+
}], selectedMaxLength: [{
|
|
195
|
+
type: Input
|
|
196
|
+
}], selectedMaxLengthTemplate: [{
|
|
197
|
+
type: Input
|
|
198
|
+
}], selectionSeparator: [{
|
|
199
|
+
type: Input
|
|
200
|
+
}], multiple: [{
|
|
201
|
+
type: Input
|
|
202
|
+
}], showClear: [{
|
|
203
|
+
type: Input
|
|
204
|
+
}], itemTemplate: [{
|
|
205
|
+
type: Input
|
|
206
|
+
}], selected: [{
|
|
207
|
+
type: Input
|
|
208
|
+
}], searchable: [{
|
|
209
|
+
type: Input
|
|
210
|
+
}], disabled: [{
|
|
211
|
+
type: Input
|
|
212
|
+
}], selectionChange: [{
|
|
213
|
+
type: Output
|
|
214
|
+
}], onClickOutside: [{
|
|
215
|
+
type: HostListener,
|
|
216
|
+
args: ['document:click', ['$event']]
|
|
217
|
+
}] } });
|
|
218
|
+
|
|
219
|
+
/*
|
|
220
|
+
* Public API Surface of ys-dropdown
|
|
221
|
+
*/
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Generated bundle index. Do not edit.
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
export { YsDropdownComponent };
|
|
228
|
+
//# sourceMappingURL=yoozsoft-yoozsoft-ng-dropdown.mjs.map
|
|
@@ -0,0 +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 = true;\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(isSelected(option)){\r\n <i class=\"fa fa-check text-success ms-auto\"></i>\r\n }\r\n {{option[optionLabel]}}\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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"}
|
|
@@ -21,7 +21,7 @@ class YsSelectComponent {
|
|
|
21
21
|
/**Size of multiple attribute */
|
|
22
22
|
size;
|
|
23
23
|
/**Display clear button */
|
|
24
|
-
|
|
24
|
+
showClear = false;
|
|
25
25
|
disabled = false;
|
|
26
26
|
selected = new EventEmitter();
|
|
27
27
|
onChange = () => { };
|
|
@@ -72,13 +72,13 @@ class YsSelectComponent {
|
|
|
72
72
|
return typeof item == 'object';
|
|
73
73
|
}
|
|
74
74
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
75
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsSelectComponent, isStandalone: true, selector: "ys-select", inputs: { id: "id", options: "options", optionLabel: "optionLabel", placeholder: "placeholder", styleClass: "styleClass", invalid: "invalid", invalidFeedback: "invalidFeedback", valid: "valid", validFeedback: "validFeedback", multiple: "multiple", size: "size",
|
|
75
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: YsSelectComponent, isStandalone: true, selector: "ys-select", inputs: { id: "id", options: "options", optionLabel: "optionLabel", placeholder: "placeholder", styleClass: "styleClass", invalid: "invalid", invalidFeedback: "invalidFeedback", valid: "valid", validFeedback: "validFeedback", multiple: "multiple", size: "size", showClear: "showClear", disabled: "disabled" }, outputs: { selected: "selected" }, providers: [
|
|
76
76
|
{
|
|
77
77
|
provide: NG_VALUE_ACCESSOR,
|
|
78
78
|
useExisting: forwardRef(() => YsSelectComponent),
|
|
79
79
|
multi: true
|
|
80
80
|
}
|
|
81
|
-
], ngImport: i0, template: "<div class=\"ys-select\" [ngClass]=\"{'input-group':
|
|
81
|
+
], ngImport: i0, template: "<div class=\"ys-select\" [ngClass]=\"{'input-group': showClear, 'is-valid': valid, 'is-invalid': invalid}\">\r\n\r\n @if (!multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\" class=\"d-none\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\"\r\n [multiple]=\"multiple\" [size]=\"size\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (showClear) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearValue()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-times\"></span>\r\n </button>\r\n }\r\n</div>\r\n\r\n@if(valid && validFeedback){\r\n<div class=\"valid-feedback\">{{validFeedback}}</div>\r\n}\r\n@if(invalid && invalidFeedback){\r\n<div class=\"invalid-feedback\">{{invalidFeedback}}</div>\r\n}", styles: [""], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.SelectMultipleControlValueAccessor, selector: "select[multiple][formControlName],select[multiple][formControl],select[multiple][ngModel]", inputs: ["compareWith"] }, { 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: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
|
|
82
82
|
}
|
|
83
83
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: YsSelectComponent, decorators: [{
|
|
84
84
|
type: Component,
|
|
@@ -88,7 +88,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
|
|
|
88
88
|
useExisting: forwardRef(() => YsSelectComponent),
|
|
89
89
|
multi: true
|
|
90
90
|
}
|
|
91
|
-
], template: "<div class=\"ys-select\" [ngClass]=\"{'input-group':
|
|
91
|
+
], template: "<div class=\"ys-select\" [ngClass]=\"{'input-group': showClear, 'is-valid': valid, 'is-invalid': invalid}\">\r\n\r\n @if (!multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\" class=\"d-none\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\"\r\n [multiple]=\"multiple\" [size]=\"size\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (showClear) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearValue()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-times\"></span>\r\n </button>\r\n }\r\n</div>\r\n\r\n@if(valid && validFeedback){\r\n<div class=\"valid-feedback\">{{validFeedback}}</div>\r\n}\r\n@if(invalid && invalidFeedback){\r\n<div class=\"invalid-feedback\">{{invalidFeedback}}</div>\r\n}" }]
|
|
92
92
|
}], propDecorators: { id: [{
|
|
93
93
|
type: Input
|
|
94
94
|
}], options: [{
|
|
@@ -111,7 +111,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
|
|
|
111
111
|
type: Input
|
|
112
112
|
}], size: [{
|
|
113
113
|
type: Input
|
|
114
|
-
}],
|
|
114
|
+
}], showClear: [{
|
|
115
115
|
type: Input
|
|
116
116
|
}], disabled: [{
|
|
117
117
|
type: Input
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yoozsoft-yoozsoft-ng-select.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/select/src/ys-select/ys-select.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/select/src/ys-select/ys-select.component.html","../../../../projects/yoozsoft/yoozsoft-ng/select/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/select/yoozsoft-yoozsoft-ng-select.ts"],"sourcesContent":["\r\nimport { NgClass } from '@angular/common';\r\nimport { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'ys-select',\r\n imports: [FormsModule, NgClass],\r\n templateUrl: './ys-select.component.html',\r\n styleUrl: './ys-select.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsSelectComponent),\r\n multi: true\r\n }\r\n ]\r\n})\r\nexport class YsSelectComponent implements ControlValueAccessor {\r\n\r\n /**ُSelect element id */\r\n @Input() id: string = 'ys-select';\r\n @Input() options: any[] = [];\r\n /**Name of field to display in option title */\r\n @Input() optionLabel: string = 'label';\r\n @Input() placeholder?: string;\r\n @Input() styleClass?: string;\r\n @Input() invalid?: boolean = false;\r\n @Input() invalidFeedback?: string;\r\n @Input() valid?: boolean = false;\r\n @Input() validFeedback?: string;\r\n /**Support multiple attribute */\r\n @Input() multiple?: boolean = false;\r\n /**Size of multiple attribute */\r\n @Input() size?: number;\r\n /**Display clear button */\r\n @Input()
|
|
1
|
+
{"version":3,"file":"yoozsoft-yoozsoft-ng-select.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/select/src/ys-select/ys-select.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/select/src/ys-select/ys-select.component.html","../../../../projects/yoozsoft/yoozsoft-ng/select/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/select/yoozsoft-yoozsoft-ng-select.ts"],"sourcesContent":["\r\nimport { NgClass } from '@angular/common';\r\nimport { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\n@Component({\r\n selector: 'ys-select',\r\n imports: [FormsModule, NgClass],\r\n templateUrl: './ys-select.component.html',\r\n styleUrl: './ys-select.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsSelectComponent),\r\n multi: true\r\n }\r\n ]\r\n})\r\nexport class YsSelectComponent implements ControlValueAccessor {\r\n\r\n /**ُSelect element id */\r\n @Input() id: string = 'ys-select';\r\n @Input() options: any[] = [];\r\n /**Name of field to display in option title */\r\n @Input() optionLabel: string = 'label';\r\n @Input() placeholder?: string;\r\n @Input() styleClass?: string;\r\n @Input() invalid?: boolean = false;\r\n @Input() invalidFeedback?: string;\r\n @Input() valid?: boolean = false;\r\n @Input() validFeedback?: string;\r\n /**Support multiple attribute */\r\n @Input() multiple?: boolean = false;\r\n /**Size of multiple attribute */\r\n @Input() size?: number;\r\n /**Display clear button */\r\n @Input() showClear?: boolean = false;\r\n\r\n @Input() disabled: boolean = false;\r\n @Output() selected: EventEmitter<any> = new EventEmitter<any>();\r\n\r\n onChange: any = () => { }\r\n onTouched: any = () => { }\r\n\r\n value?: any;\r\n\r\n writeValue(obj: any): void {\r\n if (!this.multiple && this.placeholder && !obj) {\r\n this.value = null;\r\n this.onChange(this.value);\r\n return;\r\n }\r\n\r\n if (this.multiple && !obj) {\r\n this.multiple ? this.value = [] : this.value = null;\r\n this.onChange(this.value);\r\n return;\r\n }\r\n\r\n if (!this.multiple && obj && Array.isArray(obj)) {\r\n if (obj.length) {\r\n this.value = obj[0];\r\n }\r\n else {\r\n this.value = null;\r\n }\r\n this.onChange(this.value);\r\n return;\r\n }\r\n\r\n this.value = obj;\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 onModelChange(option: any) {\r\n this.onChange(option);\r\n this.onTouched(option);\r\n this.selected.emit(option);\r\n }\r\n\r\n clearValue() {\r\n this.multiple ? this.value = [] : this.value = null;\r\n this.onModelChange(this.value);\r\n }\r\n\r\n isObject(item: any) {\r\n return typeof item == 'object';\r\n }\r\n\r\n}\r\n","<div class=\"ys-select\" [ngClass]=\"{'input-group': showClear, 'is-valid': valid, 'is-invalid': invalid}\">\r\n\r\n @if (!multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\" class=\"d-none\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (multiple) {\r\n <select [id]=\"id\" class=\"form-select {{styleClass}}\" [ngClass]=\"{'is-valid': valid, 'is-invalid': invalid}\"\r\n aria-label=\"Select option\" [(ngModel)]=\"value\" (ngModelChange)=\"onModelChange($event)\" [disabled]=\"disabled\"\r\n [multiple]=\"multiple\" [size]=\"size\">\r\n @if (placeholder) {\r\n <option selected disabled [ngValue]=\"null\"> {{placeholder}}\r\n </option>\r\n }\r\n @for (item of options; track item; let i = $index) {\r\n <option [selected]=\" i === 0 && !placeholder \" [ngValue]=\"item\">\r\n {{isObject(item) ? item[optionLabel] : item}}\r\n </option>\r\n }\r\n </select>\r\n }\r\n\r\n @if (showClear) {\r\n <button class=\"btn btn-outline-secondary btn-clear\" type=\"button\" id=\"btn-clear\" (click)=\"clearValue()\"\r\n [disabled]=\"disabled\">\r\n <span class=\"fa fa-times\"></span>\r\n </button>\r\n }\r\n</div>\r\n\r\n@if(valid && validFeedback){\r\n<div class=\"valid-feedback\">{{validFeedback}}</div>\r\n}\r\n@if(invalid && invalidFeedback){\r\n<div class=\"invalid-feedback\">{{invalidFeedback}}</div>\r\n}","/*\r\n * Public API Surface of ys-select\r\n */\r\n\r\nexport * from './src/ys-select/ys-select.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
|
+
"version": "5.2.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"@angular/common": "^20.0.0",
|
|
6
6
|
"@angular/core": "^20.0.0"
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"ng-bootstrap",
|
|
16
16
|
"components",
|
|
17
17
|
"autocomplete",
|
|
18
|
+
"dropdown",
|
|
18
19
|
"file-upload",
|
|
19
20
|
"navbar",
|
|
20
21
|
"password-strength",
|
|
@@ -40,17 +41,21 @@
|
|
|
40
41
|
"types": "./autocomplete/index.d.ts",
|
|
41
42
|
"default": "./fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs"
|
|
42
43
|
},
|
|
43
|
-
"./
|
|
44
|
-
"types": "./
|
|
45
|
-
"default": "./fesm2022/yoozsoft-yoozsoft-ng-
|
|
44
|
+
"./datepicker": {
|
|
45
|
+
"types": "./datepicker/index.d.ts",
|
|
46
|
+
"default": "./fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs"
|
|
47
|
+
},
|
|
48
|
+
"./dropdown": {
|
|
49
|
+
"types": "./dropdown/index.d.ts",
|
|
50
|
+
"default": "./fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs"
|
|
46
51
|
},
|
|
47
52
|
"./directives": {
|
|
48
53
|
"types": "./directives/index.d.ts",
|
|
49
54
|
"default": "./fesm2022/yoozsoft-yoozsoft-ng-directives.mjs"
|
|
50
55
|
},
|
|
51
|
-
"./
|
|
52
|
-
"types": "./
|
|
53
|
-
"default": "./fesm2022/yoozsoft-yoozsoft-ng-
|
|
56
|
+
"./file-upload": {
|
|
57
|
+
"types": "./file-upload/index.d.ts",
|
|
58
|
+
"default": "./fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs"
|
|
54
59
|
},
|
|
55
60
|
"./footer": {
|
|
56
61
|
"types": "./footer/index.d.ts",
|
|
@@ -68,9 +73,9 @@
|
|
|
68
73
|
"types": "./overlay/index.d.ts",
|
|
69
74
|
"default": "./fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs"
|
|
70
75
|
},
|
|
71
|
-
"./
|
|
72
|
-
"types": "./
|
|
73
|
-
"default": "./fesm2022/yoozsoft-yoozsoft-ng-
|
|
76
|
+
"./progress": {
|
|
77
|
+
"types": "./progress/index.d.ts",
|
|
78
|
+
"default": "./fesm2022/yoozsoft-yoozsoft-ng-progress.mjs"
|
|
74
79
|
},
|
|
75
80
|
"./password-strength": {
|
|
76
81
|
"types": "./password-strength/index.d.ts",
|
|
@@ -88,9 +93,9 @@
|
|
|
88
93
|
"types": "./toast/index.d.ts",
|
|
89
94
|
"default": "./fesm2022/yoozsoft-yoozsoft-ng-toast.mjs"
|
|
90
95
|
},
|
|
91
|
-
"./
|
|
92
|
-
"types": "./
|
|
93
|
-
"default": "./fesm2022/yoozsoft-yoozsoft-ng-
|
|
96
|
+
"./sidebar": {
|
|
97
|
+
"types": "./sidebar/index.d.ts",
|
|
98
|
+
"default": "./fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs"
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
}
|
package/select/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ declare class YsSelectComponent implements ControlValueAccessor {
|
|
|
19
19
|
/**Size of multiple attribute */
|
|
20
20
|
size?: number;
|
|
21
21
|
/**Display clear button */
|
|
22
|
-
|
|
22
|
+
showClear?: boolean;
|
|
23
23
|
disabled: boolean;
|
|
24
24
|
selected: EventEmitter<any>;
|
|
25
25
|
onChange: any;
|
|
@@ -33,7 +33,7 @@ declare class YsSelectComponent implements ControlValueAccessor {
|
|
|
33
33
|
clearValue(): void;
|
|
34
34
|
isObject(item: any): boolean;
|
|
35
35
|
static ɵfac: i0.ɵɵFactoryDeclaration<YsSelectComponent, never>;
|
|
36
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<YsSelectComponent, "ys-select", never, { "id": { "alias": "id"; "required": false; }; "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "invalid": { "alias": "invalid"; "required": false; }; "invalidFeedback": { "alias": "invalidFeedback"; "required": false; }; "valid": { "alias": "valid"; "required": false; }; "validFeedback": { "alias": "validFeedback"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "size": { "alias": "size"; "required": false; }; "
|
|
36
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<YsSelectComponent, "ys-select", never, { "id": { "alias": "id"; "required": false; }; "options": { "alias": "options"; "required": false; }; "optionLabel": { "alias": "optionLabel"; "required": false; }; "placeholder": { "alias": "placeholder"; "required": false; }; "styleClass": { "alias": "styleClass"; "required": false; }; "invalid": { "alias": "invalid"; "required": false; }; "invalidFeedback": { "alias": "invalidFeedback"; "required": false; }; "valid": { "alias": "valid"; "required": false; }; "validFeedback": { "alias": "validFeedback"; "required": false; }; "multiple": { "alias": "multiple"; "required": false; }; "size": { "alias": "size"; "required": false; }; "showClear": { "alias": "showClear"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; }, { "selected": "selected"; }, never, never, true, never>;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
export { YsSelectComponent };
|