diff --git a/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx b/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx new file mode 100644 index 000000000..3514452f8 --- /dev/null +++ b/app/w/[id]/components/workflow-block/components/sub-block/components/checkbox-list.tsx @@ -0,0 +1,81 @@ +import { Label } from '@/components/ui/label' +import { Checkbox } from '@/components/ui/checkbox' +import { useSubBlockValue } from '../hooks/use-sub-block-value' +import { cn } from '@/lib/utils' +import { useEffect } from 'react' + +interface CheckboxListProps { + blockId: string + subBlockId: string + title: string + options: { label: string; id: string }[] + layout?: 'full' | 'half' +} + +export function CheckboxList({ + blockId, + subBlockId, + title, + options, + layout, +}: CheckboxListProps) { + const [value, setValue] = useSubBlockValue(blockId, subBlockId) + + // Initialize values with all options set to false by default + const values = (() => { + const defaultValues = options.reduce( + (acc, option) => ({ + ...acc, + [option.id]: false, + }), + {} + ) + + return { + ...defaultValues, + ...(typeof value === 'object' && value !== null ? value : {}), + } + })() as Record + + // Move initialization to useEffect + useEffect(() => { + if (value === null) { + setValue(values) + } + }, [value, setValue, values]) + + const handleCheckedChange = (id: string, checked: boolean) => { + setValue({ + ...values, + [id]: checked, + }) + } + + return ( +
+ {options.map((option) => ( +
+ + handleCheckedChange(option.id, checked as boolean) + } + /> + +
+ ))} +
+ ) +} diff --git a/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx b/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx index 181a7d726..eea19c7af 100644 --- a/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx +++ b/app/w/[id]/components/workflow-block/components/sub-block/sub-block.tsx @@ -8,6 +8,7 @@ import { Table } from './components/table' import { Code } from './components/code' import { Switch } from './components/switch' import { ToolInput } from './components/tool-input' +import { CheckboxList } from './components/checkbox-list' interface SubBlockProps { blockId: string @@ -53,7 +54,7 @@ export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) { ) @@ -95,6 +96,16 @@ export function SubBlock({ blockId, config, isConnecting }: SubBlockProps) { ) case 'tool-input': return + case 'checkbox-list': + return ( + + ) default: return null } diff --git a/blocks/blocks/crewai.ts b/blocks/blocks/crewai.ts index b8b6aad56..2b149220e 100644 --- a/blocks/blocks/crewai.ts +++ b/blocks/blocks/crewai.ts @@ -49,6 +49,13 @@ export const CrewAIVisionBlock: BlockConfig = { 'claude-3-sonnet-20240229' ] }, + { + id: 'prompt', + title: 'Prompt', + type: 'long-input', + layout: 'full', + placeholder: 'Enter prompt for image analysis (optional)' + }, { id: 'apiKey', title: 'API Key', @@ -56,14 +63,7 @@ export const CrewAIVisionBlock: BlockConfig = { layout: 'full', placeholder: 'Enter your API key', password: true - }, - { - id: 'prompt', - title: 'Custom Prompt', - type: 'long-input', - layout: 'full', - placeholder: 'Enter custom prompt for image analysis (optional)' - } + }, ] } } \ No newline at end of file diff --git a/blocks/blocks/firecrawl.ts b/blocks/blocks/firecrawl.ts index 8f5525def..fcb99556f 100644 --- a/blocks/blocks/firecrawl.ts +++ b/blocks/blocks/firecrawl.ts @@ -30,6 +30,19 @@ export const FirecrawlScrapeBlock: BlockConfig = { } }, subBlocks: [ + { + id: 'url', + title: 'Website URL', + type: 'short-input', + layout: 'full', + placeholder: 'Enter the webpage URL to scrape' + }, + { + id: 'onlyMainContent', + title: 'Only Main Content', + type: 'switch', + layout: 'half' + }, { id: 'apiKey', title: 'API Key', @@ -38,19 +51,6 @@ export const FirecrawlScrapeBlock: BlockConfig = { placeholder: 'Enter your Firecrawl API key', password: true }, - { - id: 'url', - title: 'Website URL', - type: 'short-input', - layout: 'full', - placeholder: 'Enter the webpage URL to scrape' - }, - { - id: 'onlyMainContent', - title: 'Only Main Content', - type: 'switch', - layout: 'half' - } ] } } diff --git a/blocks/blocks/jina.ts b/blocks/blocks/jina.ts index ed21dae28..8f8e84191 100644 --- a/blocks/blocks/jina.ts +++ b/blocks/blocks/jina.ts @@ -38,28 +38,16 @@ export const JinaBlock: BlockConfig = { placeholder: 'Enter URL to read', }, { - id: 'useReaderLMv2', - title: 'Use ReaderLM v2', - type: 'switch', - layout: 'half', - }, - { - id: 'removeImages', - title: 'Remove Images', - type: 'switch', - layout: 'half', - }, - { - id: 'gatherLinks', - title: 'Gather Links', - type: 'switch', - layout: 'half', - }, - { - id: 'jsonResponse', - title: 'JSON Response', - type: 'switch', + id: 'options', + title: 'Options', + type: 'checkbox-list', layout: 'half', + options: [ + { label: 'Use ReaderLM v2', id: 'useReaderLMv2' }, + { label: 'Remove Images', id: 'removeImages' }, + { label: 'Gather Links', id: 'gatherLinks' }, + { label: 'JSON Response', id: 'jsonResponse' } + ] }, { id: 'apiKey', diff --git a/blocks/blocks/slack.ts b/blocks/blocks/slack.ts index aa85b90fe..47f3eca2a 100644 --- a/blocks/blocks/slack.ts +++ b/blocks/blocks/slack.ts @@ -29,15 +29,6 @@ export const SlackMessageBlock: BlockConfig = { } }, subBlocks: [ - { - id: 'apiKey', - title: 'OAuth Token', - type: 'short-input', - layout: 'full', - placeholder: 'Enter your Slack OAuth token', - password: true, - connectionDroppable: false - }, { id: 'channel', title: 'Channel', @@ -51,6 +42,15 @@ export const SlackMessageBlock: BlockConfig = { type: 'long-input', layout: 'full', placeholder: 'Enter your alert message' + }, + { + id: 'apiKey', + title: 'OAuth Token', + type: 'short-input', + layout: 'full', + placeholder: 'Enter your Slack OAuth token', + password: true, + connectionDroppable: false } ] } diff --git a/blocks/types.ts b/blocks/types.ts index e5d0e1f53..4f951c479 100644 --- a/blocks/types.ts +++ b/blocks/types.ts @@ -15,7 +15,7 @@ export type BlockOutput = export type ParamType = 'string' | 'number' | 'boolean' | 'json' -export type SubBlockType = 'short-input' | 'long-input' | 'dropdown' | 'slider' | 'table' | 'code' | 'switch' | 'tool-input' +export type SubBlockType = 'short-input' | 'long-input' | 'dropdown' | 'slider' | 'table' | 'code' | 'switch' | 'tool-input' | 'checkbox-list' export type SubBlockLayout = 'full' | 'half' export interface ParamConfig { @@ -28,7 +28,7 @@ export interface SubBlockConfig { title: string type: SubBlockType layout?: SubBlockLayout - options?: string[] + options?: string[] | { label: string; id: string }[] min?: number max?: number columns?: string[] diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx new file mode 100644 index 000000000..df61a1388 --- /dev/null +++ b/components/ui/checkbox.tsx @@ -0,0 +1,30 @@ +"use client" + +import * as React from "react" +import * as CheckboxPrimitive from "@radix-ui/react-checkbox" +import { Check } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)) +Checkbox.displayName = CheckboxPrimitive.Root.displayName + +export { Checkbox } diff --git a/package-lock.json b/package-lock.json index 6ad659296..ae0605591 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@radix-ui/react-alert-dialog": "^1.1.5", + "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-dialog": "^1.1.5", "@radix-ui/react-dropdown-menu": "^2.1.4", "@radix-ui/react-label": "^2.1.1", @@ -2050,6 +2051,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.3.tgz", + "integrity": "sha512-HD7/ocp8f1B3e6OHygH0n7ZKjONkhciy1Nh0yuBgObqThc3oyx+vuMfFHKAknXRHHWVE9XvXStxJFyjUmB8PIw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", diff --git a/package.json b/package.json index a61c18b7a..9f9a1f30b 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@radix-ui/react-alert-dialog": "^1.1.5", + "@radix-ui/react-checkbox": "^1.1.3", "@radix-ui/react-dialog": "^1.1.5", "@radix-ui/react-dropdown-menu": "^2.1.4", "@radix-ui/react-label": "^2.1.1",