Introducing The Forge (#1072)

The Forge allows anyone to easily create their own Typebot Block.

Closes #380
This commit is contained in:
Baptiste Arnaud
2023-12-13 10:22:02 +01:00
committed by GitHub
parent c373108b55
commit 5e019bbb22
184 changed files with 42659 additions and 37411 deletions

View File

@@ -0,0 +1,126 @@
import { createAction, option } from '@typebot.io/forge'
import { baseOptions } from '../baseOptions'
import { defaultBaseUrl } from '../constants'
export const bookEvent = createAction({
name: 'Book event',
baseOptions,
options: option.object({
link: option.string.layout({
label: 'Event link',
placeholder: 'https://cal.com/...',
}),
layout: option
.enum(['Month', 'Weekly', 'Columns'])
.layout({ label: 'Layout:', defaultValue: 'Month', direction: 'row' }),
name: option.string.layout({
accordion: 'Prefill information',
label: 'Name',
placeholder: 'John Doe',
}),
email: option.string.layout({
accordion: 'Prefill information',
label: 'Email',
placeholder: 'johndoe@gmail.com',
}),
saveBookedDateInVariableId: option.string.layout({
label: 'Save booked date',
input: 'variableDropdown',
}),
}),
getSetVariableIds: ({ saveBookedDateInVariableId }) =>
saveBookedDateInVariableId ? [saveBookedDateInVariableId] : [],
run: {
web: {
displayEmbedBubble: {
waitForEvent: {
getSaveVariableId: ({ saveBookedDateInVariableId }) =>
saveBookedDateInVariableId,
parseFunction: () => {
return {
args: {},
content: `Cal("on", {
action: "bookingSuccessful",
callback: (e) => {
continueFlow(e.detail.data.date)
}
})`,
}
},
},
parseInitFunction: ({ options }) => {
if (!options.link) throw new Error('Missing link')
const baseUrl = options.baseUrl ?? defaultBaseUrl
const link = options.link?.startsWith('http')
? options.link.replace(/http.+:\/\/[^\/]+\//, '')
: options.link
return {
args: {
baseUrl,
link: link ?? '',
name: options.name ?? null,
email: options.email ?? null,
layout: parseLayoutAttr(options.layout),
},
content: `(function (C, A, L) {
let p = function (a, ar) {
a.q.push(ar);
};
let d = C.document;
C.Cal =
C.Cal ||
function () {
let cal = C.Cal;
let ar = arguments;
if (!cal.loaded) {
cal.ns = {};
cal.q = cal.q || [];
d.head.appendChild(d.createElement("script")).src = A;
cal.loaded = true;
}
if (ar[0] === L) {
const api = function () {
p(api, arguments);
};
const namespace = ar[1];
api.q = api.q || [];
typeof namespace === "string"
? (cal.ns[namespace] = api) && p(api, ar)
: p(cal, ar);
return;
}
p(cal, ar);
};
})(window, baseUrl + "/embed/embed.js", "init");
Cal("init", { origin: baseUrl });
Cal("inline", {
elementOrSelector: typebotElement,
calLink: link,
layout,
config: {
name: name ?? undefined,
email: email ?? undefined,
}
});
Cal("ui", {"hideEventTypeDetails":false,layout});`,
}
},
},
},
},
})
const parseLayoutAttr = (
layout?: 'Month' | 'Weekly' | 'Columns'
): 'month_view' | 'week_view' | 'column_view' => {
switch (layout) {
case 'Weekly':
return 'week_view'
case 'Columns':
return 'column_view'
default:
return 'month_view'
}
}

View File

@@ -0,0 +1,11 @@
import { option } from '@typebot.io/forge'
import { defaultBaseUrl } from './constants'
export const baseOptions = option.object({
baseUrl: option.string.layout({
label: 'Base origin',
placeholder: 'https://cal.com',
defaultValue: defaultBaseUrl,
accordion: 'Customize host',
}),
})

View File

@@ -0,0 +1 @@
export const defaultBaseUrl = 'https://app.cal.com'

View File

@@ -0,0 +1,13 @@
import { createBlock } from '@typebot.io/forge'
import { CalComLogo } from './logo'
import { bookEvent } from './actions/bookEvent'
import { baseOptions } from './baseOptions'
export const calCom = createBlock({
id: 'cal-com',
name: 'Cal.com',
tags: ['calendar', 'scheduling', 'meetings'],
LightLogo: CalComLogo,
options: baseOptions,
actions: [bookEvent],
})

View File

@@ -0,0 +1,16 @@
import React from 'react'
export const CalComLogo = (props: React.SVGProps<SVGSVGElement>) => (
<svg viewBox="0 0 31 31" {...props}>
<rect width="31" height="31" rx="3" fill="#2B2F33" />
<path
d="M9.40968 21.7097C5.75369 21.7097 3 18.9373 3 15.5145C3 12.0804 5.61308 9.28516 9.40968 9.28516C11.4251 9.28516 12.8195 9.87843 13.9093 11.2361L12.1516 12.6395C11.4134 11.8864 10.5228 11.5099 9.40968 11.5099C6.9372 11.5099 5.57792 13.324 5.57792 15.5145C5.57792 17.7051 7.06609 19.4849 9.40968 19.4849C10.5111 19.4849 11.4486 19.1085 12.1868 18.3555L13.921 19.8158C12.8782 21.1164 11.4486 21.7097 9.40968 21.7097Z"
fill="white"
/>
<path
d="M21.4917 12.595H23.8586V21.4941H21.4917V20.1935C20.9995 21.1176 20.1792 21.7337 18.6091 21.7337C16.1015 21.7337 14.0977 19.6459 14.0977 17.0788C14.0977 14.5117 16.1015 12.4238 18.6091 12.4238C20.1676 12.4238 20.9995 13.0399 21.4917 13.9641V12.595ZM21.5619 17.0788C21.5619 15.6869 20.5659 14.5345 18.9958 14.5345C17.4841 14.5345 16.4998 15.6982 16.4998 17.0788C16.4998 18.425 17.4841 19.623 18.9958 19.623C20.5542 19.623 21.5619 18.4593 21.5619 17.0788Z"
fill="white"
/>
<path d="M25.5332 9H27.9002V21.4816H25.5332V9Z" fill="white" />
</svg>
)

View File

@@ -0,0 +1,15 @@
{
"name": "@typebot.io/cal-com-block",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"keywords": [],
"license": "ISC",
"devDependencies": {
"@typebot.io/forge": "workspace:*",
"@typebot.io/tsconfig": "workspace:*",
"@types/react": "18.2.15",
"typescript": "5.3.2",
"@typebot.io/lib": "workspace:*"
}
}

View File

@@ -0,0 +1,10 @@
{
"extends": "@typebot.io/tsconfig/base.json",
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"],
"compilerOptions": {
"lib": ["ESNext", "DOM"],
"noEmit": true,
"jsx": "react"
}
}