@openconsole/shadcn 0.2.5 → 0.2.7

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 (113) hide show
  1. package/components/index.ts +1 -2
  2. package/components/ui/accordion.tsx +66 -66
  3. package/components/ui/alert-dialog.tsx +196 -196
  4. package/components/ui/alert.tsx +66 -66
  5. package/components/ui/aspect-ratio.tsx +11 -11
  6. package/components/ui/avatar.tsx +53 -53
  7. package/components/ui/badge.tsx +46 -46
  8. package/components/ui/breadcrumb.tsx +109 -109
  9. package/components/ui/button-group.tsx +83 -83
  10. package/components/ui/button.tsx +60 -60
  11. package/components/ui/calendar.tsx +219 -219
  12. package/components/ui/card.tsx +92 -92
  13. package/components/ui/carousel.tsx +241 -241
  14. package/components/ui/chart.tsx +374 -374
  15. package/components/ui/checkbox.tsx +32 -32
  16. package/components/ui/collapsible.tsx +33 -33
  17. package/components/ui/command.tsx +184 -184
  18. package/components/ui/context-menu.tsx +252 -252
  19. package/components/ui/dialog.tsx +143 -143
  20. package/components/ui/direction.tsx +22 -22
  21. package/components/ui/drawer.tsx +135 -135
  22. package/components/ui/dropdown-menu.tsx +257 -257
  23. package/components/ui/empty.tsx +104 -104
  24. package/components/ui/field.tsx +248 -248
  25. package/components/ui/form.tsx +167 -167
  26. package/components/ui/hover-card.tsx +44 -44
  27. package/components/ui/index.ts +59 -59
  28. package/components/ui/input-group.tsx +170 -170
  29. package/components/ui/input-otp.tsx +77 -77
  30. package/components/ui/input.tsx +21 -21
  31. package/components/ui/item.tsx +193 -193
  32. package/components/ui/kbd.tsx +28 -28
  33. package/components/ui/label.tsx +24 -24
  34. package/components/ui/menubar.tsx +276 -276
  35. package/components/ui/native-select.tsx +62 -62
  36. package/components/ui/navigation-menu.tsx +168 -168
  37. package/components/ui/pagination.tsx +127 -127
  38. package/components/ui/popover.tsx +89 -89
  39. package/components/ui/progress.tsx +31 -31
  40. package/components/ui/radio-group.tsx +45 -45
  41. package/components/ui/resizable.tsx +53 -53
  42. package/components/ui/scroll-area.tsx +58 -58
  43. package/components/ui/select.tsx +187 -187
  44. package/components/ui/separator.tsx +28 -28
  45. package/components/ui/sheet.tsx +139 -139
  46. package/components/ui/sidebar.tsx +724 -724
  47. package/components/ui/skeleton.tsx +13 -13
  48. package/components/ui/slider.tsx +63 -63
  49. package/components/ui/sonner.tsx +40 -40
  50. package/components/ui/spinner.tsx +16 -16
  51. package/components/ui/switch.tsx +35 -35
  52. package/components/ui/table.tsx +116 -116
  53. package/components/ui/tabs.tsx +66 -66
  54. package/components/ui/textarea.tsx +18 -18
  55. package/components/ui/toggle-group.tsx +83 -83
  56. package/components/ui/toggle.tsx +47 -47
  57. package/components/ui/tooltip.tsx +61 -61
  58. package/hooks/index.ts +1 -1
  59. package/hooks/use-mobile.ts +19 -19
  60. package/index.ts +3 -3
  61. package/lib/index.ts +1 -1
  62. package/lib/utils.ts +6 -6
  63. package/package.json +1 -1
  64. package/styles.css +124 -124
  65. package/components/ai-elements/agent.tsx +0 -141
  66. package/components/ai-elements/artifact.tsx +0 -148
  67. package/components/ai-elements/attachments.tsx +0 -426
  68. package/components/ai-elements/audio-player.tsx +0 -231
  69. package/components/ai-elements/canvas.tsx +0 -26
  70. package/components/ai-elements/chain-of-thought.tsx +0 -222
  71. package/components/ai-elements/checkpoint.tsx +0 -71
  72. package/components/ai-elements/code-block.tsx +0 -562
  73. package/components/ai-elements/commit.tsx +0 -458
  74. package/components/ai-elements/confirmation.tsx +0 -174
  75. package/components/ai-elements/connection.tsx +0 -28
  76. package/components/ai-elements/context.tsx +0 -409
  77. package/components/ai-elements/controls.tsx +0 -18
  78. package/components/ai-elements/conversation.tsx +0 -168
  79. package/components/ai-elements/edge.tsx +0 -143
  80. package/components/ai-elements/environment-variables.tsx +0 -324
  81. package/components/ai-elements/file-tree.tsx +0 -304
  82. package/components/ai-elements/image.tsx +0 -24
  83. package/components/ai-elements/index.ts +0 -51
  84. package/components/ai-elements/inline-citation.tsx +0 -296
  85. package/components/ai-elements/jsx-preview.tsx +0 -310
  86. package/components/ai-elements/message.tsx +0 -360
  87. package/components/ai-elements/mic-selector.tsx +0 -375
  88. package/components/ai-elements/model-selector.tsx +0 -213
  89. package/components/ai-elements/node.tsx +0 -71
  90. package/components/ai-elements/open-in-chat.tsx +0 -370
  91. package/components/ai-elements/package-info.tsx +0 -239
  92. package/components/ai-elements/panel.tsx +0 -15
  93. package/components/ai-elements/persona.tsx +0 -306
  94. package/components/ai-elements/plan.tsx +0 -147
  95. package/components/ai-elements/prompt-input.tsx +0 -1463
  96. package/components/ai-elements/queue.tsx +0 -274
  97. package/components/ai-elements/reasoning.tsx +0 -228
  98. package/components/ai-elements/sandbox.tsx +0 -132
  99. package/components/ai-elements/schema-display.tsx +0 -471
  100. package/components/ai-elements/shimmer.tsx +0 -77
  101. package/components/ai-elements/snippet.tsx +0 -145
  102. package/components/ai-elements/sources.tsx +0 -77
  103. package/components/ai-elements/speech-input.tsx +0 -323
  104. package/components/ai-elements/stack-trace.tsx +0 -528
  105. package/components/ai-elements/suggestion.tsx +0 -57
  106. package/components/ai-elements/task.tsx +0 -87
  107. package/components/ai-elements/terminal.tsx +0 -273
  108. package/components/ai-elements/test-results.tsx +0 -496
  109. package/components/ai-elements/tool.tsx +0 -173
  110. package/components/ai-elements/toolbar.tsx +0 -16
  111. package/components/ai-elements/transcription.tsx +0 -125
  112. package/components/ai-elements/voice-selector.tsx +0 -524
  113. package/components/ai-elements/web-preview.tsx +0 -281
