@tekus/design-system 5.28.0 → 5.29.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/fesm2022/tekus-design-system-components-button.mjs +11 -3
- package/fesm2022/tekus-design-system-components-button.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-card.mjs +1 -1
- package/fesm2022/tekus-design-system-components-card.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-drawer.mjs +17 -3
- package/fesm2022/tekus-design-system-components-drawer.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-dropdown.mjs +13 -3
- package/fesm2022/tekus-design-system-components-dropdown.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-fallback-view.mjs +1 -1
- package/fesm2022/tekus-design-system-components-fallback-view.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-icon.mjs +15 -1
- package/fesm2022/tekus-design-system-components-icon.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-menu.mjs +1 -0
- package/fesm2022/tekus-design-system-components-menu.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-message.mjs +2 -2
- package/fesm2022/tekus-design-system-components-message.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-modal.mjs +1 -1
- package/fesm2022/tekus-design-system-components-modal.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-panel-menu.mjs +1 -0
- package/fesm2022/tekus-design-system-components-panel-menu.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-select.mjs +335 -103
- package/fesm2022/tekus-design-system-components-select.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-sidebar-layout.mjs +1 -1
- package/fesm2022/tekus-design-system-components-sidebar-layout.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toast.mjs +1 -1
- package/fesm2022/tekus-design-system-components-toast.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-topbar.mjs +1 -1
- package/fesm2022/tekus-design-system-components-topbar.mjs.map +1 -1
- package/package.json +1 -1
- package/types/tekus-design-system-components-button.d.ts +9 -1
- package/types/tekus-design-system-components-drawer.d.ts +10 -1
- package/types/tekus-design-system-components-dropdown.d.ts +11 -1
- package/types/tekus-design-system-components-select.d.ts +216 -79
|
@@ -1,212 +1,444 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject,
|
|
2
|
+
import { signal, Injectable, inject, viewChild, input, model, output, effect, ChangeDetectionStrategy, Component, ElementRef, Directive } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/forms';
|
|
4
4
|
import { NgControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
5
5
|
import * as i2 from 'primeng/floatlabel';
|
|
6
6
|
import { FloatLabelModule } from 'primeng/floatlabel';
|
|
7
7
|
import { Select } from 'primeng/select';
|
|
8
|
-
import * as
|
|
8
|
+
import * as i4 from 'primeng/message';
|
|
9
9
|
import { MessageModule } from 'primeng/message';
|
|
10
|
+
import { IconComponent } from '@tekus/design-system/components/icon';
|
|
11
|
+
import { toSignal, toObservable } from '@angular/core/rxjs-interop';
|
|
12
|
+
import { combineLatest, debounceTime, auditTime, distinctUntilChanged, map, tap, switchMap, of, scan } from 'rxjs';
|
|
13
|
+
import * as i3 from 'primeng/api';
|
|
14
|
+
|
|
15
|
+
class TkSelectManager {
|
|
16
|
+
constructor() {
|
|
17
|
+
/**
|
|
18
|
+
* Reactive signal for the current search query.
|
|
19
|
+
*/
|
|
20
|
+
this.searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
|
|
21
|
+
/**
|
|
22
|
+
* Reactive signal for the current pagination page.
|
|
23
|
+
*/
|
|
24
|
+
this.page = signal(1, ...(ngDevMode ? [{ debugName: "page" }] : /* istanbul ignore next */ []));
|
|
25
|
+
/**
|
|
26
|
+
* Additional parameters to send to the data source.
|
|
27
|
+
*/
|
|
28
|
+
this.fetchParams = signal({}, ...(ngDevMode ? [{ debugName: "fetchParams" }] : /* istanbul ignore next */ []));
|
|
29
|
+
/**
|
|
30
|
+
* Sorting field.
|
|
31
|
+
*/
|
|
32
|
+
this.sortField = signal(undefined, ...(ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []));
|
|
33
|
+
/**
|
|
34
|
+
* Sorting order (1 for ASC, -1 for DESC).
|
|
35
|
+
*/
|
|
36
|
+
this.sortOrder = signal(undefined, ...(ngDevMode ? [{ debugName: "sortOrder" }] : /* istanbul ignore next */ []));
|
|
37
|
+
/**
|
|
38
|
+
* Reactive signal indicating if data is currently being fetched.
|
|
39
|
+
*/
|
|
40
|
+
this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
41
|
+
/**
|
|
42
|
+
* Reactive signal indicating if there are more items to fetch.
|
|
43
|
+
*/
|
|
44
|
+
this.hasMore = signal(true, ...(ngDevMode ? [{ debugName: "hasMore" }] : /* istanbul ignore next */ []));
|
|
45
|
+
/**
|
|
46
|
+
* Number of items per page to detect the end of data.
|
|
47
|
+
*/
|
|
48
|
+
this.pageSize = 20;
|
|
49
|
+
/**
|
|
50
|
+
* Final accumulated list of items exposed as a Signal.
|
|
51
|
+
*/
|
|
52
|
+
this.items = toSignal(combineLatest({
|
|
53
|
+
filter: toObservable(this.searchQuery).pipe(debounceTime(200)),
|
|
54
|
+
page: toObservable(this.page),
|
|
55
|
+
params: toObservable(this.fetchParams),
|
|
56
|
+
sortField: toObservable(this.sortField),
|
|
57
|
+
sortOrder: toObservable(this.sortOrder)
|
|
58
|
+
}).pipe(auditTime(0), distinctUntilChanged((prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)), map(data => ({ ...data, pageSize: this.pageSize })), tap((request) => {
|
|
59
|
+
if (request.page === 1) {
|
|
60
|
+
this.hasMore.set(true);
|
|
61
|
+
}
|
|
62
|
+
this.loading.set(true);
|
|
63
|
+
}), switchMap((request) => {
|
|
64
|
+
const fetcher$ = this.dataSource
|
|
65
|
+
? this.dataSource.fetch(request)
|
|
66
|
+
: of([]);
|
|
67
|
+
return fetcher$.pipe(tap(results => {
|
|
68
|
+
if (results.length < this.pageSize) {
|
|
69
|
+
this.hasMore.set(false);
|
|
70
|
+
}
|
|
71
|
+
}), map(results => ({ results, page: request.page })), tap(() => this.loading.set(false)));
|
|
72
|
+
}), scan((acc, { results, page }) => {
|
|
73
|
+
return page === 1 ? results : [...acc, ...results];
|
|
74
|
+
}, [])), { initialValue: [] });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Updates the search query and resets pagination.
|
|
78
|
+
* @param query - The new search string.
|
|
79
|
+
*/
|
|
80
|
+
updateSearch(query) {
|
|
81
|
+
if (this.searchQuery() !== query) {
|
|
82
|
+
this.searchQuery.set(query);
|
|
83
|
+
this.page.set(1);
|
|
84
|
+
this.hasMore.set(true);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Increments the page to trigger the next data chunk.
|
|
89
|
+
*/
|
|
90
|
+
loadNextPage() {
|
|
91
|
+
this.page.update(p => p + 1);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Configures the data provider for the manager.
|
|
95
|
+
* @param provider - Object implementing the SelectDataSource interface.
|
|
96
|
+
*/
|
|
97
|
+
setDataSource(provider) {
|
|
98
|
+
this.dataSource = provider;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Updates additional fetch parameters and resets pagination.
|
|
102
|
+
* @param params - The new parameters object.
|
|
103
|
+
*/
|
|
104
|
+
updateParams(params) {
|
|
105
|
+
if (JSON.stringify(this.fetchParams()) !== JSON.stringify(params)) {
|
|
106
|
+
this.fetchParams.set(params);
|
|
107
|
+
this.page.set(1);
|
|
108
|
+
this.hasMore.set(true);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resets the manager state to its initial values.
|
|
113
|
+
*/
|
|
114
|
+
reset() {
|
|
115
|
+
this.searchQuery.set('');
|
|
116
|
+
this.page.set(1);
|
|
117
|
+
this.hasMore.set(true);
|
|
118
|
+
}
|
|
119
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: TkSelectManager, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
120
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: TkSelectManager }); }
|
|
121
|
+
}
|
|
122
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: TkSelectManager, decorators: [{
|
|
123
|
+
type: Injectable
|
|
124
|
+
}] });
|
|
10
125
|
|
|
11
126
|
class SelectComponent {
|
|
12
127
|
constructor() {
|
|
13
128
|
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
129
|
+
this.manager = inject((TkSelectManager));
|
|
130
|
+
/** PrimeNG Select instance */
|
|
131
|
+
this.selectComponent = viewChild('pSelect', ...(ngDevMode ? [{ debugName: "selectComponent" }] : /* istanbul ignore next */ []));
|
|
132
|
+
/** Final reactive list of items */
|
|
14
133
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @description
|
|
17
|
-
* HTML id attribute for the multiselect input.
|
|
18
|
-
*
|
|
134
|
+
* HTML id attribute for the select input.
|
|
19
135
|
* @default 'select'
|
|
20
136
|
*/
|
|
21
137
|
this.id = input('select', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
22
138
|
/**
|
|
23
|
-
* @property {InputSignal<FormControl>} control
|
|
24
|
-
* @description
|
|
25
139
|
* External FormControl used to read/set the input value.
|
|
26
|
-
* If not provided, an internal FormControl is created.
|
|
27
140
|
*/
|
|
28
141
|
this.control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : /* istanbul ignore next */ []));
|
|
29
142
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* Array of available options displayed in the dropdown.
|
|
143
|
+
* Static options for synchronous mode.
|
|
144
|
+
* If provided, they take precedence over the manager's async stream.
|
|
33
145
|
*/
|
|
34
146
|
this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
35
147
|
/**
|
|
36
|
-
*
|
|
37
|
-
|
|
148
|
+
* Data source for asynchronous infinite scroll mode.
|
|
149
|
+
*/
|
|
150
|
+
this.dataSource = model(...(ngDevMode ? [undefined, { debugName: "dataSource" }] : /* istanbul ignore next */ []));
|
|
151
|
+
/**
|
|
38
152
|
* Name of the property used to display the text of each option.
|
|
39
|
-
*
|
|
40
153
|
* @default 'label'
|
|
41
154
|
*/
|
|
42
155
|
this.optionLabel = input('label', ...(ngDevMode ? [{ debugName: "optionLabel" }] : /* istanbul ignore next */ []));
|
|
43
156
|
/**
|
|
44
|
-
* @property {string} label
|
|
45
|
-
* @description
|
|
46
157
|
* Floating label displayed above the select input.
|
|
47
158
|
*/
|
|
48
159
|
this.label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
49
160
|
/**
|
|
50
|
-
* @property {boolean} showClear
|
|
51
|
-
* @description
|
|
52
161
|
* Enables the clear button to remove the current selection.
|
|
53
|
-
*
|
|
54
162
|
* @default true
|
|
55
163
|
*/
|
|
56
164
|
this.showClear = input(true, ...(ngDevMode ? [{ debugName: "showClear" }] : /* istanbul ignore next */ []));
|
|
57
165
|
/**
|
|
58
|
-
* @property {T | null} value
|
|
59
|
-
* @description
|
|
60
|
-
* Internal selected value. Synced with Angular forms and the model signal.
|
|
61
|
-
*
|
|
62
|
-
* @internal
|
|
63
|
-
*/
|
|
64
|
-
this.value = null;
|
|
65
|
-
/**
|
|
66
|
-
* @property {boolean} disabled
|
|
67
|
-
* @description
|
|
68
166
|
* Determines whether the select field is disabled.
|
|
69
|
-
*
|
|
70
167
|
* @default false
|
|
71
168
|
*/
|
|
72
169
|
this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
73
|
-
this.internalDisabled = signal(false, ...(ngDevMode ? [{ debugName: "internalDisabled" }] : /* istanbul ignore next */ []));
|
|
74
170
|
/**
|
|
75
|
-
* @property {InputSignal<string>} errorMessage
|
|
76
|
-
* @description
|
|
77
171
|
* Message to display when the control is invalid and touched.
|
|
78
172
|
*/
|
|
79
173
|
this.errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
80
174
|
/**
|
|
81
|
-
* @property {InputSignal<string>} hint
|
|
82
|
-
* @description
|
|
83
175
|
* Hint text to display below the input.
|
|
84
176
|
*/
|
|
85
177
|
this.hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
86
178
|
/**
|
|
87
|
-
*
|
|
88
|
-
* @
|
|
179
|
+
* Enables filtering/search input.
|
|
180
|
+
* @default false
|
|
181
|
+
*/
|
|
182
|
+
this.filter = input(false, ...(ngDevMode ? [{ debugName: "filter" }] : /* istanbul ignore next */ []));
|
|
183
|
+
/**
|
|
184
|
+
* Placeholder text displayed when no value is selected.
|
|
185
|
+
* @default 'Select an option'
|
|
186
|
+
*/
|
|
187
|
+
this.placeholder = input('Select an option', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
188
|
+
/**
|
|
189
|
+
* Loading state for the dropdown.
|
|
190
|
+
*/
|
|
191
|
+
this.loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
192
|
+
/**
|
|
193
|
+
* Additional parameters for the async data source.
|
|
194
|
+
* Useful for sending context like categoryId, parentId, etc.
|
|
195
|
+
*/
|
|
196
|
+
this.fetchParams = input({}, ...(ngDevMode ? [{ debugName: "fetchParams" }] : /* istanbul ignore next */ []));
|
|
197
|
+
/**
|
|
198
|
+
* Field name to sort by in the async data source.
|
|
199
|
+
*/
|
|
200
|
+
this.sortField = input(undefined, ...(ngDevMode ? [{ debugName: "sortField" }] : /* istanbul ignore next */ []));
|
|
201
|
+
/**
|
|
202
|
+
* Order to sort by (1 for ASC, -1 for DESC).
|
|
203
|
+
*/
|
|
204
|
+
this.sortOrder = input(undefined, ...(ngDevMode ? [{ debugName: "sortOrder" }] : /* istanbul ignore next */ []));
|
|
205
|
+
/**
|
|
206
|
+
* Internal writable signal for the disabled state.
|
|
207
|
+
*/
|
|
208
|
+
this.internalDisabled = signal(false, ...(ngDevMode ? [{ debugName: "internalDisabled" }] : /* istanbul ignore next */ []));
|
|
209
|
+
/**
|
|
89
210
|
* Two-way binding model using Angular signals.
|
|
90
|
-
*
|
|
211
|
+
* This is the single source of truth for the selected value.
|
|
212
|
+
*/
|
|
213
|
+
this.model = model(null, ...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
214
|
+
/**
|
|
215
|
+
* Text to display when there are no options.
|
|
91
216
|
*/
|
|
92
|
-
this.
|
|
217
|
+
this.emptyMessage = input('No data available', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
|
|
218
|
+
/**
|
|
219
|
+
* Text to display when no results match the filter.
|
|
220
|
+
*/
|
|
221
|
+
this.emptyFilterMessage = input('No results found', ...(ngDevMode ? [{ debugName: "emptyFilterMessage" }] : /* istanbul ignore next */ []));
|
|
93
222
|
/**
|
|
94
|
-
* @event modelChange
|
|
95
|
-
* @description
|
|
96
223
|
* Emits whenever the value changes.
|
|
97
|
-
* Payload: the selected item of type `T` or `null`.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* <tk-select (modelChange)="onChange($event)"></tk-select>
|
|
101
224
|
*/
|
|
102
225
|
this.modelChange = output();
|
|
226
|
+
/**
|
|
227
|
+
* Emits the filter search term.
|
|
228
|
+
*/
|
|
229
|
+
this.filterChange = output();
|
|
103
230
|
// CVA callbacks
|
|
104
231
|
this.onChangeFn = () => { };
|
|
105
232
|
this.onTouchedFn = () => { };
|
|
106
|
-
this.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
233
|
+
this.scrollHandler = this.handleScroll.bind(this);
|
|
234
|
+
this.lastListContainer = null;
|
|
235
|
+
if (this.ngControl) {
|
|
236
|
+
this.ngControl.valueAccessor = this;
|
|
237
|
+
}
|
|
238
|
+
// Synchronize parameters with the manager
|
|
239
|
+
effect(() => {
|
|
240
|
+
this.manager.updateParams(this.fetchParams());
|
|
241
|
+
});
|
|
242
|
+
effect(() => {
|
|
243
|
+
this.manager.sortField.set(this.sortField());
|
|
244
|
+
this.manager.sortOrder.set(this.sortOrder());
|
|
245
|
+
});
|
|
246
|
+
// Synchronize disabled state
|
|
247
|
+
effect(() => {
|
|
117
248
|
this.internalDisabled.set(this.disabled());
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
*/
|
|
125
|
-
this.syncModel = effect(() => {
|
|
126
|
-
const v = this.model();
|
|
127
|
-
if (v !== this.value) {
|
|
128
|
-
this.value = v ?? null;
|
|
129
|
-
this.onChangeFn(v ?? null);
|
|
249
|
+
});
|
|
250
|
+
// Synchronize data source (Strictly necessary effect to bridge with manager)
|
|
251
|
+
effect(() => {
|
|
252
|
+
const source = this.dataSource();
|
|
253
|
+
if (source) {
|
|
254
|
+
this.manager.setDataSource(source);
|
|
130
255
|
}
|
|
131
|
-
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Displays the items from the manager if provided, otherwise the static options.
|
|
260
|
+
* Includes a "Ghost Option" logic to ensure the selected item is always visible
|
|
261
|
+
* even if it's not in the current loaded chunk of data.
|
|
262
|
+
*/
|
|
263
|
+
get items() {
|
|
264
|
+
const baseItems = this.dataSource()
|
|
265
|
+
? this.manager.items()
|
|
266
|
+
: this.options();
|
|
267
|
+
const selected = this.model();
|
|
268
|
+
if (!selected)
|
|
269
|
+
return baseItems;
|
|
270
|
+
// Check if selected item is already in the list to avoid duplicates
|
|
271
|
+
// We compare by stringifying or by a known 'id' field if possible
|
|
272
|
+
const exists = baseItems.some(item => {
|
|
273
|
+
if (item === selected)
|
|
274
|
+
return true;
|
|
275
|
+
const itemId = item?.['id'] || item?.['code'];
|
|
276
|
+
const selectedId = selected?.['id'] || selected?.['code'];
|
|
277
|
+
return itemId !== undefined && itemId === selectedId;
|
|
278
|
+
});
|
|
279
|
+
return exists ? baseItems : [selected, ...baseItems];
|
|
132
280
|
}
|
|
133
|
-
// -----------------------------------
|
|
134
|
-
// CONTROL VALUE ACCESSOR (Forms API)
|
|
135
|
-
// -----------------------------------
|
|
136
281
|
/**
|
|
137
|
-
*
|
|
138
|
-
* @
|
|
139
|
-
* Receives value updates from Angular Forms and writes them into the component.
|
|
140
|
-
*
|
|
141
|
-
* @param {T | null} value - New value from the forms API.
|
|
282
|
+
* Receives value updates from Angular Forms API.
|
|
283
|
+
* @param value - New value from the forms API.
|
|
142
284
|
*/
|
|
143
285
|
writeValue(value) {
|
|
144
286
|
this.model.set(value);
|
|
145
287
|
}
|
|
146
288
|
/**
|
|
147
|
-
* @method registerOnChange
|
|
148
|
-
* @description
|
|
149
289
|
* Registers a callback that is invoked when the component's value changes.
|
|
290
|
+
* @param fn - The callback function.
|
|
150
291
|
*/
|
|
151
292
|
registerOnChange(fn) {
|
|
152
293
|
this.onChangeFn = fn;
|
|
153
294
|
}
|
|
154
295
|
/**
|
|
155
|
-
* @method registerOnTouched
|
|
156
|
-
* @description
|
|
157
296
|
* Registers a callback invoked when the component is touched.
|
|
297
|
+
* @param fn - The callback function.
|
|
158
298
|
*/
|
|
159
299
|
registerOnTouched(fn) {
|
|
160
300
|
this.onTouchedFn = fn;
|
|
161
301
|
}
|
|
162
302
|
/**
|
|
163
|
-
*
|
|
164
|
-
* @
|
|
165
|
-
* Updates the disabled state of the select control.
|
|
166
|
-
*
|
|
167
|
-
* @param {boolean} isDisabled - Whether the component should be disabled.
|
|
303
|
+
* Updates the disabled state of the control.
|
|
304
|
+
* @param isDisabled - Whether the component should be disabled.
|
|
168
305
|
*/
|
|
169
306
|
setDisabledState(isDisabled) {
|
|
170
307
|
this.internalDisabled.set(isDisabled);
|
|
171
308
|
}
|
|
172
|
-
// -----------------------------------
|
|
173
|
-
// UI EVENTS
|
|
174
|
-
// -----------------------------------
|
|
175
309
|
/**
|
|
176
|
-
*
|
|
177
|
-
* @
|
|
178
|
-
* Handles the selection event emitted by the PrimeNG Select component.
|
|
179
|
-
* Updates Angular Forms, Signals, and emits the modelChange event.
|
|
180
|
-
*
|
|
181
|
-
* @param event - Event containing the `value` of the selected option.
|
|
310
|
+
* Handles UI changes from the PrimeNG Select.
|
|
311
|
+
* @param event - Event containing the selected value.
|
|
182
312
|
*/
|
|
183
313
|
handleChange(event) {
|
|
184
314
|
const value = event.value ?? null;
|
|
185
|
-
this.value
|
|
315
|
+
this.model.set(value);
|
|
186
316
|
this.onChangeFn(value);
|
|
187
317
|
this.onTouchedFn();
|
|
188
|
-
this.model.set(value);
|
|
189
318
|
this.modelChange.emit(value);
|
|
190
319
|
if (this.effectiveControl) {
|
|
191
|
-
this.effectiveControl.setValue(value);
|
|
320
|
+
this.effectiveControl.setValue(value, { emitEvent: false });
|
|
192
321
|
this.effectiveControl.markAsDirty();
|
|
193
322
|
this.effectiveControl.markAsTouched();
|
|
194
323
|
}
|
|
195
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Handles filter input changes and notifies the manager.
|
|
327
|
+
* @param event - Filter event containing the search term.
|
|
328
|
+
*/
|
|
329
|
+
handleFilter(event) {
|
|
330
|
+
const query = event.filter || '';
|
|
331
|
+
this.manager.updateSearch(query);
|
|
332
|
+
this.filterChange.emit(event);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Returns the underlying FormControl for validation state checking.
|
|
336
|
+
*/
|
|
196
337
|
get effectiveControl() {
|
|
197
338
|
return this.ngControl?.control || null;
|
|
198
339
|
}
|
|
340
|
+
/**
|
|
341
|
+
* Adds a scroll listener to the PrimeNG select list container when the panel opens.
|
|
342
|
+
*/
|
|
343
|
+
onPanelShow() {
|
|
344
|
+
const listContainer = document.querySelector('.p-select-list-container');
|
|
345
|
+
if (listContainer) {
|
|
346
|
+
this.lastListContainer = listContainer;
|
|
347
|
+
listContainer.addEventListener('scroll', this.scrollHandler);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Cleans up state, removes listeners and resets the manager when the panel closes.
|
|
352
|
+
*/
|
|
353
|
+
onPanelHide() {
|
|
354
|
+
this.removeScrollListener();
|
|
355
|
+
this.manager.reset();
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Cleans up listeners on component destruction.
|
|
359
|
+
*/
|
|
360
|
+
ngOnDestroy() {
|
|
361
|
+
this.removeScrollListener();
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Safely removes the scroll event listener.
|
|
365
|
+
*/
|
|
366
|
+
removeScrollListener() {
|
|
367
|
+
if (this.lastListContainer) {
|
|
368
|
+
this.lastListContainer.removeEventListener('scroll', this.scrollHandler);
|
|
369
|
+
this.lastListContainer = null;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
/**
|
|
373
|
+
* Detects if the user has reached the bottom of the list.
|
|
374
|
+
*/
|
|
375
|
+
handleScroll(event) {
|
|
376
|
+
const target = event.target;
|
|
377
|
+
if (!target)
|
|
378
|
+
return;
|
|
379
|
+
// Trigger near the bottom (1px threshold)
|
|
380
|
+
const atBottom = target.scrollHeight - target.scrollTop <= target.clientHeight + 1;
|
|
381
|
+
if (atBottom &&
|
|
382
|
+
this.manager.dataSource &&
|
|
383
|
+
!this.manager.loading() &&
|
|
384
|
+
this.manager.hasMore()) {
|
|
385
|
+
this.manager.loadNextPage();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
199
388
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
200
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.3", type: SelectComponent, isStandalone: true, selector: "tk-select", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", modelChange: "modelChange" }, ngImport: i0, template: "<p-floatlabel class=\"w-full\">\n <p-select [id]=\"id()\" class=\"w-full\" [options]=\"options()\" [optionLabel]=\"optionLabel()\" [showClear]=\"showClear()\"\n [disabled]=\"disabled()\" [ngModel]=\"value\" [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \" [class.ng-dirty]=\"effectiveControl?.dirty\" [class.ng-touched]=\"effectiveControl?.touched\"\n (onChange)=\"handleChange($event)\" />\n <label [for]=\"id()\">{{ label() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>", styles: [":host ::ng-deep .p-select{width:100%;border:none;border-bottom:1px solid var(--tk-color-border-default, #cecdcd);border-radius:0;color:var(--tk-color-text-default, #191a1b);background-color:transparent}:host ::ng-deep .p-select:focus{border-color:var(--tk-color-primary-default, #16006f)}:host ::ng-deep .p-select.ng-invalid.ng-dirty,:host ::ng-deep .p-select.ng-invalid.ng-touched{border-color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-label{padding:var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-25, 4px)!important}:host ::ng-deep .p-floatlabel .p-inputwrapper-focus~label{color:var(--tk-primary-600, #140065);top:-.688rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(input.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel label{color:var(--tk-color-base-surface-500, #8a8a8b);font-family:var(--tk-font-family, Poppins, sans-serif);font-weight:var(--tk-font-weight-400, 400);left:var(--tk-spacing-base-25, .25rem);transition-duration:.2s}:host ::ng-deep .p-floatlabel:has(.p-select:focus) label,:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065);top:-.75rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065)}:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-dirty) label,:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-touched) label{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-option span{color:var(--tk-color-text-default, #191a1b)!important;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .p-select-option:hover{background-color:var(--tk-primary-100, #b7b0d2)!important}:host ::ng-deep .p-select-option[data-p-highlight=true]{background-color:var(--tk-primary-100, #b7b0d2)!important;color:var(--tk-primary-500, #16006f)!important}:host ::ng-deep .p-select-clear-icon{color:var(--tk-surface-700, #424243)!important}:host ::ng-deep .p-select-option-check-icon{color:transparent}:host ::ng-deep p-message[severity=error] .p-inline-message-text,:host ::ng-deep p-message[severity=error] span{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep p-message[severity=secondary] .p-inline-message-text,:host ::ng-deep p-message[severity=secondary] span{color:var(--tk-color-base-surface-600, #5d5d5e)}:host ::ng-deep .tk-select-bottom{display:flex;justify-content:space-between;align-items:flex-start;margin-top:var(--tk-spacing-base-25, .25rem);min-height:var(--tk-spacing-base-125, 1.25rem)}:host ::ng-deep .tk-select-messages{flex:1;margin-right:var(--tk-spacing-base-100, 1rem)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FloatLabelModule }, { kind: "component", type: i2.FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i3.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
389
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.3", type: SelectComponent, isStandalone: true, selector: "tk-select", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, dataSource: { classPropertyName: "dataSource", publicName: "dataSource", isSignal: true, isRequired: false, transformFunction: null }, optionLabel: { classPropertyName: "optionLabel", publicName: "optionLabel", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, showClear: { classPropertyName: "showClear", publicName: "showClear", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, fetchParams: { classPropertyName: "fetchParams", publicName: "fetchParams", isSignal: true, isRequired: false, transformFunction: null }, sortField: { classPropertyName: "sortField", publicName: "sortField", isSignal: true, isRequired: false, transformFunction: null }, sortOrder: { classPropertyName: "sortOrder", publicName: "sortOrder", isSignal: true, isRequired: false, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dataSource: "dataSourceChange", model: "modelChange", modelChange: "modelChange", filterChange: "filterChange" }, providers: [TkSelectManager], viewQueries: [{ propertyName: "selectComponent", first: true, predicate: ["pSelect"], descendants: true, isSignal: true }], ngImport: i0, template: "<p-floatlabel class=\"w-full\">\n <p-select\n #pSelect\n [id]=\"id()\"\n class=\"w-full\"\n [options]=\"items\"\n [optionLabel]=\"optionLabel()\"\n [showClear]=\"showClear()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"model()\"\n [filter]=\"filter()\"\n [loading]=\"manager.loading()\"\n [emptyMessage]=\"emptyMessage()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onChange)=\"handleChange($event)\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"onPanelShow()\"\n (onHide)=\"onPanelHide()\"\n [resetFilterOnHide]=\"true\">\n \n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if (model()) {\n <div>{{ $any(model())[optionLabel()] }}</div>\n } @else if (placeholder()) {\n <span class=\"text-secondary\">{{ placeholder() }}</span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"empty\">\n <div class=\"tk-select-empty-container\">\n <tk-icon icon=\"info\" size=\"2xl\"></tk-icon>\n <span>{{ emptyMessage() }}</span>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"emptyfilter\">\n <div class=\"tk-select-empty-container\">\n <tk-icon icon=\"magnifying-glass\" size=\"2xl\"></tk-icon>\n <span>{{ emptyFilterMessage() }}</span>\n </div>\n </ng-template>\n </p-select>\n <label [for]=\"id()\">{{ label() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\n", styles: [":host ::ng-deep .p-select{width:100%;border:none;border-bottom:1px solid var(--tk-color-border-default, #cecdcd);border-radius:0;color:var(--tk-color-text-default, #191a1b);background-color:transparent}:host ::ng-deep .p-select:focus{border-color:var(--tk-color-primary-default, #16006f)}:host ::ng-deep .p-select.ng-invalid.ng-dirty,:host ::ng-deep .p-select.ng-invalid.ng-touched{border-color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-label{padding:var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-25, 4px)!important}:host ::ng-deep .p-floatlabel .p-inputwrapper-focus~label{color:var(--tk-primary-600, #140065);top:-.688rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(input.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel label{color:var(--tk-color-base-surface-500, #8a8a8b);font-family:var(--tk-font-family, Poppins, sans-serif);font-weight:var(--tk-font-weight-400, 400);left:var(--tk-spacing-base-25, .25rem);transition-duration:.2s}:host ::ng-deep .p-floatlabel:has(.p-select:focus) label,:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065);top:-.75rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065)}:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-dirty) label,:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-touched) label{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-option span{color:var(--tk-color-text-default, #191a1b)!important;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .p-select-option:hover{background-color:var(--tk-primary-100, #b7b0d2)!important}:host ::ng-deep .p-select-option[data-p-highlight=true]{background-color:var(--tk-primary-100, #b7b0d2)!important;color:var(--tk-primary-500, #16006f)!important}:host ::ng-deep .p-select-clear-icon{color:var(--tk-surface-700, #424243)!important}:host ::ng-deep .p-select-option-check-icon{color:transparent}:host ::ng-deep p-message[severity=error] .p-inline-message-text,:host ::ng-deep p-message[severity=error] span{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep p-message[severity=secondary] .p-inline-message-text,:host ::ng-deep p-message[severity=secondary] span{color:var(--tk-color-base-surface-600, #5d5d5e)}:host ::ng-deep .tk-select-bottom{display:flex;justify-content:space-between;align-items:flex-start;margin-top:var(--tk-spacing-base-25, .25rem);min-height:var(--tk-spacing-base-125, 1.25rem)}:host ::ng-deep .tk-select-messages{flex:1;margin-right:var(--tk-spacing-base-100, 1rem)}:host ::ng-deep .tk-select-empty-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--tk-spacing-base-150, 1.5rem);text-align:center;color:var(--tk-color-base-surface-500, #8a8a8b)}:host ::ng-deep .tk-select-empty-container tk-icon{margin-bottom:var(--tk-spacing-base-50, .5rem)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { 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: "component", type: Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: FloatLabelModule }, { kind: "component", type: i2.FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: IconComponent, selector: "tk-icon", inputs: ["icon", "styleIcon", "color", "size", "disabled"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
201
390
|
}
|
|
202
391
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: SelectComponent, decorators: [{
|
|
203
392
|
type: Component,
|
|
204
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'tk-select',
|
|
205
|
-
|
|
393
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'tk-select', providers: [TkSelectManager], imports: [
|
|
394
|
+
FormsModule,
|
|
395
|
+
Select,
|
|
396
|
+
FloatLabelModule,
|
|
397
|
+
MessageModule,
|
|
398
|
+
ReactiveFormsModule,
|
|
399
|
+
IconComponent,
|
|
400
|
+
], template: "<p-floatlabel class=\"w-full\">\n <p-select\n #pSelect\n [id]=\"id()\"\n class=\"w-full\"\n [options]=\"items\"\n [optionLabel]=\"optionLabel()\"\n [showClear]=\"showClear()\"\n [disabled]=\"disabled()\"\n [ngModel]=\"model()\"\n [filter]=\"filter()\"\n [loading]=\"manager.loading()\"\n [emptyMessage]=\"emptyMessage()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onChange)=\"handleChange($event)\"\n (onFilter)=\"handleFilter($event)\"\n (onShow)=\"onPanelShow()\"\n (onHide)=\"onPanelHide()\"\n [resetFilterOnHide]=\"true\">\n \n <ng-template pTemplate=\"selectedItem\" let-selectedOption>\n @if (model()) {\n <div>{{ $any(model())[optionLabel()] }}</div>\n } @else if (placeholder()) {\n <span class=\"text-secondary\">{{ placeholder() }}</span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"empty\">\n <div class=\"tk-select-empty-container\">\n <tk-icon icon=\"info\" size=\"2xl\"></tk-icon>\n <span>{{ emptyMessage() }}</span>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"emptyfilter\">\n <div class=\"tk-select-empty-container\">\n <tk-icon icon=\"magnifying-glass\" size=\"2xl\"></tk-icon>\n <span>{{ emptyFilterMessage() }}</span>\n </div>\n </ng-template>\n </p-select>\n <label [for]=\"id()\">{{ label() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\n", styles: [":host ::ng-deep .p-select{width:100%;border:none;border-bottom:1px solid var(--tk-color-border-default, #cecdcd);border-radius:0;color:var(--tk-color-text-default, #191a1b);background-color:transparent}:host ::ng-deep .p-select:focus{border-color:var(--tk-color-primary-default, #16006f)}:host ::ng-deep .p-select.ng-invalid.ng-dirty,:host ::ng-deep .p-select.ng-invalid.ng-touched{border-color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-label{padding:var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-25, 4px)!important}:host ::ng-deep .p-floatlabel .p-inputwrapper-focus~label{color:var(--tk-primary-600, #140065);top:-.688rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(input.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel label{color:var(--tk-color-base-surface-500, #8a8a8b);font-family:var(--tk-font-family, Poppins, sans-serif);font-weight:var(--tk-font-weight-400, 400);left:var(--tk-spacing-base-25, .25rem);transition-duration:.2s}:host ::ng-deep .p-floatlabel:has(.p-select:focus) label,:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065);top:-.75rem}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(.p-filled) label{top:-.75rem;color:var(--tk-color-base-surface-950, #191a1b)}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-focus) label{color:var(--tk-color-base-primary-600, #140065)}:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-dirty) label,:host ::ng-deep .p-floatlabel:has(.p-select.ng-invalid.ng-touched) label{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep .p-select-option span{color:var(--tk-color-text-default, #191a1b)!important;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .p-select-option:hover{background-color:var(--tk-primary-100, #b7b0d2)!important}:host ::ng-deep .p-select-option[data-p-highlight=true]{background-color:var(--tk-primary-100, #b7b0d2)!important;color:var(--tk-primary-500, #16006f)!important}:host ::ng-deep .p-select-clear-icon{color:var(--tk-surface-700, #424243)!important}:host ::ng-deep .p-select-option-check-icon{color:transparent}:host ::ng-deep p-message[severity=error] .p-inline-message-text,:host ::ng-deep p-message[severity=error] span{color:var(--tk-color-base-red-700, #cf2604)}:host ::ng-deep p-message[severity=secondary] .p-inline-message-text,:host ::ng-deep p-message[severity=secondary] span{color:var(--tk-color-base-surface-600, #5d5d5e)}:host ::ng-deep .tk-select-bottom{display:flex;justify-content:space-between;align-items:flex-start;margin-top:var(--tk-spacing-base-25, .25rem);min-height:var(--tk-spacing-base-125, 1.25rem)}:host ::ng-deep .tk-select-messages{flex:1;margin-right:var(--tk-spacing-base-100, 1rem)}:host ::ng-deep .tk-select-empty-container{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--tk-spacing-base-150, 1.5rem);text-align:center;color:var(--tk-color-base-surface-500, #8a8a8b)}:host ::ng-deep .tk-select-empty-container tk-icon{margin-bottom:var(--tk-spacing-base-50, .5rem)}\n"] }]
|
|
401
|
+
}], ctorParameters: () => [], propDecorators: { selectComponent: [{ type: i0.ViewChild, args: ['pSelect', { isSignal: true }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], dataSource: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataSource", required: false }] }, { type: i0.Output, args: ["dataSourceChange"] }], optionLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "optionLabel", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], showClear: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClear", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], fetchParams: [{ type: i0.Input, args: [{ isSignal: true, alias: "fetchParams", required: false }] }], sortField: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortField", required: false }] }], sortOrder: [{ type: i0.Input, args: [{ isSignal: true, alias: "sortOrder", required: false }] }], model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], modelChange: [{ type: i0.Output, args: ["modelChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }] } });
|
|
402
|
+
|
|
403
|
+
class IntersectionDirective {
|
|
404
|
+
constructor() {
|
|
405
|
+
/**
|
|
406
|
+
* Emits when the element enters the viewport.
|
|
407
|
+
*/
|
|
408
|
+
this.intersect = output();
|
|
409
|
+
this.element = inject(ElementRef);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Initializes the Intersection Observer on component mount.
|
|
413
|
+
*/
|
|
414
|
+
ngOnInit() {
|
|
415
|
+
this.observer = new IntersectionObserver(([entry]) => {
|
|
416
|
+
if (entry.isIntersecting) {
|
|
417
|
+
this.intersect.emit();
|
|
418
|
+
}
|
|
419
|
+
}, { threshold: 0.1 });
|
|
420
|
+
this.observer.observe(this.element.nativeElement);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Cleans up the observer to prevent memory leaks.
|
|
424
|
+
*/
|
|
425
|
+
ngOnDestroy() {
|
|
426
|
+
this.observer?.disconnect();
|
|
427
|
+
}
|
|
428
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: IntersectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
429
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.3", type: IntersectionDirective, isStandalone: true, selector: "[tkIntersection]", outputs: { intersect: "intersect" }, ngImport: i0 }); }
|
|
430
|
+
}
|
|
431
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: IntersectionDirective, decorators: [{
|
|
432
|
+
type: Directive,
|
|
433
|
+
args: [{
|
|
434
|
+
selector: '[tkIntersection]',
|
|
435
|
+
standalone: true
|
|
436
|
+
}]
|
|
437
|
+
}], ctorParameters: () => [], propDecorators: { intersect: [{ type: i0.Output, args: ["intersect"] }] } });
|
|
206
438
|
|
|
207
439
|
/**
|
|
208
440
|
* Generated bundle index. Do not edit.
|
|
209
441
|
*/
|
|
210
442
|
|
|
211
|
-
export { SelectComponent };
|
|
443
|
+
export { IntersectionDirective, SelectComponent, TkSelectManager };
|
|
212
444
|
//# sourceMappingURL=tekus-design-system-components-select.mjs.map
|