@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.
Files changed (153) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/LICENSE +21 -0
  3. package/README.md +537 -0
  4. package/attack-flow.d.ts +16 -0
  5. package/charts.d.ts +32 -0
  6. package/decorators/index.js +8 -0
  7. package/decorators/withRouter.js +10 -0
  8. package/decorators/withTheme.js +10 -0
  9. package/decorators.d.ts +10 -0
  10. package/domain.d.ts +23 -0
  11. package/editor.d.ts +25 -0
  12. package/index.d.ts +702 -0
  13. package/lib/cn.js +8 -0
  14. package/lib/theme.js +26 -0
  15. package/lib/useFullscreen.js +52 -0
  16. package/lib/useListenOnResizeDebounce.js +22 -0
  17. package/lib/useThemeColors.js +39 -0
  18. package/package.json +113 -0
  19. package/preset/createConfig.js +98 -0
  20. package/preset/createPreview.js +53 -0
  21. package/preset/index.js +6 -0
  22. package/preset/restoreNativeFocus.js +33 -0
  23. package/preset/types.js +0 -0
  24. package/preset.d.ts +27 -0
  25. package/theme-9m7j1UoI.d.ts +5 -0
  26. package/ui/Accordion/Accordion.js +82 -0
  27. package/ui/Accordion/AccordionSection.js +41 -0
  28. package/ui/Accordion/FolderTreeExpandTrigger.js +29 -0
  29. package/ui/Accordion/chevronVariants.js +31 -0
  30. package/ui/Accordion/index.js +16 -0
  31. package/ui/AnimatedDots/AnimatedDots.js +10 -0
  32. package/ui/AnimatedDots/index.js +4 -0
  33. package/ui/Aside/Aside.js +34 -0
  34. package/ui/Aside/index.js +4 -0
  35. package/ui/AttackFlow/AttackFlow.js +9 -0
  36. package/ui/AttackFlow/AttackFlowLayout.js +63 -0
  37. package/ui/AttackFlow/Controls.js +42 -0
  38. package/ui/AttackFlow/Node.js +47 -0
  39. package/ui/AttackFlow/OtherNode.js +44 -0
  40. package/ui/AttackFlow/index.js +4 -0
  41. package/ui/AttackFlow/prependData.js +153 -0
  42. package/ui/AttackFlow/types.js +0 -0
  43. package/ui/AttackFlow/useAttackFlow.js +193 -0
  44. package/ui/Badge/Badge.js +57 -0
  45. package/ui/Badge/index.js +5 -0
  46. package/ui/Button/Button.css +1 -0
  47. package/ui/Button/Button.js +109 -0
  48. package/ui/Button/index.js +5 -0
  49. package/ui/Charts/AreaChartWithGradient.js +79 -0
  50. package/ui/Charts/index.js +4 -0
  51. package/ui/Checkbox/Checkbox.js +31 -0
  52. package/ui/Checkbox/index.js +4 -0
  53. package/ui/ConditionalContent/ConditionalContent.js +10 -0
  54. package/ui/ConditionalContent/index.js +4 -0
  55. package/ui/CorrelationTimer/CorrelationTimer.js +62 -0
  56. package/ui/CorrelationTimer/index.js +4 -0
  57. package/ui/DeleteButtonConfirm/DeleteButtonConfirm.js +65 -0
  58. package/ui/DeleteButtonConfirm/index.js +4 -0
  59. package/ui/Dialog/ConfirmDialog.js +54 -0
  60. package/ui/Dialog/DefaultDialog.js +82 -0
  61. package/ui/Dialog/Dialog.js +120 -0
  62. package/ui/Dialog/index.js +32 -0
  63. package/ui/Dropdown/Dropdown.js +204 -0
  64. package/ui/Dropdown/DropdownsCheckbox.js +102 -0
  65. package/ui/Dropdown/DropdownsSelect.js +97 -0
  66. package/ui/Dropdown/index.js +38 -0
  67. package/ui/Editor/Editor.js +97 -0
  68. package/ui/Editor/index.js +4 -0
  69. package/ui/Editor/monacoSetup.js +38 -0
  70. package/ui/Editor/theme.js +50 -0
  71. package/ui/Editor/types.js +0 -0
  72. package/ui/EmptyState/EmptyState.js +26 -0
  73. package/ui/EmptyState/index.js +4 -0
  74. package/ui/Field/Field.js +204 -0
  75. package/ui/Field/index.js +24 -0
  76. package/ui/HelperText/HelperText.js +7 -0
  77. package/ui/HelperText/index.js +4 -0
  78. package/ui/Input/Input.js +40 -0
  79. package/ui/Input/index.js +4 -0
  80. package/ui/InputNumber/InputNumber.js +90 -0
  81. package/ui/InputNumber/index.js +4 -0
  82. package/ui/InputPassword/InputPassword.js +30 -0
  83. package/ui/InputPassword/index.js +4 -0
  84. package/ui/Label/Label.js +13 -0
  85. package/ui/Label/LabelInfo.js +14 -0
  86. package/ui/Label/index.js +6 -0
  87. package/ui/MultiSelect/MultiSelect.js +163 -0
  88. package/ui/MultiSelect/index.js +4 -0
  89. package/ui/PageHeader/PageHeader.js +51 -0
  90. package/ui/PageHeader/index.js +4 -0
  91. package/ui/Pagination/Pagination.js +97 -0
  92. package/ui/Pagination/PaginationWrap.js +149 -0
  93. package/ui/Pagination/index.js +20 -0
  94. package/ui/RadioGroup/RadioGroup.js +45 -0
  95. package/ui/RadioGroup/index.js +5 -0
  96. package/ui/ScrollArea/ScrollArea.js +57 -0
  97. package/ui/ScrollArea/index.js +5 -0
  98. package/ui/SearchInput/SearchInput.js +38 -0
  99. package/ui/SearchInput/index.js +4 -0
  100. package/ui/SearchInputFields/SearchInputFields.js +53 -0
  101. package/ui/SearchInputFields/index.js +4 -0
  102. package/ui/Select/Select.js +155 -0
  103. package/ui/Select/SelectDefault.js +43 -0
  104. package/ui/Select/index.js +26 -0
  105. package/ui/Separator/Separator.js +26 -0
  106. package/ui/Separator/index.js +4 -0
  107. package/ui/Severity/Severity.js +11 -0
  108. package/ui/Severity/index.js +4 -0
  109. package/ui/Severity/utils.js +53 -0
  110. package/ui/Skeleton/Skeleton.js +25 -0
  111. package/ui/Skeleton/index.js +5 -0
  112. package/ui/Slider/Slider.js +50 -0
  113. package/ui/Slider/index.js +4 -0
  114. package/ui/Spinner/Spinner.js +21 -0
  115. package/ui/Spinner/index.js +5 -0
  116. package/ui/SpinnerSquare/SpinnerSquare.css +1 -0
  117. package/ui/SpinnerSquare/SpinnerSquare.js +22 -0
  118. package/ui/SpinnerSquare/index.js +4 -0
  119. package/ui/StatisticCard/StatisticCard.js +27 -0
  120. package/ui/StatisticCard/index.js +4 -0
  121. package/ui/StatisticCard/types.js +0 -0
  122. package/ui/Suggestions/Suggestions.js +244 -0
  123. package/ui/Suggestions/index.js +4 -0
  124. package/ui/Switch/Switch.js +64 -0
  125. package/ui/Switch/index.js +4 -0
  126. package/ui/SyncProcessBar/SyncProcessBar.js +14 -0
  127. package/ui/SyncProcessBar/index.js +4 -0
  128. package/ui/Table/GroupHeaderRow.js +36 -0
  129. package/ui/Table/RowGrouped.js +19 -0
  130. package/ui/Table/ServerGroupedTableBody.js +89 -0
  131. package/ui/Table/SortableHeader.js +46 -0
  132. package/ui/Table/Table.js +110 -0
  133. package/ui/Table/TableWrap.js +124 -0
  134. package/ui/Table/columnStyle.js +14 -0
  135. package/ui/Table/index.js +28 -0
  136. package/ui/Tabs/Tabs.js +76 -0
  137. package/ui/Tabs/index.js +4 -0
  138. package/ui/TextTruncate/TextTruncate.js +107 -0
  139. package/ui/TextTruncate/index.js +4 -0
  140. package/ui/Textarea/Textarea.js +20 -0
  141. package/ui/Textarea/index.js +4 -0
  142. package/ui/ThemeToggle/ThemeToggle.js +23 -0
  143. package/ui/ThemeToggle/index.js +4 -0
  144. package/ui/Toast/Toast.js +23 -0
  145. package/ui/Toast/index.js +4 -0
  146. package/ui/Tooltip/Tooltip.js +17 -0
  147. package/ui/Tooltip/TooltipLayout.js +60 -0
  148. package/ui/Tooltip/index.js +14 -0
  149. package/ui/TreeGuide/TreeGuide.js +23 -0
  150. package/ui/TreeGuide/index.js +5 -0
  151. package/ui/entries/charts.js +2 -0
  152. package/ui/entries/domain.js +3 -0
  153. 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,4 @@
1
+ import { Suggestions } from "./Suggestions.js";
2
+ export {
3
+ Suggestions
4
+ };
@@ -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,4 @@
1
+ import { Switch } from "./Switch.js";
2
+ export {
3
+ Switch
4
+ };
@@ -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,4 @@
1
+ import { SyncProcessBar as SyncProcessBar2 } from "./SyncProcessBar.js";
2
+ export {
3
+ SyncProcessBar2 as SyncProcessBar
4
+ };
@@ -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
+ };