@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.
Files changed (120) hide show
  1. package/LICENSE +661 -661
  2. package/NOTICE +16 -16
  3. package/README.md +110 -93
  4. package/dist/components/ui/command.d.ts +2 -2
  5. package/dist/components/ui/input.d.ts +1 -1
  6. package/dist/components/ui/resizable.d.ts +1 -1
  7. package/dist/components/ui/textarea.d.ts +1 -1
  8. package/dist/graph/BaseNode.js +10 -10
  9. package/dist/graph/reactFlowRegistry.d.ts.map +1 -1
  10. package/dist/lib/utils.d.ts +3 -0
  11. package/dist/lib/utils.d.ts.map +1 -0
  12. package/dist/lib/utils.js +6 -0
  13. package/dist/lib/utils.js.map +1 -0
  14. package/dist/toolbars/CanvasTabsToolbar.d.ts +11 -0
  15. package/dist/toolbars/CanvasTabsToolbar.d.ts.map +1 -0
  16. package/dist/toolbars/CanvasTabsToolbar.js +101 -0
  17. package/dist/toolbars/CanvasTabsToolbar.js.map +1 -0
  18. package/package.json +2 -2
  19. package/src/BuilderLayout.tsx +345 -345
  20. package/src/Canvas.tsx +261 -261
  21. package/src/CanvasEditor.tsx +142 -142
  22. package/src/CanvasTabsToolbar.tsx +176 -176
  23. package/src/RightConfigPanel.tsx +266 -266
  24. package/src/WorkflowBuilder.tsx +412 -412
  25. package/src/cn.ts +6 -6
  26. package/src/components/ui/add-button.tsx +39 -39
  27. package/src/components/ui/alert-dialog.tsx +141 -141
  28. package/src/components/ui/alert.tsx +59 -59
  29. package/src/components/ui/badge.tsx +36 -36
  30. package/src/components/ui/button.tsx +85 -85
  31. package/src/components/ui/card.tsx +79 -79
  32. package/src/components/ui/checkbox.tsx +28 -28
  33. package/src/components/ui/collapsible.tsx +9 -9
  34. package/src/components/ui/command.tsx +153 -153
  35. package/src/components/ui/delete-button.tsx +23 -23
  36. package/src/components/ui/dialog.tsx +125 -125
  37. package/src/components/ui/dropdown-menu.tsx +198 -198
  38. package/src/components/ui/input.tsx +55 -55
  39. package/src/components/ui/label.tsx +24 -24
  40. package/src/components/ui/readonly-banner.tsx +15 -15
  41. package/src/components/ui/resizable.tsx +43 -43
  42. package/src/components/ui/scroll-area.tsx +102 -102
  43. package/src/components/ui/select.tsx +160 -160
  44. package/src/components/ui/separator.tsx +29 -29
  45. package/src/components/ui/switch.tsx +27 -27
  46. package/src/components/ui/textarea.tsx +51 -51
  47. package/src/components/ui/toast.tsx +127 -127
  48. package/src/components/ui/toaster.tsx +33 -33
  49. package/src/components/ui/toggle-group.tsx +59 -59
  50. package/src/components/ui/toggle.tsx +43 -43
  51. package/src/components/ui/tooltip.tsx +32 -32
  52. package/src/dialogs/NodePickerDialog.tsx +84 -84
  53. package/src/dialogs/ValidationDialog.tsx +184 -184
  54. package/src/graph/BaseNode.tsx +557 -557
  55. package/src/graph/CustomEdge.tsx +185 -185
  56. package/src/graph/CustomNode.tsx +16 -16
  57. package/src/graph/FunctionCallNode.tsx +30 -30
  58. package/src/graph/PortHandle.tsx +189 -189
  59. package/src/graph/reactFlowRegistry.ts +26 -26
  60. package/src/hooks/use-toast.ts +125 -125
  61. package/src/hooks/useAvailableVariables.ts +20 -20
  62. package/src/hooks/useCanvasHistory.ts +22 -22
  63. package/src/hooks/useCanvasTabs.ts +168 -168
  64. package/src/hooks/useFunctionDiagnosticsSync.ts +40 -40
  65. package/src/hooks/useFunctionRegistry.ts +26 -26
  66. package/src/hooks/useFunctions.ts +44 -44
  67. package/src/hooks/useGraph.ts +161 -161
  68. package/src/hooks/useNodeDefinitions.ts +82 -82
  69. package/src/hooks/useParamErrors.ts +26 -26
  70. package/src/hooks/useResolvedTheme.ts +30 -30
  71. package/src/hooks/useResourceDiagnosticsSync.ts +58 -58
  72. package/src/hooks/useSuppressThemeTransition.ts +79 -79
  73. package/src/hooks/useWorkflowSerialization.ts +127 -127
  74. package/src/i18n/index.ts +53 -53
  75. package/src/i18n/locales/de.json +501 -501
  76. package/src/i18n/locales/en.json +557 -557
  77. package/src/index.ts +27 -27
  78. package/src/inputs/ExpressionInput.tsx +297 -297
  79. package/src/inputs/ParameterEditor.tsx +515 -515
  80. package/src/inputs/PortSection.tsx +144 -144
  81. package/src/panels/BuilderSidebar.tsx +301 -301
  82. package/src/panels/ChannelConfigPanel.tsx +49 -49
  83. package/src/panels/ChannelsPanel.tsx +28 -28
  84. package/src/panels/DebugConsolePanel.tsx +73 -73
  85. package/src/panels/DebugContextPanel.tsx +77 -77
  86. package/src/panels/DebugExternalIOPanel.tsx +180 -180
  87. package/src/panels/DiagnosticsPanel.tsx +170 -170
  88. package/src/panels/EdgeConfigPanel.tsx +104 -104
  89. package/src/panels/FunctionConfigPanel.tsx +179 -179
  90. package/src/panels/FunctionListPanel.tsx +45 -45
  91. package/src/panels/MemoryConfigPanel.tsx +55 -55
  92. package/src/panels/MemoryPanel.tsx +40 -40
  93. package/src/panels/ModelConfigPanel.tsx +41 -41
  94. package/src/panels/ModelsPanel.tsx +36 -36
  95. package/src/panels/NodeConfigPanel.tsx +630 -630
  96. package/src/panels/NodeLibrary.tsx +288 -288
  97. package/src/panels/ResourceConfigPanel.tsx +132 -132
  98. package/src/panels/ResourceListPanel.tsx +113 -113
  99. package/src/panels/VariableConfigPanel.tsx +161 -161
  100. package/src/panels/VariablesPanel.tsx +145 -145
  101. package/src/stores/canvasStore.test.ts +44 -44
  102. package/src/stores/canvasStore.ts +245 -245
  103. package/src/stores/debugStore.ts +74 -74
  104. package/src/stores/diagnosticsStore.ts +130 -130
  105. package/src/stores/editorStore.ts +202 -202
  106. package/src/styles/index.css +526 -526
  107. package/src/utils/categoryConstants.ts +26 -26
  108. package/src/utils/channelOperations.ts +86 -86
  109. package/src/utils/connectionRules.ts +137 -137
  110. package/src/utils/functionOperations.ts +179 -179
  111. package/src/utils/graphOperations.ts +550 -550
  112. package/src/utils/history.ts +207 -207
  113. package/src/utils/memoryOperations.ts +57 -57
  114. package/src/utils/migrateFunctionNodes.ts +107 -107
  115. package/src/utils/modelOperations.ts +55 -55
  116. package/src/utils/paramDisplay.ts +71 -71
  117. package/src/utils/resourceHelpers.ts +32 -32
  118. package/src/utils/translation.ts +28 -28
  119. package/src/utils/variableOperations.ts +75 -75
  120. package/tailwind-preset.ts +166 -166
