diff --git a/apps/builder/components/board/graph/BlockNode/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx b/apps/builder/components/board/graph/BlockNode/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx index 1e48f46731..506bddd6b5 100644 --- a/apps/builder/components/board/graph/BlockNode/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx +++ b/apps/builder/components/board/graph/BlockNode/StepNode/SettingsPopoverContent/bodies/WebhookSettings/WebhookSettings.tsx @@ -159,6 +159,7 @@ export const WebhookSettings = ({ @@ -181,7 +182,9 @@ export const WebhookSettings = ({ - {testResponse && } + {testResponse && ( + + )} {(testResponse || options?.responseVariableMapping) && ( diff --git a/apps/builder/components/shared/CodeEditor.tsx b/apps/builder/components/shared/CodeEditor.tsx index 0145de8202..7d95292f2d 100644 --- a/apps/builder/components/shared/CodeEditor.tsx +++ b/apps/builder/components/shared/CodeEditor.tsx @@ -1,15 +1,18 @@ import { Box, BoxProps } from '@chakra-ui/react' import { EditorState, EditorView, basicSetup } from '@codemirror/basic-setup' import { json } from '@codemirror/lang-json' +import { css } from '@codemirror/lang-css' import { useEffect, useRef } from 'react' type Props = { value: string + lang: 'css' | 'json' onChange?: (value: string) => void isReadOnly?: boolean } export const CodeEditor = ({ value, + lang, onChange, isReadOnly = false, ...props @@ -31,14 +34,15 @@ export const CodeEditor = ({ if (update.docChanged && onChange) onChange(update.state.doc.toJSON().join(' ')) }) + const extensions = [ + updateListenerExtension, + basicSetup, + EditorState.readOnly.of(isReadOnly), + ] + extensions.push(lang === 'json' ? json() : css()) const editor = new EditorView({ state: EditorState.create({ - extensions: [ - updateListenerExtension, - basicSetup, - json(), - EditorState.readOnly.of(isReadOnly), - ], + extensions, }), parent: editorContainer.current, }) diff --git a/apps/builder/components/theme/CustomCssSettings/CustomCssSettings.tsx b/apps/builder/components/theme/CustomCssSettings/CustomCssSettings.tsx new file mode 100644 index 0000000000..f876fee781 --- /dev/null +++ b/apps/builder/components/theme/CustomCssSettings/CustomCssSettings.tsx @@ -0,0 +1,17 @@ +import { CodeEditor } from 'components/shared/CodeEditor' +import React from 'react' + +type Props = { + customCss?: string + onCustomCssChange: (css: string) => void +} + +export const CustomCssSettings = ({ customCss, onCustomCssChange }: Props) => { + return ( + + ) +} diff --git a/apps/builder/components/theme/SideMenu.tsx b/apps/builder/components/theme/SideMenu.tsx index 71e71cdcd1..8c4eee3f0c 100644 --- a/apps/builder/components/theme/SideMenu.tsx +++ b/apps/builder/components/theme/SideMenu.tsx @@ -8,12 +8,13 @@ import { HStack, Stack, } from '@chakra-ui/react' -import { ChatIcon, CodeIcon, LayoutIcon, PencilIcon } from 'assets/icons' +import { ChatIcon, CodeIcon, PencilIcon } from 'assets/icons' import { headerHeight } from 'components/shared/TypebotHeader' import { useTypebot } from 'contexts/TypebotContext' import { ChatTheme, GeneralTheme } from 'models' import React from 'react' import { ChatThemeSettings } from './ChatSettings' +import { CustomCssSettings } from './CustomCssSettings/CustomCssSettings' import { GeneralSettings } from './GeneralSettings' export const SideMenu = () => { @@ -25,6 +26,9 @@ export const SideMenu = () => { const handleGeneralThemeChange = (general: GeneralTheme) => updateTypebot({ theme: { ...typebot?.theme, general } }) + const handleCustomCssChange = (customCss: string) => + updateTypebot({ theme: { ...typebot?.theme, customCss } }) + return ( { /> - - - - - Layout - - - - - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. - - @@ -94,10 +83,10 @@ export const SideMenu = () => { - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim - ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut - aliquip ex ea commodo consequat. + diff --git a/apps/builder/cypress/tests/theme/customCss.ts b/apps/builder/cypress/tests/theme/customCss.ts new file mode 100644 index 0000000000..2fb1da2d4d --- /dev/null +++ b/apps/builder/cypress/tests/theme/customCss.ts @@ -0,0 +1,26 @@ +import { getIframeBody } from 'cypress/support' + +describe('Custom CSS settings', () => { + beforeEach(() => { + cy.task('seed') + cy.signOut() + }) + + it('should reflect changes in real time', () => { + cy.loadTypebotFixtureInDatabase('typebots/theme/theme.json') + cy.signIn('test2@gmail.com') + cy.visit('/typebots/typebot4/theme') + cy.findByRole('button', { name: 'Custom CSS' }).click() + + cy.findByTestId('code-editor').type( + '.typebot-button {background-color: green}', + { + parseSpecialCharSequences: false, + } + ) + getIframeBody() + .findByTestId('button') + .should('have.css', 'background-color') + .should('eq', 'rgb(0, 128, 0)') + }) +}) diff --git a/apps/builder/package.json b/apps/builder/package.json index 90a536f5ea..54d22bb582 100644 --- a/apps/builder/package.json +++ b/apps/builder/package.json @@ -13,6 +13,7 @@ "@chakra-ui/css-reset": "^1.1.1", "@chakra-ui/react": "^1.7.4", "@codemirror/basic-setup": "^0.19.1", + "@codemirror/lang-css": "^0.19.3", "@codemirror/lang-json": "^0.19.1", "@codemirror/text": "^0.19.6", "@dnd-kit/core": "^4.0.3", diff --git a/packages/bot-engine/src/components/TypebotViewer.tsx b/packages/bot-engine/src/components/TypebotViewer.tsx index 33cf000416..1330c2ede3 100644 --- a/packages/bot-engine/src/components/TypebotViewer.tsx +++ b/packages/bot-engine/src/components/TypebotViewer.tsx @@ -48,6 +48,7 @@ export const TypebotViewer = ({ {phoneNumberInputStyle} {phoneSyle} {style} + {typebot.theme?.customCss} } style={{ width: '100%', height: '100%', border: 'none' }} diff --git a/packages/models/src/typebot/theme.ts b/packages/models/src/typebot/theme.ts index fb027497b5..93c6f25553 100644 --- a/packages/models/src/typebot/theme.ts +++ b/packages/models/src/typebot/theme.ts @@ -1,6 +1,7 @@ export type Theme = { general?: GeneralTheme chat?: ChatTheme + customCss?: string } export type GeneralTheme = { diff --git a/yarn.lock b/yarn.lock index e8a5e8f917..42aa11a5e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -811,7 +811,7 @@ "@codemirror/state" "^0.19.0" "@codemirror/view" "^0.19.23" -"@codemirror/highlight@^0.19.0": +"@codemirror/highlight@^0.19.0", "@codemirror/highlight@^0.19.6": version "0.19.7" resolved "https://registry.yarnpkg.com/@codemirror/highlight/-/highlight-0.19.7.tgz#91a0c9994c759f5f153861e3aae74ff9e7c7c35b" integrity sha512-3W32hBCY0pbbv/xidismw+RDMKuIag+fo4kZIbD7WoRj+Ttcaxjf+vP6RttRHXLaaqbWh031lTeON8kMlDhMYw== @@ -831,6 +831,17 @@ "@codemirror/state" "^0.19.2" "@codemirror/view" "^0.19.0" +"@codemirror/lang-css@^0.19.3": + version "0.19.3" + resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-0.19.3.tgz#7a17adf78c6fcdab4ad5ee4e360631c41e949e4a" + integrity sha512-tyCUJR42/UlfOPLb94/p7dN+IPsYSIzHbAHP2KQHANj0I+Orqp+IyIOS++M8TuCX4zkWh9dvi8s92yy/Tn8Ifg== + dependencies: + "@codemirror/autocomplete" "^0.19.0" + "@codemirror/highlight" "^0.19.6" + "@codemirror/language" "^0.19.0" + "@codemirror/state" "^0.19.0" + "@lezer/css" "^0.15.2" + "@codemirror/lang-json@^0.19.1": version "0.19.1" resolved "https://registry.yarnpkg.com/@codemirror/lang-json/-/lang-json-0.19.1.tgz#616588d1422529965243c10af6c44ad0b9134fb0" @@ -1338,6 +1349,13 @@ resolved "https://registry.yarnpkg.com/@lezer/common/-/common-0.15.11.tgz#965b5067036305f12e8a3efc344076850be1d3a8" integrity sha512-vv0nSdIaVCRcJ8rPuDdsrNVfBOYe/4Szr/LhF929XyDmBndLDuWiCCHooGlGlJfzELyO608AyDhVsuX/ZG36NA== +"@lezer/css@^0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@lezer/css/-/css-0.15.2.tgz#e96995da67df90bb4b191aaa8a486349cca5d8e7" + integrity sha512-tnMOMZY0Zs6JQeVjqfmREYMV0GnmZR1NitndLWioZMD6mA7VQF/PPKPmJX1f+ZgVZQc5Am0df9mX3aiJnNJlKQ== + dependencies: + "@lezer/lr" "^0.15.0" + "@lezer/json@^0.15.0": version "0.15.0" resolved "https://registry.yarnpkg.com/@lezer/json/-/json-0.15.0.tgz#b96c1161eb8514e05f4eaaec95c68376e76e539f"