@kopexa/filter 0.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 (51) hide show
  1. package/LICENSE +201 -0
  2. package/dist/chunk-3WNAREG6.mjs +29 -0
  3. package/dist/chunk-63P4ITVP.mjs +263 -0
  4. package/dist/chunk-7KY2PDNL.mjs +136 -0
  5. package/dist/chunk-7QP7FRID.mjs +47 -0
  6. package/dist/chunk-EF4VI36D.mjs +36 -0
  7. package/dist/chunk-I3Z2T4N2.mjs +14 -0
  8. package/dist/chunk-PTJ7HZPA.mjs +164 -0
  9. package/dist/chunk-TBHYZZSX.mjs +139 -0
  10. package/dist/chunk-URDCG5NI.mjs +111 -0
  11. package/dist/filter-active.d.mts +13 -0
  12. package/dist/filter-active.d.ts +13 -0
  13. package/dist/filter-active.js +538 -0
  14. package/dist/filter-active.mjs +12 -0
  15. package/dist/filter-context.d.mts +28 -0
  16. package/dist/filter-context.d.ts +28 -0
  17. package/dist/filter-context.js +39 -0
  18. package/dist/filter-context.mjs +10 -0
  19. package/dist/filter-i18n.d.mts +20 -0
  20. package/dist/filter-i18n.d.ts +20 -0
  21. package/dist/filter-i18n.js +52 -0
  22. package/dist/filter-i18n.mjs +7 -0
  23. package/dist/filter-menu.d.mts +65 -0
  24. package/dist/filter-menu.d.ts +65 -0
  25. package/dist/filter-menu.js +169 -0
  26. package/dist/filter-menu.mjs +15 -0
  27. package/dist/filter-trigger.d.mts +14 -0
  28. package/dist/filter-trigger.d.ts +14 -0
  29. package/dist/filter-trigger.js +170 -0
  30. package/dist/filter-trigger.mjs +10 -0
  31. package/dist/filter-types.d.mts +60 -0
  32. package/dist/filter-types.d.ts +60 -0
  33. package/dist/filter-types.js +72 -0
  34. package/dist/filter-types.mjs +11 -0
  35. package/dist/filter-value-editor.d.mts +11 -0
  36. package/dist/filter-value-editor.d.ts +11 -0
  37. package/dist/filter-value-editor.js +414 -0
  38. package/dist/filter-value-editor.mjs +11 -0
  39. package/dist/filter.d.mts +24 -0
  40. package/dist/filter.d.ts +24 -0
  41. package/dist/filter.js +242 -0
  42. package/dist/filter.mjs +11 -0
  43. package/dist/index.d.mts +13 -0
  44. package/dist/index.d.ts +13 -0
  45. package/dist/index.js +909 -0
  46. package/dist/index.mjs +39 -0
  47. package/dist/messages.d.mts +104 -0
  48. package/dist/messages.d.ts +104 -0
  49. package/dist/messages.js +134 -0
  50. package/dist/messages.mjs +7 -0
  51. package/package.json +69 -0
