@shival99/z-ui 1.0.1 → 1.0.2

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 (114) hide show
  1. package/assets/css/animations.css +207 -0
  2. package/assets/css/base.css +76 -0
  3. package/assets/css/tailwind.css +53 -0
  4. package/assets/css/themes/gray.css +73 -0
  5. package/assets/css/themes/green.css +75 -0
  6. package/assets/css/themes/hospital.css +79 -0
  7. package/assets/css/themes/neutral.css +73 -0
  8. package/assets/css/themes/orange.css +73 -0
  9. package/assets/css/themes/slate.css +73 -0
  10. package/assets/css/themes/stone.css +73 -0
  11. package/assets/css/themes/violet.css +73 -0
  12. package/assets/css/themes/zinc.css +73 -0
  13. package/assets/images/avatar.svg +6 -0
  14. package/assets/images/logo.svg +6 -0
  15. package/fesm2022/shival99-z-ui-components-z-accordion.mjs +148 -0
  16. package/fesm2022/shival99-z-ui-components-z-accordion.mjs.map +1 -0
  17. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs +74 -0
  18. package/fesm2022/shival99-z-ui-components-z-breadcrumb.mjs.map +1 -0
  19. package/fesm2022/shival99-z-ui-components-z-button.mjs +155 -0
  20. package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -0
  21. package/fesm2022/shival99-z-ui-components-z-calendar.mjs +2335 -0
  22. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -0
  23. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +240 -0
  24. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -0
  25. package/fesm2022/shival99-z-ui-components-z-code.mjs +139 -0
  26. package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -0
  27. package/fesm2022/shival99-z-ui-components-z-drawer.mjs +664 -0
  28. package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -0
  29. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs +55 -0
  30. package/fesm2022/shival99-z-ui-components-z-dropdown-menu.mjs.map +1 -0
  31. package/fesm2022/shival99-z-ui-components-z-editor.mjs +411 -0
  32. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -0
  33. package/fesm2022/shival99-z-ui-components-z-filter.mjs +794 -0
  34. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -0
  35. package/fesm2022/shival99-z-ui-components-z-icon.mjs +451 -0
  36. package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -0
  37. package/fesm2022/shival99-z-ui-components-z-input.mjs +804 -0
  38. package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -0
  39. package/fesm2022/shival99-z-ui-components-z-loading.mjs +105 -0
  40. package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -0
  41. package/fesm2022/shival99-z-ui-components-z-menu.mjs +351 -0
  42. package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -0
  43. package/fesm2022/shival99-z-ui-components-z-modal.mjs +722 -0
  44. package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -0
  45. package/fesm2022/shival99-z-ui-components-z-pagination.mjs +131 -0
  46. package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -0
  47. package/fesm2022/shival99-z-ui-components-z-popover.mjs +917 -0
  48. package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -0
  49. package/fesm2022/shival99-z-ui-components-z-radio.mjs +154 -0
  50. package/fesm2022/shival99-z-ui-components-z-radio.mjs.map +1 -0
  51. package/fesm2022/shival99-z-ui-components-z-select.mjs +998 -0
  52. package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -0
  53. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +139 -0
  54. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -0
  55. package/fesm2022/shival99-z-ui-components-z-switch.mjs +127 -0
  56. package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -0
  57. package/fesm2022/shival99-z-ui-components-z-table.mjs +2628 -0
  58. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -0
  59. package/fesm2022/shival99-z-ui-components-z-tabs.mjs +259 -0
  60. package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -0
  61. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +335 -0
  62. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -0
  63. package/fesm2022/shival99-z-ui-components-z-toast.mjs +93 -0
  64. package/fesm2022/shival99-z-ui-components-z-toast.mjs.map +1 -0
  65. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +660 -0
  66. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -0
  67. package/fesm2022/shival99-z-ui-components-z-upload.mjs +504 -0
  68. package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -0
  69. package/fesm2022/shival99-z-ui-i18n.mjs +258 -0
  70. package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -0
  71. package/fesm2022/shival99-z-ui-pipes.mjs +116 -0
  72. package/fesm2022/shival99-z-ui-pipes.mjs.map +1 -0
  73. package/fesm2022/shival99-z-ui-providers.mjs +203 -0
  74. package/fesm2022/shival99-z-ui-providers.mjs.map +1 -0
  75. package/fesm2022/shival99-z-ui-services.mjs +919 -0
  76. package/fesm2022/shival99-z-ui-services.mjs.map +1 -0
  77. package/fesm2022/shival99-z-ui-utils.mjs +591 -0
  78. package/fesm2022/shival99-z-ui-utils.mjs.map +1 -0
  79. package/fesm2022/z-ui.mjs +3 -19924
  80. package/fesm2022/z-ui.mjs.map +1 -1
  81. package/package.json +129 -1
  82. package/types/shival99-z-ui-components-z-accordion.d.ts +55 -0
  83. package/types/shival99-z-ui-components-z-breadcrumb.d.ts +36 -0
  84. package/types/shival99-z-ui-components-z-button.d.ts +41 -0
  85. package/types/shival99-z-ui-components-z-calendar.d.ts +300 -0
  86. package/types/shival99-z-ui-components-z-checkbox.d.ts +84 -0
  87. package/types/shival99-z-ui-components-z-code.d.ts +35 -0
  88. package/types/shival99-z-ui-components-z-drawer.d.ts +232 -0
  89. package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +50 -0
  90. package/types/shival99-z-ui-components-z-editor.d.ts +115 -0
  91. package/types/shival99-z-ui-components-z-filter.d.ts +268 -0
  92. package/types/shival99-z-ui-components-z-icon.d.ts +291 -0
  93. package/types/shival99-z-ui-components-z-input.d.ts +188 -0
  94. package/types/shival99-z-ui-components-z-loading.d.ts +46 -0
  95. package/types/shival99-z-ui-components-z-menu.d.ts +116 -0
  96. package/types/shival99-z-ui-components-z-modal.d.ts +270 -0
  97. package/types/shival99-z-ui-components-z-pagination.d.ts +52 -0
  98. package/types/shival99-z-ui-components-z-popover.d.ts +134 -0
  99. package/types/shival99-z-ui-components-z-radio.d.ts +63 -0
  100. package/types/shival99-z-ui-components-z-select.d.ts +268 -0
  101. package/types/shival99-z-ui-components-z-skeleton.d.ts +55 -0
  102. package/types/shival99-z-ui-components-z-switch.d.ts +48 -0
  103. package/types/shival99-z-ui-components-z-table.d.ts +482 -0
  104. package/types/shival99-z-ui-components-z-tabs.d.ts +75 -0
  105. package/types/shival99-z-ui-components-z-timeline.d.ts +98 -0
  106. package/types/shival99-z-ui-components-z-toast.d.ts +61 -0
  107. package/types/shival99-z-ui-components-z-tooltip.d.ts +85 -0
  108. package/types/shival99-z-ui-components-z-upload.d.ts +136 -0
  109. package/types/shival99-z-ui-i18n.d.ts +50 -0
  110. package/types/shival99-z-ui-pipes.d.ts +36 -0
  111. package/types/shival99-z-ui-providers.d.ts +132 -0
  112. package/types/shival99-z-ui-services.d.ts +364 -0
  113. package/types/shival99-z-ui-utils.d.ts +145 -0
  114. package/types/z-ui.d.ts +3 -4977
