@shival99/z-ui 2.6.8 → 2.6.10

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.
Files changed (58) hide show
  1. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +1211 -0
  2. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -0
  3. package/fesm2022/shival99-z-ui-components-z-drawer.mjs +991 -0
  4. package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -0
  5. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +99 -0
  6. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -0
  7. package/fesm2022/shival99-z-ui-components-z-editor.mjs +16 -6
  8. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-filter.mjs +962 -0
  10. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -0
  11. package/fesm2022/shival99-z-ui-components-z-gallery.mjs +2 -2
  12. package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-number-ticker.mjs +352 -0
  14. package/fesm2022/shival99-z-ui-components-z-number-ticker.mjs.map +1 -0
  15. package/fesm2022/shival99-z-ui-components-z-pagination.mjs +179 -0
  16. package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -0
  17. package/fesm2022/shival99-z-ui-components-z-qrcode.mjs +429 -0
  18. package/fesm2022/shival99-z-ui-components-z-qrcode.mjs.map +1 -0
  19. package/fesm2022/shival99-z-ui-components-z-radio.mjs +183 -0
  20. package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -0
  21. package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs +137 -0
  22. package/fesm2022/shival99-z-ui-components-z-scrollarea.mjs.map +1 -0
  23. package/fesm2022/shival99-z-ui-components-z-show-more.mjs +138 -0
  24. package/fesm2022/shival99-z-ui-components-z-show-more.mjs.map +1 -0
  25. package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs +80 -0
  26. package/fesm2022/shival99-z-ui-components-z-skeleton-auto.mjs.map +1 -0
  27. package/fesm2022/shival99-z-ui-components-z-steps.mjs +420 -0
  28. package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -0
  29. package/fesm2022/shival99-z-ui-components-z-table.mjs +11424 -0
  30. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
  31. package/fesm2022/shival99-z-ui-components-z-tabs.mjs +1102 -0
  32. package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
  33. package/fesm2022/shival99-z-ui-components-z-tags.mjs +364 -0
  34. package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -0
  35. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +254 -0
  36. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
  37. package/fesm2022/shival99-z-ui-services-excel.mjs +672 -0
  38. package/fesm2022/shival99-z-ui-services-excel.mjs.map +1 -0
  39. package/package.json +1 -1
  40. package/types/shival99-z-ui-components-z-autocomplete.d.ts +301 -0
  41. package/types/shival99-z-ui-components-z-drawer.d.ts +298 -0
  42. package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +52 -0
  43. package/types/shival99-z-ui-components-z-editor.d.ts +3 -3
  44. package/types/shival99-z-ui-components-z-filter.d.ts +285 -0
  45. package/types/shival99-z-ui-components-z-modal.d.ts +1 -1
  46. package/types/shival99-z-ui-components-z-number-ticker.d.ts +110 -0
  47. package/types/shival99-z-ui-components-z-pagination.d.ts +55 -0
  48. package/types/shival99-z-ui-components-z-qrcode.d.ts +79 -0
  49. package/types/shival99-z-ui-components-z-radio.d.ts +69 -0
  50. package/types/shival99-z-ui-components-z-scrollarea.d.ts +48 -0
  51. package/types/shival99-z-ui-components-z-show-more.d.ts +36 -0
  52. package/types/shival99-z-ui-components-z-skeleton-auto.d.ts +35 -0
  53. package/types/shival99-z-ui-components-z-steps.d.ts +106 -0
  54. package/types/shival99-z-ui-components-z-table.d.ts +2386 -0
  55. package/types/shival99-z-ui-components-z-tabs.d.ts +196 -0
  56. package/types/shival99-z-ui-components-z-tags.d.ts +127 -0
  57. package/types/shival99-z-ui-components-z-timeline.d.ts +71 -0
  58. package/types/shival99-z-ui-services-excel.d.ts +36 -0