@@ -0,0 +1,538 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/filter-active.tsx
23
+ var filter_active_exports = {};
24
+ __export(filter_active_exports, {
25
+ FilterActive: () => FilterActive
26
+ });
27
+ module.exports = __toCommonJS(filter_active_exports);
28
+ var import_i18n3 = require("@kopexa/i18n");
29
+ var import_icons = require("@kopexa/icons");
30
+ var import_popover = require("@kopexa/popover");
31
+ var import_shared_utils = require("@kopexa/shared-utils");
32
+
33
+ // src/filter-context.tsx
34
+ var import_react_utils = require("@kopexa/react-utils");
35
+ var [FilterProvider, useFilterContext] = (0, import_react_utils.createContext)({
36
+ name: "FilterContext",
37
+ strict: true,
38
+ errorMessage: "useFilterContext must be used within a Filter component. Make sure to wrap your FilterMenu, FilterTrigger, etc. inside a <Filter> component."
39
+ });
40
+
41
+ // src/filter-value-editor.tsx
42
+ var import_checkbox = require("@kopexa/checkbox");
43
+ var import_i18n2 = require("@kopexa/i18n");
44
+ var import_input = require("@kopexa/input");
45
+ var import_select = require("@kopexa/select");
46
+
47
+ // src/filter-types.ts
48
+ var DEFAULT_OPERATORS = {
49
+ text: [
50
+ "equals",
51
+ "not_equals",
52
+ "contains",
53
+ "not_contains",
54
+ "starts_with",
55
+ "ends_with",
56
+ "is_empty",
57
+ "is_not_empty"
58
+ ],
59
+ number: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
60
+ select: ["equals", "not_equals", "is_empty", "is_not_empty"],
61
+ multiselect: ["equals", "not_equals", "is_empty", "is_not_empty"],
62
+ date: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
63
+ daterange: ["between"],
64
+ boolean: ["equals"]
65
+ };
66
+
67
+ // src/messages.ts
68
+ var import_i18n = require("@kopexa/i18n");
69
+ var messages = (0, import_i18n.defineMessages)({
70
+ add_filter: {
71
+ id: "filter.add_filter",
72
+ defaultMessage: "Add Filter",
73
+ description: "Button text for adding a new filter"
74
+ },
75
+ clear_all: {
76
+ id: "filter.clear_all",
77
+ defaultMessage: "Clear all",
78
+ description: "Button text for clearing all filters"
79
+ },
80
+ no_fields: {
81
+ id: "filter.no_fields",
82
+ defaultMessage: "No filter options available",
83
+ description: "Message when no filter fields are configured"
84
+ },
85
+ apply: {
86
+ id: "filter.apply",
87
+ defaultMessage: "Apply",
88
+ description: "Button text for applying a filter value"
89
+ },
90
+ cancel: {
91
+ id: "filter.cancel",
92
+ defaultMessage: "Cancel",
93
+ description: "Button text for canceling filter editing"
94
+ },
95
+ select_value: {
96
+ id: "filter.select_value",
97
+ defaultMessage: "Select value...",
98
+ description: "Placeholder for value selection"
99
+ },
100
+ enter_value: {
101
+ id: "filter.enter_value",
102
+ defaultMessage: "Enter value...",
103
+ description: "Placeholder for value input"
104
+ },
105
+ // Operators
106
+ op_equals: {
107
+ id: "filter.operator.equals",
108
+ defaultMessage: "is",
109
+ description: "Operator: equals"
110
+ },
111
+ op_not_equals: {
112
+ id: "filter.operator.not_equals",
113
+ defaultMessage: "is not",
114
+ description: "Operator: not equals"
115
+ },
116
+ op_contains: {
117
+ id: "filter.operator.contains",
118
+ defaultMessage: "contains",
119
+ description: "Operator: contains"
120
+ },
121
+ op_not_contains: {
122
+ id: "filter.operator.not_contains",
123
+ defaultMessage: "does not contain",
124
+ description: "Operator: does not contain"
125
+ },
126
+ op_starts_with: {
127
+ id: "filter.operator.starts_with",
128
+ defaultMessage: "starts with",
129
+ description: "Operator: starts with"
130
+ },
131
+ op_ends_with: {
132
+ id: "filter.operator.ends_with",
133
+ defaultMessage: "ends with",
134
+ description: "Operator: ends with"
135
+ },
136
+ op_gt: {
137
+ id: "filter.operator.gt",
138
+ defaultMessage: "greater than",
139
+ description: "Operator: greater than"
140
+ },
141
+ op_lt: {
142
+ id: "filter.operator.lt",
143
+ defaultMessage: "less than",
144
+ description: "Operator: less than"
145
+ },
146
+ op_gte: {
147
+ id: "filter.operator.gte",
148
+ defaultMessage: "greater or equal",
149
+ description: "Operator: greater than or equal"
150
+ },
151
+ op_lte: {
152
+ id: "filter.operator.lte",
153
+ defaultMessage: "less or equal",
154
+ description: "Operator: less than or equal"
155
+ },
156
+ op_between: {
157
+ id: "filter.operator.between",
158
+ defaultMessage: "between",
159
+ description: "Operator: between"
160
+ },
161
+ op_is_empty: {
162
+ id: "filter.operator.is_empty",
163
+ defaultMessage: "is empty",
164
+ description: "Operator: is empty"
165
+ },
166
+ op_is_not_empty: {
167
+ id: "filter.operator.is_not_empty",
168
+ defaultMessage: "is not empty",
169
+ description: "Operator: is not empty"
170
+ }
171
+ });
172
+
173
+ // src/filter-value-editor.tsx
174
+ var import_jsx_runtime = require("react/jsx-runtime");
175
+ function FilterValueEditor({ filter, field }) {
176
+ var _a;
177
+ const { styles, updateFilter, setEditingFilterId } = useFilterContext();
178
+ const t = (0, import_i18n2.useSafeIntl)();
179
+ const operators = (_a = field.operators) != null ? _a : DEFAULT_OPERATORS[field.type];
180
+ const handleOperatorChange = (newOperator) => {
181
+ updateFilter(filter.id, { operator: newOperator });
182
+ if (newOperator === "is_empty" || newOperator === "is_not_empty") {
183
+ setEditingFilterId(null);
184
+ }
185
+ };
186
+ const handleValueChange = (newValue) => {
187
+ updateFilter(filter.id, { value: newValue });
188
+ };
189
+ const handleSelectValue = (newValue) => {
190
+ updateFilter(filter.id, { value: newValue });
191
+ setEditingFilterId(null);
192
+ };
193
+ const getOperatorLabel = (op) => {
194
+ const key = `op_${op}`;
195
+ return messages[key] ? t.formatMessage(messages[key]) : op;
196
+ };
197
+ const needsValue = filter.operator !== "is_empty" && filter.operator !== "is_not_empty";
198
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-slot": "filter-value-editor", children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorHeader(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.editorTitle(), children: field.label }) }),
200
+ operators.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorOperator(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
201
+ import_select.Select,
202
+ {
203
+ value: filter.operator,
204
+ onValueChange: (val) => handleOperatorChange(val),
205
+ size: "sm",
206
+ children: [
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Trigger, { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Value, {}) }),
208
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Content, { children: operators.map((op) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Item, { value: op, children: getOperatorLabel(op) }, op)) })
209
+ ]
210
+ }
211
+ ) }),
212
+ needsValue && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorInput(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
213
+ ValueInput,
214
+ {
215
+ field,
216
+ operator: filter.operator,
217
+ value: filter.value,
218
+ onChange: handleValueChange,
219
+ onSelect: handleSelectValue
220
+ }
221
+ ) })
222
+ ] });
223
+ }
224
+ function ValueInput({
225
+ field,
226
+ operator,
227
+ value,
228
+ onChange,
229
+ onSelect
230
+ }) {
231
+ var _a, _b, _c, _d, _e, _f;
232
+ const t = (0, import_i18n2.useSafeIntl)();
233
+ switch (field.type) {
234
+ case "text":
235
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
236
+ import_input.Input,
237
+ {
238
+ value: String(value != null ? value : ""),
239
+ onChange: (e) => onChange(e.target.value),
240
+ placeholder: (_a = field.placeholder) != null ? _a : t.formatMessage(messages.enter_value),
241
+ size: "sm",
242
+ autoFocus: true
243
+ }
244
+ );
245
+ case "number":
246
+ if (operator === "between") {
247
+ const [min, max] = Array.isArray(value) ? value : [void 0, void 0];
248
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
249
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
250
+ import_input.Input,
251
+ {
252
+ type: "number",
253
+ value: min != null ? min : "",
254
+ onChange: (e) => onChange([
255
+ e.target.value ? Number(e.target.value) : void 0,
256
+ max
257
+ ]),
258
+ placeholder: "Min",
259
+ min: field.min,
260
+ max: field.max,
261
+ step: field.step,
262
+ size: "sm",
263
+ autoFocus: true
264
+ }
265
+ ),
266
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "-" }),
267
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
268
+ import_input.Input,
269
+ {
270
+ type: "number",
271
+ value: max != null ? max : "",
272
+ onChange: (e) => onChange([
273
+ min,
274
+ e.target.value ? Number(e.target.value) : void 0
275
+ ]),
276
+ placeholder: "Max",
277
+ min: field.min,
278
+ max: field.max,
279
+ step: field.step,
280
+ size: "sm"
281
+ }
282
+ )
283
+ ] });
284
+ }
285
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
286
+ import_input.Input,
287
+ {
288
+ type: "number",
289
+ value: value !== void 0 && value !== null ? String(value) : "",
290
+ onChange: (e) => onChange(e.target.value ? Number(e.target.value) : void 0),
291
+ placeholder: (_b = field.placeholder) != null ? _b : t.formatMessage(messages.enter_value),
292
+ min: field.min,
293
+ max: field.max,
294
+ step: field.step,
295
+ size: "sm",
296
+ autoFocus: true
297
+ }
298
+ );
299
+ case "select":
300
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_select.Select, { value: String(value != null ? value : ""), onValueChange: onSelect, size: "sm", children: [
301
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Trigger, { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
302
+ import_select.Select.Value,
303
+ {
304
+ placeholder: (_c = field.placeholder) != null ? _c : t.formatMessage(messages.select_value)
305
+ }
306
+ ) }),
307
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Content, { children: (_d = field.options) == null ? void 0 : _d.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
308
+ import_select.Select.Item,
309
+ {
310
+ value: option.value,
311
+ disabled: option.disabled,
312
+ children: [
313
+ option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mr-2 size-4", children: option.icon }),
314
+ option.label
315
+ ]
316
+ },
317
+ option.value
318
+ )) })
319
+ ] });
320
+ case "multiselect": {
321
+ const selectedValues = Array.isArray(value) ? value : [];
322
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "space-y-2 max-h-[200px] overflow-auto", children: (_e = field.options) == null ? void 0 : _e.map((option) => (
323
+ // biome-ignore lint/a11y/noLabelWithoutControl: Checkbox is a custom form control inside the label
324
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
325
+ "label",
326
+ {
327
+ className: "flex items-center gap-2 cursor-pointer",
328
+ children: [
329
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
330
+ import_checkbox.Checkbox,
331
+ {
332
+ checked: selectedValues.includes(option.value),
333
+ onCheckedChange: (checked) => {
334
+ if (checked) {
335
+ onChange([...selectedValues, option.value]);
336
+ } else {
337
+ onChange(selectedValues.filter((v) => v !== option.value));
338
+ }
339
+ },
340
+ disabled: option.disabled
341
+ }
342
+ ),
343
+ option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "size-4", children: option.icon }),
344
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm", children: option.label })
345
+ ]
346
+ },
347
+ option.value
348
+ )
349
+ )) });
350
+ }
351
+ case "boolean":
352
+ return (
353
+ // biome-ignore lint/a11y/noLabelWithoutControl: Checkbox is a custom form control inside the label
354
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer", children: [
355
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
356
+ import_checkbox.Checkbox,
357
+ {
358
+ checked: Boolean(value),
359
+ onCheckedChange: (checked) => onSelect(Boolean(checked))
360
+ }
361
+ ),
362
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm", children: field.label })
363
+ ] })
364
+ );
365
+ case "date":
366
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
367
+ import_input.Input,
368
+ {
369
+ type: "date",
370
+ value: value instanceof Date ? value.toISOString().split("T")[0] : String(value != null ? value : ""),
371
+ onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : void 0),
372
+ size: "sm"
373
+ }
374
+ );
375
+ case "daterange": {
376
+ const [start, end] = Array.isArray(value) ? value : [void 0, void 0];
377
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
378
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
379
+ import_input.Input,
380
+ {
381
+ type: "date",
382
+ value: start instanceof Date ? start.toISOString().split("T")[0] : String(start != null ? start : ""),
383
+ onChange: (e) => onChange([
384
+ e.target.value ? new Date(e.target.value) : void 0,
385
+ end
386
+ ]),
387
+ size: "sm"
388
+ }
389
+ ),
390
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "-" }),
391
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
392
+ import_input.Input,
393
+ {
394
+ type: "date",
395
+ value: end instanceof Date ? end.toISOString().split("T")[0] : String(end != null ? end : ""),
396
+ onChange: (e) => onChange([
397
+ start,
398
+ e.target.value ? new Date(e.target.value) : void 0
399
+ ]),
400
+ size: "sm"
401
+ }
402
+ )
403
+ ] });
404
+ }
405
+ default:
406
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
407
+ import_input.Input,
408
+ {
409
+ value: String(value != null ? value : ""),
410
+ onChange: (e) => onChange(e.target.value),
411
+ placeholder: (_f = field.placeholder) != null ? _f : t.formatMessage(messages.enter_value),
412
+ size: "sm"
413
+ }
414
+ );
415
+ }
416
+ }
417
+
418
+ // src/filter-active.tsx
419
+ var import_jsx_runtime2 = require("react/jsx-runtime");
420
+ function FilterActive(props) {
421
+ const { showClearAll = true, className, ...rest } = props;
422
+ const { value, styles, clearFilters } = useFilterContext();
423
+ const t = (0, import_i18n3.useSafeIntl)();
424
+ if (value.length === 0) {
425
+ return null;
426
+ }
427
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
428
+ "div",
429
+ {
430
+ "data-slot": "filter-active",
431
+ className: (0, import_shared_utils.cn)(styles.active(), className),
432
+ ...rest,
433
+ children: [
434
+ value.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FilterField, { filter }, filter.id)),
435
+ showClearAll && value.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
436
+ "button",
437
+ {
438
+ type: "button",
439
+ className: styles.clearAll(),
440
+ onClick: clearFilters,
441
+ children: t.formatMessage(messages.clear_all)
442
+ }
443
+ )
444
+ ]
445
+ }
446
+ );
447
+ }
448
+ FilterActive.displayName = "FilterActive";
449
+ function FilterField({ filter }) {
450
+ const { fields, styles, removeFilter, editingFilterId, setEditingFilterId } = useFilterContext();
451
+ const t = (0, import_i18n3.useSafeIntl)();
452
+ const field = fields.get(filter.fieldId);
453
+ if (!field) return null;
454
+ const isEditing = editingFilterId === filter.id;
455
+ const operatorKey = `op_${filter.operator}`;
456
+ const operatorLabel = messages[operatorKey] ? t.formatMessage(messages[operatorKey]) : filter.operator;
457
+ const valueDisplay = getValueDisplay(filter, field);
458
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
459
+ import_popover.Popover.Root,
460
+ {
461
+ open: isEditing,
462
+ onOpenChange: (open) => setEditingFilterId(open ? filter.id : null),
463
+ children: [
464
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_popover.Popover.Trigger, { "data-slot": "filter-field", className: styles.field(), children: [
465
+ field.icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.menuItemIcon(), children: field.icon }),
466
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.fieldLabel(), children: field.label }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.fieldOperator(), children: operatorLabel }),
468
+ valueDisplay && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.fieldValue(), children: valueDisplay }),
469
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
470
+ "button",
471
+ {
472
+ type: "button",
473
+ className: styles.fieldRemove(),
474
+ onClick: (e) => {
475
+ e.stopPropagation();
476
+ removeFilter(filter.id);
477
+ },
478
+ "aria-label": "Remove filter",
479
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.CloseIcon, { className: "size-3" })
480
+ }
481
+ )
482
+ ] }),
483
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
484
+ import_popover.Popover.Content,
485
+ {
486
+ "data-slot": "filter-editor",
487
+ className: styles.editor(),
488
+ align: "start",
489
+ showArrow: false,
490
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(FilterValueEditor, { filter, field })
491
+ }
492
+ )
493
+ ]
494
+ }
495
+ );
496
+ }
497
+ function getValueDisplay(filter, field) {
498
+ var _a, _b, _c, _d;
499
+ const { value, operator } = filter;
500
+ if (operator === "is_empty" || operator === "is_not_empty") {
501
+ return null;
502
+ }
503
+ if (value === void 0 || value === null || value === "") {
504
+ return "...";
505
+ }
506
+ if (field.type === "boolean") {
507
+ return value ? "Yes" : "No";
508
+ }
509
+ if (field.type === "select" && field.options) {
510
+ const option = field.options.find((o) => o.value === value);
511
+ return (_a = option == null ? void 0 : option.label) != null ? _a : String(value);
512
+ }
513
+ if (field.type === "multiselect" && Array.isArray(value)) {
514
+ if (value.length === 0) return "...";
515
+ if (value.length === 1 && field.options) {
516
+ const option = field.options.find((o) => o.value === value[0]);
517
+ return (_b = option == null ? void 0 : option.label) != null ? _b : String(value[0]);
518
+ }
519
+ return `${value.length} selected`;
520
+ }
521
+ if (field.type === "date" && value instanceof Date) {
522
+ return value.toLocaleDateString();
523
+ }
524
+ if (field.type === "daterange" && Array.isArray(value)) {
525
+ const [start, end] = value;
526
+ const startStr = start instanceof Date ? start.toLocaleDateString() : "...";
527
+ const endStr = end instanceof Date ? end.toLocaleDateString() : "...";
528
+ return `${startStr} - ${endStr}`;
529
+ }
530
+ if (operator === "between" && Array.isArray(value)) {
531
+ return `${(_c = value[0]) != null ? _c : "..."} - ${(_d = value[1]) != null ? _d : "..."}`;
532
+ }
533
+ return String(value);
534
+ }
535
+ // Annotate the CommonJS export names for ESM import in node:
536
+ 0 && (module.exports = {
537
+ FilterActive
538
+ });
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ FilterActive
5
+ } from "./chunk-7KY2PDNL.mjs";
6
+ import "./chunk-63P4ITVP.mjs";
7
+ import "./chunk-URDCG5NI.mjs";
8
+ import "./chunk-I3Z2T4N2.mjs";
9
+ import "./chunk-7QP7FRID.mjs";
10
+ export {
11
+ FilterActive
12
+ };
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+ import { filter, FilterVariantProps } from '@kopexa/theme';
3
+ import { FilterI18nConfig } from './filter-i18n.mjs';
4
+ import { FilterValue, FilterFieldConfig } from './filter-types.mjs';
5
+
6
+ interface FilterContextValue {
7
+ value: FilterValue[];
8
+ fields: Map<string, FilterFieldConfig>;
9
+ allowMultiple: boolean;
10
+ styles: ReturnType<typeof filter>;
11
+ size: FilterVariantProps["size"];
12
+ variant: FilterVariantProps["variant"];
13
+ i18n: FilterI18nConfig;
14
+ addFilter: (fieldId: string) => void;
15
+ updateFilter: (filterId: string, updates: Partial<FilterValue>) => void;
16
+ removeFilter: (filterId: string) => void;
17
+ clearFilters: () => void;
18
+ registerField: (field: FilterFieldConfig) => void;
19
+ unregisterField: (fieldId: string) => void;
20
+ menuOpen: boolean;
21
+ setMenuOpen: (open: boolean) => void;
22
+ editingFilterId: string | null;
23
+ setEditingFilterId: (id: string | null) => void;
24
+ }
25
+ declare const FilterProvider: React.Provider<FilterContextValue>;
26
+ declare const useFilterContext: () => FilterContextValue;
27
+
28
+ export { type FilterContextValue, FilterProvider, useFilterContext };
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+ import { filter, FilterVariantProps } from '@kopexa/theme';
3
+ import { FilterI18nConfig } from './filter-i18n.js';
4
+ import { FilterValue, FilterFieldConfig } from './filter-types.js';
5
+
6
+ interface FilterContextValue {
7
+ value: FilterValue[];
8
+ fields: Map<string, FilterFieldConfig>;
9
+ allowMultiple: boolean;
10
+ styles: ReturnType<typeof filter>;
11
+ size: FilterVariantProps["size"];
12
+ variant: FilterVariantProps["variant"];
13
+ i18n: FilterI18nConfig;
14
+ addFilter: (fieldId: string) => void;
15
+ updateFilter: (filterId: string, updates: Partial<FilterValue>) => void;
16
+ removeFilter: (filterId: string) => void;
17
+ clearFilters: () => void;
18
+ registerField: (field: FilterFieldConfig) => void;
19
+ unregisterField: (fieldId: string) => void;
20
+ menuOpen: boolean;
21
+ setMenuOpen: (open: boolean) => void;
22
+ editingFilterId: string | null;
23
+ setEditingFilterId: (id: string | null) => void;
24
+ }
25
+ declare const FilterProvider: React.Provider<FilterContextValue>;
26
+ declare const useFilterContext: () => FilterContextValue;
27
+
28
+ export { type FilterContextValue, FilterProvider, useFilterContext };
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ "use strict";
3
+ "use client";
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
21
+
22
+ // src/filter-context.tsx
23
+ var filter_context_exports = {};
24
+ __export(filter_context_exports, {
25
+ FilterProvider: () => FilterProvider,
26
+ useFilterContext: () => useFilterContext
27
+ });
28
+ module.exports = __toCommonJS(filter_context_exports);
29
+ var import_react_utils = require("@kopexa/react-utils");
30
+ var [FilterProvider, useFilterContext] = (0, import_react_utils.createContext)({
31
+ name: "FilterContext",
32
+ strict: true,
33
+ errorMessage: "useFilterContext must be used within a Filter component. Make sure to wrap your FilterMenu, FilterTrigger, etc. inside a <Filter> component."
34
+ });
35
+ // Annotate the CommonJS export names for ESM import in node:
36
+ 0 && (module.exports = {
37
+ FilterProvider,
38
+ useFilterContext
39
+ });
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ "use client";
3
+ import {
4
+ FilterProvider,
5
+ useFilterContext
6
+ } from "./chunk-I3Z2T4N2.mjs";
7
+ export {
8
+ FilterProvider,
9
+ useFilterContext
10
+ };
@@ -0,0 +1,20 @@
1
+ import { FilterOperator } from './filter-types.mjs';
2
+ import 'react';
3
+
4
+ /**
5
+ * i18n configuration for the Filter component
6
+ */
7
+ interface FilterI18nConfig {
8
+ addFilter: string;
9
+ clearAll: string;
10
+ noFields: string;
11
+ selectValue: string;
12
+ enterValue: string;
13
+ operators: Record<FilterOperator, string>;
14
+ }
15
+ /**
16
+ * Default English translations
17
+ */
18
+ declare const DEFAULT_I18N: FilterI18nConfig;
19
+
20
+ export { DEFAULT_I18N, type FilterI18nConfig };