mirror of
https://github.com/simstudioai/sim.git
synced 2026-01-09 15:07:55 -05:00
Switched from basic/advanced to blocks/tools and added toolbar tabs dynamic width calculation
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -39,3 +39,6 @@ yarn-error.log*
|
|||||||
# typescript
|
# typescript
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
next-env.d.ts
|
next-env.d.ts
|
||||||
|
|
||||||
|
# cursorrules
|
||||||
|
.cursorrules
|
||||||
|
|||||||
@@ -1,29 +1,55 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
|
import { useRef, useEffect, useState } from 'react'
|
||||||
|
|
||||||
interface ToolbarTabsProps {
|
interface ToolbarTabsProps {
|
||||||
activeTab: 'basic' | 'advanced'
|
activeTab: 'blocks' | 'tools'
|
||||||
onTabChange: (tab: 'basic' | 'advanced') => void
|
onTabChange: (tab: 'blocks' | 'tools') => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
||||||
|
const blocksRef = useRef<HTMLButtonElement>(null)
|
||||||
|
const toolsRef = useRef<HTMLButtonElement>(null)
|
||||||
|
const [underlineStyle, setUnderlineStyle] = useState({
|
||||||
|
width: 0,
|
||||||
|
transform: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const activeRef = activeTab === 'blocks' ? blocksRef : toolsRef
|
||||||
|
if (activeRef.current) {
|
||||||
|
const rect = activeRef.current.getBoundingClientRect()
|
||||||
|
const parentRect =
|
||||||
|
activeRef.current.parentElement?.getBoundingClientRect()
|
||||||
|
const offsetLeft = parentRect ? rect.left - parentRect.left : 0
|
||||||
|
|
||||||
|
setUnderlineStyle({
|
||||||
|
width: rect.width,
|
||||||
|
transform: `translateX(${offsetLeft}px)`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [activeTab])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative pt-5">
|
<div className="relative pt-5">
|
||||||
<div className="flex gap-8 px-6">
|
<div className="flex gap-8 px-6">
|
||||||
<button
|
<button
|
||||||
onClick={() => onTabChange('basic')}
|
ref={blocksRef}
|
||||||
|
onClick={() => onTabChange('blocks')}
|
||||||
className={`text-sm font-medium transition-colors hover:text-black ${
|
className={`text-sm font-medium transition-colors hover:text-black ${
|
||||||
activeTab === 'basic' ? 'text-black' : 'text-muted-foreground'
|
activeTab === 'blocks' ? 'text-black' : 'text-muted-foreground'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Basic
|
Blocks
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => onTabChange('advanced')}
|
ref={toolsRef}
|
||||||
|
onClick={() => onTabChange('tools')}
|
||||||
className={`text-sm font-medium transition-colors hover:text-black ${
|
className={`text-sm font-medium transition-colors hover:text-black ${
|
||||||
activeTab === 'advanced' ? 'text-black' : 'text-muted-foreground'
|
activeTab === 'tools' ? 'text-black' : 'text-muted-foreground'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Advanced
|
Tools
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -32,10 +58,8 @@ export function ToolbarTabs({ activeTab, onTabChange }: ToolbarTabsProps) {
|
|||||||
<div
|
<div
|
||||||
className="absolute bottom-0 h-[1.5px] bg-black transition-transform duration-200"
|
className="absolute bottom-0 h-[1.5px] bg-black transition-transform duration-200"
|
||||||
style={{
|
style={{
|
||||||
width: activeTab === 'advanced' ? '68px' : '38px',
|
width: `${underlineStyle.width}px`,
|
||||||
transform: `translateX(${
|
transform: underlineStyle.transform,
|
||||||
activeTab === 'advanced' ? '91px' : '23.75px'
|
|
||||||
})`,
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||||
|
|
||||||
export function Toolbar() {
|
export function Toolbar() {
|
||||||
const [activeTab, setActiveTab] = useState<BlockCategory>('basic')
|
const [activeTab, setActiveTab] = useState<BlockCategory>('blocks')
|
||||||
const [searchQuery, setSearchQuery] = useState('')
|
const [searchQuery, setSearchQuery] = useState('')
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false)
|
const [isCollapsed, setIsCollapsed] = useState(false)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export const AgentBlock: BlockConfig<ChatResponse> = {
|
|||||||
description: 'Use any LLM',
|
description: 'Use any LLM',
|
||||||
bgColor: '#7F2FFF',
|
bgColor: '#7F2FFF',
|
||||||
icon: AgentIcon,
|
icon: AgentIcon,
|
||||||
category: 'basic',
|
category: 'blocks',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['openai.chat', 'anthropic.chat', 'google.chat', 'xai.chat', 'deepseek.chat', 'deepseek.reasoner'],
|
access: ['openai.chat', 'anthropic.chat', 'google.chat', 'xai.chat', 'deepseek.chat', 'deepseek.reasoner'],
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const ApiBlock: BlockConfig<RequestResponse> = {
|
|||||||
description: 'Use any API',
|
description: 'Use any API',
|
||||||
bgColor: '#2F55FF',
|
bgColor: '#2F55FF',
|
||||||
icon: ApiIcon,
|
icon: ApiIcon,
|
||||||
category: 'basic',
|
category: 'blocks',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['http.request']
|
access: ['http.request']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const CrewAIVisionBlock: BlockConfig<VisionResponse> = {
|
|||||||
description: 'Analyze images with vision models',
|
description: 'Analyze images with vision models',
|
||||||
bgColor: '#FF5A50',
|
bgColor: '#FF5A50',
|
||||||
icon: CrewAIIcon,
|
icon: CrewAIIcon,
|
||||||
category: 'advanced'
|
category: 'tools'
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['crewai.vision']
|
access: ['crewai.vision']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const FirecrawlScrapeBlock: BlockConfig<ScrapeResponse> = {
|
|||||||
description: 'Scrape website content',
|
description: 'Scrape website content',
|
||||||
bgColor: '#FF613A',
|
bgColor: '#FF613A',
|
||||||
icon: FirecrawlIcon,
|
icon: FirecrawlIcon,
|
||||||
category: 'advanced'
|
category: 'tools'
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['firecrawl.scrape']
|
access: ['firecrawl.scrape']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const FunctionBlock: BlockConfig<CodeExecutionOutput> = {
|
|||||||
description: 'Add custom logic',
|
description: 'Add custom logic',
|
||||||
bgColor: '#FF8D2F',
|
bgColor: '#FF8D2F',
|
||||||
icon: CodeIcon,
|
icon: CodeIcon,
|
||||||
category: 'advanced',
|
category: 'blocks',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['function.execute']
|
access: ['function.execute']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const GitHubBlock: BlockConfig<RepoInfoResponse> = {
|
|||||||
description: 'Fetch GitHub repository information and metadata',
|
description: 'Fetch GitHub repository information and metadata',
|
||||||
bgColor: '#ffffff',
|
bgColor: '#ffffff',
|
||||||
icon: GithubIcon,
|
icon: GithubIcon,
|
||||||
category: 'advanced',
|
category: 'tools',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['github.repoinfo']
|
access: ['github.repoinfo']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const JinaBlock: BlockConfig<ReadUrlResponse> = {
|
|||||||
description: 'Convert website content into text',
|
description: 'Convert website content into text',
|
||||||
bgColor: '#333333',
|
bgColor: '#333333',
|
||||||
icon: JinaAIIcon,
|
icon: JinaAIIcon,
|
||||||
category: 'advanced',
|
category: 'tools',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['jina.readurl']
|
access: ['jina.readurl']
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const SlackMessageBlock: BlockConfig<SlackMessageResponse> = {
|
|||||||
description: 'Send a message to Slack',
|
description: 'Send a message to Slack',
|
||||||
bgColor: '#611f69',
|
bgColor: '#611f69',
|
||||||
icon: SlackIcon,
|
icon: SlackIcon,
|
||||||
category: 'advanced'
|
category: 'tools'
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['slack.message']
|
access: ['slack.message']
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const TranslateBlock: BlockConfig<ChatResponse> = {
|
|||||||
description: 'Translate text to any language',
|
description: 'Translate text to any language',
|
||||||
bgColor: '#FF4B4B',
|
bgColor: '#FF4B4B',
|
||||||
icon: TranslateIcon,
|
icon: TranslateIcon,
|
||||||
category: 'advanced',
|
category: 'tools',
|
||||||
},
|
},
|
||||||
tools: {
|
tools: {
|
||||||
access: ['openai.chat', 'anthropic.chat', 'google.chat'],
|
access: ['openai.chat', 'anthropic.chat', 'google.chat'],
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export const getBlock = (type: string): BlockConfig | undefined =>
|
|||||||
blocks[type]
|
blocks[type]
|
||||||
|
|
||||||
|
|
||||||
export const getBlocksByCategory = (category: 'basic' | 'advanced'): BlockConfig[] =>
|
export const getBlocksByCategory = (category: 'blocks' | 'tools'): BlockConfig[] =>
|
||||||
Object.values(blocks).filter(block => block.toolbar.category === category)
|
Object.values(blocks).filter(block => block.toolbar.category === category)
|
||||||
|
|
||||||
export const getAllBlockTypes = (): string[] =>
|
export const getAllBlockTypes = (): string[] =>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ToolResponse } from '@/tools/types'
|
|||||||
import { ExtractToolOutput, ToolOutputToValueType } from './utils'
|
import { ExtractToolOutput, ToolOutputToValueType } from './utils'
|
||||||
|
|
||||||
export type BlockIcon = (props: SVGProps<SVGSVGElement>) => JSX.Element
|
export type BlockIcon = (props: SVGProps<SVGSVGElement>) => JSX.Element
|
||||||
export type BlockCategory = 'basic' | 'advanced'
|
export type BlockCategory = 'blocks' | 'tools'
|
||||||
|
|
||||||
export type PrimitiveValueType = 'string' | 'number' | 'json' | 'boolean' | 'any'
|
export type PrimitiveValueType = 'string' | 'number' | 'json' | 'boolean' | 'any'
|
||||||
export type ValueType = PrimitiveValueType | Record<string, PrimitiveValueType>
|
export type ValueType = PrimitiveValueType | Record<string, PrimitiveValueType>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ describe('Serializer', () => {
|
|||||||
toolbar: {
|
toolbar: {
|
||||||
title: 'Agent Block',
|
title: 'Agent Block',
|
||||||
description: 'Use any LLM',
|
description: 'Use any LLM',
|
||||||
category: 'basic',
|
category: 'blocks',
|
||||||
bgColor: '#7F2FFF'
|
bgColor: '#7F2FFF'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ describe('Serializer', () => {
|
|||||||
toolbar: {
|
toolbar: {
|
||||||
title: 'API Block',
|
title: 'API Block',
|
||||||
description: 'Make HTTP requests',
|
description: 'Make HTTP requests',
|
||||||
category: 'basic',
|
category: '',
|
||||||
bgColor: '#00FF00'
|
bgColor: '#00FF00'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ describe('Serializer', () => {
|
|||||||
metadata: {
|
metadata: {
|
||||||
title: 'Agent Block',
|
title: 'Agent Block',
|
||||||
description: 'Use any LLM',
|
description: 'Use any LLM',
|
||||||
category: 'basic',
|
category: 'blocks',
|
||||||
color: '#7F2FFF',
|
color: '#7F2FFF',
|
||||||
type: 'agent'
|
type: 'agent'
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user