@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,20 @@
|
|
|
1
|
+
import { FilterOperator } from './filter-types.js';
|
|
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 };
|
|
@@ -0,0 +1,52 @@
|
|
|
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-i18n.ts
|
|
22
|
+
var filter_i18n_exports = {};
|
|
23
|
+
__export(filter_i18n_exports, {
|
|
24
|
+
DEFAULT_I18N: () => DEFAULT_I18N
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(filter_i18n_exports);
|
|
27
|
+
var DEFAULT_I18N = {
|
|
28
|
+
addFilter: "Add Filter",
|
|
29
|
+
clearAll: "Clear all",
|
|
30
|
+
noFields: "No filter options available",
|
|
31
|
+
selectValue: "Select value...",
|
|
32
|
+
enterValue: "Enter value...",
|
|
33
|
+
operators: {
|
|
34
|
+
equals: "is",
|
|
35
|
+
not_equals: "is not",
|
|
36
|
+
contains: "contains",
|
|
37
|
+
not_contains: "does not contain",
|
|
38
|
+
starts_with: "starts with",
|
|
39
|
+
ends_with: "ends with",
|
|
40
|
+
gt: "greater than",
|
|
41
|
+
lt: "less than",
|
|
42
|
+
gte: "greater or equal",
|
|
43
|
+
lte: "less or equal",
|
|
44
|
+
between: "between",
|
|
45
|
+
is_empty: "is empty",
|
|
46
|
+
is_not_empty: "is not empty"
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
50
|
+
0 && (module.exports = {
|
|
51
|
+
DEFAULT_I18N
|
|
52
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { FilterFieldType, FilterOption, FilterOperator } from './filter-types.mjs';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterMenuProps {
|
|
6
|
+
/** Children (FilterGroup, FilterItem components) */
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
/** Additional class name */
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* FilterMenu renders both:
|
|
13
|
+
* 1. A hidden container where FilterItems register themselves (always mounted)
|
|
14
|
+
* 2. The actual dropdown content with menu items based on registered fields
|
|
15
|
+
*/
|
|
16
|
+
declare function FilterMenu(props: FilterMenuProps): react_jsx_runtime.JSX.Element;
|
|
17
|
+
declare namespace FilterMenu {
|
|
18
|
+
var displayName: string;
|
|
19
|
+
}
|
|
20
|
+
interface FilterGroupProps {
|
|
21
|
+
/** Group label */
|
|
22
|
+
label?: string;
|
|
23
|
+
/** Children (FilterItem components) */
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
26
|
+
declare function FilterGroup(props: FilterGroupProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
declare namespace FilterGroup {
|
|
28
|
+
var displayName: string;
|
|
29
|
+
}
|
|
30
|
+
interface FilterItemProps {
|
|
31
|
+
/** Field ID (must be unique) */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Display label */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Icon */
|
|
36
|
+
icon?: ReactNode;
|
|
37
|
+
/** Field type */
|
|
38
|
+
type: FilterFieldType;
|
|
39
|
+
/** Options for select/multiselect */
|
|
40
|
+
options?: FilterOption[];
|
|
41
|
+
/** Custom operators */
|
|
42
|
+
operators?: FilterOperator[];
|
|
43
|
+
/** Placeholder text */
|
|
44
|
+
placeholder?: string;
|
|
45
|
+
/** Min value (for number) */
|
|
46
|
+
min?: number;
|
|
47
|
+
/** Max value (for number) */
|
|
48
|
+
max?: number;
|
|
49
|
+
/** Step value (for number) */
|
|
50
|
+
step?: number;
|
|
51
|
+
/** Enable search (for select) */
|
|
52
|
+
searchable?: boolean;
|
|
53
|
+
/** Disabled state */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
}
|
|
56
|
+
declare function FilterItem(props: FilterItemProps): null;
|
|
57
|
+
declare namespace FilterItem {
|
|
58
|
+
var displayName: string;
|
|
59
|
+
}
|
|
60
|
+
declare function FilterMenuSeparator(): react_jsx_runtime.JSX.Element;
|
|
61
|
+
declare namespace FilterMenuSeparator {
|
|
62
|
+
var displayName: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { FilterGroup, type FilterGroupProps, FilterItem, type FilterItemProps, FilterMenu, type FilterMenuProps, FilterMenuSeparator };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { FilterFieldType, FilterOption, FilterOperator } from './filter-types.js';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
import { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterMenuProps {
|
|
6
|
+
/** Children (FilterGroup, FilterItem components) */
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
/** Additional class name */
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* FilterMenu renders both:
|
|
13
|
+
* 1. A hidden container where FilterItems register themselves (always mounted)
|
|
14
|
+
* 2. The actual dropdown content with menu items based on registered fields
|
|
15
|
+
*/
|
|
16
|
+
declare function FilterMenu(props: FilterMenuProps): react_jsx_runtime.JSX.Element;
|
|
17
|
+
declare namespace FilterMenu {
|
|
18
|
+
var displayName: string;
|
|
19
|
+
}
|
|
20
|
+
interface FilterGroupProps {
|
|
21
|
+
/** Group label */
|
|
22
|
+
label?: string;
|
|
23
|
+
/** Children (FilterItem components) */
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
26
|
+
declare function FilterGroup(props: FilterGroupProps): react_jsx_runtime.JSX.Element;
|
|
27
|
+
declare namespace FilterGroup {
|
|
28
|
+
var displayName: string;
|
|
29
|
+
}
|
|
30
|
+
interface FilterItemProps {
|
|
31
|
+
/** Field ID (must be unique) */
|
|
32
|
+
id: string;
|
|
33
|
+
/** Display label */
|
|
34
|
+
label: string;
|
|
35
|
+
/** Icon */
|
|
36
|
+
icon?: ReactNode;
|
|
37
|
+
/** Field type */
|
|
38
|
+
type: FilterFieldType;
|
|
39
|
+
/** Options for select/multiselect */
|
|
40
|
+
options?: FilterOption[];
|
|
41
|
+
/** Custom operators */
|
|
42
|
+
operators?: FilterOperator[];
|
|
43
|
+
/** Placeholder text */
|
|
44
|
+
placeholder?: string;
|
|
45
|
+
/** Min value (for number) */
|
|
46
|
+
min?: number;
|
|
47
|
+
/** Max value (for number) */
|
|
48
|
+
max?: number;
|
|
49
|
+
/** Step value (for number) */
|
|
50
|
+
step?: number;
|
|
51
|
+
/** Enable search (for select) */
|
|
52
|
+
searchable?: boolean;
|
|
53
|
+
/** Disabled state */
|
|
54
|
+
disabled?: boolean;
|
|
55
|
+
}
|
|
56
|
+
declare function FilterItem(props: FilterItemProps): null;
|
|
57
|
+
declare namespace FilterItem {
|
|
58
|
+
var displayName: string;
|
|
59
|
+
}
|
|
60
|
+
declare function FilterMenuSeparator(): react_jsx_runtime.JSX.Element;
|
|
61
|
+
declare namespace FilterMenuSeparator {
|
|
62
|
+
var displayName: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { FilterGroup, type FilterGroupProps, FilterItem, type FilterItemProps, FilterMenu, type FilterMenuProps, FilterMenuSeparator };
|
|
@@ -0,0 +1,169 @@
|
|
|
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-menu.tsx
|
|
23
|
+
var filter_menu_exports = {};
|
|
24
|
+
__export(filter_menu_exports, {
|
|
25
|
+
FilterGroup: () => FilterGroup,
|
|
26
|
+
FilterItem: () => FilterItem,
|
|
27
|
+
FilterMenu: () => FilterMenu,
|
|
28
|
+
FilterMenuSeparator: () => FilterMenuSeparator
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(filter_menu_exports);
|
|
31
|
+
var import_dropdown_menu = require("@kopexa/dropdown-menu");
|
|
32
|
+
var import_shared_utils = require("@kopexa/shared-utils");
|
|
33
|
+
var import_react = require("react");
|
|
34
|
+
|
|
35
|
+
// src/filter-context.tsx
|
|
36
|
+
var import_react_utils = require("@kopexa/react-utils");
|
|
37
|
+
var [FilterProvider, useFilterContext] = (0, import_react_utils.createContext)({
|
|
38
|
+
name: "FilterContext",
|
|
39
|
+
strict: true,
|
|
40
|
+
errorMessage: "useFilterContext must be used within a Filter component. Make sure to wrap your FilterMenu, FilterTrigger, etc. inside a <Filter> component."
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// src/filter-menu.tsx
|
|
44
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
45
|
+
function FilterMenu(props) {
|
|
46
|
+
var _a;
|
|
47
|
+
const { children, className } = props;
|
|
48
|
+
const { fields, styles, addFilter, allowMultiple, value } = useFilterContext();
|
|
49
|
+
const fieldGroups = /* @__PURE__ */ new Map();
|
|
50
|
+
for (const [id, field] of fields) {
|
|
51
|
+
const group = field.group;
|
|
52
|
+
if (!fieldGroups.has(group)) {
|
|
53
|
+
fieldGroups.set(group, /* @__PURE__ */ new Map());
|
|
54
|
+
}
|
|
55
|
+
(_a = fieldGroups.get(group)) == null ? void 0 : _a.set(id, field);
|
|
56
|
+
}
|
|
57
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
58
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "none" }, "aria-hidden": "true", children }),
|
|
59
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
60
|
+
import_dropdown_menu.DropdownMenu.Content,
|
|
61
|
+
{
|
|
62
|
+
"data-slot": "filter-menu",
|
|
63
|
+
className: (0, import_shared_utils.cn)("min-w-[220px]", className),
|
|
64
|
+
align: "start",
|
|
65
|
+
children: fields.size === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2 py-3 text-sm text-muted-foreground text-center", children: "Loading..." }) : Array.from(fieldGroups.entries()).map(([groupLabel, groupFields]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_dropdown_menu.DropdownMenu.Group, { children: [
|
|
66
|
+
groupLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dropdown_menu.DropdownMenu.Label, { children: groupLabel }),
|
|
67
|
+
Array.from(groupFields.values()).map((field) => {
|
|
68
|
+
const hasFilter = value.some((f) => f.fieldId === field.id);
|
|
69
|
+
const isDisabled = field.disabled || !allowMultiple && hasFilter;
|
|
70
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
71
|
+
import_dropdown_menu.DropdownMenu.Item,
|
|
72
|
+
{
|
|
73
|
+
"data-slot": "filter-item",
|
|
74
|
+
disabled: isDisabled,
|
|
75
|
+
onSelect: () => addFilter(field.id),
|
|
76
|
+
children: [
|
|
77
|
+
field.icon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.menuItemIcon(), children: field.icon }),
|
|
78
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: field.label })
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
field.id
|
|
82
|
+
);
|
|
83
|
+
})
|
|
84
|
+
] }, groupLabel != null ? groupLabel : "ungrouped"))
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
FilterMenu.displayName = "FilterMenu";
|
|
90
|
+
function FilterGroup(props) {
|
|
91
|
+
const { label, children } = props;
|
|
92
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilterGroupProvider, { label, children });
|
|
93
|
+
}
|
|
94
|
+
FilterGroup.displayName = "FilterGroup";
|
|
95
|
+
var FilterGroupContext = (0, import_react.createContext)(void 0);
|
|
96
|
+
function FilterGroupProvider({
|
|
97
|
+
label,
|
|
98
|
+
children
|
|
99
|
+
}) {
|
|
100
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilterGroupContext.Provider, { value: label, children });
|
|
101
|
+
}
|
|
102
|
+
function useFilterGroup() {
|
|
103
|
+
return (0, import_react.useContext)(FilterGroupContext);
|
|
104
|
+
}
|
|
105
|
+
function FilterItem(props) {
|
|
106
|
+
const {
|
|
107
|
+
id,
|
|
108
|
+
label,
|
|
109
|
+
icon,
|
|
110
|
+
type,
|
|
111
|
+
options,
|
|
112
|
+
operators,
|
|
113
|
+
placeholder,
|
|
114
|
+
min,
|
|
115
|
+
max,
|
|
116
|
+
step,
|
|
117
|
+
searchable,
|
|
118
|
+
disabled
|
|
119
|
+
} = props;
|
|
120
|
+
const { registerField, unregisterField } = useFilterContext();
|
|
121
|
+
const group = useFilterGroup();
|
|
122
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
123
|
+
registerField({
|
|
124
|
+
id,
|
|
125
|
+
label,
|
|
126
|
+
icon,
|
|
127
|
+
type,
|
|
128
|
+
options,
|
|
129
|
+
operators,
|
|
130
|
+
placeholder,
|
|
131
|
+
min,
|
|
132
|
+
max,
|
|
133
|
+
step,
|
|
134
|
+
searchable,
|
|
135
|
+
group,
|
|
136
|
+
disabled
|
|
137
|
+
});
|
|
138
|
+
return () => unregisterField(id);
|
|
139
|
+
}, [
|
|
140
|
+
id,
|
|
141
|
+
label,
|
|
142
|
+
icon,
|
|
143
|
+
type,
|
|
144
|
+
options,
|
|
145
|
+
operators,
|
|
146
|
+
placeholder,
|
|
147
|
+
min,
|
|
148
|
+
max,
|
|
149
|
+
step,
|
|
150
|
+
searchable,
|
|
151
|
+
group,
|
|
152
|
+
disabled,
|
|
153
|
+
registerField,
|
|
154
|
+
unregisterField
|
|
155
|
+
]);
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
FilterItem.displayName = "FilterItem";
|
|
159
|
+
function FilterMenuSeparator() {
|
|
160
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dropdown_menu.DropdownMenu.Separator, { "data-slot": "filter-menu-separator" });
|
|
161
|
+
}
|
|
162
|
+
FilterMenuSeparator.displayName = "FilterMenuSeparator";
|
|
163
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
164
|
+
0 && (module.exports = {
|
|
165
|
+
FilterGroup,
|
|
166
|
+
FilterItem,
|
|
167
|
+
FilterMenu,
|
|
168
|
+
FilterMenuSeparator
|
|
169
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import {
|
|
4
|
+
FilterGroup,
|
|
5
|
+
FilterItem,
|
|
6
|
+
FilterMenu,
|
|
7
|
+
FilterMenuSeparator
|
|
8
|
+
} from "./chunk-TBHYZZSX.mjs";
|
|
9
|
+
import "./chunk-I3Z2T4N2.mjs";
|
|
10
|
+
export {
|
|
11
|
+
FilterGroup,
|
|
12
|
+
FilterItem,
|
|
13
|
+
FilterMenu,
|
|
14
|
+
FilterMenuSeparator
|
|
15
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { DropdownMenu } from '@kopexa/dropdown-menu';
|
|
3
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterTriggerProps extends Omit<ComponentProps<typeof DropdownMenu.Trigger>, "asChild"> {
|
|
6
|
+
/** Custom icon */
|
|
7
|
+
icon?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare function FilterTrigger(props: FilterTriggerProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare namespace FilterTrigger {
|
|
11
|
+
var displayName: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { FilterTrigger, type FilterTriggerProps };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { DropdownMenu } from '@kopexa/dropdown-menu';
|
|
3
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
interface FilterTriggerProps extends Omit<ComponentProps<typeof DropdownMenu.Trigger>, "asChild"> {
|
|
6
|
+
/** Custom icon */
|
|
7
|
+
icon?: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
declare function FilterTrigger(props: FilterTriggerProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare namespace FilterTrigger {
|
|
11
|
+
var displayName: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { FilterTrigger, type FilterTriggerProps };
|
|
@@ -0,0 +1,170 @@
|
|
|
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-trigger.tsx
|
|
23
|
+
var filter_trigger_exports = {};
|
|
24
|
+
__export(filter_trigger_exports, {
|
|
25
|
+
FilterTrigger: () => FilterTrigger
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(filter_trigger_exports);
|
|
28
|
+
var import_dropdown_menu = require("@kopexa/dropdown-menu");
|
|
29
|
+
var import_i18n2 = require("@kopexa/i18n");
|
|
30
|
+
var import_icons = require("@kopexa/icons");
|
|
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/messages.ts
|
|
42
|
+
var import_i18n = require("@kopexa/i18n");
|
|
43
|
+
var messages = (0, import_i18n.defineMessages)({
|
|
44
|
+
add_filter: {
|
|
45
|
+
id: "filter.add_filter",
|
|
46
|
+
defaultMessage: "Add Filter",
|
|
47
|
+
description: "Button text for adding a new filter"
|
|
48
|
+
},
|
|
49
|
+
clear_all: {
|
|
50
|
+
id: "filter.clear_all",
|
|
51
|
+
defaultMessage: "Clear all",
|
|
52
|
+
description: "Button text for clearing all filters"
|
|
53
|
+
},
|
|
54
|
+
no_fields: {
|
|
55
|
+
id: "filter.no_fields",
|
|
56
|
+
defaultMessage: "No filter options available",
|
|
57
|
+
description: "Message when no filter fields are configured"
|
|
58
|
+
},
|
|
59
|
+
apply: {
|
|
60
|
+
id: "filter.apply",
|
|
61
|
+
defaultMessage: "Apply",
|
|
62
|
+
description: "Button text for applying a filter value"
|
|
63
|
+
},
|
|
64
|
+
cancel: {
|
|
65
|
+
id: "filter.cancel",
|
|
66
|
+
defaultMessage: "Cancel",
|
|
67
|
+
description: "Button text for canceling filter editing"
|
|
68
|
+
},
|
|
69
|
+
select_value: {
|
|
70
|
+
id: "filter.select_value",
|
|
71
|
+
defaultMessage: "Select value...",
|
|
72
|
+
description: "Placeholder for value selection"
|
|
73
|
+
},
|
|
74
|
+
enter_value: {
|
|
75
|
+
id: "filter.enter_value",
|
|
76
|
+
defaultMessage: "Enter value...",
|
|
77
|
+
description: "Placeholder for value input"
|
|
78
|
+
},
|
|
79
|
+
// Operators
|
|
80
|
+
op_equals: {
|
|
81
|
+
id: "filter.operator.equals",
|
|
82
|
+
defaultMessage: "is",
|
|
83
|
+
description: "Operator: equals"
|
|
84
|
+
},
|
|
85
|
+
op_not_equals: {
|
|
86
|
+
id: "filter.operator.not_equals",
|
|
87
|
+
defaultMessage: "is not",
|
|
88
|
+
description: "Operator: not equals"
|
|
89
|
+
},
|
|
90
|
+
op_contains: {
|
|
91
|
+
id: "filter.operator.contains",
|
|
92
|
+
defaultMessage: "contains",
|
|
93
|
+
description: "Operator: contains"
|
|
94
|
+
},
|
|
95
|
+
op_not_contains: {
|
|
96
|
+
id: "filter.operator.not_contains",
|
|
97
|
+
defaultMessage: "does not contain",
|
|
98
|
+
description: "Operator: does not contain"
|
|
99
|
+
},
|
|
100
|
+
op_starts_with: {
|
|
101
|
+
id: "filter.operator.starts_with",
|
|
102
|
+
defaultMessage: "starts with",
|
|
103
|
+
description: "Operator: starts with"
|
|
104
|
+
},
|
|
105
|
+
op_ends_with: {
|
|
106
|
+
id: "filter.operator.ends_with",
|
|
107
|
+
defaultMessage: "ends with",
|
|
108
|
+
description: "Operator: ends with"
|
|
109
|
+
},
|
|
110
|
+
op_gt: {
|
|
111
|
+
id: "filter.operator.gt",
|
|
112
|
+
defaultMessage: "greater than",
|
|
113
|
+
description: "Operator: greater than"
|
|
114
|
+
},
|
|
115
|
+
op_lt: {
|
|
116
|
+
id: "filter.operator.lt",
|
|
117
|
+
defaultMessage: "less than",
|
|
118
|
+
description: "Operator: less than"
|
|
119
|
+
},
|
|
120
|
+
op_gte: {
|
|
121
|
+
id: "filter.operator.gte",
|
|
122
|
+
defaultMessage: "greater or equal",
|
|
123
|
+
description: "Operator: greater than or equal"
|
|
124
|
+
},
|
|
125
|
+
op_lte: {
|
|
126
|
+
id: "filter.operator.lte",
|
|
127
|
+
defaultMessage: "less or equal",
|
|
128
|
+
description: "Operator: less than or equal"
|
|
129
|
+
},
|
|
130
|
+
op_between: {
|
|
131
|
+
id: "filter.operator.between",
|
|
132
|
+
defaultMessage: "between",
|
|
133
|
+
description: "Operator: between"
|
|
134
|
+
},
|
|
135
|
+
op_is_empty: {
|
|
136
|
+
id: "filter.operator.is_empty",
|
|
137
|
+
defaultMessage: "is empty",
|
|
138
|
+
description: "Operator: is empty"
|
|
139
|
+
},
|
|
140
|
+
op_is_not_empty: {
|
|
141
|
+
id: "filter.operator.is_not_empty",
|
|
142
|
+
defaultMessage: "is not empty",
|
|
143
|
+
description: "Operator: is not empty"
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// src/filter-trigger.tsx
|
|
148
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
149
|
+
function FilterTrigger(props) {
|
|
150
|
+
const { className, children, icon, ...rest } = props;
|
|
151
|
+
const { styles } = useFilterContext();
|
|
152
|
+
const t = (0, import_i18n2.useSafeIntl)();
|
|
153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
154
|
+
import_dropdown_menu.DropdownMenu.Trigger,
|
|
155
|
+
{
|
|
156
|
+
"data-slot": "filter-trigger",
|
|
157
|
+
className: (0, import_shared_utils.cn)(styles.trigger(), className),
|
|
158
|
+
...rest,
|
|
159
|
+
children: [
|
|
160
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: styles.triggerIcon(), children: icon != null ? icon : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.PlusIcon, { className: "size-4" }) }),
|
|
161
|
+
children != null ? children : t.formatMessage(messages.add_filter)
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
FilterTrigger.displayName = "FilterTrigger";
|
|
167
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
168
|
+
0 && (module.exports = {
|
|
169
|
+
FilterTrigger
|
|
170
|
+
});
|
|
@@ -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 };
|