@kopexa/filter 0.0.83 → 0.0.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,16 @@
1
1
  "use client";
2
2
  import {
3
3
  DEFAULT_FILTER_BAR_OPERATORS
4
- } from "./chunk-HACVUP5P.mjs";
4
+ } from "./chunk-L3J62ATJ.mjs";
5
5
 
6
6
  // src/filter-bar-internal.tsx
7
7
  import { Button } from "@kopexa/button";
8
8
  import { Checkbox } from "@kopexa/checkbox";
9
9
  import { Command } from "@kopexa/command";
10
+ import {
11
+ DateFieldPicker,
12
+ parseDate
13
+ } from "@kopexa/date-picker";
10
14
  import { DropdownMenu } from "@kopexa/dropdown-menu";
11
15
  import { CheckIcon, ChevronDownIcon, CloseIcon, PlusIcon } from "@kopexa/icons";
12
16
  import { Input } from "@kopexa/input";
@@ -70,7 +74,8 @@ function FilterPill(props) {
70
74
  const isEmptyOperator = filter.operator === "is_empty" || filter.operator === "is_not_empty";
71
75
  const hasCustomRenderer = !!field.customRenderer;
72
76
  const useInlineInput = !hasCustomRenderer && (field.type === "text" || field.type === "number");
73
- const usePopover = !useInlineInput && !isEmptyOperator;
77
+ const useDateInput = !hasCustomRenderer && field.type === "date" && !isEmptyOperator;
78
+ const usePopover = !useInlineInput && !useDateInput && !isEmptyOperator;
74
79
  const handleOpenChange = useCallback(
75
80
  (isOpen) => {
76
81
  setOpen(isOpen);
@@ -131,6 +136,7 @@ function FilterPill(props) {
131
136
  operator: filter.operator,
132
137
  operators,
133
138
  i18n,
139
+ fieldType: field.type,
134
140
  onChange: (op) => {
135
141
  const newUpdates = { operator: op };
136
142
  if (op === "is_empty" || op === "is_not_empty") {
@@ -151,6 +157,15 @@ function FilterPill(props) {
151
157
  disabled
152
158
  }
153
159
  ),
160
+ useDateInput && /* @__PURE__ */ jsx(
161
+ DateFilterValue,
162
+ {
163
+ filter,
164
+ field,
165
+ onUpdate,
166
+ disabled
167
+ }
168
+ ),
154
169
  usePopover && /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: handleOpenChange, children: [
155
170
  /* @__PURE__ */ jsxs(
156
171
  Popover.Trigger,
@@ -208,9 +223,13 @@ function FilterPill(props) {
208
223
  );
209
224
  }
210
225
  function OperatorDropdown(props) {
211
- const { operator, operators, i18n, onChange, disabled } = props;
226
+ const { operator, operators, i18n, fieldType, onChange, disabled } = props;
227
+ const label = (op) => {
228
+ var _a;
229
+ return fieldType === "date" && ((_a = i18n.dateOperators) == null ? void 0 : _a[op]) || i18n.operators[op];
230
+ };
212
231
  const hasSingleOperator = operators.length === 1;
213
- const currentLabel = i18n.operators[operator];
232
+ const currentLabel = label(operator);
214
233
  if (hasSingleOperator) {
215
234
  return /* @__PURE__ */ jsx(
216
235
  "span",
@@ -250,7 +269,7 @@ function OperatorDropdown(props) {
250
269
  className: "gap-2",
251
270
  children: [
252
271
  op === operator && /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }),
253
- /* @__PURE__ */ jsx("span", { className: op !== operator ? "pl-6" : "", children: i18n.operators[op] })
272
+ /* @__PURE__ */ jsx("span", { className: op !== operator ? "pl-6" : "", children: label(op) })
254
273
  ]
255
274
  },
256
275
  op
@@ -284,7 +303,7 @@ function InlineValueInput(props) {
284
303
  children: /* @__PURE__ */ jsx(
285
304
  "input",
286
305
  {
287
- type: field.type === "number" ? "number" : "text",
306
+ type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
288
307
  className: cn(
289
308
  "bg-transparent border-none outline-none",
290
309
  "placeholder:text-muted-foreground",
@@ -294,7 +313,7 @@ function InlineValueInput(props) {
294
313
  onChange: handleChange,
295
314
  placeholder,
296
315
  "aria-label": `${field.label} value`,
297
- style: { width: getInputWidth(filter.value, placeholder, 6) },
316
+ style: field.type === "date" ? void 0 : { width: getInputWidth(filter.value, placeholder, 6) },
298
317
  min: field.min,
299
318
  max: field.max,
300
319
  step: field.step,
@@ -304,6 +323,28 @@ function InlineValueInput(props) {
304
323
  }
305
324
  );
306
325
  }
326
+ function safeParseDate(value) {
327
+ if (typeof value !== "string" || !value) return null;
328
+ try {
329
+ return parseDate(value.slice(0, 10));
330
+ } catch {
331
+ return null;
332
+ }
333
+ }
334
+ function DateFilterValue(props) {
335
+ const { filter, field, onUpdate, disabled } = props;
336
+ return /* @__PURE__ */ jsx("span", { className: "flex items-center px-1 py-0.5", children: /* @__PURE__ */ jsx(
337
+ DateFieldPicker,
338
+ {
339
+ variant: "ghost",
340
+ size: "sm",
341
+ value: safeParseDate(filter.value),
342
+ onChange: (v) => onUpdate({ value: v ? v.toString() : null }),
343
+ isDisabled: disabled,
344
+ "aria-label": field.label
345
+ }
346
+ ) });
347
+ }
307
348
  function ValueEditor(props) {
308
349
  var _a, _b, _c, _d;
309
350
  const { filter, field, i18n, onUpdate, onClose } = props;
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  AddFilterDropdown,
4
4
  FilterPill
5
- } from "./chunk-TCLE7EEK.mjs";
5
+ } from "./chunk-3LFPXMAB.mjs";
6
6
  import {
7
7
  filterBarMessages
8
- } from "./chunk-I7WCYMXD.mjs";
8
+ } from "./chunk-XXUWQU2D.mjs";
9
9
  import {
10
10
  getFilterDefaultValue
11
- } from "./chunk-HACVUP5P.mjs";
11
+ } from "./chunk-L3J62ATJ.mjs";
12
12
 
13
13
  // src/filter-bar.tsx
14
14
  import { useSafeIntl } from "@kopexa/i18n";
@@ -56,6 +56,14 @@ function FilterBar(props) {
56
56
  lte: t.formatMessage(filterBarMessages.op_lte),
57
57
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
58
58
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
59
+ },
60
+ dateOperators: {
61
+ equals: t.formatMessage(filterBarMessages.op_date_on),
62
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
63
+ gt: t.formatMessage(filterBarMessages.op_date_after),
64
+ lt: t.formatMessage(filterBarMessages.op_date_before),
65
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
66
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
59
67
  }
60
68
  };
61
69
  return {
@@ -64,6 +72,10 @@ function FilterBar(props) {
64
72
  operators: {
65
73
  ...defaultI18n.operators,
66
74
  ...i18nProp == null ? void 0 : i18nProp.operators
75
+ },
76
+ dateOperators: {
77
+ ...defaultI18n.dateOperators,
78
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
67
79
  }
68
80
  };
69
81
  }, [t, i18nProp]);
@@ -24,6 +24,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
24
24
  "is_empty",
25
25
  "is_not_empty"
26
26
  ],
27
+ date: [
28
+ "equals",
29
+ "not_equals",
30
+ "gt",
31
+ "lt",
32
+ "gte",
33
+ "lte",
34
+ "is_empty",
35
+ "is_not_empty"
36
+ ],
27
37
  custom: ["equals", "not_equals"]
28
38
  };
29
39
  function isBooleanSelectField(field) {
@@ -94,6 +94,36 @@ var filterBarMessages = defineMessages({
94
94
  defaultMessage: "less or equal",
95
95
  description: "Operator: less than or equal"
96
96
  },
97
+ op_date_on: {
98
+ id: "filter-bar.operator.date_on",
99
+ defaultMessage: "on",
100
+ description: "Date operator: equals (on)"
101
+ },
102
+ op_date_not_on: {
103
+ id: "filter-bar.operator.date_not_on",
104
+ defaultMessage: "not on",
105
+ description: "Date operator: not equals"
106
+ },
107
+ op_date_after: {
108
+ id: "filter-bar.operator.date_after",
109
+ defaultMessage: "after",
110
+ description: "Date operator: greater than (after)"
111
+ },
112
+ op_date_before: {
113
+ id: "filter-bar.operator.date_before",
114
+ defaultMessage: "before",
115
+ description: "Date operator: less than (before)"
116
+ },
117
+ op_date_on_or_after: {
118
+ id: "filter-bar.operator.date_on_or_after",
119
+ defaultMessage: "on or after",
120
+ description: "Date operator: greater or equal"
121
+ },
122
+ op_date_on_or_before: {
123
+ id: "filter-bar.operator.date_on_or_before",
124
+ defaultMessage: "on or before",
125
+ description: "Date operator: less or equal"
126
+ },
97
127
  op_is_empty: {
98
128
  id: "filter-bar.operator.is_empty",
99
129
  defaultMessage: "is empty",
@@ -2,13 +2,13 @@
2
2
  import {
3
3
  AddFilterDropdown,
4
4
  FilterPill
5
- } from "./chunk-TCLE7EEK.mjs";
5
+ } from "./chunk-3LFPXMAB.mjs";
6
6
  import {
7
7
  filterBarMessages
8
- } from "./chunk-I7WCYMXD.mjs";
8
+ } from "./chunk-XXUWQU2D.mjs";
9
9
  import {
10
10
  getFilterDefaultValue
11
- } from "./chunk-HACVUP5P.mjs";
11
+ } from "./chunk-L3J62ATJ.mjs";
12
12
 
13
13
  // src/search-filter-bar.tsx
14
14
  import { useSafeIntl } from "@kopexa/i18n";
@@ -72,6 +72,14 @@ function SearchFilterBar(props) {
72
72
  lte: t.formatMessage(filterBarMessages.op_lte),
73
73
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
74
74
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
75
+ },
76
+ dateOperators: {
77
+ equals: t.formatMessage(filterBarMessages.op_date_on),
78
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
79
+ gt: t.formatMessage(filterBarMessages.op_date_after),
80
+ lt: t.formatMessage(filterBarMessages.op_date_before),
81
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
82
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
75
83
  }
76
84
  };
77
85
  return {
@@ -80,6 +88,10 @@ function SearchFilterBar(props) {
80
88
  operators: {
81
89
  ...defaultI18n.operators,
82
90
  ...i18nProp == null ? void 0 : i18nProp.operators
91
+ },
92
+ dateOperators: {
93
+ ...defaultI18n.dateOperators,
94
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
83
95
  }
84
96
  };
85
97
  }, [t, i18nProp]);
@@ -29,6 +29,7 @@ module.exports = __toCommonJS(filter_bar_internal_exports);
29
29
  var import_button = require("@kopexa/button");
30
30
  var import_checkbox = require("@kopexa/checkbox");
31
31
  var import_command = require("@kopexa/command");
32
+ var import_date_picker = require("@kopexa/date-picker");
32
33
  var import_dropdown_menu = require("@kopexa/dropdown-menu");
33
34
  var import_icons = require("@kopexa/icons");
34
35
  var import_input = require("@kopexa/input");
@@ -60,6 +61,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
60
61
  "is_empty",
61
62
  "is_not_empty"
62
63
  ],
