@brainfish-ai/components 0.18.4-alpha.6 → 0.18.4
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/accordion.d.ts +12 -0
- package/dist/alert-dialog.d.ts +46 -0
- package/dist/alert.d.ts +18 -0
- package/dist/badge.d.ts +14 -0
- package/dist/button-group.d.ts +21 -0
- package/dist/button.d.ts +16 -0
- package/dist/calendar.d.ts +12 -0
- package/dist/card.d.ts +15 -0
- package/dist/chart-area-linear.d.ts +41 -0
- package/dist/chart-radial-stacked.d.ts +39 -0
- package/dist/chat-search.d.ts +426 -0
- package/dist/collapsible.d.ts +10 -0
- package/dist/colors.d.ts +161 -0
- package/dist/combobox.d.ts +23 -0
- package/dist/command.d.ts +90 -0
- package/dist/components/ui/accordion.d.ts +2 -0
- package/dist/components/ui/alert-dialog.d.ts +2 -0
- package/dist/components/ui/alert.d.ts +2 -0
- package/dist/components/ui/badge.d.ts +2 -0
- package/dist/components/ui/button-group.d.ts +2 -0
- package/dist/components/ui/button.d.ts +2 -0
- package/dist/components/ui/calendar.d.ts +2 -0
- package/dist/components/ui/card.d.ts +2 -0
- package/dist/components/ui/collapsible.d.ts +2 -0
- package/dist/components/ui/command.d.ts +2 -0
- package/dist/components/ui/dialog.d.ts +2 -0
- package/dist/components/ui/div-button.d.ts +2 -0
- package/dist/components/ui/dropdown-menu.d.ts +2 -0
- package/dist/components/ui/icon.d.ts +2 -0
- package/dist/components/ui/input.d.ts +2 -0
- package/dist/components/ui/item.d.ts +2 -0
- package/dist/components/ui/label.d.ts +2 -0
- package/dist/components/ui/popover.d.ts +2 -0
- package/dist/components/ui/progress.d.ts +2 -0
- package/dist/components/ui/scroll-area.d.ts +2 -0
- package/dist/components/ui/select.d.ts +2 -0
- package/dist/components/ui/separator.d.ts +2 -0
- package/dist/components/ui/sheet.d.ts +2 -0
- package/dist/components/ui/spinner.d.ts +2 -0
- package/dist/components/ui/switch.d.ts +2 -0
- package/dist/components/ui/table.d.ts +2 -0
- package/dist/components/ui/textarea.d.ts +2 -0
- package/dist/components/ui/tooltip.d.ts +2 -0
- package/dist/confirm-dialog.d.ts +35 -0
- package/dist/convos.d.ts +179 -0
- package/dist/data-table.d.ts +23 -0
- package/dist/date-picker.d.ts +12 -0
- package/dist/dialog.d.ts +30 -0
- package/dist/div-button.d.ts +16 -0
- package/dist/dropdown-menu.d.ts +43 -0
- package/dist/esm/ChatSearch.css +1 -0
- package/dist/esm/chunks/ChatSearch.BJtS7ZMs.js +6482 -0
- package/dist/esm/chunks/ChatSearch.BJtS7ZMs.js.map +1 -0
- package/dist/esm/chunks/FormattedMessage.ieoe4jPf.js +39760 -0
- package/dist/esm/chunks/FormattedMessage.ieoe4jPf.js.map +1 -0
- package/dist/esm/chunks/_commonjsHelpers.BFTU3MAI.js +8 -0
- package/dist/esm/chunks/_commonjsHelpers.BFTU3MAI.js.map +1 -0
- package/dist/esm/chunks/chart.DGCX9VIn.js +219 -0
- package/dist/esm/chunks/chart.DGCX9VIn.js.map +1 -0
- package/dist/esm/chunks/combobox.CkN-wAHB.js +74 -0
- package/dist/esm/chunks/combobox.CkN-wAHB.js.map +1 -0
- package/dist/esm/chunks/dark.Cl9Z44CU.js +17 -0
- package/dist/esm/chunks/dark.Cl9Z44CU.js.map +1 -0
- package/dist/esm/chunks/data-table.DbcAYxMY.js +102 -0
- package/dist/esm/chunks/data-table.DbcAYxMY.js.map +1 -0
- package/dist/esm/chunks/date-picker.sQXSlqNZ.js +26 -0
- package/dist/esm/chunks/date-picker.sQXSlqNZ.js.map +1 -0
- package/dist/esm/chunks/extends.mO86zOh3.js +12 -0
- package/dist/esm/chunks/extends.mO86zOh3.js.map +1 -0
- package/dist/esm/chunks/feedback.D139-1Wr.js +214 -0
- package/dist/esm/chunks/feedback.D139-1Wr.js.map +1 -0
- package/dist/esm/chunks/file-upload-status.Vw0Zxmir.js +141 -0
- package/dist/esm/chunks/file-upload-status.Vw0Zxmir.js.map +1 -0
- package/dist/esm/chunks/filters.Be4KPvMA.js +565 -0
- package/dist/esm/chunks/filters.Be4KPvMA.js.map +1 -0
- package/dist/esm/chunks/formatNumber.Bm2k8QrT.js +10 -0
- package/dist/esm/chunks/formatNumber.Bm2k8QrT.js.map +1 -0
- package/dist/esm/chunks/generating-star.CozjECmM.js +1490 -0
- package/dist/esm/chunks/generating-star.CozjECmM.js.map +1 -0
- package/dist/esm/chunks/index.BqibIWDw.js +137 -0
- package/dist/esm/chunks/index.BqibIWDw.js.map +1 -0
- package/dist/esm/chunks/logo.BXk28Fqo.js +181 -0
- package/dist/esm/chunks/logo.BXk28Fqo.js.map +1 -0
- package/dist/esm/chunks/primary.CtiRZbqq.js +18 -0
- package/dist/esm/chunks/primary.CtiRZbqq.js.map +1 -0
- package/dist/esm/chunks/simpleSelect.B1rktKkt.js +23 -0
- package/dist/esm/chunks/simpleSelect.B1rktKkt.js.map +1 -0
- package/dist/esm/chunks/trend-value.COSukPwk.js +51 -0
- package/dist/esm/chunks/trend-value.COSukPwk.js.map +1 -0
- package/dist/esm/chunks/two-level-combobox.DsWPDcI6.js +132 -0
- package/dist/esm/chunks/two-level-combobox.DsWPDcI6.js.map +1 -0
- package/dist/esm/chunks/utils.Cwtlq8dh.js +45 -0
- package/dist/esm/chunks/utils.Cwtlq8dh.js.map +1 -0
- package/dist/esm/colors.js +170 -0
- package/dist/esm/colors.js.map +1 -0
- package/dist/esm/components/chart-area-linear.js +87 -0
- package/dist/esm/components/chart-area-linear.js.map +1 -0
- package/dist/esm/components/chart-radial-stacked.js +49 -0
- package/dist/esm/components/chart-radial-stacked.js.map +1 -0
- package/dist/esm/components/chat-search.js +2 -0
- package/dist/esm/components/chat-search.js.map +1 -0
- package/dist/esm/components/combobox.js +2 -0
- package/dist/esm/components/combobox.js.map +1 -0
- package/dist/esm/components/confirm-dialog.js +48 -0
- package/dist/esm/components/confirm-dialog.js.map +1 -0
- package/dist/esm/components/convos.js +602 -0
- package/dist/esm/components/convos.js.map +1 -0
- package/dist/esm/components/data-table.js +2 -0
- package/dist/esm/components/data-table.js.map +1 -0
- package/dist/esm/components/date-picker.js +2 -0
- package/dist/esm/components/date-picker.js.map +1 -0
- package/dist/esm/components/feedback.js +2 -0
- package/dist/esm/components/feedback.js.map +1 -0
- package/dist/esm/components/file-upload.js +2 -0
- package/dist/esm/components/file-upload.js.map +1 -0
- package/dist/esm/components/filter.js +2 -0
- package/dist/esm/components/filter.js.map +1 -0
- package/dist/esm/components/generating-star.js +2 -0
- package/dist/esm/components/generating-star.js.map +1 -0
- package/dist/esm/components/logo.js +2 -0
- package/dist/esm/components/logo.js.map +1 -0
- package/dist/esm/components/markdown.js +2 -0
- package/dist/esm/components/markdown.js.map +1 -0
- package/dist/esm/components/metric-card.js +28 -0
- package/dist/esm/components/metric-card.js.map +1 -0
- package/dist/esm/components/select.js +2 -0
- package/dist/esm/components/select.js.map +1 -0
- package/dist/esm/components/trend-value.js +2 -0
- package/dist/esm/components/trend-value.js.map +1 -0
- package/dist/esm/components/two-level-combobox.js +2 -0
- package/dist/esm/components/two-level-combobox.js.map +1 -0
- package/dist/esm/components/ui/accordion.js +47 -0
- package/dist/esm/components/ui/accordion.js.map +1 -0
- package/dist/esm/components/ui/alert-dialog.js +147 -0
- package/dist/esm/components/ui/alert-dialog.js.map +1 -0
- package/dist/esm/components/ui/alert.js +121 -0
- package/dist/esm/components/ui/alert.js.map +1 -0
- package/dist/esm/components/ui/badge.js +27 -0
- package/dist/esm/components/ui/badge.js.map +1 -0
- package/dist/esm/components/ui/button-group.js +74 -0
- package/dist/esm/components/ui/button-group.js.map +1 -0
- package/dist/esm/components/ui/button.js +52 -0
- package/dist/esm/components/ui/button.js.map +1 -0
- package/dist/esm/components/ui/calendar.js +26 -0
- package/dist/esm/components/ui/calendar.js.map +1 -0
- package/dist/esm/components/ui/card.js +56 -0
- package/dist/esm/components/ui/card.js.map +1 -0
- package/dist/esm/components/ui/collapsible.js +34 -0
- package/dist/esm/components/ui/collapsible.js.map +1 -0
- package/dist/esm/components/ui/command.js +103 -0
- package/dist/esm/components/ui/command.js.map +1 -0
- package/dist/esm/components/ui/dialog.js +88 -0
- package/dist/esm/components/ui/dialog.js.map +1 -0
- package/dist/esm/components/ui/div-button.js +61 -0
- package/dist/esm/components/ui/div-button.js.map +1 -0
- package/dist/esm/components/ui/dropdown-menu.js +132 -0
- package/dist/esm/components/ui/dropdown-menu.js.map +1 -0
- package/dist/esm/components/ui/icon.js +16 -0
- package/dist/esm/components/ui/icon.js.map +1 -0
- package/dist/esm/components/ui/input.js +29 -0
- package/dist/esm/components/ui/input.js.map +1 -0
- package/dist/esm/components/ui/item.js +179 -0
- package/dist/esm/components/ui/item.js.map +1 -0
- package/dist/esm/components/ui/label.js +20 -0
- package/dist/esm/components/ui/label.js.map +1 -0
- package/dist/esm/components/ui/popover.js +24 -0
- package/dist/esm/components/ui/popover.js.map +1 -0
- package/dist/esm/components/ui/progress.js +23 -0
- package/dist/esm/components/ui/progress.js.map +1 -0
- package/dist/esm/components/ui/scroll-area.js +34 -0
- package/dist/esm/components/ui/scroll-area.js.map +1 -0
- package/dist/esm/components/ui/select.js +81 -0
- package/dist/esm/components/ui/select.js.map +1 -0
- package/dist/esm/components/ui/separator.js +24 -0
- package/dist/esm/components/ui/separator.js.map +1 -0
- package/dist/esm/components/ui/sheet.js +99 -0
- package/dist/esm/components/ui/sheet.js.map +1 -0
- package/dist/esm/components/ui/spinner.js +18 -0
- package/dist/esm/components/ui/spinner.js.map +1 -0
- package/dist/esm/components/ui/switch.js +27 -0
- package/dist/esm/components/ui/switch.js.map +1 -0
- package/dist/esm/components/ui/table.js +83 -0
- package/dist/esm/components/ui/table.js.map +1 -0
- package/dist/esm/components/ui/textarea.js +34 -0
- package/dist/esm/components/ui/textarea.js.map +1 -0
- package/dist/esm/components/ui/tooltip.js +34 -0
- package/dist/esm/components/ui/tooltip.js.map +1 -0
- package/dist/esm/convos.css +1 -0
- package/dist/esm/date-picker.css +1 -0
- package/dist/esm/global.css +1 -0
- package/dist/esm/index.js +150 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/tailwind.preset.js +1492 -0
- package/dist/esm/tailwind.preset.js.map +1 -0
- package/dist/feedback.d.ts +21 -0
- package/dist/file-upload.d.ts +45 -0
- package/dist/filter.d.ts +82 -0
- package/dist/generating-star.d.ts +15 -0
- package/dist/icon.d.ts +26 -0
- package/dist/index.d.ts +1378 -0
- package/dist/input.d.ts +11 -0
- package/dist/item.d.ts +39 -0
- package/dist/label.d.ts +8 -0
- package/dist/logo.d.ts +14 -0
- package/dist/markdown.d.ts +55 -0
- package/dist/metric-card.d.ts +21 -0
- package/dist/popover.d.ts +12 -0
- package/dist/progress.d.ts +8 -0
- package/dist/scroll-area.d.ts +8 -0
- package/dist/select.d.ts +20 -0
- package/dist/separator.d.ts +6 -0
- package/dist/sheet.d.ts +39 -0
- package/dist/spinner.d.ts +5 -0
- package/dist/stats.html +4949 -0
- package/dist/switch.d.ts +6 -0
- package/dist/table.d.ts +19 -0
- package/dist/tailwind.preset.d.ts +1 -0
- package/dist/textarea.d.ts +9 -0
- package/dist/tooltip.d.ts +18 -0
- package/dist/trend-value.d.ts +19 -0
- package/dist/two-level-combobox.d.ts +24 -0
- package/package.json +2 -2
|
@@ -0,0 +1,565 @@
|
|
|
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 { ButtonGroup } from '../components/ui/button-group.js';
|
|
7
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from '../components/ui/dropdown-menu.js';
|
|
8
|
+
import { Popover, PopoverTrigger, PopoverContent } from '../components/ui/popover.js';
|
|
9
|
+
import { c as cn } from './utils.Cwtlq8dh.js';
|
|
10
|
+
|
|
11
|
+
var Operator = /* @__PURE__ */ ((Operator2) => {
|
|
12
|
+
Operator2["IS"] = "is";
|
|
13
|
+
Operator2["IS_NOT"] = "is not";
|
|
14
|
+
Operator2["CONTAINS"] = "contains";
|
|
15
|
+
Operator2["DOES_NOT_CONTAIN"] = "does not contain";
|
|
16
|
+
Operator2["STARTS_WITH"] = "starts with";
|
|
17
|
+
return Operator2;
|
|
18
|
+
})(Operator || {});
|
|
19
|
+
|
|
20
|
+
const useMultiSelectHelpers = (internalFilter, valueOptions, selectPlaceholder) => {
|
|
21
|
+
const getSelectedValues = () => {
|
|
22
|
+
if (Array.isArray(internalFilter.value)) {
|
|
23
|
+
return internalFilter.value;
|
|
24
|
+
}
|
|
25
|
+
return internalFilter.value ? [internalFilter.value] : [];
|
|
26
|
+
};
|
|
27
|
+
const isValueSelected = (valueId) => {
|
|
28
|
+
const selectedValues = getSelectedValues();
|
|
29
|
+
return selectedValues.includes(valueId);
|
|
30
|
+
};
|
|
31
|
+
const getDisplayValue = () => {
|
|
32
|
+
const selectedValues = getSelectedValues();
|
|
33
|
+
if (selectedValues.length === 0) return selectPlaceholder;
|
|
34
|
+
if (selectedValues.length === 1) {
|
|
35
|
+
const option = valueOptions.find((opt) => opt.id === selectedValues[0]);
|
|
36
|
+
return option?.label || selectedValues[0];
|
|
37
|
+
}
|
|
38
|
+
return `${selectedValues.length} selected`;
|
|
39
|
+
};
|
|
40
|
+
return {
|
|
41
|
+
getSelectedValues,
|
|
42
|
+
isValueSelected,
|
|
43
|
+
getDisplayValue
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const CustomValueInput = ({
|
|
48
|
+
inputValue,
|
|
49
|
+
setInputValue,
|
|
50
|
+
customValuePlaceholder,
|
|
51
|
+
customValueButtonLabel,
|
|
52
|
+
onSubmit,
|
|
53
|
+
handleKeyDown
|
|
54
|
+
}) => {
|
|
55
|
+
const inputRef = useRef(null);
|
|
56
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
57
|
+
"form",
|
|
58
|
+
{
|
|
59
|
+
className: "p-3",
|
|
60
|
+
onSubmit: (e) => {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
onSubmit();
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
/* @__PURE__ */ React__default.createElement(
|
|
66
|
+
Input,
|
|
67
|
+
{
|
|
68
|
+
ref: inputRef,
|
|
69
|
+
type: "text",
|
|
70
|
+
value: inputValue,
|
|
71
|
+
onChange: (e) => setInputValue(e.target.value),
|
|
72
|
+
placeholder: customValuePlaceholder,
|
|
73
|
+
className: "mb-2",
|
|
74
|
+
onKeyDown: (e) => handleKeyDown(e, true)
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
/* @__PURE__ */ React__default.createElement(
|
|
78
|
+
Button,
|
|
79
|
+
{
|
|
80
|
+
type: "submit",
|
|
81
|
+
variant: "dark",
|
|
82
|
+
className: "w-full",
|
|
83
|
+
onKeyDown: (e) => handleKeyDown(e, false),
|
|
84
|
+
"data-custom-submit-button": true
|
|
85
|
+
},
|
|
86
|
+
customValueButtonLabel
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const getInitialValues = (value) => {
|
|
92
|
+
if (Array.isArray(value)) {
|
|
93
|
+
return value;
|
|
94
|
+
} else if (value) {
|
|
95
|
+
return [value];
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
};
|
|
99
|
+
const MultiSelectDropdown = ({
|
|
100
|
+
internalFilter,
|
|
101
|
+
valueOptions,
|
|
102
|
+
onConfirm,
|
|
103
|
+
onClose
|
|
104
|
+
}) => {
|
|
105
|
+
const [pendingValues, setPendingValues] = useState(() => getInitialValues(internalFilter.value));
|
|
106
|
+
const [announcement, setAnnouncement] = useState("");
|
|
107
|
+
const buttonRefs = useRef([]);
|
|
108
|
+
const applyButtonRef = useRef(null);
|
|
109
|
+
const handleValueToggle = (valueId) => {
|
|
110
|
+
const option = valueOptions.find((opt) => opt.id === valueId);
|
|
111
|
+
const isCurrentlySelected = pendingValues.includes(valueId);
|
|
112
|
+
setPendingValues((prev) => {
|
|
113
|
+
const newValues = prev.includes(valueId) ? prev.filter((id) => id !== valueId) : [...prev, valueId];
|
|
114
|
+
if (option) {
|
|
115
|
+
const action = isCurrentlySelected ? "deselected" : "selected";
|
|
116
|
+
setAnnouncement(`${option.label} ${action}.`);
|
|
117
|
+
}
|
|
118
|
+
return newValues;
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
const handleConfirm = () => {
|
|
122
|
+
onConfirm(pendingValues);
|
|
123
|
+
onClose();
|
|
124
|
+
};
|
|
125
|
+
const isValueSelected = (valueId) => {
|
|
126
|
+
return pendingValues.includes(valueId);
|
|
127
|
+
};
|
|
128
|
+
const focusButton = (index) => {
|
|
129
|
+
if (index < valueOptions.length) {
|
|
130
|
+
buttonRefs.current[index]?.focus();
|
|
131
|
+
} else {
|
|
132
|
+
applyButtonRef.current?.focus();
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const handleKeyDown = (e, index) => {
|
|
136
|
+
switch (e.key) {
|
|
137
|
+
case "ArrowDown": {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
const nextIndex = Math.min(index + 1, valueOptions.length);
|
|
140
|
+
focusButton(nextIndex);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case "ArrowUp": {
|
|
144
|
+
e.preventDefault();
|
|
145
|
+
const prevIndex = Math.max(index - 1, 0);
|
|
146
|
+
focusButton(prevIndex);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
case "Enter":
|
|
150
|
+
case "Spacebar":
|
|
151
|
+
e.preventDefault();
|
|
152
|
+
if (index < valueOptions.length) {
|
|
153
|
+
handleValueToggle(valueOptions[index].id);
|
|
154
|
+
} else {
|
|
155
|
+
handleConfirm();
|
|
156
|
+
}
|
|
157
|
+
break;
|
|
158
|
+
case "Escape":
|
|
159
|
+
e.preventDefault();
|
|
160
|
+
onClose();
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
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(
|
|
165
|
+
"button",
|
|
166
|
+
{
|
|
167
|
+
key: option.id,
|
|
168
|
+
ref: (el) => buttonRefs.current[index] = el,
|
|
169
|
+
type: "button",
|
|
170
|
+
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",
|
|
171
|
+
onClick: () => handleValueToggle(option.id),
|
|
172
|
+
onKeyDown: (e) => handleKeyDown(e, index),
|
|
173
|
+
role: "option",
|
|
174
|
+
"aria-selected": isValueSelected(option.id)
|
|
175
|
+
},
|
|
176
|
+
isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
177
|
+
!isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement("span", { className: "mr-2 w-3.5" }),
|
|
178
|
+
option.label
|
|
179
|
+
)), /* @__PURE__ */ React__default.createElement("div", { className: "border-t border-border mt-1 pt-2 px-2 pb-2" }, /* @__PURE__ */ React__default.createElement(
|
|
180
|
+
Button,
|
|
181
|
+
{
|
|
182
|
+
ref: applyButtonRef,
|
|
183
|
+
onClick: handleConfirm,
|
|
184
|
+
size: "sm",
|
|
185
|
+
className: "w-full",
|
|
186
|
+
disabled: pendingValues.length === 0,
|
|
187
|
+
onKeyDown: (e) => handleKeyDown(e, valueOptions.length)
|
|
188
|
+
},
|
|
189
|
+
"Apply (",
|
|
190
|
+
pendingValues.length,
|
|
191
|
+
" selected)"
|
|
192
|
+
)));
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const SingleSelectDropdown = ({
|
|
196
|
+
valueOptions,
|
|
197
|
+
isValueSelected,
|
|
198
|
+
onValueSelect
|
|
199
|
+
}) => {
|
|
200
|
+
const buttonRefs = useRef([]);
|
|
201
|
+
const focusButton = (index) => {
|
|
202
|
+
buttonRefs.current[index]?.focus();
|
|
203
|
+
};
|
|
204
|
+
const handleKeyDown = (e, index) => {
|
|
205
|
+
switch (e.key) {
|
|
206
|
+
case "ArrowDown": {
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
const nextIndex = Math.min(index + 1, valueOptions.length - 1);
|
|
209
|
+
focusButton(nextIndex);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "ArrowUp": {
|
|
213
|
+
e.preventDefault();
|
|
214
|
+
const prevIndex = Math.max(index - 1, 0);
|
|
215
|
+
focusButton(prevIndex);
|
|
216
|
+
break;
|
|
217
|
+
}
|
|
218
|
+
case "Enter":
|
|
219
|
+
case "Spacebar":
|
|
220
|
+
e.preventDefault();
|
|
221
|
+
onValueSelect(valueOptions[index].id);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
return /* @__PURE__ */ React__default.createElement("div", { className: "py-1", role: "listbox" }, valueOptions.map((option, index) => /* @__PURE__ */ React__default.createElement(
|
|
226
|
+
"button",
|
|
227
|
+
{
|
|
228
|
+
key: option.id,
|
|
229
|
+
ref: (el) => buttonRefs.current[index] = el,
|
|
230
|
+
type: "button",
|
|
231
|
+
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",
|
|
232
|
+
onClick: () => onValueSelect(option.id),
|
|
233
|
+
onKeyDown: (e) => handleKeyDown(e, index)
|
|
234
|
+
},
|
|
235
|
+
isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
236
|
+
!isValueSelected(option.id) && /* @__PURE__ */ React__default.createElement("span", { className: "mr-2 w-3.5" }),
|
|
237
|
+
option.label
|
|
238
|
+
)));
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const Filter = forwardRef(
|
|
242
|
+
({
|
|
243
|
+
filter,
|
|
244
|
+
sourceOptions,
|
|
245
|
+
rules,
|
|
246
|
+
onSourceChange,
|
|
247
|
+
onRemoveFilter,
|
|
248
|
+
onFilterChange,
|
|
249
|
+
selectPlaceholder = "Select a value",
|
|
250
|
+
customValuePlaceholder = "Enter custom value",
|
|
251
|
+
customValueButtonLabel = "Done",
|
|
252
|
+
sourceFirstMessage = "Please select a source first"
|
|
253
|
+
}, ref) => {
|
|
254
|
+
const [internalFilter, setInternalFilter] = useState({
|
|
255
|
+
id: filter.id,
|
|
256
|
+
source: filter.source,
|
|
257
|
+
operator: filter.operator || Operator.IS,
|
|
258
|
+
value: filter.value
|
|
259
|
+
});
|
|
260
|
+
const [inputValue, setInputValue] = useState("");
|
|
261
|
+
const [openDropdownType, setOpenDropdownType] = useState(null);
|
|
262
|
+
const inputRef = useRef(null);
|
|
263
|
+
const sourceButtonRef = useRef(null);
|
|
264
|
+
const divRef = useRef(null);
|
|
265
|
+
useImperativeHandle(ref, () => ({
|
|
266
|
+
focus: () => {
|
|
267
|
+
sourceButtonRef.current?.focus();
|
|
268
|
+
}
|
|
269
|
+
}));
|
|
270
|
+
const currentRules = internalFilter.source ? rules[internalFilter.source] : void 0;
|
|
271
|
+
const operatorOptions = currentRules?.operators || [];
|
|
272
|
+
const isMultiSelect = currentRules?.multiSelect || false;
|
|
273
|
+
let inputType = currentRules?.inputType || "dropdown";
|
|
274
|
+
if (internalFilter.operator === Operator.CONTAINS || internalFilter.operator === Operator.DOES_NOT_CONTAIN) {
|
|
275
|
+
inputType = "custom";
|
|
276
|
+
}
|
|
277
|
+
const valueOptions = currentRules?.getValueOptions ? currentRules.getValueOptions() : [];
|
|
278
|
+
const { getSelectedValues, isValueSelected, getDisplayValue } = useMultiSelectHelpers(
|
|
279
|
+
internalFilter,
|
|
280
|
+
valueOptions,
|
|
281
|
+
selectPlaceholder
|
|
282
|
+
);
|
|
283
|
+
useEffect(() => {
|
|
284
|
+
if (openDropdownType === "value" && inputType === "custom") {
|
|
285
|
+
const timeoutId = setTimeout(() => inputRef.current?.focus(), 50);
|
|
286
|
+
return () => clearTimeout(timeoutId);
|
|
287
|
+
}
|
|
288
|
+
return void 0;
|
|
289
|
+
}, [openDropdownType, inputType]);
|
|
290
|
+
useEffect(() => {
|
|
291
|
+
setInternalFilter({
|
|
292
|
+
id: filter.id,
|
|
293
|
+
source: filter.source,
|
|
294
|
+
operator: filter.operator || Operator.IS,
|
|
295
|
+
value: filter.value
|
|
296
|
+
});
|
|
297
|
+
}, [filter]);
|
|
298
|
+
const checkAndTriggerChange = (newFilter) => {
|
|
299
|
+
const hasValue = Array.isArray(newFilter.value) ? newFilter.value.length > 0 : !!newFilter.value?.trim();
|
|
300
|
+
const isComplete = newFilter.source && newFilter.operator && hasValue;
|
|
301
|
+
if (isComplete) {
|
|
302
|
+
onFilterChange(newFilter);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
const updateFilterField = (field, value) => {
|
|
306
|
+
const newFilter = { ...internalFilter, [field]: value };
|
|
307
|
+
if (field === "source") {
|
|
308
|
+
const sourceRules = rules[value];
|
|
309
|
+
newFilter.operator = sourceRules?.operators[0]?.id;
|
|
310
|
+
newFilter.value = sourceRules?.multiSelect ? [] : "";
|
|
311
|
+
}
|
|
312
|
+
if (field === "operator") {
|
|
313
|
+
if (internalFilter.source) {
|
|
314
|
+
const sourceRules = rules[internalFilter.source];
|
|
315
|
+
if (sourceRules?.inputType === "dropdown") {
|
|
316
|
+
newFilter.value = sourceRules?.multiSelect ? [] : "";
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
setInternalFilter(newFilter);
|
|
321
|
+
checkAndTriggerChange(newFilter);
|
|
322
|
+
if (!isMultiSelect || field !== "value") {
|
|
323
|
+
setOpenDropdownType(null);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const handleValueToggle = (valueId) => {
|
|
327
|
+
const selectedValues = getSelectedValues();
|
|
328
|
+
let newValues;
|
|
329
|
+
if (isMultiSelect) {
|
|
330
|
+
if (selectedValues.includes(valueId)) {
|
|
331
|
+
newValues = selectedValues.filter((id) => id !== valueId);
|
|
332
|
+
} else {
|
|
333
|
+
newValues = [...selectedValues, valueId];
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
newValues = [valueId];
|
|
337
|
+
}
|
|
338
|
+
const newFilter = {
|
|
339
|
+
...internalFilter,
|
|
340
|
+
value: isMultiSelect ? newValues : newValues[0] || ""
|
|
341
|
+
};
|
|
342
|
+
setInternalFilter(newFilter);
|
|
343
|
+
checkAndTriggerChange(newFilter);
|
|
344
|
+
if (!isMultiSelect) {
|
|
345
|
+
setOpenDropdownType(null);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
const handleMultiSelectConfirm = (selectedValues) => {
|
|
349
|
+
const newFilter = {
|
|
350
|
+
...internalFilter,
|
|
351
|
+
value: selectedValues
|
|
352
|
+
};
|
|
353
|
+
setInternalFilter(newFilter);
|
|
354
|
+
const isComplete = newFilter.source && newFilter.operator && selectedValues.length > 0;
|
|
355
|
+
if (isComplete) onFilterChange(newFilter);
|
|
356
|
+
setOpenDropdownType(null);
|
|
357
|
+
};
|
|
358
|
+
const handleCustomValueSubmit = () => {
|
|
359
|
+
if (inputValue.trim()) {
|
|
360
|
+
const newFilter = { ...internalFilter, value: inputValue.trim() };
|
|
361
|
+
setInternalFilter(newFilter);
|
|
362
|
+
setInputValue("");
|
|
363
|
+
setOpenDropdownType(null);
|
|
364
|
+
if (newFilter.source && newFilter.operator && newFilter.value) {
|
|
365
|
+
onFilterChange(newFilter);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
const handleKeyDown = (e, isInput) => {
|
|
370
|
+
if (e.key === "Escape") {
|
|
371
|
+
setOpenDropdownType(null);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (e.key === "Tab") {
|
|
375
|
+
if (isInput && !e.shiftKey) {
|
|
376
|
+
e.preventDefault();
|
|
377
|
+
const button = document.querySelector("[data-custom-submit-button]");
|
|
378
|
+
button?.focus();
|
|
379
|
+
} else if (!isInput) {
|
|
380
|
+
e.preventDefault();
|
|
381
|
+
inputRef.current?.focus();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
386
|
+
ButtonGroup,
|
|
387
|
+
{
|
|
388
|
+
ref: divRef,
|
|
389
|
+
orientation: "horizontal",
|
|
390
|
+
className: "rounded-full border border-border divide-x-2 divide-dark-500"
|
|
391
|
+
},
|
|
392
|
+
/* @__PURE__ */ React__default.createElement(
|
|
393
|
+
DropdownMenu,
|
|
394
|
+
{
|
|
395
|
+
open: openDropdownType === "source",
|
|
396
|
+
onOpenChange: (open) => setOpenDropdownType(open ? "source" : null),
|
|
397
|
+
modal: false
|
|
398
|
+
},
|
|
399
|
+
/* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(Button, { ref: sourceButtonRef, variant: "ghost", size: "xs", className: "rounded-l-full font-bold" }, sourceOptions.find((opt) => opt.id === internalFilter.source)?.label || sourceOptions[0]?.label || selectPlaceholder)),
|
|
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
|
+
),
|
|
414
|
+
/* @__PURE__ */ React__default.createElement(
|
|
415
|
+
DropdownMenu,
|
|
416
|
+
{
|
|
417
|
+
open: openDropdownType === "operator",
|
|
418
|
+
onOpenChange: (open) => setOpenDropdownType(open ? "operator" : null),
|
|
419
|
+
modal: false
|
|
420
|
+
},
|
|
421
|
+
/* @__PURE__ */ React__default.createElement(DropdownMenuTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(Button, { variant: "ghost", size: "xs" }, operatorOptions.find((opt) => opt.id === internalFilter.operator)?.label || selectPlaceholder)),
|
|
422
|
+
/* @__PURE__ */ React__default.createElement(DropdownMenuContent, { align: "start", className: "w-48" }, operatorOptions.map((option) => /* @__PURE__ */ React__default.createElement(
|
|
423
|
+
DropdownMenuItem,
|
|
424
|
+
{
|
|
425
|
+
key: option.id,
|
|
426
|
+
className: "flex items-center",
|
|
427
|
+
onSelect: () => updateFilterField("operator", option.id)
|
|
428
|
+
},
|
|
429
|
+
option.id === internalFilter.operator && /* @__PURE__ */ React__default.createElement(Check, { size: 14, className: "mr-2" }),
|
|
430
|
+
option.label
|
|
431
|
+
)))
|
|
432
|
+
),
|
|
433
|
+
/* @__PURE__ */ React__default.createElement(
|
|
434
|
+
Popover,
|
|
435
|
+
{
|
|
436
|
+
open: openDropdownType === "value",
|
|
437
|
+
onOpenChange: (open) => setOpenDropdownType(open ? "value" : null)
|
|
438
|
+
},
|
|
439
|
+
/* @__PURE__ */ React__default.createElement(PopoverTrigger, { asChild: true }, /* @__PURE__ */ React__default.createElement(Button, { variant: "ghost", size: "xs", className: "font-bold" }, getDisplayValue())),
|
|
440
|
+
/* @__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(
|
|
441
|
+
CustomValueInput,
|
|
442
|
+
{
|
|
443
|
+
inputValue,
|
|
444
|
+
setInputValue,
|
|
445
|
+
customValuePlaceholder,
|
|
446
|
+
customValueButtonLabel,
|
|
447
|
+
onSubmit: handleCustomValueSubmit,
|
|
448
|
+
handleKeyDown
|
|
449
|
+
}
|
|
450
|
+
)), 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(
|
|
451
|
+
MultiSelectDropdown,
|
|
452
|
+
{
|
|
453
|
+
internalFilter,
|
|
454
|
+
valueOptions,
|
|
455
|
+
onConfirm: handleMultiSelectConfirm,
|
|
456
|
+
onClose: () => setOpenDropdownType(null)
|
|
457
|
+
}
|
|
458
|
+
) : /* @__PURE__ */ React__default.createElement(
|
|
459
|
+
SingleSelectDropdown,
|
|
460
|
+
{
|
|
461
|
+
valueOptions,
|
|
462
|
+
isValueSelected,
|
|
463
|
+
onValueSelect: handleValueToggle
|
|
464
|
+
}
|
|
465
|
+
)) : /* @__PURE__ */ React__default.createElement("div", { className: "p-3 text-sm text-gray-500" }, sourceFirstMessage)))
|
|
466
|
+
),
|
|
467
|
+
/* @__PURE__ */ React__default.createElement(
|
|
468
|
+
Button,
|
|
469
|
+
{
|
|
470
|
+
type: "button",
|
|
471
|
+
variant: "ghost",
|
|
472
|
+
size: "xs",
|
|
473
|
+
onClick: () => {
|
|
474
|
+
setInternalFilter({ id: filter.id });
|
|
475
|
+
setOpenDropdownType(null);
|
|
476
|
+
onRemoveFilter(filter.id);
|
|
477
|
+
},
|
|
478
|
+
className: "p-2 hover:bg-black/10 rounded-none rounded-r-full",
|
|
479
|
+
"aria-label": "Remove filter"
|
|
480
|
+
},
|
|
481
|
+
/* @__PURE__ */ React__default.createElement(XCircle, { size: 16, weight: "fill" })
|
|
482
|
+
)
|
|
483
|
+
);
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
Filter.displayName = "Filter";
|
|
487
|
+
|
|
488
|
+
const Filters = ({
|
|
489
|
+
filters,
|
|
490
|
+
onFilterChange,
|
|
491
|
+
onFilterRemove,
|
|
492
|
+
onFilterAdd,
|
|
493
|
+
sourceOptions,
|
|
494
|
+
rules,
|
|
495
|
+
className
|
|
496
|
+
}) => {
|
|
497
|
+
const [internalFilters, setInternalFilters] = useState(filters || []);
|
|
498
|
+
const filterRefs = useRef({});
|
|
499
|
+
useEffect(() => {
|
|
500
|
+
setInternalFilters(filters || []);
|
|
501
|
+
}, [filters]);
|
|
502
|
+
const usedSources = internalFilters.map((filter) => filter.source).filter(Boolean);
|
|
503
|
+
const availableSources = sourceOptions.filter((option) => {
|
|
504
|
+
if (rules[option.id]?.multiSelect) {
|
|
505
|
+
return !usedSources.includes(option.id);
|
|
506
|
+
}
|
|
507
|
+
return sourceOptions;
|
|
508
|
+
});
|
|
509
|
+
const canAddFilter = availableSources.length > 0;
|
|
510
|
+
const handleAddFilter = () => {
|
|
511
|
+
if (!canAddFilter) return;
|
|
512
|
+
const newFilter = {
|
|
513
|
+
id: createId(),
|
|
514
|
+
source: availableSources[0].id,
|
|
515
|
+
operator: Operator.IS,
|
|
516
|
+
value: rules[availableSources[0].id]?.multiSelect ? [] : ""
|
|
517
|
+
};
|
|
518
|
+
const newFilters = [...internalFilters, newFilter];
|
|
519
|
+
setInternalFilters(newFilters);
|
|
520
|
+
requestAnimationFrame(() => {
|
|
521
|
+
filterRefs.current[newFilter.id]?.focus();
|
|
522
|
+
});
|
|
523
|
+
onFilterAdd?.(newFilter);
|
|
524
|
+
};
|
|
525
|
+
const handleRemoveFilter = (filter) => {
|
|
526
|
+
const newFilters = internalFilters.filter((f) => f.id !== filter.id);
|
|
527
|
+
setInternalFilters(newFilters);
|
|
528
|
+
onFilterRemove(filter.id);
|
|
529
|
+
};
|
|
530
|
+
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) => {
|
|
531
|
+
const filterSourceOptions = sourceOptions.filter(
|
|
532
|
+
(option) => !usedSources.includes(option.id) || // Available sources
|
|
533
|
+
option.id === filter.source
|
|
534
|
+
// Or its own current source
|
|
535
|
+
);
|
|
536
|
+
return /* @__PURE__ */ React__default.createElement(
|
|
537
|
+
Filter,
|
|
538
|
+
{
|
|
539
|
+
key: filter.id,
|
|
540
|
+
ref: (ref) => {
|
|
541
|
+
filterRefs.current[filter.id] = ref;
|
|
542
|
+
},
|
|
543
|
+
filter,
|
|
544
|
+
sourceOptions: filterSourceOptions,
|
|
545
|
+
rules,
|
|
546
|
+
onRemoveFilter: () => handleRemoveFilter(filter),
|
|
547
|
+
onFilterChange
|
|
548
|
+
}
|
|
549
|
+
);
|
|
550
|
+
}), canAddFilter && /* @__PURE__ */ React__default.createElement(
|
|
551
|
+
Button,
|
|
552
|
+
{
|
|
553
|
+
onClick: handleAddFilter,
|
|
554
|
+
variant: "ghost",
|
|
555
|
+
className: "border border-foreground rounded-full gap-1",
|
|
556
|
+
size: "sm",
|
|
557
|
+
title: "Add filter"
|
|
558
|
+
},
|
|
559
|
+
/* @__PURE__ */ React__default.createElement(Plus, { size: 16 }),
|
|
560
|
+
"Add filter"
|
|
561
|
+
));
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
export { Filter as F, Operator as O, Filters as a };
|
|
565
|
+
//# sourceMappingURL=filters.Be4KPvMA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filters.Be4KPvMA.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 { ButtonGroup } from '@/components/ui/button-group';\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 <ButtonGroup\n ref={divRef}\n orientation=\"horizontal\"\n className=\"rounded-full border border-border divide-x-2 divide-dark-500\"\n >\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 ref={sourceButtonRef} variant=\"ghost\" size=\"xs\" className=\"rounded-l-full font-bold\">\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 variant=\"ghost\" size=\"xs\">\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 variant=\"ghost\" size=\"xs\" className=\"font-bold\">\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=\"xs\"\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 </ButtonGroup>\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) => {\n // If the source has multiSelect enabled, filter out used sources\n if (rules[option.id]?.multiSelect) {\n return !usedSources.includes(option.id);\n }\n\n // If multiSelect is false or undefined, allow the source to be used multiple times\n return sourceOptions;\n });\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 {canAddFilter && (\n <Button\n onClick={handleAddFilter}\n variant=\"ghost\"\n className=\"border border-foreground rounded-full gap-1\"\n size=\"sm\"\n title=\"Add filter\"\n >\n <Plus size={16} />\n Add filter\n </Button>\n )}\n </fieldset>\n );\n};\n\nexport { Filters };\n"],"names":["Operator","React"],"mappings":"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"}
|