@aiready/components 0.1.0
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/README.md +240 -0
- package/dist/charts/ForceDirectedGraph.d.ts +40 -0
- package/dist/charts/ForceDirectedGraph.js +294 -0
- package/dist/charts/ForceDirectedGraph.js.map +1 -0
- package/dist/components/badge.d.ts +13 -0
- package/dist/components/badge.js +32 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.d.ts +14 -0
- package/dist/components/button.js +52 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.d.ts +10 -0
- package/dist/components/card.js +66 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/checkbox.d.ts +8 -0
- package/dist/components/checkbox.js +42 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/container.d.ts +8 -0
- package/dist/components/container.js +36 -0
- package/dist/components/container.js.map +1 -0
- package/dist/components/grid.d.ts +9 -0
- package/dist/components/grid.js +44 -0
- package/dist/components/grid.js.map +1 -0
- package/dist/components/input.d.ts +7 -0
- package/dist/components/input.js +30 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/label.d.ts +10 -0
- package/dist/components/label.js +28 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/radio-group.d.ts +17 -0
- package/dist/components/radio-group.js +64 -0
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/select.js +45 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +9 -0
- package/dist/components/separator.js +30 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/stack.d.ts +11 -0
- package/dist/components/stack.js +60 -0
- package/dist/components/stack.js.map +1 -0
- package/dist/components/switch.d.ts +9 -0
- package/dist/components/switch.js +49 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/textarea.d.ts +7 -0
- package/dist/components/textarea.js +29 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/hooks/useD3.d.ts +6 -0
- package/dist/hooks/useD3.js +35 -0
- package/dist/hooks/useD3.js.map +1 -0
- package/dist/hooks/useDebounce.d.ts +3 -0
- package/dist/hooks/useDebounce.js +19 -0
- package/dist/hooks/useDebounce.js.map +1 -0
- package/dist/hooks/useForceSimulation.d.ts +39 -0
- package/dist/hooks/useForceSimulation.js +107 -0
- package/dist/hooks/useForceSimulation.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +927 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/cn.d.ts +5 -0
- package/dist/utils/cn.js +11 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/colors.d.ts +19 -0
- package/dist/utils/colors.js +52 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/formatters.d.ts +13 -0
- package/dist/utils/formatters.js +100 -0
- package/dist/utils/formatters.js.map +1 -0
- package/package.json +83 -0
- package/src/charts/ForceDirectedGraph.tsx +356 -0
- package/src/components/badge.tsx +35 -0
- package/src/components/button.tsx +53 -0
- package/src/components/card.tsx +78 -0
- package/src/components/checkbox.tsx +39 -0
- package/src/components/container.tsx +31 -0
- package/src/components/grid.tsx +40 -0
- package/src/components/input.tsx +24 -0
- package/src/components/label.tsx +24 -0
- package/src/components/radio-group.tsx +71 -0
- package/src/components/select.tsx +53 -0
- package/src/components/separator.tsx +29 -0
- package/src/components/stack.tsx +61 -0
- package/src/components/switch.tsx +49 -0
- package/src/components/textarea.tsx +23 -0
- package/src/hooks/useD3.ts +125 -0
- package/src/hooks/useDebounce.ts +44 -0
- package/src/hooks/useForceSimulation.ts +328 -0
- package/src/index.ts +51 -0
- package/src/utils/cn.ts +11 -0
- package/src/utils/colors.ts +58 -0
- package/src/utils/formatters.ts +161 -0
- package/tailwind.config.js +46 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,927 @@
|
|
|
1
|
+
import * as React2 from 'react';
|
|
2
|
+
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
|
+
import { twMerge } from 'tailwind-merge';
|
|
6
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
+
import * as d32 from 'd3';
|
|
8
|
+
|
|
9
|
+
// src/components/button.tsx
|
|
10
|
+
function cn(...inputs) {
|
|
11
|
+
return twMerge(clsx(inputs));
|
|
12
|
+
}
|
|
13
|
+
var buttonVariants = cva(
|
|
14
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
|
15
|
+
{
|
|
16
|
+
variants: {
|
|
17
|
+
variant: {
|
|
18
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
19
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
20
|
+
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
21
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
22
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
23
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
24
|
+
},
|
|
25
|
+
size: {
|
|
26
|
+
default: "h-10 px-4 py-2",
|
|
27
|
+
sm: "h-9 rounded-md px-3",
|
|
28
|
+
lg: "h-11 rounded-md px-8",
|
|
29
|
+
icon: "h-10 w-10"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: {
|
|
33
|
+
variant: "default",
|
|
34
|
+
size: "default"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
var Button = React2.forwardRef(
|
|
39
|
+
({ className, variant, size, ...props }, ref) => {
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
44
|
+
ref,
|
|
45
|
+
...props
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
Button.displayName = "Button";
|
|
51
|
+
var Card = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
ref,
|
|
55
|
+
className: cn(
|
|
56
|
+
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
|
57
|
+
className
|
|
58
|
+
),
|
|
59
|
+
...props
|
|
60
|
+
}
|
|
61
|
+
));
|
|
62
|
+
Card.displayName = "Card";
|
|
63
|
+
var CardHeader = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
64
|
+
"div",
|
|
65
|
+
{
|
|
66
|
+
ref,
|
|
67
|
+
className: cn("flex flex-col space-y-1.5 p-6", className),
|
|
68
|
+
...props
|
|
69
|
+
}
|
|
70
|
+
));
|
|
71
|
+
CardHeader.displayName = "CardHeader";
|
|
72
|
+
var CardTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
73
|
+
"h3",
|
|
74
|
+
{
|
|
75
|
+
ref,
|
|
76
|
+
className: cn(
|
|
77
|
+
"text-2xl font-semibold leading-none tracking-tight",
|
|
78
|
+
className
|
|
79
|
+
),
|
|
80
|
+
...props
|
|
81
|
+
}
|
|
82
|
+
));
|
|
83
|
+
CardTitle.displayName = "CardTitle";
|
|
84
|
+
var CardDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
85
|
+
"p",
|
|
86
|
+
{
|
|
87
|
+
ref,
|
|
88
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
89
|
+
...props
|
|
90
|
+
}
|
|
91
|
+
));
|
|
92
|
+
CardDescription.displayName = "CardDescription";
|
|
93
|
+
var CardContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
|
|
94
|
+
CardContent.displayName = "CardContent";
|
|
95
|
+
var CardFooter = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
96
|
+
"div",
|
|
97
|
+
{
|
|
98
|
+
ref,
|
|
99
|
+
className: cn("flex items-center p-6 pt-0", className),
|
|
100
|
+
...props
|
|
101
|
+
}
|
|
102
|
+
));
|
|
103
|
+
CardFooter.displayName = "CardFooter";
|
|
104
|
+
var Input = React2.forwardRef(
|
|
105
|
+
({ className, type, ...props }, ref) => {
|
|
106
|
+
return /* @__PURE__ */ jsx(
|
|
107
|
+
"input",
|
|
108
|
+
{
|
|
109
|
+
type,
|
|
110
|
+
className: cn(
|
|
111
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
112
|
+
className
|
|
113
|
+
),
|
|
114
|
+
ref,
|
|
115
|
+
...props
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
);
|
|
120
|
+
Input.displayName = "Input";
|
|
121
|
+
var labelVariants = cva(
|
|
122
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
123
|
+
);
|
|
124
|
+
var Label = React2.forwardRef(
|
|
125
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
126
|
+
"label",
|
|
127
|
+
{
|
|
128
|
+
ref,
|
|
129
|
+
className: cn(labelVariants(), className),
|
|
130
|
+
...props
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
Label.displayName = "Label";
|
|
135
|
+
var badgeVariants = cva(
|
|
136
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
137
|
+
{
|
|
138
|
+
variants: {
|
|
139
|
+
variant: {
|
|
140
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
141
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
142
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
143
|
+
outline: "text-foreground"
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
defaultVariants: {
|
|
147
|
+
variant: "default"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
function Badge({ className, variant, ...props }) {
|
|
152
|
+
return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
153
|
+
}
|
|
154
|
+
var Container = React2.forwardRef(
|
|
155
|
+
({ className, size = "lg", ...props }, ref) => {
|
|
156
|
+
return /* @__PURE__ */ jsx(
|
|
157
|
+
"div",
|
|
158
|
+
{
|
|
159
|
+
ref,
|
|
160
|
+
className: cn(
|
|
161
|
+
"mx-auto w-full px-4 sm:px-6 lg:px-8",
|
|
162
|
+
{
|
|
163
|
+
"max-w-screen-sm": size === "sm",
|
|
164
|
+
"max-w-screen-md": size === "md",
|
|
165
|
+
"max-w-screen-lg": size === "lg",
|
|
166
|
+
"max-w-screen-xl": size === "xl",
|
|
167
|
+
"max-w-full": size === "full"
|
|
168
|
+
},
|
|
169
|
+
className
|
|
170
|
+
),
|
|
171
|
+
...props
|
|
172
|
+
}
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
);
|
|
176
|
+
Container.displayName = "Container";
|
|
177
|
+
var Grid = React2.forwardRef(
|
|
178
|
+
({ className, cols = 3, gap = "md", ...props }, ref) => {
|
|
179
|
+
return /* @__PURE__ */ jsx(
|
|
180
|
+
"div",
|
|
181
|
+
{
|
|
182
|
+
ref,
|
|
183
|
+
className: cn(
|
|
184
|
+
"grid",
|
|
185
|
+
{
|
|
186
|
+
"grid-cols-1": cols === 1,
|
|
187
|
+
"grid-cols-1 sm:grid-cols-2": cols === 2,
|
|
188
|
+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-3": cols === 3,
|
|
189
|
+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-4": cols === 4,
|
|
190
|
+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-5": cols === 5,
|
|
191
|
+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-6": cols === 6,
|
|
192
|
+
"grid-cols-1 sm:grid-cols-2 lg:grid-cols-12": cols === 12
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"gap-2": gap === "sm",
|
|
196
|
+
"gap-4": gap === "md",
|
|
197
|
+
"gap-6": gap === "lg",
|
|
198
|
+
"gap-8": gap === "xl"
|
|
199
|
+
},
|
|
200
|
+
className
|
|
201
|
+
),
|
|
202
|
+
...props
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
Grid.displayName = "Grid";
|
|
208
|
+
var Stack = React2.forwardRef(
|
|
209
|
+
({
|
|
210
|
+
className,
|
|
211
|
+
direction = "vertical",
|
|
212
|
+
spacing = "md",
|
|
213
|
+
align = "stretch",
|
|
214
|
+
justify = "start",
|
|
215
|
+
...props
|
|
216
|
+
}, ref) => {
|
|
217
|
+
return /* @__PURE__ */ jsx(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
ref,
|
|
221
|
+
className: cn(
|
|
222
|
+
"flex",
|
|
223
|
+
{
|
|
224
|
+
"flex-col": direction === "vertical",
|
|
225
|
+
"flex-row": direction === "horizontal"
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"gap-1": spacing === "xs",
|
|
229
|
+
"gap-2": spacing === "sm",
|
|
230
|
+
"gap-4": spacing === "md",
|
|
231
|
+
"gap-6": spacing === "lg",
|
|
232
|
+
"gap-8": spacing === "xl"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"items-start": align === "start",
|
|
236
|
+
"items-center": align === "center",
|
|
237
|
+
"items-end": align === "end",
|
|
238
|
+
"items-stretch": align === "stretch"
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"justify-start": justify === "start",
|
|
242
|
+
"justify-center": justify === "center",
|
|
243
|
+
"justify-end": justify === "end",
|
|
244
|
+
"justify-between": justify === "between",
|
|
245
|
+
"justify-around": justify === "around"
|
|
246
|
+
},
|
|
247
|
+
className
|
|
248
|
+
),
|
|
249
|
+
...props
|
|
250
|
+
}
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
);
|
|
254
|
+
Stack.displayName = "Stack";
|
|
255
|
+
var Separator = React2.forwardRef(
|
|
256
|
+
({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
257
|
+
"div",
|
|
258
|
+
{
|
|
259
|
+
ref,
|
|
260
|
+
role: decorative ? "none" : "separator",
|
|
261
|
+
"aria-orientation": orientation,
|
|
262
|
+
className: cn(
|
|
263
|
+
"shrink-0 bg-border",
|
|
264
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
265
|
+
className
|
|
266
|
+
),
|
|
267
|
+
...props
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
);
|
|
271
|
+
Separator.displayName = "Separator";
|
|
272
|
+
var Checkbox = React2.forwardRef(
|
|
273
|
+
({ className, label, id, ...props }, ref) => {
|
|
274
|
+
const checkboxId = id || React2.useId();
|
|
275
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
276
|
+
/* @__PURE__ */ jsx(
|
|
277
|
+
"input",
|
|
278
|
+
{
|
|
279
|
+
type: "checkbox",
|
|
280
|
+
id: checkboxId,
|
|
281
|
+
ref,
|
|
282
|
+
className: cn(
|
|
283
|
+
"h-4 w-4 rounded border-gray-300 text-primary focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
284
|
+
className
|
|
285
|
+
),
|
|
286
|
+
...props
|
|
287
|
+
}
|
|
288
|
+
),
|
|
289
|
+
label && /* @__PURE__ */ jsx(
|
|
290
|
+
"label",
|
|
291
|
+
{
|
|
292
|
+
htmlFor: checkboxId,
|
|
293
|
+
className: "ml-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
294
|
+
children: label
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
] });
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
Checkbox.displayName = "Checkbox";
|
|
301
|
+
var RadioGroup = React2.forwardRef(
|
|
302
|
+
({
|
|
303
|
+
className,
|
|
304
|
+
options,
|
|
305
|
+
value,
|
|
306
|
+
onChange,
|
|
307
|
+
name,
|
|
308
|
+
orientation = "vertical",
|
|
309
|
+
...props
|
|
310
|
+
}, ref) => {
|
|
311
|
+
return /* @__PURE__ */ jsx(
|
|
312
|
+
"div",
|
|
313
|
+
{
|
|
314
|
+
ref,
|
|
315
|
+
className: cn(
|
|
316
|
+
"flex",
|
|
317
|
+
orientation === "vertical" ? "flex-col gap-2" : "flex-row gap-4",
|
|
318
|
+
className
|
|
319
|
+
),
|
|
320
|
+
...props,
|
|
321
|
+
children: options.map((option) => {
|
|
322
|
+
const id = `${name}-${option.value}`;
|
|
323
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
324
|
+
/* @__PURE__ */ jsx(
|
|
325
|
+
"input",
|
|
326
|
+
{
|
|
327
|
+
type: "radio",
|
|
328
|
+
id,
|
|
329
|
+
name,
|
|
330
|
+
value: option.value,
|
|
331
|
+
checked: value === option.value,
|
|
332
|
+
disabled: option.disabled,
|
|
333
|
+
onChange: (e) => onChange?.(e.target.value),
|
|
334
|
+
className: "h-4 w-4 border-gray-300 text-primary focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
/* @__PURE__ */ jsx(
|
|
338
|
+
"label",
|
|
339
|
+
{
|
|
340
|
+
htmlFor: id,
|
|
341
|
+
className: "ml-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
342
|
+
children: option.label
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
] }, option.value);
|
|
346
|
+
})
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
RadioGroup.displayName = "RadioGroup";
|
|
352
|
+
var Switch = React2.forwardRef(
|
|
353
|
+
({ className, label, id, checked, onCheckedChange, onChange, ...props }, ref) => {
|
|
354
|
+
const switchId = id || React2.useId();
|
|
355
|
+
const handleChange = (e) => {
|
|
356
|
+
onChange?.(e);
|
|
357
|
+
onCheckedChange?.(e.target.checked);
|
|
358
|
+
};
|
|
359
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
360
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: switchId, className: "relative inline-flex cursor-pointer items-center", children: [
|
|
361
|
+
/* @__PURE__ */ jsx(
|
|
362
|
+
"input",
|
|
363
|
+
{
|
|
364
|
+
type: "checkbox",
|
|
365
|
+
id: switchId,
|
|
366
|
+
ref,
|
|
367
|
+
checked,
|
|
368
|
+
onChange: handleChange,
|
|
369
|
+
className: "peer sr-only",
|
|
370
|
+
...props
|
|
371
|
+
}
|
|
372
|
+
),
|
|
373
|
+
/* @__PURE__ */ jsx(
|
|
374
|
+
"div",
|
|
375
|
+
{
|
|
376
|
+
className: cn(
|
|
377
|
+
'peer h-6 w-11 rounded-full bg-gray-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[""] peer-checked:bg-primary peer-checked:after:translate-x-full peer-checked:after:border-white peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-ring peer-focus:ring-offset-2 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
|
|
378
|
+
className
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
)
|
|
382
|
+
] }),
|
|
383
|
+
label && /* @__PURE__ */ jsx("span", { className: "ml-3 text-sm font-medium text-foreground", children: label })
|
|
384
|
+
] });
|
|
385
|
+
}
|
|
386
|
+
);
|
|
387
|
+
Switch.displayName = "Switch";
|
|
388
|
+
var Textarea = React2.forwardRef(
|
|
389
|
+
({ className, ...props }, ref) => {
|
|
390
|
+
return /* @__PURE__ */ jsx(
|
|
391
|
+
"textarea",
|
|
392
|
+
{
|
|
393
|
+
className: cn(
|
|
394
|
+
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
395
|
+
className
|
|
396
|
+
),
|
|
397
|
+
ref,
|
|
398
|
+
...props
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
Textarea.displayName = "Textarea";
|
|
404
|
+
var Select = React2.forwardRef(
|
|
405
|
+
({ className, options, placeholder, onChange, ...props }, ref) => {
|
|
406
|
+
const handleChange = (e) => {
|
|
407
|
+
onChange?.(e.target.value);
|
|
408
|
+
};
|
|
409
|
+
return /* @__PURE__ */ jsxs(
|
|
410
|
+
"select",
|
|
411
|
+
{
|
|
412
|
+
ref,
|
|
413
|
+
className: cn(
|
|
414
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
415
|
+
className
|
|
416
|
+
),
|
|
417
|
+
onChange: handleChange,
|
|
418
|
+
...props,
|
|
419
|
+
children: [
|
|
420
|
+
placeholder && /* @__PURE__ */ jsx("option", { value: "", disabled: true, children: placeholder }),
|
|
421
|
+
options.map((option) => /* @__PURE__ */ jsx(
|
|
422
|
+
"option",
|
|
423
|
+
{
|
|
424
|
+
value: option.value,
|
|
425
|
+
disabled: option.disabled,
|
|
426
|
+
children: option.label
|
|
427
|
+
},
|
|
428
|
+
option.value
|
|
429
|
+
))
|
|
430
|
+
]
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
Select.displayName = "Select";
|
|
436
|
+
|
|
437
|
+
// src/utils/colors.ts
|
|
438
|
+
var severityColors = {
|
|
439
|
+
critical: "#ef4444",
|
|
440
|
+
// red-500
|
|
441
|
+
major: "#f59e0b",
|
|
442
|
+
// amber-500
|
|
443
|
+
minor: "#eab308",
|
|
444
|
+
// yellow-500
|
|
445
|
+
info: "#60a5fa"
|
|
446
|
+
// blue-400
|
|
447
|
+
};
|
|
448
|
+
var domainColors = [
|
|
449
|
+
"#3b82f6",
|
|
450
|
+
// blue-500
|
|
451
|
+
"#8b5cf6",
|
|
452
|
+
// violet-500
|
|
453
|
+
"#ec4899",
|
|
454
|
+
// pink-500
|
|
455
|
+
"#10b981",
|
|
456
|
+
// green-500
|
|
457
|
+
"#f59e0b",
|
|
458
|
+
// amber-500
|
|
459
|
+
"#06b6d4",
|
|
460
|
+
// cyan-500
|
|
461
|
+
"#f97316",
|
|
462
|
+
// orange-500
|
|
463
|
+
"#a855f7"
|
|
464
|
+
// purple-500
|
|
465
|
+
];
|
|
466
|
+
var chartColors = {
|
|
467
|
+
primary: "#3b82f6",
|
|
468
|
+
success: "#10b981",
|
|
469
|
+
warning: "#f59e0b",
|
|
470
|
+
danger: "#ef4444",
|
|
471
|
+
info: "#06b6d4"
|
|
472
|
+
};
|
|
473
|
+
function getDomainColor(index) {
|
|
474
|
+
return domainColors[index % domainColors.length];
|
|
475
|
+
}
|
|
476
|
+
function getSeverityColor(severity) {
|
|
477
|
+
return severityColors[severity];
|
|
478
|
+
}
|
|
479
|
+
function hexToRgba(hex, alpha) {
|
|
480
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
481
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
482
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
483
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// src/utils/formatters.ts
|
|
487
|
+
function formatNumber(value) {
|
|
488
|
+
return new Intl.NumberFormat("en-US").format(value);
|
|
489
|
+
}
|
|
490
|
+
function formatCompactNumber(value) {
|
|
491
|
+
return new Intl.NumberFormat("en-US", {
|
|
492
|
+
notation: "compact",
|
|
493
|
+
maximumFractionDigits: 1
|
|
494
|
+
}).format(value);
|
|
495
|
+
}
|
|
496
|
+
function formatPercentage(value, decimals = 1) {
|
|
497
|
+
return `${(value * 100).toFixed(decimals)}%`;
|
|
498
|
+
}
|
|
499
|
+
function formatFileSize(bytes) {
|
|
500
|
+
const units = ["B", "KB", "MB", "GB", "TB"];
|
|
501
|
+
let size = bytes;
|
|
502
|
+
let unitIndex = 0;
|
|
503
|
+
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
504
|
+
size /= 1024;
|
|
505
|
+
unitIndex++;
|
|
506
|
+
}
|
|
507
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
508
|
+
}
|
|
509
|
+
function formatRelativeTime(date) {
|
|
510
|
+
const now = /* @__PURE__ */ new Date();
|
|
511
|
+
const diffMs = now.getTime() - date.getTime();
|
|
512
|
+
const diffSec = Math.floor(diffMs / 1e3);
|
|
513
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
514
|
+
const diffHour = Math.floor(diffMin / 60);
|
|
515
|
+
const diffDay = Math.floor(diffHour / 24);
|
|
516
|
+
const diffMonth = Math.floor(diffDay / 30);
|
|
517
|
+
const diffYear = Math.floor(diffDay / 365);
|
|
518
|
+
if (diffYear > 0) {
|
|
519
|
+
return `${diffYear} year${diffYear > 1 ? "s" : ""} ago`;
|
|
520
|
+
}
|
|
521
|
+
if (diffMonth > 0) {
|
|
522
|
+
return `${diffMonth} month${diffMonth > 1 ? "s" : ""} ago`;
|
|
523
|
+
}
|
|
524
|
+
if (diffDay > 0) {
|
|
525
|
+
return `${diffDay} day${diffDay > 1 ? "s" : ""} ago`;
|
|
526
|
+
}
|
|
527
|
+
if (diffHour > 0) {
|
|
528
|
+
return `${diffHour} hour${diffHour > 1 ? "s" : ""} ago`;
|
|
529
|
+
}
|
|
530
|
+
if (diffMin > 0) {
|
|
531
|
+
return `${diffMin} minute${diffMin > 1 ? "s" : ""} ago`;
|
|
532
|
+
}
|
|
533
|
+
return "just now";
|
|
534
|
+
}
|
|
535
|
+
function formatDate(date) {
|
|
536
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
537
|
+
year: "numeric",
|
|
538
|
+
month: "short",
|
|
539
|
+
day: "numeric"
|
|
540
|
+
}).format(date);
|
|
541
|
+
}
|
|
542
|
+
function formatDateTime(date) {
|
|
543
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
544
|
+
year: "numeric",
|
|
545
|
+
month: "short",
|
|
546
|
+
day: "numeric",
|
|
547
|
+
hour: "numeric",
|
|
548
|
+
minute: "2-digit",
|
|
549
|
+
hour12: true
|
|
550
|
+
}).format(date);
|
|
551
|
+
}
|
|
552
|
+
function formatDuration(ms) {
|
|
553
|
+
const seconds = Math.floor(ms / 1e3);
|
|
554
|
+
const minutes = Math.floor(seconds / 60);
|
|
555
|
+
const hours = Math.floor(minutes / 60);
|
|
556
|
+
if (hours > 0) {
|
|
557
|
+
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
|
|
558
|
+
}
|
|
559
|
+
if (minutes > 0) {
|
|
560
|
+
return `${minutes}m ${seconds % 60}s`;
|
|
561
|
+
}
|
|
562
|
+
return `${seconds}s`;
|
|
563
|
+
}
|
|
564
|
+
function formatMetric(value, unit = "number") {
|
|
565
|
+
switch (unit) {
|
|
566
|
+
case "bytes":
|
|
567
|
+
return formatFileSize(value);
|
|
568
|
+
case "percentage":
|
|
569
|
+
return formatPercentage(value);
|
|
570
|
+
case "duration":
|
|
571
|
+
return formatDuration(value);
|
|
572
|
+
default:
|
|
573
|
+
return formatCompactNumber(value);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
function formatRange(min, max) {
|
|
577
|
+
return `${formatCompactNumber(min)} - ${formatCompactNumber(max)}`;
|
|
578
|
+
}
|
|
579
|
+
function formatDecimal(value, decimals = 2) {
|
|
580
|
+
return value.toFixed(decimals);
|
|
581
|
+
}
|
|
582
|
+
function useDebounce(value, delay = 300) {
|
|
583
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
584
|
+
useEffect(() => {
|
|
585
|
+
const timer = setTimeout(() => {
|
|
586
|
+
setDebouncedValue(value);
|
|
587
|
+
}, delay);
|
|
588
|
+
return () => {
|
|
589
|
+
clearTimeout(timer);
|
|
590
|
+
};
|
|
591
|
+
}, [value, delay]);
|
|
592
|
+
return debouncedValue;
|
|
593
|
+
}
|
|
594
|
+
function useD3(renderFn, dependencies = []) {
|
|
595
|
+
const ref = useRef(null);
|
|
596
|
+
useEffect(() => {
|
|
597
|
+
if (ref.current) {
|
|
598
|
+
const selection = d32.select(ref.current);
|
|
599
|
+
renderFn(selection);
|
|
600
|
+
}
|
|
601
|
+
}, dependencies);
|
|
602
|
+
return ref;
|
|
603
|
+
}
|
|
604
|
+
function useD3WithResize(renderFn, dependencies = []) {
|
|
605
|
+
const ref = useRef(null);
|
|
606
|
+
useEffect(() => {
|
|
607
|
+
if (!ref.current) return;
|
|
608
|
+
const selection = d32.select(ref.current);
|
|
609
|
+
const render = () => renderFn(selection);
|
|
610
|
+
render();
|
|
611
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
612
|
+
render();
|
|
613
|
+
});
|
|
614
|
+
resizeObserver.observe(ref.current);
|
|
615
|
+
return () => {
|
|
616
|
+
resizeObserver.disconnect();
|
|
617
|
+
};
|
|
618
|
+
}, dependencies);
|
|
619
|
+
return ref;
|
|
620
|
+
}
|
|
621
|
+
function useForceSimulation(initialNodes, initialLinks, options) {
|
|
622
|
+
const {
|
|
623
|
+
chargeStrength = -300,
|
|
624
|
+
linkDistance = 100,
|
|
625
|
+
linkStrength = 1,
|
|
626
|
+
collisionStrength = 1,
|
|
627
|
+
collisionRadius = 10,
|
|
628
|
+
centerStrength = 0.1,
|
|
629
|
+
width,
|
|
630
|
+
height,
|
|
631
|
+
alphaDecay = 0.0228,
|
|
632
|
+
velocityDecay = 0.4
|
|
633
|
+
} = options;
|
|
634
|
+
const [nodes, setNodes] = useState(initialNodes);
|
|
635
|
+
const [links, setLinks] = useState(initialLinks);
|
|
636
|
+
const [isRunning, setIsRunning] = useState(false);
|
|
637
|
+
const [alpha, setAlpha] = useState(1);
|
|
638
|
+
const simulationRef = useRef(null);
|
|
639
|
+
useEffect(() => {
|
|
640
|
+
const nodesCopy = initialNodes.map((node) => ({ ...node }));
|
|
641
|
+
const linksCopy = initialLinks.map((link) => ({ ...link }));
|
|
642
|
+
const simulation = d32.forceSimulation(nodesCopy).force(
|
|
643
|
+
"link",
|
|
644
|
+
d32.forceLink(linksCopy).id((d) => d.id).distance(linkDistance).strength(linkStrength)
|
|
645
|
+
).force("charge", d32.forceManyBody().strength(chargeStrength)).force("center", d32.forceCenter(width / 2, height / 2).strength(centerStrength)).force(
|
|
646
|
+
"collision",
|
|
647
|
+
d32.forceCollide().radius(collisionRadius).strength(collisionStrength)
|
|
648
|
+
).alphaDecay(alphaDecay).velocityDecay(velocityDecay);
|
|
649
|
+
simulationRef.current = simulation;
|
|
650
|
+
simulation.on("tick", () => {
|
|
651
|
+
setNodes([...nodesCopy]);
|
|
652
|
+
setLinks([...linksCopy]);
|
|
653
|
+
setAlpha(simulation.alpha());
|
|
654
|
+
setIsRunning(simulation.alpha() > simulation.alphaMin());
|
|
655
|
+
});
|
|
656
|
+
simulation.on("end", () => {
|
|
657
|
+
setIsRunning(false);
|
|
658
|
+
});
|
|
659
|
+
return () => {
|
|
660
|
+
simulation.stop();
|
|
661
|
+
};
|
|
662
|
+
}, [
|
|
663
|
+
initialNodes,
|
|
664
|
+
initialLinks,
|
|
665
|
+
chargeStrength,
|
|
666
|
+
linkDistance,
|
|
667
|
+
linkStrength,
|
|
668
|
+
collisionStrength,
|
|
669
|
+
collisionRadius,
|
|
670
|
+
centerStrength,
|
|
671
|
+
width,
|
|
672
|
+
height,
|
|
673
|
+
alphaDecay,
|
|
674
|
+
velocityDecay
|
|
675
|
+
]);
|
|
676
|
+
const restart = () => {
|
|
677
|
+
if (simulationRef.current) {
|
|
678
|
+
simulationRef.current.alpha(1).restart();
|
|
679
|
+
setIsRunning(true);
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
const stop = () => {
|
|
683
|
+
if (simulationRef.current) {
|
|
684
|
+
simulationRef.current.stop();
|
|
685
|
+
setIsRunning(false);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
return {
|
|
689
|
+
nodes,
|
|
690
|
+
links,
|
|
691
|
+
restart,
|
|
692
|
+
stop,
|
|
693
|
+
isRunning,
|
|
694
|
+
alpha
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
function useDrag(simulation) {
|
|
698
|
+
const dragStarted = (event, node) => {
|
|
699
|
+
if (!simulation) return;
|
|
700
|
+
if (!event.active) simulation.alphaTarget(0.3).restart();
|
|
701
|
+
node.fx = node.x;
|
|
702
|
+
node.fy = node.y;
|
|
703
|
+
};
|
|
704
|
+
const dragged = (event, node) => {
|
|
705
|
+
node.fx = event.x;
|
|
706
|
+
node.fy = event.y;
|
|
707
|
+
};
|
|
708
|
+
const dragEnded = (event, node) => {
|
|
709
|
+
if (!simulation) return;
|
|
710
|
+
if (!event.active) simulation.alphaTarget(0);
|
|
711
|
+
node.fx = null;
|
|
712
|
+
node.fy = null;
|
|
713
|
+
};
|
|
714
|
+
return {
|
|
715
|
+
onDragStart: dragStarted,
|
|
716
|
+
onDrag: dragged,
|
|
717
|
+
onDragEnd: dragEnded
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
var ForceDirectedGraph = ({
|
|
721
|
+
nodes: initialNodes,
|
|
722
|
+
links: initialLinks,
|
|
723
|
+
width,
|
|
724
|
+
height,
|
|
725
|
+
simulationOptions,
|
|
726
|
+
enableZoom = true,
|
|
727
|
+
enableDrag = true,
|
|
728
|
+
onNodeClick,
|
|
729
|
+
onNodeHover,
|
|
730
|
+
onLinkClick,
|
|
731
|
+
selectedNodeId,
|
|
732
|
+
hoveredNodeId,
|
|
733
|
+
defaultNodeColor = "#69b3a2",
|
|
734
|
+
defaultNodeSize = 10,
|
|
735
|
+
defaultLinkColor = "#999",
|
|
736
|
+
defaultLinkWidth = 1,
|
|
737
|
+
showNodeLabels = true,
|
|
738
|
+
showLinkLabels = false,
|
|
739
|
+
className
|
|
740
|
+
}) => {
|
|
741
|
+
const svgRef = useRef(null);
|
|
742
|
+
const gRef = useRef(null);
|
|
743
|
+
const [transform, setTransform] = useState({ k: 1, x: 0, y: 0 });
|
|
744
|
+
const { nodes, links, restart } = useForceSimulation(initialNodes, initialLinks, {
|
|
745
|
+
width,
|
|
746
|
+
height,
|
|
747
|
+
...simulationOptions
|
|
748
|
+
});
|
|
749
|
+
useEffect(() => {
|
|
750
|
+
if (!enableZoom || !svgRef.current || !gRef.current) return;
|
|
751
|
+
const svg = d32.select(svgRef.current);
|
|
752
|
+
const g = d32.select(gRef.current);
|
|
753
|
+
const zoom2 = d32.zoom().scaleExtent([0.1, 10]).on("zoom", (event) => {
|
|
754
|
+
g.attr("transform", event.transform);
|
|
755
|
+
setTransform(event.transform);
|
|
756
|
+
});
|
|
757
|
+
svg.call(zoom2);
|
|
758
|
+
return () => {
|
|
759
|
+
svg.on(".zoom", null);
|
|
760
|
+
};
|
|
761
|
+
}, [enableZoom]);
|
|
762
|
+
const handleDragStart = useCallback(
|
|
763
|
+
(event, node) => {
|
|
764
|
+
if (!enableDrag) return;
|
|
765
|
+
event.stopPropagation();
|
|
766
|
+
node.fx = node.x;
|
|
767
|
+
node.fy = node.y;
|
|
768
|
+
restart();
|
|
769
|
+
},
|
|
770
|
+
[enableDrag, restart]
|
|
771
|
+
);
|
|
772
|
+
const handleDrag = useCallback(
|
|
773
|
+
(event, node) => {
|
|
774
|
+
if (!enableDrag) return;
|
|
775
|
+
const svg = svgRef.current;
|
|
776
|
+
if (!svg) return;
|
|
777
|
+
const rect = svg.getBoundingClientRect();
|
|
778
|
+
const x = (event.clientX - rect.left - transform.x) / transform.k;
|
|
779
|
+
const y = (event.clientY - rect.top - transform.y) / transform.k;
|
|
780
|
+
node.fx = x;
|
|
781
|
+
node.fy = y;
|
|
782
|
+
},
|
|
783
|
+
[enableDrag, transform]
|
|
784
|
+
);
|
|
785
|
+
const handleDragEnd = useCallback(
|
|
786
|
+
(event, node) => {
|
|
787
|
+
if (!enableDrag) return;
|
|
788
|
+
event.stopPropagation();
|
|
789
|
+
node.fx = null;
|
|
790
|
+
node.fy = null;
|
|
791
|
+
},
|
|
792
|
+
[enableDrag]
|
|
793
|
+
);
|
|
794
|
+
const handleNodeClick = useCallback(
|
|
795
|
+
(node) => {
|
|
796
|
+
onNodeClick?.(node);
|
|
797
|
+
},
|
|
798
|
+
[onNodeClick]
|
|
799
|
+
);
|
|
800
|
+
const handleNodeMouseEnter = useCallback(
|
|
801
|
+
(node) => {
|
|
802
|
+
onNodeHover?.(node);
|
|
803
|
+
},
|
|
804
|
+
[onNodeHover]
|
|
805
|
+
);
|
|
806
|
+
const handleNodeMouseLeave = useCallback(() => {
|
|
807
|
+
onNodeHover?.(null);
|
|
808
|
+
}, [onNodeHover]);
|
|
809
|
+
const handleLinkClick = useCallback(
|
|
810
|
+
(link) => {
|
|
811
|
+
onLinkClick?.(link);
|
|
812
|
+
},
|
|
813
|
+
[onLinkClick]
|
|
814
|
+
);
|
|
815
|
+
return /* @__PURE__ */ jsxs(
|
|
816
|
+
"svg",
|
|
817
|
+
{
|
|
818
|
+
ref: svgRef,
|
|
819
|
+
width,
|
|
820
|
+
height,
|
|
821
|
+
className: cn("bg-white dark:bg-gray-900", className),
|
|
822
|
+
children: [
|
|
823
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
|
|
824
|
+
"marker",
|
|
825
|
+
{
|
|
826
|
+
id: "arrow",
|
|
827
|
+
viewBox: "0 0 10 10",
|
|
828
|
+
refX: "20",
|
|
829
|
+
refY: "5",
|
|
830
|
+
markerWidth: "6",
|
|
831
|
+
markerHeight: "6",
|
|
832
|
+
orient: "auto",
|
|
833
|
+
children: /* @__PURE__ */ jsx("path", { d: "M 0 0 L 10 5 L 0 10 z", fill: defaultLinkColor })
|
|
834
|
+
}
|
|
835
|
+
) }),
|
|
836
|
+
/* @__PURE__ */ jsxs("g", { ref: gRef, children: [
|
|
837
|
+
links.map((link, i) => {
|
|
838
|
+
const source = link.source;
|
|
839
|
+
const target = link.target;
|
|
840
|
+
if (!source.x || !source.y || !target.x || !target.y) return null;
|
|
841
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
842
|
+
/* @__PURE__ */ jsx(
|
|
843
|
+
"line",
|
|
844
|
+
{
|
|
845
|
+
x1: source.x,
|
|
846
|
+
y1: source.y,
|
|
847
|
+
x2: target.x,
|
|
848
|
+
y2: target.y,
|
|
849
|
+
stroke: link.color || defaultLinkColor,
|
|
850
|
+
strokeWidth: link.width || defaultLinkWidth,
|
|
851
|
+
opacity: 0.6,
|
|
852
|
+
className: "cursor-pointer transition-opacity hover:opacity-100",
|
|
853
|
+
onClick: () => handleLinkClick(link)
|
|
854
|
+
}
|
|
855
|
+
),
|
|
856
|
+
showLinkLabels && link.label && /* @__PURE__ */ jsx(
|
|
857
|
+
"text",
|
|
858
|
+
{
|
|
859
|
+
x: (source.x + target.x) / 2,
|
|
860
|
+
y: (source.y + target.y) / 2,
|
|
861
|
+
fill: "#666",
|
|
862
|
+
fontSize: "10",
|
|
863
|
+
textAnchor: "middle",
|
|
864
|
+
dominantBaseline: "middle",
|
|
865
|
+
pointerEvents: "none",
|
|
866
|
+
children: link.label
|
|
867
|
+
}
|
|
868
|
+
)
|
|
869
|
+
] }, `link-${i}`);
|
|
870
|
+
}),
|
|
871
|
+
nodes.map((node) => {
|
|
872
|
+
if (!node.x || !node.y) return null;
|
|
873
|
+
const isSelected = selectedNodeId === node.id;
|
|
874
|
+
const isHovered = hoveredNodeId === node.id;
|
|
875
|
+
const nodeSize = node.size || defaultNodeSize;
|
|
876
|
+
const nodeColor = node.color || defaultNodeColor;
|
|
877
|
+
return /* @__PURE__ */ jsxs(
|
|
878
|
+
"g",
|
|
879
|
+
{
|
|
880
|
+
transform: `translate(${node.x},${node.y})`,
|
|
881
|
+
className: "cursor-pointer",
|
|
882
|
+
onClick: () => handleNodeClick(node),
|
|
883
|
+
onMouseEnter: () => handleNodeMouseEnter(node),
|
|
884
|
+
onMouseLeave: handleNodeMouseLeave,
|
|
885
|
+
onMouseDown: (e) => handleDragStart(e, node),
|
|
886
|
+
onMouseMove: (e) => handleDrag(e, node),
|
|
887
|
+
onMouseUp: (e) => handleDragEnd(e, node),
|
|
888
|
+
children: [
|
|
889
|
+
/* @__PURE__ */ jsx(
|
|
890
|
+
"circle",
|
|
891
|
+
{
|
|
892
|
+
r: nodeSize,
|
|
893
|
+
fill: nodeColor,
|
|
894
|
+
stroke: isSelected ? "#000" : isHovered ? "#666" : "none",
|
|
895
|
+
strokeWidth: isSelected ? 3 : 2,
|
|
896
|
+
opacity: isHovered || isSelected ? 1 : 0.9,
|
|
897
|
+
className: "transition-all"
|
|
898
|
+
}
|
|
899
|
+
),
|
|
900
|
+
showNodeLabels && node.label && /* @__PURE__ */ jsx(
|
|
901
|
+
"text",
|
|
902
|
+
{
|
|
903
|
+
y: nodeSize + 15,
|
|
904
|
+
fill: "#333",
|
|
905
|
+
fontSize: "12",
|
|
906
|
+
textAnchor: "middle",
|
|
907
|
+
dominantBaseline: "middle",
|
|
908
|
+
pointerEvents: "none",
|
|
909
|
+
className: "select-none",
|
|
910
|
+
children: node.label
|
|
911
|
+
}
|
|
912
|
+
)
|
|
913
|
+
]
|
|
914
|
+
},
|
|
915
|
+
node.id
|
|
916
|
+
);
|
|
917
|
+
})
|
|
918
|
+
] })
|
|
919
|
+
]
|
|
920
|
+
}
|
|
921
|
+
);
|
|
922
|
+
};
|
|
923
|
+
ForceDirectedGraph.displayName = "ForceDirectedGraph";
|
|
924
|
+
|
|
925
|
+
export { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Container, ForceDirectedGraph, Grid, Input, Label, RadioGroup, Select, Separator, Stack, Switch, Textarea, badgeVariants, buttonVariants, chartColors, cn, domainColors, formatCompactNumber, formatDate, formatDateTime, formatDecimal, formatDuration, formatFileSize, formatMetric, formatNumber, formatPercentage, formatRange, formatRelativeTime, getDomainColor, getSeverityColor, hexToRgba, severityColors, useD3, useD3WithResize, useDebounce, useDrag, useForceSimulation };
|
|
926
|
+
//# sourceMappingURL=index.js.map
|
|
927
|
+
//# sourceMappingURL=index.js.map
|