@@ -0,0 +1,794 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { Pipe, input, output, contentChild, signal, viewChild, computed, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { cva } from 'class-variance-authority';
5
+ import { zMergeClasses } from '@shival99/z-ui/utils';
6
+ import { ZButtonComponent } from '@shival99/z-ui/components/z-button';
7
+ import { ZIconComponent } from '@shival99/z-ui/components/z-icon';
8
+ import { ZPopoverDirective } from '@shival99/z-ui/components/z-popover';
9
+ import { ZSwitchComponent } from '@shival99/z-ui/components/z-switch';
10
+
11
+ function generateFilterId() {
12
+ return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
13
+ }
14
+ function createFilter(field, operator = 'is', values = []) {
15
+ return {
16
+ id: generateFilterId(),
17
+ field,
18
+ operator,
19
+ values,
20
+ };
21
+ }
22
+ function isFieldGroup(item) {
23
+ return 'fields' in item && Array.isArray(item.fields);
24
+ }
25
+ function isGroupLevelField(field) {
26
+ return Boolean(field.group && field.fields);
27
+ }
28
+ function flattenFields(fields) {
29
+ return fields.reduce((acc, item) => {
30
+ if (isFieldGroup(item)) {
31
+ return [...acc, ...item.fields];
32
+ }
33
+ if (isGroupLevelField(item)) {
34
+ return [...acc, ...item.fields];
35
+ }
36
+ return [...acc, item];
37
+ }, []);
38
+ }
39
+ function getFieldsMap(fields) {
40
+ const flatFields = flattenFields(fields);
41
+ return flatFields.reduce((acc, field) => {
42
+ if (field.key) {
43
+ acc[field.key] = field;
44
+ }
45
+ return acc;
46
+ }, {});
47
+ }
48
+ function createOperatorsFromI18n(i18n) {
49
+ return {
50
+ select: [
51
+ { value: 'is', label: i18n.operators.is },
52
+ { value: 'is_not', label: i18n.operators.isNot },
53
+ { value: 'empty', label: i18n.operators.empty },
54
+ { value: 'not_empty', label: i18n.operators.notEmpty },
55
+ ],
56
+ multiselect: [
57
+ { value: 'is_any_of', label: i18n.operators.isAnyOf },
58
+ { value: 'is_not_any_of', label: i18n.operators.isNotAnyOf },
59
+ { value: 'includes_all', label: i18n.operators.includesAll },
60
+ { value: 'excludes_all', label: i18n.operators.excludesAll },
61
+ { value: 'empty', label: i18n.operators.empty },
62
+ { value: 'not_empty', label: i18n.operators.notEmpty },
63
+ ],
64
+ date: [
65
+ { value: 'before', label: i18n.operators.before },
66
+ { value: 'after', label: i18n.operators.after },
67
+ { value: 'is', label: i18n.operators.is },
68
+ { value: 'is_not', label: i18n.operators.isNot },
69
+ { value: 'empty', label: i18n.operators.empty },
70
+ { value: 'not_empty', label: i18n.operators.notEmpty },
71
+ ],
72
+ daterange: [
73
+ { value: 'between', label: i18n.operators.between },
74
+ { value: 'not_between', label: i18n.operators.notBetween },
75
+ { value: 'empty', label: i18n.operators.empty },
76
+ { value: 'not_empty', label: i18n.operators.notEmpty },
77
+ ],
78
+ text: [
79
+ { value: 'contains', label: i18n.operators.contains },
80
+ { value: 'not_contains', label: i18n.operators.notContains },
81
+ { value: 'starts_with', label: i18n.operators.startsWith },
82
+ { value: 'ends_with', label: i18n.operators.endsWith },
83
+ { value: 'is', label: i18n.operators.isExactly },
84
+ { value: 'empty', label: i18n.operators.empty },
85
+ { value: 'not_empty', label: i18n.operators.notEmpty },
86
+ ],
87
+ number: [
88
+ { value: 'equals', label: i18n.operators.equals },
89
+ { value: 'not_equals', label: i18n.operators.notEquals },
90
+ { value: 'greater_than', label: i18n.operators.greaterThan },
91
+ { value: 'less_than', label: i18n.operators.lessThan },
92
+ { value: 'between', label: i18n.operators.between },
93
+ { value: 'empty', label: i18n.operators.empty },
94
+ { value: 'not_empty', label: i18n.operators.notEmpty },
95
+ ],
96
+ numberrange: [
97
+ { value: 'between', label: i18n.operators.between },
98
+ { value: 'overlaps', label: i18n.operators.overlaps },
99
+ { value: 'contains', label: i18n.operators.contains },
100
+ { value: 'empty', label: i18n.operators.empty },
101
+ { value: 'not_empty', label: i18n.operators.notEmpty },
102
+ ],
103
+ boolean: [
104
+ { value: 'is', label: i18n.operators.is },
105
+ { value: 'is_not', label: i18n.operators.isNot },
106
+ { value: 'empty', label: i18n.operators.empty },
107
+ { value: 'not_empty', label: i18n.operators.notEmpty },
108
+ ],
109
+ email: [
110
+ { value: 'contains', label: i18n.operators.contains },
111
+ { value: 'not_contains', label: i18n.operators.notContains },
112
+ { value: 'starts_with', label: i18n.operators.startsWith },
113
+ { value: 'ends_with', label: i18n.operators.endsWith },
114
+ { value: 'is', label: i18n.operators.isExactly },
115
+ { value: 'empty', label: i18n.operators.empty },
116
+ { value: 'not_empty', label: i18n.operators.notEmpty },
117
+ ],
118
+ url: [
119
+ { value: 'contains', label: i18n.operators.contains },
120
+ { value: 'not_contains', label: i18n.operators.notContains },
121
+ { value: 'starts_with', label: i18n.operators.startsWith },
122
+ { value: 'ends_with', label: i18n.operators.endsWith },
123
+ { value: 'is', label: i18n.operators.isExactly },
124
+ { value: 'empty', label: i18n.operators.empty },
125
+ { value: 'not_empty', label: i18n.operators.notEmpty },
126
+ ],
127
+ tel: [
128
+ { value: 'contains', label: i18n.operators.contains },
129
+ { value: 'not_contains', label: i18n.operators.notContains },
130
+ { value: 'starts_with', label: i18n.operators.startsWith },
131
+ { value: 'ends_with', label: i18n.operators.endsWith },
132
+ { value: 'is', label: i18n.operators.isExactly },
133
+ { value: 'empty', label: i18n.operators.empty },
134
+ { value: 'not_empty', label: i18n.operators.notEmpty },
135
+ ],
136
+ time: [
137
+ { value: 'before', label: i18n.operators.before },
138
+ { value: 'after', label: i18n.operators.after },
139
+ { value: 'is', label: i18n.operators.is },
140
+ { value: 'between', label: i18n.operators.between },
141
+ { value: 'empty', label: i18n.operators.empty },
142
+ { value: 'not_empty', label: i18n.operators.notEmpty },
143
+ ],
144
+ datetime: [
145
+ { value: 'before', label: i18n.operators.before },
146
+ { value: 'after', label: i18n.operators.after },
147
+ { value: 'is', label: i18n.operators.is },
148
+ { value: 'between', label: i18n.operators.between },
149
+ { value: 'empty', label: i18n.operators.empty },
150
+ { value: 'not_empty', label: i18n.operators.notEmpty },
151
+ ],
152
+ };
153
+ }
154
+ function getOperatorsForField(field, values, i18n) {
155
+ if (field.operators) {
156
+ return field.operators;
157
+ }
158
+ const operators = createOperatorsFromI18n(i18n);
159
+ let fieldType = field.type || 'select';
160
+ if (fieldType === 'select' && values.length > 1) {
161
+ fieldType = 'multiselect';
162
+ }
163
+ if (fieldType === 'multiselect' || field.type === 'multiselect') {
164
+ return operators['multiselect'];
165
+ }
166
+ return operators[fieldType] || operators['select'];
167
+ }
168
+ function formatOperator(operator) {
169
+ return operator.replace(/_/g, ' ');
170
+ }
171
+ function getDefaultOperator(fieldType) {
172
+ switch (fieldType) {
173
+ case 'daterange':
174
+ case 'numberrange':
175
+ return 'between';
176
+ case 'boolean':
177
+ return 'is';
178
+ case 'multiselect':
179
+ return 'is_any_of';
180
+ default:
181
+ return 'is';
182
+ }
183
+ }
184
+ function getDefaultValues(fieldType, field) {
185
+ switch (fieldType) {
186
+ case 'text':
187
+ case 'number':
188
+ case 'date':
189
+ case 'email':
190
+ case 'url':
191
+ case 'tel':
192
+ case 'time':
193
+ case 'datetime':
194
+ return [''];
195
+ case 'daterange':
196
+ return ['', ''];
197
+ case 'numberrange':
198
+ return [field.min || 0, field.max || 100];
199
+ case 'boolean':
200
+ return [false];
201
+ default:
202
+ return [];
203
+ }
204
+ }
205
+ function getInputPattern(fieldType) {
206
+ switch (fieldType) {
207
+ case 'email':
208
+ return '^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$';
209
+ case 'url':
210
+ return '^https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$';
211
+ case 'tel':
212
+ return '^[\\+]?[1-9][\\d]{0,15}$';
213
+ default:
214
+ return undefined;
215
+ }
216
+ }
217
+
218
+ class ZFilterFieldPipe {
219
+ transform(filter, fields) {
220
+ const fieldsMap = getFieldsMap(fields);
221
+ return fieldsMap[filter.field];
222
+ }
223
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterFieldPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
224
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterFieldPipe, isStandalone: true, name: "zFilterField" });
225
+ }
226
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterFieldPipe, decorators: [{
227
+ type: Pipe,
228
+ args: [{
229
+ name: 'zFilterField',
230
+ standalone: true,
231
+ pure: true,
232
+ }]
233
+ }] });
234
+
235
+ class ZFilterInputPatternPipe {
236
+ transform(field) {
237
+ switch (field.type) {
238
+ case 'email':
239
+ return '[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,}$';
240
+ case 'url':
241
+ return 'https?://.+';
242
+ case 'tel':
243
+ return '[0-9+\\-\\s()]+';
244
+ default:
245
+ return field.pattern || '';
246
+ }
247
+ }
248
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterInputPatternPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
249
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterInputPatternPipe, isStandalone: true, name: "zFilterInputPattern" });
250
+ }
251
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterInputPatternPipe, decorators: [{
252
+ type: Pipe,
253
+ args: [{
254
+ name: 'zFilterInputPattern',
255
+ standalone: true,
256
+ pure: true,
257
+ }]
258
+ }] });
259
+
260
+ class ZFilterIsBetweenOperatorPipe {
261
+ transform(filter) {
262
+ return filter.operator === 'between' || filter.operator === 'not_between';
263
+ }
264
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
265
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, isStandalone: true, name: "zFilterIsBetweenOperator" });
266
+ }
267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsBetweenOperatorPipe, decorators: [{
268
+ type: Pipe,
269
+ args: [{
270
+ name: 'zFilterIsBetweenOperator',
271
+ standalone: true,
272
+ pure: true,
273
+ }]
274
+ }] });
275
+
276
+ class ZFilterIsValueHiddenPipe {
277
+ transform(filter) {
278
+ const { operator } = filter;
279
+ return operator === 'is_empty' || operator === 'is_not_empty';
280
+ }
281
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
282
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, isStandalone: true, name: "zFilterIsValueHidden" });
283
+ }
284
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterIsValueHiddenPipe, decorators: [{
285
+ type: Pipe,
286
+ args: [{
287
+ name: 'zFilterIsValueHidden',
288
+ standalone: true,
289
+ pure: true,
290
+ }]
291
+ }] });
292
+
293
+ class ZFilterOperatorLabelPipe {
294
+ transform(filter, fields, i18n) {
295
+ const fieldsMap = getFieldsMap(fields);
296
+ const field = fieldsMap[filter.field];
297
+ if (!field) {
298
+ return '';
299
+ }
300
+ const operators = getOperatorsForField(field, filter.values, i18n);
301
+ const op = operators.find(o => o.value === filter.operator);
302
+ return op?.label || formatOperator(filter.operator);
303
+ }
304
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorLabelPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
305
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorLabelPipe, isStandalone: true, name: "zFilterOperatorLabel" });
306
+ }
307
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorLabelPipe, decorators: [{
308
+ type: Pipe,
309
+ args: [{
310
+ name: 'zFilterOperatorLabel',
311
+ standalone: true,
312
+ pure: true,
313
+ }]
314
+ }] });
315
+
316
+ class ZFilterOperatorsPipe {
317
+ transform(filter, fields, i18n) {
318
+ const fieldsMap = getFieldsMap(fields);
319
+ const field = fieldsMap[filter.field];
320
+ if (!field) {
321
+ return [];
322
+ }
323
+ return getOperatorsForField(field, filter.values, i18n);
324
+ }
325
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
326
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorsPipe, isStandalone: true, name: "zFilterOperators" });
327
+ }
328
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterOperatorsPipe, decorators: [{
329
+ type: Pipe,
330
+ args: [{
331
+ name: 'zFilterOperators',
332
+ standalone: true,
333
+ pure: true,
334
+ }]
335
+ }] });
336
+
337
+ class ZFilterSelectedOptionsPipe {
338
+ transform(filter, fields) {
339
+ const fieldsMap = getFieldsMap(fields);
340
+ const field = fieldsMap[filter.field];
341
+ if (!field?.options) {
342
+ return [];
343
+ }
344
+ return field.options.filter(opt => filter.values.includes(opt.value));
345
+ }
346
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
347
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, isStandalone: true, name: "zFilterSelectedOptions" });
348
+ }
349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterSelectedOptionsPipe, decorators: [{
350
+ type: Pipe,
351
+ args: [{
352
+ name: 'zFilterSelectedOptions',
353
+ standalone: true,
354
+ pure: true,
355
+ }]
356
+ }] });
357
+
358
+ class ZFilterUnselectedOptionsPipe {
359
+ transform(filter, fields) {
360
+ const fieldsMap = getFieldsMap(fields);
361
+ const field = fieldsMap[filter.field];
362
+ if (!field?.options) {
363
+ return [];
364
+ }
365
+ return field.options.filter(opt => !filter.values.includes(opt.value));
366
+ }
367
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
368
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, isStandalone: true, name: "zFilterUnselectedOptions" });
369
+ }
370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterUnselectedOptionsPipe, decorators: [{
371
+ type: Pipe,
372
+ args: [{
373
+ name: 'zFilterUnselectedOptions',
374
+ standalone: true,
375
+ pure: true,
376
+ }]
377
+ }] });
378
+
379
+ const Z_FILTER_PIPES = [
380
+ ZFilterFieldPipe,
381
+ ZFilterOperatorLabelPipe,
382
+ ZFilterOperatorsPipe,
383
+ ZFilterSelectedOptionsPipe,
384
+ ZFilterUnselectedOptionsPipe,
385
+ ZFilterInputPatternPipe,
386
+ ZFilterIsValueHiddenPipe,
387
+ ZFilterIsBetweenOperatorPipe,
388
+ ];
389
+
390
+ const DEFAULT_FILTER_I18N = {
391
+ addFilter: 'Add filter',
392
+ searchFields: 'Search fields...',
393
+ noFieldsFound: 'No fields found.',
394
+ noResultsFound: 'No results found.',
395
+ select: 'Select...',
396
+ true: 'True',
397
+ false: 'False',
398
+ min: 'Min',
399
+ max: 'Max',
400
+ to: 'to',
401
+ selected: 'selected',
402
+ selectedCount: 'selected',
403
+ addFilterTitle: 'Add filter',
404
+ operators: {
405
+ is: 'is',
406
+ isNot: 'is not',
407
+ isAnyOf: 'is any of',
408
+ isNotAnyOf: 'is not any of',
409
+ includesAll: 'includes all',
410
+ excludesAll: 'excludes all',
411
+ before: 'before',
412
+ after: 'after',
413
+ between: 'between',
414
+ notBetween: 'not between',
415
+ contains: 'contains',
416
+ notContains: 'does not contain',
417
+ startsWith: 'starts with',
418
+ endsWith: 'ends with',
419
+ isExactly: 'is exactly',
420
+ equals: 'equals',
421
+ notEquals: 'not equals',
422
+ greaterThan: 'greater than',
423
+ lessThan: 'less than',
424
+ overlaps: 'overlaps',
425
+ includes: 'includes',
426
+ excludes: 'excludes',
427
+ includesAllOf: 'includes all of',
428
+ includesAnyOf: 'includes any of',
429
+ empty: 'is empty',
430
+ notEmpty: 'is not empty',
431
+ },
432
+ placeholders: {
433
+ enterField: 'Enter value...',
434
+ selectField: 'Select...',
435
+ searchField: 'Search...',
436
+ enterKey: 'Enter key...',
437
+ enterValue: 'Enter value...',
438
+ },
439
+ validation: {
440
+ invalidEmail: 'Invalid email format',
441
+ invalidUrl: 'Invalid URL format',
442
+ invalidTel: 'Invalid phone format',
443
+ invalid: 'Invalid input format',
444
+ },
445
+ };
446
+
447
+ const zFilterContainerVariants = cva('flex flex-wrap items-center gap-2', {
448
+ variants: {
449
+ size: {
450
+ sm: 'gap-1.5',
451
+ md: 'gap-2',
452
+ lg: 'gap-2.5',
453
+ },
454
+ },
455
+ defaultVariants: {
456
+ size: 'md',
457
+ },
458
+ });
459
+ const zFilterItemVariants = cva('inline-flex items-stretch rounded-[4px] border border-input bg-background shadow-xs overflow-hidden', {
460
+ variants: {
461
+ size: {
462
+ sm: 'h-8',
463
+ md: 'h-9',
464
+ lg: 'h-10',
465
+ },
466
+ },
467
+ defaultVariants: {
468
+ size: 'md',
469
+ },
470
+ });
471
+ const zFilterFieldLabelVariants = cva('flex items-center gap-1.5 bg-background font-medium text-muted-foreground border-r border-input', {
472
+ variants: {
473
+ size: {
474
+ sm: 'px-2 text-xs',
475
+ md: 'px-2.5 text-sm',
476
+ lg: 'px-3 text-sm',
477
+ },
478
+ },
479
+ defaultVariants: {
480
+ size: 'md',
481
+ },
482
+ });
483
+ const zFilterInputVariants = cva('flex items-center bg-background px-2 focus-within:bg-muted/50', {
484
+ variants: {
485
+ size: {
486
+ sm: 'text-xs',
487
+ md: 'text-sm',
488
+ lg: 'text-sm',
489
+ },
490
+ },
491
+ defaultVariants: {
492
+ size: 'md',
493
+ },
494
+ });
495
+ 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', {
496
+ variants: {
497
+ size: {
498
+ sm: 'px-1.5',
499
+ md: 'px-2',
500
+ lg: 'px-2.5',
501
+ },
502
+ },
503
+ defaultVariants: {
504
+ size: 'md',
505
+ },
506
+ });
507
+ const zFilterBetweenVariants = cva('text-muted-foreground flex items-center', {
508
+ variants: {
509
+ size: {
510
+ sm: 'px-1 text-xs',
511
+ md: 'px-1.5 text-xs',
512
+ lg: 'px-2 text-sm',
513
+ },
514
+ },
515
+ defaultVariants: {
516
+ size: 'md',
517
+ },
518
+ });
519
+
520
+ class ZFilterComponent {
521
+ class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
522
+ zFilters = input.required(...(ngDevMode ? [{ debugName: "zFilters" }] : []));
523
+ zFields = input.required(...(ngDevMode ? [{ debugName: "zFields" }] : []));
524
+ zSize = input('md', ...(ngDevMode ? [{ debugName: "zSize" }] : []));
525
+ zI18n = input({}, ...(ngDevMode ? [{ debugName: "zI18n" }] : []));
526
+ zShowAddButton = input(true, ...(ngDevMode ? [{ debugName: "zShowAddButton" }] : []));
527
+ zAllowMultiple = input(true, ...(ngDevMode ? [{ debugName: "zAllowMultiple" }] : []));
528
+ zAddButtonIcon = input('lucidePlus', ...(ngDevMode ? [{ debugName: "zAddButtonIcon" }] : []));
529
+ zAddButtonText = input(...(ngDevMode ? [undefined, { debugName: "zAddButtonText" }] : []));
530
+ zFiltersChange = output();
531
+ zFilterAdd = output();
532
+ zFilterRemove = output();
533
+ zFilterUpdate = output();
534
+ addButtonTemplate = contentChild('addButton', ...(ngDevMode ? [{ debugName: "addButtonTemplate" }] : []));
535
+ addFilterOpen = signal(false, ...(ngDevMode ? [{ debugName: "addFilterOpen" }] : []));
536
+ searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
537
+ operatorPopoverOpen = signal(null, ...(ngDevMode ? [{ debugName: "operatorPopoverOpen" }] : []));
538
+ valuePopoverOpen = signal(null, ...(ngDevMode ? [{ debugName: "valuePopoverOpen" }] : []));
539
+ addFilterSearchInput = viewChild('addFilterSearchInput', ...(ngDevMode ? [{ debugName: "addFilterSearchInput" }] : []));
540
+ focusSearchInput() {
541
+ setTimeout(() => {
542
+ this.addFilterSearchInput()?.nativeElement?.focus();
543
+ }, 50);
544
+ }
545
+ focusSelectSearch(filterId) {
546
+ setTimeout(() => {
547
+ const input = document.getElementById(`select-search-${filterId}`);
548
+ input?.focus();
549
+ }, 50);
550
+ }
551
+ i18n = computed(() => {
552
+ const custom = this.zI18n();
553
+ return {
554
+ ...DEFAULT_FILTER_I18N,
555
+ ...custom,
556
+ operators: { ...DEFAULT_FILTER_I18N.operators, ...custom.operators },
557
+ placeholders: { ...DEFAULT_FILTER_I18N.placeholders, ...custom.placeholders },
558
+ validation: { ...DEFAULT_FILTER_I18N.validation, ...custom.validation },
559
+ };
560
+ }, ...(ngDevMode ? [{ debugName: "i18n" }] : []));
561
+ fieldsMap = computed(() => getFieldsMap(this.zFields()), ...(ngDevMode ? [{ debugName: "fieldsMap" }] : []));
562
+ selectableFields = computed(() => {
563
+ const flatFields = flattenFields(this.zFields());
564
+ const filters = this.zFilters();
565
+ return flatFields.filter(field => {
566
+ if (!field.key || field.type === 'separator') {
567
+ return false;
568
+ }
569
+ if (this.zAllowMultiple()) {
570
+ return true;
571
+ }
572
+ return !filters.some(filter => filter.field === field.key);
573
+ });
574
+ }, ...(ngDevMode ? [{ debugName: "selectableFields" }] : []));
575
+ filteredFields = computed(() => {
576
+ const query = this.searchQuery().toLowerCase().trim();
577
+ if (!query) {
578
+ return this.selectableFields();
579
+ }
580
+ return this.selectableFields().filter(field => field.label?.toLowerCase().includes(query) || field.key?.toLowerCase().includes(query));
581
+ }, ...(ngDevMode ? [{ debugName: "filteredFields" }] : []));
582
+ groupedFields = computed(() => {
583
+ const allFields = this.zFields();
584
+ const query = this.searchQuery().toLowerCase().trim();
585
+ const filters = this.zFilters();
586
+ const allowMultiple = this.zAllowMultiple();
587
+ const filterField = (field) => {
588
+ if (!field.key || field.type === 'separator') {
589
+ return false;
590
+ }
591
+ if (!allowMultiple && filters.some(f => f.field === field.key)) {
592
+ return false;
593
+ }
594
+ if (query && !field.label?.toLowerCase().includes(query) && !field.key?.toLowerCase().includes(query)) {
595
+ return false;
596
+ }
597
+ return true;
598
+ };
599
+ const groups = [];
600
+ for (const item of allFields) {
601
+ if ('fields' in item && Array.isArray(item.fields)) {
602
+ const groupName = item.group || '';
603
+ const filteredGroupFields = item.fields.filter(filterField);
604
+ if (filteredGroupFields.length > 0) {
605
+ groups.push({ group: groupName, fields: filteredGroupFields });
606
+ }
607
+ }
608
+ else {
609
+ const field = item;
610
+ if (filterField(field)) {
611
+ const groupName = field.group || '';
612
+ const existingGroup = groups.find(g => g.group === groupName);
613
+ if (existingGroup) {
614
+ existingGroup.fields.push(field);
615
+ }
616
+ else {
617
+ groups.push({ group: groupName, fields: [field] });
618
+ }
619
+ }
620
+ }
621
+ }
622
+ return groups;
623
+ }, ...(ngDevMode ? [{ debugName: "groupedFields" }] : []));
624
+ buttonSize = computed(() => {
625
+ const size = this.zSize();
626
+ if (size === 'sm') {
627
+ return 'sm';
628
+ }
629
+ if (size === 'lg') {
630
+ return 'lg';
631
+ }
632
+ return 'default';
633
+ }, ...(ngDevMode ? [{ debugName: "buttonSize" }] : []));
634
+ hostClasses = computed(() => zMergeClasses(zFilterContainerVariants({ size: this.zSize() }), this.class()), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
635
+ getItemClasses() {
636
+ return zFilterItemVariants({ size: this.zSize() });
637
+ }
638
+ getLabelClasses() {
639
+ return zFilterFieldLabelVariants({ size: this.zSize() });
640
+ }
641
+ getInputClasses() {
642
+ return zFilterInputVariants({ size: this.zSize() });
643
+ }
644
+ getRemoveButtonClasses() {
645
+ return zFilterRemoveButtonVariants({ size: this.zSize() });
646
+ }
647
+ getBetweenClasses() {
648
+ return zFilterBetweenVariants({ size: this.zSize() });
649
+ }
650
+ getFieldForFilter(filter) {
651
+ return this.fieldsMap()[filter.field];
652
+ }
653
+ getOperatorsForFilter(filter) {
654
+ const field = this.getFieldForFilter(filter);
655
+ if (!field) {
656
+ return [];
657
+ }
658
+ return getOperatorsForField(field, filter.values, this.i18n());
659
+ }
660
+ getOperatorLabel(filter) {
661
+ const operators = this.getOperatorsForFilter(filter);
662
+ const op = operators.find(o => o.value === filter.operator);
663
+ return op?.label || formatOperator(filter.operator);
664
+ }
665
+ getSelectedOptions(filter) {
666
+ const field = this.getFieldForFilter(filter);
667
+ if (!field?.options) {
668
+ return [];
669
+ }
670
+ return field.options.filter(opt => filter.values.includes(opt.value));
671
+ }
672
+ getUnselectedOptions(filter) {
673
+ const field = this.getFieldForFilter(filter);
674
+ if (!field?.options) {
675
+ return [];
676
+ }
677
+ return field.options.filter(opt => !filter.values.includes(opt.value));
678
+ }
679
+ isValueHidden(filter) {
680
+ return filter.operator === 'empty' || filter.operator === 'not_empty';
681
+ }
682
+ isBetweenOperator(filter) {
683
+ return filter.operator === 'between';
684
+ }
685
+ getInputPattern(field) {
686
+ return field.pattern || getInputPattern(field.type || '');
687
+ }
688
+ onFieldSelect(field) {
689
+ if (!field.key) {
690
+ return;
691
+ }
692
+ const defaultOperator = field.defaultOperator || getDefaultOperator(field.type || 'select');
693
+ const defaultValues = getDefaultValues(field.type || 'select', field);
694
+ const newFilter = createFilter(field.key, defaultOperator, defaultValues);
695
+ const newFilters = [...this.zFilters(), newFilter];
696
+ this.zFiltersChange.emit(newFilters);
697
+ this.zFilterAdd.emit(newFilter);
698
+ this.addFilterOpen.set(false);
699
+ this.searchQuery.set('');
700
+ }
701
+ updateFilterOperator(filter, operator) {
702
+ const updates = { operator };
703
+ if (operator === 'empty' || operator === 'not_empty') {
704
+ updates.values = [];
705
+ }
706
+ const updatedFilters = this.zFilters().map(f => {
707
+ if (f.id === filter.id) {
708
+ return { ...f, ...updates };
709
+ }
710
+ return f;
711
+ });
712
+ this.zFiltersChange.emit(updatedFilters);
713
+ this.zFilterUpdate.emit({ filter, updates });
714
+ this.operatorPopoverOpen.set(null);
715
+ }
716
+ onSelectValueChange(filter, option) {
717
+ const field = this.getFieldForFilter(filter);
718
+ const isMultiSelect = field?.type === 'multiselect';
719
+ const isSelected = filter.values.includes(option.value);
720
+ let newValues;
721
+ if (isMultiSelect) {
722
+ newValues = isSelected ? filter.values.filter(v => v !== option.value) : [...filter.values, option.value];
723
+ }
724
+ else {
725
+ newValues = isSelected ? [] : [option.value];
726
+ }
727
+ const updatedFilters = this.zFilters().map(f => {
728
+ if (f.id === filter.id) {
729
+ return { ...f, values: newValues };
730
+ }
731
+ return f;
732
+ });
733
+ this.zFiltersChange.emit(updatedFilters);
734
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
735
+ }
736
+ removeFilter(filter) {
737
+ const updatedFilters = this.zFilters().filter(f => f.id !== filter.id);
738
+ this.zFiltersChange.emit(updatedFilters);
739
+ this.zFilterRemove.emit(filter);
740
+ }
741
+ onInputChange(filter, event, index = 0) {
742
+ const input = event.target;
743
+ const newValues = [...filter.values];
744
+ newValues[index] = input.value;
745
+ const updatedFilters = this.zFilters().map(f => {
746
+ if (f.id === filter.id) {
747
+ return { ...f, values: newValues };
748
+ }
749
+ return f;
750
+ });
751
+ this.zFiltersChange.emit(updatedFilters);
752
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
753
+ }
754
+ onBooleanChange(filter, checked) {
755
+ const newValues = [checked];
756
+ const updatedFilters = this.zFilters().map(f => {
757
+ if (f.id === filter.id) {
758
+ return { ...f, values: newValues };
759
+ }
760
+ return f;
761
+ });
762
+ this.zFiltersChange.emit(updatedFilters);
763
+ this.zFilterUpdate.emit({ filter, updates: { values: newValues } });
764
+ }
765
+ onSearchInput(event) {
766
+ const input = event.target;
767
+ this.searchQuery.set(input.value);
768
+ }
769
+ trackByFilterId(index, filter) {
770
+ return filter.id;
771
+ }
772
+ trackByOptionValue(index, option) {
773
+ return option.value;
774
+ }
775
+ trackByFieldKey(index, field) {
776
+ return field.key || `field-${index}`;
777
+ }
778
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
779
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.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-[200px]\">\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-[300px] 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=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\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-[200px]\">\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-[200px] 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}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSize", "zLabel", "zText", "zDisabled", "zTextPosition", "zChecked"], outputs: ["zCheckedChange", "zChange"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl"], exportAs: ["zPopover"] }, { 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 });
780
+ }
781
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterComponent, decorators: [{
782
+ type: Component,
783
+ args: [{ selector: 'z-filter', imports: [ZIconComponent, NgTemplateOutlet, ZSwitchComponent, ZButtonComponent, ZPopoverDirective, ...Z_FILTER_PIPES], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
784
+ '[class]': 'hostClasses()',
785
+ 'data-slot': 'z-filter',
786
+ }, 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-[200px]\">\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-[300px] 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=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\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-[200px]\">\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-[200px] 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}\n"] }]
787
+ }], propDecorators: { 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 }] }], zFiltersChange: [{ type: i0.Output, args: ["zFiltersChange"] }], zFilterAdd: [{ type: i0.Output, args: ["zFilterAdd"] }], zFilterRemove: [{ type: i0.Output, args: ["zFilterRemove"] }], zFilterUpdate: [{ type: i0.Output, args: ["zFilterUpdate"] }], addButtonTemplate: [{ type: i0.ContentChild, args: ['addButton', { isSignal: true }] }], addFilterSearchInput: [{ type: i0.ViewChild, args: ['addFilterSearchInput', { isSignal: true }] }] } });
788
+
789
+ /**
790
+ * Generated bundle index. Do not edit.
791
+ */
792
+
793
+ 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 };
794
+ //# sourceMappingURL=shival99-z-ui-components-z-filter.mjs.map