[FRONT COMPONENTS] Twenty UI elements generation (#17866)

## PR description

This PR:
- Creates a TypeScript-based extractor that discovers all exported
twenty-ui components by scanning barrel files, extracting
props/slots/events via ts-morph type analysis, and generating the remote
DOM bindings automatically.

- Adds a new ESLint rule which enforces all *Props types in twenty-ui
components to be exported, which is required for the extractor to
discover component prop types. Existing twenty-ui components are updated
to comply with this rule.

- Extends the remote DOM generation to support slots, per-component
events, forwardRef wrappers, and richer property types (array, object,
function)

## Edge cases to fix in another PR

- Icons cannot be rendered inside buttons
- IconButtons throw an error when mounted
- MenuItems are not displayed correctly
- MenuItemNavigate throws on click

## Video Demo


https://github.com/user-attachments/assets/c2ed67cf-6a15-4896-9fec-e83fac0e862b
This commit is contained in:
Raphaël Bosi
2026-02-12 12:48:16 +01:00
committed by GitHub
parent c48ccbca99
commit cb7d0b83a8
133 changed files with 10556 additions and 984 deletions
@@ -1,3 +0,0 @@
export const eventToReactProp = (eventName: string): string => {
return `on${eventName.charAt(0).toUpperCase()}${eventName.slice(1)}`;
};
@@ -2,10 +2,9 @@ export { addExportedConst } from './add-exported-const';
export { addExportedType } from './add-exported-type';
export { addFileHeader } from './add-file-header';
export { addStatement } from './add-statement';
export { eventToReactProp } from './event-to-react-prop';
export { extractHtmlTag } from './extract-html-tag';
export { GENERATED_FILE_HEADER } from './generated-file-header';
export { generatePropertiesConfig } from './generate-properties-config';
export { generatePropertiesType } from './generate-properties-type';
export { GENERATED_FILE_HEADER } from './generated-file-header';
export { schemaTypeToConstructor } from './schema-type-to-constructor';
export { schemaTypeToTs } from './schema-type-to-ts';
@@ -4,6 +4,9 @@ const SCHEMA_TYPE_TO_CONSTRUCTOR: Record<PropertySchema['type'], string> = {
boolean: 'Boolean',
number: 'Number',
string: 'String',
array: 'Array',
object: 'Object',
function: 'Function',
};
export const schemaTypeToConstructor = (type: PropertySchema['type']): string =>
@@ -4,6 +4,9 @@ const SCHEMA_TYPE_TO_TS: Record<PropertySchema['type'], string> = {
boolean: 'boolean',
number: 'number',
string: 'string',
array: 'unknown[]',
object: 'Record<string, unknown>',
function: '(...args: unknown[]) => unknown',
};
export const schemaTypeToTs = (type: PropertySchema['type']): string =>