64
+ date: [
65
+ "equals",
66
+ "not_equals",
67
+ "gt",
68
+ "lt",
69
+ "gte",
70
+ "lte",
71
+ "is_empty",
72
+ "is_not_empty"
73
+ ],
63
74
  custom: ["equals", "not_equals"]
64
75
  };
65
76
 
@@ -116,7 +127,8 @@ function FilterPill(props) {
116
127
  const isEmptyOperator = filter.operator === "is_empty" || filter.operator === "is_not_empty";
117
128
  const hasCustomRenderer = !!field.customRenderer;
118
129
  const useInlineInput = !hasCustomRenderer && (field.type === "text" || field.type === "number");
119
- const usePopover = !useInlineInput && !isEmptyOperator;
130
+ const useDateInput = !hasCustomRenderer && field.type === "date" && !isEmptyOperator;
131
+ const usePopover = !useInlineInput && !useDateInput && !isEmptyOperator;
120
132
  const handleOpenChange = (0, import_react.useCallback)(
121
133
  (isOpen) => {
122
134
  setOpen(isOpen);
@@ -177,6 +189,7 @@ function FilterPill(props) {
177
189
  operator: filter.operator,
178
190
  operators,
179
191
  i18n,
192
+ fieldType: field.type,
180
193
  onChange: (op) => {
181
194
  const newUpdates = { operator: op };
182
195
  if (op === "is_empty" || op === "is_not_empty") {
@@ -197,6 +210,15 @@ function FilterPill(props) {
197
210
  disabled
198
211
  }
199
212
  ),
213
+ useDateInput && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
214
+ DateFilterValue,
215
+ {
216
+ filter,
217
+ field,
218
+ onUpdate,
219
+ disabled
220
+ }
221
+ ),
200
222
  usePopover && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_popover.Popover.Root, { open, onOpenChange: handleOpenChange, children: [
201
223
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
202
224
  import_popover.Popover.Trigger,
@@ -254,9 +276,13 @@ function FilterPill(props) {
254
276
  );
255
277
  }
256
278
  function OperatorDropdown(props) {
257
- const { operator, operators, i18n, onChange, disabled } = props;
279
+ const { operator, operators, i18n, fieldType, onChange, disabled } = props;
280
+ const label = (op) => {
281
+ var _a;
282
+ return fieldType === "date" && ((_a = i18n.dateOperators) == null ? void 0 : _a[op]) || i18n.operators[op];
283
+ };
258
284
  const hasSingleOperator = operators.length === 1;
259
- const currentLabel = i18n.operators[operator];
285
+ const currentLabel = label(operator);
260
286
  if (hasSingleOperator) {
261
287
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
262
288
  "span",
@@ -296,7 +322,7 @@ function OperatorDropdown(props) {
296
322
  className: "gap-2",
297
323
  children: [
298
324
  op === operator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.CheckIcon, { className: "size-4" }),
299
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: i18n.operators[op] })
325
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: label(op) })
300
326
  ]
301
327
  },
302
328
  op
@@ -330,7 +356,7 @@ function InlineValueInput(props) {
330
356
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
331
357
  "input",
332
358
  {
333
- type: field.type === "number" ? "number" : "text",
359
+ type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
334
360
  className: (0, import_shared_utils.cn)(
335
361
  "bg-transparent border-none outline-none",
336
362
  "placeholder:text-muted-foreground",
@@ -340,7 +366,7 @@ function InlineValueInput(props) {
340
366
  onChange: handleChange,
341
367
  placeholder,
342
368
  "aria-label": `${field.label} value`,
343
- style: { width: getInputWidth(filter.value, placeholder, 6) },
369
+ style: field.type === "date" ? void 0 : { width: getInputWidth(filter.value, placeholder, 6) },
344
370
  min: field.min,
345
371
  max: field.max,
346
372
  step: field.step,
@@ -350,6 +376,28 @@ function InlineValueInput(props) {
350
376
  }
351
377
  );
352
378
  }
379
+ function safeParseDate(value) {
380
+ if (typeof value !== "string" || !value) return null;
381
+ try {
382
+ return (0, import_date_picker.parseDate)(value.slice(0, 10));
383
+ } catch {
384
+ return null;
385
+ }
386
+ }
387
+ function DateFilterValue(props) {
388
+ const { filter, field, onUpdate, disabled } = props;
389
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center px-1 py-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
390
+ import_date_picker.DateFieldPicker,
391
+ {
392
+ variant: "ghost",
393
+ size: "sm",
394
+ value: safeParseDate(filter.value),
395
+ onChange: (v) => onUpdate({ value: v ? v.toString() : null }),
396
+ isDisabled: disabled,
397
+ "aria-label": field.label
398
+ }
399
+ ) });
400
+ }
353
401
  function ValueEditor(props) {
354
402
  var _a, _b, _c, _d;
355
403
  const { filter, field, i18n, onUpdate, onClose } = props;
@@ -3,8 +3,8 @@
3
3
  import {
4
4
  AddFilterDropdown,
5
5
  FilterPill
6
- } from "./chunk-TCLE7EEK.mjs";
7
- import "./chunk-HACVUP5P.mjs";
6
+ } from "./chunk-3LFPXMAB.mjs";
7
+ import "./chunk-L3J62ATJ.mjs";
8
8
  export {
9
9
  AddFilterDropdown,
10
10
  FilterPill
@@ -89,6 +89,36 @@ declare const filterBarMessages: {
89
89
  defaultMessage: string;
90
90
  description: string;
91
91
  };
92
+ op_date_on: {
93
+ id: string;
94
+ defaultMessage: string;
95
+ description: string;
96
+ };
97
+ op_date_not_on: {
98
+ id: string;
99
+ defaultMessage: string;
100
+ description: string;
101
+ };
102
+ op_date_after: {
103
+ id: string;
104
+ defaultMessage: string;
105
+ description: string;
106
+ };
107
+ op_date_before: {
108
+ id: string;
109
+ defaultMessage: string;
110
+ description: string;
111
+ };
112
+ op_date_on_or_after: {
113
+ id: string;
114
+ defaultMessage: string;
115
+ description: string;
116
+ };
117
+ op_date_on_or_before: {
118
+ id: string;
119
+ defaultMessage: string;
120
+ description: string;
121
+ };
92
122
  op_is_empty: {
93
123
  id: string;
94
124
  defaultMessage: string;
@@ -89,6 +89,36 @@ declare const filterBarMessages: {
89
89
  defaultMessage: string;
90
90
  description: string;
91
91
  };
92
+ op_date_on: {
93
+ id: string;
94
+ defaultMessage: string;
95
+ description: string;
96
+ };
97
+ op_date_not_on: {
98
+ id: string;
99
+ defaultMessage: string;
100
+ description: string;
101
+ };
102
+ op_date_after: {
103
+ id: string;
104
+ defaultMessage: string;
105
+ description: string;
106
+ };
107
+ op_date_before: {
108
+ id: string;
109
+ defaultMessage: string;
110
+ description: string;
111
+ };
112
+ op_date_on_or_after: {
113
+ id: string;
114
+ defaultMessage: string;
115
+ description: string;
116
+ };
117
+ op_date_on_or_before: {
118
+ id: string;
119
+ defaultMessage: string;
120
+ description: string;
121
+ };
92
122
  op_is_empty: {
93
123
  id: string;
94
124
  defaultMessage: string;
@@ -117,6 +117,36 @@ var filterBarMessages = (0, import_i18n.defineMessages)({
117
117
  defaultMessage: "less or equal",
118
118
  description: "Operator: less than or equal"
119
119
  },
120
+ op_date_on: {
121
+ id: "filter-bar.operator.date_on",
122
+ defaultMessage: "on",
123
+ description: "Date operator: equals (on)"
124
+ },
125
+ op_date_not_on: {
126
+ id: "filter-bar.operator.date_not_on",
127
+ defaultMessage: "not on",
128
+ description: "Date operator: not equals"
129
+ },
130
+ op_date_after: {
131
+ id: "filter-bar.operator.date_after",
132
+ defaultMessage: "after",
133
+ description: "Date operator: greater than (after)"
134
+ },
135
+ op_date_before: {
136
+ id: "filter-bar.operator.date_before",
137
+ defaultMessage: "before",
138
+ description: "Date operator: less than (before)"
139
+ },
140
+ op_date_on_or_after: {
141
+ id: "filter-bar.operator.date_on_or_after",
142
+ defaultMessage: "on or after",
143
+ description: "Date operator: greater or equal"
144
+ },
145
+ op_date_on_or_before: {
146
+ id: "filter-bar.operator.date_on_or_before",
147
+ defaultMessage: "on or before",
148
+ description: "Date operator: less or equal"
149
+ },
120
150
  op_is_empty: {
121
151
  id: "filter-bar.operator.is_empty",
122
152
  defaultMessage: "is empty",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  filterBarMessages
4
- } from "./chunk-I7WCYMXD.mjs";
4
+ } from "./chunk-XXUWQU2D.mjs";
5
5
  export {
6
6
  filterBarMessages
7
7
  };
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  /**
4
4
  * Supported field types for FilterBar
5
5
  */
6
- type FilterBarFieldType = "select" | "multiselect" | "text" | "number" | "custom";
6
+ type FilterBarFieldType = "select" | "multiselect" | "text" | "number" | "date" | "custom";
7
7
  /**
8
8
  * Supported operators for FilterBar
9
9
  */
@@ -113,6 +113,8 @@ interface FilterBarI18nConfig {
113
113
  selectValue: string;
114
114
  enterValue: string;
115
115
  operators: Record<FilterBarOperator, string>;
116
+ /** Operator labels specific to `date` fields (e.g. before/after/on). */
117
+ dateOperators?: Partial<Record<FilterBarOperator, string>>;
116
118
  validation?: {
117
119
  required?: string;
118
120
  invalid?: string;
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  /**
4
4
  * Supported field types for FilterBar
5
5
  */
6
- type FilterBarFieldType = "select" | "multiselect" | "text" | "number" | "custom";
6
+ type FilterBarFieldType = "select" | "multiselect" | "text" | "number" | "date" | "custom";
7
7
  /**
8
8
  * Supported operators for FilterBar
9
9
  */
@@ -113,6 +113,8 @@ interface FilterBarI18nConfig {
113
113
  selectValue: string;
114
114
  enterValue: string;
115
115
  operators: Record<FilterBarOperator, string>;
116
+ /** Operator labels specific to `date` fields (e.g. before/after/on). */
117
+ dateOperators?: Partial<Record<FilterBarOperator, string>>;
116
118
  validation?: {
117
119
  required?: string;
118
120
  invalid?: string;
@@ -50,6 +50,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
50
50
  "is_empty",
51
51
  "is_not_empty"
52
52
  ],
53
+ date: [
54
+ "equals",
55
+ "not_equals",
56
+ "gt",
57
+ "lt",
58
+ "gte",
59
+ "lte",
60
+ "is_empty",
61
+ "is_not_empty"
62
+ ],
53
63
  custom: ["equals", "not_equals"]
54
64
  };
55
65
  function isBooleanSelectField(field) {
@@ -4,7 +4,7 @@ import {
4
4
  DEFAULT_FILTER_BAR_OPERATORS,
5
5
  getFilterDefaultValue,
6
6
  isBooleanSelectField
7
- } from "./chunk-HACVUP5P.mjs";
7
+ } from "./chunk-L3J62ATJ.mjs";
8
8
  export {
9
9
  DEFAULT_FILTER_BAR_OPERATORS,
10
10
  getFilterDefaultValue,
@@ -34,6 +34,7 @@ var import_react2 = require("react");
34
34
  var import_button = require("@kopexa/button");
35
35
  var import_checkbox = require("@kopexa/checkbox");
36
36
  var import_command = require("@kopexa/command");
37
+ var import_date_picker = require("@kopexa/date-picker");
37
38
  var import_dropdown_menu = require("@kopexa/dropdown-menu");
38
39
  var import_icons = require("@kopexa/icons");
39
40
  var import_input = require("@kopexa/input");
@@ -65,6 +66,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
65
66
  "is_empty",
66
67
  "is_not_empty"
67
68
  ],
69
+ date: [
70
+ "equals",
71
+ "not_equals",
72
+ "gt",
73
+ "lt",
74
+ "gte",
75
+ "lte",
76
+ "is_empty",
77
+ "is_not_empty"
78
+ ],
68
79
  custom: ["equals", "not_equals"]
69
80
  };
70
81
  function isBooleanSelectField(field) {
@@ -139,7 +150,8 @@ function FilterPill(props) {
139
150
  const isEmptyOperator = filter.operator === "is_empty" || filter.operator === "is_not_empty";
140
151
  const hasCustomRenderer = !!field.customRenderer;
141
152
  const useInlineInput = !hasCustomRenderer && (field.type === "text" || field.type === "number");
142
- const usePopover = !useInlineInput && !isEmptyOperator;
153
+ const useDateInput = !hasCustomRenderer && field.type === "date" && !isEmptyOperator;
154
+ const usePopover = !useInlineInput && !useDateInput && !isEmptyOperator;
143
155
  const handleOpenChange = (0, import_react.useCallback)(
144
156
  (isOpen) => {
145
157
  setOpen(isOpen);
@@ -200,6 +212,7 @@ function FilterPill(props) {
200
212
  operator: filter.operator,
201
213
  operators,
202
214
  i18n,
215
+ fieldType: field.type,
203
216
  onChange: (op) => {
204
217
  const newUpdates = { operator: op };
205
218
  if (op === "is_empty" || op === "is_not_empty") {
@@ -220,6 +233,15 @@ function FilterPill(props) {
220
233
  disabled
221
234
  }
222
235
  ),
236
+ useDateInput && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
237
+ DateFilterValue,
238
+ {
239
+ filter,
240
+ field,
241
+ onUpdate,
242
+ disabled
243
+ }
244
+ ),
223
245
  usePopover && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_popover.Popover.Root, { open, onOpenChange: handleOpenChange, children: [
224
246
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
225
247
  import_popover.Popover.Trigger,
@@ -277,9 +299,13 @@ function FilterPill(props) {
277
299
  );
278
300
  }
279
301
  function OperatorDropdown(props) {
280
- const { operator, operators, i18n, onChange, disabled } = props;
302
+ const { operator, operators, i18n, fieldType, onChange, disabled } = props;
303
+ const label = (op) => {
304
+ var _a;
305
+ return fieldType === "date" && ((_a = i18n.dateOperators) == null ? void 0 : _a[op]) || i18n.operators[op];
306
+ };
281
307
  const hasSingleOperator = operators.length === 1;
282
- const currentLabel = i18n.operators[operator];
308
+ const currentLabel = label(operator);
283
309
  if (hasSingleOperator) {
284
310
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
285
311
  "span",
@@ -319,7 +345,7 @@ function OperatorDropdown(props) {
319
345
  className: "gap-2",
320
346
  children: [
321
347
  op === operator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.CheckIcon, { className: "size-4" }),
322
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: i18n.operators[op] })
348
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: label(op) })
323
349
  ]
324
350
  },
325
351
  op
@@ -353,7 +379,7 @@ function InlineValueInput(props) {
353
379
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
354
380
  "input",
355
381
  {
356
- type: field.type === "number" ? "number" : "text",
382
+ type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
357
383
  className: (0, import_shared_utils.cn)(
358
384
  "bg-transparent border-none outline-none",
359
385
  "placeholder:text-muted-foreground",
@@ -363,7 +389,7 @@ function InlineValueInput(props) {
363
389
  onChange: handleChange,
364
390
  placeholder,
365
391
  "aria-label": `${field.label} value`,
366
- style: { width: getInputWidth(filter.value, placeholder, 6) },
392
+ style: field.type === "date" ? void 0 : { width: getInputWidth(filter.value, placeholder, 6) },
367
393
  min: field.min,
368
394
  max: field.max,
369
395
  step: field.step,
@@ -373,6 +399,28 @@ function InlineValueInput(props) {
373
399
  }
374
400
  );
375
401
  }
402
+ function safeParseDate(value) {
403
+ if (typeof value !== "string" || !value) return null;
404
+ try {
405
+ return (0, import_date_picker.parseDate)(value.slice(0, 10));
406
+ } catch {
407
+ return null;
408
+ }
409
+ }
410
+ function DateFilterValue(props) {
411
+ const { filter, field, onUpdate, disabled } = props;
412
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center px-1 py-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
413
+ import_date_picker.DateFieldPicker,
414
+ {
415
+ variant: "ghost",
416
+ size: "sm",
417
+ value: safeParseDate(filter.value),
418
+ onChange: (v) => onUpdate({ value: v ? v.toString() : null }),
419
+ isDisabled: disabled,
420
+ "aria-label": field.label
421
+ }
422
+ ) });
423
+ }
376
424
  function ValueEditor(props) {
377
425
  var _a, _b, _c, _d;
378
426
  const { filter, field, i18n, onUpdate, onClose } = props;
@@ -759,6 +807,36 @@ var filterBarMessages = (0, import_i18n.defineMessages)({
759
807
  defaultMessage: "less or equal",
760
808
  description: "Operator: less than or equal"
761
809
  },
810
+ op_date_on: {
811
+ id: "filter-bar.operator.date_on",
812
+ defaultMessage: "on",
813
+ description: "Date operator: equals (on)"
814
+ },
815
+ op_date_not_on: {
816
+ id: "filter-bar.operator.date_not_on",
817
+ defaultMessage: "not on",
818
+ description: "Date operator: not equals"
819
+ },
820
+ op_date_after: {
821
+ id: "filter-bar.operator.date_after",
822
+ defaultMessage: "after",
823
+ description: "Date operator: greater than (after)"
824
+ },
825
+ op_date_before: {
826
+ id: "filter-bar.operator.date_before",
827
+ defaultMessage: "before",
828
+ description: "Date operator: less than (before)"
829
+ },
830
+ op_date_on_or_after: {
831
+ id: "filter-bar.operator.date_on_or_after",
832
+ defaultMessage: "on or after",
833
+ description: "Date operator: greater or equal"
834
+ },
835
+ op_date_on_or_before: {
836
+ id: "filter-bar.operator.date_on_or_before",
837
+ defaultMessage: "on or before",
838
+ description: "Date operator: less or equal"
839
+ },
762
840
  op_is_empty: {
763
841
  id: "filter-bar.operator.is_empty",
764
842
  defaultMessage: "is empty",
@@ -835,6 +913,14 @@ function FilterBar(props) {
835
913
  lte: t.formatMessage(filterBarMessages.op_lte),
836
914
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
837
915
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
916
+ },
917
+ dateOperators: {
918
+ equals: t.formatMessage(filterBarMessages.op_date_on),
919
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
920
+ gt: t.formatMessage(filterBarMessages.op_date_after),
921
+ lt: t.formatMessage(filterBarMessages.op_date_before),
922
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
923
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
838
924
  }
839
925
  };
840
926
  return {
@@ -843,6 +929,10 @@ function FilterBar(props) {
843
929
  operators: {
844
930
  ...defaultI18n.operators,
845
931
  ...i18nProp == null ? void 0 : i18nProp.operators
932
+ },
933
+ dateOperators: {
934
+ ...defaultI18n.dateOperators,
935
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
846
936
  }
847
937
  };
848
938
  }, [t, i18nProp]);
@@ -2,10 +2,10 @@
2
2
  "use client";
3
3
  import {
4
4
  FilterBar
5
- } from "./chunk-VII35ERE.mjs";
6
- import "./chunk-TCLE7EEK.mjs";
7
- import "./chunk-I7WCYMXD.mjs";
8
- import "./chunk-HACVUP5P.mjs";
5
+ } from "./chunk-C5Z5JGHO.mjs";
6
+ import "./chunk-3LFPXMAB.mjs";
7
+ import "./chunk-XXUWQU2D.mjs";
8
+ import "./chunk-L3J62ATJ.mjs";
9
9
  export {
10
10
  FilterBar
11
11
  };
package/dist/index.js CHANGED
@@ -1146,6 +1146,7 @@ var import_react3 = require("react");
1146
1146
  var import_button = require("@kopexa/button");
1147
1147
  var import_checkbox2 = require("@kopexa/checkbox");
1148
1148
  var import_command = require("@kopexa/command");
1149
+ var import_date_picker = require("@kopexa/date-picker");
1149
1150
  var import_dropdown_menu4 = require("@kopexa/dropdown-menu");
1150
1151
  var import_icons3 = require("@kopexa/icons");
1151
1152
  var import_input2 = require("@kopexa/input");
@@ -1177,6 +1178,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
1177
1178
  "is_empty",
1178
1179
  "is_not_empty"
1179
1180
  ],
1181
+ date: [
1182
+ "equals",
1183
+ "not_equals",
1184
+ "gt",
1185
+ "lt",
1186
+ "gte",
1187
+ "lte",
1188
+ "is_empty",
1189
+ "is_not_empty"
1190
+ ],
1180
1191
  custom: ["equals", "not_equals"]
1181
1192
  };
1182
1193
  function isBooleanSelectField(field) {
@@ -1251,7 +1262,8 @@ function FilterPill(props) {
1251
1262
  const isEmptyOperator = filter.operator === "is_empty" || filter.operator === "is_not_empty";
1252
1263
  const hasCustomRenderer = !!field.customRenderer;
1253
1264
  const useInlineInput = !hasCustomRenderer && (field.type === "text" || field.type === "number");
1254
- const usePopover = !useInlineInput && !isEmptyOperator;
1265
+ const useDateInput = !hasCustomRenderer && field.type === "date" && !isEmptyOperator;
1266
+ const usePopover = !useInlineInput && !useDateInput && !isEmptyOperator;
1255
1267
  const handleOpenChange = (0, import_react2.useCallback)(
1256
1268
  (isOpen) => {
1257
1269
  setOpen(isOpen);
@@ -1312,6 +1324,7 @@ function FilterPill(props) {
1312
1324
  operator: filter.operator,
1313
1325
  operators,
1314
1326
  i18n,
1327
+ fieldType: field.type,
1315
1328
  onChange: (op) => {
1316
1329
  const newUpdates = { operator: op };
1317
1330
  if (op === "is_empty" || op === "is_not_empty") {
@@ -1332,6 +1345,15 @@ function FilterPill(props) {
1332
1345
  disabled
1333
1346
  }
1334
1347
  ),
1348
+ useDateInput && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1349
+ DateFilterValue,
1350
+ {
1351
+ filter,
1352
+ field,
1353
+ onUpdate,
1354
+ disabled
1355
+ }
1356
+ ),
1335
1357
  usePopover && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_popover2.Popover.Root, { open, onOpenChange: handleOpenChange, children: [
1336
1358
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1337
1359
  import_popover2.Popover.Trigger,
@@ -1389,9 +1411,13 @@ function FilterPill(props) {
1389
1411
  );
1390
1412
  }
1391
1413
  function OperatorDropdown(props) {
1392
- const { operator, operators, i18n, onChange, disabled } = props;
1414
+ const { operator, operators, i18n, fieldType, onChange, disabled } = props;
1415
+ const label = (op) => {
1416
+ var _a;
1417
+ return fieldType === "date" && ((_a = i18n.dateOperators) == null ? void 0 : _a[op]) || i18n.operators[op];
1418
+ };
1393
1419
  const hasSingleOperator = operators.length === 1;
1394
- const currentLabel = i18n.operators[operator];
1420
+ const currentLabel = label(operator);
1395
1421
  if (hasSingleOperator) {
1396
1422
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1397
1423
  "span",
@@ -1431,7 +1457,7 @@ function OperatorDropdown(props) {
1431
1457
  className: "gap-2",
1432
1458
  children: [
1433
1459
  op === operator && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons3.CheckIcon, { className: "size-4" }),
1434
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: op !== operator ? "pl-6" : "", children: i18n.operators[op] })
1460
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: op !== operator ? "pl-6" : "", children: label(op) })
1435
1461
  ]
1436
1462
  },
1437
1463
  op
@@ -1465,7 +1491,7 @@ function InlineValueInput2(props) {
1465
1491
  children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1466
1492
  "input",
1467
1493
  {
1468
- type: field.type === "number" ? "number" : "text",
1494
+ type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
1469
1495
  className: (0, import_shared_utils5.cn)(
1470
1496
  "bg-transparent border-none outline-none",
1471
1497
  "placeholder:text-muted-foreground",
@@ -1475,7 +1501,7 @@ function InlineValueInput2(props) {
1475
1501
  onChange: handleChange,
1476
1502
  placeholder,
1477
1503
  "aria-label": `${field.label} value`,
1478
- style: { width: getInputWidth2(filter.value, placeholder, 6) },
1504
+ style: field.type === "date" ? void 0 : { width: getInputWidth2(filter.value, placeholder, 6) },
1479
1505
  min: field.min,
1480
1506
  max: field.max,
1481
1507
  step: field.step,
@@ -1485,6 +1511,28 @@ function InlineValueInput2(props) {
1485
1511
  }
1486
1512
  );
1487
1513
  }
1514
+ function safeParseDate(value) {
1515
+ if (typeof value !== "string" || !value) return null;
1516
+ try {
1517
+ return (0, import_date_picker.parseDate)(value.slice(0, 10));
1518
+ } catch {
1519
+ return null;
1520
+ }
1521
+ }
1522
+ function DateFilterValue(props) {
1523
+ const { filter, field, onUpdate, disabled } = props;
1524
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "flex items-center px-1 py-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1525
+ import_date_picker.DateFieldPicker,
1526
+ {
1527
+ variant: "ghost",
1528
+ size: "sm",
1529
+ value: safeParseDate(filter.value),
1530
+ onChange: (v) => onUpdate({ value: v ? v.toString() : null }),
1531
+ isDisabled: disabled,
1532
+ "aria-label": field.label
1533
+ }
1534
+ ) });
1535
+ }
1488
1536
  function ValueEditor(props) {
1489
1537
  var _a, _b, _c, _d;
1490
1538
  const { filter, field, i18n, onUpdate, onClose } = props;
@@ -1871,6 +1919,36 @@ var filterBarMessages = (0, import_i18n6.defineMessages)({
1871
1919
  defaultMessage: "less or equal",
1872
1920
  description: "Operator: less than or equal"
1873
1921
  },
1922
+ op_date_on: {
1923
+ id: "filter-bar.operator.date_on",
1924
+ defaultMessage: "on",
1925
+ description: "Date operator: equals (on)"
1926
+ },
1927
+ op_date_not_on: {
1928
+ id: "filter-bar.operator.date_not_on",
1929
+ defaultMessage: "not on",
1930
+ description: "Date operator: not equals"
1931
+ },
1932
+ op_date_after: {
1933
+ id: "filter-bar.operator.date_after",
1934
+ defaultMessage: "after",
1935
+ description: "Date operator: greater than (after)"
1936
+ },
1937
+ op_date_before: {
1938
+ id: "filter-bar.operator.date_before",
1939
+ defaultMessage: "before",
1940
+ description: "Date operator: less than (before)"
1941
+ },
1942
+ op_date_on_or_after: {
1943
+ id: "filter-bar.operator.date_on_or_after",
1944
+ defaultMessage: "on or after",
1945
+ description: "Date operator: greater or equal"
1946
+ },
1947
+ op_date_on_or_before: {
1948
+ id: "filter-bar.operator.date_on_or_before",
1949
+ defaultMessage: "on or before",
1950
+ description: "Date operator: less or equal"
1951
+ },
1874
1952
  op_is_empty: {
1875
1953
  id: "filter-bar.operator.is_empty",
1876
1954
  defaultMessage: "is empty",
@@ -1947,6 +2025,14 @@ function FilterBar(props) {
1947
2025
  lte: t.formatMessage(filterBarMessages.op_lte),
1948
2026
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
1949
2027
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
2028
+ },
2029
+ dateOperators: {
2030
+ equals: t.formatMessage(filterBarMessages.op_date_on),
2031
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
2032
+ gt: t.formatMessage(filterBarMessages.op_date_after),
2033
+ lt: t.formatMessage(filterBarMessages.op_date_before),
2034
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
2035
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
1950
2036
  }
1951
2037
  };
1952
2038
  return {
@@ -1955,6 +2041,10 @@ function FilterBar(props) {
1955
2041
  operators: {
1956
2042
  ...defaultI18n.operators,
1957
2043
  ...i18nProp == null ? void 0 : i18nProp.operators
2044
+ },
2045
+ dateOperators: {
2046
+ ...defaultI18n.dateOperators,
2047
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
1958
2048
  }
1959
2049
  };
1960
2050
  }, [t, i18nProp]);
@@ -2129,6 +2219,14 @@ function SearchFilterBar(props) {
2129
2219
  lte: t.formatMessage(filterBarMessages.op_lte),
2130
2220
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
2131
2221
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
2222
+ },
2223
+ dateOperators: {
2224
+ equals: t.formatMessage(filterBarMessages.op_date_on),
2225
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
2226
+ gt: t.formatMessage(filterBarMessages.op_date_after),
2227
+ lt: t.formatMessage(filterBarMessages.op_date_before),
2228
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
2229
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
2132
2230
  }
2133
2231
  };
2134
2232
  return {
@@ -2137,6 +2235,10 @@ function SearchFilterBar(props) {
2137
2235
  operators: {
2138
2236
  ...defaultI18n.operators,
2139
2237
  ...i18nProp == null ? void 0 : i18nProp.operators
2238
+ },
2239
+ dateOperators: {
2240
+ ...defaultI18n.dateOperators,
2241
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
2140
2242
  }
2141
2243
  };
2142
2244
  }, [t, i18nProp]);
package/dist/index.mjs CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-LWDVRMCI.mjs";
8
8
  import {
9
9
  SearchFilterBar
10
- } from "./chunk-QRWKEHAH.mjs";
10
+ } from "./chunk-ZXC2YC65.mjs";
11
11
  import {
12
12
  FilterActive
13
13
  } from "./chunk-KBVTXOFI.mjs";
@@ -17,15 +17,15 @@ import {
17
17
  import "./chunk-PHESMHTT.mjs";
18
18
  import {
19
19
  FilterBar
20
- } from "./chunk-VII35ERE.mjs";
21
- import "./chunk-TCLE7EEK.mjs";
20
+ } from "./chunk-C5Z5JGHO.mjs";
21
+ import "./chunk-3LFPXMAB.mjs";
22
22
  import {
23
23
  filterBarMessages
24
- } from "./chunk-I7WCYMXD.mjs";
24
+ } from "./chunk-XXUWQU2D.mjs";
25
25
  import {
26
26
  getFilterDefaultValue,
27
27
  isBooleanSelectField
28
- } from "./chunk-HACVUP5P.mjs";
28
+ } from "./chunk-L3J62ATJ.mjs";
29
29
  import "./chunk-3WNAREG6.mjs";
30
30
  import {
31
31
  FilterGroup,
@@ -37,6 +37,7 @@ var import_react2 = require("react");
37
37
  var import_button = require("@kopexa/button");
38
38
  var import_checkbox = require("@kopexa/checkbox");
39
39
  var import_command = require("@kopexa/command");
40
+ var import_date_picker = require("@kopexa/date-picker");
40
41
  var import_dropdown_menu = require("@kopexa/dropdown-menu");
41
42
  var import_icons = require("@kopexa/icons");
42
43
  var import_input = require("@kopexa/input");
@@ -68,6 +69,16 @@ var DEFAULT_FILTER_BAR_OPERATORS = {
68
69
  "is_empty",
69
70
  "is_not_empty"
70
71
  ],
72
+ date: [
73
+ "equals",
74
+ "not_equals",
75
+ "gt",
76
+ "lt",
77
+ "gte",
78
+ "lte",
79
+ "is_empty",
80
+ "is_not_empty"
81
+ ],
71
82
  custom: ["equals", "not_equals"]
72
83
  };
73
84
  function isBooleanSelectField(field) {
@@ -142,7 +153,8 @@ function FilterPill(props) {
142
153
  const isEmptyOperator = filter.operator === "is_empty" || filter.operator === "is_not_empty";
143
154
  const hasCustomRenderer = !!field.customRenderer;
144
155
  const useInlineInput = !hasCustomRenderer && (field.type === "text" || field.type === "number");
145
- const usePopover = !useInlineInput && !isEmptyOperator;
156
+ const useDateInput = !hasCustomRenderer && field.type === "date" && !isEmptyOperator;
157
+ const usePopover = !useInlineInput && !useDateInput && !isEmptyOperator;
146
158
  const handleOpenChange = (0, import_react.useCallback)(
147
159
  (isOpen) => {
148
160
  setOpen(isOpen);
@@ -203,6 +215,7 @@ function FilterPill(props) {
203
215
  operator: filter.operator,
204
216
  operators,
205
217
  i18n,
218
+ fieldType: field.type,
206
219
  onChange: (op) => {
207
220
  const newUpdates = { operator: op };
208
221
  if (op === "is_empty" || op === "is_not_empty") {
@@ -223,6 +236,15 @@ function FilterPill(props) {
223
236
  disabled
224
237
  }
225
238
  ),
239
+ useDateInput && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
240
+ DateFilterValue,
241
+ {
242
+ filter,
243
+ field,
244
+ onUpdate,
245
+ disabled
246
+ }
247
+ ),
226
248
  usePopover && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_popover.Popover.Root, { open, onOpenChange: handleOpenChange, children: [
227
249
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
228
250
  import_popover.Popover.Trigger,
@@ -280,9 +302,13 @@ function FilterPill(props) {
280
302
  );
281
303
  }
282
304
  function OperatorDropdown(props) {
283
- const { operator, operators, i18n, onChange, disabled } = props;
305
+ const { operator, operators, i18n, fieldType, onChange, disabled } = props;
306
+ const label = (op) => {
307
+ var _a;
308
+ return fieldType === "date" && ((_a = i18n.dateOperators) == null ? void 0 : _a[op]) || i18n.operators[op];
309
+ };
284
310
  const hasSingleOperator = operators.length === 1;
285
- const currentLabel = i18n.operators[operator];
311
+ const currentLabel = label(operator);
286
312
  if (hasSingleOperator) {
287
313
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
288
314
  "span",
@@ -322,7 +348,7 @@ function OperatorDropdown(props) {
322
348
  className: "gap-2",
323
349
  children: [
324
350
  op === operator && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.CheckIcon, { className: "size-4" }),
325
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: i18n.operators[op] })
351
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: op !== operator ? "pl-6" : "", children: label(op) })
326
352
  ]
327
353
  },
328
354
  op
@@ -356,7 +382,7 @@ function InlineValueInput(props) {
356
382
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
357
383
  "input",
358
384
  {
359
- type: field.type === "number" ? "number" : "text",
385
+ type: field.type === "number" ? "number" : field.type === "date" ? "date" : "text",
360
386
  className: (0, import_shared_utils.cn)(
361
387
  "bg-transparent border-none outline-none",
362
388
  "placeholder:text-muted-foreground",
@@ -366,7 +392,7 @@ function InlineValueInput(props) {
366
392
  onChange: handleChange,
367
393
  placeholder,
368
394
  "aria-label": `${field.label} value`,
369
- style: { width: getInputWidth(filter.value, placeholder, 6) },
395
+ style: field.type === "date" ? void 0 : { width: getInputWidth(filter.value, placeholder, 6) },
370
396
  min: field.min,
371
397
  max: field.max,
372
398
  step: field.step,
@@ -376,6 +402,28 @@ function InlineValueInput(props) {
376
402
  }
377
403
  );
378
404
  }
405
+ function safeParseDate(value) {
406
+ if (typeof value !== "string" || !value) return null;
407
+ try {
408
+ return (0, import_date_picker.parseDate)(value.slice(0, 10));
409
+ } catch {
410
+ return null;
411
+ }
412
+ }
413
+ function DateFilterValue(props) {
414
+ const { filter, field, onUpdate, disabled } = props;
415
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "flex items-center px-1 py-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
416
+ import_date_picker.DateFieldPicker,
417
+ {
418
+ variant: "ghost",
419
+ size: "sm",
420
+ value: safeParseDate(filter.value),
421
+ onChange: (v) => onUpdate({ value: v ? v.toString() : null }),
422
+ isDisabled: disabled,
423
+ "aria-label": field.label
424
+ }
425
+ ) });
426
+ }
379
427
  function ValueEditor(props) {
380
428
  var _a, _b, _c, _d;
381
429
  const { filter, field, i18n, onUpdate, onClose } = props;
@@ -762,6 +810,36 @@ var filterBarMessages = (0, import_i18n.defineMessages)({
762
810
  defaultMessage: "less or equal",
763
811
  description: "Operator: less than or equal"
764
812
  },
813
+ op_date_on: {
814
+ id: "filter-bar.operator.date_on",
815
+ defaultMessage: "on",
816
+ description: "Date operator: equals (on)"
817
+ },
818
+ op_date_not_on: {
819
+ id: "filter-bar.operator.date_not_on",
820
+ defaultMessage: "not on",
821
+ description: "Date operator: not equals"
822
+ },
823
+ op_date_after: {
824
+ id: "filter-bar.operator.date_after",
825
+ defaultMessage: "after",
826
+ description: "Date operator: greater than (after)"
827
+ },
828
+ op_date_before: {
829
+ id: "filter-bar.operator.date_before",
830
+ defaultMessage: "before",
831
+ description: "Date operator: less than (before)"
832
+ },
833
+ op_date_on_or_after: {
834
+ id: "filter-bar.operator.date_on_or_after",
835
+ defaultMessage: "on or after",
836
+ description: "Date operator: greater or equal"
837
+ },
838
+ op_date_on_or_before: {
839
+ id: "filter-bar.operator.date_on_or_before",
840
+ defaultMessage: "on or before",
841
+ description: "Date operator: less or equal"
842
+ },
765
843
  op_is_empty: {
766
844
  id: "filter-bar.operator.is_empty",
767
845
  defaultMessage: "is empty",
@@ -851,6 +929,14 @@ function SearchFilterBar(props) {
851
929
  lte: t.formatMessage(filterBarMessages.op_lte),
852
930
  is_empty: t.formatMessage(filterBarMessages.op_is_empty),
853
931
  is_not_empty: t.formatMessage(filterBarMessages.op_is_not_empty)
932
+ },
933
+ dateOperators: {
934
+ equals: t.formatMessage(filterBarMessages.op_date_on),
935
+ not_equals: t.formatMessage(filterBarMessages.op_date_not_on),
936
+ gt: t.formatMessage(filterBarMessages.op_date_after),
937
+ lt: t.formatMessage(filterBarMessages.op_date_before),
938
+ gte: t.formatMessage(filterBarMessages.op_date_on_or_after),
939
+ lte: t.formatMessage(filterBarMessages.op_date_on_or_before)
854
940
  }
855
941
  };
856
942
  return {
@@ -859,6 +945,10 @@ function SearchFilterBar(props) {
859
945
  operators: {
860
946
  ...defaultI18n.operators,
861
947
  ...i18nProp == null ? void 0 : i18nProp.operators
948
+ },
949
+ dateOperators: {
950
+ ...defaultI18n.dateOperators,
951
+ ...i18nProp == null ? void 0 : i18nProp.dateOperators
862
952
  }
863
953
  };
864
954
  }, [t, i18nProp]);
@@ -2,10 +2,10 @@
2
2
  "use client";
3
3
  import {
4
4
  SearchFilterBar
5
- } from "./chunk-QRWKEHAH.mjs";
6
- import "./chunk-TCLE7EEK.mjs";
7
- import "./chunk-I7WCYMXD.mjs";
8
- import "./chunk-HACVUP5P.mjs";
5
+ } from "./chunk-ZXC2YC65.mjs";
6
+ import "./chunk-3LFPXMAB.mjs";
7
+ import "./chunk-XXUWQU2D.mjs";
8
+ import "./chunk-L3J62ATJ.mjs";
9
9
  export {
10
10
  SearchFilterBar
11
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kopexa/filter",
3
- "version": "0.0.83",
3
+ "version": "0.0.84",
4
4
  "description": "A filter component for building complex filtering interfaces",
5
5
  "keywords": [
6
6
  "filter",
@@ -30,26 +30,27 @@
30
30
  "peerDependencies": {
31
31
  "react": ">=19.0.0-rc.0",
32
32
  "react-dom": ">=19.0.0-rc.0",
33
- "@kopexa/theme": "17.34.0"
33
+ "@kopexa/theme": "17.35.0"
34
34
  },
35
35
  "dependencies": {
36
- "@kopexa/react-utils": "17.1.35",
37
- "@kopexa/shared-utils": "17.0.93",
38
- "@kopexa/use-controllable-state": "17.0.93",
39
- "@kopexa/use-debounced-callback": "17.0.93",
40
- "@kopexa/icons": "17.10.22",
41
- "@kopexa/button": "17.0.93",
42
- "@kopexa/input": "17.0.93",
43
- "@kopexa/select": "17.2.58",
44
- "@kopexa/combobox": "17.4.16",
45
- "@kopexa/i18n": "17.15.8",
46
- "@kopexa/popover": "17.2.58",
47
- "@kopexa/dropdown-menu": "17.0.93",
48
- "@kopexa/calendar": "17.0.93",
49
- "@kopexa/checkbox": "17.0.93",
50
- "@kopexa/switch": "17.2.58",
51
- "@kopexa/command": "17.0.93",
52
- "@kopexa/spinner": "17.0.93"
36
+ "@kopexa/react-utils": "17.1.36",
37
+ "@kopexa/shared-utils": "17.0.94",
38
+ "@kopexa/use-controllable-state": "17.0.94",
39
+ "@kopexa/use-debounced-callback": "17.0.94",
40
+ "@kopexa/icons": "17.10.23",
41
+ "@kopexa/button": "17.0.94",
42
+ "@kopexa/i18n": "17.16.0",
43
+ "@kopexa/input": "17.0.94",
44
+ "@kopexa/combobox": "17.4.17",
45
+ "@kopexa/calendar": "17.0.94",
46
+ "@kopexa/select": "17.2.59",
47
+ "@kopexa/date-picker": "1.5.0",
48
+ "@kopexa/popover": "17.2.59",
49
+ "@kopexa/dropdown-menu": "17.0.94",
50
+ "@kopexa/checkbox": "17.0.94",
51
+ "@kopexa/command": "17.0.94",
52
+ "@kopexa/switch": "17.2.59",
53
+ "@kopexa/spinner": "17.0.94"
53
54
  },
54
55
  "clean-package": "../../../clean-package.config.json",
55
56
  "module": "dist/index.mjs",