[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:
@@ -148,6 +148,7 @@ export { appendCopySuffix } from './strings/appendCopySuffix';
|
||||
export { camelToSnakeCase } from './strings/camelToSnakeCase';
|
||||
export { capitalize } from './strings/capitalize';
|
||||
export { pascalCase } from './strings/pascalCase';
|
||||
export { pascalToKebab } from './strings/pascalToKebab';
|
||||
export { stringifySafely } from './strings/stringifySafely';
|
||||
export { uncapitalize } from './strings/uncapitalize';
|
||||
export type {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { pascalToKebab } from '../pascalToKebab';
|
||||
|
||||
describe('pascalToKebab', () => {
|
||||
it('should convert PascalCase to kebab-case', () => {
|
||||
expect(pascalToKebab('UserProfile')).toBe('user-profile');
|
||||
});
|
||||
|
||||
it('should convert single word', () => {
|
||||
expect(pascalToKebab('Button')).toBe('button');
|
||||
});
|
||||
|
||||
it('should handle consecutive uppercase letters', () => {
|
||||
expect(pascalToKebab('HTMLElement')).toBe('html-element');
|
||||
});
|
||||
|
||||
it('should handle numbers in the name', () => {
|
||||
expect(pascalToKebab('H1Title')).toBe('h1-title');
|
||||
});
|
||||
|
||||
it('should handle multi-word PascalCase', () => {
|
||||
expect(pascalToKebab('MyComponentName')).toBe('my-component-name');
|
||||
});
|
||||
|
||||
it('should handle already lowercase', () => {
|
||||
expect(pascalToKebab('button')).toBe('button');
|
||||
});
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
export * from './appendCopySuffix';
|
||||
export * from './capitalize';
|
||||
export * from './pascalCase';
|
||||
export * from './pascalToKebab';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export const pascalToKebab = (name: string): string => {
|
||||
return name
|
||||
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
||||
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
||||
.toLowerCase();
|
||||
};
|
||||
Reference in New Issue
Block a user