@socprime/react-ui 0.0.5
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/CHANGELOG.md +56 -0
- package/LICENSE +21 -0
- package/README.md +537 -0
- package/attack-flow.d.ts +16 -0
- package/charts.d.ts +32 -0
- package/decorators/index.js +8 -0
- package/decorators/withRouter.js +10 -0
- package/decorators/withTheme.js +10 -0
- package/decorators.d.ts +10 -0
- package/domain.d.ts +23 -0
- package/editor.d.ts +25 -0
- package/index.d.ts +702 -0
- package/lib/cn.js +8 -0
- package/lib/theme.js +26 -0
- package/lib/useFullscreen.js +52 -0
- package/lib/useListenOnResizeDebounce.js +22 -0
- package/lib/useThemeColors.js +39 -0
- package/package.json +113 -0
- package/preset/createConfig.js +98 -0
- package/preset/createPreview.js +53 -0
- package/preset/index.js +6 -0
- package/preset/restoreNativeFocus.js +33 -0
- package/preset/types.js +0 -0
- package/preset.d.ts +27 -0
- package/theme-9m7j1UoI.d.ts +5 -0
- package/ui/Accordion/Accordion.js +82 -0
- package/ui/Accordion/AccordionSection.js +41 -0
- package/ui/Accordion/FolderTreeExpandTrigger.js +29 -0
- package/ui/Accordion/chevronVariants.js +31 -0
- package/ui/Accordion/index.js +16 -0
- package/ui/AnimatedDots/AnimatedDots.js +10 -0
- package/ui/AnimatedDots/index.js +4 -0
- package/ui/Aside/Aside.js +34 -0
- package/ui/Aside/index.js +4 -0
- package/ui/AttackFlow/AttackFlow.js +9 -0
- package/ui/AttackFlow/AttackFlowLayout.js +63 -0
- package/ui/AttackFlow/Controls.js +42 -0
- package/ui/AttackFlow/Node.js +47 -0
- package/ui/AttackFlow/OtherNode.js +44 -0
- package/ui/AttackFlow/index.js +4 -0
- package/ui/AttackFlow/prependData.js +153 -0
- package/ui/AttackFlow/types.js +0 -0
- package/ui/AttackFlow/useAttackFlow.js +193 -0
- package/ui/Badge/Badge.js +57 -0
- package/ui/Badge/index.js +5 -0
- package/ui/Button/Button.css +1 -0
- package/ui/Button/Button.js +109 -0
- package/ui/Button/index.js +5 -0
- package/ui/Charts/AreaChartWithGradient.js +79 -0
- package/ui/Charts/index.js +4 -0
- package/ui/Checkbox/Checkbox.js +31 -0
- package/ui/Checkbox/index.js +4 -0
- package/ui/ConditionalContent/ConditionalContent.js +10 -0
- package/ui/ConditionalContent/index.js +4 -0
- package/ui/CorrelationTimer/CorrelationTimer.js +62 -0
- package/ui/CorrelationTimer/index.js +4 -0
- package/ui/DeleteButtonConfirm/DeleteButtonConfirm.js +65 -0
- package/ui/DeleteButtonConfirm/index.js +4 -0
- package/ui/Dialog/ConfirmDialog.js +54 -0
- package/ui/Dialog/DefaultDialog.js +82 -0
- package/ui/Dialog/Dialog.js +120 -0
- package/ui/Dialog/index.js +32 -0
- package/ui/Dropdown/Dropdown.js +204 -0
- package/ui/Dropdown/DropdownsCheckbox.js +102 -0
- package/ui/Dropdown/DropdownsSelect.js +97 -0
- package/ui/Dropdown/index.js +38 -0
- package/ui/Editor/Editor.js +97 -0
- package/ui/Editor/index.js +4 -0
- package/ui/Editor/monacoSetup.js +38 -0
- package/ui/Editor/theme.js +50 -0
- package/ui/Editor/types.js +0 -0
- package/ui/EmptyState/EmptyState.js +26 -0
- package/ui/EmptyState/index.js +4 -0
- package/ui/Field/Field.js +204 -0
- package/ui/Field/index.js +24 -0
- package/ui/HelperText/HelperText.js +7 -0
- package/ui/HelperText/index.js +4 -0
- package/ui/Input/Input.js +40 -0
- package/ui/Input/index.js +4 -0
- package/ui/InputNumber/InputNumber.js +90 -0
- package/ui/InputNumber/index.js +4 -0
- package/ui/InputPassword/InputPassword.js +30 -0
- package/ui/InputPassword/index.js +4 -0
- package/ui/Label/Label.js +13 -0
- package/ui/Label/LabelInfo.js +14 -0
- package/ui/Label/index.js +6 -0
- package/ui/MultiSelect/MultiSelect.js +163 -0
- package/ui/MultiSelect/index.js +4 -0
- package/ui/PageHeader/PageHeader.js +51 -0
- package/ui/PageHeader/index.js +4 -0
- package/ui/Pagination/Pagination.js +97 -0
- package/ui/Pagination/PaginationWrap.js +149 -0
- package/ui/Pagination/index.js +20 -0
- package/ui/RadioGroup/RadioGroup.js +45 -0
- package/ui/RadioGroup/index.js +5 -0
- package/ui/ScrollArea/ScrollArea.js +57 -0
- package/ui/ScrollArea/index.js +5 -0
- package/ui/SearchInput/SearchInput.js +38 -0
- package/ui/SearchInput/index.js +4 -0
- package/ui/SearchInputFields/SearchInputFields.js +53 -0
- package/ui/SearchInputFields/index.js +4 -0
- package/ui/Select/Select.js +155 -0
- package/ui/Select/SelectDefault.js +43 -0
- package/ui/Select/index.js +26 -0
- package/ui/Separator/Separator.js +26 -0
- package/ui/Separator/index.js +4 -0
- package/ui/Severity/Severity.js +11 -0
- package/ui/Severity/index.js +4 -0
- package/ui/Severity/utils.js +53 -0
- package/ui/Skeleton/Skeleton.js +25 -0
- package/ui/Skeleton/index.js +5 -0
- package/ui/Slider/Slider.js +50 -0
- package/ui/Slider/index.js +4 -0
- package/ui/Spinner/Spinner.js +21 -0
- package/ui/Spinner/index.js +5 -0
- package/ui/SpinnerSquare/SpinnerSquare.css +1 -0
- package/ui/SpinnerSquare/SpinnerSquare.js +22 -0
- package/ui/SpinnerSquare/index.js +4 -0
- package/ui/StatisticCard/StatisticCard.js +27 -0
- package/ui/StatisticCard/index.js +4 -0
- package/ui/StatisticCard/types.js +0 -0
- package/ui/Suggestions/Suggestions.js +244 -0
- package/ui/Suggestions/index.js +4 -0
- package/ui/Switch/Switch.js +64 -0
- package/ui/Switch/index.js +4 -0
- package/ui/SyncProcessBar/SyncProcessBar.js +14 -0
- package/ui/SyncProcessBar/index.js +4 -0
- package/ui/Table/GroupHeaderRow.js +36 -0
- package/ui/Table/RowGrouped.js +19 -0
- package/ui/Table/ServerGroupedTableBody.js +89 -0
- package/ui/Table/SortableHeader.js +46 -0
- package/ui/Table/Table.js +110 -0
- package/ui/Table/TableWrap.js +124 -0
- package/ui/Table/columnStyle.js +14 -0
- package/ui/Table/index.js +28 -0
- package/ui/Tabs/Tabs.js +76 -0
- package/ui/Tabs/index.js +4 -0
- package/ui/TextTruncate/TextTruncate.js +107 -0
- package/ui/TextTruncate/index.js +4 -0
- package/ui/Textarea/Textarea.js +20 -0
- package/ui/Textarea/index.js +4 -0
- package/ui/ThemeToggle/ThemeToggle.js +23 -0
- package/ui/ThemeToggle/index.js +4 -0
- package/ui/Toast/Toast.js +23 -0
- package/ui/Toast/index.js +4 -0
- package/ui/Tooltip/Tooltip.js +17 -0
- package/ui/Tooltip/TooltipLayout.js +60 -0
- package/ui/Tooltip/index.js +14 -0
- package/ui/TreeGuide/TreeGuide.js +23 -0
- package/ui/TreeGuide/index.js +5 -0
- package/ui/entries/charts.js +2 -0
- package/ui/entries/domain.js +3 -0
- package/ui/index.js +45 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "../Button/Button.js";
|
|
3
|
+
import { Input } from "../Input/Input.js";
|
|
4
|
+
import { ScrollArea } from "../ScrollArea/ScrollArea.js";
|
|
5
|
+
import { cn } from "../../lib/cn.js";
|
|
6
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
7
|
+
import { Check, XIcon } from "lucide-react";
|
|
8
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
9
|
+
const Suggestions = ({
|
|
10
|
+
options,
|
|
11
|
+
value = "",
|
|
12
|
+
placeholder = "Start typing...",
|
|
13
|
+
id,
|
|
14
|
+
name,
|
|
15
|
+
className,
|
|
16
|
+
disabled = false,
|
|
17
|
+
loading = false,
|
|
18
|
+
dropdownClassName,
|
|
19
|
+
minChars = 0,
|
|
20
|
+
showAllOnFocus = true,
|
|
21
|
+
allowCustomValue = false,
|
|
22
|
+
onChange
|
|
23
|
+
}) => {
|
|
24
|
+
const [open, setOpen] = useState(false);
|
|
25
|
+
const [inputValue, setInputValue] = useState("");
|
|
26
|
+
const [highlightedIndex, setHighlightedIndex] = useState(-1);
|
|
27
|
+
const inputRef = useRef(null);
|
|
28
|
+
const lastSelectedValueRef = useRef("");
|
|
29
|
+
const isSelectingRef = useRef(false);
|
|
30
|
+
const isFocusedRef = useRef(false);
|
|
31
|
+
const inputValueRef = useRef("");
|
|
32
|
+
const setInputValueSync = (val) => {
|
|
33
|
+
inputValueRef.current = val;
|
|
34
|
+
setInputValue(val);
|
|
35
|
+
};
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (isFocusedRef.current) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const selectedOption = options.find((opt) => opt.value === value);
|
|
41
|
+
setInputValueSync(selectedOption ? selectedOption.label : value);
|
|
42
|
+
lastSelectedValueRef.current = value ?? "";
|
|
43
|
+
}, [value, options]);
|
|
44
|
+
const labelCounts = useMemo(() => {
|
|
45
|
+
return options.reduce((acc, option) => {
|
|
46
|
+
const key = option.label.toLowerCase();
|
|
47
|
+
acc[key] = (acc[key] || 0) + 1;
|
|
48
|
+
return acc;
|
|
49
|
+
}, {});
|
|
50
|
+
}, [options]);
|
|
51
|
+
const filteredOptions = useMemo(() => {
|
|
52
|
+
const query = inputValueRef.current;
|
|
53
|
+
if (!query || query.length < minChars) {
|
|
54
|
+
return showAllOnFocus ? options : [];
|
|
55
|
+
}
|
|
56
|
+
const lower = query.toLowerCase();
|
|
57
|
+
return options.filter(
|
|
58
|
+
(option) => option.label.toLowerCase().includes(lower) || (labelCounts[option.label.toLowerCase()] || 0) > 1 && option.value.toLowerCase().includes(lower)
|
|
59
|
+
);
|
|
60
|
+
}, [options, inputValue, minChars, showAllOnFocus, labelCounts]);
|
|
61
|
+
const handleInputChange = (newValue) => {
|
|
62
|
+
setInputValueSync(newValue);
|
|
63
|
+
setHighlightedIndex(-1);
|
|
64
|
+
if (newValue.length >= minChars || showAllOnFocus && newValue.length === 0) {
|
|
65
|
+
setOpen(true);
|
|
66
|
+
} else {
|
|
67
|
+
setOpen(false);
|
|
68
|
+
}
|
|
69
|
+
if (allowCustomValue) {
|
|
70
|
+
onChange(newValue);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const handleSelectOption = (option) => {
|
|
74
|
+
isSelectingRef.current = true;
|
|
75
|
+
setInputValueSync(option.label);
|
|
76
|
+
onChange(option.value);
|
|
77
|
+
lastSelectedValueRef.current = option.value;
|
|
78
|
+
setOpen(false);
|
|
79
|
+
inputRef.current?.blur();
|
|
80
|
+
setTimeout(() => {
|
|
81
|
+
isSelectingRef.current = false;
|
|
82
|
+
}, 200);
|
|
83
|
+
};
|
|
84
|
+
const handleInputFocus = () => {
|
|
85
|
+
isFocusedRef.current = true;
|
|
86
|
+
setHighlightedIndex(-1);
|
|
87
|
+
if (showAllOnFocus || inputValueRef.current.length >= minChars) {
|
|
88
|
+
setOpen(true);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const handleInputBlur = () => {
|
|
92
|
+
isFocusedRef.current = false;
|
|
93
|
+
setTimeout(() => {
|
|
94
|
+
if (isSelectingRef.current) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
setOpen(false);
|
|
98
|
+
const currentInputValue = inputValueRef.current;
|
|
99
|
+
if (!allowCustomValue && currentInputValue) {
|
|
100
|
+
const exactMatches = options.filter(
|
|
101
|
+
(opt) => opt.label.toLowerCase() === currentInputValue.toLowerCase()
|
|
102
|
+
);
|
|
103
|
+
if (exactMatches.length > 1) {
|
|
104
|
+
const currentOption = options.find((opt) => opt.value === value);
|
|
105
|
+
if (currentOption && exactMatches.some((opt) => opt.value === currentOption.value)) {
|
|
106
|
+
setInputValueSync(currentOption.label);
|
|
107
|
+
} else {
|
|
108
|
+
setInputValueSync(exactMatches[0].label);
|
|
109
|
+
onChange(exactMatches[0].value);
|
|
110
|
+
lastSelectedValueRef.current = exactMatches[0].value;
|
|
111
|
+
}
|
|
112
|
+
} else if (exactMatches.length === 1) {
|
|
113
|
+
setInputValueSync(exactMatches[0].label);
|
|
114
|
+
onChange(exactMatches[0].value);
|
|
115
|
+
lastSelectedValueRef.current = exactMatches[0].value;
|
|
116
|
+
} else {
|
|
117
|
+
const currentOption = options.find((opt) => opt.value === value);
|
|
118
|
+
const lastSelectedOption = lastSelectedValueRef.current ? options.find((opt) => opt.value === lastSelectedValueRef.current) : void 0;
|
|
119
|
+
if (currentOption) {
|
|
120
|
+
setInputValueSync(currentOption.label);
|
|
121
|
+
} else if (lastSelectedOption) {
|
|
122
|
+
setInputValueSync(lastSelectedOption.label);
|
|
123
|
+
onChange(lastSelectedOption.value);
|
|
124
|
+
} else {
|
|
125
|
+
setInputValueSync("");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}, 150);
|
|
130
|
+
};
|
|
131
|
+
const handleKeyDown = (e) => {
|
|
132
|
+
if (!open || filteredOptions.length === 0) return;
|
|
133
|
+
switch (e.key) {
|
|
134
|
+
case "ArrowDown":
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
setHighlightedIndex((prev) => prev < filteredOptions.length - 1 ? prev + 1 : prev);
|
|
137
|
+
break;
|
|
138
|
+
case "ArrowUp":
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
setHighlightedIndex((prev) => prev > 0 ? prev - 1 : -1);
|
|
141
|
+
break;
|
|
142
|
+
case "Enter":
|
|
143
|
+
e.preventDefault();
|
|
144
|
+
if (highlightedIndex >= 0 && highlightedIndex < filteredOptions.length) {
|
|
145
|
+
handleSelectOption(filteredOptions[highlightedIndex]);
|
|
146
|
+
} else if (filteredOptions.length > 0) {
|
|
147
|
+
handleSelectOption(filteredOptions[0]);
|
|
148
|
+
}
|
|
149
|
+
break;
|
|
150
|
+
case "Escape":
|
|
151
|
+
e.preventDefault();
|
|
152
|
+
setOpen(false);
|
|
153
|
+
inputRef.current?.blur();
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const isSelected = (option) => {
|
|
160
|
+
return option.value === value;
|
|
161
|
+
};
|
|
162
|
+
return /* @__PURE__ */ jsxs(PopoverPrimitive.Root, { open, children: [
|
|
163
|
+
/* @__PURE__ */ jsx(PopoverPrimitive.Anchor, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
164
|
+
/* @__PURE__ */ jsx(
|
|
165
|
+
Input,
|
|
166
|
+
{
|
|
167
|
+
ref: inputRef,
|
|
168
|
+
type: "text",
|
|
169
|
+
id,
|
|
170
|
+
name,
|
|
171
|
+
value: inputValue,
|
|
172
|
+
loading,
|
|
173
|
+
onChange: (e) => handleInputChange(e.target.value),
|
|
174
|
+
onFocus: handleInputFocus,
|
|
175
|
+
onBlur: handleInputBlur,
|
|
176
|
+
onKeyDown: handleKeyDown,
|
|
177
|
+
disabled,
|
|
178
|
+
placeholder,
|
|
179
|
+
className: cn("pr-7 text-xs", className)
|
|
180
|
+
}
|
|
181
|
+
),
|
|
182
|
+
inputValue && /* @__PURE__ */ jsx(
|
|
183
|
+
Button,
|
|
184
|
+
{
|
|
185
|
+
variant: "ghost",
|
|
186
|
+
size: "xxs",
|
|
187
|
+
"aria-label": "Clear",
|
|
188
|
+
className: "absolute top-1/2 right-2 -translate-y-1/2 px-1 text-xs hover:bg-transparent",
|
|
189
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
190
|
+
onClick: () => {
|
|
191
|
+
setInputValueSync("");
|
|
192
|
+
onChange("");
|
|
193
|
+
lastSelectedValueRef.current = "";
|
|
194
|
+
inputRef.current?.focus();
|
|
195
|
+
},
|
|
196
|
+
children: /* @__PURE__ */ jsx(XIcon, { className: "size-4" })
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
] }) }),
|
|
200
|
+
/* @__PURE__ */ jsx(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
201
|
+
PopoverPrimitive.Content,
|
|
202
|
+
{
|
|
203
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
204
|
+
className: cn(
|
|
205
|
+
"bg-secondary border-border text-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 z-50 rounded-md border shadow-md outline-none",
|
|
206
|
+
dropdownClassName || "w-[var(--radix-popover-anchor-width)]"
|
|
207
|
+
),
|
|
208
|
+
sideOffset: 4,
|
|
209
|
+
children: /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[300px]", children: /* @__PURE__ */ jsx("div", { className: "p-1", children: filteredOptions.map((option, index) => {
|
|
210
|
+
const selected = isSelected(option);
|
|
211
|
+
const isDuplicateLabel = (labelCounts[option.label.toLowerCase()] || 0) > 1;
|
|
212
|
+
return /* @__PURE__ */ jsxs(
|
|
213
|
+
"div",
|
|
214
|
+
{
|
|
215
|
+
onMouseDown: (e) => {
|
|
216
|
+
e.preventDefault();
|
|
217
|
+
if (!option.disabled) {
|
|
218
|
+
handleSelectOption(option);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
onMouseEnter: () => setHighlightedIndex(index),
|
|
222
|
+
className: cn(
|
|
223
|
+
'focus:text-default [&_svg:not([class*="text-"])]:text-subdued focus:bg-hover relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-left text-xs outline-hidden transition-colors select-none',
|
|
224
|
+
"hover:bg-hover",
|
|
225
|
+
highlightedIndex === index && "bg-hover",
|
|
226
|
+
selected && "bg-hover",
|
|
227
|
+
option.disabled && "pointer-events-none opacity-50"
|
|
228
|
+
),
|
|
229
|
+
children: [
|
|
230
|
+
option.label,
|
|
231
|
+
isDuplicateLabel && /* @__PURE__ */ jsx("span", { className: "text-subdued text-[10px]", children: option.value }),
|
|
232
|
+
selected && /* @__PURE__ */ jsx(Check, { className: "absolute top-1/2 right-2 h-4 w-4 -translate-y-1/2" })
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
`${option.value}-${index}`
|
|
236
|
+
);
|
|
237
|
+
}) }) })
|
|
238
|
+
}
|
|
239
|
+
) })
|
|
240
|
+
] });
|
|
241
|
+
};
|
|
242
|
+
export {
|
|
243
|
+
Suggestions
|
|
244
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
3
|
+
import { Tooltip } from "../Tooltip/Tooltip.js";
|
|
4
|
+
import { cn } from "../../lib/cn.js";
|
|
5
|
+
import { cva } from "class-variance-authority";
|
|
6
|
+
const switchVariants = cva(
|
|
7
|
+
"peer data-[state=checked]:bg-success data-[state=unchecked]:bg-comet focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 disabled:bg-gray-chateau inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-20",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
size: {
|
|
11
|
+
s: "h-3.5 w-6",
|
|
12
|
+
m: "h-[1.15rem] w-8",
|
|
13
|
+
l: "h-6 w-11",
|
|
14
|
+
xl: "h-7 w-14"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
defaultVariants: {
|
|
18
|
+
size: "m"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
const switchThumbVariants = cva(
|
|
23
|
+
"bg-primary data-[state=unchecked]:bg-primary data-[state=checked]:bg-primary pointer-events-none block rounded-full ring-0 transition-transform data-[state=unchecked]:translate-x-0 disabled:bg-border",
|
|
24
|
+
{
|
|
25
|
+
variants: {
|
|
26
|
+
size: {
|
|
27
|
+
s: "size-3 data-[state=checked]:translate-x-[calc(100%-2px)]",
|
|
28
|
+
m: "size-4 data-[state=checked]:translate-x-[calc(100%-2px)]",
|
|
29
|
+
l: "size-5 data-[state=checked]:translate-x-[110%]",
|
|
30
|
+
xl: "size-6 data-[state=checked]:translate-x-[125%]"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
defaultVariants: {
|
|
34
|
+
size: "m"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
const Switch = ({
|
|
39
|
+
className,
|
|
40
|
+
thumbClassName,
|
|
41
|
+
tooltip,
|
|
42
|
+
size,
|
|
43
|
+
...props
|
|
44
|
+
}) => {
|
|
45
|
+
const element = /* @__PURE__ */ jsx(
|
|
46
|
+
SwitchPrimitive.Root,
|
|
47
|
+
{
|
|
48
|
+
"data-slot": "switch",
|
|
49
|
+
className: cn(switchVariants({ size }), className),
|
|
50
|
+
...props,
|
|
51
|
+
children: /* @__PURE__ */ jsx(
|
|
52
|
+
SwitchPrimitive.Thumb,
|
|
53
|
+
{
|
|
54
|
+
"data-slot": "switch-thumb",
|
|
55
|
+
className: cn(switchThumbVariants({ size }), thumbClassName)
|
|
56
|
+
}
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
return tooltip ? /* @__PURE__ */ jsx(Tooltip, { content: tooltip, children: element }) : element;
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
Switch
|
|
64
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { RefreshCw } from "lucide-react";
|
|
3
|
+
const SyncProcessBar = () => {
|
|
4
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-border bg-secondary overflow-hidden rounded-lg border", children: [
|
|
5
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 px-4 py-3", children: [
|
|
6
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "text-success size-4 animate-spin" }),
|
|
7
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-chateau text-xs", children: "Synchronization In Progress" })
|
|
8
|
+
] }),
|
|
9
|
+
/* @__PURE__ */ jsx("div", { className: "bg-primary relative h-1 overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "animate-progress from-success/0 via-success to-success/0 absolute top-0 left-0 h-full w-2/5 bg-gradient-to-r" }) })
|
|
10
|
+
] });
|
|
11
|
+
};
|
|
12
|
+
export {
|
|
13
|
+
SyncProcessBar
|
|
14
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from "../Badge/Badge.js";
|
|
3
|
+
import { ChevronDown, ChevronRight } from "lucide-react";
|
|
4
|
+
import { TableCell, TableRow } from "./Table.js";
|
|
5
|
+
const GroupHeaderRow = ({
|
|
6
|
+
colSpan,
|
|
7
|
+
label,
|
|
8
|
+
count,
|
|
9
|
+
isExpanded,
|
|
10
|
+
onToggle
|
|
11
|
+
}) => {
|
|
12
|
+
return /* @__PURE__ */ jsx(
|
|
13
|
+
TableRow,
|
|
14
|
+
{
|
|
15
|
+
className: "bg-secondary hover:bg-secondary/50 border-border cursor-pointer border-b transition-colors",
|
|
16
|
+
onClick: onToggle,
|
|
17
|
+
children: /* @__PURE__ */ jsx(TableCell, { colSpan, className: "px-6 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 font-medium", children: [
|
|
18
|
+
isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "text-gray-chateau h-4 w-4" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "text-gray-chateau h-4 w-4" }),
|
|
19
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
20
|
+
/* @__PURE__ */ jsx("span", { className: "text-default text-s", children: label || "Unknown" }),
|
|
21
|
+
/* @__PURE__ */ jsx(
|
|
22
|
+
Badge,
|
|
23
|
+
{
|
|
24
|
+
variant: "secondary",
|
|
25
|
+
className: "text-2xs text-gray-chateau bg-border/50 rounded-full",
|
|
26
|
+
children: count
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
] })
|
|
30
|
+
] }) })
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
export {
|
|
35
|
+
GroupHeaderRow
|
|
36
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GroupHeaderRow } from "./GroupHeaderRow.js";
|
|
3
|
+
const RowGrouped = ({ row, table }) => {
|
|
4
|
+
const groupValue = row.getVisibleCells()[0]?.getValue();
|
|
5
|
+
const label = groupValue != null && groupValue !== "" ? String(groupValue) : "Unknown";
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
GroupHeaderRow,
|
|
8
|
+
{
|
|
9
|
+
colSpan: row.getVisibleCells().length - table.getState().grouping.length,
|
|
10
|
+
label,
|
|
11
|
+
count: row.subRows.length,
|
|
12
|
+
isExpanded: row.getIsExpanded(),
|
|
13
|
+
onToggle: row.getToggleExpandedHandler()
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
RowGrouped
|
|
19
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { EmptyState } from "../EmptyState/EmptyState.js";
|
|
4
|
+
import { flexRender } from "@tanstack/react-table";
|
|
5
|
+
import { DatabaseIcon } from "lucide-react";
|
|
6
|
+
import { motion } from "motion/react";
|
|
7
|
+
import { Fragment } from "react";
|
|
8
|
+
import { getColumnStyle } from "./columnStyle.js";
|
|
9
|
+
import { GroupHeaderRow } from "./GroupHeaderRow.js";
|
|
10
|
+
import { TableBody, TableCell, TableRow } from "./Table.js";
|
|
11
|
+
const resolveRowId = (table, item, index) => {
|
|
12
|
+
const getRowId = table.options.getRowId;
|
|
13
|
+
if (typeof getRowId === "function") {
|
|
14
|
+
return getRowId(item, index, void 0);
|
|
15
|
+
}
|
|
16
|
+
return String(index);
|
|
17
|
+
};
|
|
18
|
+
const ServerGroupedTableBody = ({
|
|
19
|
+
groups,
|
|
20
|
+
expandedGroups,
|
|
21
|
+
onToggleGroup,
|
|
22
|
+
table,
|
|
23
|
+
columnsCount,
|
|
24
|
+
classNameCell
|
|
25
|
+
}) => {
|
|
26
|
+
if (!groups.length) {
|
|
27
|
+
return /* @__PURE__ */ jsx(TableBody, { children: /* @__PURE__ */ jsx(TableRow, { className: "hover:bg-transparent", children: /* @__PURE__ */ jsx(TableCell, { colSpan: columnsCount, className: "h-24 text-center", children: /* @__PURE__ */ jsx(
|
|
28
|
+
EmptyState,
|
|
29
|
+
{
|
|
30
|
+
Icon: DatabaseIcon,
|
|
31
|
+
title: "No data",
|
|
32
|
+
description: "Results will be displayed here after you add some data"
|
|
33
|
+
}
|
|
34
|
+
) }) }) });
|
|
35
|
+
}
|
|
36
|
+
return /* @__PURE__ */ jsx(TableBody, { children: groups.map(([groupKey, items], groupIndex) => {
|
|
37
|
+
const isExpanded = expandedGroups[groupKey] ?? false;
|
|
38
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
39
|
+
/* @__PURE__ */ jsx(
|
|
40
|
+
GroupHeaderRow,
|
|
41
|
+
{
|
|
42
|
+
colSpan: columnsCount,
|
|
43
|
+
label: groupKey,
|
|
44
|
+
count: items.length,
|
|
45
|
+
isExpanded,
|
|
46
|
+
onToggle: () => onToggleGroup(groupKey)
|
|
47
|
+
}
|
|
48
|
+
),
|
|
49
|
+
isExpanded && items.map((item, itemIndex) => {
|
|
50
|
+
const rowId = resolveRowId(table, item, itemIndex);
|
|
51
|
+
const row = table.getRow(rowId);
|
|
52
|
+
if (!row) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const rowAnimationIndex = groupIndex + itemIndex;
|
|
56
|
+
return /* @__PURE__ */ jsx(
|
|
57
|
+
motion.tr,
|
|
58
|
+
{
|
|
59
|
+
className: cn("hover:bg-hover/20 border-border border-b transition-colors"),
|
|
60
|
+
initial: { opacity: 0, x: -50 },
|
|
61
|
+
animate: { opacity: 1, x: 0 },
|
|
62
|
+
exit: { opacity: 0, x: -50 },
|
|
63
|
+
transition: {
|
|
64
|
+
duration: 0.3,
|
|
65
|
+
delay: rowAnimationIndex * 0.05,
|
|
66
|
+
ease: [0.16, 1, 0.3, 1]
|
|
67
|
+
},
|
|
68
|
+
children: row.getVisibleCells().map((cell) => {
|
|
69
|
+
const columnStyle = getColumnStyle(cell.column.columnDef.meta);
|
|
70
|
+
return /* @__PURE__ */ jsx(
|
|
71
|
+
TableCell,
|
|
72
|
+
{
|
|
73
|
+
className: cn("px-6 py-4", classNameCell),
|
|
74
|
+
style: columnStyle,
|
|
75
|
+
children: flexRender(cell.column.columnDef.cell, cell.getContext())
|
|
76
|
+
},
|
|
77
|
+
cell.id
|
|
78
|
+
);
|
|
79
|
+
})
|
|
80
|
+
},
|
|
81
|
+
row.id
|
|
82
|
+
);
|
|
83
|
+
})
|
|
84
|
+
] }, groupKey);
|
|
85
|
+
}) });
|
|
86
|
+
};
|
|
87
|
+
export {
|
|
88
|
+
ServerGroupedTableBody
|
|
89
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
4
|
+
const SortableHeader = ({
|
|
5
|
+
header,
|
|
6
|
+
isSortingEnabled
|
|
7
|
+
}) => {
|
|
8
|
+
const canSort = header.column.getCanSort();
|
|
9
|
+
const isSorted = header.column.getIsSorted();
|
|
10
|
+
const sortDirection = isSorted === "asc" ? "asc" : isSorted === "desc" ? "desc" : null;
|
|
11
|
+
if (!canSort || !isSortingEnabled) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return /* @__PURE__ */ jsxs(
|
|
15
|
+
"span",
|
|
16
|
+
{
|
|
17
|
+
className: cn(
|
|
18
|
+
"flex flex-col",
|
|
19
|
+
!isSorted && "opacity-0 transition-opacity group-hover:opacity-100"
|
|
20
|
+
),
|
|
21
|
+
children: [
|
|
22
|
+
/* @__PURE__ */ jsx(
|
|
23
|
+
ChevronUpIcon,
|
|
24
|
+
{
|
|
25
|
+
className: cn(
|
|
26
|
+
"size-3",
|
|
27
|
+
sortDirection === "asc" ? "text-success" : "text-subdued opacity-30"
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ jsx(
|
|
32
|
+
ChevronDownIcon,
|
|
33
|
+
{
|
|
34
|
+
className: cn(
|
|
35
|
+
"-mt-1 size-3",
|
|
36
|
+
sortDirection === "desc" ? "text-success" : "text-subdued opacity-30"
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
export {
|
|
45
|
+
SortableHeader
|
|
46
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../lib/cn.js";
|
|
3
|
+
import { ScrollArea } from "../ScrollArea/ScrollArea.js";
|
|
4
|
+
const Table = ({
|
|
5
|
+
className,
|
|
6
|
+
classNameTable,
|
|
7
|
+
orientation = "both",
|
|
8
|
+
classNameScrollArea,
|
|
9
|
+
...props
|
|
10
|
+
}) => {
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
"div",
|
|
13
|
+
{
|
|
14
|
+
className: cn("border-border bg-primary flex overflow-hidden rounded-md border", className),
|
|
15
|
+
children: /* @__PURE__ */ jsx(ScrollArea, { className: cn("w-1 flex-1", classNameScrollArea), orientation, children: /* @__PURE__ */ jsx(
|
|
16
|
+
"table",
|
|
17
|
+
{
|
|
18
|
+
"data-slot": "table",
|
|
19
|
+
className: cn("w-full caption-bottom", classNameTable),
|
|
20
|
+
...props
|
|
21
|
+
}
|
|
22
|
+
) })
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
const TableHeader = ({ className, ...props }) => {
|
|
27
|
+
return /* @__PURE__ */ jsx("thead", { "data-slot": "table-header", className: cn("[&_tr]:border-b", className), ...props });
|
|
28
|
+
};
|
|
29
|
+
const TableBody = ({ className, ...props }) => {
|
|
30
|
+
return /* @__PURE__ */ jsx(
|
|
31
|
+
"tbody",
|
|
32
|
+
{
|
|
33
|
+
"data-slot": "table-body",
|
|
34
|
+
className: cn("[&_tr:last-child]:border-0", className),
|
|
35
|
+
...props
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
const TableFooter = ({ className, ...props }) => {
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
41
|
+
"tfoot",
|
|
42
|
+
{
|
|
43
|
+
"data-slot": "table-footer",
|
|
44
|
+
className: cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className),
|
|
45
|
+
...props
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
const TableRow = ({ className, ...props }) => {
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
"tr",
|
|
52
|
+
{
|
|
53
|
+
"data-slot": "table-row",
|
|
54
|
+
className: cn(
|
|
55
|
+
"hover:bg-hover/20 data-[state=selected]:bg-secondary/80 border-border border-b transition-colors",
|
|
56
|
+
className
|
|
57
|
+
),
|
|
58
|
+
...props
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
const TableHead = ({ className, ...props }) => {
|
|
63
|
+
return /* @__PURE__ */ jsx(
|
|
64
|
+
"th",
|
|
65
|
+
{
|
|
66
|
+
"data-slot": "table-head",
|
|
67
|
+
className: cn(
|
|
68
|
+
"text-subdued text-2xs px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
69
|
+
className
|
|
70
|
+
),
|
|
71
|
+
...props
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
const TableCell = ({ className, ...props }) => {
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
"td",
|
|
78
|
+
{
|
|
79
|
+
"data-slot": "table-cell",
|
|
80
|
+
className: cn(
|
|
81
|
+
"p-2 align-middle [&:has([role=checkbox])]:pr-2 [&>[role=checkbox]]:translate-y-[2px]",
|
|
82
|
+
className
|
|
83
|
+
),
|
|
84
|
+
...props
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
const TableCaption = ({
|
|
89
|
+
className,
|
|
90
|
+
...props
|
|
91
|
+
}) => {
|
|
92
|
+
return /* @__PURE__ */ jsx(
|
|
93
|
+
"caption",
|
|
94
|
+
{
|
|
95
|
+
"data-slot": "table-caption",
|
|
96
|
+
className: cn("text-muted-foreground mt-4 text-sm", className),
|
|
97
|
+
...props
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
export {
|
|
102
|
+
Table,
|
|
103
|
+
TableBody,
|
|
104
|
+
TableCaption,
|
|
105
|
+
TableCell,
|
|
106
|
+
TableFooter,
|
|
107
|
+
TableHead,
|
|
108
|
+
TableHeader,
|
|
109
|
+
TableRow
|
|
110
|
+
};
|