Files
twenty/packages/twenty-sdk/scripts/remote-dom/generators/schemas.ts
T
Raphaël Bosi cb7d0b83a8 [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
2026-02-12 12:48:16 +01:00

36 lines
1.2 KiB
TypeScript

import { z } from 'zod';
export const PropertySchemaZ = z.object({
type: z.enum(['string', 'number', 'boolean', 'array', 'object', 'function']),
optional: z.boolean(),
});
export const HtmlElementConfigZ = z.object({
tag: z.string().regex(/^html-[a-z0-9]+$/, 'Tag must start with "html-"'),
name: z
.string()
.regex(/^Html[A-Z]/, 'Name must be PascalCase starting with Html'),
properties: z.record(z.string(), PropertySchemaZ),
});
export const HtmlElementConfigArrayZ = z.array(HtmlElementConfigZ);
export const ComponentSchemaZ = z.object({
name: z.string().min(1),
tagName: z.string().min(1),
customElementName: z.string().min(1),
properties: z.record(z.string(), PropertySchemaZ),
slots: z.array(z.string()).optional(),
events: z.array(z.string()).readonly(),
isHtmlElement: z.boolean(),
htmlTag: z.string().optional(),
componentImport: z.string().optional(),
componentPath: z.string().optional(),
propsTypeName: z.string().optional(),
supportsRefForwarding: z.boolean().optional(),
});
export type PropertySchema = z.infer<typeof PropertySchemaZ>;
export type HtmlElementConfig = z.infer<typeof HtmlElementConfigZ>;
export type ComponentSchema = z.infer<typeof ComponentSchemaZ>;