@@ -1,458 +0,0 @@
1
- "use client";
2
-
3
- import { Avatar, AvatarFallback } from "../ui/avatar";
4
- import { Button } from "../ui/button";
5
- import {
6
- Collapsible,
7
- CollapsibleContent,
8
- CollapsibleTrigger,
9
- } from "../ui/collapsible";
10
- import { cn } from "../../lib/utils";
11
- import {
12
- CheckIcon,
13
- CopyIcon,
14
- FileIcon,
15
- GitCommitIcon,
16
- MinusIcon,
17
- PlusIcon,
18
- } from "lucide-react";
19
- import type { ComponentProps, HTMLAttributes } from "react";
20
- import { useCallback, useEffect, useRef, useState } from "react";
21
-
22
- export type CommitProps = ComponentProps<typeof Collapsible>;
23
-
24
- export const Commit = ({ className, children, ...props }: CommitProps) => (
25
- <Collapsible
26
- className={cn("rounded-lg border bg-background", className)}
27
- {...props}
28
- >
29
- {children}
30
- </Collapsible>
31
- );
32
-
33
- export type CommitHeaderProps = ComponentProps<typeof CollapsibleTrigger>;
34
-
35
- export const CommitHeader = ({
36
- className,
37
- children,
38
- ...props
39
- }: CommitHeaderProps) => (
40
- <CollapsibleTrigger asChild {...props}>
41
- <div
42
- className={cn(
43
- "group flex cursor-pointer items-center justify-between gap-4 p-3 text-left transition-colors hover:opacity-80",
44
- className
45
- )}
46
- >
47
- {children}
48
- </div>
49
- </CollapsibleTrigger>
50
- );
51
-
52
- export type CommitHashProps = HTMLAttributes<HTMLSpanElement>;
53
-
54
- export const CommitHash = ({
55
- className,
56
- children,
57
- ...props
58
- }: CommitHashProps) => (
59
- <span className={cn("font-mono text-xs", className)} {...props}>
60
- <GitCommitIcon className="mr-1 inline-block size-3" />
61
- {children}
62
- </span>
63
- );
64
-
65
- export type CommitMessageProps = HTMLAttributes<HTMLSpanElement>;
66
-
67
- export const CommitMessage = ({
68
- className,
69
- children,
70
- ...props
71
- }: CommitMessageProps) => (
72
- <span className={cn("font-medium text-sm", className)} {...props}>
73
- {children}
74
- </span>
75
- );
76
-
77
- export type CommitMetadataProps = HTMLAttributes<HTMLDivElement>;
78
-
79
- export const CommitMetadata = ({
80
- className,
81
- children,
82
- ...props
83
- }: CommitMetadataProps) => (
84
- <div
85
- className={cn(
86
- "flex items-center gap-2 text-muted-foreground text-xs",
87
- className
88
- )}
89
- {...props}
90
- >
91
- {children}
92
- </div>
93
- );
94
-
95
- export type CommitSeparatorProps = HTMLAttributes<HTMLSpanElement>;
96
-
97
- export const CommitSeparator = ({
98
- className,
99
- children,
100
- ...props
101
- }: CommitSeparatorProps) => (
102
- <span className={className} {...props}>
103
- {children ?? "•"}
104
- </span>
105
- );
106
-
107
- export type CommitInfoProps = HTMLAttributes<HTMLDivElement>;
108
-
109
- export const CommitInfo = ({
110
- className,
111
- children,
112
- ...props
113
- }: CommitInfoProps) => (
114
- <div className={cn("flex flex-1 flex-col", className)} {...props}>
115
- {children}
116
- </div>
117
- );
118
-
119
- export type CommitAuthorProps = HTMLAttributes<HTMLDivElement>;
120
-
121
- export const CommitAuthor = ({
122
- className,
123
- children,
124
- ...props
125
- }: CommitAuthorProps) => (
126
- <div className={cn("flex items-center", className)} {...props}>
127
- {children}
128
- </div>
129
- );
130
-
131
- export type CommitAuthorAvatarProps = ComponentProps<typeof Avatar> & {
132
- initials: string;
133
- };
134
-
135
- export const CommitAuthorAvatar = ({
136
- initials,
137
- className,
138
- ...props
139
- }: CommitAuthorAvatarProps) => (
140
- <Avatar className={cn("size-8", className)} {...props}>
141
- <AvatarFallback className="text-xs">{initials}</AvatarFallback>
142
- </Avatar>
143
- );
144
-
145
- export type CommitTimestampProps = HTMLAttributes<HTMLTimeElement> & {
146
- date: Date;
147
- };
148
-
149
- const relativeTimeFormat = new Intl.RelativeTimeFormat("en", {
150
- numeric: "auto",
151
- });
152
-
153
- const formatRelativeDate = (date: Date) => {
154
- const days = Math.round(
155
- (date.getTime() - Date.now()) / (1000 * 60 * 60 * 24)
156
- );
157
- return relativeTimeFormat.format(days, "day");
158
- };
159
-
160
- export const CommitTimestamp = ({
161
- date,
162
- className,
163
- children,
164
- ...props
165
- }: CommitTimestampProps) => {
166
- const [formatted, setFormatted] = useState("");
167
-
168
- const updateFormatted = useCallback(() => {
169
- setFormatted(formatRelativeDate(date));
170
- }, [date]);
171
-
172
- useEffect(() => {
173
- updateFormatted();
174
- }, [updateFormatted]);
175
-
176
- return (
177
- <time
178
- className={cn("text-xs", className)}
179
- dateTime={date.toISOString()}
180
- {...props}
181
- >
182
- {children ?? formatted}
183
- </time>
184
- );
185
- };
186
-
187
- export type CommitActionsProps = HTMLAttributes<HTMLDivElement>;
188
-
189
- const handleActionsClick = (e: React.MouseEvent) => e.stopPropagation();
190
- const handleActionsKeyDown = (e: React.KeyboardEvent) => e.stopPropagation();
191
-
192
- export const CommitActions = ({
193
- className,
194
- children,
195
- ...props
196
- }: CommitActionsProps) => (
197
- <div
198
- className={cn("flex items-center gap-1", className)}
199
- onClick={handleActionsClick}
200
- onKeyDown={handleActionsKeyDown}
201
- role="group"
202
- {...props}
203
- >
204
- {children}
205
- </div>
206
- );
207
-
208
- export type CommitCopyButtonProps = ComponentProps<typeof Button> & {
209
- hash: string;
210
- onCopy?: () => void;
211
- onError?: (error: Error) => void;
212
- timeout?: number;
213
- };
214
-
215
- export const CommitCopyButton = ({
216
- hash,
217
- onCopy,
218
- onError,
219
- timeout = 2000,
220
- children,
221
- className,
222
- ...props
223
- }: CommitCopyButtonProps) => {
224
- const [isCopied, setIsCopied] = useState(false);
225
- const timeoutRef = useRef<number>(0);
226
-
227
- const copyToClipboard = useCallback(async () => {
228
- if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
229
- onError?.(new Error("Clipboard API not available"));
230
- return;
231
- }
232
-
233
- try {
234
- if (!isCopied) {
235
- await navigator.clipboard.writeText(hash);
236
- setIsCopied(true);
237
- onCopy?.();
238
- timeoutRef.current = window.setTimeout(
239
- () => setIsCopied(false),
240
- timeout
241
- );
242
- }
243
- } catch (error) {
244
- onError?.(error as Error);
245
- }
246
- }, [hash, onCopy, onError, timeout, isCopied]);
247
-
248
- useEffect(
249
- () => () => {
250
- window.clearTimeout(timeoutRef.current);
251
- },
252
- []
253
- );
254
-
255
- const Icon = isCopied ? CheckIcon : CopyIcon;
256
-
257
- return (
258
- <Button
259
- className={cn("size-7 shrink-0", className)}
260
- onClick={copyToClipboard}
261
- size="icon"
262
- variant="ghost"
263
- {...props}
264
- >
265
- {children ?? <Icon size={14} />}
266
- </Button>
267
- );
268
- };
269
-
270
- export type CommitContentProps = ComponentProps<typeof CollapsibleContent>;
271
-
272
- export const CommitContent = ({
273
- className,
274
- children,
275
- ...props
276
- }: CommitContentProps) => (
277
- <CollapsibleContent className={cn("border-t p-3", className)} {...props}>
278
- {children}
279
- </CollapsibleContent>
280
- );
281
-
282
- export type CommitFilesProps = HTMLAttributes<HTMLDivElement>;
283
-
284
- export const CommitFiles = ({
285
- className,
286
- children,
287
- ...props
288
- }: CommitFilesProps) => (
289
- <div className={cn("space-y-1", className)} {...props}>
290
- {children}
291
- </div>
292
- );
293
-
294
- export type CommitFileProps = HTMLAttributes<HTMLDivElement>;
295
-
296
- export const CommitFile = ({
297
- className,
298
- children,
299
- ...props
300
- }: CommitFileProps) => (
301
- <div
302
- className={cn(
303
- "flex items-center justify-between gap-2 rounded px-2 py-1 text-sm hover:bg-muted/50",
304
- className
305
- )}
306
- {...props}
307
- >
308
- {children}
309
- </div>
310
- );
311
-
312
- export type CommitFileInfoProps = HTMLAttributes<HTMLDivElement>;
313
-
314
- export const CommitFileInfo = ({
315
- className,
316
- children,
317
- ...props
318
- }: CommitFileInfoProps) => (
319
- <div className={cn("flex min-w-0 items-center gap-2", className)} {...props}>
320
- {children}
321
- </div>
322
- );
323
-
324
- const fileStatusStyles = {
325
- added: "text-green-600 dark:text-green-400",
326
- deleted: "text-red-600 dark:text-red-400",
327
- modified: "text-yellow-600 dark:text-yellow-400",
328
- renamed: "text-blue-600 dark:text-blue-400",
329
- };
330
-
331
- const fileStatusLabels = {
332
- added: "A",
333
- deleted: "D",
334
- modified: "M",
335
- renamed: "R",
336
- };
337
-
338
- export type CommitFileStatusProps = HTMLAttributes<HTMLSpanElement> & {
339
- status: "added" | "modified" | "deleted" | "renamed";
340
- };
341
-
342
- export const CommitFileStatus = ({
343
- status,
344
- className,
345
- children,
346
- ...props
347
- }: CommitFileStatusProps) => (
348
- <span
349
- className={cn(
350
- "font-medium font-mono text-xs",
351
- fileStatusStyles[status],
352
- className
353
- )}
354
- {...props}
355
- >
356
- {children ?? fileStatusLabels[status]}
357
- </span>
358
- );
359
-
360
- export type CommitFileIconProps = ComponentProps<typeof FileIcon>;
361
-
362
- export const CommitFileIcon = ({
363
- className,
364
- ...props
365
- }: CommitFileIconProps) => (
366
- <FileIcon
367
- className={cn("size-3.5 shrink-0 text-muted-foreground", className)}
368
- {...props}
369
- />
370
- );
371
-
372
- export type CommitFilePathProps = HTMLAttributes<HTMLSpanElement>;
373
-
374
- export const CommitFilePath = ({
375
- className,
376
- children,
377
- ...props
378
- }: CommitFilePathProps) => (
379
- <span className={cn("truncate font-mono text-xs", className)} {...props}>
380
- {children}
381
- </span>
382
- );
383
-
384
- export type CommitFileChangesProps = HTMLAttributes<HTMLDivElement>;
385
-
386
- export const CommitFileChanges = ({
387
- className,
388
- children,
389
- ...props
390
- }: CommitFileChangesProps) => (
391
- <div
392
- className={cn(
393
- "flex shrink-0 items-center gap-1 font-mono text-xs",
394
- className
395
- )}
396
- {...props}
397
- >
398
- {children}
399
- </div>
400
- );
401
-
402
- export type CommitFileAdditionsProps = HTMLAttributes<HTMLSpanElement> & {
403
- count: number;
404
- };
405
-
406
- export const CommitFileAdditions = ({
407
- count,
408
- className,
409
- children,
410
- ...props
411
- }: CommitFileAdditionsProps) => {
412
- if (count <= 0) {
413
- return null;
414
- }
415
-
416
- return (
417
- <span
418
- className={cn("text-green-600 dark:text-green-400", className)}
419
- {...props}
420
- >
421
- {children ?? (
422
- <>
423
- <PlusIcon className="inline-block size-3" />
424
- {count}
425
- </>
426
- )}
427
- </span>
428
- );
429
- };
430
-
431
- export type CommitFileDeletionsProps = HTMLAttributes<HTMLSpanElement> & {
432
- count: number;
433
- };
434
-
435
- export const CommitFileDeletions = ({
436
- count,
437
- className,
438
- children,
439
- ...props
440
- }: CommitFileDeletionsProps) => {
441
- if (count <= 0) {
442
- return null;
443
- }
444
-
445
- return (
446
- <span
447
- className={cn("text-red-600 dark:text-red-400", className)}
448
- {...props}
449
- >
450
- {children ?? (
451
- <>
452
- <MinusIcon className="inline-block size-3" />
453
- {count}
454
- </>
455
- )}
456
- </span>
457
- );
458
- };
@@ -1,174 +0,0 @@
1
- "use client";
2
-
3
- import { Alert, AlertDescription } from "../ui/alert";
4
- import { Button } from "../ui/button";
5
- import { cn } from "../../lib/utils";
6
- import type { ToolUIPart } from "ai";
7
- import type { ComponentProps, ReactNode } from "react";
8
- import { createContext, useContext, useMemo } from "react";
9
-
10
- type ToolUIPartApproval =
11
- | {
12
- id: string;
13
- approved?: never;
14
- reason?: never;
15
- }
16
- | {
17
- id: string;
18
- approved: boolean;
19
- reason?: string;
20
- }
21
- | {
22
- id: string;
23
- approved: true;
24
- reason?: string;
25
- }
26
- | {
27
- id: string;
28
- approved: true;
29
- reason?: string;
30
- }
31
- | {
32
- id: string;
33
- approved: false;
34
- reason?: string;
35
- }
36
- | undefined;
37
-
38
- interface ConfirmationContextValue {
39
- approval: ToolUIPartApproval;
40
- state: ToolUIPart["state"];
41
- }
42
-
43
- const ConfirmationContext = createContext<ConfirmationContextValue | null>(
44
- null
45
- );
46
-
47
- const useConfirmation = () => {
48
- const context = useContext(ConfirmationContext);
49
-
50
- if (!context) {
51
- throw new Error("Confirmation components must be used within Confirmation");
52
- }
53
-
54
- return context;
55
- };
56
-
57
- export type ConfirmationProps = ComponentProps<typeof Alert> & {
58
- approval?: ToolUIPartApproval;
59
- state: ToolUIPart["state"];
60
- };
61
-
62
- export const Confirmation = ({
63
- className,
64
- approval,
65
- state,
66
- ...props
67
- }: ConfirmationProps) => {
68
- const contextValue = useMemo(() => ({ approval, state }), [approval, state]);
69
-
70
- if (!approval || state === "input-streaming" || state === "input-available") {
71
- return null;
72
- }
73
-
74
- return (
75
- <ConfirmationContext.Provider value={contextValue}>
76
- <Alert className={cn("flex flex-col gap-2", className)} {...props} />
77
- </ConfirmationContext.Provider>
78
- );
79
- };
80
-
81
- export type ConfirmationTitleProps = ComponentProps<typeof AlertDescription>;
82
-
83
- export const ConfirmationTitle = ({
84
- className,
85
- ...props
86
- }: ConfirmationTitleProps) => (
87
- <AlertDescription className={cn("inline", className)} {...props} />
88
- );
89
-
90
- export interface ConfirmationRequestProps {
91
- children?: ReactNode;
92
- }
93
-
94
- export const ConfirmationRequest = ({ children }: ConfirmationRequestProps) => {
95
- const { state } = useConfirmation();
96
-
97
- // Only show when approval is requested
98
- if (state !== "approval-requested") {
99
- return null;
100
- }
101
-
102
- return children;
103
- };
104
-
105
- export interface ConfirmationAcceptedProps {
106
- children?: ReactNode;
107
- }
108
-
109
- export const ConfirmationAccepted = ({
110
- children,
111
- }: ConfirmationAcceptedProps) => {
112
- const { approval, state } = useConfirmation();
113
-
114
- // Only show when approved and in response states
115
- if (
116
- !approval?.approved ||
117
- (state !== "approval-responded" &&
118
- state !== "output-denied" &&
119
- state !== "output-available")
120
- ) {
121
- return null;
122
- }
123
-
124
- return children;
125
- };
126
-
127
- export interface ConfirmationRejectedProps {
128
- children?: ReactNode;
129
- }
130
-
131
- export const ConfirmationRejected = ({
132
- children,
133
- }: ConfirmationRejectedProps) => {
134
- const { approval, state } = useConfirmation();
135
-
136
- // Only show when rejected and in response states
137
- if (
138
- approval?.approved !== false ||
139
- (state !== "approval-responded" &&
140
- state !== "output-denied" &&
141
- state !== "output-available")
142
- ) {
143
- return null;
144
- }
145
-
146
- return children;
147
- };
148
-
149
- export type ConfirmationActionsProps = ComponentProps<"div">;
150
-
151
- export const ConfirmationActions = ({
152
- className,
153
- ...props
154
- }: ConfirmationActionsProps) => {
155
- const { state } = useConfirmation();
156
-
157
- // Only show when approval is requested
158
- if (state !== "approval-requested") {
159
- return null;
160
- }
161
-
162
- return (
163
- <div
164
- className={cn("flex items-center justify-end gap-2 self-end", className)}
165
- {...props}
166
- />
167
- );
168
- };
169
-
170
- export type ConfirmationActionProps = ComponentProps<typeof Button>;
171
-
172
- export const ConfirmationAction = (props: ConfirmationActionProps) => (
173
- <Button className="h-8 px-3 text-sm" type="button" {...props} />
174
- );
@@ -1,28 +0,0 @@
1
- import type { ConnectionLineComponent } from "@xyflow/react";
2
-
3
- const HALF = 0.5;
4
-
5
- export const Connection: ConnectionLineComponent = ({
6
- fromX,
7
- fromY,
8
- toX,
9
- toY,
10
- }) => (
11
- <g>
12
- <path
13
- className="animated"
14
- d={`M${fromX},${fromY} C ${fromX + (toX - fromX) * HALF},${fromY} ${fromX + (toX - fromX) * HALF},${toY} ${toX},${toY}`}
15
- fill="none"
16
- stroke="var(--color-ring)"
17
- strokeWidth={1}
18
- />
19
- <circle
20
- cx={toX}
21
- cy={toY}
22
- fill="#fff"
23
- r={3}
24
- stroke="var(--color-ring)"
25
- strokeWidth={1}
26
- />
27
- </g>
28
- );