From 9604dbe78ac47c45215c16a92296e2e69f6705e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Thu, 5 Feb 2026 11:44:02 +0100 Subject: [PATCH] Front components communication between host and remote (#17716) Co-authored-by: Charles Bochet --- .../components/FrontComponentRenderer.tsx | 9 +- .../utils/mockFrontComponent.ts | 111 +- packages/twenty-sdk/package.json | 39 +- packages/twenty-sdk/project.json | 81 +- .../twenty-sdk/scripts/generateBarrels.ts | 559 -------- .../remote-dom/generateRemoteDomElements.ts | 10 +- ...eplace-html-tags-with-remote-components.ts | 2 +- .../build/manifest/manifest-build.ts | 6 +- .../FrontComponentRenderer.stories.tsx | 2 +- .../useFrontComponentExecutionContext.ts | 26 + .../src/front-component/api/index.ts | 3 + .../types/FrontComponentExecutionContext.ts | 3 + .../FrontComponentExecutionContextStore.ts | 6 + .../common}/AllowedHtmlElements.ts | 0 .../common}/AllowedUiComponents.ts | 2 +- .../common}/CommonHtmlEvents.ts | 0 .../common}/EventToReact.ts | 0 .../common}/HtmlCommonProperties.ts | 2 +- .../common}/HtmlTagToRemoteComponent.ts | 0 .../common}/index.ts | 0 .../components/FrontComponentRenderer.tsx | 44 - .../components/FrontComponentRenderer.tsx | 73 ++ .../host/generated/host-component-registry.ts | 405 ++++++ .../host/generated/host-index.ts | 0 .../front-component/{ => renderer}/index.ts | 188 ++- .../components/FrontComponentErrorEffect.tsx | 18 + .../FrontComponentUpdateContextEffect.tsx | 20 + .../components/FrontComponentWorkerEffect.tsx | 16 +- .../FrontComponentExecutionContextStore.ts | 28 + .../remote/generated/remote-components.ts | 1157 +++++++++++++++++ .../remote/generated/remote-elements.ts | 733 +++++++++++ .../remote/generated/remote-index.ts | 0 .../remote/mock/mock-front-component.ts | 0 .../remote/worker/createRemoteWorker.ts | 0 .../remote/worker/remote-worker.ts | 12 +- .../types/FrontComponentExecutionContext.ts | 3 + .../types/HostToWorkerRenderContext.ts | 0 .../{ => renderer}/types/PropertySchema.ts | 0 .../{ => renderer}/types/WorkerExports.ts | 2 + packages/twenty-sdk/src/index.ts | 9 - .../__tests__/define-front-component.spec.ts | 0 .../sdk/common/types/define-entity.type.ts | 6 +- .../define-front-component.ts | 4 +- .../front-component-config.ts | 0 packages/twenty-sdk/src/sdk/index.ts | 13 +- packages/twenty-sdk/src/ui/index.ts | 9 - packages/twenty-sdk/tsconfig.json | 1 - packages/twenty-sdk/vite.config.ts | 29 +- 48 files changed, 2766 insertions(+), 865 deletions(-) delete mode 100644 packages/twenty-sdk/scripts/generateBarrels.ts create mode 100644 packages/twenty-sdk/src/front-component/api/hooks/useFrontComponentExecutionContext.ts create mode 100644 packages/twenty-sdk/src/front-component/api/index.ts create mode 100644 packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContext.ts create mode 100644 packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContextStore.ts rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/AllowedHtmlElements.ts (100%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/AllowedUiComponents.ts (89%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/CommonHtmlEvents.ts (100%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/EventToReact.ts (100%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/HtmlCommonProperties.ts (86%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/HtmlTagToRemoteComponent.ts (100%) rename packages/twenty-sdk/src/{front-component-constants => front-component/common}/index.ts (100%) delete mode 100644 packages/twenty-sdk/src/front-component/host/components/FrontComponentRenderer.tsx create mode 100644 packages/twenty-sdk/src/front-component/renderer/host/components/FrontComponentRenderer.tsx create mode 100644 packages/twenty-sdk/src/front-component/renderer/host/generated/host-component-registry.ts rename packages/twenty-sdk/src/front-component/{ => renderer}/host/generated/host-index.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/index.ts (84%) create mode 100644 packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentErrorEffect.tsx create mode 100644 packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentUpdateContextEffect.tsx rename packages/twenty-sdk/src/front-component/{ => renderer}/remote/components/FrontComponentWorkerEffect.tsx (74%) create mode 100644 packages/twenty-sdk/src/front-component/renderer/remote/context/FrontComponentExecutionContextStore.ts create mode 100644 packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-components.ts create mode 100644 packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-elements.ts rename packages/twenty-sdk/src/front-component/{ => renderer}/remote/generated/remote-index.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/remote/mock/mock-front-component.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/remote/worker/createRemoteWorker.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/remote/worker/remote-worker.ts (71%) create mode 100644 packages/twenty-sdk/src/front-component/renderer/types/FrontComponentExecutionContext.ts rename packages/twenty-sdk/src/front-component/{ => renderer}/types/HostToWorkerRenderContext.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/types/PropertySchema.ts (100%) rename packages/twenty-sdk/src/front-component/{ => renderer}/types/WorkerExports.ts (63%) rename packages/twenty-sdk/src/sdk/{front-components => }/__tests__/define-front-component.spec.ts (100%) rename packages/twenty-sdk/src/sdk/{front-components => }/define-front-component.ts (96%) rename packages/twenty-sdk/src/sdk/{front-components => }/front-component-config.ts (100%) diff --git a/packages/twenty-front/src/modules/front-components/components/FrontComponentRenderer.tsx b/packages/twenty-front/src/modules/front-components/components/FrontComponentRenderer.tsx index ff588847d9..7b45fb1703 100644 --- a/packages/twenty-front/src/modules/front-components/components/FrontComponentRenderer.tsx +++ b/packages/twenty-front/src/modules/front-components/components/FrontComponentRenderer.tsx @@ -1,10 +1,13 @@ +import { currentUserState } from '@/auth/states/currentUserState'; import { getMockFrontComponentUrl } from '@/front-components/utils/mockFrontComponent'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { useTheme } from '@emotion/react'; import { t } from '@lingui/core/macro'; import { useState } from 'react'; -import { FrontComponentRenderer as SharedFrontComponentRenderer } from 'twenty-sdk/front-component'; +import { useRecoilValue } from 'recoil'; +import { FrontComponentRenderer as SharedFrontComponentRenderer } from 'twenty-sdk/front-component/renderer'; import { isDefined } from 'twenty-shared/utils'; + type FrontComponentRendererProps = { frontComponentId: string; }; @@ -16,6 +19,7 @@ export const FrontComponentRenderer = ({ const [hasError, setHasError] = useState(false); const { enqueueErrorSnackBar } = useSnackBar(); + const currentUser = useRecoilValue(currentUserState); const handleError = (error?: Error) => { if (isDefined(error)) { @@ -36,6 +40,9 @@ export const FrontComponentRenderer = ({ ); diff --git a/packages/twenty-front/src/modules/front-components/utils/mockFrontComponent.ts b/packages/twenty-front/src/modules/front-components/utils/mockFrontComponent.ts index 781e9b58ee..c8d3da9820 100644 --- a/packages/twenty-front/src/modules/front-components/utils/mockFrontComponent.ts +++ b/packages/twenty-front/src/modules/front-components/utils/mockFrontComponent.ts @@ -1,18 +1,107 @@ +/* eslint-disable */ import { isDefined } from 'twenty-shared/utils'; const mockFrontComponentCode = ` -const { jsx } = globalThis; -const { TwentyUiButton } = globalThis.RemoteComponents; +// react-globals:react +var useState = globalThis.React.useState; +var useEffect = globalThis.React.useEffect; +var useSyncExternalStore = globalThis.React.useSyncExternalStore; -export default jsx(TwentyUiButton, { - variant: 'primary', - disabled: false, - fullWidth: false, - onClick: () => { - console.log('Button clicked'); - }, - title: 'Click me', -}); +// react-globals:react/jsx-runtime +var jsx = globalThis.jsx; +var jsxs = globalThis.jsxs; +var Fragment = globalThis.React.Fragment; + +// src/tata/test-component.front-component.tsx +var RemoteComponents = globalThis.RemoteComponents; +var getStore = () => { + const store = globalThis.frontComponentExecutionContextStore; + if (store === void 0) { + throw new Error( + "frontComponentExecutionContextStore not found on globalThis. This hook must be used within a front component running in the worker." + ); + } + return store; +}; +var useFrontComponentExecutionContext = () => { + const store = getStore(); + return useSyncExternalStore(store.subscribe, store.getSnapshot); +}; +var TestComponent = () => { + const [count, setCount] = useState(0); + const [timer, setTimer] = useState(0); + const context = useFrontComponentExecutionContext(); + useEffect(() => { + const interval = setInterval(() => { + setTimer((prevTimer) => prevTimer + 1); + }, 1e3); + return () => clearInterval(interval); + }, []); + return /* @__PURE__ */ jsxs( + RemoteComponents.HtmlDiv, + { + style: { + padding: "20px", + fontFamily: "Arial, sans-serif", + maxWidth: "400px", + margin: "0 auto", + display: "flex", + flexDirection: "column", + alignItems: "center" + }, + children: [ + /* @__PURE__ */ jsx(RemoteComponents.HtmlH1, { style: { color: "#333", marginBottom: "20px", fontSize: "24px" }, children: "Test Component" }), + /* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "10px", color: "#666" }, children: [ + "Count: ", + count + ] }), + /* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "20px", color: "#666" }, children: [ + "Timer: ", + timer, + "s" + ] }), + /* @__PURE__ */ jsxs(RemoteComponents.HtmlP, { style: { fontSize: "18px", marginBottom: "20px", color: "#666" }, children: [ + "User ID: ", + context?.userId + ] }), + /* @__PURE__ */ jsx( + RemoteComponents.HtmlButton, + { + onClick: () => setCount(count + 1), + style: { + padding: "10px 20px", + fontSize: "16px", + backgroundColor: "#007bff", + color: "white", + border: "none", + borderRadius: "5px", + cursor: "pointer", + transition: "all 0.3s ease", + boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)" + }, + onMouseEnter: (e) => { + e.currentTarget.style.backgroundColor = "#0056b3"; + e.currentTarget.style.transform = "translateY(-2px)"; + e.currentTarget.style.boxShadow = "0 4px 8px rgba(0, 0, 0, 0.3)"; + }, + onMouseLeave: (e) => { + e.currentTarget.style.backgroundColor = "#007bff"; + e.currentTarget.style.transform = "translateY(0)"; + e.currentTarget.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.2)"; + }, + children: "Increment" + } + ) + ] + } + ); +}; +var test_component_front_component_default = globalThis.jsx(TestComponent, {}); +export { + test_component_front_component_default as default, + useFrontComponentExecutionContext +}; +//# sourceMappingURL=test-component.front-component.mjs.map `; let cachedMockBlobUrl: string | null = null; diff --git a/packages/twenty-sdk/package.json b/packages/twenty-sdk/package.json index aedcb772d4..8c6da6a97f 100644 --- a/packages/twenty-sdk/package.json +++ b/packages/twenty-sdk/package.json @@ -5,13 +5,12 @@ "module": "dist/index.mjs", "types": "dist/index.d.ts", "bin": { - "twenty": "dist/cli/index.cjs" + "twenty": "dist/cli.cjs" }, "files": [ "dist", - "front-component", - "front-component-constants", - "ui" + "ui", + "front-component" ], "scripts": { "build": "npx rimraf dist && npx vite build", @@ -32,20 +31,20 @@ "import": "./dist/index.mjs", "require": "./dist/index.cjs" }, - "./front-component": { - "types": "./dist/front-component/index.d.ts", - "import": "./dist/front-component/index.mjs", - "require": "./dist/front-component/index.cjs" - }, - "./front-component-constants": { - "types": "./dist/front-component-constants/index.d.ts", - "import": "./dist/front-component-constants/index.mjs", - "require": "./dist/front-component-constants/index.cjs" - }, "./ui": { "types": "./dist/ui/index.d.ts", "import": "./dist/ui/index.mjs", "require": "./dist/ui/index.cjs" + }, + "./front-component/renderer": { + "types": "./dist/front-component/renderer/index.d.ts", + "import": "./dist/front-component/renderer/index.mjs", + "require": "./dist/front-component/renderer/index.cjs" + }, + "./front-component/api": { + "types": "./dist/front-component/api/index.d.ts", + "import": "./dist/front-component/api/index.mjs", + "require": "./dist/front-component/api/index.cjs" } }, "license": "AGPL-3.0", @@ -105,14 +104,14 @@ }, "typesVersions": { "*": { - "front-component": [ - "dist/front-component/index.d.ts" - ], - "front-component-constants": [ - "dist/front-component-constants/index.d.ts" - ], "ui": [ "dist/ui/index.d.ts" + ], + "front-component/renderer": [ + "dist/front-component/renderer/index.d.ts" + ], + "front-component/api": [ + "dist/front-component/api/index.d.ts" ] } } diff --git a/packages/twenty-sdk/project.json b/packages/twenty-sdk/project.json index c5e7d72001..77da008d39 100644 --- a/packages/twenty-sdk/project.json +++ b/packages/twenty-sdk/project.json @@ -3,32 +3,15 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "packages/twenty-sdk/src", "projectType": "library", - "tags": [ - "scope:sdk", - "scope:shared" - ], + "tags": ["scope:sdk", "scope:shared"], "targets": { "build": { - "dependsOn": [ - "generateBarrels", - "^build" - ], - "outputs": [ - "{projectRoot}/dist", - "{projectRoot}/front-component/package.json", - "{projectRoot}/front-component/dist", - "{projectRoot}/front-component-constants/package.json", - "{projectRoot}/front-component-constants/dist", - "{projectRoot}/ui/package.json", - "{projectRoot}/ui/dist" - ] + "dependsOn": ["^build"], + "outputs": ["{projectRoot}/dist"] }, "dev": { "executor": "nx:run-commands", - "dependsOn": [ - "generateBarrels", - "^build" - ], + "dependsOn": ["^build"], "options": { "cwd": "packages/twenty-sdk", "command": "npx rimraf dist && npx vite build --watch" @@ -36,43 +19,21 @@ }, "start": { "executor": "nx:run-commands", - "dependsOn": [ - "build" - ], + "dependsOn": ["build"], "options": { "cwd": "packages/twenty-sdk", "command": "node dist/cli.cjs" } }, - "generateBarrels": { - "executor": "nx:run-commands", - "cache": true, - "inputs": [ - "production", - "{projectRoot}/scripts/generateBarrels.ts" - ], - "outputs": [ - "{projectRoot}/src/index.ts", - "{projectRoot}/src/*/index.ts", - "{projectRoot}/package.json" - ], - "options": { - "command": "tsx {projectRoot}/scripts/generateBarrels.ts" - } - }, "typecheck": {}, "lint": { "options": { - "lintFilePatterns": [ - "{projectRoot}/src/**/*.{ts,json}" - ], + "lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"], "maxWarnings": 0 }, "configurations": { "ci": { - "lintFilePatterns": [ - "{projectRoot}/src/**/*.{ts,json}" - ], + "lintFilePatterns": ["{projectRoot}/src/**/*.{ts,json}"], "maxWarnings": 0 }, "fix": {} @@ -80,9 +41,7 @@ }, "test": { "executor": "@nx/vitest:test", - "outputs": [ - "{workspaceRoot}/coverage/{projectRoot}" - ], + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], "options": { "config": "{projectRoot}/vitest.config.ts" }, @@ -146,9 +105,7 @@ "storybook:prebuild": { "executor": "nx:run-commands", "cache": true, - "dependsOn": [ - "generateRemoteDomElements" - ], + "dependsOn": ["generateRemoteDomElements"], "inputs": [ "{projectRoot}/src/front-component/__stories__/mocks/**/*", "{projectRoot}/src/front-component/__stories__/utils/**/*", @@ -156,25 +113,19 @@ "{projectRoot}/src/front-component-constants/**/*", "{projectRoot}/src/sdk/**/*" ], - "outputs": [ - "{projectRoot}/src/front-component/__stories__/built/*" - ], + "outputs": ["{projectRoot}/src/front-component/__stories__/built/*"], "options": { "command": "tsx {projectRoot}/src/front-component/__stories__/utils/buildMockComponents.ts" } }, "storybook:build": { - "dependsOn": [ - "storybook:prebuild" - ], + "dependsOn": ["storybook:prebuild"], "configurations": { "test": {} } }, "storybook:serve:dev": { - "dependsOn": [ - "storybook:prebuild" - ], + "dependsOn": ["storybook:prebuild"], "options": { "port": 6008 } @@ -189,17 +140,13 @@ } }, "storybook:test": { - "dependsOn": [ - "storybook:prebuild" - ], + "dependsOn": ["storybook:prebuild"], "options": { "command": "vitest run --coverage --config vitest.storybook.config.ts --shard={args.shard}" } }, "storybook:test:no-coverage": { - "dependsOn": [ - "storybook:prebuild" - ], + "dependsOn": ["storybook:prebuild"], "options": { "command": "vitest run --config vitest.storybook.config.ts --shard={args.shard}" } diff --git a/packages/twenty-sdk/scripts/generateBarrels.ts b/packages/twenty-sdk/scripts/generateBarrels.ts deleted file mode 100644 index 5c86bcf4a7..0000000000 --- a/packages/twenty-sdk/scripts/generateBarrels.ts +++ /dev/null @@ -1,559 +0,0 @@ -import prettier from '@prettier/sync'; -import * as fs from 'fs'; -import { globSync } from 'glob'; -import path from 'path'; -import { type Options } from 'prettier'; -import slash from 'slash'; -import ts from 'typescript'; - -// TODO prastoin refactor this file in several one into its dedicated package and make it a TypeScript CLI - -const INDEX_FILENAME = 'index'; -const PACKAGE_JSON_FILENAME = 'package.json'; -const NX_PROJECT_CONFIGURATION_FILENAME = 'project.json'; -const PACKAGE_PATH = path.resolve('packages/twenty-sdk'); -const SRC_PATH = path.resolve(`${PACKAGE_PATH}/src`); -const PACKAGE_JSON_PATH = path.join(PACKAGE_PATH, PACKAGE_JSON_FILENAME); -const NX_PROJECT_CONFIGURATION_PATH = path.join( - PACKAGE_PATH, - NX_PROJECT_CONFIGURATION_FILENAME, -); -const EXCLUDED_EXTENSIONS = [ - '**/*.test.ts', - '**/*.test.tsx', - '**/*.spec.ts', - '**/*.spec.tsx', - '**/*.stories.ts', - '**/*.stories.tsx', -] as const; -const EXCLUDED_DIRECTORIES = [ - '**/__tests__/**', - '**/__mocks__/**', - '**/__stories__/**', - '**/internal/**', - '**/cli/**', -] as const; -const ROOT_DIRECTORIES = ['sdk']; - -// Modules that re-export from external packages instead of local files -const EXTERNAL_REEXPORT_MODULES: Record = { - ui: `export * from 'twenty-ui'; -export * from 'twenty-ui/accessibility'; -export * from 'twenty-ui/components'; -export * from 'twenty-ui/display'; -export * from 'twenty-ui/feedback'; -export * from 'twenty-ui/input'; -export * from 'twenty-ui/json-visualizer'; -export * from 'twenty-ui/layout'; -export * from 'twenty-ui/navigation'; -export * from 'twenty-ui/theme'; -export * from 'twenty-ui/utilities';`, -}; - -const prettierConfigFile = prettier.resolveConfigFile(); -if (prettierConfigFile == null) { - throw new Error('Prettier config file not found'); -} -const prettierConfiguration = prettier.resolveConfig(prettierConfigFile); -const prettierFormat = (str: string, parser: Options['parser']) => - prettier.format(str, { - ...prettierConfiguration, - parser, - }); -type createTypeScriptFileArgs = { - path: string; - content: string; - filename: string; -}; -const createTypeScriptFile = ({ - content, - path: filePath, - filename, -}: createTypeScriptFileArgs) => { - const header = ` -/* - * _____ _ - *|_ _|_ _____ _ __ | |_ _ _ - * | | \\ \\ /\\ / / _ \\ '_ \\| __| | | | Auto-generated file - * | | \\ V V / __/ | | | |_| |_| | Any edits to this will be overridden - * |_| \\_/\\_/ \\___|_| |_|\\__|\\__, | - * |___/ - */ -`; - const formattedContent = prettierFormat( - `${header}\n${content}\n`, - 'typescript', - ); - fs.writeFileSync( - path.join(filePath, `${filename}.ts`), - formattedContent, - 'utf-8', - ); -}; - -const getLastPathFolder = (pathStr: string) => path.basename(pathStr); - -const getSubDirectoryPaths = (directoryPath: string): string[] => { - const pattern = slash(path.join(directoryPath, '*/')); - return globSync(pattern, { - ignore: [...EXCLUDED_DIRECTORIES], - cwd: SRC_PATH, - nodir: false, - maxDepth: 1, - }).sort((a, b) => a.localeCompare(b)); -}; - -const partitionFileExportsByType = (declarations: DeclarationOccurrence[]) => { - return declarations.reduce<{ - typeAndInterfaceDeclarations: DeclarationOccurrence[]; - otherDeclarations: DeclarationOccurrence[]; - }>( - (acc, { kind, name }) => { - if (kind === 'type' || kind === 'interface') { - return { - ...acc, - typeAndInterfaceDeclarations: [ - ...acc.typeAndInterfaceDeclarations, - { kind, name }, - ], - }; - } - - return { - ...acc, - otherDeclarations: [...acc.otherDeclarations, { kind, name }], - }; - }, - { - typeAndInterfaceDeclarations: [], - otherDeclarations: [], - }, - ); -}; - -const generateModuleIndexFiles = (exportByBarrel: ExportByBarrel[]) => { - return exportByBarrel.map( - ({ barrel: { moduleDirectory }, allFileExports }) => { - const content = allFileExports - .sort((a, b) => a.file.localeCompare(b.file)) - .map(({ exports, file }) => { - const { otherDeclarations, typeAndInterfaceDeclarations } = - partitionFileExportsByType(exports); - - const fileWithoutExtension = path.parse(file).name; - const pathToImport = slash( - path.relative( - moduleDirectory, - path.join(path.dirname(file), fileWithoutExtension), - ), - ); - const mapDeclarationNameAndJoin = ( - declarations: DeclarationOccurrence[], - ) => declarations.map(({ name }) => name).join(', '); - - const typeExport = - typeAndInterfaceDeclarations.length > 0 - ? `export type { ${mapDeclarationNameAndJoin(typeAndInterfaceDeclarations)} } from "./${pathToImport}"` - : ''; - const othersExport = - otherDeclarations.length > 0 - ? `export { ${mapDeclarationNameAndJoin(otherDeclarations)} } from "./${pathToImport}"` - : ''; - - return [typeExport, othersExport] - .filter((el) => el !== '') - .join('\n'); - }) - .join('\n'); - - return { - content, - path: moduleDirectory, - filename: INDEX_FILENAME, - }; - }, - ); -}; - -type JsonUpdate = Record; -type WriteInJsonFileArgs = { - content: JsonUpdate; - file: string; -}; -const updateJsonFile = ({ content, file }: WriteInJsonFileArgs) => { - const updatedJsonFile = JSON.stringify(content); - const formattedContent = prettierFormat(updatedJsonFile, 'json-stringify'); - fs.writeFileSync(file, formattedContent, 'utf-8'); -}; - -const writeInPackageJson = (update: JsonUpdate) => { - const rawJsonFile = fs.readFileSync(PACKAGE_JSON_PATH, 'utf-8'); - const initialJsonFile = JSON.parse(rawJsonFile); - - updateJsonFile({ - file: PACKAGE_JSON_PATH, - content: { - ...initialJsonFile, - ...update, - }, - }); -}; - -const updateNxProjectConfigurationBuildOutputs = (outputs: JsonUpdate) => { - const rawJsonFile = fs.readFileSync(NX_PROJECT_CONFIGURATION_PATH, 'utf-8'); - const initialJsonFile = JSON.parse(rawJsonFile); - - updateJsonFile({ - file: NX_PROJECT_CONFIGURATION_PATH, - content: { - ...initialJsonFile, - targets: { - ...initialJsonFile.targets, - build: { - ...initialJsonFile.targets.build, - outputs, - }, - }, - }, - }); -}; - -type ExportOccurrence = { - types: string; - import: string; - require: string; -}; -type ExportsConfig = Record; - -const generateModulePackageExports = (moduleDirectories: string[]) => { - return moduleDirectories.reduce((acc, moduleDirectory) => { - const moduleName = getLastPathFolder(moduleDirectory); - if (moduleName === undefined) { - throw new Error( - `Should never occur, moduleName is undefined ${moduleDirectory}`, - ); - } - - return { - ...acc, - [`./${moduleName}`]: { - types: `./dist/${moduleName}/index.d.ts`, - import: `./dist/${moduleName}/index.mjs`, - require: `./dist/${moduleName}/index.cjs`, - }, - }; - }, {}); -}; - -const computePackageJsonFilesAndExportsConfig = ( - moduleDirectories: string[], -) => { - const entrypoints = moduleDirectories.map(getLastPathFolder); - const exports = { - '.': { - types: './dist/index.d.ts', - import: './dist/index.mjs', - require: './dist/index.cjs', - }, - ...generateModulePackageExports(moduleDirectories), - } satisfies ExportsConfig; - - const typesVersionsEntries = entrypoints.reduce>( - (acc, moduleName) => ({ - ...acc, - [`${moduleName}`]: [`dist/${moduleName}/index.d.ts`], - }), - {}, - ); - - return { - exports, - typesVersions: { '*': typesVersionsEntries }, - files: ['dist', ...entrypoints], - }; -}; - -const computeProjectNxBuildOutputsPath = (moduleDirectories: string[]) => { - const dynamicOutputsPath = moduleDirectories - .map(getLastPathFolder) - .flatMap((barrelName) => - ['package.json', 'dist'].map( - (subPath) => `{projectRoot}/${barrelName}/${subPath}`, - ), - ); - - return ['{projectRoot}/dist', ...dynamicOutputsPath]; -}; - -const getTypeScriptFiles = ( - directoryPath: string, - includeIndex: boolean = false, -): string[] => { - const pattern = slash(path.join(directoryPath, '**', '*.{ts,tsx}')); - const files = globSync(pattern, { - cwd: SRC_PATH, - nodir: true, - ignore: [...EXCLUDED_EXTENSIONS, ...EXCLUDED_DIRECTORIES], - }); - - return files.filter( - (file) => - !file.endsWith('.d.ts') && - (includeIndex ? true : !file.endsWith('index.ts')), - ); -}; - -const getKind = ( - node: ts.VariableStatement, -): Extract => { - const isConst = (node.declarationList.flags & ts.NodeFlags.Const) !== 0; - if (isConst) { - return 'const'; - } - - const isLet = (node.declarationList.flags & ts.NodeFlags.Let) !== 0; - if (isLet) { - return 'let'; - } - - return 'var'; -}; - -const extractExportsFromSourceFile = (sourceFile: ts.SourceFile) => { - const exports: DeclarationOccurrence[] = []; - - const visit = (node: ts.Node) => { - if (!ts.canHaveModifiers(node)) { - ts.forEachChild(node, visit); - return; - } - const modifiers = ts.getModifiers(node); - const isExport = modifiers?.some( - (mod) => mod.kind === ts.SyntaxKind.ExportKeyword, - ); - - if (!isExport && !ts.isExportDeclaration(node)) { - ts.forEachChild(node, visit); - return; - } - - switch (true) { - case ts.isTypeAliasDeclaration(node): - exports.push({ - kind: 'type', - name: node.name.text, - }); - break; - - case ts.isInterfaceDeclaration(node): - exports.push({ - kind: 'interface', - name: node.name.text, - }); - break; - - case ts.isEnumDeclaration(node): - exports.push({ - kind: 'enum', - name: node.name.text, - }); - break; - - case ts.isFunctionDeclaration(node) && node.name !== undefined: - exports.push({ - kind: 'function', - name: node.name.text, - }); - break; - - case ts.isVariableStatement(node): - node.declarationList.declarations.forEach((decl) => { - const kind = getKind(node); - - if (ts.isIdentifier(decl.name)) { - exports.push({ - kind, - name: decl.name.text, - }); - } else if (ts.isObjectBindingPattern(decl.name)) { - decl.name.elements.forEach((element) => { - if ( - !ts.isBindingElement(element) || - !ts.isIdentifier(element.name) - ) { - return; - } - - exports.push({ - kind, - name: element.name.text, - }); - }); - } - }); - break; - - case ts.isClassDeclaration(node) && node.name !== undefined: - exports.push({ - kind: 'class', - name: node.name.text, - }); - break; - case ts.isExportDeclaration(node): - if (node.exportClause && ts.isNamedExports(node.exportClause)) { - node.exportClause.elements.forEach((element) => { - const exportName = element.name.text; - - // Check both the declaration and the individual specifier for type-only exports - const isTypeExport = - node.isTypeOnly || ts.isTypeOnlyExportDeclaration(node); - if (isTypeExport) { - // should handle kind - exports.push({ - kind: 'type', - name: exportName, - }); - return; - } - - exports.push({ - kind: 'const', - name: exportName, - }); - }); - } - break; - } - ts.forEachChild(node, visit); - }; - - visit(sourceFile); - return exports; -}; - -type ExportKind = - | 'type' - | 'interface' - | 'enum' - | 'function' - | 'const' - | 'let' - | 'var' - | 'class'; -type DeclarationOccurrence = { kind: ExportKind; name: string }; -type FileExports = Array<{ - file: string; - exports: DeclarationOccurrence[]; -}>; - -const findAllExports = (directoryPath: string): FileExports => { - const results: FileExports = []; - - const files = getTypeScriptFiles(directoryPath); - - for (const file of files) { - const sourceFile = ts.createSourceFile( - file, - fs.readFileSync(file, 'utf8'), - ts.ScriptTarget.Latest, - true, - ); - - const exports = extractExportsFromSourceFile(sourceFile); - if (exports.length > 0) { - results.push({ - file, - exports, - }); - } - } - - return results; -}; - -type ExportByBarrel = { - barrel: { - moduleName: string; - moduleDirectory: string; - }; - allFileExports: FileExports; -}; -const retrieveExportsByBarrel = (barrelDirectories: string[]) => { - return barrelDirectories.map((moduleDirectory) => { - const moduleExportsPerFile = findAllExports(moduleDirectory); - const moduleName = getLastPathFolder(moduleDirectory); - if (!moduleName) { - throw new Error( - `Should never occur moduleName not found ${moduleDirectory}`, - ); - } - - return { - barrel: { - moduleName, - moduleDirectory, - }, - allFileExports: moduleExportsPerFile, - }; - }); -}; - -const main = () => { - const moduleDirectories = getSubDirectoryPaths(SRC_PATH); - - const rootDirectory = moduleDirectories.find((dir) => - ROOT_DIRECTORIES.includes(getLastPathFolder(dir)), - ); - - // Separate modules that re-export from external packages - const externalReexportModuleNames = Object.keys(EXTERNAL_REEXPORT_MODULES); - const localModuleDirectories = moduleDirectories.filter( - (dir) => !externalReexportModuleNames.includes(getLastPathFolder(dir)), - ); - - const otherBarrelDirectories = moduleDirectories.filter( - (dir) => !ROOT_DIRECTORIES.includes(getLastPathFolder(dir)), - ); - - const exportsByBarrel = retrieveExportsByBarrel(localModuleDirectories); - const moduleIndexFiles = generateModuleIndexFiles(exportsByBarrel); - - const packageJsonConfig = computePackageJsonFilesAndExportsConfig( - otherBarrelDirectories, - ); - const nxBuildOutputsPath = computeProjectNxBuildOutputsPath( - otherBarrelDirectories, - ); - - updateNxProjectConfigurationBuildOutputs(nxBuildOutputsPath); - writeInPackageJson(packageJsonConfig); - moduleIndexFiles.forEach(createTypeScriptFile); - - // Generate index files for modules that re-export from external packages - for (const [moduleName, content] of Object.entries( - EXTERNAL_REEXPORT_MODULES, - )) { - const moduleDirectory = path.join(SRC_PATH, moduleName); - if (!fs.existsSync(moduleDirectory)) { - fs.mkdirSync(moduleDirectory, { recursive: true }); - } - createTypeScriptFile({ - path: moduleDirectory, - filename: INDEX_FILENAME, - content, - }); - } - - // Ensure top-level src/index.ts re-exports the root directories barrel so consumers can `import * from "twenty-sdk"` - // We intentionally keep this file minimal: it delegates to the generated src//index.ts - if (rootDirectory) { - createTypeScriptFile({ - path: SRC_PATH, - filename: INDEX_FILENAME, - content: ROOT_DIRECTORIES.map( - (rootDirectory) => `export * from "./${rootDirectory}";`, - ).join('\n'), - }); - } -}; -main(); diff --git a/packages/twenty-sdk/scripts/remote-dom/generateRemoteDomElements.ts b/packages/twenty-sdk/scripts/remote-dom/generateRemoteDomElements.ts index ebaa64215b..8048c13faa 100644 --- a/packages/twenty-sdk/scripts/remote-dom/generateRemoteDomElements.ts +++ b/packages/twenty-sdk/scripts/remote-dom/generateRemoteDomElements.ts @@ -3,11 +3,11 @@ import * as fs from 'fs'; import * as path from 'path'; import { IndentationText, Project, QuoteKind } from 'ts-morph'; -import { ALLOWED_HTML_ELEMENTS } from '../../src/front-component-constants/AllowedHtmlElements'; -import { ALLOWED_UI_COMPONENTS } from '../../src/front-component-constants/AllowedUiComponents'; -import { COMMON_HTML_EVENTS } from '../../src/front-component-constants/CommonHtmlEvents'; -import { EVENT_TO_REACT } from '../../src/front-component-constants/EventToReact'; -import { HTML_COMMON_PROPERTIES } from '../../src/front-component-constants/HtmlCommonProperties'; +import { ALLOWED_HTML_ELEMENTS } from '../../src/front-component/common/AllowedHtmlElements'; +import { ALLOWED_UI_COMPONENTS } from '../../src/front-component/common/AllowedUiComponents'; +import { COMMON_HTML_EVENTS } from '../../src/front-component/common/CommonHtmlEvents'; +import { EVENT_TO_REACT } from '../../src/front-component/common/EventToReact'; +import { HTML_COMMON_PROPERTIES } from '../../src/front-component/common/HtmlCommonProperties'; import { type ComponentSchema, diff --git a/packages/twenty-sdk/src/cli/utilities/build/common/front-component-build/utils/replace-html-tags-with-remote-components.ts b/packages/twenty-sdk/src/cli/utilities/build/common/front-component-build/utils/replace-html-tags-with-remote-components.ts index 5bbd4183d1..c3b7f6e50d 100644 --- a/packages/twenty-sdk/src/cli/utilities/build/common/front-component-build/utils/replace-html-tags-with-remote-components.ts +++ b/packages/twenty-sdk/src/cli/utilities/build/common/front-component-build/utils/replace-html-tags-with-remote-components.ts @@ -1,6 +1,6 @@ import { isDefined } from 'twenty-shared/utils'; -import { HTML_TAG_TO_REMOTE_COMPONENT } from '../../../../../../front-component-constants'; +import { HTML_TAG_TO_REMOTE_COMPONENT } from '../../../../../../front-component/common'; const REMOTE_COMPONENTS_GLOBAL_NAMESPACE = 'RemoteComponents'; diff --git a/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-build.ts b/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-build.ts index 57899c129b..20c3a4f7f8 100644 --- a/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-build.ts +++ b/packages/twenty-sdk/src/cli/utilities/build/manifest/manifest-build.ts @@ -6,11 +6,12 @@ import { } from '@/cli/utilities/build/manifest/manifest-extract-config'; import { extractManifestFromFile } from '@/cli/utilities/build/manifest/manifest-extract-config-from-file'; import { + type ApplicationConfig, type FrontComponentConfig, type LogicFunctionConfig, - type ApplicationConfig, } from '@/sdk'; import { glob } from 'fast-glob'; +import * as fs from 'fs-extra'; import { readFile } from 'fs-extra'; import { basename, extname, relative, sep } from 'path'; import { @@ -24,9 +25,8 @@ import { type ObjectManifest, type RoleManifest, } from 'twenty-shared/application'; -import { assertUnreachable } from 'twenty-shared/utils'; import { type Sources } from 'twenty-shared/types'; -import * as fs from 'fs-extra'; +import { assertUnreachable } from 'twenty-shared/utils'; const loadSources = async (appPath: string): Promise => { return await glob(['**/*.ts', '**/*.tsx'], { diff --git a/packages/twenty-sdk/src/front-component/__stories__/FrontComponentRenderer.stories.tsx b/packages/twenty-sdk/src/front-component/__stories__/FrontComponentRenderer.stories.tsx index 55d3e601dd..a80e94548f 100644 --- a/packages/twenty-sdk/src/front-component/__stories__/FrontComponentRenderer.stories.tsx +++ b/packages/twenty-sdk/src/front-component/__stories__/FrontComponentRenderer.stories.tsx @@ -1,7 +1,7 @@ import { type Meta, type StoryObj } from '@storybook/react-vite'; import { expect, fn, userEvent, waitFor, within } from 'storybook/test'; -import { FrontComponentRenderer } from '../host/components/FrontComponentRenderer'; +import { FrontComponentRenderer } from '../renderer/host/components/FrontComponentRenderer'; import { getBuiltComponentPath } from './utils/loadBuiltComponent'; diff --git a/packages/twenty-sdk/src/front-component/api/hooks/useFrontComponentExecutionContext.ts b/packages/twenty-sdk/src/front-component/api/hooks/useFrontComponentExecutionContext.ts new file mode 100644 index 0000000000..c89b322569 --- /dev/null +++ b/packages/twenty-sdk/src/front-component/api/hooks/useFrontComponentExecutionContext.ts @@ -0,0 +1,26 @@ +import { useSyncExternalStore } from 'react'; +import { type FrontComponentExecutionContext } from '../types/FrontComponentExecutionContext'; +import { type FrontComponentExecutionContextStore } from '../types/FrontComponentExecutionContextStore'; + +const getStore = (): FrontComponentExecutionContextStore => { + const store = (globalThis as Record) + .frontComponentExecutionContextStore as + | FrontComponentExecutionContextStore + | undefined; + + if (store === undefined) { + throw new Error( + 'frontComponentExecutionContextStore not found on globalThis. This hook must be used within a front component running in the worker.', + ); + } + + return store; +}; + +export const useFrontComponentExecutionContext = (): + | FrontComponentExecutionContext + | undefined => { + const store = getStore(); + + return useSyncExternalStore(store.subscribe, store.getSnapshot); +}; diff --git a/packages/twenty-sdk/src/front-component/api/index.ts b/packages/twenty-sdk/src/front-component/api/index.ts new file mode 100644 index 0000000000..fc03b9744d --- /dev/null +++ b/packages/twenty-sdk/src/front-component/api/index.ts @@ -0,0 +1,3 @@ +export { useFrontComponentExecutionContext } from './hooks/useFrontComponentExecutionContext'; +export type { FrontComponentExecutionContext } from './types/FrontComponentExecutionContext'; +export type { FrontComponentExecutionContextStore } from './types/FrontComponentExecutionContextStore'; diff --git a/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContext.ts b/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContext.ts new file mode 100644 index 0000000000..0b6fb8874e --- /dev/null +++ b/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContext.ts @@ -0,0 +1,3 @@ +export type FrontComponentExecutionContext = { + userId: string; +}; diff --git a/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContextStore.ts b/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContextStore.ts new file mode 100644 index 0000000000..bcc043399c --- /dev/null +++ b/packages/twenty-sdk/src/front-component/api/types/FrontComponentExecutionContextStore.ts @@ -0,0 +1,6 @@ +import { type FrontComponentExecutionContext } from './FrontComponentExecutionContext'; + +export type FrontComponentExecutionContextStore = { + getSnapshot: () => FrontComponentExecutionContext | undefined; + subscribe: (listener: () => void) => () => void; +}; diff --git a/packages/twenty-sdk/src/front-component-constants/AllowedHtmlElements.ts b/packages/twenty-sdk/src/front-component/common/AllowedHtmlElements.ts similarity index 100% rename from packages/twenty-sdk/src/front-component-constants/AllowedHtmlElements.ts rename to packages/twenty-sdk/src/front-component/common/AllowedHtmlElements.ts diff --git a/packages/twenty-sdk/src/front-component-constants/AllowedUiComponents.ts b/packages/twenty-sdk/src/front-component/common/AllowedUiComponents.ts similarity index 89% rename from packages/twenty-sdk/src/front-component-constants/AllowedUiComponents.ts rename to packages/twenty-sdk/src/front-component/common/AllowedUiComponents.ts index b9fb719a75..f13da74d43 100644 --- a/packages/twenty-sdk/src/front-component-constants/AllowedUiComponents.ts +++ b/packages/twenty-sdk/src/front-component/common/AllowedUiComponents.ts @@ -1,4 +1,4 @@ -import { type PropertySchema } from '../front-component/types/PropertySchema'; +import { type PropertySchema } from '../renderer/types/PropertySchema'; export type AllowedUiComponent = { tag: string; diff --git a/packages/twenty-sdk/src/front-component-constants/CommonHtmlEvents.ts b/packages/twenty-sdk/src/front-component/common/CommonHtmlEvents.ts similarity index 100% rename from packages/twenty-sdk/src/front-component-constants/CommonHtmlEvents.ts rename to packages/twenty-sdk/src/front-component/common/CommonHtmlEvents.ts diff --git a/packages/twenty-sdk/src/front-component-constants/EventToReact.ts b/packages/twenty-sdk/src/front-component/common/EventToReact.ts similarity index 100% rename from packages/twenty-sdk/src/front-component-constants/EventToReact.ts rename to packages/twenty-sdk/src/front-component/common/EventToReact.ts diff --git a/packages/twenty-sdk/src/front-component-constants/HtmlCommonProperties.ts b/packages/twenty-sdk/src/front-component/common/HtmlCommonProperties.ts similarity index 86% rename from packages/twenty-sdk/src/front-component-constants/HtmlCommonProperties.ts rename to packages/twenty-sdk/src/front-component/common/HtmlCommonProperties.ts index 29c0e25d70..12dfc40e41 100644 --- a/packages/twenty-sdk/src/front-component-constants/HtmlCommonProperties.ts +++ b/packages/twenty-sdk/src/front-component/common/HtmlCommonProperties.ts @@ -1,4 +1,4 @@ -import { type PropertySchema } from '../front-component/types/PropertySchema'; +import { type PropertySchema } from '../renderer/types/PropertySchema'; export const HTML_COMMON_PROPERTIES: Record = { id: { type: 'string', optional: true }, diff --git a/packages/twenty-sdk/src/front-component-constants/HtmlTagToRemoteComponent.ts b/packages/twenty-sdk/src/front-component/common/HtmlTagToRemoteComponent.ts similarity index 100% rename from packages/twenty-sdk/src/front-component-constants/HtmlTagToRemoteComponent.ts rename to packages/twenty-sdk/src/front-component/common/HtmlTagToRemoteComponent.ts diff --git a/packages/twenty-sdk/src/front-component-constants/index.ts b/packages/twenty-sdk/src/front-component/common/index.ts similarity index 100% rename from packages/twenty-sdk/src/front-component-constants/index.ts rename to packages/twenty-sdk/src/front-component/common/index.ts diff --git a/packages/twenty-sdk/src/front-component/host/components/FrontComponentRenderer.tsx b/packages/twenty-sdk/src/front-component/host/components/FrontComponentRenderer.tsx deleted file mode 100644 index a34a877662..0000000000 --- a/packages/twenty-sdk/src/front-component/host/components/FrontComponentRenderer.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { - type RemoteReceiver, - RemoteRootRenderer, -} from '@remote-dom/react/host'; -import { useState } from 'react'; -import { isDefined } from 'twenty-shared/utils'; - -import { ThemeProvider } from '@emotion/react'; -import { type ThemeType } from 'twenty-ui/theme'; -import { FrontComponentWorkerEffect } from '../../remote/components/FrontComponentWorkerEffect'; -import { componentRegistry } from '../generated/host-component-registry'; - -type FrontComponentContentProps = { - componentUrl: string; - onError: (error?: Error) => void; - theme: ThemeType; -}; - -export const FrontComponentRenderer = ({ - componentUrl, - onError, - theme, -}: FrontComponentContentProps) => { - const [receiver, setReceiver] = useState(null); - - return ( - <> - - - {isDefined(receiver) && ( - - - - )} - - ); -}; diff --git a/packages/twenty-sdk/src/front-component/renderer/host/components/FrontComponentRenderer.tsx b/packages/twenty-sdk/src/front-component/renderer/host/components/FrontComponentRenderer.tsx new file mode 100644 index 0000000000..7d99bdefd0 --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/host/components/FrontComponentRenderer.tsx @@ -0,0 +1,73 @@ +import { FrontComponentErrorEffect } from '@/front-component/renderer/remote/components/FrontComponentErrorEffect'; +import { FrontComponentUpdateContextEffect } from '@/front-component/renderer/remote/components/FrontComponentUpdateContextEffect'; +import { type FrontComponentExecutionContext } from '@/front-component/renderer/types/FrontComponentExecutionContext'; +import { type WorkerExports } from '@/front-component/renderer/types/WorkerExports'; +import { type ThreadWebWorker } from '@quilted/threads'; +import { + type RemoteReceiver, + RemoteRootRenderer, +} from '@remote-dom/react/host'; +import { useMemo, useState } from 'react'; +import { isDefined } from 'twenty-shared/utils'; + +import { ThemeProvider } from '@emotion/react'; +import { type ThemeType } from 'twenty-ui/theme'; +import { FrontComponentWorkerEffect } from '../../remote/components/FrontComponentWorkerEffect'; +import { componentRegistry } from '../generated/host-component-registry'; + +type FrontComponentContentProps = { + componentUrl: string; + executionContext: FrontComponentExecutionContext; + onError: (error?: Error) => void; + theme: ThemeType; +}; + +export const FrontComponentRenderer = ({ + componentUrl, + executionContext, + onError, + theme, +}: FrontComponentContentProps) => { + const [receiver, setReceiver] = useState(null); + const [thread, setThread] = useState | null>( + null, + ); + const [error, setError] = useState(null); + + const MemoizedFrontComponentWorkerEffect = useMemo(() => { + return ( + + ); + }, [componentUrl, setError, setReceiver, setThread]); + + return ( + <> + {MemoizedFrontComponentWorkerEffect} + + {isDefined(error) && ( + + )} + + {isDefined(thread) && ( + + )} + + {isDefined(receiver) && ( + + + + )} + + ); +}; diff --git a/packages/twenty-sdk/src/front-component/renderer/host/generated/host-component-registry.ts b/packages/twenty-sdk/src/front-component/renderer/host/generated/host-component-registry.ts new file mode 100644 index 0000000000..5668035e9e --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/host/generated/host-component-registry.ts @@ -0,0 +1,405 @@ +/* + * _____ _ + *|_ _|_ _____ _ __ | |_ _ _ + * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file + * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden + * |_| \_/\_/ \___|_| |_|\__|\__, | + * |___/ + */ + +import React from 'react'; +import { + RemoteFragmentRenderer, + createRemoteComponentRenderer, +} from '@remote-dom/react/host'; +import { Button } from 'twenty-ui/input'; +const INTERNAL_PROPS = new Set(['element', 'receiver', 'components']); + +const EVENT_NAME_MAP: Record = { + onclick: 'onClick', + ondblclick: 'onDoubleClick', + onmousedown: 'onMouseDown', + onmouseup: 'onMouseUp', + onmouseover: 'onMouseOver', + onmouseout: 'onMouseOut', + onmouseenter: 'onMouseEnter', + onmouseleave: 'onMouseLeave', + onkeydown: 'onKeyDown', + onkeyup: 'onKeyUp', + onkeypress: 'onKeyPress', + onfocus: 'onFocus', + onblur: 'onBlur', + onchange: 'onChange', + oninput: 'onInput', + onsubmit: 'onSubmit', + onscroll: 'onScroll', + onwheel: 'onWheel', + oncontextmenu: 'onContextMenu', + ondrag: 'onDrag', +}; + +const parseStyle = ( + styleString: string | undefined, +): React.CSSProperties | undefined => { + if (!styleString || typeof styleString !== 'string') { + return styleString as React.CSSProperties | undefined; + } + + const style: Record = {}; + const declarations = styleString.split(';').filter(Boolean); + + for (const declaration of declarations) { + const colonIndex = declaration.indexOf(':'); + if (colonIndex === -1) continue; + + const property = declaration.slice(0, colonIndex).trim(); + const value = declaration.slice(colonIndex + 1).trim(); + + const camelProperty = property.replace(/-([a-z])/g, (_, letter: string) => + letter.toUpperCase(), + ); + style[camelProperty] = value; + } + + return style; +}; + +const wrapEventHandler = (handler: () => void) => { + return (_event: unknown) => { + handler(); + }; +}; + +const filterProps = (props: Record) => { + const filtered: Record = {}; + for (const [key, value] of Object.entries(props)) { + if (INTERNAL_PROPS.has(key) || value === undefined) continue; + + if (key === 'style') { + filtered.style = parseStyle(value as string | undefined); + } else { + const normalizedKey = EVENT_NAME_MAP[key.toLowerCase()] || key; + if (normalizedKey.startsWith('on') && typeof value === 'function') { + filtered[normalizedKey] = wrapEventHandler(value as () => void); + } else { + filtered[normalizedKey] = value; + } + } + } + return filtered; +}; +const HtmlDivWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('div', filterProps(props), children); +}; +const HtmlSpanWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('span', filterProps(props), children); +}; +const HtmlSectionWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('section', filterProps(props), children); +}; +const HtmlArticleWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('article', filterProps(props), children); +}; +const HtmlHeaderWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('header', filterProps(props), children); +}; +const HtmlFooterWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('footer', filterProps(props), children); +}; +const HtmlMainWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('main', filterProps(props), children); +}; +const HtmlNavWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('nav', filterProps(props), children); +}; +const HtmlAsideWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('aside', filterProps(props), children); +}; +const HtmlPWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('p', filterProps(props), children); +}; +const HtmlH1Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h1', filterProps(props), children); +}; +const HtmlH2Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h2', filterProps(props), children); +}; +const HtmlH3Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h3', filterProps(props), children); +}; +const HtmlH4Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h4', filterProps(props), children); +}; +const HtmlH5Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h5', filterProps(props), children); +}; +const HtmlH6Wrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('h6', filterProps(props), children); +}; +const HtmlStrongWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('strong', filterProps(props), children); +}; +const HtmlEmWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('em', filterProps(props), children); +}; +const HtmlSmallWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('small', filterProps(props), children); +}; +const HtmlCodeWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('code', filterProps(props), children); +}; +const HtmlPreWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('pre', filterProps(props), children); +}; +const HtmlBlockquoteWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('blockquote', filterProps(props), children); +}; +const HtmlAWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('a', filterProps(props), children); +}; +const HtmlImgWrapper = ({ + children: _children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('img', filterProps(props)); +}; +const HtmlUlWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('ul', filterProps(props), children); +}; +const HtmlOlWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('ol', filterProps(props), children); +}; +const HtmlLiWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('li', filterProps(props), children); +}; +const HtmlFormWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('form', filterProps(props), children); +}; +const HtmlLabelWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('label', filterProps(props), children); +}; +const HtmlInputWrapper = ({ + children: _children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('input', filterProps(props)); +}; +const HtmlTextareaWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('textarea', filterProps(props), children); +}; +const HtmlSelectWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('select', filterProps(props), children); +}; +const HtmlOptionWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('option', filterProps(props), children); +}; +const HtmlButtonWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('button', filterProps(props), children); +}; +const HtmlTableWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('table', filterProps(props), children); +}; +const HtmlTheadWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('thead', filterProps(props), children); +}; +const HtmlTbodyWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('tbody', filterProps(props), children); +}; +const HtmlTfootWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('tfoot', filterProps(props), children); +}; +const HtmlTrWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('tr', filterProps(props), children); +}; +const HtmlThWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('th', filterProps(props), children); +}; +const HtmlTdWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('td', filterProps(props), children); +}; +const HtmlBrWrapper = ({ + children: _children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('br', filterProps(props)); +}; +const HtmlHrWrapper = ({ + children: _children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement('hr', filterProps(props)); +}; +const TwentyUiButtonWrapper = ({ + children, + ...props +}: { children?: React.ReactNode } & Record) => { + return React.createElement(Button, filterProps(props), children); +}; +type ComponentRegistryValue = + | ReturnType + | typeof RemoteFragmentRenderer; + +export const componentRegistry: Map = new Map([ + ['html-div', createRemoteComponentRenderer(HtmlDivWrapper)], + ['html-span', createRemoteComponentRenderer(HtmlSpanWrapper)], + ['html-section', createRemoteComponentRenderer(HtmlSectionWrapper)], + ['html-article', createRemoteComponentRenderer(HtmlArticleWrapper)], + ['html-header', createRemoteComponentRenderer(HtmlHeaderWrapper)], + ['html-footer', createRemoteComponentRenderer(HtmlFooterWrapper)], + ['html-main', createRemoteComponentRenderer(HtmlMainWrapper)], + ['html-nav', createRemoteComponentRenderer(HtmlNavWrapper)], + ['html-aside', createRemoteComponentRenderer(HtmlAsideWrapper)], + ['html-p', createRemoteComponentRenderer(HtmlPWrapper)], + ['html-h1', createRemoteComponentRenderer(HtmlH1Wrapper)], + ['html-h2', createRemoteComponentRenderer(HtmlH2Wrapper)], + ['html-h3', createRemoteComponentRenderer(HtmlH3Wrapper)], + ['html-h4', createRemoteComponentRenderer(HtmlH4Wrapper)], + ['html-h5', createRemoteComponentRenderer(HtmlH5Wrapper)], + ['html-h6', createRemoteComponentRenderer(HtmlH6Wrapper)], + ['html-strong', createRemoteComponentRenderer(HtmlStrongWrapper)], + ['html-em', createRemoteComponentRenderer(HtmlEmWrapper)], + ['html-small', createRemoteComponentRenderer(HtmlSmallWrapper)], + ['html-code', createRemoteComponentRenderer(HtmlCodeWrapper)], + ['html-pre', createRemoteComponentRenderer(HtmlPreWrapper)], + ['html-blockquote', createRemoteComponentRenderer(HtmlBlockquoteWrapper)], + ['html-a', createRemoteComponentRenderer(HtmlAWrapper)], + ['html-img', createRemoteComponentRenderer(HtmlImgWrapper)], + ['html-ul', createRemoteComponentRenderer(HtmlUlWrapper)], + ['html-ol', createRemoteComponentRenderer(HtmlOlWrapper)], + ['html-li', createRemoteComponentRenderer(HtmlLiWrapper)], + ['html-form', createRemoteComponentRenderer(HtmlFormWrapper)], + ['html-label', createRemoteComponentRenderer(HtmlLabelWrapper)], + ['html-input', createRemoteComponentRenderer(HtmlInputWrapper)], + ['html-textarea', createRemoteComponentRenderer(HtmlTextareaWrapper)], + ['html-select', createRemoteComponentRenderer(HtmlSelectWrapper)], + ['html-option', createRemoteComponentRenderer(HtmlOptionWrapper)], + ['html-button', createRemoteComponentRenderer(HtmlButtonWrapper)], + ['html-table', createRemoteComponentRenderer(HtmlTableWrapper)], + ['html-thead', createRemoteComponentRenderer(HtmlTheadWrapper)], + ['html-tbody', createRemoteComponentRenderer(HtmlTbodyWrapper)], + ['html-tfoot', createRemoteComponentRenderer(HtmlTfootWrapper)], + ['html-tr', createRemoteComponentRenderer(HtmlTrWrapper)], + ['html-th', createRemoteComponentRenderer(HtmlThWrapper)], + ['html-td', createRemoteComponentRenderer(HtmlTdWrapper)], + ['html-br', createRemoteComponentRenderer(HtmlBrWrapper)], + ['html-hr', createRemoteComponentRenderer(HtmlHrWrapper)], + ['twenty-ui-button', createRemoteComponentRenderer(TwentyUiButtonWrapper)], + ['remote-fragment', RemoteFragmentRenderer], +]); diff --git a/packages/twenty-sdk/src/front-component/host/generated/host-index.ts b/packages/twenty-sdk/src/front-component/renderer/host/generated/host-index.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/host/generated/host-index.ts rename to packages/twenty-sdk/src/front-component/renderer/host/generated/host-index.ts diff --git a/packages/twenty-sdk/src/front-component/index.ts b/packages/twenty-sdk/src/front-component/renderer/index.ts similarity index 84% rename from packages/twenty-sdk/src/front-component/index.ts rename to packages/twenty-sdk/src/front-component/renderer/index.ts index 32c9b1c6ae..fad9220aca 100644 --- a/packages/twenty-sdk/src/front-component/index.ts +++ b/packages/twenty-sdk/src/front-component/renderer/index.ts @@ -1,126 +1,124 @@ -/* - * _____ _ - *|_ _|_ _____ _ __ | |_ _ _ - * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file - * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden - * |_| \_/\_/ \___|_| |_|\__|\__, | - * |___/ - */ - export { FrontComponentRenderer } from './host/components/FrontComponentRenderer'; export { componentRegistry } from './host/generated/host-component-registry'; +export { FrontComponentErrorEffect } from './remote/components/FrontComponentErrorEffect'; +export { FrontComponentUpdateContextEffect } from './remote/components/FrontComponentUpdateContextEffect'; export { FrontComponentWorkerEffect } from './remote/components/FrontComponentWorkerEffect'; export { - HtmlDiv, - HtmlSpan, - HtmlSection, + FrontComponentExecutionContextStore, + frontComponentExecutionContextStore, +} from './remote/context/FrontComponentExecutionContextStore'; +export { + HtmlA, HtmlArticle, - HtmlHeader, - HtmlFooter, - HtmlMain, - HtmlNav, HtmlAside, - HtmlP, + HtmlBlockquote, + HtmlBr, + HtmlButton, + HtmlCode, + HtmlDiv, + HtmlEm, + HtmlFooter, + HtmlForm, HtmlH1, HtmlH2, HtmlH3, HtmlH4, HtmlH5, HtmlH6, - HtmlStrong, - HtmlEm, - HtmlSmall, - HtmlCode, - HtmlPre, - HtmlBlockquote, - HtmlA, - HtmlImg, - HtmlUl, - HtmlOl, - HtmlLi, - HtmlForm, - HtmlLabel, - HtmlInput, - HtmlTextarea, - HtmlSelect, - HtmlOption, - HtmlButton, - HtmlTable, - HtmlThead, - HtmlTbody, - HtmlTfoot, - HtmlTr, - HtmlTh, - HtmlTd, - HtmlBr, + HtmlHeader, HtmlHr, + HtmlImg, + HtmlInput, + HtmlLabel, + HtmlLi, + HtmlMain, + HtmlNav, + HtmlOl, + HtmlOption, + HtmlP, + HtmlPre, + HtmlSection, + HtmlSelect, + HtmlSmall, + HtmlSpan, + HtmlStrong, + HtmlTable, + HtmlTbody, + HtmlTd, + HtmlTextarea, + HtmlTfoot, + HtmlTh, + HtmlThead, + HtmlTr, + HtmlUl, TwentyUiButton, } from './remote/generated/remote-components'; -export type { - HtmlCommonProperties, - HtmlCommonEvents, - HtmlAProperties, - HtmlImgProperties, - HtmlFormProperties, - HtmlLabelProperties, - HtmlInputProperties, - HtmlTextareaProperties, - HtmlSelectProperties, - HtmlOptionProperties, - HtmlButtonProperties, - HtmlThProperties, - HtmlTdProperties, - TwentyUiButtonProperties, -} from './remote/generated/remote-elements'; export { - HtmlDivElement, - HtmlSpanElement, - HtmlSectionElement, + HtmlAElement, HtmlArticleElement, - HtmlHeaderElement, - HtmlFooterElement, - HtmlMainElement, - HtmlNavElement, HtmlAsideElement, - HtmlPElement, + HtmlBlockquoteElement, + HtmlBrElement, + HtmlButtonElement, + HtmlCodeElement, + HtmlDivElement, + HtmlEmElement, + HtmlFooterElement, + HtmlFormElement, HtmlH1Element, HtmlH2Element, HtmlH3Element, HtmlH4Element, HtmlH5Element, HtmlH6Element, - HtmlStrongElement, - HtmlEmElement, - HtmlSmallElement, - HtmlCodeElement, - HtmlPreElement, - HtmlBlockquoteElement, - HtmlAElement, - HtmlImgElement, - HtmlUlElement, - HtmlOlElement, - HtmlLiElement, - HtmlFormElement, - HtmlLabelElement, - HtmlInputElement, - HtmlTextareaElement, - HtmlSelectElement, - HtmlOptionElement, - HtmlButtonElement, - HtmlTableElement, - HtmlTheadElement, - HtmlTbodyElement, - HtmlTfootElement, - HtmlTrElement, - HtmlThElement, - HtmlTdElement, - HtmlBrElement, + HtmlHeaderElement, HtmlHrElement, - TwentyUiButtonElement, - RemoteRootElement, + HtmlImgElement, + HtmlInputElement, + HtmlLabelElement, + HtmlLiElement, + HtmlMainElement, + HtmlNavElement, + HtmlOlElement, + HtmlOptionElement, + HtmlPElement, + HtmlPreElement, + HtmlSectionElement, + HtmlSelectElement, + HtmlSmallElement, + HtmlSpanElement, + HtmlStrongElement, + HtmlTableElement, + HtmlTbodyElement, + HtmlTdElement, + HtmlTextareaElement, + HtmlTfootElement, + HtmlThElement, + HtmlTheadElement, + HtmlTrElement, + HtmlUlElement, RemoteFragmentElement, + RemoteRootElement, + TwentyUiButtonElement, +} from './remote/generated/remote-elements'; +export type { + HtmlAProperties, + HtmlButtonProperties, + HtmlCommonEvents, + HtmlCommonProperties, + HtmlFormProperties, + HtmlImgProperties, + HtmlInputProperties, + HtmlLabelProperties, + HtmlOptionProperties, + HtmlSelectProperties, + HtmlTdProperties, + HtmlTextareaProperties, + HtmlThProperties, + TwentyUiButtonProperties, } from './remote/generated/remote-elements'; export { createRemoteWorker } from './remote/worker/createRemoteWorker'; +export type { FrontComponentExecutionContext } from './types/FrontComponentExecutionContext'; export type { HostToWorkerRenderContext } from './types/HostToWorkerRenderContext'; export type { PropertySchema } from './types/PropertySchema'; export type { WorkerExports } from './types/WorkerExports'; diff --git a/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentErrorEffect.tsx b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentErrorEffect.tsx new file mode 100644 index 0000000000..a7e97bdd5d --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentErrorEffect.tsx @@ -0,0 +1,18 @@ +import { useEffect } from 'react'; + +type FrontComponentErrorEffectProps = { + error: Error | null; + onError: (error: Error) => void; +}; +export const FrontComponentErrorEffect = ({ + error, + onError, +}: FrontComponentErrorEffectProps) => { + useEffect(() => { + if (error) { + onError(error); + } + }, [error, onError]); + + return null; +}; diff --git a/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentUpdateContextEffect.tsx b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentUpdateContextEffect.tsx new file mode 100644 index 0000000000..381aebce86 --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentUpdateContextEffect.tsx @@ -0,0 +1,20 @@ +import { type FrontComponentExecutionContext } from '@/front-component/renderer/types/FrontComponentExecutionContext'; +import { type WorkerExports } from '@/front-component/renderer/types/WorkerExports'; +import { type ThreadWebWorker } from '@quilted/threads'; +import { useEffect } from 'react'; + +type FrontComponentUpdateContextEffectProps = { + thread: ThreadWebWorker; + executionContext: FrontComponentExecutionContext; +}; + +export const FrontComponentUpdateContextEffect = ({ + thread, + executionContext, +}: FrontComponentUpdateContextEffectProps) => { + useEffect(() => { + thread.imports.updateContext(executionContext).catch(() => {}); + }, [executionContext, thread]); + + return null; +}; diff --git a/packages/twenty-sdk/src/front-component/remote/components/FrontComponentWorkerEffect.tsx b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentWorkerEffect.tsx similarity index 74% rename from packages/twenty-sdk/src/front-component/remote/components/FrontComponentWorkerEffect.tsx rename to packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentWorkerEffect.tsx index 680cf888b8..7872a79831 100644 --- a/packages/twenty-sdk/src/front-component/remote/components/FrontComponentWorkerEffect.tsx +++ b/packages/twenty-sdk/src/front-component/renderer/remote/components/FrontComponentWorkerEffect.tsx @@ -7,13 +7,17 @@ import { createRemoteWorker } from '../worker/createRemoteWorker'; type FrontComponentWorkerEffectProps = { componentUrl: string; setReceiver: React.Dispatch>; - onError: (error?: Error) => void; + setThread: React.Dispatch< + React.SetStateAction | null> + >; + setError: React.Dispatch>; }; export const FrontComponentWorkerEffect = ({ componentUrl, setReceiver, - onError, + setThread, + setError, }: FrontComponentWorkerEffectProps) => { useEffect(() => { const newReceiver = new RemoteReceiver({ retain, release }); @@ -21,23 +25,25 @@ export const FrontComponentWorkerEffect = ({ const worker = createRemoteWorker(); worker.onerror = (event: ErrorEvent) => { - onError(event.error); + setError(event.error); }; const thread = new ThreadWebWorker(worker); + setThread(thread); thread.imports .render(newReceiver.connection, { componentUrl }) .catch((error: Error) => { - onError(error); + setError(error); }); setReceiver(newReceiver); return () => { + setThread(null); worker.terminate(); }; - }, [componentUrl, onError, setReceiver]); + }, [componentUrl, setError, setReceiver, setThread]); return null; }; diff --git a/packages/twenty-sdk/src/front-component/renderer/remote/context/FrontComponentExecutionContextStore.ts b/packages/twenty-sdk/src/front-component/renderer/remote/context/FrontComponentExecutionContextStore.ts new file mode 100644 index 0000000000..708e7fa175 --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/remote/context/FrontComponentExecutionContextStore.ts @@ -0,0 +1,28 @@ +import { type FrontComponentExecutionContext } from '../../types/FrontComponentExecutionContext'; + +type Listener = () => void; + +export class FrontComponentExecutionContextStore { + private context: FrontComponentExecutionContext | undefined = undefined; + private listeners = new Set(); + + getSnapshot = (): FrontComponentExecutionContext | undefined => { + return this.context; + }; + + subscribe = (listener: Listener): (() => void) => { + this.listeners.add(listener); + + return () => this.listeners.delete(listener); + }; + + setContext = (context: FrontComponentExecutionContext): void => { + this.context = context; + for (const listener of this.listeners) { + listener(); + } + }; +} + +export const frontComponentExecutionContextStore = + new FrontComponentExecutionContextStore(); diff --git a/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-components.ts b/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-components.ts new file mode 100644 index 0000000000..5b3014ceac --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-components.ts @@ -0,0 +1,1157 @@ +/* + * _____ _ + *|_ _|_ _____ _ __ | |_ _ _ + * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file + * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden + * |_| \_/\_/ \___|_| |_|\__|\__, | + * |___/ + */ + +import { createRemoteComponent } from '@remote-dom/react'; +import { + HtmlDivElement, + HtmlSpanElement, + HtmlSectionElement, + HtmlArticleElement, + HtmlHeaderElement, + HtmlFooterElement, + HtmlMainElement, + HtmlNavElement, + HtmlAsideElement, + HtmlPElement, + HtmlH1Element, + HtmlH2Element, + HtmlH3Element, + HtmlH4Element, + HtmlH5Element, + HtmlH6Element, + HtmlStrongElement, + HtmlEmElement, + HtmlSmallElement, + HtmlCodeElement, + HtmlPreElement, + HtmlBlockquoteElement, + HtmlAElement, + HtmlImgElement, + HtmlUlElement, + HtmlOlElement, + HtmlLiElement, + HtmlFormElement, + HtmlLabelElement, + HtmlInputElement, + HtmlTextareaElement, + HtmlSelectElement, + HtmlOptionElement, + HtmlButtonElement, + HtmlTableElement, + HtmlTheadElement, + HtmlTbodyElement, + HtmlTfootElement, + HtmlTrElement, + HtmlThElement, + HtmlTdElement, + HtmlBrElement, + HtmlHrElement, + TwentyUiButtonElement, +} from './remote-elements'; + +export const HtmlDiv = createRemoteComponent('html-div', HtmlDivElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlSpan = createRemoteComponent('html-span', HtmlSpanElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlSection = createRemoteComponent( + 'html-section', + HtmlSectionElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlArticle = createRemoteComponent( + 'html-article', + HtmlArticleElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlHeader = createRemoteComponent( + 'html-header', + HtmlHeaderElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlFooter = createRemoteComponent( + 'html-footer', + HtmlFooterElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlMain = createRemoteComponent('html-main', HtmlMainElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlNav = createRemoteComponent('html-nav', HtmlNavElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlAside = createRemoteComponent('html-aside', HtmlAsideElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlP = createRemoteComponent('html-p', HtmlPElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH1 = createRemoteComponent('html-h1', HtmlH1Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH2 = createRemoteComponent('html-h2', HtmlH2Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH3 = createRemoteComponent('html-h3', HtmlH3Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH4 = createRemoteComponent('html-h4', HtmlH4Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH5 = createRemoteComponent('html-h5', HtmlH5Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlH6 = createRemoteComponent('html-h6', HtmlH6Element, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlStrong = createRemoteComponent( + 'html-strong', + HtmlStrongElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlEm = createRemoteComponent('html-em', HtmlEmElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlSmall = createRemoteComponent('html-small', HtmlSmallElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlCode = createRemoteComponent('html-code', HtmlCodeElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlPre = createRemoteComponent('html-pre', HtmlPreElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlBlockquote = createRemoteComponent( + 'html-blockquote', + HtmlBlockquoteElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlA = createRemoteComponent('html-a', HtmlAElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlImg = createRemoteComponent('html-img', HtmlImgElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlUl = createRemoteComponent('html-ul', HtmlUlElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlOl = createRemoteComponent('html-ol', HtmlOlElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlLi = createRemoteComponent('html-li', HtmlLiElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlForm = createRemoteComponent('html-form', HtmlFormElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlLabel = createRemoteComponent('html-label', HtmlLabelElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlInput = createRemoteComponent('html-input', HtmlInputElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTextarea = createRemoteComponent( + 'html-textarea', + HtmlTextareaElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlSelect = createRemoteComponent( + 'html-select', + HtmlSelectElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlOption = createRemoteComponent( + 'html-option', + HtmlOptionElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlButton = createRemoteComponent( + 'html-button', + HtmlButtonElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); +export const HtmlTable = createRemoteComponent('html-table', HtmlTableElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlThead = createRemoteComponent('html-thead', HtmlTheadElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTbody = createRemoteComponent('html-tbody', HtmlTbodyElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTfoot = createRemoteComponent('html-tfoot', HtmlTfootElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTr = createRemoteComponent('html-tr', HtmlTrElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTh = createRemoteComponent('html-th', HtmlThElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlTd = createRemoteComponent('html-td', HtmlTdElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlBr = createRemoteComponent('html-br', HtmlBrElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const HtmlHr = createRemoteComponent('html-hr', HtmlHrElement, { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, +}); +export const TwentyUiButton = createRemoteComponent( + 'twenty-ui-button', + TwentyUiButtonElement, + { + eventProps: { + onClick: { event: 'click' }, + onDblclick: { event: 'dblclick' }, + onMousedown: { event: 'mousedown' }, + onMouseup: { event: 'mouseup' }, + onMouseover: { event: 'mouseover' }, + onMouseout: { event: 'mouseout' }, + onMouseenter: { event: 'mouseenter' }, + onMouseleave: { event: 'mouseleave' }, + onKeydown: { event: 'keydown' }, + onKeyup: { event: 'keyup' }, + onKeypress: { event: 'keypress' }, + onFocus: { event: 'focus' }, + onBlur: { event: 'blur' }, + onChange: { event: 'change' }, + onInput: { event: 'input' }, + onSubmit: { event: 'submit' }, + onScroll: { event: 'scroll' }, + onWheel: { event: 'wheel' }, + onContextmenu: { event: 'contextmenu' }, + onDrag: { event: 'drag' }, + }, + }, +); diff --git a/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-elements.ts b/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-elements.ts new file mode 100644 index 0000000000..254606d588 --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-elements.ts @@ -0,0 +1,733 @@ +/* + * _____ _ + *|_ _|_ _____ _ __ | |_ _ _ + * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file + * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden + * |_| \_/\_/ \___|_| |_|\__|\__, | + * |___/ + */ + +import { + createRemoteElement, + RemoteRootElement, + RemoteFragmentElement, + type RemoteEvent, +} from '@remote-dom/core/elements'; + +export type HtmlCommonProperties = { + id?: string; + className?: string; + style?: string; + title?: string; + tabIndex?: number; + role?: string; + 'aria-label'?: string; + 'aria-hidden'?: boolean; + 'data-testid'?: string; +}; +export type HtmlCommonEvents = { + click(event: RemoteEvent): void; + dblclick(event: RemoteEvent): void; + mousedown(event: RemoteEvent): void; + mouseup(event: RemoteEvent): void; + mouseover(event: RemoteEvent): void; + mouseout(event: RemoteEvent): void; + mouseenter(event: RemoteEvent): void; + mouseleave(event: RemoteEvent): void; + keydown(event: RemoteEvent): void; + keyup(event: RemoteEvent): void; + keypress(event: RemoteEvent): void; + focus(event: RemoteEvent): void; + blur(event: RemoteEvent): void; + change(event: RemoteEvent): void; + input(event: RemoteEvent): void; + submit(event: RemoteEvent): void; + scroll(event: RemoteEvent): void; + wheel(event: RemoteEvent): void; + contextmenu(event: RemoteEvent): void; + drag(event: RemoteEvent): void; +}; + +const HTML_COMMON_EVENTS_ARRAY = [ + 'click', + 'dblclick', + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'mouseenter', + 'mouseleave', + 'keydown', + 'keyup', + 'keypress', + 'focus', + 'blur', + 'change', + 'input', + 'submit', + 'scroll', + 'wheel', + 'contextmenu', + 'drag', +] as const; +const HTML_COMMON_PROPERTIES_CONFIG = { + id: { type: String }, + className: { type: String }, + style: { type: String }, + title: { type: String }, + tabIndex: { type: Number }, + role: { type: String }, + 'aria-label': { type: String }, + 'aria-hidden': { type: Boolean }, + 'data-testid': { type: String }, +}; +export const HtmlDivElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlSpanElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlSectionElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlArticleElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlHeaderElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlFooterElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlMainElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlNavElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlAsideElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlPElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH1Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH2Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH3Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH4Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH5Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlH6Element = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlStrongElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlEmElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlSmallElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlCodeElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlPreElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlBlockquoteElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlAProperties = HtmlCommonProperties & { + href?: string; + target?: string; + rel?: string; +}; + +export const HtmlAElement = createRemoteElement< + HtmlAProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + href: { type: String }, + target: { type: String }, + rel: { type: String }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlImgProperties = HtmlCommonProperties & { + src?: string; + alt?: string; + width?: number; + height?: number; +}; + +export const HtmlImgElement = createRemoteElement< + HtmlImgProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + src: { type: String }, + alt: { type: String }, + width: { type: Number }, + height: { type: Number }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlUlElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlOlElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlLiElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlFormProperties = HtmlCommonProperties & { + action?: string; + method?: string; +}; + +export const HtmlFormElement = createRemoteElement< + HtmlFormProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + action: { type: String }, + method: { type: String }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlLabelProperties = HtmlCommonProperties & { + htmlFor?: string; +}; + +export const HtmlLabelElement = createRemoteElement< + HtmlLabelProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + htmlFor: { type: String }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlInputProperties = HtmlCommonProperties & { + type?: string; + name?: string; + value?: string; + placeholder?: string; + disabled?: boolean; + checked?: boolean; + readOnly?: boolean; +}; + +export const HtmlInputElement = createRemoteElement< + HtmlInputProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + type: { type: String }, + name: { type: String }, + value: { type: String }, + placeholder: { type: String }, + disabled: { type: Boolean }, + checked: { type: Boolean }, + readOnly: { type: Boolean }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlTextareaProperties = HtmlCommonProperties & { + name?: string; + value?: string; + placeholder?: string; + disabled?: boolean; + readOnly?: boolean; + rows?: number; + cols?: number; +}; + +export const HtmlTextareaElement = createRemoteElement< + HtmlTextareaProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + name: { type: String }, + value: { type: String }, + placeholder: { type: String }, + disabled: { type: Boolean }, + readOnly: { type: Boolean }, + rows: { type: Number }, + cols: { type: Number }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlSelectProperties = HtmlCommonProperties & { + name?: string; + value?: string; + disabled?: boolean; + multiple?: boolean; +}; + +export const HtmlSelectElement = createRemoteElement< + HtmlSelectProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + name: { type: String }, + value: { type: String }, + disabled: { type: Boolean }, + multiple: { type: Boolean }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlOptionProperties = HtmlCommonProperties & { + value?: string; + disabled?: boolean; + selected?: boolean; +}; + +export const HtmlOptionElement = createRemoteElement< + HtmlOptionProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + value: { type: String }, + disabled: { type: Boolean }, + selected: { type: Boolean }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlButtonProperties = HtmlCommonProperties & { + type?: string; + disabled?: boolean; +}; + +export const HtmlButtonElement = createRemoteElement< + HtmlButtonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + type: { type: String }, + disabled: { type: Boolean }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlTableElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlTheadElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlTbodyElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlTfootElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlTrElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlThProperties = HtmlCommonProperties & { + colSpan?: number; + rowSpan?: number; +}; + +export const HtmlThElement = createRemoteElement< + HtmlThProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + colSpan: { type: Number }, + rowSpan: { type: Number }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type HtmlTdProperties = HtmlCommonProperties & { + colSpan?: number; + rowSpan?: number; +}; + +export const HtmlTdElement = createRemoteElement< + HtmlTdProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + colSpan: { type: Number }, + rowSpan: { type: Number }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlBrElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +export const HtmlHrElement = createRemoteElement< + HtmlCommonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: HTML_COMMON_PROPERTIES_CONFIG, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); + +export type TwentyUiButtonProperties = HtmlCommonProperties & { + variant?: string; + accent?: string; + size?: string; + disabled?: boolean; + fullWidth?: boolean; +}; + +export const TwentyUiButtonElement = createRemoteElement< + TwentyUiButtonProperties, + Record, + Record, + HtmlCommonEvents +>({ + properties: { + ...HTML_COMMON_PROPERTIES_CONFIG, + variant: { type: String }, + accent: { type: String }, + size: { type: String }, + disabled: { type: Boolean }, + fullWidth: { type: Boolean }, + }, + events: [...HTML_COMMON_EVENTS_ARRAY], +}); +customElements.define('html-div', HtmlDivElement); +customElements.define('html-span', HtmlSpanElement); +customElements.define('html-section', HtmlSectionElement); +customElements.define('html-article', HtmlArticleElement); +customElements.define('html-header', HtmlHeaderElement); +customElements.define('html-footer', HtmlFooterElement); +customElements.define('html-main', HtmlMainElement); +customElements.define('html-nav', HtmlNavElement); +customElements.define('html-aside', HtmlAsideElement); +customElements.define('html-p', HtmlPElement); +customElements.define('html-h1', HtmlH1Element); +customElements.define('html-h2', HtmlH2Element); +customElements.define('html-h3', HtmlH3Element); +customElements.define('html-h4', HtmlH4Element); +customElements.define('html-h5', HtmlH5Element); +customElements.define('html-h6', HtmlH6Element); +customElements.define('html-strong', HtmlStrongElement); +customElements.define('html-em', HtmlEmElement); +customElements.define('html-small', HtmlSmallElement); +customElements.define('html-code', HtmlCodeElement); +customElements.define('html-pre', HtmlPreElement); +customElements.define('html-blockquote', HtmlBlockquoteElement); +customElements.define('html-a', HtmlAElement); +customElements.define('html-img', HtmlImgElement); +customElements.define('html-ul', HtmlUlElement); +customElements.define('html-ol', HtmlOlElement); +customElements.define('html-li', HtmlLiElement); +customElements.define('html-form', HtmlFormElement); +customElements.define('html-label', HtmlLabelElement); +customElements.define('html-input', HtmlInputElement); +customElements.define('html-textarea', HtmlTextareaElement); +customElements.define('html-select', HtmlSelectElement); +customElements.define('html-option', HtmlOptionElement); +customElements.define('html-button', HtmlButtonElement); +customElements.define('html-table', HtmlTableElement); +customElements.define('html-thead', HtmlTheadElement); +customElements.define('html-tbody', HtmlTbodyElement); +customElements.define('html-tfoot', HtmlTfootElement); +customElements.define('html-tr', HtmlTrElement); +customElements.define('html-th', HtmlThElement); +customElements.define('html-td', HtmlTdElement); +customElements.define('html-br', HtmlBrElement); +customElements.define('html-hr', HtmlHrElement); +customElements.define('twenty-ui-button', TwentyUiButtonElement); +customElements.define('remote-root', RemoteRootElement); +customElements.define('remote-fragment', RemoteFragmentElement); + +export { RemoteRootElement, RemoteFragmentElement }; +declare global { + interface HTMLElementTagNameMap { + 'html-div': InstanceType; + 'html-span': InstanceType; + 'html-section': InstanceType; + 'html-article': InstanceType; + 'html-header': InstanceType; + 'html-footer': InstanceType; + 'html-main': InstanceType; + 'html-nav': InstanceType; + 'html-aside': InstanceType; + 'html-p': InstanceType; + 'html-h1': InstanceType; + 'html-h2': InstanceType; + 'html-h3': InstanceType; + 'html-h4': InstanceType; + 'html-h5': InstanceType; + 'html-h6': InstanceType; + 'html-strong': InstanceType; + 'html-em': InstanceType; + 'html-small': InstanceType; + 'html-code': InstanceType; + 'html-pre': InstanceType; + 'html-blockquote': InstanceType; + 'html-a': InstanceType; + 'html-img': InstanceType; + 'html-ul': InstanceType; + 'html-ol': InstanceType; + 'html-li': InstanceType; + 'html-form': InstanceType; + 'html-label': InstanceType; + 'html-input': InstanceType; + 'html-textarea': InstanceType; + 'html-select': InstanceType; + 'html-option': InstanceType; + 'html-button': InstanceType; + 'html-table': InstanceType; + 'html-thead': InstanceType; + 'html-tbody': InstanceType; + 'html-tfoot': InstanceType; + 'html-tr': InstanceType; + 'html-th': InstanceType; + 'html-td': InstanceType; + 'html-br': InstanceType; + 'html-hr': InstanceType; + 'twenty-ui-button': InstanceType; + 'remote-root': InstanceType; + 'remote-fragment': InstanceType; + } +} diff --git a/packages/twenty-sdk/src/front-component/remote/generated/remote-index.ts b/packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-index.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/remote/generated/remote-index.ts rename to packages/twenty-sdk/src/front-component/renderer/remote/generated/remote-index.ts diff --git a/packages/twenty-sdk/src/front-component/remote/mock/mock-front-component.ts b/packages/twenty-sdk/src/front-component/renderer/remote/mock/mock-front-component.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/remote/mock/mock-front-component.ts rename to packages/twenty-sdk/src/front-component/renderer/remote/mock/mock-front-component.ts diff --git a/packages/twenty-sdk/src/front-component/remote/worker/createRemoteWorker.ts b/packages/twenty-sdk/src/front-component/renderer/remote/worker/createRemoteWorker.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/remote/worker/createRemoteWorker.ts rename to packages/twenty-sdk/src/front-component/renderer/remote/worker/createRemoteWorker.ts diff --git a/packages/twenty-sdk/src/front-component/remote/worker/remote-worker.ts b/packages/twenty-sdk/src/front-component/renderer/remote/worker/remote-worker.ts similarity index 71% rename from packages/twenty-sdk/src/front-component/remote/worker/remote-worker.ts rename to packages/twenty-sdk/src/front-component/renderer/remote/worker/remote-worker.ts index c5b2a945a8..3b473d9b27 100644 --- a/packages/twenty-sdk/src/front-component/remote/worker/remote-worker.ts +++ b/packages/twenty-sdk/src/front-component/renderer/remote/worker/remote-worker.ts @@ -12,14 +12,18 @@ import { import React from 'react'; import { createRoot } from 'react-dom/client'; import { jsx, jsxs } from 'react/jsx-runtime'; +import { type FrontComponentExecutionContext } from '../../types/FrontComponentExecutionContext'; import { type HostToWorkerRenderContext } from '../../types/HostToWorkerRenderContext'; import { type WorkerExports } from '../../types/WorkerExports'; +import { frontComponentExecutionContextStore } from '../context/FrontComponentExecutionContextStore'; import * as RemoteComponents from '../generated/remote-components'; (globalThis as Record).React = React; (globalThis as Record).RemoteComponents = RemoteComponents; (globalThis as Record).jsx = jsx; (globalThis as Record).jsxs = jsxs; +(globalThis as Record).frontComponentExecutionContextStore = + frontComponentExecutionContextStore; const render: WorkerExports['render'] = async ( connection: RemoteConnection, @@ -37,4 +41,10 @@ const render: WorkerExports['render'] = async ( reactRoot.render(componentModule.default); }; -ThreadWebWorker.self.export({ render }); +const updateContext: WorkerExports['updateContext'] = async ( + context: FrontComponentExecutionContext, +) => { + frontComponentExecutionContextStore.setContext(context); +}; + +ThreadWebWorker.self.export({ render, updateContext }); diff --git a/packages/twenty-sdk/src/front-component/renderer/types/FrontComponentExecutionContext.ts b/packages/twenty-sdk/src/front-component/renderer/types/FrontComponentExecutionContext.ts new file mode 100644 index 0000000000..732a36147a --- /dev/null +++ b/packages/twenty-sdk/src/front-component/renderer/types/FrontComponentExecutionContext.ts @@ -0,0 +1,3 @@ +export type FrontComponentExecutionContext = { + userId: string | null; +}; diff --git a/packages/twenty-sdk/src/front-component/types/HostToWorkerRenderContext.ts b/packages/twenty-sdk/src/front-component/renderer/types/HostToWorkerRenderContext.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/types/HostToWorkerRenderContext.ts rename to packages/twenty-sdk/src/front-component/renderer/types/HostToWorkerRenderContext.ts diff --git a/packages/twenty-sdk/src/front-component/types/PropertySchema.ts b/packages/twenty-sdk/src/front-component/renderer/types/PropertySchema.ts similarity index 100% rename from packages/twenty-sdk/src/front-component/types/PropertySchema.ts rename to packages/twenty-sdk/src/front-component/renderer/types/PropertySchema.ts diff --git a/packages/twenty-sdk/src/front-component/types/WorkerExports.ts b/packages/twenty-sdk/src/front-component/renderer/types/WorkerExports.ts similarity index 63% rename from packages/twenty-sdk/src/front-component/types/WorkerExports.ts rename to packages/twenty-sdk/src/front-component/renderer/types/WorkerExports.ts index 102a72711c..2218b641f3 100644 --- a/packages/twenty-sdk/src/front-component/types/WorkerExports.ts +++ b/packages/twenty-sdk/src/front-component/renderer/types/WorkerExports.ts @@ -1,4 +1,5 @@ import { type RemoteConnection } from '@remote-dom/core/elements'; +import { type FrontComponentExecutionContext } from './FrontComponentExecutionContext'; import { type HostToWorkerRenderContext } from './HostToWorkerRenderContext'; export type WorkerExports = { @@ -6,4 +7,5 @@ export type WorkerExports = { connection: RemoteConnection, context: HostToWorkerRenderContext, ) => Promise; + updateContext: (context: FrontComponentExecutionContext) => Promise; }; diff --git a/packages/twenty-sdk/src/index.ts b/packages/twenty-sdk/src/index.ts index c404b4b950..0c103ca217 100644 --- a/packages/twenty-sdk/src/index.ts +++ b/packages/twenty-sdk/src/index.ts @@ -1,10 +1 @@ -/* - * _____ _ - *|_ _|_ _____ _ __ | |_ _ _ - * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file - * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden - * |_| \_/\_/ \___|_| |_|\__|\__, | - * |___/ - */ - export * from './sdk'; diff --git a/packages/twenty-sdk/src/sdk/front-components/__tests__/define-front-component.spec.ts b/packages/twenty-sdk/src/sdk/__tests__/define-front-component.spec.ts similarity index 100% rename from packages/twenty-sdk/src/sdk/front-components/__tests__/define-front-component.spec.ts rename to packages/twenty-sdk/src/sdk/__tests__/define-front-component.spec.ts diff --git a/packages/twenty-sdk/src/sdk/common/types/define-entity.type.ts b/packages/twenty-sdk/src/sdk/common/types/define-entity.type.ts index b453294c7b..7895f1ca31 100644 --- a/packages/twenty-sdk/src/sdk/common/types/define-entity.type.ts +++ b/packages/twenty-sdk/src/sdk/common/types/define-entity.type.ts @@ -1,11 +1,11 @@ +import { type ApplicationConfig } from '@/sdk/application/application-config'; +import { type FrontComponentConfig } from '@/sdk/front-component-config'; +import { type LogicFunctionConfig } from '@/sdk/logic-functions/logic-function-config'; import { type FieldManifest, type ObjectManifest, type RoleManifest, } from 'twenty-shared/application'; -import { type FrontComponentConfig } from '@/sdk/front-components/front-component-config'; -import { type LogicFunctionConfig } from '@/sdk/logic-functions/logic-function-config'; -import { type ApplicationConfig } from '@/sdk/application/application-config'; export type ValidationResult = { success: boolean; diff --git a/packages/twenty-sdk/src/sdk/front-components/define-front-component.ts b/packages/twenty-sdk/src/sdk/define-front-component.ts similarity index 96% rename from packages/twenty-sdk/src/sdk/front-components/define-front-component.ts rename to packages/twenty-sdk/src/sdk/define-front-component.ts index a6c2c14129..42901d5ef3 100644 --- a/packages/twenty-sdk/src/sdk/front-components/define-front-component.ts +++ b/packages/twenty-sdk/src/sdk/define-front-component.ts @@ -1,6 +1,6 @@ -import { type FrontComponentConfig } from '@/sdk/front-components/front-component-config'; -import type { DefineEntity } from '@/sdk/common/types/define-entity.type'; import { createValidationResult } from '@/sdk'; +import type { DefineEntity } from '@/sdk/common/types/define-entity.type'; +import { type FrontComponentConfig } from '@/sdk/front-component-config'; export const defineFrontComponent: DefineEntity = ( config, diff --git a/packages/twenty-sdk/src/sdk/front-components/front-component-config.ts b/packages/twenty-sdk/src/sdk/front-component-config.ts similarity index 100% rename from packages/twenty-sdk/src/sdk/front-components/front-component-config.ts rename to packages/twenty-sdk/src/sdk/front-component-config.ts diff --git a/packages/twenty-sdk/src/sdk/index.ts b/packages/twenty-sdk/src/sdk/index.ts index 04ee7d5097..ff6573a88f 100644 --- a/packages/twenty-sdk/src/sdk/index.ts +++ b/packages/twenty-sdk/src/sdk/index.ts @@ -1,12 +1,3 @@ -/* - * _____ _ - *|_ _|_ _____ _ __ | |_ _ _ - * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file - * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden - * |_| \_/\_/ \___|_| |_|\__|\__, | - * |___/ - */ - export type { ApplicationConfig } from './application/application-config'; export { defineApplication } from './application/define-application'; export type { @@ -16,6 +7,7 @@ export type { } from './common/types/define-entity.type'; export type { SyncableEntityOptions } from './common/types/syncable-entity-options.type'; export { createValidationResult } from './common/utils/create-validation-result'; +export { defineFrontComponent } from './define-front-component'; export type { ActorField, AddressField, @@ -31,11 +23,10 @@ export { FieldType } from './fields/field-type'; export { OnDeleteAction } from './fields/on-delete-action'; export { RelationType } from './fields/relation-type'; export { validateFields } from './fields/validate-fields'; -export { defineFrontComponent } from './front-components/define-front-component'; export type { FrontComponentType, FrontComponentConfig, -} from './front-components/front-component-config'; +} from './front-component-config'; export { defineLogicFunction } from './logic-functions/define-logic-function'; export type { LogicFunctionHandler, diff --git a/packages/twenty-sdk/src/ui/index.ts b/packages/twenty-sdk/src/ui/index.ts index 2c682cedef..d35fd14e73 100644 --- a/packages/twenty-sdk/src/ui/index.ts +++ b/packages/twenty-sdk/src/ui/index.ts @@ -1,12 +1,3 @@ -/* - * _____ _ - *|_ _|_ _____ _ __ | |_ _ _ - * | | \ \ /\ / / _ \ '_ \| __| | | | Auto-generated file - * | | \ V V / __/ | | | |_| |_| | Any edits to this will be overridden - * |_| \_/\_/ \___|_| |_|\__|\__, | - * |___/ - */ - export * from 'twenty-ui'; export * from 'twenty-ui/accessibility'; export * from 'twenty-ui/components'; diff --git a/packages/twenty-sdk/tsconfig.json b/packages/twenty-sdk/tsconfig.json index 8405d5d815..c6d8a86880 100644 --- a/packages/twenty-sdk/tsconfig.json +++ b/packages/twenty-sdk/tsconfig.json @@ -25,7 +25,6 @@ "**/__mocks__/**/*", "**/__tests__/**/*", "vite.config.ts", - "scripts/**/*.ts", "jest.config.mjs" ], "exclude": [ diff --git a/packages/twenty-sdk/vite.config.ts b/packages/twenty-sdk/vite.config.ts index 5e03c45d3e..15f36553b6 100644 --- a/packages/twenty-sdk/vite.config.ts +++ b/packages/twenty-sdk/vite.config.ts @@ -5,11 +5,13 @@ import dts from 'vite-plugin-dts'; import tsconfigPaths from 'vite-tsconfig-paths'; import packageJson from './package.json'; -const moduleEntries = Object.keys((packageJson as any).exports || {}) - .filter((key) => key !== '.' && !key.startsWith('./src/')) - .map((module) => `src/${module.replace(/^\.\//, '')}/index.ts`); - -const entries = ['src/index.ts', 'src/cli/cli.ts', ...moduleEntries]; +const entries = [ + 'src/index.ts', + 'src/cli/cli.ts', + 'src/ui/index.ts', + 'src/front-component/renderer/index.ts', + 'src/front-component/api/index.ts', +]; export const PACKAGES_TO_VENDOR = ['twenty-ui', 'twenty-shared']; @@ -20,18 +22,15 @@ const entryFileNames = (chunk: any, extension: 'cjs' | 'mjs') => { ); } - const splitFaceModuleId = chunk.facadeModuleId?.split('/'); - if (splitFaceModuleId === undefined) { - throw new Error( - `Should never occurs splitFaceModuleId is undefined ${chunk.facadeModuleId}`, - ); - } - - const moduleDirectory = splitFaceModuleId[splitFaceModuleId?.length - 2]; - if (moduleDirectory === 'src') { + // Find which entry this chunk corresponds to + const entry = entries.find((e) => chunk.facadeModuleId?.endsWith(e)); + if (!entry || entry === 'src/index.ts' || entry === 'src/cli/cli.ts') { return `${chunk.name}.${extension}`; } - return `${moduleDirectory}/index.${extension}`; + + // Remove 'src/' prefix and '/index.ts' suffix to get the module path + const modulePath = entry.replace('src/', '').replace('/index.ts', ''); + return `${modulePath}/index.${extension}`; }; const copyTwentyPackagesInVendor = (packages: string[]) => {