@@ -1,43 +1,43 @@
1
- import { GripVertical } from "lucide-react"
2
- import * as ResizablePrimitive from "react-resizable-panels"
3
-
4
- import { cn } from "../../cn"
5
-
6
- const ResizablePanelGroup = ({
7
- className,
8
- ...props
9
- }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
10
- <ResizablePrimitive.PanelGroup
11
- className={cn(
12
- "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
13
- className
14
- )}
15
- {...props}
16
- />
17
- )
18
-
19
- const ResizablePanel = ResizablePrimitive.Panel
20
-
21
- const ResizableHandle = ({
22
- withHandle,
23
- className,
24
- ...props
25
- }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
26
- withHandle?: boolean
27
- }) => (
28
- <ResizablePrimitive.PanelResizeHandle
29
- className={cn(
30
- "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
31
- className
32
- )}
33
- {...props}
34
- >
35
- {withHandle && (
36
- <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
37
- <GripVertical className="h-2.5 w-2.5" />
38
- </div>
39
- )}
40
- </ResizablePrimitive.PanelResizeHandle>
41
- )
42
-
43
- export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
1
+ import { GripVertical } from "lucide-react"
2
+ import * as ResizablePrimitive from "react-resizable-panels"
3
+
4
+ import { cn } from "../../cn"
5
+
6
+ const ResizablePanelGroup = ({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
10
+ <ResizablePrimitive.PanelGroup
11
+ className={cn(
12
+ "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
13
+ className
14
+ )}
15
+ {...props}
16
+ />
17
+ )
18
+
19
+ const ResizablePanel = ResizablePrimitive.Panel
20
+
21
+ const ResizableHandle = ({
22
+ withHandle,
23
+ className,
24
+ ...props
25
+ }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
26
+ withHandle?: boolean
27
+ }) => (
28
+ <ResizablePrimitive.PanelResizeHandle
29
+ className={cn(
30
+ "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
31
+ className
32
+ )}
33
+ {...props}
34
+ >
35
+ {withHandle && (
36
+ <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
37
+ <GripVertical className="h-2.5 w-2.5" />
38
+ </div>
39
+ )}
40
+ </ResizablePrimitive.PanelResizeHandle>
41
+ )
42
+
43
+ export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
@@ -1,102 +1,102 @@
1
- import * as React from "react";
2
- import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3
-
4
- import { cn } from "../../cn";
5
-
6
- /**
7
- * Radix-backed overlay scrollbar — the builder's canonical scrollable surface.
8
- *
9
- * Why Radix and not the native `::-webkit-scrollbar`:
10
- * - Overlay positioning. The scrollbar is an absolutely-positioned div outside
11
- * the content flow, so it never subtracts width from content (no reflow when
12
- * it appears, no inconsistency between panels with and without overflow).
13
- * - `type="hover"`: scrollbar fades in only while the pointer is over the
14
- * panel, fades out otherwise — quiet by default.
15
- * - Thumb is semi-transparent so any content the scrollbar floats over stays
16
- * legible (the user explicitly wanted this).
17
- * - No arrow buttons. Just a thumb on a transparent track.
18
- *
19
- * The native CSS scrollbar rules in styles/index.css remain in place as a
20
- * fallback for tiny scrollable surfaces (dropdown menu lists, select popovers,
21
- * dialog bodies) where wrapping in a ScrollArea is overkill.
22
- *
23
- * `viewportRef` exposes the inner scrollable element for callers that need
24
- * imperative scroll (e.g. DebugConsolePanel auto-scrolling to bottom on new
25
- * entries). The Root forwardRef points to the outer container, which is *not*
26
- * the element with `overflow: scroll`.
27
- */
28
- interface ScrollAreaProps extends React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> {
29
- viewportRef?: React.Ref<HTMLDivElement>;
30
- /** Inner padding applied to the Viewport — usually what callers want when
31
- * replacing a `overflow-y-auto p-3` div, since Radix's Root cannot itself
32
- * carry the padding (it must clip cleanly for the overlay scrollbar). */
33
- viewportClassName?: string;
34
- }
35
-
36
- const ScrollArea = React.forwardRef<React.ElementRef<typeof ScrollAreaPrimitive.Root>, ScrollAreaProps>(
37
- ({ className, children, viewportRef, viewportClassName, type = "hover", ...props }, ref) => (
38
- <ScrollAreaPrimitive.Root
39
- ref={ref}
40
- type={type}
41
- className={cn("relative overflow-hidden", className)}
42
- {...props}
43
- >
44
- <ScrollAreaPrimitive.Viewport
45
- ref={viewportRef}
46
- className={cn("h-full w-full rounded-[inherit]", viewportClassName)}
47
- >
48
- {children}
49
- </ScrollAreaPrimitive.Viewport>
50
- <ScrollBar />
51
- <ScrollBar orientation="horizontal" />
52
- <ScrollAreaPrimitive.Corner className="bg-transparent" />
53
- </ScrollAreaPrimitive.Root>
54
- ),
55
- );
56
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
57
-
58
- /**
59
- * Themed thin scrollbar. 6px to match the native fallback, transparent track,
60
- * thumb tinted with --muted-foreground at low opacity bumping on hover. No
61
- * padding/border (the prior `p-[1px]` + transparent border was what gave it
62
- * the inset look people noticed against the native bar in other panels).
63
- *
64
- * The opacity transitions are driven by Radix's `data-state` on the scrollbar
65
- * itself (`visible` / `hidden`), which `type="hover"` flips based on pointer
66
- * position + overflow presence.
67
- */
68
- const ScrollBar = React.forwardRef<
69
- React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
70
- React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
71
- >(({ className, orientation = "vertical", ...props }, ref) => (
72
- // forceMount keeps the scrollbar in the DOM when Radix flips it to
73
- // data-state="hidden", so the opacity transition has something to animate.
74
- // Without it Radix unmounts the element after its hide delay and the bar
75
- // vanishes instantly instead of fading. The hidden bar is `pointer-events:
76
- // none` via opacity-0 + Radix not rendering interactive surfaces while
77
- // hidden, so this doesn't trap clicks.
78
- <ScrollAreaPrimitive.ScrollAreaScrollbar
79
- ref={ref}
80
- forceMount
81
- orientation={orientation}
82
- className={cn(
83
- "flex touch-none select-none transition-opacity duration-200",
84
- "data-[state=hidden]:opacity-0 data-[state=visible]:opacity-100",
85
- "data-[state=hidden]:pointer-events-none",
86
- orientation === "vertical" && "h-full w-1.5",
87
- orientation === "horizontal" && "h-1.5 flex-col w-full",
88
- className,
89
- )}
90
- {...props}
91
- >
92
- <ScrollAreaPrimitive.ScrollAreaThumb
93
- className={cn(
94
- "relative flex-1 rounded-full bg-muted-foreground/30 transition-colors",
95
- "hover:bg-muted-foreground/55",
96
- )}
97
- />
98
- </ScrollAreaPrimitive.ScrollAreaScrollbar>
99
- ));
100
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
101
-
102
- export { ScrollArea, ScrollBar };
1
+ import * as React from "react";
2
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area";
3
+
4
+ import { cn } from "../../cn";
5
+
6
+ /**
7
+ * Radix-backed overlay scrollbar — the builder's canonical scrollable surface.
8
+ *
9
+ * Why Radix and not the native `::-webkit-scrollbar`:
10
+ * - Overlay positioning. The scrollbar is an absolutely-positioned div outside
11
+ * the content flow, so it never subtracts width from content (no reflow when
12
+ * it appears, no inconsistency between panels with and without overflow).
13
+ * - `type="hover"`: scrollbar fades in only while the pointer is over the
14
+ * panel, fades out otherwise — quiet by default.
15
+ * - Thumb is semi-transparent so any content the scrollbar floats over stays
16
+ * legible (the user explicitly wanted this).
17
+ * - No arrow buttons. Just a thumb on a transparent track.
18
+ *
19
+ * The native CSS scrollbar rules in styles/index.css remain in place as a
20
+ * fallback for tiny scrollable surfaces (dropdown menu lists, select popovers,
21
+ * dialog bodies) where wrapping in a ScrollArea is overkill.
22
+ *
23
+ * `viewportRef` exposes the inner scrollable element for callers that need
24
+ * imperative scroll (e.g. DebugConsolePanel auto-scrolling to bottom on new
25
+ * entries). The Root forwardRef points to the outer container, which is *not*
26
+ * the element with `overflow: scroll`.
27
+ */
28
+ interface ScrollAreaProps extends React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root> {
29
+ viewportRef?: React.Ref<HTMLDivElement>;
30
+ /** Inner padding applied to the Viewport — usually what callers want when
31
+ * replacing a `overflow-y-auto p-3` div, since Radix's Root cannot itself
32
+ * carry the padding (it must clip cleanly for the overlay scrollbar). */
33
+ viewportClassName?: string;
34
+ }
35
+
36
+ const ScrollArea = React.forwardRef<React.ElementRef<typeof ScrollAreaPrimitive.Root>, ScrollAreaProps>(
37
+ ({ className, children, viewportRef, viewportClassName, type = "hover", ...props }, ref) => (
38
+ <ScrollAreaPrimitive.Root
39
+ ref={ref}
40
+ type={type}
41
+ className={cn("relative overflow-hidden", className)}
42
+ {...props}
43
+ >
44
+ <ScrollAreaPrimitive.Viewport
45
+ ref={viewportRef}
46
+ className={cn("h-full w-full rounded-[inherit]", viewportClassName)}
47
+ >
48
+ {children}
49
+ </ScrollAreaPrimitive.Viewport>
50
+ <ScrollBar />
51
+ <ScrollBar orientation="horizontal" />
52
+ <ScrollAreaPrimitive.Corner className="bg-transparent" />
53
+ </ScrollAreaPrimitive.Root>
54
+ ),
55
+ );
56
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
57
+
58
+ /**
59
+ * Themed thin scrollbar. 6px to match the native fallback, transparent track,
60
+ * thumb tinted with --muted-foreground at low opacity bumping on hover. No
61
+ * padding/border (the prior `p-[1px]` + transparent border was what gave it
62
+ * the inset look people noticed against the native bar in other panels).
63
+ *
64
+ * The opacity transitions are driven by Radix's `data-state` on the scrollbar
65
+ * itself (`visible` / `hidden`), which `type="hover"` flips based on pointer
66
+ * position + overflow presence.
67
+ */
68
+ const ScrollBar = React.forwardRef<
69
+ React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
70
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
71
+ >(({ className, orientation = "vertical", ...props }, ref) => (
72
+ // forceMount keeps the scrollbar in the DOM when Radix flips it to
73
+ // data-state="hidden", so the opacity transition has something to animate.
74
+ // Without it Radix unmounts the element after its hide delay and the bar
75
+ // vanishes instantly instead of fading. The hidden bar is `pointer-events:
76
+ // none` via opacity-0 + Radix not rendering interactive surfaces while
77
+ // hidden, so this doesn't trap clicks.
78
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
79
+ ref={ref}
80
+ forceMount
81
+ orientation={orientation}
82
+ className={cn(
83
+ "flex touch-none select-none transition-opacity duration-200",
84
+ "data-[state=hidden]:opacity-0 data-[state=visible]:opacity-100",
85
+ "data-[state=hidden]:pointer-events-none",
86
+ orientation === "vertical" && "h-full w-1.5",
87
+ orientation === "horizontal" && "h-1.5 flex-col w-full",
88
+ className,
89
+ )}
90
+ {...props}
91
+ >
92
+ <ScrollAreaPrimitive.ScrollAreaThumb
93
+ className={cn(
94
+ "relative flex-1 rounded-full bg-muted-foreground/30 transition-colors",
95
+ "hover:bg-muted-foreground/55",
96
+ )}
97
+ />
98
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
99
+ ));
100
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
101
+
102
+ export { ScrollArea, ScrollBar };
@@ -1,160 +1,160 @@
1
- import * as React from "react"
2
- import * as SelectPrimitive from "@radix-ui/react-select"
3
- import { Check, ChevronDown, ChevronUp } from "lucide-react"
4
-
5
- import { cn } from "../../cn"
6
-
7
- const Select = SelectPrimitive.Root
8
-
9
- const SelectGroup = SelectPrimitive.Group
10
-
11
- const SelectValue = SelectPrimitive.Value
12
-
13
- const SelectTrigger = React.forwardRef<
14
- React.ElementRef<typeof SelectPrimitive.Trigger>,
15
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
16
- >(({ className, children, ...props }, ref) => (
17
- <SelectPrimitive.Trigger
18
- ref={ref}
19
- className={cn(
20
- "flex h-10 w-full items-center justify-between rounded-md border border-input bg-field px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
21
- className
22
- )}
23
- {...props}
24
- >
25
- {children}
26
- <SelectPrimitive.Icon asChild>
27
- <ChevronDown className="h-4 w-4 opacity-50" />
28
- </SelectPrimitive.Icon>
29
- </SelectPrimitive.Trigger>
30
- ))
31
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
32
-
33
- const SelectScrollUpButton = React.forwardRef<
34
- React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
35
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
36
- >(({ className, ...props }, ref) => (
37
- <SelectPrimitive.ScrollUpButton
38
- ref={ref}
39
- className={cn(
40
- "flex cursor-default items-center justify-center py-1",
41
- className
42
- )}
43
- {...props}
44
- >
45
- <ChevronUp className="h-4 w-4" />
46
- </SelectPrimitive.ScrollUpButton>
47
- ))
48
- SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
49
-
50
- const SelectScrollDownButton = React.forwardRef<
51
- React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
52
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
53
- >(({ className, ...props }, ref) => (
54
- <SelectPrimitive.ScrollDownButton
55
- ref={ref}
56
- className={cn(
57
- "flex cursor-default items-center justify-center py-1",
58
- className
59
- )}
60
- {...props}
61
- >
62
- <ChevronDown className="h-4 w-4" />
63
- </SelectPrimitive.ScrollDownButton>
64
- ))
65
- SelectScrollDownButton.displayName =
66
- SelectPrimitive.ScrollDownButton.displayName
67
-
68
- const SelectContent = React.forwardRef<
69
- React.ElementRef<typeof SelectPrimitive.Content>,
70
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
71
- >(({ className, children, position = "popper", ...props }, ref) => (
72
- <SelectPrimitive.Portal>
73
- <SelectPrimitive.Content
74
- ref={ref}
75
- className={cn(
76
- // font-sans + fh-builder-portal: portaled to <body>, outside the builder
77
- // root — pin the font and opt into the themed scrollbar explicitly.
78
- "fh-builder-portal font-sans relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
79
- position === "popper" &&
80
- "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
81
- className
82
- )}
83
- position={position}
84
- {...props}
85
- >
86
- <SelectScrollUpButton />
87
- <SelectPrimitive.Viewport
88
- className={cn(
89
- "p-1",
90
- position === "popper" &&
91
- "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
92
- )}
93
- >
94
- {children}
95
- </SelectPrimitive.Viewport>
96
- <SelectScrollDownButton />
97
- </SelectPrimitive.Content>
98
- </SelectPrimitive.Portal>
99
- ))
100
- SelectContent.displayName = SelectPrimitive.Content.displayName
101
-
102
- const SelectLabel = React.forwardRef<
103
- React.ElementRef<typeof SelectPrimitive.Label>,
104
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
105
- >(({ className, ...props }, ref) => (
106
- <SelectPrimitive.Label
107
- ref={ref}
108
- className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
109
- {...props}
110
- />
111
- ))
112
- SelectLabel.displayName = SelectPrimitive.Label.displayName
113
-
114
- const SelectItem = React.forwardRef<
115
- React.ElementRef<typeof SelectPrimitive.Item>,
116
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
117
- >(({ className, children, ...props }, ref) => (
118
- <SelectPrimitive.Item
119
- ref={ref}
120
- className={cn(
121
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
122
- className
123
- )}
124
- {...props}
125
- >
126
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
127
- <SelectPrimitive.ItemIndicator>
128
- <Check className="h-4 w-4" />
129
- </SelectPrimitive.ItemIndicator>
130
- </span>
131
-
132
- <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
133
- </SelectPrimitive.Item>
134
- ))
135
- SelectItem.displayName = SelectPrimitive.Item.displayName
136
-
137
- const SelectSeparator = React.forwardRef<
138
- React.ElementRef<typeof SelectPrimitive.Separator>,
139
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
140
- >(({ className, ...props }, ref) => (
141
- <SelectPrimitive.Separator
142
- ref={ref}
143
- className={cn("-mx-1 my-1 h-px bg-muted", className)}
144
- {...props}
145
- />
146
- ))
147
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName
148
-
149
- export {
150
- Select,
151
- SelectGroup,
152
- SelectValue,
153
- SelectTrigger,
154
- SelectContent,
155
- SelectLabel,
156
- SelectItem,
157
- SelectSeparator,
158
- SelectScrollUpButton,
159
- SelectScrollDownButton,
160
- }
1
+ import * as React from "react"
2
+ import * as SelectPrimitive from "@radix-ui/react-select"
3
+ import { Check, ChevronDown, ChevronUp } from "lucide-react"
4
+
5
+ import { cn } from "../../cn"
6
+
7
+ const Select = SelectPrimitive.Root
8
+
9
+ const SelectGroup = SelectPrimitive.Group
10
+
11
+ const SelectValue = SelectPrimitive.Value
12
+
13
+ const SelectTrigger = React.forwardRef<
14
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
15
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
16
+ >(({ className, children, ...props }, ref) => (
17
+ <SelectPrimitive.Trigger
18
+ ref={ref}
19
+ className={cn(
20
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-field px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
21
+ className
22
+ )}
23
+ {...props}
24
+ >
25
+ {children}
26
+ <SelectPrimitive.Icon asChild>
27
+ <ChevronDown className="h-4 w-4 opacity-50" />
28
+ </SelectPrimitive.Icon>
29
+ </SelectPrimitive.Trigger>
30
+ ))
31
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
32
+
33
+ const SelectScrollUpButton = React.forwardRef<
34
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
35
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
36
+ >(({ className, ...props }, ref) => (
37
+ <SelectPrimitive.ScrollUpButton
38
+ ref={ref}
39
+ className={cn(
40
+ "flex cursor-default items-center justify-center py-1",
41
+ className
42
+ )}
43
+ {...props}
44
+ >
45
+ <ChevronUp className="h-4 w-4" />
46
+ </SelectPrimitive.ScrollUpButton>
47
+ ))
48
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
49
+
50
+ const SelectScrollDownButton = React.forwardRef<
51
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
52
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
53
+ >(({ className, ...props }, ref) => (
54
+ <SelectPrimitive.ScrollDownButton
55
+ ref={ref}
56
+ className={cn(
57
+ "flex cursor-default items-center justify-center py-1",
58
+ className
59
+ )}
60
+ {...props}
61
+ >
62
+ <ChevronDown className="h-4 w-4" />
63
+ </SelectPrimitive.ScrollDownButton>
64
+ ))
65
+ SelectScrollDownButton.displayName =
66
+ SelectPrimitive.ScrollDownButton.displayName
67
+
68
+ const SelectContent = React.forwardRef<
69
+ React.ElementRef<typeof SelectPrimitive.Content>,
70
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
71
+ >(({ className, children, position = "popper", ...props }, ref) => (
72
+ <SelectPrimitive.Portal>
73
+ <SelectPrimitive.Content
74
+ ref={ref}
75
+ className={cn(
76
+ // font-sans + fh-builder-portal: portaled to <body>, outside the builder
77
+ // root — pin the font and opt into the themed scrollbar explicitly.
78
+ "fh-builder-portal font-sans relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md 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 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
79
+ position === "popper" &&
80
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
81
+ className
82
+ )}
83
+ position={position}
84
+ {...props}
85
+ >
86
+ <SelectScrollUpButton />
87
+ <SelectPrimitive.Viewport
88
+ className={cn(
89
+ "p-1",
90
+ position === "popper" &&
91
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
92
+ )}
93
+ >
94
+ {children}
95
+ </SelectPrimitive.Viewport>
96
+ <SelectScrollDownButton />
97
+ </SelectPrimitive.Content>
98
+ </SelectPrimitive.Portal>
99
+ ))
100
+ SelectContent.displayName = SelectPrimitive.Content.displayName
101
+
102
+ const SelectLabel = React.forwardRef<
103
+ React.ElementRef<typeof SelectPrimitive.Label>,
104
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
105
+ >(({ className, ...props }, ref) => (
106
+ <SelectPrimitive.Label
107
+ ref={ref}
108
+ className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
109
+ {...props}
110
+ />
111
+ ))
112
+ SelectLabel.displayName = SelectPrimitive.Label.displayName
113
+
114
+ const SelectItem = React.forwardRef<
115
+ React.ElementRef<typeof SelectPrimitive.Item>,
116
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
117
+ >(({ className, children, ...props }, ref) => (
118
+ <SelectPrimitive.Item
119
+ ref={ref}
120
+ className={cn(
121
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
122
+ className
123
+ )}
124
+ {...props}
125
+ >
126
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
127
+ <SelectPrimitive.ItemIndicator>
128
+ <Check className="h-4 w-4" />
129
+ </SelectPrimitive.ItemIndicator>
130
+ </span>
131
+
132
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
133
+ </SelectPrimitive.Item>
134
+ ))
135
+ SelectItem.displayName = SelectPrimitive.Item.displayName
136
+
137
+ const SelectSeparator = React.forwardRef<
138
+ React.ElementRef<typeof SelectPrimitive.Separator>,
139
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
140
+ >(({ className, ...props }, ref) => (
141
+ <SelectPrimitive.Separator
142
+ ref={ref}
143
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
144
+ {...props}
145
+ />
146
+ ))
147
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName
148
+
149
+ export {
150
+ Select,
151
+ SelectGroup,
152
+ SelectValue,
153
+ SelectTrigger,
154
+ SelectContent,
155
+ SelectLabel,
156
+ SelectItem,
157
+ SelectSeparator,
158
+ SelectScrollUpButton,
159
+ SelectScrollDownButton,
160
+ }