@@ -0,0 +1,962 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { Pipe, contentChild, output, input, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import * as i1 from '@angular/forms';
5
+ import { FormsModule } from '@angular/forms';
6
+ import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
7
+ import { ZCalendarComponent } from '@shival99/z-ui/components/z-calendar';
8
+ import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
9
+ import { ZPopoverDirective } from '@shival99/z-ui/components/z-popover';
10
+ import { ZSwitchComponent } from '@shival99/z-ui/components/z-switch';
11
+ import { zMergeClasses } from '@shival99/z-ui/utils';
12
+ import { cva } from 'class-variance-authority';
13
+
14
+ function generateFilterId() {
15
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
16
+ }
17
+ function createFilter(field, operator = 'is', values = []) {
18
+ return {
19
+ id: generateFilterId(),
20
+ field,
21
+ operator,
22
+ values,
23
+ };
24
+ }
25
+ function isFieldGroup(item) {
26
+ return 'fields' in item && Array.isArray(item.fields);
27
+ }
28
+ function isGroupLevelField(field) {
29
+ return Boolean(field.group && field.fields);
30
+ }
31
+ function flattenFields(fields) {
32
+ return fields.reduce((acc, item) => {
33
+ if (isFieldGroup(item)) {
34
+ return [...acc, ...item.fields];
35
+ }
36
+ if (isGroupLevelField(item) && item.fields) {
37
+ return [...acc, ...item.fields];
38
+ }
39
+ return [...acc, item];
40
+ }, []);
41
+ }
42
+ function getFieldsMap(fields) {
43
+ const flatFields = flattenFields(fields);
44
+ return flatFields.reduce((acc, field) => {
45
+ if (field.key) {
46
+ acc[field.key] = field;
47
+ }
48
+ return acc;
49
+ }, {});
50
+ }
51
+ function createOperatorsFromI18n(i18n) {
52
+ return {
53
+ select: [
54
+ { value: 'is', label: i18n.operators.is },
55
+ { value: 'is_not', label: i18n.operators.isNot },
56
+ { value: 'empty', label: i18n.operators.empty },
57
+ { value: 'not_empty', label: i18n.operators.notEmpty },
58
+ ],
59
+ multiselect: [
60
+ { value: 'is_any_of', label: i18n.operators.isAnyOf },
61
+ { value: 'is_not_any_of', label: i18n.operators.isNotAnyOf },
62
+ { value: 'includes_all', label: i18n.operators.includesAll },
63
+ { value: 'excludes_all', label: i18n.operators.excludesAll },
64
+ { value: 'empty', label: i18n.operators.empty },
65
+ { value: 'not_empty', label: i18n.operators.notEmpty },
66
+ ],
67
+ date: [
68
+ { value: 'before', label: i18n.operators.before },
69
+ { value: 'after', label: i18n.operators.after },
70
+ { value: 'is', label: i18n.operators.is },
71
+ { value: 'is_not', label: i18n.operators.isNot },
72
+ { value: 'empty', label: i18n.operators.empty },
73
+ { value: 'not_empty', label: i18n.operators.notEmpty },
74
+ ],
75
+ daterange: [
76
+ { value: 'between', label: i18n.operators.between },
77
+ { value: 'not_between', label: i18n.operators.notBetween },
78
+ { value: 'empty', label: i18n.operators.empty },
79
+ { value: 'not_empty', label: i18n.operators.notEmpty },
80
+ ],
81
+ text: [
82
+ { value: 'contains', label: i18n.operators.contains },
83
+ { value: 'not_contains', label: i18n.operators.notContains },
84
+ { value: 'starts_with', label: i18n.operators.startsWith },
85
+ { value: 'ends_with', label: i18n.operators.endsWith },
86
+ { value: 'is', label: i18n.operators.isExactly },
87
+ { value: 'empty', label: i18n.operators.empty },
88
+ { value: 'not_empty', label: i18n.operators.notEmpty },
89
+ ],
90
+ number: [
91
+ { value: 'equals', label: i18n.operators.equals },
92
+ { value: 'not_equals', label: i18n.operators.notEquals },
93
+ { value: 'greater_than', label: i18n.operators.greaterThan },
94
+ { value: 'less_than', label: i18n.operators.lessThan },
95
+ { value: 'between', label: i18n.operators.between },
96
+ { value: 'empty', label: i18n.operators.empty },
97
+ { value: 'not_empty', label: i18n.operators.notEmpty },
98
+ ],
99
+ numberrange: [
100
+ { value: 'between', label: i18n.operators.between },
101
+ { value: 'overlaps', label: i18n.operators.overlaps },
102
+ { value: 'contains', label: i18n.operators.contains },
103
+ { value: 'empty', label: i18n.operators.empty },
104
+ { value: 'not_empty', label: i18n.operators.notEmpty },
105
+ ],
106
+ boolean: [
107
+ { value: 'is', label: i18n.operators.is },
108
+ { value: 'is_not', label: i18n.operators.isNot },
109
+ { value: 'empty', label: i18n.operators.empty },
110
+ { value: 'not_empty', label: i18n.operators.notEmpty },
111
+ ],
112
+ email: [
113
+ { value: 'contains', label: i18n.operators.contains },
114
+ { value: 'not_contains', label: i18n.operators.notContains },
115
+ { value: 'starts_with', label: i18n.operators.startsWith },
116
+ { value: 'ends_with', label: i18n.operators.endsWith },
117
+ { value: 'is', label: i18n.operators.isExactly },
118
+ { value: 'empty', label: i18n.operators.empty },
119
+ { value: 'not_empty', label: i18n.operators.notEmpty },
120
+ ],
121
+ url: [
122
+ { value: 'contains', label: i18n.operators.contains },
123
+ { value: 'not_contains', label: i18n.operators.notContains },
124
+ { value: 'starts_with', label: i18n.operators.startsWith },
125
+ { value: 'ends_with', label: i18n.operators.endsWith },
126
+ { value: 'is', label: i18n.operators.isExactly },
127
+ { value: 'empty', label: i18n.operators.empty },
128
+ { value: 'not_empty', label: i18n.operators.notEmpty },
129
+ ],
130
+ tel: [
131
+ { value: 'contains', label: i18n.operators.contains },
132
+ { value: 'not_contains', label: i18n.operators.notContains },
133
+ { value: 'starts_with', label: i18n.operators.startsWith },
134
+ { value: 'ends_with', label: i18n.operators.endsWith },
135
+ { value: 'is', label: i18n.operators.isExactly },
136
+ { value: 'empty', label: i18n.operators.empty },
137
+ { value: 'not_empty', label: i18n.operators.notEmpty },
138
+ ],
139
+ time: [
140
+ { value: 'before', label: i18n.operators.before },
141
+ { value: 'after', label: i18n.operators.after },
142
+ { value: 'is', label: i18n.operators.is },
143
+ { value: 'between', label: i18n.operators.between },
144
+ { value: 'empty', label: i18n.operators.empty },
145
+ { value: 'not_empty', label: i18n.operators.notEmpty },
146
+ ],
147
+ datetime: [
148
+ { value: 'before', label: i18n.operators.before },
149
+ { value: 'after', label: i18n.operators.after },
150
+ { value: 'is', label: i18n.operators.is },
151
+ { value: 'between', label: i18n.operators.between },
152
+ { value: 'empty', label: i18n.operators.empty },
153
+ { value: 'not_empty', label: i18n.operators.notEmpty },
154
+ ],
155
+ };
156
+ }
157
+ function getOperatorsForField(field, values, i18n) {
158
+ if (field.operators) {
159
+ return field.operators;
160
+ }
161
+ const operators = createOperatorsFromI18n(i18n);
162
+ let fieldType = field.type || 'select';
163
+ if (fieldType === 'select' && values.length > 1) {
164
+ fieldType = 'multiselect';
165
+ }
166
+ if (fieldType === 'multiselect' || field.type === 'multiselect') {
167
+ return operators['multiselect'];
168
+ }
169
+ return operators[fieldType] || operators['select'];
170
+ }
171
+ function formatOperator(operator) {
172
+ return operator.replace(/_/g, ' ');
173
+ }
174
+ function getDefaultOperator(fieldType) {
175
+ switch (fieldType) {
176
+ case 'daterange':
177
+ case 'numberrange':
178
+ return 'between';
179
+ case 'boolean':
180
+ return 'is';
181
+ case 'multiselect':
182
+ return 'is_any_of';
183
+ default:
184
+ return 'is';
185
+ }
186
+ }
187
+ function getDefaultValues(fieldType, field) {
188
+ switch (fieldType) {
189
+ case 'text':
190
+ case 'number':
191
+ case 'date':
192
+ case 'email':
193
+ case 'url':
194
+ case 'tel':
195
+ case 'time':
196
+ case 'datetime':
197
+ return [''];
198
+ case 'daterange':
199
+ return ['', ''];
200
+ case 'numberrange':
201
+ return [field.min || 0, field.max || 100];
202
+ case 'boolean':
203
+ return [false];
204
+ default:
205
+ return [];
206
+ }
207
+ }
208
+ function getInputPattern(fieldType) {
209
+ switch (fieldType) {
210
+ case 'email':
211
+ return '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$';
212
+ case 'url':
213
+ return '^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$';
214
+ case 'tel':
215
+ return '^[\\+]?[1-9][\\d]{0,15}$';
216
+ default:
217
+ return undefined;
218
+ }
219
+ }
220
+
221
+ class ZFilterFieldPipe {
222
+ transform(filter, fields) {
223
+ const fieldsMap = getFieldsMap(fields);
224
+ return fieldsMap[filter.field];
225
+ }
226
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterFieldPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
227
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterFieldPipe, isStandalone: true, name: "zFilterField" });
228
+ }
229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterFieldPipe, decorators: [{
230
+ type: Pipe,
231
+ args: [{
232
+ name: 'zFilterField',
233
+ standalone: true,
234
+ pure: true,
235
+ }]
236
+ }] });
237
+
238
+ class ZFilterInputPatternPipe {
239
+ transform(field) {
240
+ switch (field.type) {
241
+ case 'email':
242
+ return '[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$';
243
+ case 'url':
244
+ return 'https?://.+';
245
+ case 'tel':
246
+ return '[0-9+\\-\\s()]+';
247
+ default:
248
+ return field.pattern || '';
249
+ }
250
+ }
251
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterInputPatternPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
252
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterInputPatternPipe, isStandalone: true, name: "zFilterInputPattern" });
253
+ }
254
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterInputPatternPipe, decorators: [{
255
+ type: Pipe,
256
+ args: [{
257
+ name: 'zFilterInputPattern',
258
+ standalone: true,
259
+ pure: true,
260
+ }]
261
+ }] });
262
+
263
+ class ZFilterIsBetweenOperatorPipe {
264
+ transform(filter) {
265
+ return filter.operator === 'between' || filter.operator === 'not_between';
266
+ }
267
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
268
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, isStandalone: true, name: "zFilterIsBetweenOperator" });
269
+ }
270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, decorators: [{
271
+ type: Pipe,
272
+ args: [{
273
+ name: 'zFilterIsBetweenOperator',
274
+ standalone: true,
275
+ pure: true,
276
+ }]
277
+ }] });
278
+
279
+ class ZFilterIsValueHiddenPipe {
280
+ transform(filter) {
281
+ const { operator } = filter;
282
+ return operator === 'is_empty' || operator === 'is_not_empty';
283
+ }
284
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
285
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, isStandalone: true, name: "zFilterIsValueHidden" });
286
+ }
287
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, decorators: [{
288
+ type: Pipe,
289
+ args: [{
290
+ name: 'zFilterIsValueHidden',
291
+ standalone: true,
292
+ pure: true,
293
+ }]
294
+ }] });
295
+
296
+ class ZFilterOperatorLabelPipe {
297
+ transform(filter, fields, i18n) {
298
+ const fieldsMap = getFieldsMap(fields);
299
+ const field = fieldsMap[filter.field];
300
+ if (!field) {
301
+ return '';
302
+ }
303
+ const operators = getOperatorsForField(field, filter.values, i18n);
304
+ const op = operators.find(o => o.value === filter.operator);
305
+ return op?.label || formatOperator(filter.operator);
306
+ }
307
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
308
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorLabelPipe, isStandalone: true, name: "zFilterOperatorLabel" });
309
+ }
310
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorLabelPipe, decorators: [{
311
+ type: Pipe,
312
+ args: [{
313
+ name: 'zFilterOperatorLabel',
314
+ standalone: true,
315
+ pure: true,
316
+ }]
317
+ }] });
318
+
319
+ class ZFilterOperatorsPipe {
320
+ transform(filter, fields, i18n) {
321
+ const fieldsMap = getFieldsMap(fields);
322
+ const field = fieldsMap[filter.field];
323
+ if (!field) {
324
+ return [];
325
+ }
326
+ return getOperatorsForField(field, filter.values, i18n);
327
+ }
328
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
329
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorsPipe, isStandalone: true, name: "zFilterOperators" });
330
+ }
331
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterOperatorsPipe, decorators: [{
332
+ type: Pipe,
333
+ args: [{
334
+ name: 'zFilterOperators',
335
+ standalone: true,
336
+ pure: true,
337
+ }]
338
+ }] });
339
+
340
+ class ZFilterSelectedOptionsPipe {
341
+ transform(filter, fields) {
342
+ const fieldsMap = getFieldsMap(fields);
343
+ const field = fieldsMap[filter.field];
344
+ if (!field?.options) {
345
+ return [];
346
+ }
347
+ return field.options.filter(opt => filter.values.includes(opt.value));
348
+ }
349
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
350
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, isStandalone: true, name: "zFilterSelectedOptions" });
351
+ }
352
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, decorators: [{
353
+ type: Pipe,
354
+ args: [{
355
+ name: 'zFilterSelectedOptions',
356
+ standalone: true,
357
+ pure: true,
358
+ }]
359
+ }] });
360
+
361
+ class ZFilterUnselectedOptionsPipe {
362
+ transform(filter, fields) {
363
+ const fieldsMap = getFieldsMap(fields);
364
+ const field = fieldsMap[filter.field];
365
+ if (!field?.options) {
366
+ return [];
367
+ }
368
+ return field.options.filter(opt => !filter.values.includes(opt.value));
369
+ }
370
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
371
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.1.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, isStandalone: true, name: "zFilterUnselectedOptions" });
372
+ }
373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, decorators: [{
374
+ type: Pipe,
375
+ args: [{
376
+ name: 'zFilterUnselectedOptions',
377
+ standalone: true,
378
+ pure: true,
379
+ }]
380
+ }] });
381
+
382
+ const Z_FILTER_PIPES = [
383
+ ZFilterFieldPipe,
384
+ ZFilterOperatorLabelPipe,
385
+ ZFilterOperatorsPipe,
386
+ ZFilterSelectedOptionsPipe,
387
+ ZFilterUnselectedOptionsPipe,
388
+ ZFilterInputPatternPipe,
389
+ ZFilterIsValueHiddenPipe,
390
+ ZFilterIsBetweenOperatorPipe,
391
+ ];
392
+
393
+ const DEFAULT_FILTER_I18N = {
394
+ addFilter: 'Add filter',
395
+ searchFields: 'Search fields...',
396
+ noFieldsFound: 'No fields found.',
397
+ noResultsFound: 'No results found.',
398
+ select: 'Select...',
399
+ true: 'True',
400
+ false: 'False',
401
+ min: 'Min',
402
+ max: 'Max',
403
+ to: 'to',
404
+ selected: 'selected',
405
+ selectedCount: 'selected',
406
+ addFilterTitle: 'Add filter',
407
+ operators: {
408
+ is: 'is',
409
+ isNot: 'is not',
410
+ isAnyOf: 'is any of',
411
+ isNotAnyOf: 'is not any of',
412
+ includesAll: 'includes all',
413
+ excludesAll: 'excludes all',
414
+ before: 'before',
415
+ after: 'after',
416
+ between: 'between',
417
+ notBetween: 'not between',
418
+ contains: 'contains',
419
+ notContains: 'does not contain',
420
+ startsWith: 'starts with',
421
+ endsWith: 'ends with',
422
+ isExactly: 'is exactly',
423
+ equals: 'equals',
424
+ notEquals: 'not equals',
425
+ greaterThan: 'greater than',
426
+ lessThan: 'less than',
427
+ overlaps: 'overlaps',
428
+ includes: 'includes',
429
+ excludes: 'excludes',
430
+ includesAllOf: 'includes all of',
431
+ includesAnyOf: 'includes any of',
432
+ empty: 'is empty',
433
+ notEmpty: 'is not empty',
434
+ },
435
+ placeholders: {
436
+ enterField: 'Enter value...',
437
+ selectField: 'Select...',
438
+ searchField: 'Search...',
439
+ enterKey: 'Enter key...',
440
+ enterValue: 'Enter value...',
441
+ },
442
+ validation: {
443
+ invalidEmail: 'Invalid email format',
444
+ invalidUrl: 'Invalid URL format',
445
+ invalidTel: 'Invalid phone format',
446
+ invalid: 'Invalid input format',
447
+ },
448
+ };
449
+
450
+ const zFilterContainerVariants = cva('flex flex-wrap items-center gap-2', {
451
+ variants: {
452
+ size: {
453
+ sm: 'gap-1.5',
454
+ md: 'gap-2',
455
+ lg: 'gap-2.5',
456
+ },
457
+ },
458
+ defaultVariants: {
459
+ size: 'md',
460
+ },
461
+ });
462
+ const zFilterItemVariants = cva('inline-flex items-stretch rounded-sm border border-input bg-background shadow-xs overflow-hidden', {
463
+ variants: {
464
+ size: {
465
+ sm: 'h-8',
466
+ md: 'h-9',
467
+ lg: 'h-10',
468
+ },
469
+ },
470
+ defaultVariants: {
471
+ size: 'md',
472
+ },
473
+ });
474
+ const zFilterFieldLabelVariants = cva('flex items-center gap-1.5 bg-background font-medium text-muted-foreground border-r border-input', {
475
+ variants: {
476
+ size: {
477
+ sm: 'px-2 text-xs',
478
+ md: 'px-2.5 text-sm',
479
+ lg: 'px-3 text-sm',
480
+ },
481
+ },
482
+ defaultVariants: {
483
+ size: 'md',
484
+ },
485
+ });
486
+ const zFilterInputVariants = cva('flex items-center bg-background px-2 focus-within:bg-muted/50', {
487
+ variants: {
488
+ size: {
489
+ sm: 'text-xs',
490
+ md: 'text-sm',
491
+ lg: 'text-sm',
492
+ },
493
+ },
494
+ defaultVariants: {
495
+ size: 'md',
496
+ },
497
+ });
498
+ const zFilterRemoveButtonVariants = cva('flex items-center justify-center cursor-pointer bg-background text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive focus:outline-none border-l border-input', {
499
+ variants: {
500
+ size: {
501
+ sm: 'px-1.5',
502
+ md: 'px-2',
503
+ lg: 'px-2.5',
504
+ },
505
+ },
506
+ defaultVariants: {
507
+ size: 'md',
508
+ },
509
+ });
510
+ const zFilterBetweenVariants = cva('text-muted-foreground flex items-center', {
511
+ variants: {
512
+ size: {
513
+ sm: 'px-1 text-xs',
514
+ md: 'px-1.5 text-xs',
515
+ lg: 'px-2 text-sm',
516
+ },
517
+ },
518
+ defaultVariants: {
519
+ size: 'md',
520
+ },
521
+ });
522
+
523
+ class ZFilterComponent {
524
+ addButtonTemplate = contentChild('addButton', /* @ts-ignore */
525
+ ...(ngDevMode ? [{ debugName: "addButtonTemplate" }] : /* istanbul ignore next */ []));
526
+ zFiltersChange = output();
527
+ zFilterAdd = output();
528
+ zFilterRemove = output();
529
+ zFilterUpdate = output();
530
+ class = input('', /* @ts-ignore */
531
+ ...(ngDevMode ? [{ debugName: "class" }] : /* istanbul ignore next */ []));
532
+ zFilters = input.required(/* @ts-ignore */
533
+ ...(ngDevMode ? [{ debugName: "zFilters" }] : /* istanbul ignore next */ []));
534
+ zFields = input.required(/* @ts-ignore */
535
+ ...(ngDevMode ? [{ debugName: "zFields" }] : /* istanbul ignore next */ []));
536
+ zSize = input('md', /* @ts-ignore */
537
+ ...(ngDevMode ? [{ debugName: "zSize" }] : /* istanbul ignore next */ []));
538
+ zI18n = input({}, /* @ts-ignore */
539
+ ...(ngDevMode ? [{ debugName: "zI18n" }] : /* istanbul ignore next */ []));
540
+ zShowAddButton = input(true, /* @ts-ignore */
541
+ ...(ngDevMode ? [{ debugName: "zShowAddButton" }] : /* istanbul ignore next */ []));
542
+ zAllowMultiple = input(true, /* @ts-ignore */
543
+ ...(ngDevMode ? [{ debugName: "zAllowMultiple" }] : /* istanbul ignore next */ []));
544
+ zAddButtonIcon = input('lucidePlus', /* @ts-ignore */
545
+ ...(ngDevMode ? [{ debugName: "zAddButtonIcon" }] : /* istanbul ignore next */ []));
546
+ zAddButtonText = input(/* @ts-ignore */
547
+ ...(ngDevMode ? [undefined, { debugName: "zAddButtonText" }] : /* istanbul ignore next */ []));
548
+ addFilterOpen = signal(false, /* @ts-ignore */
549
+ ...(ngDevMode ? [{ debugName: "addFilterOpen" }] : /* istanbul ignore next */ []));
550
+ searchQuery = signal('', /* @ts-ignore */
551
+ ...(ngDevMode ? [{ debugName: "searchQuery" }] : /* istanbul ignore next */ []));
552
+ operatorPopoverOpen = signal(null, /* @ts-ignore */
553
+ ...(ngDevMode ? [{ debugName: "operatorPopoverOpen" }] : /* istanbul ignore next */ []));
554
+ valuePopoverOpen = signal(null, /* @ts-ignore */
555
+ ...(ngDevMode ? [{ debugName: "valuePopoverOpen" }] : /* istanbul ignore next */ []));
556
+ addFilterSearchInput = viewChild('addFilterSearchInput', /* @ts-ignore */
557
+ ...(ngDevMode ? [{ debugName: "addFilterSearchInput" }] : /* istanbul ignore next */ []));
558
+ focusSearchInput() {
559
+ setTimeout(() => {
560
+ this.addFilterSearchInput()?.nativeElement?.focus();
561
+ }, 50);
562
+ }
563
+ focusSelectSearch(filterId) {
564
+ setTimeout(() => {
565
+ const input = document.getElementById(`select-search-${filterId}`);
566
+ input?.focus();
567
+ }, 50);
568
+ }
569
+ i18n = computed(() => {
570
+ const custom = this.zI18n();
571
+ return {
572
+ ...DEFAULT_FILTER_I18N,
573
+ ...custom,
574
+ operators: { ...DEFAULT_FILTER_I18N.operators, ...custom.operators },
575
+ placeholders: { ...DEFAULT_FILTER_I18N.placeholders, ...custom.placeholders },
576
+ validation: { ...DEFAULT_FILTER_I18N.validation, ...custom.validation },
577
+ };
578
+ }, /* @ts-ignore */
579
+ ...(ngDevMode ? [{ debugName: "i18n" }] : /* istanbul ignore next */ []));
580
+ fieldsMap = computed(() => getFieldsMap(this.zFields()), /* @ts-ignore */
581
+ ...(ngDevMode ? [{ debugName: "fieldsMap" }] : /* istanbul ignore next */ []));
582
+ selectableFields = computed(() => {
583
+ const flatFields = flattenFields(this.zFields());
584
+ const filters = this.zFilters();
585
+ return flatFields.filter(field => {
586
+ if (!field.key || field.type === 'separator') {
587
+ return false;
588
+ }
589
+ if (this.zAllowMultiple()) {
590
+ return true;
591
+ }
592
+ return !filters.some(filter => filter.field === field.key);
593
+ });
594
+ }, /* @ts-ignore */
595
+ ...(ngDevMode ? [{ debugName: "selectableFields" }] : /* istanbul ignore next */ []));
596
+ filteredFields = computed(() => {
597
+ const query = this.searchQuery().toLowerCase().trim();
598
+ if (!query) {
599
+ return this.selectableFields();
600
+ }
601
+ return this.selectableFields().filter(field => field.label?.toLowerCase().includes(query) || field.key?.toLowerCase().includes(query));
602
+ }, /* @ts-ignore */
603
+ ...(ngDevMode ? [{ debugName: "filteredFields" }] : /* istanbul ignore next */ []));
604
+ groupedFields = computed(() => {
605
+ const allFields = this.zFields();
606
+ const query = this.searchQuery().toLowerCase().trim();
607
+ const filters = this.zFilters();
608
+ const allowMultiple = this.zAllowMultiple();
609
+ const filterField = (field) => {
610
+ if (!field.key || field.type === 'separator') {
611
+ return false;
612
+ }
613
+ if (!allowMultiple && filters.some(f => f.field === field.key)) {
614
+ return false;
615
+ }
616
+ if (query && !field.label?.toLowerCase().includes(query) && !field.key?.toLowerCase().includes(query)) {
617
+ return false;
618
+ }
619
+ return true;
620
+ };
621
+ const groups = [];
622
+ for (const item of allFields) {
623
+ if ('fields' in item && Array.isArray(item.fields)) {
624
+ const groupName = item.group || '';
625
+ const filteredGroupFields = item.fields.filter(filterField);
626
+ if (filteredGroupFields.length > 0) {
627
+ groups.push({ group: groupName, fields: filteredGroupFields });
628
+ }
629
+ continue;
630
+ }
631
+ const field = item;
632
+ if (!filterField(field)) {
633
+ continue;
634
+ }
635
+ const groupName = field.group || '';
636
+ const existingGroup = groups.find(g => g.group === groupName);
637
+ if (existingGroup) {
638
+ existingGroup.fields.push(field);
639
+ continue;
640
+ }
641
+ groups.push({ group: groupName, fields: [field] });
642
+ }
643
+ return groups;
644
+ }, /* @ts-ignore */
645
+ ...(ngDevMode ? [{ debugName: "groupedFields" }] : /* istanbul ignore next */ []));
646
+ buttonSize = computed(() => {
647
+ const size = this.zSize();
648
+ if (size === 'sm') {
649
+ return 'sm';
650
+ }
651
+ if (size === 'lg') {
652
+ return 'lg';
653
+ }
654
+ return 'default';
655
+ }, /* @ts-ignore */
656
+ ...(ngDevMode ? [{ debugName: "buttonSize" }] : /* istanbul ignore next */ []));
657
+ calendarSize = computed(() => {
658
+ const size = this.zSize();
659
+ if (size === 'sm') {
660
+ return 'sm';
661
+ }
662
+ if (size === 'lg') {
663
+ return 'lg';
664
+ }
665
+ return 'default';
666
+ }, /* @ts-ignore */
667
+ ...(ngDevMode ? [{ debugName: "calendarSize" }] : /* istanbul ignore next */ []));
668
+ dateValueMap = computed(() => {
669
+ const map = {};
670
+ for (const filter of this.zFilters()) {
671
+ map[filter.id] = this._parseDateValue(filter.values[0]);
672
+ }
673
+ return map;
674
+ }, /* @ts-ignore */
675
+ ...(ngDevMode ? [{ debugName: "dateValueMap" }] : /* istanbul ignore next */ []));
676
+ dateRangeValueMap = computed(() => {
677
+ const map = {};
678
+ for (const filter of this.zFilters()) {
679
+ const start = this._parseDateValue(filter.values[0]);
680
+ const end = this._parseDateValue(filter.values[1]);
681
+ map[filter.id] = start || end ? { start, end } : null;
682
+ }
683
+ return map;
684
+ }, /* @ts-ignore */
685
+ ...(ngDevMode ? [{ debugName: "dateRangeValueMap" }] : /* istanbul ignore next */ []));
686
+ timeValueMap = computed(() => {
687
+ const map = {};
688
+ for (const filter of this.zFilters()) {
689
+ map[filter.id] = this._parseTimeValue(filter.values[0]);
690
+ }
691
+ return map;
692
+ }, /* @ts-ignore */
693
+ ...(ngDevMode ? [{ debugName: "timeValueMap" }] : /* istanbul ignore next */ []));
694
+ dateTimeValueMap = computed(() => {
695
+ const map = {};
696
+ for (const filter of this.zFilters()) {
697
+ map[filter.id] = this._parseDateTimeValue(filter.values[0]);
698
+ }
699
+ return map;
700
+ }, /* @ts-ignore */
701
+ ...(ngDevMode ? [{ debugName: "dateTimeValueMap" }] : /* istanbul ignore next */ []));
702
+ hostClasses = computed(() => zMergeClasses(zFilterContainerVariants({ size: this.zSize() }), this.class()), /* @ts-ignore */
703
+ ...(ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []));
704
+ getItemClasses() {
705
+ return zFilterItemVariants({ size: this.zSize() });
706
+ }
707
+ getLabelClasses() {
708
+ return zFilterFieldLabelVariants({ size: this.zSize() });
709
+ }
710
+ getInputClasses() {
711
+ return zFilterInputVariants({ size: this.zSize() });
712
+ }
713
+ getRemoveButtonClasses() {
714
+ return zFilterRemoveButtonVariants({ size: this.zSize() });
715
+ }
716
+ getBetweenClasses() {
717
+ return zFilterBetweenVariants({ size: this.zSize() });
718
+ }
719
+ getFieldForFilter(filter) {
720
+ return this.fieldsMap()[filter.field];
721
+ }
722
+ getOperatorsForFilter(filter) {
723
+ const field = this.getFieldForFilter(filter);
724
+ if (!field) {
725
+ return [];
726
+ }
727
+ return getOperatorsForField(field, filter.values, this.i18n());
728
+ }
729
+ getOperatorLabel(filter) {
730
+ const operators = this.getOperatorsForFilter(filter);
731
+ const op = operators.find(o => o.value === filter.operator);
732
+ return op?.label || formatOperator(filter.operator);
733
+ }
734
+ getSelectedOptions(filter) {
735
+ const field = this.getFieldForFilter(filter);
736
+ if (!field?.options) {
737
+ return [];
738
+ }
739
+ return field.options.filter(opt => filter.values.includes(opt.value));
740
+ }
741
+ getUnselectedOptions(filter) {
742
+ const field = this.getFieldForFilter(filter);
743
+ if (!field?.options) {
744
+ return [];
745
+ }
746
+ return field.options.filter(opt => !filter.values.includes(opt.value));
747
+ }
748
+ isValueHidden(filter) {
749
+ return filter.operator === 'empty' || filter.operator === 'not_empty';
750
+ }
751
+ isBetweenOperator(filter) {
752
+ return filter.operator === 'between';
753
+ }
754
+ getInputPattern(field) {
755
+ return field.pattern || getInputPattern(field.type || '');
756
+ }
757
+ onFieldSelect(field) {
758
+ if (!field.key) {
759
+ return;
760
+ }
761
+ const defaultOperator = field.defaultOperator || getDefaultOperator(field.type || 'select');
762
+ const defaultValues = getDefaultValues(field.type || 'select', field);
763
+ const newFilter = createFilter(field.key, defaultOperator, defaultValues);
764
+ const newFilters = [...this.zFilters(), newFilter];
765
+ this.zFiltersChange.emit(newFilters);
766
+ this.zFilterAdd.emit(newFilter);
767
+ this.addFilterOpen.set(false);
768
+ this.searchQuery.set('');
769
+ }
770
+ updateFilterOperator(filter, operator) {
771
+ const updates = { operator };
772
+ if (operator === 'empty' || operator === 'not_empty') {
773
+ updates.values = [];
774
+ }
775
+ const updatedFilters = this.zFilters().map(f => {
776
+ if (f.id === filter.id) {
777
+ return { ...f, ...updates };
778
+ }
779
+ return f;
780
+ });
781
+ this.zFiltersChange.emit(updatedFilters);
782
+ this.zFilterUpdate.emit({ filter, updates });
783
+ this.operatorPopoverOpen.set(null);
784
+ }
785
+ onSelectValueChange(filter, option) {
786
+ const field = this.getFieldForFilter(filter);
787
+ const isSelected = filter.values.includes(option.value);
788
+ const valueMulti = isSelected ? filter.values.filter(v => v !== option.value) : [...filter.values, option.value];
789
+ const valueSingle = isSelected ? [] : [option.value];
790
+ const newValues = (field?.type === 'multiselect' ? valueMulti : valueSingle);
791
+ const updatedFilters = this.zFilters().map(f => {
792
+ if (f.id === filter.id) {
793
+ return { ...f, values: newValues };
794
+ }
795
+ return f;
796
+ });
797
+ this.zFiltersChange.emit(updatedFilters);
798
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
799
+ }
800
+ onDateValueChange(filter, value) {
801
+ const formattedValue = this._formatDateValue(value);
802
+ const nextValues = [formattedValue];
803
+ this._updateFilterValues(filter, nextValues);
804
+ }
805
+ onDateRangeValueChange(filter, value) {
806
+ const start = this._formatDateValue(value?.start ?? null);
807
+ const end = this._formatDateValue(value?.end ?? null);
808
+ const nextValues = [start, end];
809
+ this._updateFilterValues(filter, nextValues);
810
+ }
811
+ onTimeValueChange(filter, value) {
812
+ const formattedValue = this._formatTimeValue(value);
813
+ const nextValues = [formattedValue];
814
+ this._updateFilterValues(filter, nextValues);
815
+ }
816
+ onDateTimeValueChange(filter, value) {
817
+ const formattedValue = this._formatDateTimeValue(value);
818
+ const nextValues = [formattedValue];
819
+ this._updateFilterValues(filter, nextValues);
820
+ }
821
+ removeFilter(filter) {
822
+ const updatedFilters = this.zFilters().filter(f => f.id !== filter.id);
823
+ this.zFiltersChange.emit(updatedFilters);
824
+ this.zFilterRemove.emit(filter);
825
+ }
826
+ onInputChange(filter, event, index = 0) {
827
+ const input = event.target;
828
+ const newValues = [...filter.values];
829
+ newValues[index] = input.value;
830
+ const updatedFilters = this.zFilters().map(f => {
831
+ if (f.id === filter.id) {
832
+ return { ...f, values: newValues };
833
+ }
834
+ return f;
835
+ });
836
+ this.zFiltersChange.emit(updatedFilters);
837
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
838
+ }
839
+ onBooleanChange(filter, checked) {
840
+ const newValues = [checked];
841
+ const updatedFilters = this.zFilters().map(f => {
842
+ if (f.id === filter.id) {
843
+ return { ...f, values: newValues };
844
+ }
845
+ return f;
846
+ });
847
+ this.zFiltersChange.emit(updatedFilters);
848
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
849
+ }
850
+ onSearchInput(event) {
851
+ const input = event.target;
852
+ this.searchQuery.set(input.value);
853
+ }
854
+ trackByFilterId(index, filter) {
855
+ return filter.id;
856
+ }
857
+ trackByOptionValue(index, option) {
858
+ return option.value;
859
+ }
860
+ trackByFieldKey(index, field) {
861
+ return field.key || `field-${index}`;
862
+ }
863
+ _updateFilterValues(filter, values) {
864
+ const updatedFilters = this.zFilters().map(f => {
865
+ if (f.id === filter.id) {
866
+ return { ...f, values };
867
+ }
868
+ return f;
869
+ });
870
+ this.zFiltersChange.emit(updatedFilters);
871
+ this.zFilterUpdate.emit({ filter, updates: { values } });
872
+ }
873
+ _parseDateValue(value) {
874
+ if (typeof value !== 'string' || !value) {
875
+ return null;
876
+ }
877
+ const [year, month, day] = value.split('-').map(Number);
878
+ if (!year || !month || !day) {
879
+ return null;
880
+ }
881
+ const parsedDate = new Date(year, month - 1, day);
882
+ if (Number.isNaN(parsedDate.getTime())) {
883
+ return null;
884
+ }
885
+ return parsedDate;
886
+ }
887
+ _formatDateValue(value) {
888
+ if (!value) {
889
+ return '';
890
+ }
891
+ const year = value.getFullYear();
892
+ const month = String(value.getMonth() + 1).padStart(2, '0');
893
+ const day = String(value.getDate()).padStart(2, '0');
894
+ return `${year}-${month}-${day}`;
895
+ }
896
+ _parseTimeValue(value) {
897
+ if (typeof value !== 'string' || !value) {
898
+ return null;
899
+ }
900
+ const [hours, minutes] = value.split(':').map(Number);
901
+ if (hours == null || minutes == null || Number.isNaN(hours) || Number.isNaN(minutes)) {
902
+ return null;
903
+ }
904
+ const date = new Date();
905
+ date.setHours(hours, minutes, 0, 0);
906
+ return date;
907
+ }
908
+ _parseDateTimeValue(value) {
909
+ if (typeof value !== 'string' || !value) {
910
+ return null;
911
+ }
912
+ const parsed = new Date(value);
913
+ if (Number.isNaN(parsed.getTime())) {
914
+ return null;
915
+ }
916
+ return parsed;
917
+ }
918
+ _formatTimeValue(value) {
919
+ if (!value) {
920
+ return '';
921
+ }
922
+ const hours = String(value.getHours()).padStart(2, '0');
923
+ const minutes = String(value.getMinutes()).padStart(2, '0');
924
+ return `${hours}:${minutes}`;
925
+ }
926
+ _formatDateTimeValue(value) {
927
+ if (!value) {
928
+ return '';
929
+ }
930
+ const year = value.getFullYear();
931
+ const month = String(value.getMonth() + 1).padStart(2, '0');
932
+ const day = String(value.getDate()).padStart(2, '0');
933
+ const hours = String(value.getHours()).padStart(2, '0');
934
+ const minutes = String(value.getMinutes()).padStart(2, '0');
935
+ return `${year}-${month}-${day}T${hours}:${minutes}`;
936
+ }
937
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
938
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: ZFilterComponent, isStandalone: true, selector: "z-filter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zFilters: { classPropertyName: "zFilters", publicName: "zFilters", isSignal: true, isRequired: true, transformFunction: null }, zFields: { classPropertyName: "zFields", publicName: "zFields", isSignal: true, isRequired: true, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zI18n: { classPropertyName: "zI18n", publicName: "zI18n", isSignal: true, isRequired: false, transformFunction: null }, zShowAddButton: { classPropertyName: "zShowAddButton", publicName: "zShowAddButton", isSignal: true, isRequired: false, transformFunction: null }, zAllowMultiple: { classPropertyName: "zAllowMultiple", publicName: "zAllowMultiple", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonIcon: { classPropertyName: "zAddButtonIcon", publicName: "zAddButtonIcon", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonText: { classPropertyName: "zAddButtonText", publicName: "zAddButtonText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zFiltersChange: "zFiltersChange", zFilterAdd: "zFilterAdd", zFilterRemove: "zFilterRemove", zFilterUpdate: "zFilterUpdate" }, host: { attributes: { "data-slot": "z-filter" }, properties: { "class": "hostClasses()" } }, queries: [{ propertyName: "addButtonTemplate", first: true, predicate: ["addButton"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "addFilterSearchInput", first: true, predicate: ["addFilterSearchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-40 min-w-0\">\n <z-calendar\n zMode=\"single\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD\"\n [zSize]=\"calendarSize()\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-56 min-w-0\">\n <z-calendar\n zMode=\"range\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD\"\n [zSize]=\"calendarSize()\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateRangeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateRangeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-28 min-w-0\">\n <z-calendar\n zMode=\"time\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"HH:mm\"\n [zSize]=\"calendarSize()\"\n [zShowSecond]=\"false\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"timeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onTimeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-52 min-w-0\">\n <z-calendar\n zMode=\"single\"\n zShowTime\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD HH:mm\"\n [zSize]=\"calendarSize()\"\n [zShowSecond]=\"false\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateTimeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateTimeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}.z-filter-calendar z-calendar{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper>.relative{display:contents}.z-filter-calendar z-calendar [z-popover]{display:flex!important;align-items:center!important;height:auto!important;min-height:0!important;width:100%!important;border:0!important;box-shadow:none!important;padding:0!important;background:transparent!important;outline:none!important;gap:.375rem!important;cursor:pointer!important}.z-filter-calendar z-calendar [z-popover]:focus-within{border-color:transparent!important;box-shadow:none!important}.z-filter-calendar z-calendar [z-popover]>z-icon{flex-shrink:0}.z-filter-calendar z-calendar [z-popover]>input{flex:1 1 0!important;min-width:0!important;width:0!important}.z-filter-calendar z-calendar [z-popover]>button[tabindex=\"-1\"]{display:none!important}.z-filter-calendar z-calendar .z-calendar-wrapper>p{display:none!important}\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: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zAnimatedType", "zAnimate", "zAnimationTrigger", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSwitchClass", "zThumbClass", "zSize", "zMode", "zVariant", "zLabel", "zText", "zCheckedText", "zUncheckedText", "zCheckedIcon", "zUncheckedIcon", "zDisabled", "zLoading", "zTextPosition", "zWave", "zChecked"], outputs: ["zChange", "zOnBlur", "zOnFocus", "zEvent", "zCheckedChange"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zAnimatedTypeIcon", "zAnimateIcon", "zAnimationTriggerIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zPopoverTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zTriggerRef", "zManualClose", "zOutsideClickClose", "zScrollClose", "zSticky", "zShowArrow", "zKeyboardSafe"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange", "zOutsideClick"], exportAs: ["zPopover"] }, { kind: "component", type: ZCalendarComponent, selector: "z-calendar", inputs: ["class", "zMode", "zSize", "zLabel", "zLabelClass", "zPlaceholder", "zRequired", "zDisabled", "zReadonly", "zLoading", "zLoadingOutline", "zShowTime", "zTimeFormat", "zShowHour", "zShowMinute", "zShowSecond", "zQuickSelect", "zAllowEdit", "zShortTime", "zAllowClear", "zFormat", "zMinDate", "zMaxDate", "zValueType", "zValidators", "zShowOk", "zOkText", "zShowCancel", "zCancelText", "zDisabledDate", "zScrollClose", "zDefaultTime", "zRangeDefaultTime"], outputs: ["zControl", "zChange", "zOnBlur", "zOnFocus", "zEvent"], exportAs: ["zCalendar"] }, { kind: "pipe", type: ZFilterFieldPipe, name: "zFilterField" }, { kind: "pipe", type: ZFilterOperatorLabelPipe, name: "zFilterOperatorLabel" }, { kind: "pipe", type: ZFilterOperatorsPipe, name: "zFilterOperators" }, { kind: "pipe", type: ZFilterSelectedOptionsPipe, name: "zFilterSelectedOptions" }, { kind: "pipe", type: ZFilterUnselectedOptionsPipe, name: "zFilterUnselectedOptions" }, { kind: "pipe", type: ZFilterInputPatternPipe, name: "zFilterInputPattern" }, { kind: "pipe", type: ZFilterIsValueHiddenPipe, name: "zFilterIsValueHidden" }, { kind: "pipe", type: ZFilterIsBetweenOperatorPipe, name: "zFilterIsBetweenOperator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
939
+ }
940
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: ZFilterComponent, decorators: [{
941
+ type: Component,
942
+ args: [{ selector: 'z-filter', imports: [
943
+ FormsModule,
944
+ ZIconComponent,
945
+ NgTemplateOutlet,
946
+ ZSwitchComponent,
947
+ ZButtonComponent,
948
+ ZPopoverDirective,
949
+ ZCalendarComponent,
950
+ ...Z_FILTER_PIPES,
951
+ ], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
952
+ '[class]': 'hostClasses()',
953
+ 'data-slot': 'z-filter',
954
+ }, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-40 min-w-0\">\n <z-calendar\n zMode=\"single\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD\"\n [zSize]=\"calendarSize()\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-56 min-w-0\">\n <z-calendar\n zMode=\"range\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD\"\n [zSize]=\"calendarSize()\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateRangeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateRangeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-28 min-w-0\">\n <z-calendar\n zMode=\"time\"\n zAllowClear\n zValueType=\"date\"\n zFormat=\"HH:mm\"\n [zSize]=\"calendarSize()\"\n [zShowSecond]=\"false\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"timeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onTimeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n <div [class]=\"getInputClasses()\" class=\"z-filter-calendar w-52 min-w-0\">\n <z-calendar\n zMode=\"single\"\n zShowTime\n zAllowClear\n zValueType=\"date\"\n zFormat=\"YYYY-MM-DD HH:mm\"\n [zSize]=\"calendarSize()\"\n [zShowSecond]=\"false\"\n [zPlaceholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [ngModel]=\"dateTimeValueMap()[filter.id] ?? null\"\n [ngModelOptions]=\"{ standalone: true }\"\n (ngModelChange)=\"onDateTimeValueChange(filter, $event)\"\n class=\"h-full min-w-0 border-0 bg-transparent px-0 shadow-none ring-0 focus-within:border-transparent focus-within:ring-0\" />\n </div>\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}.z-filter-calendar z-calendar{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper{display:contents}.z-filter-calendar z-calendar .z-calendar-wrapper>.relative{display:contents}.z-filter-calendar z-calendar [z-popover]{display:flex!important;align-items:center!important;height:auto!important;min-height:0!important;width:100%!important;border:0!important;box-shadow:none!important;padding:0!important;background:transparent!important;outline:none!important;gap:.375rem!important;cursor:pointer!important}.z-filter-calendar z-calendar [z-popover]:focus-within{border-color:transparent!important;box-shadow:none!important}.z-filter-calendar z-calendar [z-popover]>z-icon{flex-shrink:0}.z-filter-calendar z-calendar [z-popover]>input{flex:1 1 0!important;min-width:0!important;width:0!important}.z-filter-calendar z-calendar [z-popover]>button[tabindex=\"-1\"]{display:none!important}.z-filter-calendar z-calendar .z-calendar-wrapper>p{display:none!important}\n"] }]
955
+ }], propDecorators: { addButtonTemplate: [{ type: i0.ContentChild, args: ['addButton', { isSignal: true }] }], zFiltersChange: [{ type: i0.Output, args: ["zFiltersChange"] }], zFilterAdd: [{ type: i0.Output, args: ["zFilterAdd"] }], zFilterRemove: [{ type: i0.Output, args: ["zFilterRemove"] }], zFilterUpdate: [{ type: i0.Output, args: ["zFilterUpdate"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFilters", required: true }] }], zFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFields", required: true }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zI18n: [{ type: i0.Input, args: [{ isSignal: true, alias: "zI18n", required: false }] }], zShowAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowAddButton", required: false }] }], zAllowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowMultiple", required: false }] }], zAddButtonIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonIcon", required: false }] }], zAddButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonText", required: false }] }], addFilterSearchInput: [{ type: i0.ViewChild, args: ['addFilterSearchInput', { isSignal: true }] }] } });
956
+
957
+ /**
958
+ * Generated bundle index. Do not edit.
959
+ */
960
+
961
+ export { DEFAULT_FILTER_I18N, ZFilterComponent, ZFilterFieldPipe, ZFilterInputPatternPipe, ZFilterIsBetweenOperatorPipe, ZFilterIsValueHiddenPipe, ZFilterOperatorLabelPipe, ZFilterOperatorsPipe, ZFilterSelectedOptionsPipe, ZFilterUnselectedOptionsPipe, Z_FILTER_PIPES, createFilter, flattenFields, formatOperator, getDefaultOperator, getDefaultValues, getFieldsMap, getInputPattern, getOperatorsForField, zFilterBetweenVariants, zFilterContainerVariants, zFilterFieldLabelVariants, zFilterInputVariants, zFilterItemVariants, zFilterRemoveButtonVariants };
962
+ //# sourceMappingURL=shival99-z-ui-components-z-filter.mjs.map