@ngneers/controls 0.0.1-pre1 → 0.0.1-pre3

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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/fesm2022/ngneers-controls-accordion.mjs +194 -0
  3. package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
  4. package/fesm2022/ngneers-controls-api-ng.mjs +668 -0
  5. package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
  6. package/fesm2022/ngneers-controls-api.mjs +256 -227
  7. package/fesm2022/ngneers-controls-api.mjs.map +1 -1
  8. package/fesm2022/ngneers-controls-avatar.mjs +70 -0
  9. package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
  10. package/fesm2022/ngneers-controls-base.mjs +397 -0
  11. package/fesm2022/ngneers-controls-base.mjs.map +1 -0
  12. package/fesm2022/ngneers-controls-breadcrumb.mjs +74 -0
  13. package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
  14. package/fesm2022/ngneers-controls-button-group.mjs +51 -0
  15. package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
  16. package/fesm2022/ngneers-controls-button.mjs +62 -0
  17. package/fesm2022/ngneers-controls-button.mjs.map +1 -0
  18. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs +63 -0
  19. package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs.map +1 -0
  20. package/fesm2022/ngneers-controls-calendar.mjs +468 -0
  21. package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
  22. package/fesm2022/ngneers-controls-checkbox.mjs +58 -0
  23. package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
  24. package/fesm2022/ngneers-controls-chip.mjs +52 -0
  25. package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
  26. package/fesm2022/ngneers-controls-defer.mjs +43 -0
  27. package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
  28. package/fesm2022/ngneers-controls-dialog.mjs +329 -33
  29. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -1
  30. package/fesm2022/ngneers-controls-directives.mjs +443 -0
  31. package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
  32. package/fesm2022/ngneers-controls-drawer.mjs +232 -0
  33. package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
  34. package/fesm2022/ngneers-controls-edit-inplace.mjs +120 -0
  35. package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
  36. package/fesm2022/ngneers-controls-filter.mjs +516 -0
  37. package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
  38. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs +87 -0
  39. package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs.map +1 -0
  40. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs +87 -0
  41. package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs.map +1 -0
  42. package/fesm2022/ngneers-controls-i18n.mjs +57 -0
  43. package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
  44. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs +4 -0
  45. package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs.map +1 -0
  46. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs +4 -0
  47. package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs.map +1 -0
  48. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs +4 -0
  49. package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs.map +1 -0
  50. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs +4 -0
  51. package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs.map +1 -0
  52. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs +4 -0
  53. package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs.map +1 -0
  54. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs +4 -0
  55. package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs.map +1 -0
  56. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs +4 -0
  57. package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs.map +1 -0
  58. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs +4 -0
  59. package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs.map +1 -0
  60. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs +4 -0
  61. package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs.map +1 -0
  62. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs +4 -0
  63. package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs.map +1 -0
  64. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs +4 -0
  65. package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs.map +1 -0
  66. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs +4 -0
  67. package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs.map +1 -0
  68. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs +4 -0
  69. package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs.map +1 -0
  70. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs +4 -0
  71. package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs.map +1 -0
  72. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs +4 -0
  73. package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs.map +1 -0
  74. package/fesm2022/ngneers-controls-icon.mjs +60 -18
  75. package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
  76. package/fesm2022/ngneers-controls-inplace.mjs +107 -0
  77. package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
  78. package/fesm2022/ngneers-controls-input-field.mjs +141 -0
  79. package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
  80. package/fesm2022/ngneers-controls-input-mask.mjs +282 -0
  81. package/fesm2022/ngneers-controls-input-mask.mjs.map +1 -0
  82. package/fesm2022/ngneers-controls-input.mjs +69 -0
  83. package/fesm2022/ngneers-controls-input.mjs.map +1 -0
  84. package/fesm2022/ngneers-controls-item-view.mjs +441 -0
  85. package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
  86. package/fesm2022/ngneers-controls-list-box.mjs +157 -53
  87. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
  88. package/fesm2022/ngneers-controls-menu.mjs +332 -0
  89. package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
  90. package/fesm2022/ngneers-controls-message.mjs +29 -0
  91. package/fesm2022/ngneers-controls-message.mjs.map +1 -0
  92. package/fesm2022/ngneers-controls-paginator.mjs +111 -0
  93. package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
  94. package/fesm2022/ngneers-controls-popover.mjs +129 -40
  95. package/fesm2022/ngneers-controls-popover.mjs.map +1 -1
  96. package/fesm2022/ngneers-controls-progress.mjs +82 -0
  97. package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
  98. package/fesm2022/ngneers-controls-scroller.mjs +162 -78
  99. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
  100. package/fesm2022/ngneers-controls-select-button.mjs +55 -0
  101. package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
  102. package/fesm2022/ngneers-controls-select.mjs +313 -103
  103. package/fesm2022/ngneers-controls-select.mjs.map +1 -1
  104. package/fesm2022/ngneers-controls-slider.mjs +155 -0
  105. package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
  106. package/fesm2022/ngneers-controls-spinner.mjs +169 -0
  107. package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
  108. package/fesm2022/ngneers-controls-splitter.mjs +717 -0
  109. package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
  110. package/fesm2022/ngneers-controls-switch.mjs +39 -0
  111. package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
  112. package/fesm2022/ngneers-controls-table.mjs +379 -0
  113. package/fesm2022/ngneers-controls-table.mjs.map +1 -0
  114. package/fesm2022/ngneers-controls-tabs.mjs +287 -0
  115. package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
  116. package/fesm2022/ngneers-controls-tag.mjs +29 -0
  117. package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
  118. package/fesm2022/ngneers-controls-toast.mjs +184 -0
  119. package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
  120. package/fesm2022/ngneers-controls-toggle-button.mjs +65 -0
  121. package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
  122. package/fesm2022/ngneers-controls-tooltip.mjs +454 -0
  123. package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
  124. package/fesm2022/ngneers-controls-utils-ng.mjs +227 -0
  125. package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
  126. package/fesm2022/ngneers-controls-utils.mjs +217 -60
  127. package/fesm2022/ngneers-controls-utils.mjs.map +1 -1
  128. package/fesm2022/ngneers-controls.mjs.map +1 -1
  129. package/package.json +167 -32
  130. package/types/ngneers-controls-accordion.d.ts +114 -0
  131. package/types/ngneers-controls-api-ng.d.ts +291 -0
  132. package/types/ngneers-controls-api.d.ts +99 -0
  133. package/types/ngneers-controls-avatar.d.ts +50 -0
  134. package/types/ngneers-controls-base.d.ts +166 -0
  135. package/types/ngneers-controls-breadcrumb.d.ts +86 -0
  136. package/types/ngneers-controls-button-group.d.ts +30 -0
  137. package/types/ngneers-controls-button.d.ts +34 -0
  138. package/types/ngneers-controls-calendar.d.ts +275 -0
  139. package/types/ngneers-controls-checkbox.d.ts +38 -0
  140. package/types/ngneers-controls-chip.d.ts +37 -0
  141. package/types/ngneers-controls-defer.d.ts +22 -0
  142. package/types/ngneers-controls-dialog.d.ts +218 -0
  143. package/types/ngneers-controls-directives.d.ts +146 -0
  144. package/types/ngneers-controls-drawer.d.ts +220 -0
  145. package/types/ngneers-controls-edit-inplace.d.ts +182 -0
  146. package/types/ngneers-controls-filter.d.ts +304 -0
  147. package/types/ngneers-controls-i18n.d.ts +108 -0
  148. package/types/ngneers-controls-icon.d.ts +74 -0
  149. package/types/ngneers-controls-inplace.d.ts +95 -0
  150. package/types/ngneers-controls-input-field.d.ts +159 -0
  151. package/types/ngneers-controls-input-mask.d.ts +83 -0
  152. package/types/ngneers-controls-input.d.ts +27 -0
  153. package/types/ngneers-controls-item-view.d.ts +211 -0
  154. package/types/ngneers-controls-list-box.d.ts +216 -0
  155. package/types/ngneers-controls-menu.d.ts +178 -0
  156. package/types/ngneers-controls-message.d.ts +19 -0
  157. package/types/ngneers-controls-paginator.d.ts +162 -0
  158. package/types/ngneers-controls-popover.d.ts +101 -0
  159. package/types/ngneers-controls-progress.d.ts +44 -0
  160. package/types/ngneers-controls-scroller.d.ts +137 -0
  161. package/types/ngneers-controls-select-button.d.ts +37 -0
  162. package/types/ngneers-controls-select.d.ts +314 -0
  163. package/types/ngneers-controls-slider.d.ts +53 -0
  164. package/types/ngneers-controls-spinner.d.ts +105 -0
  165. package/types/ngneers-controls-splitter.d.ts +391 -0
  166. package/types/ngneers-controls-switch.d.ts +18 -0
  167. package/types/ngneers-controls-table.d.ts +157 -0
  168. package/types/ngneers-controls-tabs.d.ts +106 -0
  169. package/types/ngneers-controls-tag.d.ts +19 -0
  170. package/types/ngneers-controls-toast.d.ts +70 -0
  171. package/types/ngneers-controls-toggle-button.d.ts +46 -0
  172. package/types/ngneers-controls-tooltip.d.ts +188 -0
  173. package/types/ngneers-controls-utils-ng.d.ts +57 -0
  174. package/types/ngneers-controls-utils.d.ts +130 -0
  175. package/api/index.d.ts +0 -134
  176. package/custom-types/index.d.ts +0 -7
  177. package/dialog/index.d.ts +0 -43
  178. package/fesm2022/ngneers-controls-custom-types.mjs +0 -4
  179. package/fesm2022/ngneers-controls-custom-types.mjs.map +0 -1
  180. package/fesm2022/ngneers-controls-form-field.mjs +0 -33
  181. package/fesm2022/ngneers-controls-form-field.mjs.map +0 -1
  182. package/fesm2022/ngneers-controls-lazy-cacher.mjs +0 -30
  183. package/fesm2022/ngneers-controls-lazy-cacher.mjs.map +0 -1
  184. package/fesm2022/ngneers-controls-text-field.mjs +0 -23
  185. package/fesm2022/ngneers-controls-text-field.mjs.map +0 -1
  186. package/form-field/index.d.ts +0 -19
  187. package/icon/index.d.ts +0 -30
  188. package/lazy-cacher/index.d.ts +0 -14
  189. package/list-box/index.d.ts +0 -58
  190. package/popover/index.d.ts +0 -41
  191. package/scroller/index.d.ts +0 -95
  192. package/select/index.d.ts +0 -86
  193. package/text-field/index.d.ts +0 -10
  194. package/utils/index.d.ts +0 -36
  195. /package/{index.d.ts → types/ngneers-controls.d.ts} +0 -0
