@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.
- package/LICENSE +201 -0
- package/dist/chunk-3WNAREG6.mjs +29 -0
- package/dist/chunk-63P4ITVP.mjs +263 -0
- package/dist/chunk-7KY2PDNL.mjs +136 -0
- package/dist/chunk-7QP7FRID.mjs +47 -0
- package/dist/chunk-EF4VI36D.mjs +36 -0
- package/dist/chunk-I3Z2T4N2.mjs +14 -0
- package/dist/chunk-PTJ7HZPA.mjs +164 -0
- package/dist/chunk-TBHYZZSX.mjs +139 -0
- package/dist/chunk-URDCG5NI.mjs +111 -0
- package/dist/filter-active.d.mts +13 -0
- package/dist/filter-active.d.ts +13 -0
- package/dist/filter-active.js +538 -0
- package/dist/filter-active.mjs +12 -0
- package/dist/filter-context.d.mts +28 -0
- package/dist/filter-context.d.ts +28 -0
- package/dist/filter-context.js +39 -0
- package/dist/filter-context.mjs +10 -0
- package/dist/filter-i18n.d.mts +20 -0
- package/dist/filter-i18n.d.ts +20 -0
- package/dist/filter-i18n.js +52 -0
- package/dist/filter-i18n.mjs +7 -0
- package/dist/filter-menu.d.mts +65 -0
- package/dist/filter-menu.d.ts +65 -0
- package/dist/filter-menu.js +169 -0
- package/dist/filter-menu.mjs +15 -0
- package/dist/filter-trigger.d.mts +14 -0
- package/dist/filter-trigger.d.ts +14 -0
- package/dist/filter-trigger.js +170 -0
- package/dist/filter-trigger.mjs +10 -0
- package/dist/filter-types.d.mts +60 -0
- package/dist/filter-types.d.ts +60 -0
- package/dist/filter-types.js +72 -0
- package/dist/filter-types.mjs +11 -0
- package/dist/filter-value-editor.d.mts +11 -0
- package/dist/filter-value-editor.d.ts +11 -0
- package/dist/filter-value-editor.js +414 -0
- package/dist/filter-value-editor.mjs +11 -0
- package/dist/filter.d.mts +24 -0
- package/dist/filter.d.ts +24 -0
- package/dist/filter.js +242 -0
- package/dist/filter.mjs +11 -0
- package/dist/index.d.mts +13 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +909 -0
- package/dist/index.mjs +39 -0
- package/dist/messages.d.mts +104 -0
- package/dist/messages.d.ts +104 -0
- package/dist/messages.js +134 -0
- package/dist/messages.mjs +7 -0
- package/package.json +69 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Filter field types supported by the component
|
|
5
|
+
*/
|
|
6
|
+
type FilterFieldType = "text" | "number" | "select" | "multiselect" | "date" | "daterange" | "boolean";
|
|
7
|
+
/**
|
|
8
|
+
* Filter operators for comparing values
|
|
9
|
+
*/
|
|
10
|
+
type FilterOperator = "equals" | "not_equals" | "contains" | "not_contains" | "starts_with" | "ends_with" | "gt" | "lt" | "gte" | "lte" | "between" | "is_empty" | "is_not_empty";
|
|
11
|
+
/**
|
|
12
|
+
* Option for select/multiselect fields
|
|
13
|
+
*/
|
|
14
|
+
interface FilterOption {
|
|
15
|
+
value: string;
|
|
16
|
+
label: string;
|
|
17
|
+
icon?: ReactNode;
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* An active filter value
|
|
22
|
+
*/
|
|
23
|
+
interface FilterValue {
|
|
24
|
+
id: string;
|
|
25
|
+
fieldId: string;
|
|
26
|
+
operator: FilterOperator;
|
|
27
|
+
value: unknown;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Configuration for a filter field
|
|
31
|
+
*/
|
|
32
|
+
interface FilterFieldConfig {
|
|
33
|
+
id: string;
|
|
34
|
+
label: string;
|
|
35
|
+
icon?: ReactNode;
|
|
36
|
+
type: FilterFieldType;
|
|
37
|
+
operators?: FilterOperator[];
|
|
38
|
+
options?: FilterOption[];
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
min?: number;
|
|
41
|
+
max?: number;
|
|
42
|
+
step?: number;
|
|
43
|
+
searchable?: boolean;
|
|
44
|
+
group?: string;
|
|
45
|
+
disabled?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Default operators per field type
|
|
49
|
+
*/
|
|
50
|
+
declare const DEFAULT_OPERATORS: Record<FilterFieldType, FilterOperator[]>;
|
|
51
|
+
/**
|
|
52
|
+
* Get default operator for a field type
|
|
53
|
+
*/
|
|
54
|
+
declare function getDefaultOperator(type: FilterFieldType): FilterOperator;
|
|
55
|
+
/**
|
|
56
|
+
* Generate a unique filter ID
|
|
57
|
+
*/
|
|
58
|
+
declare function generateFilterId(): string;
|
|
59
|
+
|
|
60
|
+
export { DEFAULT_OPERATORS, type FilterFieldConfig, type FilterFieldType, type FilterOperator, type FilterOption, type FilterValue, generateFilterId, getDefaultOperator };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/filter-types.ts
|
|
22
|
+
var filter_types_exports = {};
|
|
23
|
+
__export(filter_types_exports, {
|
|
24
|
+
DEFAULT_OPERATORS: () => DEFAULT_OPERATORS,
|
|
25
|
+
generateFilterId: () => generateFilterId,
|
|
26
|
+
getDefaultOperator: () => getDefaultOperator
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(filter_types_exports);
|
|
29
|
+
var DEFAULT_OPERATORS = {
|
|
30
|
+
text: [
|
|
31
|
+
"equals",
|
|
32
|
+
"not_equals",
|
|
33
|
+
"contains",
|
|
34
|
+
"not_contains",
|
|
35
|
+
"starts_with",
|
|
36
|
+
"ends_with",
|
|
37
|
+
"is_empty",
|
|
38
|
+
"is_not_empty"
|
|
39
|
+
],
|
|
40
|
+
number: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
|
|
41
|
+
select: ["equals", "not_equals", "is_empty", "is_not_empty"],
|
|
42
|
+
multiselect: ["equals", "not_equals", "is_empty", "is_not_empty"],
|
|
43
|
+
date: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
|
|
44
|
+
daterange: ["between"],
|
|
45
|
+
boolean: ["equals"]
|
|
46
|
+
};
|
|
47
|
+
function getDefaultOperator(type) {
|
|
48
|
+
switch (type) {
|
|
49
|
+
case "text":
|
|
50
|
+
return "contains";
|
|
51
|
+
case "number":
|
|
52
|
+
case "date":
|
|
53
|
+
case "select":
|
|
54
|
+
case "multiselect":
|
|
55
|
+
return "equals";
|
|
56
|
+
case "daterange":
|
|
57
|
+
return "between";
|
|
58
|
+
case "boolean":
|
|
59
|
+
return "equals";
|
|
60
|
+
default:
|
|
61
|
+
return "equals";
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function generateFilterId() {
|
|
65
|
+
return `filter-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
66
|
+
}
|
|
67
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
68
|
+
0 && (module.exports = {
|
|
69
|
+
DEFAULT_OPERATORS,
|
|
70
|
+
generateFilterId,
|
|
71
|
+
getDefaultOperator
|
|
72
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { FilterValue, FilterFieldConfig } from './filter-types.mjs';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterValueEditorProps {
|
|
6
|
+
filter: FilterValue;
|
|
7
|
+
field: FilterFieldConfig;
|
|
8
|
+
}
|
|
9
|
+
declare function FilterValueEditor({ filter, field }: FilterValueEditorProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { FilterValueEditor };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { FilterValue, FilterFieldConfig } from './filter-types.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterValueEditorProps {
|
|
6
|
+
filter: FilterValue;
|
|
7
|
+
field: FilterFieldConfig;
|
|
8
|
+
}
|
|
9
|
+
declare function FilterValueEditor({ filter, field }: FilterValueEditorProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { FilterValueEditor };
|
|
@@ -0,0 +1,414 @@
|
|
|
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-value-editor.tsx
|
|
23
|
+
var filter_value_editor_exports = {};
|
|
24
|
+
__export(filter_value_editor_exports, {
|
|
25
|
+
FilterValueEditor: () => FilterValueEditor
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(filter_value_editor_exports);
|
|
28
|
+
var import_checkbox = require("@kopexa/checkbox");
|
|
29
|
+
var import_i18n2 = require("@kopexa/i18n");
|
|
30
|
+
var import_input = require("@kopexa/input");
|
|
31
|
+
var import_select = require("@kopexa/select");
|
|
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-types.ts
|
|
42
|
+
var DEFAULT_OPERATORS = {
|
|
43
|
+
text: [
|
|
44
|
+
"equals",
|
|
45
|
+
"not_equals",
|
|
46
|
+
"contains",
|
|
47
|
+
"not_contains",
|
|
48
|
+
"starts_with",
|
|
49
|
+
"ends_with",
|
|
50
|
+
"is_empty",
|
|
51
|
+
"is_not_empty"
|
|
52
|
+
],
|
|
53
|
+
number: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
|
|
54
|
+
select: ["equals", "not_equals", "is_empty", "is_not_empty"],
|
|
55
|
+
multiselect: ["equals", "not_equals", "is_empty", "is_not_empty"],
|
|
56
|
+
date: ["equals", "not_equals", "gt", "lt", "gte", "lte", "between"],
|
|
57
|
+
daterange: ["between"],
|
|
58
|
+
boolean: ["equals"]
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// src/messages.ts
|
|
62
|
+
var import_i18n = require("@kopexa/i18n");
|
|
63
|
+
var messages = (0, import_i18n.defineMessages)({
|
|
64
|
+
add_filter: {
|
|
65
|
+
id: "filter.add_filter",
|
|
66
|
+
defaultMessage: "Add Filter",
|
|
67
|
+
description: "Button text for adding a new filter"
|
|
68
|
+
},
|
|
69
|
+
clear_all: {
|
|
70
|
+
id: "filter.clear_all",
|
|
71
|
+
defaultMessage: "Clear all",
|
|
72
|
+
description: "Button text for clearing all filters"
|
|
73
|
+
},
|
|
74
|
+
no_fields: {
|
|
75
|
+
id: "filter.no_fields",
|
|
76
|
+
defaultMessage: "No filter options available",
|
|
77
|
+
description: "Message when no filter fields are configured"
|
|
78
|
+
},
|
|
79
|
+
apply: {
|
|
80
|
+
id: "filter.apply",
|
|
81
|
+
defaultMessage: "Apply",
|
|
82
|
+
description: "Button text for applying a filter value"
|
|
83
|
+
},
|
|
84
|
+
cancel: {
|
|
85
|
+
id: "filter.cancel",
|
|
86
|
+
defaultMessage: "Cancel",
|
|
87
|
+
description: "Button text for canceling filter editing"
|
|
88
|
+
},
|
|
89
|
+
select_value: {
|
|
90
|
+
id: "filter.select_value",
|
|
91
|
+
defaultMessage: "Select value...",
|
|
92
|
+
description: "Placeholder for value selection"
|
|
93
|
+
},
|
|
94
|
+
enter_value: {
|
|
95
|
+
id: "filter.enter_value",
|
|
96
|
+
defaultMessage: "Enter value...",
|
|
97
|
+
description: "Placeholder for value input"
|
|
98
|
+
},
|
|
99
|
+
// Operators
|
|
100
|
+
op_equals: {
|
|
101
|
+
id: "filter.operator.equals",
|
|
102
|
+
defaultMessage: "is",
|
|
103
|
+
description: "Operator: equals"
|
|
104
|
+
},
|
|
105
|
+
op_not_equals: {
|
|
106
|
+
id: "filter.operator.not_equals",
|
|
107
|
+
defaultMessage: "is not",
|
|
108
|
+
description: "Operator: not equals"
|
|
109
|
+
},
|
|
110
|
+
op_contains: {
|
|
111
|
+
id: "filter.operator.contains",
|
|
112
|
+
defaultMessage: "contains",
|
|
113
|
+
description: "Operator: contains"
|
|
114
|
+
},
|
|
115
|
+
op_not_contains: {
|
|
116
|
+
id: "filter.operator.not_contains",
|
|
117
|
+
defaultMessage: "does not contain",
|
|
118
|
+
description: "Operator: does not contain"
|
|
119
|
+
},
|
|
120
|
+
op_starts_with: {
|
|
121
|
+
id: "filter.operator.starts_with",
|
|
122
|
+
defaultMessage: "starts with",
|
|
123
|
+
description: "Operator: starts with"
|
|
124
|
+
},
|
|
125
|
+
op_ends_with: {
|
|
126
|
+
id: "filter.operator.ends_with",
|
|
127
|
+
defaultMessage: "ends with",
|
|
128
|
+
description: "Operator: ends with"
|
|
129
|
+
},
|
|
130
|
+
op_gt: {
|
|
131
|
+
id: "filter.operator.gt",
|
|
132
|
+
defaultMessage: "greater than",
|
|
133
|
+
description: "Operator: greater than"
|
|
134
|
+
},
|
|
135
|
+
op_lt: {
|
|
136
|
+
id: "filter.operator.lt",
|
|
137
|
+
defaultMessage: "less than",
|
|
138
|
+
description: "Operator: less than"
|
|
139
|
+
},
|
|
140
|
+
op_gte: {
|
|
141
|
+
id: "filter.operator.gte",
|
|
142
|
+
defaultMessage: "greater or equal",
|
|
143
|
+
description: "Operator: greater than or equal"
|
|
144
|
+
},
|
|
145
|
+
op_lte: {
|
|
146
|
+
id: "filter.operator.lte",
|
|
147
|
+
defaultMessage: "less or equal",
|
|
148
|
+
description: "Operator: less than or equal"
|
|
149
|
+
},
|
|
150
|
+
op_between: {
|
|
151
|
+
id: "filter.operator.between",
|
|
152
|
+
defaultMessage: "between",
|
|
153
|
+
description: "Operator: between"
|
|
154
|
+
},
|
|
155
|
+
op_is_empty: {
|
|
156
|
+
id: "filter.operator.is_empty",
|
|
157
|
+
defaultMessage: "is empty",
|
|
158
|
+
description: "Operator: is empty"
|
|
159
|
+
},
|
|
160
|
+
op_is_not_empty: {
|
|
161
|
+
id: "filter.operator.is_not_empty",
|
|
162
|
+
defaultMessage: "is not empty",
|
|
163
|
+
description: "Operator: is not empty"
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// src/filter-value-editor.tsx
|
|
168
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
169
|
+
function FilterValueEditor({ filter, field }) {
|
|
170
|
+
var _a;
|
|
171
|
+
const { styles, updateFilter, setEditingFilterId } = useFilterContext();
|
|
172
|
+
const t = (0, import_i18n2.useSafeIntl)();
|
|
173
|
+
const operators = (_a = field.operators) != null ? _a : DEFAULT_OPERATORS[field.type];
|
|
174
|
+
const handleOperatorChange = (newOperator) => {
|
|
175
|
+
updateFilter(filter.id, { operator: newOperator });
|
|
176
|
+
if (newOperator === "is_empty" || newOperator === "is_not_empty") {
|
|
177
|
+
setEditingFilterId(null);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const handleValueChange = (newValue) => {
|
|
181
|
+
updateFilter(filter.id, { value: newValue });
|
|
182
|
+
};
|
|
183
|
+
const handleSelectValue = (newValue) => {
|
|
184
|
+
updateFilter(filter.id, { value: newValue });
|
|
185
|
+
setEditingFilterId(null);
|
|
186
|
+
};
|
|
187
|
+
const getOperatorLabel = (op) => {
|
|
188
|
+
const key = `op_${op}`;
|
|
189
|
+
return messages[key] ? t.formatMessage(messages[key]) : op;
|
|
190
|
+
};
|
|
191
|
+
const needsValue = filter.operator !== "is_empty" && filter.operator !== "is_not_empty";
|
|
192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "data-slot": "filter-value-editor", children: [
|
|
193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorHeader(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.editorTitle(), children: field.label }) }),
|
|
194
|
+
operators.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorOperator(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
195
|
+
import_select.Select,
|
|
196
|
+
{
|
|
197
|
+
value: filter.operator,
|
|
198
|
+
onValueChange: (val) => handleOperatorChange(val),
|
|
199
|
+
size: "sm",
|
|
200
|
+
children: [
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Trigger, { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Value, {}) }),
|
|
202
|
+
/* @__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)) })
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
) }),
|
|
206
|
+
needsValue && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: styles.editorInput(), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
207
|
+
ValueInput,
|
|
208
|
+
{
|
|
209
|
+
field,
|
|
210
|
+
operator: filter.operator,
|
|
211
|
+
value: filter.value,
|
|
212
|
+
onChange: handleValueChange,
|
|
213
|
+
onSelect: handleSelectValue
|
|
214
|
+
}
|
|
215
|
+
) })
|
|
216
|
+
] });
|
|
217
|
+
}
|
|
218
|
+
function ValueInput({
|
|
219
|
+
field,
|
|
220
|
+
operator,
|
|
221
|
+
value,
|
|
222
|
+
onChange,
|
|
223
|
+
onSelect
|
|
224
|
+
}) {
|
|
225
|
+
var _a, _b, _c, _d, _e, _f;
|
|
226
|
+
const t = (0, import_i18n2.useSafeIntl)();
|
|
227
|
+
switch (field.type) {
|
|
228
|
+
case "text":
|
|
229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
230
|
+
import_input.Input,
|
|
231
|
+
{
|
|
232
|
+
value: String(value != null ? value : ""),
|
|
233
|
+
onChange: (e) => onChange(e.target.value),
|
|
234
|
+
placeholder: (_a = field.placeholder) != null ? _a : t.formatMessage(messages.enter_value),
|
|
235
|
+
size: "sm",
|
|
236
|
+
autoFocus: true
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
case "number":
|
|
240
|
+
if (operator === "between") {
|
|
241
|
+
const [min, max] = Array.isArray(value) ? value : [void 0, void 0];
|
|
242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
243
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
244
|
+
import_input.Input,
|
|
245
|
+
{
|
|
246
|
+
type: "number",
|
|
247
|
+
value: min != null ? min : "",
|
|
248
|
+
onChange: (e) => onChange([
|
|
249
|
+
e.target.value ? Number(e.target.value) : void 0,
|
|
250
|
+
max
|
|
251
|
+
]),
|
|
252
|
+
placeholder: "Min",
|
|
253
|
+
min: field.min,
|
|
254
|
+
max: field.max,
|
|
255
|
+
step: field.step,
|
|
256
|
+
size: "sm",
|
|
257
|
+
autoFocus: true
|
|
258
|
+
}
|
|
259
|
+
),
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "-" }),
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
262
|
+
import_input.Input,
|
|
263
|
+
{
|
|
264
|
+
type: "number",
|
|
265
|
+
value: max != null ? max : "",
|
|
266
|
+
onChange: (e) => onChange([
|
|
267
|
+
min,
|
|
268
|
+
e.target.value ? Number(e.target.value) : void 0
|
|
269
|
+
]),
|
|
270
|
+
placeholder: "Max",
|
|
271
|
+
min: field.min,
|
|
272
|
+
max: field.max,
|
|
273
|
+
step: field.step,
|
|
274
|
+
size: "sm"
|
|
275
|
+
}
|
|
276
|
+
)
|
|
277
|
+
] });
|
|
278
|
+
}
|
|
279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
280
|
+
import_input.Input,
|
|
281
|
+
{
|
|
282
|
+
type: "number",
|
|
283
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
284
|
+
onChange: (e) => onChange(e.target.value ? Number(e.target.value) : void 0),
|
|
285
|
+
placeholder: (_b = field.placeholder) != null ? _b : t.formatMessage(messages.enter_value),
|
|
286
|
+
min: field.min,
|
|
287
|
+
max: field.max,
|
|
288
|
+
step: field.step,
|
|
289
|
+
size: "sm",
|
|
290
|
+
autoFocus: true
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
case "select":
|
|
294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_select.Select, { value: String(value != null ? value : ""), onValueChange: onSelect, size: "sm", children: [
|
|
295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_select.Select.Trigger, { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
296
|
+
import_select.Select.Value,
|
|
297
|
+
{
|
|
298
|
+
placeholder: (_c = field.placeholder) != null ? _c : t.formatMessage(messages.select_value)
|
|
299
|
+
}
|
|
300
|
+
) }),
|
|
301
|
+
/* @__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)(
|
|
302
|
+
import_select.Select.Item,
|
|
303
|
+
{
|
|
304
|
+
value: option.value,
|
|
305
|
+
disabled: option.disabled,
|
|
306
|
+
children: [
|
|
307
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "mr-2 size-4", children: option.icon }),
|
|
308
|
+
option.label
|
|
309
|
+
]
|
|
310
|
+
},
|
|
311
|
+
option.value
|
|
312
|
+
)) })
|
|
313
|
+
] });
|
|
314
|
+
case "multiselect": {
|
|
315
|
+
const selectedValues = Array.isArray(value) ? value : [];
|
|
316
|
+
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) => (
|
|
317
|
+
// biome-ignore lint/a11y/noLabelWithoutControl: Checkbox is a custom form control inside the label
|
|
318
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
319
|
+
"label",
|
|
320
|
+
{
|
|
321
|
+
className: "flex items-center gap-2 cursor-pointer",
|
|
322
|
+
children: [
|
|
323
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
324
|
+
import_checkbox.Checkbox,
|
|
325
|
+
{
|
|
326
|
+
checked: selectedValues.includes(option.value),
|
|
327
|
+
onCheckedChange: (checked) => {
|
|
328
|
+
if (checked) {
|
|
329
|
+
onChange([...selectedValues, option.value]);
|
|
330
|
+
} else {
|
|
331
|
+
onChange(selectedValues.filter((v) => v !== option.value));
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
disabled: option.disabled
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
option.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "size-4", children: option.icon }),
|
|
338
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm", children: option.label })
|
|
339
|
+
]
|
|
340
|
+
},
|
|
341
|
+
option.value
|
|
342
|
+
)
|
|
343
|
+
)) });
|
|
344
|
+
}
|
|
345
|
+
case "boolean":
|
|
346
|
+
return (
|
|
347
|
+
// biome-ignore lint/a11y/noLabelWithoutControl: Checkbox is a custom form control inside the label
|
|
348
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { className: "flex items-center gap-2 cursor-pointer", children: [
|
|
349
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
350
|
+
import_checkbox.Checkbox,
|
|
351
|
+
{
|
|
352
|
+
checked: Boolean(value),
|
|
353
|
+
onCheckedChange: (checked) => onSelect(Boolean(checked))
|
|
354
|
+
}
|
|
355
|
+
),
|
|
356
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-sm", children: field.label })
|
|
357
|
+
] })
|
|
358
|
+
);
|
|
359
|
+
case "date":
|
|
360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
361
|
+
import_input.Input,
|
|
362
|
+
{
|
|
363
|
+
type: "date",
|
|
364
|
+
value: value instanceof Date ? value.toISOString().split("T")[0] : String(value != null ? value : ""),
|
|
365
|
+
onChange: (e) => onChange(e.target.value ? new Date(e.target.value) : void 0),
|
|
366
|
+
size: "sm"
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
case "daterange": {
|
|
370
|
+
const [start, end] = Array.isArray(value) ? value : [void 0, void 0];
|
|
371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
372
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
373
|
+
import_input.Input,
|
|
374
|
+
{
|
|
375
|
+
type: "date",
|
|
376
|
+
value: start instanceof Date ? start.toISOString().split("T")[0] : String(start != null ? start : ""),
|
|
377
|
+
onChange: (e) => onChange([
|
|
378
|
+
e.target.value ? new Date(e.target.value) : void 0,
|
|
379
|
+
end
|
|
380
|
+
]),
|
|
381
|
+
size: "sm"
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "text-muted-foreground", children: "-" }),
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
386
|
+
import_input.Input,
|
|
387
|
+
{
|
|
388
|
+
type: "date",
|
|
389
|
+
value: end instanceof Date ? end.toISOString().split("T")[0] : String(end != null ? end : ""),
|
|
390
|
+
onChange: (e) => onChange([
|
|
391
|
+
start,
|
|
392
|
+
e.target.value ? new Date(e.target.value) : void 0
|
|
393
|
+
]),
|
|
394
|
+
size: "sm"
|
|
395
|
+
}
|
|
396
|
+
)
|
|
397
|
+
] });
|
|
398
|
+
}
|
|
399
|
+
default:
|
|
400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
401
|
+
import_input.Input,
|
|
402
|
+
{
|
|
403
|
+
value: String(value != null ? value : ""),
|
|
404
|
+
onChange: (e) => onChange(e.target.value),
|
|
405
|
+
placeholder: (_f = field.placeholder) != null ? _f : t.formatMessage(messages.enter_value),
|
|
406
|
+
size: "sm"
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
412
|
+
0 && (module.exports = {
|
|
413
|
+
FilterValueEditor
|
|
414
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { FilterVariantProps } from '@kopexa/theme';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { FilterI18nConfig } from './filter-i18n.mjs';
|
|
5
|
+
import { FilterValue } from './filter-types.mjs';
|
|
6
|
+
|
|
7
|
+
interface FilterProps extends Omit<React.ComponentProps<"div">, "onChange" | "defaultValue">, FilterVariantProps {
|
|
8
|
+
/** Controlled filter values */
|
|
9
|
+
value?: FilterValue[];
|
|
10
|
+
/** Callback when filters change */
|
|
11
|
+
onChange?: (filters: FilterValue[]) => void;
|
|
12
|
+
/** Allow multiple filters for the same field */
|
|
13
|
+
allowMultiple?: boolean;
|
|
14
|
+
/** i18n configuration */
|
|
15
|
+
i18n?: Partial<FilterI18nConfig>;
|
|
16
|
+
/** Children */
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
declare function Filter(props: FilterProps): react_jsx_runtime.JSX.Element;
|
|
20
|
+
declare namespace Filter {
|
|
21
|
+
var displayName: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Filter, type FilterProps };
|
package/dist/filter.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { FilterVariantProps } from '@kopexa/theme';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { FilterI18nConfig } from './filter-i18n.js';
|
|
5
|
+
import { FilterValue } from './filter-types.js';
|
|
6
|
+
|
|
7
|
+
interface FilterProps extends Omit<React.ComponentProps<"div">, "onChange" | "defaultValue">, FilterVariantProps {
|
|
8
|
+
/** Controlled filter values */
|
|
9
|
+
value?: FilterValue[];
|
|
10
|
+
/** Callback when filters change */
|
|
11
|
+
onChange?: (filters: FilterValue[]) => void;
|
|
12
|
+
/** Allow multiple filters for the same field */
|
|
13
|
+
allowMultiple?: boolean;
|
|
14
|
+
/** i18n configuration */
|
|
15
|
+
i18n?: Partial<FilterI18nConfig>;
|
|
16
|
+
/** Children */
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
declare function Filter(props: FilterProps): react_jsx_runtime.JSX.Element;
|
|
20
|
+
declare namespace Filter {
|
|
21
|
+
var displayName: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { Filter, type FilterProps };
|