@tekus/design-system 5.29.2 → 5.30.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.
@@ -1,13 +1,105 @@
1
1
  import * as _angular_core from '@angular/core';
2
+ import { OnDestroy } from '@angular/core';
2
3
  import { ControlValueAccessor, NgControl, FormControl } from '@angular/forms';
4
+ import { MultiSelect } from 'primeng/multiselect';
5
+ import { Observable } from 'rxjs';
3
6
 
4
7
  interface MultiSelectOption {
5
8
  name: string;
6
9
  code: string;
7
10
  }
8
11
 
9
- declare class MultiselectComponent implements ControlValueAccessor {
12
+ /**
13
+ * Standard request object for fetching data from an asynchronous source.
14
+ * Aligned with PrimeNG LazyLoadEvent patterns.
15
+ */
16
+ interface TkMultiSelectRequest {
17
+ filter: string;
18
+ page: number;
19
+ pageSize: number;
20
+ sortField?: string;
21
+ sortOrder?: number;
22
+ params?: Record<string, unknown>;
23
+ }
24
+ /**
25
+ * Interface representing the data source for the Multiselect manager.
26
+ */
27
+ interface MultiSelectDataSource<T = MultiSelectOption> {
28
+ fetch(request: TkMultiSelectRequest): Observable<T[]>;
29
+ }
30
+ declare class TkMultiSelectManager<T = MultiSelectOption> {
31
+ /**
32
+ * Reactive signal for the current search query.
33
+ */
34
+ searchQuery: _angular_core.WritableSignal<string>;
35
+ /**
36
+ * Reactive signal for the current pagination page.
37
+ */
38
+ page: _angular_core.WritableSignal<number>;
39
+ /**
40
+ * Data source provider for fetching items.
41
+ */
42
+ dataSource: MultiSelectDataSource<T> | undefined;
43
+ /**
44
+ * Additional parameters to send to the data source.
45
+ */
46
+ fetchParams: _angular_core.WritableSignal<Record<string, unknown>>;
47
+ /**
48
+ * Sorting field.
49
+ */
50
+ sortField: _angular_core.WritableSignal<string | undefined>;
51
+ /**
52
+ * Sorting order (1 for ASC, -1 for DESC).
53
+ */
54
+ sortOrder: _angular_core.WritableSignal<number | undefined>;
55
+ /**
56
+ * Reactive signal indicating if data is currently being fetched.
57
+ */
58
+ loading: _angular_core.WritableSignal<boolean>;
59
+ /**
60
+ * Reactive signal indicating if there are more items to fetch.
61
+ */
62
+ hasMore: _angular_core.WritableSignal<boolean>;
63
+ /**
64
+ * Number of items per page to detect the end of data.
65
+ */
66
+ pageSize: number;
67
+ /**
68
+ * Final accumulated list of items exposed as a Signal.
69
+ */
70
+ items: _angular_core.Signal<T[]>;
71
+ /**
72
+ * Updates the search query and resets pagination.
73
+ * @param query - The new search string.
74
+ */
75
+ updateSearch(query: string): void;
76
+ /**
77
+ * Increments the page to trigger the next data chunk.
78
+ */
79
+ loadNextPage(): void;
80
+ /**
81
+ * Configures the data provider for the manager.
82
+ * @param provider - Object implementing the MultiSelectDataSource interface.
83
+ */
84
+ setDataSource(provider: MultiSelectDataSource<T>): void;
85
+ /**
86
+ * Updates additional fetch parameters and resets pagination.
87
+ * @param params - The new parameters object.
88
+ */
89
+ updateParams(params: Record<string, unknown>): void;
90
+ /**
91
+ * Resets the manager state to its initial values.
92
+ */
93
+ reset(): void;
94
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<TkMultiSelectManager<any>, never>;
95
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<TkMultiSelectManager<any>>;
96
+ }
97
+
98
+ declare class MultiselectComponent implements ControlValueAccessor, OnDestroy {
10
99
  readonly ngControl: NgControl | null;
100
+ readonly manager: TkMultiSelectManager<any>;
101
+ /** PrimeNG MultiSelect instance */
102
+ readonly multiselectComponent: _angular_core.Signal<MultiSelect | undefined>;
11
103
  constructor();
12
104
  /**
13
105
  * @property {Signal<MultiSelectOption[]>} selectionPool
@@ -21,6 +113,10 @@ declare class MultiselectComponent implements ControlValueAccessor {
21
113
  * The model signal for two-way binding.
22
114
  */
23
115
  readonly model: _angular_core.ModelSignal<MultiSelectOption[] | null>;
116
+ /**
117
+ * Data source for asynchronous infinite scroll mode.
118
+ */
119
+ readonly dataSource: _angular_core.ModelSignal<MultiSelectDataSource<MultiSelectOption> | undefined>;
24
120
  /**
25
121
  * @property {MultiSelectOption[]} options
26
122
  * @description
@@ -96,17 +192,47 @@ declare class MultiselectComponent implements ControlValueAccessor {
96
192
  */
97
193
  styleClass: _angular_core.InputSignal<string>;
98
194
  /**
99
- * @property {InputSignal<string>} errorMessage
100
- * @description
101
- * Message to display when the control is invalid and touched.
102
- */
195
+ * @property {InputSignal<string>} errorMessage
196
+ * @description
197
+ * Message to display when the control is invalid and touched.
198
+ */
103
199
  errorMessage: _angular_core.InputSignal<string>;
104
200
  /**
105
- * @property {InputSignal<string>} hint
106
- * @description
107
- * Hint text to display below the input.
108
- */
201
+ * @property {InputSignal<string>} hint
202
+ * @description
203
+ * Hint text to display below the input.
204
+ */
109
205
  hint: _angular_core.InputSignal<string>;
206
+ /**
207
+ * Loading state for the dropdown.
208
+ */
209
+ loading: _angular_core.InputSignal<boolean>;
210
+ /**
211
+ * Text to display when there are no options.
212
+ */
213
+ emptyMessage: _angular_core.InputSignal<string>;
214
+ /**
215
+ * Additional parameters for the async data source.
216
+ * Useful for sending context like categoryId, parentId, etc.
217
+ */
218
+ fetchParams: _angular_core.InputSignal<Record<string, unknown>>;
219
+ /**
220
+ * Field name to sort by in the async data source.
221
+ */
222
+ sortField: _angular_core.InputSignal<string | undefined>;
223
+ /**
224
+ * Order to sort by (1 for ASC, -1 for DESC).
225
+ */
226
+ sortOrder: _angular_core.InputSignal<number | undefined>;
227
+ /**
228
+ * Determines whether the select field is disabled.
229
+ * @default false
230
+ */
231
+ disabled: _angular_core.InputSignal<boolean>;
232
+ /**
233
+ * Internal writable signal for the disabled state.
234
+ */
235
+ readonly internalDisabled: _angular_core.WritableSignal<boolean>;
110
236
  /**
111
237
  * @event selectionChange
112
238
  * @description
@@ -123,6 +249,8 @@ declare class MultiselectComponent implements ControlValueAccessor {
123
249
  * Emits the filter text when the user types in the search input.
124
250
  */
125
251
  readonly filterChange: _angular_core.OutputEmitterRef<string>;
252
+ private readonly scrollHandler;
253
+ private lastListContainer;
126
254
  /**
127
255
  * @property internalOptions
128
256
  * @description
@@ -199,6 +327,31 @@ declare class MultiselectComponent implements ControlValueAccessor {
199
327
  * @param fn - The callback function.
200
328
  */
201
329
  registerOnTouched(fn: () => void): void;
330
+ /**
331
+ * Updates the disabled state of the control.
332
+ * @param isDisabled - Whether the component should be disabled.
333
+ */
334
+ setDisabledState(isDisabled: boolean): void;
335
+ /**
336
+ * Adds a scroll listener to the PrimeNG multiselect list container when the panel opens.
337
+ */
338
+ onPanelShow(): void;
339
+ /**
340
+ * Cleans up state, removes listeners and resets the manager when the panel closes.
341
+ */
342
+ onPanelHide(): void;
343
+ /**
344
+ * Cleans up listeners on component destruction.
345
+ */
346
+ ngOnDestroy(): void;
347
+ /**
348
+ * Safely removes the scroll event listener.
349
+ */
350
+ private removeScrollListener;
351
+ /**
352
+ * Detects if the user has reached the bottom of the list.
353
+ */
354
+ private handleScroll;
202
355
  /**
203
356
  * @method effectiveControl
204
357
  * @description
@@ -207,8 +360,8 @@ declare class MultiselectComponent implements ControlValueAccessor {
207
360
  */
208
361
  get effectiveControl(): FormControl | null;
209
362
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<MultiselectComponent, never>;
210
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<MultiselectComponent, "tk-multiselect", never, { "model": { "alias": "model"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "labelText": { "alias": "labelText"; "required": false; "isSignal": true; }; "display": { "alias": "display"; "required": false; "isSignal": true; }; "maxSelectedLabels": { "alias": "maxSelectedLabels"; "required": false; "isSignal": true; }; "selectedItemsLabel": { "alias": "selectedItemsLabel"; "required": false; "isSignal": true; }; "emptyFilterMessage": { "alias": "emptyFilterMessage"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "filterPlaceHolder": { "alias": "filterPlaceHolder"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "styleClass": { "alias": "styleClass"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; }, { "model": "modelChange"; "selectionChange": "selectionChange"; "filterChange": "filterChange"; }, never, never, true, never>;
363
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<MultiselectComponent, "tk-multiselect", never, { "model": { "alias": "model"; "required": false; "isSignal": true; }; "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "labelText": { "alias": "labelText"; "required": false; "isSignal": true; }; "display": { "alias": "display"; "required": false; "isSignal": true; }; "maxSelectedLabels": { "alias": "maxSelectedLabels"; "required": false; "isSignal": true; }; "selectedItemsLabel": { "alias": "selectedItemsLabel"; "required": false; "isSignal": true; }; "emptyFilterMessage": { "alias": "emptyFilterMessage"; "required": false; "isSignal": true; }; "filter": { "alias": "filter"; "required": false; "isSignal": true; }; "filterPlaceHolder": { "alias": "filterPlaceHolder"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "styleClass": { "alias": "styleClass"; "required": false; "isSignal": true; }; "errorMessage": { "alias": "errorMessage"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "emptyMessage": { "alias": "emptyMessage"; "required": false; "isSignal": true; }; "fetchParams": { "alias": "fetchParams"; "required": false; "isSignal": true; }; "sortField": { "alias": "sortField"; "required": false; "isSignal": true; }; "sortOrder": { "alias": "sortOrder"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, { "model": "modelChange"; "dataSource": "dataSourceChange"; "selectionChange": "selectionChange"; "filterChange": "filterChange"; }, never, never, true, never>;
211
364
  }
212
365
 
213
- export { MultiselectComponent };
214
- export type { MultiSelectOption };
366
+ export { MultiselectComponent, TkMultiSelectManager };
367
+ export type { MultiSelectDataSource, MultiSelectOption, TkMultiSelectRequest };
@@ -2,12 +2,14 @@ import * as _angular_core from '@angular/core';
2
2
  import { Table } from 'primeng/table';
3
3
  import { TagSeverity } from '@tekus/design-system/components/tag';
4
4
  import { SortEvent } from 'primeng/api';
5
+ import { TkAction } from '@tekus/design-system/components/action-group';
5
6
 
6
- type TableColumnType = 'text' | 'tag' | 'actions' | 'selection' | 'checkbox';
7
+ type TableColumnType = 'text' | 'tag' | 'actions' | 'selection' | 'checkbox' | 'action-group';
7
8
  interface TableColumn<T = unknown> {
8
9
  field?: string;
9
10
  header: string;
10
11
  sortable?: boolean;
12
+ filterable?: boolean;
11
13
  type?: TableColumnType;
12
14
  width?: string;
13
15
  tagSeverity?: (row: T) => TagSeverity;
@@ -15,6 +17,12 @@ interface TableColumn<T = unknown> {
15
17
  icon: string;
16
18
  action?: (row: T) => void;
17
19
  }>;
20
+ actionGroup?: Array<{
21
+ icon: string;
22
+ label: string;
23
+ action: (row: T) => void;
24
+ }>;
25
+ actionGroupMaxVisible?: number;
18
26
  }
19
27
 
20
28
  declare class TableComponent<T = unknown> {
@@ -77,6 +85,15 @@ declare class TableComponent<T = unknown> {
77
85
  readonly initialData: _angular_core.WritableSignal<T[]>;
78
86
  readonly internalData: _angular_core.WritableSignal<T[]>;
79
87
  readonly isSorted: _angular_core.WritableSignal<boolean | null>;
88
+ /** Tracks which column's filter overlay is currently open */
89
+ readonly activeFilterColumn: _angular_core.WritableSignal<string | null>;
90
+ /** Stores the selected filter value per column field (null = no filter) */
91
+ readonly columnFilters: _angular_core.WritableSignal<Record<string, string | null>>;
92
+ /** Position of the filter overlay (fixed, relative to viewport) */
93
+ readonly filterOverlayPosition: _angular_core.WritableSignal<{
94
+ top: number;
95
+ left: number;
96
+ }>;
80
97
  /**
81
98
  * @computed isAllSelected
82
99
  * @description
@@ -104,8 +121,76 @@ declare class TableComponent<T = unknown> {
104
121
  * @param value {any[]}
105
122
  */
106
123
  updateSelection(value: T[]): void;
124
+ private readonly actionGroupCache;
125
+ getActionGroup(actions: NonNullable<TableColumn<T>['actionGroup']>, row: T): TkAction[];
107
126
  customSort(event: SortEvent): void;
108
127
  sortTableData(event: SortEvent): void;
128
+ /**
129
+ * @method toggleFilterOverlay
130
+ * @description
131
+ * Opens or closes the filter overlay for a given column.
132
+ * Captures the trigger button position to render the overlay in fixed position.
133
+ */
134
+ toggleFilterOverlay(field: string, event: MouseEvent): void;
135
+ /**
136
+ * @method closeFilterOverlay
137
+ * @description
138
+ * Closes the filter overlay.
139
+ */
140
+ closeFilterOverlay(): void;
141
+ /**
142
+ * @method getUniqueColumnValues
143
+ * @description
144
+ * Returns the unique values for a given column, considering active filters
145
+ * on other columns. This ensures the list only shows values that exist
146
+ * in the currently filtered dataset.
147
+ */
148
+ getUniqueColumnValues(field: string): string[];
149
+ /**
150
+ * @method selectFilterValue
151
+ * @description
152
+ * Selects a value from the filter list and applies the filter.
153
+ */
154
+ selectFilterValue(field: string, value: string): void;
155
+ /**
156
+ * @method clearFilter
157
+ * @description
158
+ * Clears the filter for a specific column and re-applies remaining filters.
159
+ */
160
+ clearFilter(field: string): void;
161
+ /**
162
+ * @method isColumnFiltered
163
+ * @description
164
+ * Returns whether a column currently has an active filter.
165
+ */
166
+ isColumnFiltered(field: string): boolean;
167
+ /**
168
+ * @method getActiveFilterValue
169
+ * @description
170
+ * Returns the currently selected filter value for a column, or null.
171
+ */
172
+ getActiveFilterValue(field: string): string | null;
173
+ /**
174
+ * @method applyAllFilters
175
+ * @description
176
+ * Applies all active column filters to the initial data set.
177
+ */
178
+ private applyAllFilters;
179
+ /**
180
+ * @method getFilteredData
181
+ * @description
182
+ * Returns the initial data filtered by all active column filters.
183
+ * Used by both applyAllFilters and customSort (reset) to ensure
184
+ * sorting never discards active filters.
185
+ */
186
+ private getFilteredData;
187
+ /**
188
+ * @method cellToString
189
+ * @description
190
+ * Safely converts a cell value to its string representation.
191
+ * Handles primitives directly and avoids [object Object] for complex types.
192
+ */
193
+ private cellToString;
109
194
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<TableComponent<any>, never>;
110
195
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<TableComponent<any>, "tk-table", never, { "data": { "alias": "data"; "required": false; "isSignal": true; }; "columns": { "alias": "columns"; "required": false; "isSignal": true; }; "selectionMode": { "alias": "selectionMode"; "required": false; "isSignal": true; }; "selection": { "alias": "selection"; "required": false; "isSignal": true; }; "dataKey": { "alias": "dataKey"; "required": false; "isSignal": true; }; }, { "selection": "selectionChange"; }, never, never, true, never>;
111
196
  }