@brainfish-ai/components 0.8.1 → 0.8.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/dist/esm/chunks/filters.Bo2N95yq.js +564 -0
- package/dist/esm/chunks/filters.Bo2N95yq.js.map +1 -0
- package/dist/esm/components/filter.js +1 -1
- package/dist/esm/index.css +1 -1
- package/dist/esm/index.js +82 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/filter.d.ts +10 -4
- package/dist/index.d.ts +26 -4
- package/dist/stats.html +1 -1
- package/package.json +2 -2
- package/dist/esm/chunks/filters.Dy3yDv4K.js +0 -264
- package/dist/esm/chunks/filters.Dy3yDv4K.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brainfish-ai/components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"description": "Brainfish Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"default": "./dist/esm/components/*.js"
|
|
20
20
|
},
|
|
21
21
|
"./ui/*": {
|
|
22
|
-
"types": "./dist/*.d.ts",
|
|
22
|
+
"types": "./dist/components/ui/*.d.ts",
|
|
23
23
|
"import": "./dist/esm/components/ui/*.js",
|
|
24
24
|
"default": "./dist/esm/components/ui/*.js"
|
|
25
25
|
}
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import React__default, { forwardRef, useState, useRef, useEffect } from 'react';
|
|
2
|
-
import { Check, XCircle, Plus } from '@phosphor-icons/react';
|
|
3
|
-
import { createId } from '@paralleldrive/cuid2';
|
|
4
|
-
import { Button } from '../components/ui/button.js';
|
|
5
|
-
import { Input } from '../components/ui/input.js';
|
|
6
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '../components/ui/dropdown-menu.js';
|
|
7
|
-
import { c as cn } from './utils.DmKr1Ojo.js';
|
|
8
|
-
|
|
9
|
-
var Operator = /* @__PURE__ */ ((Operator2) => {
|
|
10
|
-
Operator2["IS"] = "is";
|
|
11
|
-
Operator2["IS_NOT"] = "is not";
|
|
12
|
-
Operator2["CONTAINS"] = "contains";
|
|
13
|
-
Operator2["DOES_NOT_CONTAIN"] = "does not contain";
|
|
14
|
-
Operator2["STARTS_WITH"] = "starts with";
|
|
15
|
-
return Operator2;
|
|
16
|
-
})(Operator || {});
|
|
17
|
-
const Filter = forwardRef(
|
|
18
|
-
({
|
|
19
|
-
filter,
|
|
20
|
-
sourceOptions,
|
|
21
|
-
rules,
|
|
22
|
-
onSourceChange,
|
|
23
|
-
onRemoveFilter,
|
|
24
|
-
onFilterChange,
|
|
25
|
-
selectPlaceholder = "Select a value",
|
|
26
|
-
customValuePlaceholder = "Enter custom value",
|
|
27
|
-
customValueButtonLabel = "Done",
|
|
28
|
-
sourceFirstMessage = "Please select a source first"
|
|
29
|
-
}, ref) => {
|
|
30
|
-
const [internalFilter, setInternalFilter] = useState({
|
|
31
|
-
id: filter.id,
|
|
32
|
-
source: filter.source,
|
|
33
|
-
operator: filter.operator || "is" /* IS */,
|
|
34
|
-
value: filter.value
|
|
35
|
-
});
|
|
36
|
-
const [inputValue, setInputValue] = useState("");
|
|
37
|
-
const [openDropdownType, setOpenDropdownType] = useState(null);
|
|
38
|
-
const inputRef = useRef(null);
|
|
39
|
-
const currentRules = internalFilter.source ? rules[internalFilter.source] : void 0;
|
|
40
|
-
const operatorOptions = currentRules?.operators || [];
|
|
41
|
-
let inputType = currentRules?.inputType || "dropdown";
|
|
42
|
-
if (internalFilter.operator === "contains" /* CONTAINS */ || internalFilter.operator === "does not contain" /* DOES_NOT_CONTAIN */) {
|
|
43
|
-
inputType = "custom";
|
|
44
|
-
}
|
|
45
|
-
const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (openDropdownType === "value" && inputType === "custom") {
|
|
48
|
-
const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);
|
|
49
|
-
return () => clearTimeout(timeoutId);
|
|
50
|
-
}
|
|
51
|
-
return void 0;
|
|
52
|
-
}, [openDropdownType, inputType]);
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
setInternalFilter({
|
|
55
|
-
id: filter.id,
|
|
56
|
-
source: filter.source,
|
|
57
|
-
operator: filter.operator || "is" /* IS */,
|
|
58
|
-
value: filter.value
|
|
59
|
-
});
|
|
60
|
-
}, [filter]);
|
|
61
|
-
const updateFilterField = (field, value) => {
|
|
62
|
-
const newFilter = { ...internalFilter, [field]: value };
|
|
63
|
-
if (field === "source") {
|
|
64
|
-
const sourceRules = rules[value];
|
|
65
|
-
newFilter.operator = sourceRules?.operators[0]?.id;
|
|
66
|
-
newFilter.value = "";
|
|
67
|
-
}
|
|
68
|
-
if (field === "operator") {
|
|
69
|
-
if (internalFilter.source) {
|
|
70
|
-
const sourceRules = rules[internalFilter.source];
|
|
71
|
-
if (sourceRules?.inputType === "dropdown") {
|
|
72
|
-
newFilter.value = "";
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
setInternalFilter(newFilter);
|
|
77
|
-
const isComplete = newFilter.source && newFilter.operator && newFilter.value?.trim();
|
|
78
|
-
if (isComplete) onFilterChange(newFilter);
|
|
79
|
-
setOpenDropdownType(null);
|
|
80
|
-
};
|
|
81
|
-
const handleCustomValueSubmit = () => {
|
|
82
|
-
if (inputValue.trim()) {
|
|
83
|
-
const newFilter = { ...internalFilter, value: inputValue.trim() };
|
|
84
|
-
setInternalFilter(newFilter);
|
|
85
|
-
setInputValue("");
|
|
86
|
-
setOpenDropdownType(null);
|
|
87
|
-
if (newFilter.source && newFilter.operator && newFilter.value) {
|
|
88
|
-
onFilterChange(newFilter);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
const handleKeyDown = (e, isInput) => {
|
|
93
|
-
if (e.key === "Escape") {
|
|
94
|
-
setOpenDropdownType(null);
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
if (e.key === "Tab") {
|
|
98
|
-
if (isInput && !e.shiftKey) {
|
|
99
|
-
e.preventDefault();
|
|
100
|
-
const button = document.querySelector("[data-custom-submit-button]");
|
|
101
|
-
button?.focus();
|
|
102
|
-
} else if (!isInput) {
|
|
103
|
-
e.preventDefault();
|
|
104
|
-
inputRef.current?.focus();
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
return /* @__PURE__ */ React__default.createElement("div", { className: "inline-flex items-center rounded-full border border-foreground h-8 overflow-visible", ref }, /* @__PURE__ */ React__default.createElement(
|
|
109
|
-
DropdownMenu,
|
|
110
|
-
{
|
|
111
|
-
open: openDropdownType === "source",
|
|
112
|
-
onOpenChange: (open) => setOpenDropdownType(open ? "source" : null),
|
|
113
|
-
modal: false
|
|
114
|
-
},
|
|
115
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
|
|
116
|
-
"button",
|
|
117
|
-
{
|
|
118
|
-
type: "button",
|
|
119
|
-
className: "flex items-center px-2 py-1 text-sm font-bold border-r border-[#a3a3a3] hover:bg-black/5 text-foreground rounded-l-full"
|
|
120
|
-
},
|
|
121
|
-
sourceOptions.find((opt) => opt.id === internalFilter.source)?.label || sourceOptions[0]?.label || selectPlaceholder
|
|
122
|
-
)),
|
|
123
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-48" }, sourceOptions.map((option) => /* @__PURE__ */ React__default.createElement(
|
|
124
|
-
DropdownMenuItem,
|
|
125
|
-
{
|
|
126
|
-
key: option.id,
|
|
127
|
-
className: "flex items-center",
|
|
128
|
-
onSelect: () => {
|
|
129
|
-
updateFilterField("source", option.id);
|
|
130
|
-
onSourceChange?.(option.id);
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
option.id === internalFilter.source && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
134
|
-
option.label
|
|
135
|
-
)))
|
|
136
|
-
), /* @__PURE__ */ React__default.createElement(
|
|
137
|
-
DropdownMenu,
|
|
138
|
-
{
|
|
139
|
-
open: openDropdownType === "operator",
|
|
140
|
-
onOpenChange: (open) => setOpenDropdownType(open ? "operator" : null),
|
|
141
|
-
modal: false
|
|
142
|
-
},
|
|
143
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
|
|
144
|
-
"button",
|
|
145
|
-
{
|
|
146
|
-
type: "button",
|
|
147
|
-
className: "flex items-center px-2 py-1 text-sm border-r border-[#a3a3a3] hover:bg-black/5"
|
|
148
|
-
},
|
|
149
|
-
operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder
|
|
150
|
-
)),
|
|
151
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-48" }, operatorOptions.map((option) => /* @__PURE__ */ React__default.createElement(
|
|
152
|
-
DropdownMenuItem,
|
|
153
|
-
{
|
|
154
|
-
key: option.id,
|
|
155
|
-
className: "flex items-center",
|
|
156
|
-
onSelect: () => updateFilterField("operator", option.id)
|
|
157
|
-
},
|
|
158
|
-
option.id === internalFilter.operator && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
159
|
-
option.label
|
|
160
|
-
)))
|
|
161
|
-
), /* @__PURE__ */ React__default.createElement(
|
|
162
|
-
DropdownMenu,
|
|
163
|
-
{
|
|
164
|
-
open: openDropdownType === "value",
|
|
165
|
-
onOpenChange: (open) => setOpenDropdownType(open ? "value" : null),
|
|
166
|
-
modal: false
|
|
167
|
-
},
|
|
168
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement("button", { type: "button", className: "flex items-center px-2 py-1 text-sm font-bold hover:bg-black/5" }, valueOptions.find((opt) => opt.id === internalFilter.value)?.label || internalFilter.value || selectPlaceholder)),
|
|
169
|
-
/* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-64" }, inputType === "custom" && /* @__PURE__ */ React__default.createElement(
|
|
170
|
-
"form",
|
|
171
|
-
{
|
|
172
|
-
className: "p-3",
|
|
173
|
-
onSubmit: (e) => {
|
|
174
|
-
e.preventDefault();
|
|
175
|
-
handleCustomValueSubmit();
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
/* @__PURE__ */ React__default.createElement(
|
|
179
|
-
Input,
|
|
180
|
-
{
|
|
181
|
-
ref: inputRef,
|
|
182
|
-
type: "text",
|
|
183
|
-
value: inputValue,
|
|
184
|
-
onChange: (e) => setInputValue(e.target.value),
|
|
185
|
-
placeholder: customValuePlaceholder,
|
|
186
|
-
className: "mb-2",
|
|
187
|
-
onKeyDown: (e) => handleKeyDown(e, true)
|
|
188
|
-
}
|
|
189
|
-
),
|
|
190
|
-
/* @__PURE__ */ React__default.createElement(
|
|
191
|
-
Button,
|
|
192
|
-
{
|
|
193
|
-
type: "submit",
|
|
194
|
-
variant: "dark",
|
|
195
|
-
className: "w-full",
|
|
196
|
-
onKeyDown: (e) => handleKeyDown(e, false),
|
|
197
|
-
"data-custom-submit-button": true
|
|
198
|
-
},
|
|
199
|
-
customValueButtonLabel
|
|
200
|
-
)
|
|
201
|
-
), inputType === "dropdown" && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, internalFilter.source ? valueOptions.map((option) => /* @__PURE__ */ React__default.createElement(
|
|
202
|
-
DropdownMenuItem,
|
|
203
|
-
{
|
|
204
|
-
key: option.id,
|
|
205
|
-
className: "flex items-center",
|
|
206
|
-
onSelect: () => updateFilterField("value", option.id)
|
|
207
|
-
},
|
|
208
|
-
option.id === internalFilter.value && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
209
|
-
option.label
|
|
210
|
-
)) : /* @__PURE__ */ React__default.createElement("div", { className: "p-3 text-sm text-gray-500" }, sourceFirstMessage)))
|
|
211
|
-
), /* @__PURE__ */ React__default.createElement(
|
|
212
|
-
Button,
|
|
213
|
-
{
|
|
214
|
-
type: "button",
|
|
215
|
-
variant: "ghost",
|
|
216
|
-
size: "sm",
|
|
217
|
-
onClick: () => {
|
|
218
|
-
setInternalFilter({ id: filter.id });
|
|
219
|
-
setOpenDropdownType(null);
|
|
220
|
-
onRemoveFilter(filter.id);
|
|
221
|
-
},
|
|
222
|
-
className: "p-2 hover:bg-black/10 rounded-none rounded-r-full"
|
|
223
|
-
},
|
|
224
|
-
/* @__PURE__ */ React__default.createElement(XCircle, { size: 16, weight: "fill" })
|
|
225
|
-
));
|
|
226
|
-
}
|
|
227
|
-
);
|
|
228
|
-
Filter.displayName = "Filter";
|
|
229
|
-
|
|
230
|
-
const Filters = ({ filters, onFilterChange, onFilterRemove, sourceOptions, rules, className }) => {
|
|
231
|
-
const [internalFilters, setInternalFilters] = useState(filters || []);
|
|
232
|
-
const handleAddFilter = () => {
|
|
233
|
-
const newFilter = { id: createId(), source: sourceOptions[0]?.id ?? "", operator: Operator.IS, value: "" };
|
|
234
|
-
setInternalFilters([...internalFilters, newFilter]);
|
|
235
|
-
};
|
|
236
|
-
const handleRemoveFilter = (filter) => {
|
|
237
|
-
setInternalFilters(internalFilters.filter((f) => f.id !== filter.id));
|
|
238
|
-
onFilterRemove(filter.id);
|
|
239
|
-
};
|
|
240
|
-
return /* @__PURE__ */ React__default.createElement("fieldset", { className: cn("flex flex-wrap gap-2", className) }, /* @__PURE__ */ React__default.createElement("legend", { className: "sr-only" }, "Filters"), internalFilters?.map((filter) => /* @__PURE__ */ React__default.createElement(
|
|
241
|
-
Filter,
|
|
242
|
-
{
|
|
243
|
-
key: filter.id,
|
|
244
|
-
filter,
|
|
245
|
-
sourceOptions,
|
|
246
|
-
rules,
|
|
247
|
-
onRemoveFilter: () => handleRemoveFilter(filter),
|
|
248
|
-
onFilterChange
|
|
249
|
-
}
|
|
250
|
-
)), /* @__PURE__ */ React__default.createElement(
|
|
251
|
-
Button,
|
|
252
|
-
{
|
|
253
|
-
onClick: handleAddFilter,
|
|
254
|
-
variant: "ghost",
|
|
255
|
-
className: "border border-foreground rounded-full gap-1",
|
|
256
|
-
size: "sm"
|
|
257
|
-
},
|
|
258
|
-
/* @__PURE__ */ React__default.createElement(Plus, { size: 16 }),
|
|
259
|
-
"Add filter"
|
|
260
|
-
));
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
export { Filter as F, Operator as O, Filters as a };
|
|
264
|
-
//# sourceMappingURL=filters.Dy3yDv4K.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"filters.Dy3yDv4K.js","sources":["../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["import React, { useState, useEffect, forwardRef, useRef } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\n\n// Types\nexport interface FilterOption {\n id: string;\n label: string;\n}\n\nexport enum Operator {\n IS = 'is',\n IS_NOT = 'is not',\n CONTAINS = 'contains',\n DOES_NOT_CONTAIN = 'does not contain',\n STARTS_WITH = 'starts with',\n}\n\nexport interface FilterValue {\n id: string | number;\n source?: string;\n operator?: Operator;\n value?: string;\n}\n\n/**\n * Filter rules for each source\n * How this works:\n * - You can define the rules for each source\n * - The rules are used to determine the available operators and value type\n * - The input type is used to determine the type of input displayed in when the dropdown is opened\n * - The getValueOptions function is used to determine the available options for the value\n *\n * @example\n * {\n * 'sourceId': {\n * operators: [\n * { id: 'is', label: 'is' },\n * { id: 'is not', label: 'is not' },\n * ],\n * inputType: 'dropdown' | 'custom',\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n getValueOptions?: () => FilterOption[];\n };\n}\n\ninterface FilterProps {\n filter: FilterValue;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n onSourceChange?: (sourceId: string) => void;\n onRemoveFilter: (id: string | number) => void;\n onFilterChange: (filter: FilterValue) => void;\n selectPlaceholder?: string;\n customValuePlaceholder?: string;\n customValueButtonLabel?: string;\n sourceFirstMessage?: string;\n}\n\nconst Filter = forwardRef<HTMLDivElement, FilterProps>(\n (\n {\n filter,\n sourceOptions,\n rules,\n onSourceChange,\n onRemoveFilter,\n onFilterChange,\n selectPlaceholder = 'Select a value',\n customValuePlaceholder = 'Enter custom value',\n customValueButtonLabel = 'Done',\n sourceFirstMessage = 'Please select a source first',\n }: FilterProps,\n ref,\n ) => {\n // State\n const [internalFilter, setInternalFilter] = useState<FilterValue>({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n const [inputValue, setInputValue] = useState('');\n const [openDropdownType, setOpenDropdownType] = useState<'source' | 'operator' | 'value' | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n let inputType = currentRules?.inputType || 'dropdown';\n if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {\n inputType = 'custom';\n }\n const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];\n\n // Auto-focus input when dropdown opens and custom input is needed\n useEffect(() => {\n if (openDropdownType === 'value' && inputType === 'custom') {\n const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);\n\n return () => clearTimeout(timeoutId);\n }\n\n return undefined;\n }, [openDropdownType, inputType]);\n\n // Sync with external state\n useEffect(() => {\n setInternalFilter({\n id: filter.id,\n source: filter.source,\n operator: filter.operator || Operator.IS,\n value: filter.value,\n });\n }, [filter]);\n\n // Handle field updates\n const updateFilterField = (field: keyof FilterValue, value: string) => {\n const newFilter: FilterValue = { ...internalFilter, [field]: value };\n\n // Special handling for source changes\n if (field === 'source') {\n const sourceRules = rules[value];\n newFilter.operator = sourceRules?.operators[0]?.id as Operator;\n // Do NOT auto-select the first value option; require explicit user selection\n newFilter.value = '';\n }\n // If operator changes, also clear value if inputType is dropdown\n if (field === 'operator') {\n if (internalFilter.source) {\n const sourceRules = rules[internalFilter.source];\n if (sourceRules?.inputType === 'dropdown') {\n newFilter.value = '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && newFilter.value?.trim();\n if (isComplete) onFilterChange(newFilter);\n\n setOpenDropdownType(null);\n };\n\n // Handle custom value submission\n const handleCustomValueSubmit = () => {\n if (inputValue.trim()) {\n const newFilter = { ...internalFilter, value: inputValue.trim() };\n setInternalFilter(newFilter);\n setInputValue('');\n setOpenDropdownType(null);\n if (newFilter.source && newFilter.operator && newFilter.value) {\n onFilterChange(newFilter);\n }\n }\n };\n\n // Tab trap handlers\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => {\n if (e.key === 'Escape') {\n setOpenDropdownType(null);\n\n return;\n }\n if (e.key === 'Tab') {\n if (isInput && !e.shiftKey) {\n e.preventDefault();\n const button = document.querySelector('[data-custom-submit-button]') as HTMLButtonElement;\n button?.focus();\n } else if (!isInput) {\n e.preventDefault();\n inputRef.current?.focus();\n }\n }\n };\n\n return (\n <div className=\"inline-flex items-center rounded-full border border-foreground h-8 overflow-visible\" ref={ref}>\n {/* Source Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'source'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'source' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className=\"flex items-center px-2 py-1 text-sm font-bold border-r border-[#a3a3a3] hover:bg-black/5 text-foreground rounded-l-full\"\n >\n {sourceOptions.find((opt) => opt.id === internalFilter.source)?.label ||\n sourceOptions[0]?.label ||\n selectPlaceholder}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {sourceOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => {\n updateFilterField('source', option.id);\n onSourceChange?.(option.id);\n }}\n >\n {option.id === internalFilter.source && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Operator Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'operator'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'operator' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <button\n type=\"button\"\n className=\"flex items-center px-2 py-1 text-sm border-r border-[#a3a3a3] hover:bg-black/5\"\n >\n {operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-48\">\n {operatorOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('operator', option.id)}\n >\n {option.id === internalFilter.operator && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Value Dropdown */}\n <DropdownMenu\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n modal={false}\n >\n <DropdownMenuTrigger asChild>\n <button type=\"button\" className=\"flex items-center px-2 py-1 text-sm font-bold hover:bg-black/5\">\n {valueOptions.find((opt) => opt.id === internalFilter.value)?.label ||\n internalFilter.value ||\n selectPlaceholder}\n </button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-64\">\n {inputType === 'custom' && (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n handleCustomValueSubmit();\n }}\n >\n <Input\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n onChange={(e) => setInputValue(e.target.value)}\n placeholder={customValuePlaceholder}\n className=\"mb-2\"\n onKeyDown={(e) => handleKeyDown(e, true)}\n />\n <Button\n type=\"submit\"\n variant=\"dark\"\n className=\"w-full\"\n onKeyDown={(e) => handleKeyDown(e, false)}\n data-custom-submit-button\n >\n {customValueButtonLabel}\n </Button>\n </form>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n valueOptions.map((option) => (\n <DropdownMenuItem\n key={option.id}\n className=\"flex items-center\"\n onSelect={() => updateFilterField('value', option.id)}\n >\n {option.id === internalFilter.value && <Check size={14} className=\"mr-2\" />}\n {option.label}\n </DropdownMenuItem>\n ))\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n\n {/* Remove button */}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => {\n setInternalFilter({ id: filter.id });\n setOpenDropdownType(null);\n onRemoveFilter(filter.id);\n }}\n className=\"p-2 hover:bg-black/10 rounded-none rounded-r-full\"\n >\n <XCircle size={16} weight=\"fill\" />\n </Button>\n </div>\n );\n },\n);\n\nFilter.displayName = 'Filter';\n\nexport { Filter };\n","import React, { useState } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './filter';\nimport { Button } from '../ui/button';\n\nimport { cn } from '@/lib/utils';\n\ninterface FiltersProps extends React.HTMLAttributes<HTMLDivElement> {\n filters: FilterValue[];\n onFilterChange: (filter: FilterValue) => void;\n onFilterRemove: (filterId: string | number) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({ filters, onFilterChange, onFilterRemove, sourceOptions, rules, className }: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n\n const handleAddFilter = () => {\n const newFilter = { id: createId(), source: sourceOptions[0]?.id ?? '', operator: Operator.IS, value: '' };\n\n setInternalFilters([...internalFilters, newFilter]);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n setInternalFilters(internalFilters.filter((f) => f.id !== filter.id));\n onFilterRemove(filter.id);\n };\n\n return (\n <fieldset className={cn('flex flex-wrap gap-2', className)}>\n <legend className=\"sr-only\">Filters</legend>\n {internalFilters?.map((filter) => (\n <Filter\n key={filter.id}\n filter={filter}\n sourceOptions={sourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n ))}\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","React"],"mappings":"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"}
|