Skip to content

Commit e14bb91

Browse files
feat(typeform): add Typeform integration ref (#207)
* feat(typeform): add Typeform integration ref #106 * fix(typeform): icon --------- Co-authored-by: rodrick-mpofu <rodrickmpofu@gmail.com>
1 parent eed8f16 commit e14bb91

File tree

12 files changed

+1681
-0
lines changed

12 files changed

+1681
-0
lines changed

sim/blocks/blocks/typeform.ts

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import { TypeformIcon } from '@/components/icons'
2+
import { ToolResponse } from '@/tools/types'
3+
import { BlockConfig } from '../types'
4+
5+
interface TypeformResponse extends ToolResponse {
6+
output: {
7+
total_items: number
8+
page_count: number
9+
items: Array<{
10+
landing_id: string
11+
token: string
12+
landed_at: string
13+
submitted_at: string
14+
metadata: {
15+
user_agent: string
16+
platform: string
17+
referer: string
18+
network_id: string
19+
browser: string
20+
}
21+
answers: Array<{
22+
field: {
23+
id: string
24+
type: string
25+
ref: string
26+
}
27+
type: string
28+
[key: string]: any // For different answer types (text, boolean, number, etc.)
29+
}>
30+
hidden: Record<string, any>
31+
calculated: {
32+
score: number
33+
}
34+
variables: Array<{
35+
key: string
36+
type: string
37+
[key: string]: any // For different variable types
38+
}>
39+
}>
40+
} | {
41+
fileUrl: string
42+
contentType: string
43+
filename: string
44+
} | {
45+
fields: Array<{
46+
dropoffs: number
47+
id: string
48+
label: string
49+
ref: string
50+
title: string
51+
type: string
52+
views: number
53+
}>
54+
form: {
55+
platforms: Array<{
56+
average_time: number
57+
completion_rate: number
58+
platform: string
59+
responses_count: number
60+
total_visits: number
61+
unique_visits: number
62+
}>
63+
summary: {
64+
average_time: number
65+
completion_rate: number
66+
responses_count: number
67+
total_visits: number
68+
unique_visits: number
69+
}
70+
}
71+
}
72+
}
73+
74+
export const TypeformBlock: BlockConfig<TypeformResponse> = {
75+
type: 'typeform',
76+
name: 'Typeform',
77+
description: 'Interact with Typeform',
78+
longDescription:
79+
'Access and retrieve responses from your Typeform forms. Integrate form submissions data into your workflow for analysis, storage, or processing.',
80+
category: 'tools',
81+
bgColor: '#262627', // Typeform brand color
82+
icon: TypeformIcon,
83+
subBlocks: [
84+
{
85+
id: 'operation',
86+
title: 'Operation',
87+
type: 'dropdown',
88+
layout: 'full',
89+
options: [
90+
{ label: 'Retrieve Responses', id: 'typeform_responses' },
91+
{ label: 'Download File', id: 'typeform_files' },
92+
{ label: 'Form Insights', id: 'typeform_insights' },
93+
],
94+
value: () => 'typeform_responses',
95+
},
96+
{
97+
id: 'formId',
98+
title: 'Form ID',
99+
type: 'short-input',
100+
layout: 'full',
101+
placeholder: 'Enter your Typeform form ID',
102+
},
103+
{
104+
id: 'apiKey',
105+
title: 'Personal Access Token',
106+
type: 'short-input',
107+
layout: 'full',
108+
placeholder: 'Enter your Typeform personal access token',
109+
password: true,
110+
},
111+
// Response operation fields
112+
{
113+
id: 'pageSize',
114+
title: 'Page Size',
115+
type: 'short-input',
116+
layout: 'half',
117+
placeholder: 'Number of responses per page (default: 25)',
118+
condition: { field: 'operation', value: 'typeform_responses' },
119+
},
120+
{
121+
id: 'since',
122+
title: 'Since',
123+
type: 'short-input',
124+
layout: 'half',
125+
placeholder: 'Retrieve responses after this date (ISO format)',
126+
condition: { field: 'operation', value: 'typeform_responses' },
127+
},
128+
{
129+
id: 'until',
130+
title: 'Until',
131+
type: 'short-input',
132+
layout: 'half',
133+
placeholder: 'Retrieve responses before this date (ISO format)',
134+
condition: { field: 'operation', value: 'typeform_responses' },
135+
},
136+
{
137+
id: 'completed',
138+
title: 'Completed',
139+
type: 'dropdown',
140+
layout: 'half',
141+
options: [
142+
{ label: 'All Responses', id: 'all' },
143+
{ label: 'Only Completed', id: 'true' },
144+
{ label: 'Only Incomplete', id: 'false' },
145+
],
146+
condition: { field: 'operation', value: 'typeform_responses' },
147+
},
148+
// File operation fields
149+
{
150+
id: 'responseId',
151+
title: 'Response ID',
152+
type: 'short-input',
153+
layout: 'full',
154+
placeholder: 'Enter response ID (token)',
155+
condition: { field: 'operation', value: 'typeform_files' },
156+
},
157+
{
158+
id: 'fieldId',
159+
title: 'Field ID',
160+
type: 'short-input',
161+
layout: 'half',
162+
placeholder: 'Enter file upload field ID',
163+
condition: { field: 'operation', value: 'typeform_files' },
164+
},
165+
{
166+
id: 'filename',
167+
title: 'Filename',
168+
type: 'short-input',
169+
layout: 'half',
170+
placeholder: 'Enter exact filename of the file',
171+
condition: { field: 'operation', value: 'typeform_files' },
172+
},
173+
{
174+
id: 'inline',
175+
title: 'Inline Display',
176+
type: 'switch',
177+
layout: 'half',
178+
condition: { field: 'operation', value: 'typeform_files' },
179+
},
180+
],
181+
tools: {
182+
access: ['typeform_responses', 'typeform_files', 'typeform_insights'],
183+
config: {
184+
tool: (params) => {
185+
switch (params.operation) {
186+
case 'typeform_responses':
187+
return 'typeform_responses'
188+
case 'typeform_files':
189+
return 'typeform_files'
190+
case 'typeform_insights':
191+
return 'typeform_insights'
192+
default:
193+
return 'typeform_responses'
194+
}
195+
},
196+
},
197+
},
198+
inputs: {
199+
operation: { type: 'string', required: true },
200+
formId: { type: 'string', required: true },
201+
apiKey: { type: 'string', required: true },
202+
// Response operation params
203+
pageSize: { type: 'number', required: false },
204+
since: { type: 'string', required: false },
205+
until: { type: 'string', required: false },
206+
completed: { type: 'string', required: false },
207+
// File operation params
208+
responseId: { type: 'string', required: false },
209+
fieldId: { type: 'string', required: false },
210+
filename: { type: 'string', required: false },
211+
inline: { type: 'boolean', required: false },
212+
},
213+
outputs: {
214+
response: {
215+
type: {
216+
total_items: 'number',
217+
page_count: 'number',
218+
items: 'json',
219+
},
220+
dependsOn: {
221+
subBlockId: 'operation',
222+
condition: {
223+
whenEmpty: {
224+
total_items: 'number',
225+
page_count: 'number',
226+
items: 'json',
227+
},
228+
whenFilled: 'json',
229+
},
230+
},
231+
},
232+
},
233+
}

sim/blocks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { StarterBlock } from './blocks/starter'
2727
import { SupabaseBlock } from './blocks/supabase'
2828
import { TavilyBlock } from './blocks/tavily'
2929
import { TranslateBlock } from './blocks/translate'
30+
import { TypeformBlock } from './blocks/typeform'
3031
import { VisionBlock } from './blocks/vision'
3132
import { WhatsAppBlock } from './blocks/whatsapp'
3233
import { XBlock } from './blocks/x'
@@ -67,6 +68,7 @@ export {
6768
PerplexityBlock,
6869
ConfluenceBlock,
6970
ImageGeneratorBlock,
71+
TypeformBlock,
7072
}
7173

7274
// Registry of all block configurations, alphabetically sorted
@@ -99,6 +101,7 @@ const blocks: Record<string, BlockConfig> = {
99101
supabase: SupabaseBlock,
100102
tavily: TavilyBlock,
101103
translate: TranslateBlock,
104+
typeform: TypeformBlock,
102105
vision: VisionBlock,
103106
whatsapp: WhatsAppBlock,
104107
x: XBlock,

sim/components/icons.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,3 +1756,21 @@ export function ImageIcon(props: SVGProps<SVGSVGElement>) {
17561756
</svg>
17571757
)
17581758
}
1759+
1760+
export function TypeformIcon(props: SVGProps<SVGSVGElement>) {
1761+
return (
1762+
<svg
1763+
{...props}
1764+
width="24"
1765+
height="24"
1766+
viewBox="0 0 24 24"
1767+
fill="none"
1768+
xmlns="http://www.w3.org/2000/svg"
1769+
>
1770+
<g transform="translate(1, 4)">
1771+
<rect x="0" y="0" width="5" height="16" rx="2.5" fill="currentColor" />
1772+
<rect x="8" y="0" width="14" height="16" rx="4" fill="currentColor" />
1773+
</g>
1774+
</svg>
1775+
)
1776+
}

sim/tools/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { sheetsReadTool, sheetsUpdateTool, sheetsWriteTool } from './sheets'
3636
import { slackMessageTool } from './slack/message'
3737
import { supabaseInsertTool, supabaseQueryTool, supabaseUpdateTool } from './supabase'
3838
import { tavilyExtractTool, tavilySearchTool } from './tavily'
39+
import { typeformFilesTool, typeformInsightsTool, typeformResponsesTool } from './typeform'
3940
import { OAuthTokenPayload, ToolConfig, ToolResponse } from './types'
4041
import { formatRequestParams, validateToolRequest } from './utils'
4142
import { visionTool } from './vision/vision'
@@ -65,6 +66,9 @@ export const tools: Record<string, ToolConfig> = {
6566
supabase_query: supabaseQueryTool,
6667
supabase_insert: supabaseInsertTool,
6768
supabase_update: supabaseUpdateTool,
69+
typeform_responses: typeformResponsesTool,
70+
typeform_files: typeformFilesTool,
71+
typeform_insights: typeformInsightsTool,
6872
youtube_search: youtubeSearchTool,
6973
notion_read: notionReadTool,
7074
notion_write: notionWriteTool,

0 commit comments

Comments
 (0)