@foresthubai/workflow-builder 0.3.0 → 0.4.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/LICENSE +661 -661
- package/NOTICE +16 -16
- package/README.md +110 -93
- package/dist/components/ui/command.d.ts +2 -2
- package/dist/components/ui/input.d.ts +1 -1
- package/dist/components/ui/resizable.d.ts +1 -1
- package/dist/components/ui/textarea.d.ts +1 -1
- package/dist/graph/BaseNode.js +10 -10
- package/dist/graph/reactFlowRegistry.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/toolbars/CanvasTabsToolbar.d.ts +11 -0
- package/dist/toolbars/CanvasTabsToolbar.d.ts.map +1 -0
- package/dist/toolbars/CanvasTabsToolbar.js +101 -0
- package/dist/toolbars/CanvasTabsToolbar.js.map +1 -0
- package/package.json +2 -2
- package/src/BuilderLayout.tsx +345 -345
- package/src/Canvas.tsx +261 -261
- package/src/CanvasEditor.tsx +142 -142
- package/src/CanvasTabsToolbar.tsx +176 -176
- package/src/RightConfigPanel.tsx +266 -266
- package/src/WorkflowBuilder.tsx +412 -412
- package/src/cn.ts +6 -6
- package/src/components/ui/add-button.tsx +39 -39
- package/src/components/ui/alert-dialog.tsx +141 -141
- package/src/components/ui/alert.tsx +59 -59
- package/src/components/ui/badge.tsx +36 -36
- package/src/components/ui/button.tsx +85 -85
- package/src/components/ui/card.tsx +79 -79
- package/src/components/ui/checkbox.tsx +28 -28
- package/src/components/ui/collapsible.tsx +9 -9
- package/src/components/ui/command.tsx +153 -153
- package/src/components/ui/delete-button.tsx +23 -23
- package/src/components/ui/dialog.tsx +125 -125
- package/src/components/ui/dropdown-menu.tsx +198 -198
- package/src/components/ui/input.tsx +55 -55
- package/src/components/ui/label.tsx +24 -24
- package/src/components/ui/readonly-banner.tsx +15 -15
- package/src/components/ui/resizable.tsx +43 -43
- package/src/components/ui/scroll-area.tsx +102 -102
- package/src/components/ui/select.tsx +160 -160
- package/src/components/ui/separator.tsx +29 -29
- package/src/components/ui/switch.tsx +27 -27
- package/src/components/ui/textarea.tsx +51 -51
- package/src/components/ui/toast.tsx +127 -127
- package/src/components/ui/toaster.tsx +33 -33
- package/src/components/ui/toggle-group.tsx +59 -59
- package/src/components/ui/toggle.tsx +43 -43
- package/src/components/ui/tooltip.tsx +32 -32
- package/src/dialogs/NodePickerDialog.tsx +84 -84
- package/src/dialogs/ValidationDialog.tsx +184 -184
- package/src/graph/BaseNode.tsx +557 -557
- package/src/graph/CustomEdge.tsx +185 -185
- package/src/graph/CustomNode.tsx +16 -16
- package/src/graph/FunctionCallNode.tsx +30 -30
- package/src/graph/PortHandle.tsx +189 -189
- package/src/graph/reactFlowRegistry.ts +26 -26
- package/src/hooks/use-toast.ts +125 -125
- package/src/hooks/useAvailableVariables.ts +20 -20
- package/src/hooks/useCanvasHistory.ts +22 -22
- package/src/hooks/useCanvasTabs.ts +168 -168
- package/src/hooks/useFunctionDiagnosticsSync.ts +40 -40
- package/src/hooks/useFunctionRegistry.ts +26 -26
- package/src/hooks/useFunctions.ts +44 -44
- package/src/hooks/useGraph.ts +161 -161
- package/src/hooks/useNodeDefinitions.ts +82 -82
- package/src/hooks/useParamErrors.ts +26 -26
- package/src/hooks/useResolvedTheme.ts +30 -30
- package/src/hooks/useResourceDiagnosticsSync.ts +58 -58
- package/src/hooks/useSuppressThemeTransition.ts +79 -79
- package/src/hooks/useWorkflowSerialization.ts +127 -127
- package/src/i18n/index.ts +53 -53
- package/src/i18n/locales/de.json +501 -501
- package/src/i18n/locales/en.json +557 -557
- package/src/index.ts +27 -27
- package/src/inputs/ExpressionInput.tsx +297 -297
- package/src/inputs/ParameterEditor.tsx +515 -515
- package/src/inputs/PortSection.tsx +144 -144
- package/src/panels/BuilderSidebar.tsx +301 -301
- package/src/panels/ChannelConfigPanel.tsx +49 -49
- package/src/panels/ChannelsPanel.tsx +28 -28
- package/src/panels/DebugConsolePanel.tsx +73 -73
- package/src/panels/DebugContextPanel.tsx +77 -77
- package/src/panels/DebugExternalIOPanel.tsx +180 -180
- package/src/panels/DiagnosticsPanel.tsx +170 -170
- package/src/panels/EdgeConfigPanel.tsx +104 -104
- package/src/panels/FunctionConfigPanel.tsx +179 -179
- package/src/panels/FunctionListPanel.tsx +45 -45
- package/src/panels/MemoryConfigPanel.tsx +55 -55
- package/src/panels/MemoryPanel.tsx +40 -40
- package/src/panels/ModelConfigPanel.tsx +41 -41
- package/src/panels/ModelsPanel.tsx +36 -36
- package/src/panels/NodeConfigPanel.tsx +630 -630
- package/src/panels/NodeLibrary.tsx +288 -288
- package/src/panels/ResourceConfigPanel.tsx +132 -132
- package/src/panels/ResourceListPanel.tsx +113 -113
- package/src/panels/VariableConfigPanel.tsx +161 -161
- package/src/panels/VariablesPanel.tsx +145 -145
- package/src/stores/canvasStore.test.ts +44 -44
- package/src/stores/canvasStore.ts +245 -245
- package/src/stores/debugStore.ts +74 -74
- package/src/stores/diagnosticsStore.ts +130 -130
- package/src/stores/editorStore.ts +202 -202
- package/src/styles/index.css +526 -526
- package/src/utils/categoryConstants.ts +26 -26
- package/src/utils/channelOperations.ts +86 -86
- package/src/utils/connectionRules.ts +137 -137
- package/src/utils/functionOperations.ts +179 -179
- package/src/utils/graphOperations.ts +550 -550
- package/src/utils/history.ts +207 -207
- package/src/utils/memoryOperations.ts +57 -57
- package/src/utils/migrateFunctionNodes.ts +107 -107
- package/src/utils/modelOperations.ts +55 -55
- package/src/utils/paramDisplay.ts +71 -71
- package/src/utils/resourceHelpers.ts +32 -32
- package/src/utils/translation.ts +28 -28
- package/src/utils/variableOperations.ts +75 -75
- package/tailwind-preset.ts +166 -166
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import * as React from "react"
|
|
2
|
-
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
|
3
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
-
|
|
5
|
-
import { cn } from "../../cn"
|
|
6
|
-
|
|
7
|
-
const toggleVariants = cva(
|
|
8
|
-
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
|
|
9
|
-
{
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default: "bg-transparent",
|
|
13
|
-
outline:
|
|
14
|
-
"border border-input bg-transparent hover:bg-primary/20 hover:text-foreground data-[state=on]:relative data-[state=on]:z-10 data-[state=on]:border-primary",
|
|
15
|
-
},
|
|
16
|
-
size: {
|
|
17
|
-
default: "h-10 px-3",
|
|
18
|
-
sm: "h-9 px-2.5",
|
|
19
|
-
lg: "h-11 px-5",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
defaultVariants: {
|
|
23
|
-
variant: "default",
|
|
24
|
-
size: "default",
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
const Toggle = React.forwardRef<
|
|
30
|
-
React.ElementRef<typeof TogglePrimitive.Root>,
|
|
31
|
-
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
|
32
|
-
VariantProps<typeof toggleVariants>
|
|
33
|
-
>(({ className, variant, size, ...props }, ref) => (
|
|
34
|
-
<TogglePrimitive.Root
|
|
35
|
-
ref={ref}
|
|
36
|
-
className={cn(toggleVariants({ variant, size, className }))}
|
|
37
|
-
{...props}
|
|
38
|
-
/>
|
|
39
|
-
))
|
|
40
|
-
|
|
41
|
-
Toggle.displayName = TogglePrimitive.Root.displayName
|
|
42
|
-
|
|
43
|
-
export { Toggle, toggleVariants }
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as TogglePrimitive from "@radix-ui/react-toggle"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../cn"
|
|
6
|
+
|
|
7
|
+
const toggleVariants = cva(
|
|
8
|
+
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-transparent",
|
|
13
|
+
outline:
|
|
14
|
+
"border border-input bg-transparent hover:bg-primary/20 hover:text-foreground data-[state=on]:relative data-[state=on]:z-10 data-[state=on]:border-primary",
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
default: "h-10 px-3",
|
|
18
|
+
sm: "h-9 px-2.5",
|
|
19
|
+
lg: "h-11 px-5",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
variant: "default",
|
|
24
|
+
size: "default",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const Toggle = React.forwardRef<
|
|
30
|
+
React.ElementRef<typeof TogglePrimitive.Root>,
|
|
31
|
+
React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
|
|
32
|
+
VariantProps<typeof toggleVariants>
|
|
33
|
+
>(({ className, variant, size, ...props }, ref) => (
|
|
34
|
+
<TogglePrimitive.Root
|
|
35
|
+
ref={ref}
|
|
36
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
))
|
|
40
|
+
|
|
41
|
+
Toggle.displayName = TogglePrimitive.Root.displayName
|
|
42
|
+
|
|
43
|
+
export { Toggle, toggleVariants }
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
-
|
|
4
|
-
import { cn } from "../../cn";
|
|
5
|
-
|
|
6
|
-
const TooltipProvider = TooltipPrimitive.Provider;
|
|
7
|
-
|
|
8
|
-
const Tooltip = TooltipPrimitive.Root;
|
|
9
|
-
|
|
10
|
-
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
11
|
-
|
|
12
|
-
const TooltipContent = React.forwardRef<
|
|
13
|
-
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
14
|
-
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
15
|
-
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
16
|
-
<TooltipPrimitive.Portal>
|
|
17
|
-
<TooltipPrimitive.Content
|
|
18
|
-
ref={ref}
|
|
19
|
-
sideOffset={sideOffset}
|
|
20
|
-
className={cn(
|
|
21
|
-
// font-sans + fh-builder-portal: portaled to <body>, outside the builder
|
|
22
|
-
// root — pin the font and opt into the themed scrollbar explicitly.
|
|
23
|
-
"fh-builder-portal font-sans z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
24
|
-
className,
|
|
25
|
-
)}
|
|
26
|
-
{...props}
|
|
27
|
-
/>
|
|
28
|
-
</TooltipPrimitive.Portal>
|
|
29
|
-
));
|
|
30
|
-
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
31
|
-
|
|
32
|
-
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../cn";
|
|
5
|
+
|
|
6
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
7
|
+
|
|
8
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
11
|
+
|
|
12
|
+
const TooltipContent = React.forwardRef<
|
|
13
|
+
React.ElementRef<typeof TooltipPrimitive.Content>,
|
|
14
|
+
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
|
|
15
|
+
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
16
|
+
<TooltipPrimitive.Portal>
|
|
17
|
+
<TooltipPrimitive.Content
|
|
18
|
+
ref={ref}
|
|
19
|
+
sideOffset={sideOffset}
|
|
20
|
+
className={cn(
|
|
21
|
+
// font-sans + fh-builder-portal: portaled to <body>, outside the builder
|
|
22
|
+
// root — pin the font and opt into the themed scrollbar explicitly.
|
|
23
|
+
"fh-builder-portal font-sans z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
24
|
+
className,
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
</TooltipPrimitive.Portal>
|
|
29
|
+
));
|
|
30
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
31
|
+
|
|
32
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { useTranslation } from "react-i18next";
|
|
3
|
-
import { NodeDefinition, NodeCategory } from "@foresthubai/workflow-core/node";
|
|
4
|
-
import {
|
|
5
|
-
CommandDialog,
|
|
6
|
-
CommandInput,
|
|
7
|
-
CommandList,
|
|
8
|
-
CommandEmpty,
|
|
9
|
-
CommandGroup,
|
|
10
|
-
CommandItem,
|
|
11
|
-
} from "../components/ui/command";
|
|
12
|
-
import { categoryIcons } from "../utils/categoryConstants";
|
|
13
|
-
|
|
14
|
-
interface NodePickerDialogProps {
|
|
15
|
-
open: boolean;
|
|
16
|
-
onOpenChange: (open: boolean) => void;
|
|
17
|
-
compatibleDefs: NodeDefinition[];
|
|
18
|
-
onSelect: (nodeDef: NodeDefinition) => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const CATEGORY_ORDER: NodeCategory[] = [
|
|
22
|
-
NodeCategory.Trigger,
|
|
23
|
-
NodeCategory.Input,
|
|
24
|
-
NodeCategory.Logic,
|
|
25
|
-
NodeCategory.Data,
|
|
26
|
-
NodeCategory.Function,
|
|
27
|
-
NodeCategory.AI,
|
|
28
|
-
NodeCategory.Tool,
|
|
29
|
-
NodeCategory.Output,
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
export function NodePickerDialog({ open, onOpenChange, compatibleDefs, onSelect }: NodePickerDialogProps) {
|
|
33
|
-
const { t } = useTranslation();
|
|
34
|
-
const [search, setSearch] = useState("");
|
|
35
|
-
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
if (open) setSearch("");
|
|
38
|
-
}, [open]);
|
|
39
|
-
|
|
40
|
-
// Group definitions by category
|
|
41
|
-
const grouped = new Map<NodeCategory, NodeDefinition[]>();
|
|
42
|
-
for (const def of compatibleDefs) {
|
|
43
|
-
const list = grouped.get(def.category) ?? [];
|
|
44
|
-
list.push(def);
|
|
45
|
-
grouped.set(def.category, list);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
<CommandDialog open={open} onOpenChange={onOpenChange}>
|
|
50
|
-
<CommandInput
|
|
51
|
-
placeholder={t("nodePickerSearch", "Search nodes...")}
|
|
52
|
-
value={search}
|
|
53
|
-
onValueChange={setSearch}
|
|
54
|
-
/>
|
|
55
|
-
<CommandList>
|
|
56
|
-
<CommandEmpty>{t("nodePickerEmpty", "No compatible nodes found.")}</CommandEmpty>
|
|
57
|
-
{CATEGORY_ORDER.filter((cat) => grouped.has(cat)).map((category) => {
|
|
58
|
-
const Icon = categoryIcons[category];
|
|
59
|
-
return (
|
|
60
|
-
<CommandGroup key={category} heading={category}>
|
|
61
|
-
{grouped.get(category)!.map((def) => (
|
|
62
|
-
<CommandItem
|
|
63
|
-
key={def.type + (def.type === "FunctionCall" ? `-${def.label}` : "")}
|
|
64
|
-
onSelect={() => {
|
|
65
|
-
onSelect(def);
|
|
66
|
-
onOpenChange(false);
|
|
67
|
-
}}
|
|
68
|
-
>
|
|
69
|
-
{Icon && <Icon className="mr-2 h-4 w-4 shrink-0 opacity-70" />}
|
|
70
|
-
<div className="flex flex-col min-w-0">
|
|
71
|
-
<span className="truncate">{def.label}</span>
|
|
72
|
-
{def.description && (
|
|
73
|
-
<span className="text-xs text-muted-foreground truncate">{def.description}</span>
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
</CommandItem>
|
|
77
|
-
))}
|
|
78
|
-
</CommandGroup>
|
|
79
|
-
);
|
|
80
|
-
})}
|
|
81
|
-
</CommandList>
|
|
82
|
-
</CommandDialog>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { NodeDefinition, NodeCategory } from "@foresthubai/workflow-core/node";
|
|
4
|
+
import {
|
|
5
|
+
CommandDialog,
|
|
6
|
+
CommandInput,
|
|
7
|
+
CommandList,
|
|
8
|
+
CommandEmpty,
|
|
9
|
+
CommandGroup,
|
|
10
|
+
CommandItem,
|
|
11
|
+
} from "../components/ui/command";
|
|
12
|
+
import { categoryIcons } from "../utils/categoryConstants";
|
|
13
|
+
|
|
14
|
+
interface NodePickerDialogProps {
|
|
15
|
+
open: boolean;
|
|
16
|
+
onOpenChange: (open: boolean) => void;
|
|
17
|
+
compatibleDefs: NodeDefinition[];
|
|
18
|
+
onSelect: (nodeDef: NodeDefinition) => void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const CATEGORY_ORDER: NodeCategory[] = [
|
|
22
|
+
NodeCategory.Trigger,
|
|
23
|
+
NodeCategory.Input,
|
|
24
|
+
NodeCategory.Logic,
|
|
25
|
+
NodeCategory.Data,
|
|
26
|
+
NodeCategory.Function,
|
|
27
|
+
NodeCategory.AI,
|
|
28
|
+
NodeCategory.Tool,
|
|
29
|
+
NodeCategory.Output,
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
export function NodePickerDialog({ open, onOpenChange, compatibleDefs, onSelect }: NodePickerDialogProps) {
|
|
33
|
+
const { t } = useTranslation();
|
|
34
|
+
const [search, setSearch] = useState("");
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (open) setSearch("");
|
|
38
|
+
}, [open]);
|
|
39
|
+
|
|
40
|
+
// Group definitions by category
|
|
41
|
+
const grouped = new Map<NodeCategory, NodeDefinition[]>();
|
|
42
|
+
for (const def of compatibleDefs) {
|
|
43
|
+
const list = grouped.get(def.category) ?? [];
|
|
44
|
+
list.push(def);
|
|
45
|
+
grouped.set(def.category, list);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<CommandDialog open={open} onOpenChange={onOpenChange}>
|
|
50
|
+
<CommandInput
|
|
51
|
+
placeholder={t("nodePickerSearch", "Search nodes...")}
|
|
52
|
+
value={search}
|
|
53
|
+
onValueChange={setSearch}
|
|
54
|
+
/>
|
|
55
|
+
<CommandList>
|
|
56
|
+
<CommandEmpty>{t("nodePickerEmpty", "No compatible nodes found.")}</CommandEmpty>
|
|
57
|
+
{CATEGORY_ORDER.filter((cat) => grouped.has(cat)).map((category) => {
|
|
58
|
+
const Icon = categoryIcons[category];
|
|
59
|
+
return (
|
|
60
|
+
<CommandGroup key={category} heading={category}>
|
|
61
|
+
{grouped.get(category)!.map((def) => (
|
|
62
|
+
<CommandItem
|
|
63
|
+
key={def.type + (def.type === "FunctionCall" ? `-${def.label}` : "")}
|
|
64
|
+
onSelect={() => {
|
|
65
|
+
onSelect(def);
|
|
66
|
+
onOpenChange(false);
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
{Icon && <Icon className="mr-2 h-4 w-4 shrink-0 opacity-70" />}
|
|
70
|
+
<div className="flex flex-col min-w-0">
|
|
71
|
+
<span className="truncate">{def.label}</span>
|
|
72
|
+
{def.description && (
|
|
73
|
+
<span className="text-xs text-muted-foreground truncate">{def.description}</span>
|
|
74
|
+
)}
|
|
75
|
+
</div>
|
|
76
|
+
</CommandItem>
|
|
77
|
+
))}
|
|
78
|
+
</CommandGroup>
|
|
79
|
+
);
|
|
80
|
+
})}
|
|
81
|
+
</CommandList>
|
|
82
|
+
</CommandDialog>
|
|
83
|
+
);
|
|
84
|
+
}
|