@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.
@@ -0,0 +1,564 @@
1
+ import React__default, { useRef, useState, forwardRef, useImperativeHandle, 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 { Popover, PopoverTrigger, PopoverContent } from '../components/ui/popover.js';
8
+ import { c as cn } from './utils.DmKr1Ojo.js';
9
+
10
+ var Operator = /* @__PURE__ */ ((Operator2) => {
11
+ Operator2["IS"] = "is";
12
+ Operator2["IS_NOT"] = "is not";
13
+ Operator2["CONTAINS"] = "contains";
14
+ Operator2["DOES_NOT_CONTAIN"] = "does not contain";
15
+ Operator2["STARTS_WITH"] = "starts with";
16
+ return Operator2;
17
+ })(Operator || {});
18
+
19
+ const useMultiSelectHelpers = (internalFilter, valueOptions, selectPlaceholder) => {
20
+ const getSelectedValues = () => {
21
+ if (Array.isArray(internalFilter.value)) {
22
+ return internalFilter.value;
23
+ }
24
+ return internalFilter.value ? [internalFilter.value] : [];
25
+ };
26
+ const isValueSelected = (valueId) => {
27
+ const selectedValues = getSelectedValues();
28
+ return selectedValues.includes(valueId);
29
+ };
30
+ const getDisplayValue = () => {
31
+ const selectedValues = getSelectedValues();
32
+ if (selectedValues.length === 0) return selectPlaceholder;
33
+ if (selectedValues.length === 1) {
34
+ const option = valueOptions.find((opt) => opt.id === selectedValues[0]);
35
+ return option?.label || selectedValues[0];
36
+ }
37
+ return `${selectedValues.length} selected`;
38
+ };
39
+ return {
40
+ getSelectedValues,
41
+ isValueSelected,
42
+ getDisplayValue
43
+ };
44
+ };
45
+
46
+ const CustomValueInput = ({
47
+ inputValue,
48
+ setInputValue,
49
+ customValuePlaceholder,
50
+ customValueButtonLabel,
51
+ onSubmit,
52
+ handleKeyDown
53
+ }) => {
54
+ const inputRef = useRef(null);
55
+ return /* @__PURE__ */ React__default.createElement(
56
+ "form",
57
+ {
58
+ className: "p-3",
59
+ onSubmit: (e) => {
60
+ e.preventDefault();
61
+ onSubmit();
62
+ }
63
+ },
64
+ /* @__PURE__ */ React__default.createElement(
65
+ Input,
66
+ {
67
+ ref: inputRef,
68
+ type: "text",
69
+ value: inputValue,
70
+ onChange: (e) => setInputValue(e.target.value),
71
+ placeholder: customValuePlaceholder,
72
+ className: "mb-2",
73
+ onKeyDown: (e) => handleKeyDown(e, true)
74
+ }
75
+ ),
76
+ /* @__PURE__ */ React__default.createElement(
77
+ Button,
78
+ {
79
+ type: "submit",
80
+ variant: "dark",
81
+ className: "w-full",
82
+ onKeyDown: (e) => handleKeyDown(e, false),
83
+ "data-custom-submit-button": true
84
+ },
85
+ customValueButtonLabel
86
+ )
87
+ );
88
+ };
89
+
90
+ const getInitialValues = (value) => {
91
+ if (Array.isArray(value)) {
92
+ return value;
93
+ } else if (value) {
94
+ return [value];
95
+ }
96
+ return [];
97
+ };
98
+ const MultiSelectDropdown = ({
99
+ internalFilter,
100
+ valueOptions,
101
+ onConfirm,
102
+ onClose
103
+ }) => {
104
+ const [pendingValues, setPendingValues] = useState(() => getInitialValues(internalFilter.value));
105
+ const [announcement, setAnnouncement] = useState("");
106
+ const buttonRefs = useRef([]);
107
+ const applyButtonRef = useRef(null);
108
+ const handleValueToggle = (valueId) => {
109
+ const option = valueOptions.find((opt) => opt.id === valueId);
110
+ const isCurrentlySelected = pendingValues.includes(valueId);
111
+ setPendingValues((prev) => {
112
+ const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];
113
+ if (option) {
114
+ const action = isCurrentlySelected ? "deselected" : "selected";
115
+ setAnnouncement(`${option.label} ${action}.`);
116
+ }
117
+ return newValues;
118
+ });
119
+ };
120
+ const handleConfirm = () => {
121
+ onConfirm(pendingValues);
122
+ onClose();
123
+ };
124
+ const isValueSelected = (valueId) => {
125
+ return pendingValues.includes(valueId);
126
+ };
127
+ const focusButton = (index) => {
128
+ if (index < valueOptions.length) {
129
+ buttonRefs.current[index]?.focus();
130
+ } else {
131
+ applyButtonRef.current?.focus();
132
+ }
133
+ };
134
+ const handleKeyDown = (e, index) => {
135
+ switch (e.key) {
136
+ case "ArrowDown": {
137
+ e.preventDefault();
138
+ const nextIndex = Math.min(index + 1, valueOptions.length);
139
+ focusButton(nextIndex);
140
+ break;
141
+ }
142
+ case "ArrowUp": {
143
+ e.preventDefault();
144
+ const prevIndex = Math.max(index - 1, 0);
145
+ focusButton(prevIndex);
146
+ break;
147
+ }
148
+ case "Enter":
149
+ case "Spacebar":
150
+ e.preventDefault();
151
+ if (index < valueOptions.length) {
152
+ handleValueToggle(valueOptions[index].id);
153
+ } else {
154
+ handleConfirm();
155
+ }
156
+ break;
157
+ case "Escape":
158
+ e.preventDefault();
159
+ onClose();
160
+ break;
161
+ }
162
+ };
163
+ return /* @__PURE__ */ React__default.createElement("div", { className: "py-1", role: "listbox", "aria-multiselectable": "true" }, /* @__PURE__ */ React__default.createElement("div", { "aria-live": "polite", "aria-atomic": "true", className: "sr-only" }, announcement), valueOptions.map((option, index) => /* @__PURE__ */ React__default.createElement(
164
+ "button",
165
+ {
166
+ key: option.id,
167
+ ref: (el) => buttonRefs.current[index] = el,
168
+ type: "button",
169
+ className: "relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
170
+ onClick: () => handleValueToggle(option.id),
171
+ onKeyDown: (e) => handleKeyDown(e, index),
172
+ role: "option",
173
+ "aria-selected": isValueSelected(option.id)
174
+ },
175
+ isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
176
+ !isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement("span", { className: "mr-2 w-3.5" }),
177
+ option.label
178
+ )), /* @__PURE__ */ React__default.createElement("div", { className: "border-t border-border mt-1 pt-2 px-2 pb-2" }, /* @__PURE__ */ React__default.createElement(
179
+ Button,
180
+ {
181
+ ref: applyButtonRef,
182
+ onClick: handleConfirm,
183
+ size: "sm",
184
+ className: "w-full",
185
+ disabled: pendingValues.length === 0,
186
+ onKeyDown: (e) => handleKeyDown(e, valueOptions.length)
187
+ },
188
+ "Apply (",
189
+ pendingValues.length,
190
+ " selected)"
191
+ )));
192
+ };
193
+
194
+ const SingleSelectDropdown = ({
195
+ valueOptions,
196
+ isValueSelected,
197
+ onValueSelect
198
+ }) => {
199
+ const buttonRefs = useRef([]);
200
+ const focusButton = (index) => {
201
+ buttonRefs.current[index]?.focus();
202
+ };
203
+ const handleKeyDown = (e, index) => {
204
+ switch (e.key) {
205
+ case "ArrowDown": {
206
+ e.preventDefault();
207
+ const nextIndex = Math.min(index + 1, valueOptions.length - 1);
208
+ focusButton(nextIndex);
209
+ break;
210
+ }
211
+ case "ArrowUp": {
212
+ e.preventDefault();
213
+ const prevIndex = Math.max(index - 1, 0);
214
+ focusButton(prevIndex);
215
+ break;
216
+ }
217
+ case "Enter":
218
+ case "Spacebar":
219
+ e.preventDefault();
220
+ onValueSelect(valueOptions[index].id);
221
+ break;
222
+ }
223
+ };
224
+ return /* @__PURE__ */ React__default.createElement("div", { className: "py-1", role: "listbox" }, valueOptions.map((option, index) => /* @__PURE__ */ React__default.createElement(
225
+ "button",
226
+ {
227
+ key: option.id,
228
+ ref: (el) => buttonRefs.current[index] = el,
229
+ type: "button",
230
+ className: "relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
231
+ onClick: () => onValueSelect(option.id),
232
+ onKeyDown: (e) => handleKeyDown(e, index)
233
+ },
234
+ isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
235
+ !isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement("span", { className: "mr-2 w-3.5" }),
236
+ option.label
237
+ )));
238
+ };
239
+
240
+ const Filter = forwardRef(
241
+ ({
242
+ filter,
243
+ sourceOptions,
244
+ rules,
245
+ onSourceChange,
246
+ onRemoveFilter,
247
+ onFilterChange,
248
+ selectPlaceholder = "Select a value",
249
+ customValuePlaceholder = "Enter custom value",
250
+ customValueButtonLabel = "Done",
251
+ sourceFirstMessage = "Please select a source first"
252
+ }, ref) => {
253
+ const [internalFilter, setInternalFilter] = useState({
254
+ id: filter.id,
255
+ source: filter.source,
256
+ operator: filter.operator || Operator.IS,
257
+ value: filter.value
258
+ });
259
+ const [inputValue, setInputValue] = useState("");
260
+ const [openDropdownType, setOpenDropdownType] = useState(null);
261
+ const inputRef = useRef(null);
262
+ const sourceButtonRef = useRef(null);
263
+ const divRef = useRef(null);
264
+ useImperativeHandle(ref, () => ({
265
+ focus: () => {
266
+ sourceButtonRef.current?.focus();
267
+ }
268
+ }));
269
+ const currentRules = internalFilter.source ? rules[internalFilter.source] : void 0;
270
+ const operatorOptions = currentRules?.operators || [];
271
+ const isMultiSelect = currentRules?.multiSelect || false;
272
+ let inputType = currentRules?.inputType || "dropdown";
273
+ if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {
274
+ inputType = "custom";
275
+ }
276
+ const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];
277
+ const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(
278
+ internalFilter,
279
+ valueOptions,
280
+ selectPlaceholder
281
+ );
282
+ useEffect(() => {
283
+ if (openDropdownType === "value" && inputType === "custom") {
284
+ const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);
285
+ return () => clearTimeout(timeoutId);
286
+ }
287
+ return void 0;
288
+ }, [openDropdownType, inputType]);
289
+ useEffect(() => {
290
+ setInternalFilter({
291
+ id: filter.id,
292
+ source: filter.source,
293
+ operator: filter.operator || Operator.IS,
294
+ value: filter.value
295
+ });
296
+ }, [filter]);
297
+ const checkAndTriggerChange = (newFilter) => {
298
+ const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();
299
+ const isComplete = newFilter.source && newFilter.operator && hasValue;
300
+ if (isComplete) {
301
+ onFilterChange(newFilter);
302
+ }
303
+ };
304
+ const updateFilterField = (field, value) => {
305
+ const newFilter = { ...internalFilter, [field]: value };
306
+ if (field === "source") {
307
+ const sourceRules = rules[value];
308
+ newFilter.operator = sourceRules?.operators[0]?.id;
309
+ newFilter.value = sourceRules?.multiSelect ? [] : "";
310
+ }
311
+ if (field === "operator") {
312
+ if (internalFilter.source) {
313
+ const sourceRules = rules[internalFilter.source];
314
+ if (sourceRules?.inputType === "dropdown") {
315
+ newFilter.value = sourceRules?.multiSelect ? [] : "";
316
+ }
317
+ }
318
+ }
319
+ setInternalFilter(newFilter);
320
+ checkAndTriggerChange(newFilter);
321
+ if (!isMultiSelect || field !== "value") {
322
+ setOpenDropdownType(null);
323
+ }
324
+ };
325
+ const handleValueToggle = (valueId) => {
326
+ const selectedValues = getSelectedValues();
327
+ let newValues;
328
+ if (isMultiSelect) {
329
+ if (selectedValues.includes(valueId)) {
330
+ newValues = selectedValues.filter((id) => id !== valueId);
331
+ } else {
332
+ newValues = [...selectedValues, valueId];
333
+ }
334
+ } else {
335
+ newValues = [valueId];
336
+ }
337
+ const newFilter = {
338
+ ...internalFilter,
339
+ value: isMultiSelect ? newValues : newValues[0] || ""
340
+ };
341
+ setInternalFilter(newFilter);
342
+ checkAndTriggerChange(newFilter);
343
+ if (!isMultiSelect) {
344
+ setOpenDropdownType(null);
345
+ }
346
+ };
347
+ const handleMultiSelectConfirm = (selectedValues) => {
348
+ const newFilter = {
349
+ ...internalFilter,
350
+ value: selectedValues
351
+ };
352
+ setInternalFilter(newFilter);
353
+ const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;
354
+ if (isComplete) onFilterChange(newFilter);
355
+ setOpenDropdownType(null);
356
+ };
357
+ const handleCustomValueSubmit = () => {
358
+ if (inputValue.trim()) {
359
+ const newFilter = { ...internalFilter, value: inputValue.trim() };
360
+ setInternalFilter(newFilter);
361
+ setInputValue("");
362
+ setOpenDropdownType(null);
363
+ if (newFilter.source && newFilter.operator && newFilter.value) {
364
+ onFilterChange(newFilter);
365
+ }
366
+ }
367
+ };
368
+ const handleKeyDown = (e, isInput) => {
369
+ if (e.key === "Escape") {
370
+ setOpenDropdownType(null);
371
+ return;
372
+ }
373
+ if (e.key === "Tab") {
374
+ if (isInput && !e.shiftKey) {
375
+ e.preventDefault();
376
+ const button = document.querySelector("[data-custom-submit-button]");
377
+ button?.focus();
378
+ } else if (!isInput) {
379
+ e.preventDefault();
380
+ inputRef.current?.focus();
381
+ }
382
+ }
383
+ };
384
+ return /* @__PURE__ */ React__default.createElement("div", { className: "inline-flex items-center rounded-full border border-foreground h-8 overflow-visible", ref: divRef }, /* @__PURE__ */ React__default.createElement(
385
+ DropdownMenu,
386
+ {
387
+ open: openDropdownType === "source",
388
+ onOpenChange: (open) => setOpenDropdownType(open ? "source" : null),
389
+ modal: false
390
+ },
391
+ /* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
392
+ "button",
393
+ {
394
+ ref: sourceButtonRef,
395
+ type: "button",
396
+ 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"
397
+ },
398
+ sourceOptions.find((opt) => opt.id === internalFilter.source)?.label || sourceOptions[0]?.label || selectPlaceholder
399
+ )),
400
+ /* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-48" }, sourceOptions.map((option) => /* @__PURE__ */ React__default.createElement(
401
+ DropdownMenuItem,
402
+ {
403
+ key: option.id,
404
+ className: "flex items-center",
405
+ onSelect: () => {
406
+ updateFilterField("source", option.id);
407
+ onSourceChange?.(option.id);
408
+ }
409
+ },
410
+ option.id === internalFilter.source && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
411
+ option.label
412
+ )))
413
+ ), /* @__PURE__ */ React__default.createElement(
414
+ DropdownMenu,
415
+ {
416
+ open: openDropdownType === "operator",
417
+ onOpenChange: (open) => setOpenDropdownType(open ? "operator" : null),
418
+ modal: false
419
+ },
420
+ /* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(
421
+ "button",
422
+ {
423
+ type: "button",
424
+ className: "flex items-center px-2 py-1 text-sm border-r border-[#a3a3a3] hover:bg-black/5"
425
+ },
426
+ operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder
427
+ )),
428
+ /* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-48" }, operatorOptions.map((option) => /* @__PURE__ */ React__default.createElement(
429
+ DropdownMenuItem,
430
+ {
431
+ key: option.id,
432
+ className: "flex items-center",
433
+ onSelect: () => updateFilterField("operator", option.id)
434
+ },
435
+ option.id === internalFilter.operator && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
436
+ option.label
437
+ )))
438
+ ), /* @__PURE__ */ React__default.createElement(
439
+ Popover,
440
+ {
441
+ open: openDropdownType === "value",
442
+ onOpenChange: (open) => setOpenDropdownType(open ? "value" : null)
443
+ },
444
+ /* @__PURE__ */ React__default.createElement(PopoverTrigger, { 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" }, getDisplayValue())),
445
+ /* @__PURE__ */ React__default.createElement(PopoverContent, { align: "start", className: "w-64 p-0" }, inputType === "custom" && /* @__PURE__ */ React__default.createElement("div", { className: "p-3" }, /* @__PURE__ */ React__default.createElement(
446
+ CustomValueInput,
447
+ {
448
+ inputValue,
449
+ setInputValue,
450
+ customValuePlaceholder,
451
+ customValueButtonLabel,
452
+ onSubmit: handleCustomValueSubmit,
453
+ handleKeyDown
454
+ }
455
+ )), inputType === "dropdown" && /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, internalFilter.source ? /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, isMultiSelect ? /* @__PURE__ */ React__default.createElement(
456
+ MultiSelectDropdown,
457
+ {
458
+ internalFilter,
459
+ valueOptions,
460
+ onConfirm: handleMultiSelectConfirm,
461
+ onClose: () => setOpenDropdownType(null)
462
+ }
463
+ ) : /* @__PURE__ */ React__default.createElement(
464
+ SingleSelectDropdown,
465
+ {
466
+ valueOptions,
467
+ isValueSelected,
468
+ onValueSelect: handleValueToggle
469
+ }
470
+ )) : /* @__PURE__ */ React__default.createElement("div", { className: "p-3 text-sm text-gray-500" }, sourceFirstMessage)))
471
+ ), /* @__PURE__ */ React__default.createElement(
472
+ Button,
473
+ {
474
+ type: "button",
475
+ variant: "ghost",
476
+ size: "sm",
477
+ onClick: () => {
478
+ setInternalFilter({ id: filter.id });
479
+ setOpenDropdownType(null);
480
+ onRemoveFilter(filter.id);
481
+ },
482
+ className: "p-2 hover:bg-black/10 rounded-none rounded-r-full",
483
+ "aria-label": "Remove filter"
484
+ },
485
+ /* @__PURE__ */ React__default.createElement(XCircle, { size: 16, weight: "fill" })
486
+ ));
487
+ }
488
+ );
489
+ Filter.displayName = "Filter";
490
+
491
+ const Filters = ({
492
+ filters,
493
+ onFilterChange,
494
+ onFilterRemove,
495
+ onFilterAdd,
496
+ sourceOptions,
497
+ rules,
498
+ className
499
+ }) => {
500
+ const [internalFilters, setInternalFilters] = useState(filters || []);
501
+ const filterRefs = useRef({});
502
+ useEffect(() => {
503
+ setInternalFilters(filters || []);
504
+ }, [filters]);
505
+ const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);
506
+ const availableSources = sourceOptions.filter((option) => !usedSources.includes(option.id));
507
+ const canAddFilter = availableSources.length > 0;
508
+ const handleAddFilter = () => {
509
+ if (!canAddFilter) return;
510
+ const newFilter = {
511
+ id: createId(),
512
+ source: availableSources[0].id,
513
+ operator: Operator.IS,
514
+ value: rules[availableSources[0].id]?.multiSelect ? [] : ""
515
+ };
516
+ const newFilters = [...internalFilters, newFilter];
517
+ setInternalFilters(newFilters);
518
+ requestAnimationFrame(() => {
519
+ filterRefs.current[newFilter.id]?.focus();
520
+ });
521
+ onFilterAdd?.(newFilter);
522
+ };
523
+ const handleRemoveFilter = (filter) => {
524
+ const newFilters = internalFilters.filter((f) => f.id !== filter.id);
525
+ setInternalFilters(newFilters);
526
+ onFilterRemove(filter.id);
527
+ };
528
+ 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) => {
529
+ const filterSourceOptions = sourceOptions.filter(
530
+ (option) => !usedSources.includes(option.id) || // Available sources
531
+ option.id === filter.source
532
+ // Or its own current source
533
+ );
534
+ return /* @__PURE__ */ React__default.createElement(
535
+ Filter,
536
+ {
537
+ key: filter.id,
538
+ ref: (ref) => {
539
+ filterRefs.current[filter.id] = ref;
540
+ },
541
+ filter,
542
+ sourceOptions: filterSourceOptions,
543
+ rules,
544
+ onRemoveFilter: () => handleRemoveFilter(filter),
545
+ onFilterChange
546
+ }
547
+ );
548
+ }), /* @__PURE__ */ React__default.createElement(
549
+ Button,
550
+ {
551
+ onClick: handleAddFilter,
552
+ variant: "ghost",
553
+ className: "border border-foreground rounded-full gap-1",
554
+ size: "sm",
555
+ disabled: !canAddFilter,
556
+ title: canAddFilter ? "Add filter" : "All sources are already in use"
557
+ },
558
+ /* @__PURE__ */ React__default.createElement(Plus, { size: 16 }),
559
+ "Add filter"
560
+ ));
561
+ };
562
+
563
+ export { Filter as F, Operator as O, Filters as a };
564
+ //# sourceMappingURL=filters.Bo2N95yq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filters.Bo2N95yq.js","sources":["../../../src/components/filter/types.ts","../../../src/components/filter/hooks.ts","../../../src/components/filter/components/CustomValueInput.tsx","../../../src/components/filter/components/MultiSelectDropdown.tsx","../../../src/components/filter/components/SingleSelectDropdown.tsx","../../../src/components/filter/filter.tsx","../../../src/components/filter/filters.tsx"],"sourcesContent":["// 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 | 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 * - multiSelect determines if multiple values can be selected for dropdown type\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 * multiSelect?: boolean,\n * getValueOptions?: () => FilterOption[],\n * },\n * }\n */\nexport interface FilterRules {\n [sourceId: string]: {\n operators: FilterOption[];\n inputType: 'dropdown' | 'custom';\n multiSelect?: boolean;\n getValueOptions?: () => FilterOption[];\n };\n}\n\nexport interface 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","import { FilterValue } from './types';\n\nexport const useMultiSelectHelpers = (\n internalFilter: FilterValue,\n valueOptions: Array<{ id: string; label: string }>,\n selectPlaceholder: string,\n) => {\n const getSelectedValues = (): string[] => {\n if (Array.isArray(internalFilter.value)) {\n return internalFilter.value;\n }\n\n return internalFilter.value ? [internalFilter.value] : [];\n };\n\n const isValueSelected = (valueId: string): boolean => {\n const selectedValues = getSelectedValues();\n\n return selectedValues.includes(valueId);\n };\n\n const getDisplayValue = (): string => {\n const selectedValues = getSelectedValues();\n if (selectedValues.length === 0) return selectPlaceholder;\n if (selectedValues.length === 1) {\n const option = valueOptions.find((opt) => opt.id === selectedValues[0]);\n\n return option?.label || selectedValues[0];\n }\n\n return `${selectedValues.length} selected`;\n };\n\n return {\n getSelectedValues,\n isValueSelected,\n getDisplayValue,\n };\n};\n","import React, { useRef } from 'react';\n\nimport { Button } from '@/components/ui/button';\nimport { Input } from '@/components/ui/input';\n\ninterface CustomValueInputProps {\n inputValue: string;\n setInputValue: (value: string) => void;\n customValuePlaceholder: string;\n customValueButtonLabel: string;\n onSubmit: () => void;\n handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement | HTMLButtonElement>, isInput: boolean) => void;\n}\n\nexport const CustomValueInput: React.FC<CustomValueInputProps> = ({\n inputValue,\n setInputValue,\n customValuePlaceholder,\n customValueButtonLabel,\n onSubmit,\n handleKeyDown,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n\n return (\n <form\n className=\"p-3\"\n onSubmit={(e) => {\n e.preventDefault();\n onSubmit();\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};\n","import React, { useState, useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterValue, FilterOption } from '../types';\n\nimport { Button } from '@/components/ui/button';\n\ninterface MultiSelectDropdownProps {\n internalFilter: FilterValue;\n valueOptions: FilterOption[];\n onConfirm: (selectedValues: string[]) => void;\n onClose: () => void;\n}\n\nconst getInitialValues = (value: FilterValue['value']): string[] => {\n if (Array.isArray(value)) {\n return value;\n } else if (value) {\n return [value];\n }\n\n return [];\n};\n\nexport const MultiSelectDropdown: React.FC<MultiSelectDropdownProps> = ({\n internalFilter,\n valueOptions,\n onConfirm,\n onClose,\n}) => {\n const [pendingValues, setPendingValues] = useState<string[]>(() => getInitialValues(internalFilter.value));\n const [announcement, setAnnouncement] = useState<string>('');\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n const applyButtonRef = useRef<HTMLButtonElement>(null);\n\n const handleValueToggle = (valueId: string) => {\n const option = valueOptions.find((opt) => opt.id === valueId);\n const isCurrentlySelected = pendingValues.includes(valueId);\n\n setPendingValues((prev) => {\n const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];\n\n // Announce the change\n if (option) {\n const action = isCurrentlySelected ? 'deselected' : 'selected';\n setAnnouncement(`${option.label} ${action}.`);\n }\n\n return newValues;\n });\n };\n\n const handleConfirm = () => {\n onConfirm(pendingValues);\n onClose();\n };\n\n const isValueSelected = (valueId: string): boolean => {\n return pendingValues.includes(valueId);\n };\n\n const focusButton = (index: number) => {\n if (index < valueOptions.length) {\n buttonRefs.current[index]?.focus();\n } else {\n applyButtonRef.current?.focus();\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n if (index < valueOptions.length) {\n // If the user is selecting an option\n handleValueToggle(valueOptions[index].id);\n } else {\n // If the user is selecting the apply button\n handleConfirm();\n }\n break;\n case 'Escape':\n e.preventDefault();\n onClose();\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\" aria-multiselectable=\"true\">\n {/* Screen reader announcements */}\n <div aria-live=\"polite\" aria-atomic=\"true\" className=\"sr-only\">\n {announcement}\n </div>\n\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => handleValueToggle(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n role=\"option\"\n aria-selected={isValueSelected(option.id)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n\n <div className=\"border-t border-border mt-1 pt-2 px-2 pb-2\">\n <Button\n ref={applyButtonRef}\n onClick={handleConfirm}\n size=\"sm\"\n className=\"w-full\"\n disabled={pendingValues.length === 0}\n onKeyDown={(e) => handleKeyDown(e, valueOptions.length)}\n >\n Apply ({pendingValues.length} selected)\n </Button>\n </div>\n </div>\n );\n};\n","import React, { useRef } from 'react';\nimport { Check } from '@phosphor-icons/react';\n\nimport { FilterOption } from '../types';\n\ninterface SingleSelectDropdownProps {\n valueOptions: FilterOption[];\n isValueSelected: (valueId: string) => boolean;\n onValueSelect: (valueId: string) => void;\n}\n\nexport const SingleSelectDropdown: React.FC<SingleSelectDropdownProps> = ({\n valueOptions,\n isValueSelected,\n onValueSelect,\n}) => {\n const buttonRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const focusButton = (index: number) => {\n buttonRefs.current[index]?.focus();\n };\n\n const handleKeyDown = (e: React.KeyboardEvent, index: number) => {\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const nextIndex = Math.min(index + 1, valueOptions.length - 1);\n focusButton(nextIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prevIndex = Math.max(index - 1, 0);\n focusButton(prevIndex);\n break;\n }\n case 'Enter':\n case 'Spacebar':\n e.preventDefault();\n onValueSelect(valueOptions[index].id);\n break;\n }\n };\n\n return (\n <div className=\"py-1\" role=\"listbox\">\n {valueOptions.map((option, index) => (\n <button\n key={option.id}\n ref={(el) => (buttonRefs.current[index] = el)}\n type=\"button\"\n className=\"relative flex w-full text-left cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground\"\n onClick={() => onValueSelect(option.id)}\n onKeyDown={(e) => handleKeyDown(e, index)}\n >\n {isValueSelected(option.id) && <Check size={14} className=\"mr-2\" />}\n {!isValueSelected(option.id) && <span className=\"mr-2 w-3.5\" />}\n {option.label}\n </button>\n ))}\n </div>\n );\n};\n","import React, { useState, useEffect, forwardRef, useRef, useImperativeHandle } from 'react';\nimport { Check, XCircle } from '@phosphor-icons/react';\n\nimport { FilterProps, FilterValue, Operator } from './types';\nimport { useMultiSelectHelpers } from './hooks';\nimport { CustomValueInput } from './components/CustomValueInput';\nimport { MultiSelectDropdown } from './components/MultiSelectDropdown';\nimport { SingleSelectDropdown } from './components/SingleSelectDropdown';\n\nimport { Button } from '@/components/ui/button';\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu';\nimport { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';\n\nconst Filter = forwardRef<{ focus: () => void }, 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 const sourceButtonRef = useRef<HTMLButtonElement>(null);\n const divRef = useRef<HTMLDivElement>(null);\n\n // Expose focus method\n useImperativeHandle(ref, () => ({\n focus: () => {\n sourceButtonRef.current?.focus();\n },\n }));\n\n // Get current rules for selected source\n const currentRules = internalFilter.source ? rules[internalFilter.source] : undefined;\n const operatorOptions = currentRules?.operators || [];\n const isMultiSelect = currentRules?.multiSelect || false;\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 // Multi-select helpers\n const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(\n internalFilter,\n valueOptions,\n selectPlaceholder,\n );\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 // Helper function to check if filter is complete and trigger onChange\n const checkAndTriggerChange = (newFilter: FilterValue) => {\n const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();\n\n const isComplete = newFilter.source && newFilter.operator && hasValue;\n\n if (isComplete) {\n onFilterChange(newFilter);\n }\n };\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 newFilter.value = sourceRules?.multiSelect ? [] : '';\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 = sourceRules?.multiSelect ? [] : '';\n }\n }\n }\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n if (!isMultiSelect || field !== 'value') {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select value changes\n const handleValueToggle = (valueId: string) => {\n const selectedValues = getSelectedValues();\n let newValues: string[];\n\n if (isMultiSelect) {\n if (selectedValues.includes(valueId)) {\n newValues = selectedValues.filter((id) => id !== valueId);\n } else {\n newValues = [...selectedValues, valueId];\n }\n } else {\n newValues = [valueId];\n }\n\n const newFilter = {\n ...internalFilter,\n value: isMultiSelect ? newValues : newValues[0] || '',\n };\n\n setInternalFilter(newFilter);\n checkAndTriggerChange(newFilter);\n\n // Close dropdown for single select, keep open for multi-select\n if (!isMultiSelect) {\n setOpenDropdownType(null);\n }\n };\n\n // Handle multi-select confirmation\n const handleMultiSelectConfirm = (selectedValues: string[]) => {\n const newFilter = {\n ...internalFilter,\n value: selectedValues,\n };\n\n setInternalFilter(newFilter);\n\n // Trigger onChange if filter is complete\n const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;\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={divRef}>\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 ref={sourceButtonRef}\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 Popover */}\n <Popover\n open={openDropdownType === 'value'}\n onOpenChange={(open) => setOpenDropdownType(open ? 'value' : null)}\n >\n <PopoverTrigger asChild>\n <button type=\"button\" className=\"flex items-center px-2 py-1 text-sm font-bold hover:bg-black/5\">\n {getDisplayValue()}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-0\">\n {inputType === 'custom' && (\n <div className=\"p-3\">\n <CustomValueInput\n inputValue={inputValue}\n setInputValue={setInputValue}\n customValuePlaceholder={customValuePlaceholder}\n customValueButtonLabel={customValueButtonLabel}\n onSubmit={handleCustomValueSubmit}\n handleKeyDown={handleKeyDown}\n />\n </div>\n )}\n {inputType === 'dropdown' && (\n <>\n {internalFilter.source ? (\n <>\n {isMultiSelect ? (\n <MultiSelectDropdown\n internalFilter={internalFilter}\n valueOptions={valueOptions}\n onConfirm={handleMultiSelectConfirm}\n onClose={() => setOpenDropdownType(null)}\n />\n ) : (\n <SingleSelectDropdown\n valueOptions={valueOptions}\n isValueSelected={isValueSelected}\n onValueSelect={handleValueToggle}\n />\n )}\n </>\n ) : (\n <div className=\"p-3 text-sm text-gray-500\">{sourceFirstMessage}</div>\n )}\n </>\n )}\n </PopoverContent>\n </Popover>\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 aria-label=\"Remove filter\"\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, useEffect, useRef } from 'react';\nimport { Plus } from '@phosphor-icons/react';\nimport { createId } from '@paralleldrive/cuid2';\n\nimport { Filter, FilterOption, FilterRules, FilterValue, Operator } from './index';\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 onFilterAdd?: (filter: FilterValue) => void;\n sourceOptions: FilterOption[];\n rules: FilterRules;\n}\n\nconst Filters = ({\n filters,\n onFilterChange,\n onFilterRemove,\n onFilterAdd,\n sourceOptions,\n rules,\n className,\n}: FiltersProps) => {\n const [internalFilters, setInternalFilters] = useState<FilterValue[]>(filters || []);\n const filterRefs = useRef<{ [key: string]: { focus: () => void } | null }>({});\n\n // Sync internal state with props\n useEffect(() => {\n setInternalFilters(filters || []);\n }, [filters]);\n\n // Get sources that are already in use\n const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);\n\n // Get available sources that haven't been used yet\n const availableSources = sourceOptions.filter((option) => !usedSources.includes(option.id));\n\n // Check if we can add more filters\n const canAddFilter = availableSources.length > 0;\n\n const handleAddFilter = () => {\n if (!canAddFilter) return;\n\n const newFilter = {\n id: createId(),\n source: availableSources[0].id,\n operator: Operator.IS,\n value: rules[availableSources[0].id]?.multiSelect ? [] : '',\n };\n\n const newFilters = [...internalFilters, newFilter];\n setInternalFilters(newFilters);\n\n // Focus the new filter after it's rendered\n requestAnimationFrame(() => {\n filterRefs.current[newFilter.id]?.focus();\n });\n\n // Notify parent if callback provided\n onFilterAdd?.(newFilter);\n };\n\n const handleRemoveFilter = (filter: FilterValue) => {\n const newFilters = internalFilters.filter((f) => f.id !== filter.id);\n setInternalFilters(newFilters);\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 // For each filter, include available sources plus its own current source\n const filterSourceOptions = sourceOptions.filter(\n (option) =>\n !usedSources.includes(option.id) || // Available sources\n option.id === filter.source, // Or its own current source\n );\n\n return (\n <Filter\n key={filter.id}\n ref={(ref) => {\n filterRefs.current[filter.id] = ref;\n }}\n filter={filter}\n sourceOptions={filterSourceOptions}\n rules={rules}\n onRemoveFilter={() => handleRemoveFilter(filter)}\n onFilterChange={onFilterChange}\n />\n );\n })}\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n disabled={!canAddFilter}\n title={canAddFilter ? 'Add filter' : 'All sources are already in use'}\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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"}
@@ -1,2 +1,2 @@
1
- export { F as Filter, a as Filters, O as Operator } from '../chunks/filters.Dy3yDv4K.js';
1
+ export { F as Filter, a as Filters, O as Operator } from '../chunks/filters.Bo2N95yq.js';
2
2
  //# sourceMappingURL=filter.js.map