@@ -0,0 +1,516 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { inject, input, booleanAttribute, computed, output, viewChild, effect, ChangeDetectionStrategy, Component } from '@angular/core';
4
+ import { getActiveFilterConditions, executeFilter } from '@ngneers/controls/api';
5
+ import { ValueControlBase, NgnPt, provideSelf } from '@ngneers/controls/base';
6
+ import { NgnButton } from '@ngneers/controls/button';
7
+ import { I18n } from '@ngneers/controls/i18n';
8
+ import { NgnIcon } from '@ngneers/controls/icon';
9
+ import { NgnInput } from '@ngneers/controls/input';
10
+ import { NgnInputField } from '@ngneers/controls/input-field';
11
+ import { NgnPopover } from '@ngneers/controls/popover';
12
+ import { NgnSelect } from '@ngneers/controls/select';
13
+ import { deepMerge, NgnError } from '@ngneers/controls/utils';
14
+ import { filterControlTemplate } from '@ngneers/controls-themes/templates/filter';
15
+
16
+ function defaultOperatorsForType(dataType) {
17
+ switch (dataType) {
18
+ case 'string':
19
+ return [
20
+ { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },
21
+ { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },
22
+ { id: 'contains', labelKey: 'filter_operators_contains', requiresValue: true },
23
+ { id: 'startsWith', labelKey: 'filter_operators_startsWith', requiresValue: true },
24
+ { id: 'endsWith', labelKey: 'filter_operators_endsWith', requiresValue: true },
25
+ { id: 'isEmpty', labelKey: 'filter_operators_isEmpty', requiresValue: false },
26
+ { id: 'isNotEmpty', labelKey: 'filter_operators_isNotEmpty', requiresValue: false },
27
+ ];
28
+ case 'number':
29
+ return [
30
+ { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },
31
+ { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },
32
+ { id: 'greaterThan', labelKey: 'filter_operators_greaterThan', requiresValue: true },
33
+ {
34
+ id: 'greaterThanOrEqual',
35
+ labelKey: 'filter_operators_greaterThanOrEqual',
36
+ requiresValue: true,
37
+ },
38
+ { id: 'lessThan', labelKey: 'filter_operators_lessThan', requiresValue: true },
39
+ {
40
+ id: 'lessThanOrEqual',
41
+ labelKey: 'filter_operators_lessThanOrEqual',
42
+ requiresValue: true,
43
+ },
44
+ ];
45
+ case 'date':
46
+ case 'dateTime':
47
+ return [
48
+ { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },
49
+ { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },
50
+ { id: 'greaterThan', labelKey: 'filter_operators_after', requiresValue: true },
51
+ { id: 'greaterThanOrEqual', labelKey: 'filter_operators_onOrAfter', requiresValue: true },
52
+ { id: 'lessThan', labelKey: 'filter_operators_before', requiresValue: true },
53
+ { id: 'lessThanOrEqual', labelKey: 'filter_operators_onOrBefore', requiresValue: true },
54
+ ];
55
+ case 'boolean':
56
+ return [
57
+ { id: 'isTrue', labelKey: 'filter_operators_isTrue', requiresValue: false },
58
+ { id: 'isFalse', labelKey: 'filter_operators_isFalse', requiresValue: false },
59
+ ];
60
+ case 'custom':
61
+ return [
62
+ { id: 'custom', labelKey: 'filter_operators_custom', requiresValue: true },
63
+ ];
64
+ case 'list':
65
+ return [
66
+ { id: 'in', labelKey: 'filter_operators_in', requiresValue: true },
67
+ ];
68
+ }
69
+ }
70
+ /**
71
+ * @category control
72
+ */
73
+ class NgnFilter extends ValueControlBase {
74
+ theme = this.injectThemeTemplate(filterControlTemplate, 'root');
75
+ i18n = inject(I18n).translations;
76
+ unsafeI18n = inject(I18n).unsafe;
77
+ /** Data to filter. */
78
+ data = input([], ...(ngDevMode ? [{ debugName: "data" }] : []));
79
+ /** Datatype of the values in {@link data}. */
80
+ dataType = input('string', ...(ngDevMode ? [{ debugName: "dataType" }] : []));
81
+ /** Allows multiple conditions and a match mode (any/all). */
82
+ allowMultiple = input(false, { ...(ngDevMode ? { debugName: "allowMultiple" } : {}), transform: booleanAttribute });
83
+ /**
84
+ * Options for `dataType="list"`.
85
+ * When provided, they are used as-is. When `null` or `undefined`, options are derived from {@link data}.
86
+ */
87
+ listOptions = input(...(ngDevMode ? [undefined, { debugName: "listOptions" }] : []));
88
+ /**
89
+ * Controls how the filter is rendered.
90
+ * - `inline`: renders the filter rows directly
91
+ * - `input`: renders an input-like trigger that opens a popover (default)
92
+ * - `headless`: renders only the popover and can be opened programmatically via {@link show}
93
+ */
94
+ mode = input('input', ...(ngDevMode ? [{ debugName: "mode" }] : []));
95
+ /**
96
+ * Popover anchor used only in `headless` mode.
97
+ * In `input` mode the anchor is the internal input-field.
98
+ */
99
+ anchor = input(null, ...(ngDevMode ? [{ debugName: "anchor" }] : []));
100
+ /**
101
+ * When true, the component will filter {@link data} locally and emit the filtered result.
102
+ * When false, only the filter configuration is emitted (useful for server-side filtering).
103
+ */
104
+ filterLocally = input(true, { ...(ngDevMode ? { debugName: "filterLocally" } : {}), transform: booleanAttribute });
105
+ /** Options for the popover (when {@link mode} is not `inline`). */
106
+ popoverOptions = input({}, ...(ngDevMode ? [{ debugName: "popoverOptions" }] : []));
107
+ appliedPopoverOptions = computed(() => deepMerge({
108
+ sizeConstraints: {
109
+ width: '250px',
110
+ minHeight: '200px',
111
+ maxHeight: '500px',
112
+ },
113
+ placement: 'bottom-start',
114
+ }, this.popoverOptions()), ...(ngDevMode ? [{ debugName: "appliedPopoverOptions" }] : []));
115
+ /** Emits whenever the filter configuration changes. */
116
+ filterChange = output();
117
+ /** Emits the filtered data whenever local filtering is enabled. */
118
+ filterResultChange = output();
119
+ _popover = viewChild(NgnPopover, ...(ngDevMode ? [{ debugName: "_popover" }] : []));
120
+ // Note: `value()` is the single source of truth.
121
+ // It can be `null` (cleared). For rendering, use `templateConfig()` which falls back to defaults.
122
+ createCondition(operator) {
123
+ return { operator, rawValue: null };
124
+ }
125
+ defaultConfig() {
126
+ if (this.dataType() === 'list') {
127
+ return {
128
+ dataType: 'list',
129
+ matchMode: 'all',
130
+ conditions: [{ operator: 'in', rawValue: null }],
131
+ };
132
+ }
133
+ const firstOp = this.operatorDefs()[0]?.id ?? 'isEqual';
134
+ return {
135
+ dataType: this.dataType(),
136
+ matchMode: this.allowMultiple() ? 'all' : 'all',
137
+ conditions: [
138
+ {
139
+ operator: firstOp,
140
+ rawValue: null,
141
+ },
142
+ ],
143
+ };
144
+ }
145
+ /**
146
+ * Config used for UI rendering.
147
+ * Falls back to a default config when the actual {@link value} is null.
148
+ */
149
+ templateConfig = computed(() => (this.value() ?? this.defaultConfig()), ...(ngDevMode ? [{ debugName: "templateConfig" }] : []));
150
+ templateListSelection = computed(() => {
151
+ const cfg = this.templateConfig();
152
+ if (cfg.dataType !== 'list') {
153
+ return [];
154
+ }
155
+ const raw = cfg.conditions[0]?.rawValue;
156
+ if (!raw) {
157
+ return [];
158
+ }
159
+ try {
160
+ const parsed = JSON.parse(raw);
161
+ return Array.isArray(parsed) ? parsed.map(v => String(v)) : [];
162
+ }
163
+ catch {
164
+ return [];
165
+ }
166
+ }, ...(ngDevMode ? [{ debugName: "templateListSelection" }] : []));
167
+ operatorDefs = computed(() => {
168
+ const dt = this.dataType();
169
+ const defs = defaultOperatorsForType(dt);
170
+ if (dt === 'custom' && defs.length === 1 && defs[0]?.id === 'custom') {
171
+ return defs;
172
+ }
173
+ return defs;
174
+ }, ...(ngDevMode ? [{ debugName: "operatorDefs" }] : []));
175
+ operatorOptions = computed(() => {
176
+ const options = this.operatorDefs().map(op => ({
177
+ label: this.i18n[op.labelKey],
178
+ value: op.id,
179
+ testId: `filter-operator-${op.id}`,
180
+ }));
181
+ return options;
182
+ }, ...(ngDevMode ? [{ debugName: "operatorOptions" }] : []));
183
+ autoListOptions = computed(() => {
184
+ const seen = new Set();
185
+ const items = [];
186
+ for (const raw of this.data()) {
187
+ const s = String(raw);
188
+ if (seen.has(s)) {
189
+ continue;
190
+ }
191
+ seen.add(s);
192
+ items.push({ label: s, value: s, testId: `filter-list-${s}` });
193
+ }
194
+ return items.sort((a, b) => {
195
+ if (typeof a.label === 'string' && typeof b.label === 'string') {
196
+ return a.label.localeCompare(b.label);
197
+ }
198
+ if (typeof a.label === 'function' && typeof b.label === 'function') {
199
+ return a.label().localeCompare(b.label());
200
+ }
201
+ return 0;
202
+ });
203
+ }, ...(ngDevMode ? [{ debugName: "autoListOptions" }] : []));
204
+ resolvedListOptions = computed(() => {
205
+ const listOptions = this.listOptions();
206
+ return listOptions
207
+ ? listOptions.map((opt) => ({
208
+ label: opt,
209
+ value: opt,
210
+ testId: `filter-list-${opt}`,
211
+ }))
212
+ : this.autoListOptions();
213
+ }, ...(ngDevMode ? [{ debugName: "resolvedListOptions" }] : []));
214
+ matchModeOptions = [
215
+ { label: this.i18n['filter_match_all'], value: 'all', testId: 'filter-match-all' },
216
+ { label: this.i18n['filter_match_any'], value: 'any', testId: 'filter-match-any' },
217
+ ];
218
+ inputType = computed(() => {
219
+ switch (this.dataType()) {
220
+ case 'number':
221
+ return 'number';
222
+ case 'date':
223
+ return 'date';
224
+ case 'dateTime':
225
+ return 'datetime-local';
226
+ default:
227
+ return 'text';
228
+ }
229
+ }, ...(ngDevMode ? [{ debugName: "inputType" }] : []));
230
+ summaryText = computed(() => {
231
+ const currentValue = this.value();
232
+ if (!currentValue) {
233
+ return this.i18n['filter_noFilter']();
234
+ }
235
+ if (currentValue.dataType === 'list') {
236
+ const selected = this.templateListSelection();
237
+ if (selected.length === 0) {
238
+ return this.i18n['filter_noFilter']();
239
+ }
240
+ if (selected.length === 1) {
241
+ return selected[0] ?? this.i18n['filter_noFilter']();
242
+ }
243
+ return `${selected.length} ${this.i18n['filter_selected']()}`;
244
+ }
245
+ const active = this.activeConditionConfigs();
246
+ if (active.length === 0) {
247
+ return this.i18n['filter_noFilter']();
248
+ }
249
+ if (active.length === 1) {
250
+ const c = active[0];
251
+ const def = this.operatorDefs().find(d => d.id === c?.operator);
252
+ const operatorLabel = def ? this.i18n._unsafe[def.labelKey]?.() : c?.operator;
253
+ return c?.rawValue == null || c?.rawValue === ''
254
+ ? operatorLabel
255
+ : `${operatorLabel} ${c.rawValue}`;
256
+ }
257
+ const matchLabel = currentValue.matchMode === 'all'
258
+ ? this.i18n['filter_match_all']()
259
+ : this.i18n['filter_match_any']();
260
+ return `${active.length} ${this.i18n['filter_conditions']()} (${matchLabel})`;
261
+ }, ...(ngDevMode ? [{ debugName: "summaryText" }] : []));
262
+ activeConditionConfigs = computed(() => {
263
+ const cfg = this.value();
264
+ if (!cfg || cfg.dataType === 'list') {
265
+ return [];
266
+ }
267
+ const defs = this.operatorDefs();
268
+ const defById = new Map(defs.map(d => [d.id, d]));
269
+ return cfg.conditions.filter(c => {
270
+ const def = defById.get(c.operator);
271
+ const requiresValue = def?.requiresValue ?? true;
272
+ return !requiresValue || (c.rawValue != null && c.rawValue !== '');
273
+ });
274
+ }, ...(ngDevMode ? [{ debugName: "activeConditionConfigs" }] : []));
275
+ activeConditions = computed(() => {
276
+ const cfg = this.value();
277
+ return cfg ? getActiveFilterConditions(cfg) : [];
278
+ }, ...(ngDevMode ? [{ debugName: "activeConditions" }] : []));
279
+ filteredData = computed(() => {
280
+ if (!this.filterLocally()) {
281
+ return this.data();
282
+ }
283
+ const cfg = this.value();
284
+ if (!cfg) {
285
+ return this.data();
286
+ }
287
+ return executeFilter(this.data(), cfg);
288
+ }, ...(ngDevMode ? [{ debugName: "filteredData" }] : []));
289
+ constructor() {
290
+ super();
291
+ effect(() => {
292
+ this.filterChange.emit(this.value() ?? null);
293
+ });
294
+ effect(() => {
295
+ // When local filtering is disabled, do not emit or compute any result.
296
+ if (!this.filterLocally()) {
297
+ return;
298
+ }
299
+ this.filterResultChange.emit(this.filteredData());
300
+ });
301
+ effect(() => {
302
+ if (!this.allowMultiple()) {
303
+ const cfg = this.value();
304
+ if (!cfg || cfg.dataType === 'list') {
305
+ return;
306
+ }
307
+ if (cfg.conditions.length <= 1 && cfg.matchMode === 'all') {
308
+ return;
309
+ }
310
+ this.value.set({
311
+ ...cfg,
312
+ matchMode: 'all',
313
+ conditions: cfg.conditions.slice(0, 1),
314
+ });
315
+ }
316
+ });
317
+ effect(() => {
318
+ const defs = this.operatorDefs();
319
+ const first = defs[0];
320
+ if (!first) {
321
+ throw new NgnError('filter', 'No operators available.');
322
+ }
323
+ // Ensure all conditions use a valid operator
324
+ const defIds = new Set(defs.map(d => d.id));
325
+ const normalizeConditions = (conditions) => {
326
+ let changed = false;
327
+ const next = conditions.map(c => {
328
+ if (defIds.has(c.operator)) {
329
+ return c;
330
+ }
331
+ changed = true;
332
+ return { ...c, operator: first.id, rawValue: null };
333
+ });
334
+ return changed ? next : conditions;
335
+ };
336
+ const cfg = this.value();
337
+ if (!cfg || cfg.dataType === 'list') {
338
+ return;
339
+ }
340
+ const current = cfg.conditions;
341
+ const next = normalizeConditions(current);
342
+ if (next !== current) {
343
+ this.value.set({ ...cfg, conditions: next });
344
+ }
345
+ });
346
+ }
347
+ setMatchMode(value) {
348
+ if (value === 'all' || value === 'any') {
349
+ const cfg = this.templateConfig();
350
+ if (cfg.dataType === 'list') {
351
+ return;
352
+ }
353
+ this.value.set({
354
+ ...cfg,
355
+ matchMode: this.allowMultiple() ? value : 'all',
356
+ });
357
+ }
358
+ }
359
+ operatorRequiresValue(operator) {
360
+ const def = this.operatorDefs().find(d => d.id === operator);
361
+ return def?.requiresValue ?? true;
362
+ }
363
+ setOperator(index, operator) {
364
+ if (!operator) {
365
+ return;
366
+ }
367
+ const cfg = this.templateConfig();
368
+ if (cfg.dataType === 'list') {
369
+ return;
370
+ }
371
+ const next = cfg.conditions.slice();
372
+ const existing = next[index];
373
+ if (!existing) {
374
+ return;
375
+ }
376
+ next[index] = {
377
+ ...existing,
378
+ operator,
379
+ rawValue: this.operatorRequiresValue(operator) ? existing.rawValue : null,
380
+ };
381
+ this.value.set({
382
+ ...cfg,
383
+ matchMode: this.allowMultiple() ? cfg.matchMode : 'all',
384
+ conditions: next,
385
+ });
386
+ }
387
+ setRawValue(index, rawValue) {
388
+ const cfg = this.templateConfig();
389
+ if (cfg.dataType === 'list') {
390
+ return;
391
+ }
392
+ const next = cfg.conditions.slice();
393
+ const existing = next[index];
394
+ if (!existing) {
395
+ return;
396
+ }
397
+ next[index] = { ...existing, rawValue };
398
+ this.value.set({
399
+ ...cfg,
400
+ matchMode: this.allowMultiple() ? cfg.matchMode : 'all',
401
+ conditions: next,
402
+ });
403
+ }
404
+ addCondition() {
405
+ if (!this.allowMultiple()) {
406
+ return;
407
+ }
408
+ const cfg = this.templateConfig();
409
+ if (cfg.dataType === 'list') {
410
+ return;
411
+ }
412
+ const firstOp = this.operatorDefs()[0]?.id ?? 'isEqual';
413
+ this.value.set({
414
+ ...cfg,
415
+ matchMode: 'all',
416
+ conditions: [...cfg.conditions, this.createCondition(firstOp)],
417
+ });
418
+ }
419
+ removeCondition(index) {
420
+ if (!this.allowMultiple()) {
421
+ return;
422
+ }
423
+ const cfg = this.templateConfig();
424
+ if (cfg.dataType === 'list') {
425
+ return;
426
+ }
427
+ const current = cfg.conditions;
428
+ if (current.length <= 1) {
429
+ return;
430
+ }
431
+ const next = current.slice();
432
+ next.splice(index, 1);
433
+ this.value.set({
434
+ ...cfg,
435
+ matchMode: cfg.matchMode,
436
+ conditions: next,
437
+ });
438
+ }
439
+ setListSelection(value) {
440
+ const arr = Array.isArray(value)
441
+ ? value.map(v => String(v))
442
+ : value == null
443
+ ? []
444
+ : [String(value)];
445
+ this.value.set({
446
+ dataType: 'list',
447
+ matchMode: 'all',
448
+ conditions: [
449
+ {
450
+ operator: 'in',
451
+ rawValue: arr.length > 0 ? JSON.stringify(arr) : null,
452
+ },
453
+ ],
454
+ });
455
+ }
456
+ clear() {
457
+ this.value.set(null);
458
+ if (this.mode() !== 'inline') {
459
+ this.hide();
460
+ }
461
+ }
462
+ /** Shows the filter popup. Only works when {@link mode} is not `inline`. */
463
+ show() {
464
+ if (this.mode() === 'inline') {
465
+ throw new NgnError('filter', 'Cannot open an inline filter.');
466
+ }
467
+ if (this.mode() === 'headless' && !this.anchor()) {
468
+ throw new NgnError('filter', 'Headless mode requires an [anchor] input.');
469
+ }
470
+ const popover = this._popover();
471
+ if (!popover) {
472
+ throw new NgnError('filter', 'Popover is not available.');
473
+ }
474
+ popover.show();
475
+ }
476
+ /** Hides the filter popup. Only works when {@link mode} is not `inline`. */
477
+ hide() {
478
+ if (this.mode() === 'inline') {
479
+ throw new NgnError('filter', 'Cannot close an inline filter.');
480
+ }
481
+ this._popover()?.hide();
482
+ }
483
+ onKeyDown(event) {
484
+ if (event.key === 'Enter') {
485
+ if (this.mode() !== 'inline') {
486
+ this._popover()?.toggle();
487
+ event.stopPropagation();
488
+ event.preventDefault();
489
+ }
490
+ }
491
+ }
492
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnFilter, deps: [], target: i0.ɵɵFactoryTarget.Component });
493
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: NgnFilter, isStandalone: true, selector: "ngn-filter", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, allowMultiple: { classPropertyName: "allowMultiple", publicName: "allowMultiple", isSignal: true, isRequired: false, transformFunction: null }, listOptions: { classPropertyName: "listOptions", publicName: "listOptions", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, filterLocally: { classPropertyName: "filterLocally", publicName: "filterLocally", isSignal: true, isRequired: false, transformFunction: null }, popoverOptions: { classPropertyName: "popoverOptions", publicName: "popoverOptions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filterChange: "filterChange", filterResultChange: "filterResultChange" }, host: { styleAttribute: "display: block;" }, providers: [provideSelf(NgnFilter)], viewQueries: [{ propertyName: "_popover", first: true, predicate: NgnPopover, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #rowsTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'rows'\">\r\n @if (dataType() === 'list') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" data-testid=\"filter-row-list\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'value'\"\r\n [multiple]=\"true\"\r\n [options]=\"resolvedListOptions()\"\r\n [value]=\"$any(templateListSelection())\"\r\n (valueChange)=\"setListSelection($event)\"\r\n />\r\n </div>\r\n } @else {\r\n @for (c of templateConfig().conditions; track $index; let i = $index) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" [attr.data-testid]=\"'filter-row-' + i\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'operator'\"\r\n [options]=\"operatorOptions()\"\r\n [value]=\"c.operator\"\r\n (valueChange)=\"setOperator(i, $event)\"\r\n />\r\n @if (operatorRequiresValue(c.operator)) {\r\n <ngn-input-field [ptInt]=\"this\" [ptClass]=\"'value'\">\r\n <input\r\n ngnInput\r\n [type]=\"inputType()\"\r\n [value]=\"c.rawValue || ''\"\r\n (valueChange)=\"setRawValue(i, $event)\"\r\n />\r\n </ngn-input-field>\r\n }\r\n\r\n @if (allowMultiple() && templateConfig().conditions.length > 1) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row-actions'\">\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n [kind]=\"'text'\"\r\n [color]=\"'error'\"\r\n (click)=\"removeCondition(i)\"\r\n >\r\n {{ i18n['filter_removeCondition']() + ' ' + (i + 1) }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #matchModeTemplate>\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'match'\"\r\n [options]=\"matchModeOptions\"\r\n [value]=\"templateConfig().matchMode\"\r\n (valueChange)=\"setMatchMode($event)\"\r\n data-testid=\"filter-match-mode\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #footerTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'footer'\">\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n kind=\"secondary\"\r\n (click)=\"addCondition()\"\r\n data-testid=\"filter-add-rule\"\r\n >\r\n <span aria-hidden=\"true\">+</span>\r\n {{ i18n['filter_addCondition']() }}\r\n </button>\r\n }\r\n <button type=\"button\" ngnButton kind=\"secondary\" (click)=\"clear()\" data-testid=\"filter-clear\">\r\n {{ i18n['filter_clear']() }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #popoverTemplate let-anchor=\"anchor\">\r\n <ngn-popover\r\n #popover\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"anchor\"\r\n [hasShrinkableContent]=\"true\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [id]=\"inputId() + '_popover'\"\r\n >\r\n <ng-template #lazy>\r\n <div [ptInt]=\"this\" [ptClass]=\"'popover-content'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n </ng-template>\r\n </ngn-popover>\r\n</ng-template>\r\n\r\n@if (mode() === 'inline') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'inline'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n} @else if (mode() === 'input') {\r\n <ngn-input-field\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'input-field'\"\r\n (click)=\"show()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n #field\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n [invalid]=\"invalid()\"\r\n >\r\n <div role=\"button\" [ptInt]=\"this\" [ptClass]=\"'summary'\">{{ summaryText() }}</div>\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" defaultIcon=\"magnifying_glass\" />\r\n </ngn-input-field>\r\n\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: field.element.nativeElement }\"\r\n />\r\n} @else {\r\n @if (anchor()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: anchor() }\"\r\n />\r\n }\r\n}\r\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NgnInputField, selector: "ngn-input-field", inputs: ["label", "labelledBy", "labelKind", "inputId", "showClearButton", "iconClearButton", "tabindex", "invalid", "readonly", "disabled"] }, { kind: "directive", type: NgnInput, selector: "input[ngnInput], textarea[ngnInput]", inputs: ["invalid", "value"], outputs: ["valueChange"] }, { kind: "component", type: NgnSelect, selector: "ngn-select", inputs: ["popoverOptions", "options", "filter", "filterText", "filterIcon", "dropdownIcon", "virtual", "itemHeight", "editable", "editableAutoFilter", "multiple", "scrollToSelectedItemOnOpen", "tabindex", "checkbox"] }, { kind: "component", type: NgnPopover, selector: "ngn-popover", inputs: ["open", "anchor", "options", "hasShrinkableContent", "closeBy"], outputs: ["closed", "closing", "openChange"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "directive", type: NgnButton, selector: "button[ngnButton], a[ngnButton]", inputs: ["inline"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
494
+ }
495
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnFilter, decorators: [{
496
+ type: Component,
497
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-filter', imports: [
498
+ NgnPt,
499
+ NgTemplateOutlet,
500
+ NgnInputField,
501
+ NgnInput,
502
+ NgnSelect,
503
+ NgnPopover,
504
+ NgnIcon,
505
+ NgnButton,
506
+ ], providers: [provideSelf(NgnFilter)], host: {
507
+ style: 'display: block;',
508
+ }, template: "<ng-template #rowsTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'rows'\">\r\n @if (dataType() === 'list') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" data-testid=\"filter-row-list\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'value'\"\r\n [multiple]=\"true\"\r\n [options]=\"resolvedListOptions()\"\r\n [value]=\"$any(templateListSelection())\"\r\n (valueChange)=\"setListSelection($event)\"\r\n />\r\n </div>\r\n } @else {\r\n @for (c of templateConfig().conditions; track $index; let i = $index) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" [attr.data-testid]=\"'filter-row-' + i\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'operator'\"\r\n [options]=\"operatorOptions()\"\r\n [value]=\"c.operator\"\r\n (valueChange)=\"setOperator(i, $event)\"\r\n />\r\n @if (operatorRequiresValue(c.operator)) {\r\n <ngn-input-field [ptInt]=\"this\" [ptClass]=\"'value'\">\r\n <input\r\n ngnInput\r\n [type]=\"inputType()\"\r\n [value]=\"c.rawValue || ''\"\r\n (valueChange)=\"setRawValue(i, $event)\"\r\n />\r\n </ngn-input-field>\r\n }\r\n\r\n @if (allowMultiple() && templateConfig().conditions.length > 1) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row-actions'\">\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n [kind]=\"'text'\"\r\n [color]=\"'error'\"\r\n (click)=\"removeCondition(i)\"\r\n >\r\n {{ i18n['filter_removeCondition']() + ' ' + (i + 1) }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #matchModeTemplate>\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'match'\"\r\n [options]=\"matchModeOptions\"\r\n [value]=\"templateConfig().matchMode\"\r\n (valueChange)=\"setMatchMode($event)\"\r\n data-testid=\"filter-match-mode\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #footerTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'footer'\">\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n kind=\"secondary\"\r\n (click)=\"addCondition()\"\r\n data-testid=\"filter-add-rule\"\r\n >\r\n <span aria-hidden=\"true\">+</span>\r\n {{ i18n['filter_addCondition']() }}\r\n </button>\r\n }\r\n <button type=\"button\" ngnButton kind=\"secondary\" (click)=\"clear()\" data-testid=\"filter-clear\">\r\n {{ i18n['filter_clear']() }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #popoverTemplate let-anchor=\"anchor\">\r\n <ngn-popover\r\n #popover\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"anchor\"\r\n [hasShrinkableContent]=\"true\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [id]=\"inputId() + '_popover'\"\r\n >\r\n <ng-template #lazy>\r\n <div [ptInt]=\"this\" [ptClass]=\"'popover-content'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n </ng-template>\r\n </ngn-popover>\r\n</ng-template>\r\n\r\n@if (mode() === 'inline') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'inline'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n} @else if (mode() === 'input') {\r\n <ngn-input-field\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'input-field'\"\r\n (click)=\"show()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n #field\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n [invalid]=\"invalid()\"\r\n >\r\n <div role=\"button\" [ptInt]=\"this\" [ptClass]=\"'summary'\">{{ summaryText() }}</div>\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" defaultIcon=\"magnifying_glass\" />\r\n </ngn-input-field>\r\n\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: field.element.nativeElement }\"\r\n />\r\n} @else {\r\n @if (anchor()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: anchor() }\"\r\n />\r\n }\r\n}\r\n" }]
509
+ }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], dataType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataType", required: false }] }], allowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowMultiple", required: false }] }], listOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "listOptions", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], filterLocally: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterLocally", required: false }] }], popoverOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "popoverOptions", required: false }] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }], filterResultChange: [{ type: i0.Output, args: ["filterResultChange"] }], _popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => NgnPopover), { isSignal: true }] }] } });
510
+
511
+ /**
512
+ * Generated bundle index. Do not edit.
513
+ */
514
+
515
+ export { NgnFilter };
516
+ //# sourceMappingURL=ngneers-controls-filter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-filter.mjs","sources":["../../src/filter/filter.ts","../../src/filter/filter.html","../../src/filter/ngneers-controls-filter.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n booleanAttribute,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { executeFilter, getActiveFilterConditions, type NgnItem } from '@ngneers/controls/api';\r\nimport { NgnPt, provideSelf, ValueControlBase } from '@ngneers/controls/base';\r\nimport { NgnButton } from '@ngneers/controls/button';\r\nimport { I18n } from '@ngneers/controls/i18n';\r\nimport { NgnIcon } from '@ngneers/controls/icon';\r\nimport { NgnInput } from '@ngneers/controls/input';\r\nimport { NgnInputField } from '@ngneers/controls/input-field';\r\nimport { NgnPopover, type PopoverOptions } from '@ngneers/controls/popover';\r\nimport { NgnSelect } from '@ngneers/controls/select';\r\nimport { deepMerge, NgnError } from '@ngneers/controls/utils';\r\nimport { filterControlTemplate } from '@ngneers/controls-themes/templates/filter';\r\n\r\nimport type {\r\n NgnFilterCondition,\r\n NgnFilterConditionConfig,\r\n NgnFilterConfig,\r\n NgnFilterDataType,\r\n NgnFilterMode,\r\n NgnFilterOperatorId,\r\n} from './types';\r\nimport type { Anchor } from '@ngneers/controls/api/ng';\r\n\r\ntype ConditionInternal = {\r\n operator: NgnFilterOperatorId;\r\n rawValue: string | null;\r\n};\r\n\r\ntype OperatorDef = {\r\n id: NgnFilterOperatorId;\r\n labelKey: string;\r\n requiresValue: boolean;\r\n};\r\n\r\nfunction defaultOperatorsForType(dataType: NgnFilterDataType) {\r\n switch (dataType) {\r\n case 'string':\r\n return [\r\n { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },\r\n { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },\r\n { id: 'contains', labelKey: 'filter_operators_contains', requiresValue: true },\r\n { id: 'startsWith', labelKey: 'filter_operators_startsWith', requiresValue: true },\r\n { id: 'endsWith', labelKey: 'filter_operators_endsWith', requiresValue: true },\r\n { id: 'isEmpty', labelKey: 'filter_operators_isEmpty', requiresValue: false },\r\n { id: 'isNotEmpty', labelKey: 'filter_operators_isNotEmpty', requiresValue: false },\r\n ] as const satisfies OperatorDef[];\r\n case 'number':\r\n return [\r\n { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },\r\n { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },\r\n { id: 'greaterThan', labelKey: 'filter_operators_greaterThan', requiresValue: true },\r\n {\r\n id: 'greaterThanOrEqual',\r\n labelKey: 'filter_operators_greaterThanOrEqual',\r\n requiresValue: true,\r\n },\r\n { id: 'lessThan', labelKey: 'filter_operators_lessThan', requiresValue: true },\r\n {\r\n id: 'lessThanOrEqual',\r\n labelKey: 'filter_operators_lessThanOrEqual',\r\n requiresValue: true,\r\n },\r\n ] as const satisfies OperatorDef[];\r\n case 'date':\r\n case 'dateTime':\r\n return [\r\n { id: 'isEqual', labelKey: 'filter_operators_isEqual', requiresValue: true },\r\n { id: 'isNotEqual', labelKey: 'filter_operators_isNotEqual', requiresValue: true },\r\n { id: 'greaterThan', labelKey: 'filter_operators_after', requiresValue: true },\r\n { id: 'greaterThanOrEqual', labelKey: 'filter_operators_onOrAfter', requiresValue: true },\r\n { id: 'lessThan', labelKey: 'filter_operators_before', requiresValue: true },\r\n { id: 'lessThanOrEqual', labelKey: 'filter_operators_onOrBefore', requiresValue: true },\r\n ] as const satisfies OperatorDef[];\r\n case 'boolean':\r\n return [\r\n { id: 'isTrue', labelKey: 'filter_operators_isTrue', requiresValue: false },\r\n { id: 'isFalse', labelKey: 'filter_operators_isFalse', requiresValue: false },\r\n ] as const satisfies OperatorDef[];\r\n case 'custom':\r\n return [\r\n { id: 'custom', labelKey: 'filter_operators_custom', requiresValue: true },\r\n ] as const satisfies OperatorDef[];\r\n case 'list':\r\n return [\r\n { id: 'in', labelKey: 'filter_operators_in', requiresValue: true },\r\n ] as const satisfies OperatorDef[];\r\n }\r\n}\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-filter',\r\n templateUrl: './filter.html',\r\n imports: [\r\n NgnPt,\r\n NgTemplateOutlet,\r\n NgnInputField,\r\n NgnInput,\r\n NgnSelect,\r\n NgnPopover,\r\n NgnIcon,\r\n NgnButton,\r\n ],\r\n providers: [provideSelf(NgnFilter)],\r\n host: {\r\n style: 'display: block;',\r\n },\r\n})\r\nexport class NgnFilter<T = unknown> extends ValueControlBase<'filter', NgnFilterConfig | null> {\r\n protected readonly theme = this.injectThemeTemplate(filterControlTemplate, 'root');\r\n protected readonly i18n = inject(I18n).translations;\r\n protected readonly unsafeI18n = inject(I18n).unsafe;\r\n\r\n /** Data to filter. */\r\n public readonly data = input<readonly T[]>([]);\r\n /** Datatype of the values in {@link data}. */\r\n public readonly dataType = input<NgnFilterDataType>('string');\r\n /** Allows multiple conditions and a match mode (any/all). */\r\n public readonly allowMultiple = input(false, { transform: booleanAttribute });\r\n\r\n /**\r\n * Options for `dataType=\"list\"`.\r\n * When provided, they are used as-is. When `null` or `undefined`, options are derived from {@link data}.\r\n */\r\n public readonly listOptions = input<readonly string[] | null | undefined>();\r\n\r\n /**\r\n * Controls how the filter is rendered.\r\n * - `inline`: renders the filter rows directly\r\n * - `input`: renders an input-like trigger that opens a popover (default)\r\n * - `headless`: renders only the popover and can be opened programmatically via {@link show}\r\n */\r\n public readonly mode = input<NgnFilterMode>('input');\r\n\r\n /**\r\n * Popover anchor used only in `headless` mode.\r\n * In `input` mode the anchor is the internal input-field.\r\n */\r\n public readonly anchor = input<Anchor | null>(null);\r\n\r\n /**\r\n * When true, the component will filter {@link data} locally and emit the filtered result.\r\n * When false, only the filter configuration is emitted (useful for server-side filtering).\r\n */\r\n public readonly filterLocally = input(true, { transform: booleanAttribute });\r\n\r\n /** Options for the popover (when {@link mode} is not `inline`). */\r\n public readonly popoverOptions = input<PopoverOptions>({});\r\n protected readonly appliedPopoverOptions = computed(() =>\r\n deepMerge(\r\n <PopoverOptions>{\r\n sizeConstraints: {\r\n width: '250px',\r\n minHeight: '200px',\r\n maxHeight: '500px',\r\n },\r\n placement: 'bottom-start',\r\n },\r\n this.popoverOptions()\r\n )\r\n );\r\n\r\n /** Emits whenever the filter configuration changes. */\r\n public readonly filterChange = output<NgnFilterConfig | null>();\r\n /** Emits the filtered data whenever local filtering is enabled. */\r\n public readonly filterResultChange = output<readonly T[]>();\r\n\r\n private readonly _popover = viewChild(NgnPopover);\r\n\r\n // Note: `value()` is the single source of truth.\r\n // It can be `null` (cleared). For rendering, use `templateConfig()` which falls back to defaults.\r\n\r\n private createCondition(operator: NgnFilterOperatorId): ConditionInternal {\r\n return { operator, rawValue: null };\r\n }\r\n\r\n private defaultConfig(): NgnFilterConfig {\r\n if (this.dataType() === 'list') {\r\n return {\r\n dataType: 'list',\r\n matchMode: 'all',\r\n conditions: <readonly NgnFilterConditionConfig[]>[{ operator: 'in', rawValue: null }],\r\n };\r\n }\r\n\r\n const firstOp = this.operatorDefs()[0]?.id ?? 'isEqual';\r\n return {\r\n dataType: this.dataType(),\r\n matchMode: this.allowMultiple() ? 'all' : 'all',\r\n conditions: <readonly NgnFilterConditionConfig[]>[\r\n {\r\n operator: firstOp,\r\n rawValue: null,\r\n },\r\n ],\r\n };\r\n }\r\n\r\n /**\r\n * Config used for UI rendering.\r\n * Falls back to a default config when the actual {@link value} is null.\r\n */\r\n protected readonly templateConfig = computed<NgnFilterConfig>(\r\n () => (this.value() ?? this.defaultConfig()) as NgnFilterConfig\r\n );\r\n\r\n protected readonly templateListSelection = computed<readonly string[]>(() => {\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType !== 'list') {\r\n return [];\r\n }\r\n const raw = cfg.conditions[0]?.rawValue;\r\n if (!raw) {\r\n return [];\r\n }\r\n try {\r\n const parsed: unknown = JSON.parse(raw);\r\n return Array.isArray(parsed) ? parsed.map(v => String(v)) : [];\r\n } catch {\r\n return [];\r\n }\r\n });\r\n\r\n protected readonly operatorDefs = computed(() => {\r\n const dt = this.dataType();\r\n const defs = defaultOperatorsForType(dt);\r\n if (dt === 'custom' && defs.length === 1 && defs[0]?.id === 'custom') {\r\n return defs;\r\n }\r\n return defs;\r\n });\r\n\r\n protected readonly operatorOptions = computed(() => {\r\n const options = this.operatorDefs().map(\r\n op =>\r\n <NgnItem>{\r\n label: this.i18n[op.labelKey],\r\n value: op.id,\r\n testId: `filter-operator-${op.id}`,\r\n }\r\n );\r\n return options;\r\n });\r\n\r\n protected readonly autoListOptions = computed<readonly NgnItem[]>(() => {\r\n const seen = new Set<string>();\r\n const items: Array<NgnItem> = [];\r\n\r\n for (const raw of this.data()) {\r\n const s = String(raw);\r\n if (seen.has(s)) {\r\n continue;\r\n }\r\n seen.add(s);\r\n items.push({ label: s, value: s, testId: `filter-list-${s}` });\r\n }\r\n\r\n return items.sort((a, b) => {\r\n if (typeof a.label === 'string' && typeof b.label === 'string') {\r\n return a.label.localeCompare(b.label);\r\n }\r\n if (typeof a.label === 'function' && typeof b.label === 'function') {\r\n return a.label().localeCompare(b.label());\r\n }\r\n return 0;\r\n });\r\n });\r\n\r\n protected readonly resolvedListOptions = computed<readonly NgnItem[]>(() => {\r\n const listOptions = this.listOptions();\r\n return listOptions\r\n ? listOptions.map(\r\n (opt): NgnItem => ({\r\n label: opt,\r\n value: opt,\r\n testId: `filter-list-${opt}`,\r\n })\r\n )\r\n : this.autoListOptions();\r\n });\r\n\r\n protected readonly matchModeOptions: readonly NgnItem[] = [\r\n { label: this.i18n['filter_match_all'], value: 'all', testId: 'filter-match-all' },\r\n { label: this.i18n['filter_match_any'], value: 'any', testId: 'filter-match-any' },\r\n ];\r\n\r\n protected readonly inputType = computed(() => {\r\n switch (this.dataType()) {\r\n case 'number':\r\n return 'number';\r\n case 'date':\r\n return 'date';\r\n case 'dateTime':\r\n return 'datetime-local';\r\n default:\r\n return 'text';\r\n }\r\n });\r\n\r\n protected readonly summaryText = computed(() => {\r\n const currentValue = this.value();\r\n if (!currentValue) {\r\n return this.i18n['filter_noFilter']();\r\n }\r\n\r\n if (currentValue.dataType === 'list') {\r\n const selected = this.templateListSelection();\r\n if (selected.length === 0) {\r\n return this.i18n['filter_noFilter']();\r\n }\r\n if (selected.length === 1) {\r\n return selected[0] ?? this.i18n['filter_noFilter']();\r\n }\r\n return `${selected.length} ${this.i18n['filter_selected']()}`;\r\n }\r\n\r\n const active = this.activeConditionConfigs();\r\n if (active.length === 0) {\r\n return this.i18n['filter_noFilter']();\r\n }\r\n if (active.length === 1) {\r\n const c = active[0];\r\n\r\n const def = this.operatorDefs().find(d => d.id === c?.operator);\r\n const operatorLabel = def ? this.i18n._unsafe[def.labelKey]?.() : c?.operator;\r\n return c?.rawValue == null || c?.rawValue === ''\r\n ? operatorLabel\r\n : `${operatorLabel} ${c.rawValue}`;\r\n }\r\n\r\n const matchLabel =\r\n currentValue.matchMode === 'all'\r\n ? this.i18n['filter_match_all']()\r\n : this.i18n['filter_match_any']();\r\n return `${active.length} ${this.i18n['filter_conditions']()} (${matchLabel})`;\r\n });\r\n\r\n protected readonly activeConditionConfigs = computed<readonly NgnFilterConditionConfig[]>(() => {\r\n const cfg = this.value();\r\n if (!cfg || cfg.dataType === 'list') {\r\n return [];\r\n }\r\n const defs = this.operatorDefs();\r\n const defById = new Map(defs.map(d => [d.id, d] as const));\r\n\r\n return cfg.conditions.filter(c => {\r\n const def = defById.get(c.operator);\r\n const requiresValue = def?.requiresValue ?? true;\r\n return !requiresValue || (c.rawValue != null && c.rawValue !== '');\r\n });\r\n });\r\n\r\n protected readonly activeConditions = computed<readonly NgnFilterCondition[]>(() => {\r\n const cfg = this.value();\r\n return cfg ? getActiveFilterConditions(cfg) : [];\r\n });\r\n\r\n protected readonly filteredData = computed<readonly T[]>(() => {\r\n if (!this.filterLocally()) {\r\n return this.data();\r\n }\r\n const cfg = this.value();\r\n if (!cfg) {\r\n return this.data();\r\n }\r\n return executeFilter(this.data(), cfg);\r\n });\r\n\r\n constructor() {\r\n super();\r\n\r\n effect(() => {\r\n this.filterChange.emit(this.value() ?? null);\r\n });\r\n\r\n effect(() => {\r\n // When local filtering is disabled, do not emit or compute any result.\r\n if (!this.filterLocally()) {\r\n return;\r\n }\r\n this.filterResultChange.emit(this.filteredData());\r\n });\r\n\r\n effect(() => {\r\n if (!this.allowMultiple()) {\r\n const cfg = this.value();\r\n if (!cfg || cfg.dataType === 'list') {\r\n return;\r\n }\r\n if (cfg.conditions.length <= 1 && cfg.matchMode === 'all') {\r\n return;\r\n }\r\n this.value.set({\r\n ...cfg,\r\n matchMode: 'all',\r\n conditions: cfg.conditions.slice(0, 1),\r\n });\r\n }\r\n });\r\n\r\n effect(() => {\r\n const defs = this.operatorDefs();\r\n const first = defs[0];\r\n if (!first) {\r\n throw new NgnError('filter', 'No operators available.');\r\n }\r\n // Ensure all conditions use a valid operator\r\n const defIds = new Set(defs.map(d => d.id));\r\n\r\n const normalizeConditions = (\r\n conditions: readonly ConditionInternal[]\r\n ): readonly ConditionInternal[] => {\r\n let changed = false;\r\n const next = conditions.map(c => {\r\n if (defIds.has(c.operator)) {\r\n return c;\r\n }\r\n changed = true;\r\n return { ...c, operator: first.id, rawValue: null };\r\n });\r\n return changed ? next : conditions;\r\n };\r\n\r\n const cfg = this.value();\r\n if (!cfg || cfg.dataType === 'list') {\r\n return;\r\n }\r\n\r\n const current = cfg.conditions;\r\n const next = normalizeConditions(current);\r\n if (next !== current) {\r\n this.value.set({ ...cfg, conditions: next });\r\n }\r\n });\r\n }\r\n\r\n protected setMatchMode(value: unknown): void {\r\n if (value === 'all' || value === 'any') {\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType === 'list') {\r\n return;\r\n }\r\n this.value.set({\r\n ...cfg,\r\n matchMode: this.allowMultiple() ? value : 'all',\r\n });\r\n }\r\n }\r\n\r\n protected operatorRequiresValue(operator: NgnFilterOperatorId): boolean {\r\n const def = this.operatorDefs().find(d => d.id === operator);\r\n return def?.requiresValue ?? true;\r\n }\r\n\r\n protected setOperator(index: number, operator: NgnFilterOperatorId | null): void {\r\n if (!operator) {\r\n return;\r\n }\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType === 'list') {\r\n return;\r\n }\r\n const next = cfg.conditions.slice();\r\n const existing = next[index];\r\n if (!existing) {\r\n return;\r\n }\r\n next[index] = {\r\n ...existing,\r\n operator,\r\n rawValue: this.operatorRequiresValue(operator) ? existing.rawValue : null,\r\n };\r\n this.value.set({\r\n ...cfg,\r\n matchMode: this.allowMultiple() ? cfg.matchMode : 'all',\r\n conditions: next,\r\n });\r\n }\r\n\r\n protected setRawValue(index: number, rawValue: string | null): void {\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType === 'list') {\r\n return;\r\n }\r\n const next = cfg.conditions.slice();\r\n const existing = next[index];\r\n if (!existing) {\r\n return;\r\n }\r\n next[index] = { ...existing, rawValue };\r\n this.value.set({\r\n ...cfg,\r\n matchMode: this.allowMultiple() ? cfg.matchMode : 'all',\r\n conditions: next,\r\n });\r\n }\r\n\r\n protected addCondition(): void {\r\n if (!this.allowMultiple()) {\r\n return;\r\n }\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType === 'list') {\r\n return;\r\n }\r\n const firstOp = this.operatorDefs()[0]?.id ?? 'isEqual';\r\n this.value.set({\r\n ...cfg,\r\n matchMode: 'all',\r\n conditions: [...cfg.conditions, this.createCondition(firstOp)],\r\n });\r\n }\r\n\r\n protected removeCondition(index: number): void {\r\n if (!this.allowMultiple()) {\r\n return;\r\n }\r\n const cfg = this.templateConfig();\r\n if (cfg.dataType === 'list') {\r\n return;\r\n }\r\n const current = cfg.conditions;\r\n if (current.length <= 1) {\r\n return;\r\n }\r\n const next = current.slice();\r\n next.splice(index, 1);\r\n this.value.set({\r\n ...cfg,\r\n matchMode: cfg.matchMode,\r\n conditions: next,\r\n });\r\n }\r\n\r\n protected setListSelection(value: unknown): void {\r\n const arr = Array.isArray(value)\r\n ? value.map(v => String(v))\r\n : value == null\r\n ? []\r\n : [String(value)];\r\n\r\n this.value.set({\r\n dataType: 'list',\r\n matchMode: 'all',\r\n conditions: <readonly NgnFilterConditionConfig[]>[\r\n {\r\n operator: 'in',\r\n rawValue: arr.length > 0 ? JSON.stringify(arr) : null,\r\n },\r\n ],\r\n });\r\n }\r\n\r\n protected clear(): void {\r\n this.value.set(null);\r\n if (this.mode() !== 'inline') {\r\n this.hide();\r\n }\r\n }\r\n\r\n /** Shows the filter popup. Only works when {@link mode} is not `inline`. */\r\n public show(): void {\r\n if (this.mode() === 'inline') {\r\n throw new NgnError('filter', 'Cannot open an inline filter.');\r\n }\r\n if (this.mode() === 'headless' && !this.anchor()) {\r\n throw new NgnError('filter', 'Headless mode requires an [anchor] input.');\r\n }\r\n const popover = this._popover();\r\n if (!popover) {\r\n throw new NgnError('filter', 'Popover is not available.');\r\n }\r\n popover.show();\r\n }\r\n\r\n /** Hides the filter popup. Only works when {@link mode} is not `inline`. */\r\n public hide(): void {\r\n if (this.mode() === 'inline') {\r\n throw new NgnError('filter', 'Cannot close an inline filter.');\r\n }\r\n this._popover()?.hide();\r\n }\r\n\r\n protected onKeyDown(event: KeyboardEvent): void {\r\n if (event.key === 'Enter') {\r\n if (this.mode() !== 'inline') {\r\n this._popover()?.toggle();\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n }\r\n }\r\n}\r\n","<ng-template #rowsTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'rows'\">\r\n @if (dataType() === 'list') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" data-testid=\"filter-row-list\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'value'\"\r\n [multiple]=\"true\"\r\n [options]=\"resolvedListOptions()\"\r\n [value]=\"$any(templateListSelection())\"\r\n (valueChange)=\"setListSelection($event)\"\r\n />\r\n </div>\r\n } @else {\r\n @for (c of templateConfig().conditions; track $index; let i = $index) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row'\" [attr.data-testid]=\"'filter-row-' + i\">\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'operator'\"\r\n [options]=\"operatorOptions()\"\r\n [value]=\"c.operator\"\r\n (valueChange)=\"setOperator(i, $event)\"\r\n />\r\n @if (operatorRequiresValue(c.operator)) {\r\n <ngn-input-field [ptInt]=\"this\" [ptClass]=\"'value'\">\r\n <input\r\n ngnInput\r\n [type]=\"inputType()\"\r\n [value]=\"c.rawValue || ''\"\r\n (valueChange)=\"setRawValue(i, $event)\"\r\n />\r\n </ngn-input-field>\r\n }\r\n\r\n @if (allowMultiple() && templateConfig().conditions.length > 1) {\r\n <div [ptInt]=\"this\" [ptClass]=\"'row-actions'\">\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n [kind]=\"'text'\"\r\n [color]=\"'error'\"\r\n (click)=\"removeCondition(i)\"\r\n >\r\n {{ i18n['filter_removeCondition']() + ' ' + (i + 1) }}\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n }\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #matchModeTemplate>\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <ngn-select\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'match'\"\r\n [options]=\"matchModeOptions\"\r\n [value]=\"templateConfig().matchMode\"\r\n (valueChange)=\"setMatchMode($event)\"\r\n data-testid=\"filter-match-mode\"\r\n />\r\n }\r\n</ng-template>\r\n\r\n<ng-template #footerTemplate>\r\n <div [ptInt]=\"this\" [ptClass]=\"'footer'\">\r\n @if (dataType() !== 'list' && allowMultiple()) {\r\n <button\r\n type=\"button\"\r\n ngnButton\r\n kind=\"secondary\"\r\n (click)=\"addCondition()\"\r\n data-testid=\"filter-add-rule\"\r\n >\r\n <span aria-hidden=\"true\">+</span>\r\n {{ i18n['filter_addCondition']() }}\r\n </button>\r\n }\r\n <button type=\"button\" ngnButton kind=\"secondary\" (click)=\"clear()\" data-testid=\"filter-clear\">\r\n {{ i18n['filter_clear']() }}\r\n </button>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #popoverTemplate let-anchor=\"anchor\">\r\n <ngn-popover\r\n #popover\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"anchor\"\r\n [hasShrinkableContent]=\"true\"\r\n (keydown)=\"onKeyDown($event)\"\r\n [id]=\"inputId() + '_popover'\"\r\n >\r\n <ng-template #lazy>\r\n <div [ptInt]=\"this\" [ptClass]=\"'popover-content'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n </ng-template>\r\n </ngn-popover>\r\n</ng-template>\r\n\r\n@if (mode() === 'inline') {\r\n <div [ptInt]=\"this\" [ptClass]=\"'inline'\">\r\n <ng-container [ngTemplateOutlet]=\"matchModeTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"rowsTemplate\" />\r\n <ng-container [ngTemplateOutlet]=\"footerTemplate\" />\r\n </div>\r\n} @else if (mode() === 'input') {\r\n <ngn-input-field\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'input-field'\"\r\n (click)=\"show()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n #field\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n [invalid]=\"invalid()\"\r\n >\r\n <div role=\"button\" [ptInt]=\"this\" [ptClass]=\"'summary'\">{{ summaryText() }}</div>\r\n <ngn-icon [ptInt]=\"this\" [ptClass]=\"'icon'\" defaultIcon=\"magnifying_glass\" />\r\n </ngn-input-field>\r\n\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: field.element.nativeElement }\"\r\n />\r\n} @else {\r\n @if (anchor()) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"popoverTemplate\"\r\n [ngTemplateOutletContext]=\"{ anchor: anchor() }\"\r\n />\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}