@yoozsoft/yoozsoft-ng 5.3.5 → 7.1.1
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/README.md +143 -24
- package/assets/js/UTIF.js-master/LICENSE +21 -21
- package/assets/js/UTIF.js-master/README.md +72 -72
- package/assets/js/UTIF.js-master/UTIF.js +1762 -1762
- package/assets/js/UTIF.js-master/package-lock.json +13 -13
- package/assets/js/UTIF.js-master/package.json +24 -0
- package/assets/styles/components/_ys-navbar.scss +22 -0
- package/assets/styles/components/_ys-pagination.scss +10 -0
- package/assets/styles/{ys-layout.scss → utilities/ys-layout.scss} +1 -1
- package/assets/styles/ys-styles.scss +2 -0
- package/autocomplete/package.json +4 -0
- package/date/package.json +4 -0
- package/datepicker/package.json +4 -0
- package/dropdown/package.json +4 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs +257 -197
- package/fesm2022/yoozsoft-yoozsoft-ng-autocomplete.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs +562 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-date.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs +600 -837
- package/fesm2022/yoozsoft-yoozsoft-ng-datepicker.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs +161 -151
- package/fesm2022/yoozsoft-yoozsoft-ng-dropdown.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs +93 -103
- package/fesm2022/yoozsoft-yoozsoft-ng-file-upload.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs +16 -21
- package/fesm2022/yoozsoft-yoozsoft-ng-footer.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs +20 -24
- package/fesm2022/yoozsoft-yoozsoft-ng-loading.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs +60 -76
- package/fesm2022/yoozsoft-yoozsoft-ng-navbar.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs +11 -15
- package/fesm2022/yoozsoft-yoozsoft-ng-overlay.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs +61 -55
- package/fesm2022/yoozsoft-yoozsoft-ng-pagination.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs +142 -130
- package/fesm2022/yoozsoft-yoozsoft-ng-password-strength.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs +44 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-pipes.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs +51 -34
- package/fesm2022/yoozsoft-yoozsoft-ng-progress.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs +155 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-rating.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs +78 -80
- package/fesm2022/yoozsoft-yoozsoft-ng-select.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs +99 -99
- package/fesm2022/yoozsoft-yoozsoft-ng-sidebar.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs +316 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-table.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs +128 -114
- package/fesm2022/yoozsoft-yoozsoft-ng-tiff-viewer.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs +112 -62
- package/fesm2022/yoozsoft-yoozsoft-ng-toast.mjs.map +1 -1
- package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs +37 -0
- package/fesm2022/yoozsoft-yoozsoft-ng-validators.mjs.map +1 -0
- package/fesm2022/yoozsoft-yoozsoft-ng.mjs.map +1 -1
- package/file-upload/package.json +4 -0
- package/footer/package.json +4 -0
- package/loading/package.json +4 -0
- package/navbar/package.json +4 -0
- package/overlay/package.json +4 -0
- package/package.json +61 -38
- package/pagination/package.json +4 -0
- package/password-strength/package.json +4 -0
- package/pipes/package.json +4 -0
- package/progress/package.json +4 -0
- package/rating/package.json +4 -0
- package/select/package.json +4 -0
- package/sidebar/package.json +4 -0
- package/table/package.json +4 -0
- package/tiff-viewer/package.json +4 -0
- package/toast/package.json +4 -0
- package/types/yoozsoft-yoozsoft-ng-autocomplete.d.ts +79 -0
- package/types/yoozsoft-yoozsoft-ng-date.d.ts +118 -0
- package/types/yoozsoft-yoozsoft-ng-datepicker.d.ts +120 -0
- package/types/yoozsoft-yoozsoft-ng-dropdown.d.ts +76 -0
- package/types/yoozsoft-yoozsoft-ng-file-upload.d.ts +75 -0
- package/types/yoozsoft-yoozsoft-ng-footer.d.ts +26 -0
- package/types/yoozsoft-yoozsoft-ng-loading.d.ts +14 -0
- package/types/yoozsoft-yoozsoft-ng-navbar.d.ts +60 -0
- package/types/yoozsoft-yoozsoft-ng-overlay.d.ts +10 -0
- package/types/yoozsoft-yoozsoft-ng-pagination.d.ts +31 -0
- package/types/yoozsoft-yoozsoft-ng-password-strength.d.ts +73 -0
- package/types/yoozsoft-yoozsoft-ng-pipes.d.ts +11 -0
- package/types/yoozsoft-yoozsoft-ng-progress.d.ts +31 -0
- package/types/yoozsoft-yoozsoft-ng-rating.d.ts +56 -0
- package/types/yoozsoft-yoozsoft-ng-select.d.ts +43 -0
- package/types/yoozsoft-yoozsoft-ng-sidebar.d.ts +69 -0
- package/types/yoozsoft-yoozsoft-ng-table.d.ts +137 -0
- package/types/yoozsoft-yoozsoft-ng-tiff-viewer.d.ts +53 -0
- package/types/yoozsoft-yoozsoft-ng-toast.d.ts +66 -0
- package/types/yoozsoft-yoozsoft-ng-validators.d.ts +5 -0
- package/validators/package.json +4 -0
- package/autocomplete/index.d.ts +0 -71
- package/datepicker/index.d.ts +0 -291
- package/directives/index.d.ts +0 -17
- package/dropdown/index.d.ts +0 -62
- package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs +0 -57
- package/fesm2022/yoozsoft-yoozsoft-ng-directives.mjs.map +0 -1
- package/file-upload/index.d.ts +0 -72
- package/footer/index.d.ts +0 -25
- package/loading/index.d.ts +0 -13
- package/navbar/index.d.ts +0 -56
- package/overlay/index.d.ts +0 -11
- package/pagination/index.d.ts +0 -29
- package/password-strength/index.d.ts +0 -84
- package/progress/index.d.ts +0 -28
- package/select/index.d.ts +0 -39
- package/sidebar/index.d.ts +0 -94
- package/tiff-viewer/index.d.ts +0 -52
- package/toast/index.d.ts +0 -53
- /package/assets/styles/{ys-preloader-9.scss → preloaders/ys-preloader-9.scss} +0 -0
- /package/assets/styles/{ys-preloader.scss → preloaders/ys-preloader.scss} +0 -0
- /package/{index.d.ts → types/yoozsoft-yoozsoft-ng.d.ts} +0 -0
|
@@ -1,45 +1,101 @@
|
|
|
1
|
-
import { NgTemplateOutlet } from '@angular/common';
|
|
1
|
+
import { isPlatformBrowser, NgTemplateOutlet, NgClass } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import {
|
|
3
|
+
import { inject, ElementRef, PLATFORM_ID, input, output, signal, computed, effect, forwardRef, HostListener, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
6
6
|
|
|
7
|
-
class
|
|
8
|
-
/** لیست گزینهها */
|
|
9
|
-
_options = [];
|
|
10
|
-
set options(value) { this._options = this.normalizeOptions(value); }
|
|
11
|
-
get options() { return this._options; }
|
|
12
|
-
optionLabel = 'label';
|
|
13
|
-
placeholder = '';
|
|
14
|
-
searchPlaceholder = '';
|
|
15
|
-
selectedMaxLength = 3;
|
|
16
|
-
selectedMaxLengthTemplate = '{length} items selected';
|
|
17
|
-
selectionSeparator = ", ";
|
|
18
|
-
/** انتخاب چندگانه یا تکی */
|
|
19
|
-
multiple = false;
|
|
20
|
-
showClear = false;
|
|
21
|
-
/** تمپلیت سفارشی برای آیتمها */
|
|
22
|
-
itemTemplate;
|
|
23
|
-
/** مقدار انتخابشده */
|
|
24
|
-
selected = this.multiple ? [] : null;
|
|
25
|
-
/** قابلیت جستجو */
|
|
26
|
-
searchable = false;
|
|
27
|
-
disabled = false;
|
|
28
|
-
/** رویداد خروجی هنگام تغییر انتخاب */
|
|
29
|
-
selectionChange = new EventEmitter();
|
|
30
|
-
searchTerm = '';
|
|
31
|
-
isOpen = false;
|
|
32
|
-
highlightedIndex = -1;
|
|
7
|
+
class YsDropdown {
|
|
33
8
|
elRef = inject(ElementRef);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
9
|
+
platformId = inject(PLATFORM_ID);
|
|
10
|
+
/** List of options */
|
|
11
|
+
options = input([], /* @ts-ignore */
|
|
12
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
13
|
+
/** Field of object that display as label */
|
|
14
|
+
optionLabel = input('label', /* @ts-ignore */
|
|
15
|
+
...(ngDevMode ? [{ debugName: "optionLabel" }] : /* istanbul ignore next */ []));
|
|
16
|
+
placeholder = input('', /* @ts-ignore */
|
|
17
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
18
|
+
searchPlaceholder = input('', /* @ts-ignore */
|
|
19
|
+
...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
|
|
20
|
+
selectedMaxLength = input(3, /* @ts-ignore */
|
|
21
|
+
...(ngDevMode ? [{ debugName: "selectedMaxLength" }] : /* istanbul ignore next */ []));
|
|
22
|
+
selectedMaxLengthTemplate = input('{length} items selected', /* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [{ debugName: "selectedMaxLengthTemplate" }] : /* istanbul ignore next */ []));
|
|
24
|
+
selectionSeparator = input(', ', /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "selectionSeparator" }] : /* istanbul ignore next */ []));
|
|
26
|
+
dropDownToggleIconClass = input('fa fa-chevron-down', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "dropDownToggleIconClass" }] : /* istanbul ignore next */ []));
|
|
28
|
+
clearIconClass = input('fa fa-times', /* @ts-ignore */
|
|
29
|
+
...(ngDevMode ? [{ debugName: "clearIconClass" }] : /* istanbul ignore next */ []));
|
|
30
|
+
multipleCheckIconClass = input('fa fa-check', /* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [{ debugName: "multipleCheckIconClass" }] : /* istanbul ignore next */ []));
|
|
32
|
+
/** Multiple choice mode */
|
|
33
|
+
multiple = input(false, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
|
|
35
|
+
showClear = input(false, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
|
|
37
|
+
/** Search capability */
|
|
38
|
+
searchable = input(false, /* @ts-ignore */
|
|
39
|
+
...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
|
|
40
|
+
disabled = input(false, /* @ts-ignore */
|
|
41
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
42
|
+
/** Custom template for items */
|
|
43
|
+
itemTemplate = input(/* @ts-ignore */
|
|
44
|
+
...(ngDevMode ? [undefined, { debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
45
|
+
/** Output event when selection changes */
|
|
46
|
+
selectionChange = output();
|
|
47
|
+
searchTerm = signal('', /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "searchTerm" }] : /* istanbul ignore next */ []));
|
|
49
|
+
isOpen = signal(false, /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
51
|
+
highlightedIndex = signal(-1, /* @ts-ignore */
|
|
52
|
+
...(ngDevMode ? [{ debugName: "highlightedIndex" }] : /* istanbul ignore next */ []));
|
|
53
|
+
/** Selected value */
|
|
54
|
+
selected = signal(null, /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
|
|
56
|
+
disabledState = signal(false, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
|
|
58
|
+
isDisabled = computed(() => this.disabled() || this.disabledState(), /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
60
|
+
filteredOptions = computed(() => {
|
|
61
|
+
if (!this.searchable() || !this.searchTerm().trim()) {
|
|
62
|
+
return this.normalizedOptions();
|
|
39
63
|
}
|
|
40
|
-
|
|
41
|
-
|
|
64
|
+
const term = this.searchTerm().toLowerCase();
|
|
65
|
+
return this.normalizedOptions().filter((opt) => opt.label.toLowerCase().includes(term));
|
|
66
|
+
}, /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "filteredOptions" }] : /* istanbul ignore next */ []));
|
|
68
|
+
normalizedOptions = computed(() => this.normalizeOptions(this.options()), /* @ts-ignore */
|
|
69
|
+
...(ngDevMode ? [{ debugName: "normalizedOptions" }] : /* istanbul ignore next */ []));
|
|
70
|
+
hasSelection = computed(() => this.multiple()
|
|
71
|
+
? Array.isArray(this.selected()) && this.selected().length > 0
|
|
72
|
+
: !!this.selected(), /* @ts-ignore */
|
|
73
|
+
...(ngDevMode ? [{ debugName: "hasSelection" }] : /* istanbul ignore next */ []));
|
|
74
|
+
selectedLabels = computed(() => {
|
|
75
|
+
if (this.multiple()) {
|
|
76
|
+
if (!Array.isArray(this.selected()))
|
|
77
|
+
return '';
|
|
78
|
+
// لیست object های انتخابی را پیدا میکنیم
|
|
79
|
+
const selectedItems = this.normalizedOptions().filter((o) => this.selected().includes(o.value));
|
|
80
|
+
const count = selectedItems.length;
|
|
81
|
+
// اگر بیشتر از حد مجاز باشد → متن سفارشی
|
|
82
|
+
if (count > this.selectedMaxLength()) {
|
|
83
|
+
return this.selectedMaxLengthTemplate().replace('{length}', count + '');
|
|
84
|
+
}
|
|
85
|
+
// در غیر اینصورت لیبلها را نمایش بده
|
|
86
|
+
return selectedItems.map((o) => o.label).join(this.selectionSeparator());
|
|
42
87
|
}
|
|
88
|
+
const item = this.normalizedOptions().find((o) => o.value === this.selected());
|
|
89
|
+
return item?.label ?? '';
|
|
90
|
+
}, /* @ts-ignore */
|
|
91
|
+
...(ngDevMode ? [{ debugName: "selectedLabels" }] : /* istanbul ignore next */ []));
|
|
92
|
+
_onChange = (_) => { };
|
|
93
|
+
_onTouched = () => { };
|
|
94
|
+
constructor() {
|
|
95
|
+
effect(() => this.selected.set(this.multiple() ? [] : null));
|
|
96
|
+
}
|
|
97
|
+
writeValue(obj) {
|
|
98
|
+
this.selected.set(this.multiple() ? (Array.isArray(obj) ? obj : []) : obj);
|
|
43
99
|
}
|
|
44
100
|
registerOnChange(fn) {
|
|
45
101
|
this._onChange = fn;
|
|
@@ -48,201 +104,155 @@ class YsDropdownComponent {
|
|
|
48
104
|
this._onTouched = fn;
|
|
49
105
|
}
|
|
50
106
|
setDisabledState(isDisabled) {
|
|
51
|
-
this.
|
|
107
|
+
this.disabledState.set(isDisabled);
|
|
52
108
|
}
|
|
53
109
|
normalizeOptions(list) {
|
|
54
110
|
if (!Array.isArray(list))
|
|
55
111
|
return [];
|
|
56
|
-
return list.map(item => {
|
|
112
|
+
return list.map((item) => {
|
|
57
113
|
// 1. اگر primitive بود
|
|
58
114
|
if (['string', 'number', 'boolean'].includes(typeof item)) {
|
|
59
115
|
return {
|
|
60
116
|
raw: item,
|
|
61
117
|
label: String(item),
|
|
62
|
-
value: item
|
|
118
|
+
value: item,
|
|
119
|
+
disabled: false,
|
|
63
120
|
};
|
|
64
121
|
}
|
|
65
122
|
// 2. اگر OptionItem<T> بود
|
|
66
|
-
if ('value' in item) {
|
|
123
|
+
if (item && typeof item === 'object' && 'value' in item) {
|
|
67
124
|
return {
|
|
68
125
|
raw: item,
|
|
69
126
|
label: item.label ?? String(item.value),
|
|
70
127
|
value: item.value,
|
|
71
|
-
|
|
128
|
+
disabled: item.disabled,
|
|
129
|
+
...item,
|
|
72
130
|
};
|
|
73
131
|
}
|
|
74
132
|
// 3. object معمولی
|
|
75
133
|
return {
|
|
76
134
|
raw: item,
|
|
77
|
-
label: item[this.optionLabel] ?? JSON.stringify(item),
|
|
78
|
-
value: item
|
|
135
|
+
label: item[this.optionLabel()] ?? JSON.stringify(item),
|
|
136
|
+
value: item,
|
|
137
|
+
disabled: false,
|
|
79
138
|
};
|
|
80
139
|
});
|
|
81
140
|
}
|
|
82
|
-
get selectedLabels() {
|
|
83
|
-
if (this.multiple) {
|
|
84
|
-
if (!Array.isArray(this.selected))
|
|
85
|
-
return '';
|
|
86
|
-
// لیست object های انتخابی را پیدا میکنیم
|
|
87
|
-
const selectedItems = this.options.filter(o => this.selected.includes(o.value));
|
|
88
|
-
const count = selectedItems.length;
|
|
89
|
-
// اگر بیشتر از حد مجاز باشد → متن سفارشی
|
|
90
|
-
if (count > this.selectedMaxLength) {
|
|
91
|
-
return this.selectedMaxLengthTemplate.replace('{length}', count + '');
|
|
92
|
-
}
|
|
93
|
-
// در غیر اینصورت لیبلها را نمایش بده
|
|
94
|
-
return selectedItems.map(o => o.label).join(this.selectionSeparator);
|
|
95
|
-
}
|
|
96
|
-
const item = this.options.find(o => o.value === this.selected);
|
|
97
|
-
return item?.label ?? '';
|
|
98
|
-
}
|
|
99
141
|
toggleDropdown() {
|
|
100
|
-
this.isOpen
|
|
101
|
-
|
|
102
|
-
this.highlightedIndex = -1;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
filterOptions() {
|
|
106
|
-
let list = this.options;
|
|
107
|
-
if (this.searchable && this.searchTerm.trim()) {
|
|
108
|
-
const term = this.searchTerm.toLowerCase();
|
|
109
|
-
list = this.options.filter(opt => opt[this.optionLabel].toLowerCase().includes(term));
|
|
110
|
-
}
|
|
111
|
-
// هر بار جستجو انجام شد index ریست بشه
|
|
112
|
-
this.highlightedIndex = Math.min(this.highlightedIndex, list.length - 1);
|
|
113
|
-
return list;
|
|
142
|
+
this.isOpen.update((v) => !v);
|
|
143
|
+
this.highlightedIndex.set(-1);
|
|
114
144
|
}
|
|
115
145
|
selectOption(option) {
|
|
116
146
|
if (option.disabled)
|
|
117
147
|
return;
|
|
118
|
-
const
|
|
119
|
-
if (this.multiple) {
|
|
120
|
-
|
|
121
|
-
this.selected = exists
|
|
122
|
-
? this.selected.filter((x) => x !== returnedValue)
|
|
123
|
-
: [...(this.selected || []), returnedValue];
|
|
148
|
+
const value = option.value;
|
|
149
|
+
if (this.multiple()) {
|
|
150
|
+
this.selected.update((list) => list?.includes(value) ? list.filter((x) => x !== value) : [...(list || []), value]);
|
|
124
151
|
}
|
|
125
152
|
else {
|
|
126
|
-
this.selected
|
|
127
|
-
this.isOpen
|
|
153
|
+
this.selected.set(value);
|
|
154
|
+
this.isOpen.set(false);
|
|
128
155
|
}
|
|
129
|
-
this._onChange(this.selected);
|
|
130
|
-
this.selectionChange.emit(this.selected);
|
|
156
|
+
this._onChange(this.selected());
|
|
157
|
+
this.selectionChange.emit(this.selected());
|
|
158
|
+
this._onTouched();
|
|
131
159
|
}
|
|
132
160
|
isSelected(option) {
|
|
133
|
-
if (this.multiple) {
|
|
134
|
-
return Array.isArray(this.selected)
|
|
135
|
-
? this.selected.includes(option.value)
|
|
136
|
-
: false;
|
|
161
|
+
if (this.multiple()) {
|
|
162
|
+
return Array.isArray(this.selected()) ? this.selected().includes(option.value) : false;
|
|
137
163
|
}
|
|
138
|
-
return this.selected === option.value;
|
|
164
|
+
return this.selected() === option.value;
|
|
139
165
|
}
|
|
140
166
|
clearSelection() {
|
|
141
|
-
this.selected
|
|
142
|
-
this._onChange(this.selected);
|
|
167
|
+
this.selected.set(this.multiple() ? [] : null);
|
|
168
|
+
this._onChange(this.selected());
|
|
169
|
+
this.selectionChange.emit(this.selected());
|
|
143
170
|
this._onTouched();
|
|
144
|
-
this.selectionChange.emit(this.selected);
|
|
145
171
|
}
|
|
146
172
|
onKeyDown(event) {
|
|
147
|
-
const
|
|
148
|
-
if (!
|
|
173
|
+
const list = this.filteredOptions();
|
|
174
|
+
if (!list.length)
|
|
149
175
|
return;
|
|
150
176
|
switch (event.key) {
|
|
151
177
|
case 'ArrowDown':
|
|
152
178
|
event.preventDefault();
|
|
153
|
-
this.highlightedIndex
|
|
179
|
+
this.highlightedIndex.update((i) => (i + 1) % list.length);
|
|
154
180
|
this.scrollToHighlighted();
|
|
155
181
|
break;
|
|
156
182
|
case 'ArrowUp':
|
|
157
183
|
event.preventDefault();
|
|
158
|
-
this.highlightedIndex
|
|
184
|
+
this.highlightedIndex.update((i) => (i > 0 ? i - 1 : list.length - 1));
|
|
159
185
|
this.scrollToHighlighted();
|
|
160
186
|
break;
|
|
161
187
|
case 'Enter':
|
|
162
188
|
event.preventDefault();
|
|
163
|
-
if (this.
|
|
164
|
-
this.
|
|
189
|
+
if (!this.isOpen()) {
|
|
190
|
+
this.isOpen.set(true);
|
|
191
|
+
return;
|
|
165
192
|
}
|
|
193
|
+
const idx = this.highlightedIndex();
|
|
194
|
+
if (idx >= 0)
|
|
195
|
+
this.selectOption(list[idx]);
|
|
196
|
+
break;
|
|
197
|
+
case 'Tab':
|
|
198
|
+
this.isOpen.set(false);
|
|
166
199
|
break;
|
|
167
200
|
case 'Escape':
|
|
168
|
-
this.isOpen
|
|
201
|
+
this.isOpen.set(false);
|
|
169
202
|
break;
|
|
170
203
|
}
|
|
171
204
|
}
|
|
172
205
|
scrollToHighlighted() {
|
|
173
|
-
|
|
174
|
-
|
|
206
|
+
if (!isPlatformBrowser(this.platformId))
|
|
207
|
+
return;
|
|
208
|
+
queueMicrotask(() => {
|
|
175
209
|
const dropdown = this.elRef.nativeElement.querySelector('.dropdown-menu');
|
|
176
210
|
const items = dropdown?.querySelectorAll('.dropdown-item');
|
|
177
|
-
const activeItem = items?.[this.highlightedIndex];
|
|
178
|
-
if (activeItem
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
211
|
+
const activeItem = items?.[this.highlightedIndex()];
|
|
212
|
+
if (!activeItem || !dropdown)
|
|
213
|
+
return;
|
|
214
|
+
const itemTop = activeItem.offsetTop;
|
|
215
|
+
const itemBottom = itemTop + activeItem.offsetHeight;
|
|
216
|
+
const dropdownScrollTop = dropdown.scrollTop;
|
|
217
|
+
const dropdownHeight = dropdown.clientHeight;
|
|
218
|
+
if (itemBottom > dropdownScrollTop + dropdownHeight) {
|
|
219
|
+
dropdown.scrollTop = itemBottom - dropdownHeight;
|
|
220
|
+
}
|
|
221
|
+
else if (itemTop < dropdownScrollTop) {
|
|
222
|
+
dropdown.scrollTop = itemTop;
|
|
189
223
|
}
|
|
190
224
|
});
|
|
191
225
|
}
|
|
192
226
|
/** Close by clicking outside */
|
|
193
227
|
onClickOutside(event) {
|
|
228
|
+
if (!isPlatformBrowser(this.platformId))
|
|
229
|
+
return;
|
|
230
|
+
if (!this.isOpen())
|
|
231
|
+
return;
|
|
194
232
|
const clickedInside = this.elRef.nativeElement.contains(event.target);
|
|
195
233
|
if (!clickedInside) {
|
|
196
|
-
this.isOpen
|
|
234
|
+
this.isOpen.set(false);
|
|
197
235
|
}
|
|
198
236
|
}
|
|
199
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
200
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
237
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: YsDropdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
238
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: YsDropdown, isStandalone: true, selector: "ys-dropdown", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, selectedMaxLength: { classPropertyName: "selectedMaxLength", publicName: "selectedMaxLength", isSignal: true, isRequired: false, transformFunction: null }, selectedMaxLengthTemplate: { classPropertyName: "selectedMaxLengthTemplate", publicName: "selectedMaxLengthTemplate", isSignal: true, isRequired: false, transformFunction: null }, selectionSeparator: { classPropertyName: "selectionSeparator", publicName: "selectionSeparator", isSignal: true, isRequired: false, transformFunction: null }, dropDownToggleIconClass: { classPropertyName: "dropDownToggleIconClass", publicName: "dropDownToggleIconClass", isSignal: true, isRequired: false, transformFunction: null }, clearIconClass: { classPropertyName: "clearIconClass", publicName: "clearIconClass", isSignal: true, isRequired: false, transformFunction: null }, multipleCheckIconClass: { classPropertyName: "multipleCheckIconClass", publicName: "multipleCheckIconClass", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, itemTemplate: { classPropertyName: "itemTemplate", publicName: "itemTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
|
|
201
239
|
{
|
|
202
240
|
provide: NG_VALUE_ACCESSOR,
|
|
203
|
-
useExisting: forwardRef(() =>
|
|
241
|
+
useExisting: forwardRef(() => YsDropdown),
|
|
204
242
|
multi: true,
|
|
205
243
|
},
|
|
206
|
-
], ngImport: i0, template: "<div class=\"dropdown ys-dropdown\">\
|
|
244
|
+
], ngImport: i0, template: "<div class=\"dropdown ys-dropdown\">\n <div class=\"input-group w-100\">\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels()\" [placeholder]=\"placeholder()\"\n readonly (click)=\"isOpen.set(true)\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled()\" />\n <!-- (focus)=\"isOpen.set(true)\" replace with (click)=\"isOpen.set(true)\" (keydown.enter)=\"isOpen.set(true)\" -->\n\n @if(showClear() && hasSelection()){\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"isDisabled()\">\n <i [ngClass]=\"clearIconClass()\"></i>\n </button>\n }\n\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\n [disabled]=\"isDisabled()\">\n <i [ngClass]=\"dropDownToggleIconClass()\"></i>\n </button>\n </div>\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen()\">\n\n @if(searchable()){\n <div class=\"px-2\">\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder()\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" (keydown)=\"onKeyDown($event)\">\n </div>\n }\n\n @for (option of filteredOptions(); track option.value) {\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\n [class.highlighted]=\"$index === highlightedIndex()\">\n\n @if(itemTemplate()){\n <ng-container [ngTemplateOutlet]=\"itemTemplate()\" [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-container>\n } @else {\n @if(multiple()){\n <i class=\"{{multipleCheckIconClass()}} text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\n }\n <!-- <span>{{option[optionLabel]}}</span> -->\n <span>{{option.label}}</span>\n }\n </div>\n }\n </div>\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]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[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: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.Eager });
|
|
207
245
|
}
|
|
208
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
246
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: YsDropdown, decorators: [{
|
|
209
247
|
type: Component,
|
|
210
|
-
args: [{ selector: 'ys-dropdown', imports: [NgTemplateOutlet, FormsModule], providers: [
|
|
248
|
+
args: [{ selector: 'ys-dropdown', imports: [NgTemplateOutlet, FormsModule, NgClass], changeDetection: ChangeDetectionStrategy.Eager, providers: [
|
|
211
249
|
{
|
|
212
250
|
provide: NG_VALUE_ACCESSOR,
|
|
213
|
-
useExisting: forwardRef(() =>
|
|
251
|
+
useExisting: forwardRef(() => YsDropdown),
|
|
214
252
|
multi: true,
|
|
215
253
|
},
|
|
216
|
-
], template: "<div class=\"dropdown ys-dropdown\">\
|
|
217
|
-
}], propDecorators: { options: [{
|
|
218
|
-
type: Input
|
|
219
|
-
}], optionLabel: [{
|
|
220
|
-
type: Input
|
|
221
|
-
}], placeholder: [{
|
|
222
|
-
type: Input
|
|
223
|
-
}], searchPlaceholder: [{
|
|
224
|
-
type: Input
|
|
225
|
-
}], selectedMaxLength: [{
|
|
226
|
-
type: Input
|
|
227
|
-
}], selectedMaxLengthTemplate: [{
|
|
228
|
-
type: Input
|
|
229
|
-
}], selectionSeparator: [{
|
|
230
|
-
type: Input
|
|
231
|
-
}], multiple: [{
|
|
232
|
-
type: Input
|
|
233
|
-
}], showClear: [{
|
|
234
|
-
type: Input
|
|
235
|
-
}], itemTemplate: [{
|
|
236
|
-
type: Input
|
|
237
|
-
}], selected: [{
|
|
238
|
-
type: Input
|
|
239
|
-
}], searchable: [{
|
|
240
|
-
type: Input
|
|
241
|
-
}], disabled: [{
|
|
242
|
-
type: Input
|
|
243
|
-
}], selectionChange: [{
|
|
244
|
-
type: Output
|
|
245
|
-
}], onClickOutside: [{
|
|
254
|
+
], template: "<div class=\"dropdown ys-dropdown\">\n <div class=\"input-group w-100\">\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels()\" [placeholder]=\"placeholder()\"\n readonly (click)=\"isOpen.set(true)\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled()\" />\n <!-- (focus)=\"isOpen.set(true)\" replace with (click)=\"isOpen.set(true)\" (keydown.enter)=\"isOpen.set(true)\" -->\n\n @if(showClear() && hasSelection()){\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"isDisabled()\">\n <i [ngClass]=\"clearIconClass()\"></i>\n </button>\n }\n\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\n [disabled]=\"isDisabled()\">\n <i [ngClass]=\"dropDownToggleIconClass()\"></i>\n </button>\n </div>\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen()\">\n\n @if(searchable()){\n <div class=\"px-2\">\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder()\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" (keydown)=\"onKeyDown($event)\">\n </div>\n }\n\n @for (option of filteredOptions(); track option.value) {\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\n [class.highlighted]=\"$index === highlightedIndex()\">\n\n @if(itemTemplate()){\n <ng-container [ngTemplateOutlet]=\"itemTemplate()\" [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-container>\n } @else {\n @if(multiple()){\n <i class=\"{{multipleCheckIconClass()}} text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\n }\n <!-- <span>{{option[optionLabel]}}</span> -->\n <span>{{option.label}}</span>\n }\n </div>\n }\n </div>\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"] }]
|
|
255
|
+
}], ctorParameters: () => [], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], selectedMaxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMaxLength", required: false }] }], selectedMaxLengthTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedMaxLengthTemplate", required: false }] }], selectionSeparator: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionSeparator", required: false }] }], dropDownToggleIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropDownToggleIconClass", required: false }] }], clearIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearIconClass", required: false }] }], multipleCheckIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "multipleCheckIconClass", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], itemTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemTemplate", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], onClickOutside: [{
|
|
246
256
|
type: HostListener,
|
|
247
257
|
args: ['document:click', ['$event']]
|
|
248
258
|
}] } });
|
|
@@ -255,5 +265,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImpor
|
|
|
255
265
|
* Generated bundle index. Do not edit.
|
|
256
266
|
*/
|
|
257
267
|
|
|
258
|
-
export {
|
|
268
|
+
export { YsDropdown };
|
|
259
269
|
//# sourceMappingURL=yoozsoft-yoozsoft-ng-dropdown.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yoozsoft-yoozsoft-ng-dropdown.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.component.html","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/yoozsoft-yoozsoft-ng-dropdown.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport { Component, ElementRef, EventEmitter, forwardRef, HostListener, inject, Input, Output, TemplateRef } from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\ninterface ItemTemplate {\r\n raw: any;\r\n label: string;\r\n value: any;\r\n}\r\n\r\n@Component({\r\n selector: 'ys-dropdown',\r\n imports: [NgTemplateOutlet, FormsModule],\r\n templateUrl: './ys-dropdown.component.html',\r\n styleUrl: './ys-dropdown.component.scss',\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsDropdownComponent),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsDropdownComponent implements ControlValueAccessor {\r\n\r\n /** لیست گزینهها */\r\n private _options: any[] = [];\r\n @Input()\r\n set options(value: any[]) { this._options = this.normalizeOptions(value); }\r\n get options() { return this._options; }\r\n\r\n @Input() optionLabel: string = 'label';\r\n @Input() placeholder: string = '';\r\n @Input() searchPlaceholder: string = '';\r\n @Input() selectedMaxLength: number = 3;\r\n @Input() selectedMaxLengthTemplate: string = '{length} items selected';\r\n @Input() selectionSeparator: string = \", \";\r\n\r\n /** انتخاب چندگانه یا تکی */\r\n @Input() multiple: boolean = false;\r\n\r\n @Input() showClear: boolean = false;\r\n\r\n /** تمپلیت سفارشی برای آیتمها */\r\n @Input() itemTemplate?: TemplateRef<any>;\r\n\r\n /** مقدار انتخابشده */\r\n @Input() selected: any[] | any = this.multiple ? [] : null;\r\n\r\n /** قابلیت جستجو */\r\n @Input() searchable: boolean = false;\r\n\r\n @Input() disabled: boolean = false;\r\n\r\n /** رویداد خروجی هنگام تغییر انتخاب */\r\n @Output() selectionChange = new EventEmitter<any>();\r\n\r\n searchTerm = '';\r\n isOpen = false;\r\n highlightedIndex: number = -1;\r\n\r\n private elRef = inject(ElementRef)\r\n\r\n private _onChange: (value: any) => void = () => { };\r\n private _onTouched: () => void = () => { };\r\n\r\n writeValue(obj: any): void {\r\n if (this.multiple) {\r\n this.selected = obj ? [...obj] : [];\r\n } else {\r\n this.selected = obj;\r\n }\r\n }\r\n registerOnChange(fn: any): void {\r\n this._onChange = fn;\r\n }\r\n registerOnTouched(fn: any): void {\r\n this._onTouched = fn;\r\n }\r\n setDisabledState?(isDisabled: boolean): void {\r\n this.disabled = isDisabled;\r\n }\r\n\r\n private normalizeOptions(list: any[]): any[] {\r\n if (!Array.isArray(list)) return [];\r\n\r\n return list.map(item => {\r\n\r\n // 1. اگر primitive بود\r\n if (['string', 'number', 'boolean'].includes(typeof item)) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: String(item),\r\n value: item\r\n };\r\n }\r\n\r\n // 2. اگر OptionItem<T> بود\r\n if ('value' in item) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item.label ?? String(item.value),\r\n value: item.value,\r\n ...item\r\n };\r\n }\r\n\r\n // 3. object معمولی\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item[this.optionLabel] ?? JSON.stringify(item),\r\n value: item\r\n };\r\n });\r\n }\r\n\r\n get selectedLabels(): string {\r\n if (this.multiple) {\r\n if (!Array.isArray(this.selected)) return '';\r\n\r\n // لیست object های انتخابی را پیدا میکنیم\r\n const selectedItems = this.options.filter(o =>\r\n this.selected.includes(o.value)\r\n );\r\n\r\n const count = selectedItems.length;\r\n\r\n // اگر بیشتر از حد مجاز باشد → متن سفارشی\r\n if (count > this.selectedMaxLength) {\r\n return this.selectedMaxLengthTemplate.replace('{length}', count + '');\r\n }\r\n\r\n // در غیر اینصورت لیبلها را نمایش بده\r\n return selectedItems.map(o => o.label).join(this.selectionSeparator);\r\n }\r\n\r\n const item = this.options.find(o => o.value === this.selected);\r\n return item?.label ?? '';\r\n }\r\n\r\n toggleDropdown() {\r\n this.isOpen = !this.isOpen;\r\n if (this.isOpen) {\r\n this.highlightedIndex = -1;\r\n }\r\n }\r\n\r\n filterOptions(): any[] {\r\n let list = this.options;\r\n if (this.searchable && this.searchTerm.trim()) {\r\n const term = this.searchTerm.toLowerCase();\r\n list = this.options.filter(opt =>\r\n opt[this.optionLabel].toLowerCase().includes(term)\r\n );\r\n }\r\n // هر بار جستجو انجام شد index ریست بشه\r\n this.highlightedIndex = Math.min(this.highlightedIndex, list.length - 1);\r\n return list;\r\n }\r\n\r\n selectOption(option: any) {\r\n if (option.disabled) return;\r\n\r\n const returnedValue = option.value; // مقدار نهایی برای فرم\r\n\r\n if (this.multiple) {\r\n const exists = this.selected?.some((x: any) => x === returnedValue);\r\n this.selected = exists\r\n ? this.selected.filter((x: any) => x !== returnedValue)\r\n : [...(this.selected || []), returnedValue];\r\n } else {\r\n this.selected = returnedValue;\r\n this.isOpen = false;\r\n }\r\n\r\n this._onChange(this.selected);\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n isSelected(option: any): boolean {\r\n if (this.multiple) {\r\n return Array.isArray(this.selected)\r\n ? this.selected.includes(option.value)\r\n : false;\r\n }\r\n\r\n return this.selected === option.value;\r\n }\r\n\r\n clearSelection() {\r\n this.selected = this.multiple ? [] : null;\r\n this._onChange(this.selected);\r\n this._onTouched();\r\n this.selectionChange.emit(this.selected);\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent) {\r\n const filtered = this.filterOptions();\r\n if (!filtered.length) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.highlightedIndex = (this.highlightedIndex + 1) % filtered.length;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.highlightedIndex = this.highlightedIndex > 0 ? this.highlightedIndex - 1 : filtered.length - 1;\r\n this.scrollToHighlighted();\r\n break;\r\n case 'Enter':\r\n event.preventDefault();\r\n if (this.highlightedIndex >= 0 && this.highlightedIndex < filtered.length) {\r\n this.selectOption(filtered[this.highlightedIndex]);\r\n }\r\n break;\r\n case 'Escape':\r\n this.isOpen = false;\r\n break;\r\n }\r\n }\r\n\r\n scrollToHighlighted() {\r\n // تأخیر جزئی برای اطمینان از رندر کامل\r\n setTimeout(() => {\r\n const dropdown = this.elRef.nativeElement.querySelector('.dropdown-menu');\r\n const items = dropdown?.querySelectorAll('.dropdown-item');\r\n const activeItem = items?.[this.highlightedIndex] as HTMLElement;\r\n if (activeItem && dropdown) {\r\n const itemTop = activeItem.offsetTop;\r\n const itemBottom = itemTop + activeItem.offsetHeight;\r\n const dropdownScrollTop = dropdown.scrollTop;\r\n const dropdownHeight = dropdown.clientHeight;\r\n\r\n if (itemBottom > dropdownScrollTop + dropdownHeight) {\r\n dropdown.scrollTop = itemBottom - dropdownHeight;\r\n } else if (itemTop < dropdownScrollTop) {\r\n dropdown.scrollTop = itemTop;\r\n }\r\n }\r\n });\r\n }\r\n\r\n /** Close by clicking outside */\r\n @HostListener('document:click', ['$event'])\r\n onClickOutside(event: MouseEvent) {\r\n const clickedInside = this.elRef.nativeElement.contains(event.target);\r\n if (!clickedInside) {\r\n this.isOpen = false;\r\n }\r\n }\r\n\r\n}\r\n","<div class=\"dropdown ys-dropdown\">\r\n <div class=\"input-group w-100\">\r\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels\" [placeholder]=\"placeholder\" readonly\r\n (focus)=\"isOpen = true\" (keydown)=\"onKeyDown($event)\" [disabled]=\"disabled\" />\r\n\r\n @if(showClear && (multiple ? selected?.length > 0 : selected)){\r\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"disabled\">\r\n <i class=\"fa fa-times\"></i>\r\n </button>\r\n }\r\n\r\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\r\n [disabled]=\"disabled\">\r\n <i class=\"fa fa-chevron-down\"></i>\r\n </button>\r\n </div>\r\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen\">\r\n\r\n @if(searchable){\r\n <div class=\"px-2\">\r\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder\" [(ngModel)]=\"searchTerm\"\r\n (keydown)=\"onKeyDown($event)\">\r\n </div>\r\n }\r\n\r\n @for (option of filterOptions(); track $index) {\r\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\r\n [class.highlighted]=\"$index === highlightedIndex\">\r\n @if(itemTemplate){\r\n <ng-container [ngTemplateOutlet]=\"itemTemplate\" [ngTemplateOutletContext]=\"{ option: option }\">\r\n </ng-container>\r\n }\r\n @else {\r\n @if(multiple){\r\n <i class=\"fa fa-check text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\r\n }\r\n <!-- <span>{{option[optionLabel]}}</span> -->\r\n <span>{{option.label}}</span>\r\n }\r\n </div>\r\n }\r\n </div>\r\n</div>","/*\r\n * Public API Surface of ys-dropdown\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/ys-dropdown/ys-dropdown.component';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"yoozsoft-yoozsoft-ng-dropdown.mjs","sources":["../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/src/ys-dropdown/ys-dropdown.html","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/public-api.ts","../../../../projects/yoozsoft/yoozsoft-ng/dropdown/yoozsoft-yoozsoft-ng-dropdown.ts"],"sourcesContent":["import { isPlatformBrowser, NgClass, NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n Component,\r\n computed,\r\n effect,\r\n ElementRef,\r\n forwardRef,\r\n HostListener,\r\n inject,\r\n input,\r\n output,\r\n PLATFORM_ID,\r\n signal,\r\n TemplateRef,\r\n ChangeDetectionStrategy,\r\n} from '@angular/core';\r\nimport { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';\r\n\r\ninterface ItemTemplate {\r\n raw: unknown;\r\n label: string;\r\n value: unknown;\r\n disabled: boolean;\r\n}\r\n\r\n@Component({\r\n selector: 'ys-dropdown',\r\n imports: [NgTemplateOutlet, FormsModule, NgClass],\r\n templateUrl: './ys-dropdown.html',\r\n styleUrl: './ys-dropdown.scss',\r\n changeDetection: ChangeDetectionStrategy.Eager,\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => YsDropdown),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class YsDropdown implements ControlValueAccessor {\r\n private elRef = inject(ElementRef);\r\n private platformId = inject(PLATFORM_ID);\r\n\r\n /** List of options */\r\n options = input<any[]>([]);\r\n /** Field of object that display as label */\r\n optionLabel = input<string>('label');\r\n placeholder = input<string>('');\r\n searchPlaceholder = input<string>('');\r\n selectedMaxLength = input<number>(3);\r\n selectedMaxLengthTemplate = input<string>('{length} items selected');\r\n selectionSeparator = input<string>(', ');\r\n dropDownToggleIconClass = input<string>('fa fa-chevron-down');\r\n clearIconClass = input<string>('fa fa-times');\r\n multipleCheckIconClass = input<string>('fa fa-check');\r\n\r\n /** Multiple choice mode */\r\n multiple = input<boolean>(false);\r\n showClear = input<boolean>(false);\r\n\r\n /** Search capability */\r\n searchable = input<boolean>(false);\r\n\r\n disabled = input<boolean>(false);\r\n\r\n /** Custom template for items */\r\n itemTemplate = input<TemplateRef<any>>();\r\n\r\n /** Output event when selection changes */\r\n selectionChange = output<unknown | unknown[] | null>();\r\n\r\n searchTerm = signal<string>('');\r\n isOpen = signal<boolean>(false);\r\n highlightedIndex = signal<number>(-1);\r\n /** Selected value */\r\n selected = signal<any[] | any>(null);\r\n\r\n private disabledState = signal(false);\r\n readonly isDisabled = computed(() => this.disabled() || this.disabledState());\r\n\r\n readonly filteredOptions = computed<ItemTemplate[]>(() => {\r\n if (!this.searchable() || !this.searchTerm().trim()) {\r\n return this.normalizedOptions();\r\n }\r\n\r\n const term = this.searchTerm().toLowerCase();\r\n\r\n return this.normalizedOptions().filter((opt) => opt.label.toLowerCase().includes(term));\r\n });\r\n\r\n readonly normalizedOptions = computed(() => this.normalizeOptions(this.options()));\r\n\r\n readonly hasSelection = computed(() =>\r\n this.multiple()\r\n ? Array.isArray(this.selected()) && this.selected().length > 0\r\n : !!this.selected(),\r\n );\r\n\r\n readonly selectedLabels = computed(() => {\r\n if (this.multiple()) {\r\n if (!Array.isArray(this.selected())) return '';\r\n\r\n // لیست object های انتخابی را پیدا میکنیم\r\n const selectedItems = this.normalizedOptions().filter((o) =>\r\n this.selected().includes(o.value),\r\n );\r\n\r\n const count = selectedItems.length;\r\n\r\n // اگر بیشتر از حد مجاز باشد → متن سفارشی\r\n if (count > this.selectedMaxLength()) {\r\n return this.selectedMaxLengthTemplate().replace('{length}', count + '');\r\n }\r\n\r\n // در غیر اینصورت لیبلها را نمایش بده\r\n return selectedItems.map((o) => o.label).join(this.selectionSeparator());\r\n }\r\n\r\n const item = this.normalizedOptions().find((o) => o.value === this.selected());\r\n return item?.label ?? '';\r\n });\r\n\r\n private _onChange = (_: unknown) => {};\r\n private _onTouched: () => void = () => {};\r\n\r\n constructor() {\r\n effect(() => this.selected.set(this.multiple() ? [] : null));\r\n }\r\n\r\n writeValue(obj: any): void {\r\n this.selected.set(this.multiple() ? (Array.isArray(obj) ? obj : []) : 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.disabledState.set(isDisabled);\r\n }\r\n\r\n private normalizeOptions(list: any[]): ItemTemplate[] {\r\n if (!Array.isArray(list)) return [];\r\n\r\n return list.map((item) => {\r\n // 1. اگر primitive بود\r\n if (['string', 'number', 'boolean'].includes(typeof item)) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: String(item),\r\n value: item,\r\n disabled: false,\r\n };\r\n }\r\n\r\n // 2. اگر OptionItem<T> بود\r\n if (item && typeof item === 'object' && 'value' in item) {\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item.label ?? String(item.value),\r\n value: item.value,\r\n disabled: item.disabled,\r\n ...item,\r\n };\r\n }\r\n\r\n // 3. object معمولی\r\n return <ItemTemplate>{\r\n raw: item,\r\n label: item[this.optionLabel()] ?? JSON.stringify(item),\r\n value: item,\r\n disabled: false,\r\n };\r\n });\r\n }\r\n\r\n toggleDropdown() {\r\n this.isOpen.update((v) => !v);\r\n this.highlightedIndex.set(-1);\r\n }\r\n\r\n selectOption(option: ItemTemplate) {\r\n if (option.disabled) return;\r\n\r\n const value = option.value;\r\n\r\n if (this.multiple()) {\r\n this.selected.update((list: any[]) =>\r\n list?.includes(value) ? list.filter((x) => x !== value) : [...(list || []), value],\r\n );\r\n } else {\r\n this.selected.set(value);\r\n this.isOpen.set(false);\r\n }\r\n\r\n this._onChange(this.selected());\r\n this.selectionChange.emit(this.selected());\r\n this._onTouched();\r\n }\r\n\r\n isSelected(option: any): boolean {\r\n if (this.multiple()) {\r\n return Array.isArray(this.selected()) ? this.selected().includes(option.value) : false;\r\n }\r\n\r\n return this.selected() === option.value;\r\n }\r\n\r\n clearSelection() {\r\n this.selected.set(this.multiple() ? [] : null);\r\n this._onChange(this.selected());\r\n this.selectionChange.emit(this.selected());\r\n this._onTouched();\r\n }\r\n\r\n onKeyDown(event: KeyboardEvent) {\r\n const list = this.filteredOptions();\r\n if (!list.length) return;\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this.highlightedIndex.update((i) => (i + 1) % list.length);\r\n this.scrollToHighlighted();\r\n break;\r\n\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this.highlightedIndex.update((i) => (i > 0 ? i - 1 : list.length - 1));\r\n this.scrollToHighlighted();\r\n break;\r\n\r\n case 'Enter':\r\n event.preventDefault();\r\n\r\n if (!this.isOpen()) {\r\n this.isOpen.set(true);\r\n return;\r\n }\r\n\r\n const idx = this.highlightedIndex();\r\n if (idx >= 0) this.selectOption(list[idx]);\r\n break;\r\n\r\n case 'Tab':\r\n this.isOpen.set(false);\r\n break;\r\n\r\n case 'Escape':\r\n this.isOpen.set(false);\r\n break;\r\n }\r\n }\r\n\r\n scrollToHighlighted() {\r\n if (!isPlatformBrowser(this.platformId)) return;\r\n\r\n queueMicrotask(() => {\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\r\n if (!activeItem || !dropdown) return;\r\n\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 /** Close by clicking outside */\r\n @HostListener('document:click', ['$event'])\r\n onClickOutside(event: MouseEvent) {\r\n if (!isPlatformBrowser(this.platformId)) return;\r\n\r\n if (!this.isOpen()) return;\r\n\r\n const clickedInside = this.elRef.nativeElement.contains(event.target);\r\n if (!clickedInside) {\r\n this.isOpen.set(false);\r\n }\r\n }\r\n}\r\n","<div class=\"dropdown ys-dropdown\">\n <div class=\"input-group w-100\">\n <input #inputRef type=\"text\" class=\"form-control\" [value]=\"selectedLabels()\" [placeholder]=\"placeholder()\"\n readonly (click)=\"isOpen.set(true)\" (keydown)=\"onKeyDown($event)\" [disabled]=\"isDisabled()\" />\n <!-- (focus)=\"isOpen.set(true)\" replace with (click)=\"isOpen.set(true)\" (keydown.enter)=\"isOpen.set(true)\" -->\n\n @if(showClear() && hasSelection()){\n <button class=\"btn btn-outline-secondary\" type=\"button\" (click)=\"clearSelection()\" [disabled]=\"isDisabled()\">\n <i [ngClass]=\"clearIconClass()\"></i>\n </button>\n }\n\n <button class=\"btn btn-outline-secondary dropdown-toggle\" type=\"button\" (click)=\"toggleDropdown()\"\n [disabled]=\"isDisabled()\">\n <i [ngClass]=\"dropDownToggleIconClass()\"></i>\n </button>\n </div>\n <div class=\"dropdown-menu w-100 overflow-auto\" [class.show]=\"isOpen()\">\n\n @if(searchable()){\n <div class=\"px-2\">\n <input type=\"text\" class=\"form-control mb-2\" [placeholder]=\"searchPlaceholder()\" [ngModel]=\"searchTerm()\"\n (ngModelChange)=\"searchTerm.set($event)\" (keydown)=\"onKeyDown($event)\">\n </div>\n }\n\n @for (option of filteredOptions(); track option.value) {\n <div class=\"dropdown-item\" (click)=\"selectOption(option)\" [class.active]=\"isSelected(option)\"\n [class.highlighted]=\"$index === highlightedIndex()\">\n\n @if(itemTemplate()){\n <ng-container [ngTemplateOutlet]=\"itemTemplate()\" [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-container>\n } @else {\n @if(multiple()){\n <i class=\"{{multipleCheckIconClass()}} text-success me-1\" [class.invisible]=\"!isSelected(option)\"></i>\n }\n <!-- <span>{{option[optionLabel]}}</span> -->\n <span>{{option.label}}</span>\n }\n </div>\n }\n </div>\n</div>","/*\r\n * Public API Surface of ys-dropdown\r\n */\r\n\r\nexport * from './src/models';\r\nexport * from './src/ys-dropdown/ys-dropdown';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|