Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions apps/site/app/components/ObjectUIProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
'use client';

// Import components to trigger registration
import '@object-ui/components';
import { initializeComponents } from '@object-ui/components';
import { ComponentRegistry } from '@object-ui/core';
import { useEffect } from 'react';

export function ObjectUIProvider({ children }: { children: React.ReactNode }) {
// Components are auto-registered on import
// Explicitly call init to ensure components are registered
useEffect(() => {
initializeComponents();
// Log registered components for debugging
const componentTypes = ComponentRegistry.getAllTypes();
console.log('[ObjectUIProvider] Registered components:', componentTypes);
}, []);

return <>{children}</>;
}
1 change: 1 addition & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"main": "dist/index.umd.cjs",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"sideEffects": true,
"exports": {
".": {
"types": "./dist/index.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@ export * from './lib/utils';

// Export raw Shadcn UI components
export * from './ui';

// Export an init function to ensure components are registered
// This is a workaround for bundlers that might tree-shake side-effect imports
export function initializeComponents() {
// This function exists to ensure the import side-effects above are executed
// Simply importing this module should register all components
return true;
}
54 changes: 51 additions & 3 deletions packages/components/src/renderers/basic/icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,61 @@ import { ComponentRegistry } from '@object-ui/core';
import type { IconSchema } from '@object-ui/types';
import { icons } from 'lucide-react';
import React, { forwardRef } from 'react';
import { cn } from '../../lib/utils';

// Convert kebab-case to PascalCase for Lucide icon names
// e.g., "arrow-right" -> "ArrowRight", "home" -> "Home"
function toPascalCase(str: string): string {
return str
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join('');
}

const IconRenderer = forwardRef<SVGSVGElement, { schema: IconSchema; className?: string; [key: string]: any }>(
({ schema, className, ...props }, ref) => {
const Icon = (icons as any)[schema.name || schema.icon];
if (!Icon) return null;
return <Icon ref={ref} className={className} {...props} />;
// Extract designer-related props
const {
'data-obj-id': dataObjId,
'data-obj-type': dataObjType,
style,
...iconProps
} = props;

// Convert icon name to PascalCase for Lucide lookup
const iconName = toPascalCase(schema.name);
const Icon = (icons as any)[iconName];

if (!Icon) {
console.warn(`Icon "${schema.name}" (lookup: "${iconName}") not found in lucide-react`);
return null;
}

// Build size style
const sizeStyle = schema.size ? { width: schema.size, height: schema.size } : undefined;

// Merge classNames: schema color, schema className, prop className
const mergedClassName = cn(
schema.color,
schema.className,
className
);

return (
<Icon
ref={ref}
className={mergedClassName}
style={{ ...sizeStyle, ...style }}
{...iconProps}
// Apply designer props
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType }}
/>
);
}
);

IconRenderer.displayName = 'IconRenderer';

ComponentRegistry.register('icon',
IconRenderer,
{
Expand All @@ -27,6 +73,8 @@ ComponentRegistry.register('icon',
category: 'basic',
inputs: [
{ name: 'name', type: 'string', label: 'Icon Name', defaultValue: 'smile' },
{ name: 'size', type: 'number', label: 'Size (px)' },
{ name: 'color', type: 'string', label: 'Color Class' },
{ name: 'className', type: 'string', label: 'CSS Class' }
]
}
Expand Down
4 changes: 3 additions & 1 deletion packages/components/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ export default defineConfig({
fileName: 'index',
},
rollupOptions: {
external: ['react', 'react-dom'],
external: ['react', 'react-dom', '@object-ui/core', '@object-ui/react', '@object-ui/types'],
output: {
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'@object-ui/core': 'ObjectUICore',
'@object-ui/react': 'ObjectUIReact',
},
},
},
Expand Down
Loading